Skip to main content
Glama
dicoy

sqlens-mcp

by dicoy

sqlens-mcp

CI

An MCP server that gives Claude read-only access to your local development databases — inspect schemas, run queries, and explain query plans across Postgres, MySQL, and SQLite without leaving the conversation.

Built with the Model Context Protocol TypeScript SDK and a dialect-agnostic provider pattern. Only SELECT statements are permitted; SQLite connections open in readonly mode at the driver level.


Tools

Tool

What it answers

list_connections

What databases are configured? (credentials masked)

list_tables

What tables and views exist? How many rows? How large on disk?

describe_table

What are the columns, types, nullability, defaults, indexes, and foreign keys?

run_query

Run a SELECT and get results as a formatted table (max 500 rows, default 50).

explain_query

What query plan does the engine choose? (EXPLAIN ANALYZE on Postgres, EXPLAIN QUERY PLAN on SQLite).

demo


Related MCP server: MCP Database Server

Installation

npm install -g sqlens-mcp

Or use it without installing — npx will fetch and run it on demand (see Claude config below).

From source

git clone https://github.com/dicoy/sqlens-mcp.git
cd sqlens-mcp
npm install
npm run build

Add to Claude Code

claude mcp add sqlens -- npx -y sqlens-mcp

Add to Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json on macOS:

{
  "mcpServers": {
    "sqlens": {
      "command": "npx",
      "args": ["-y", "sqlens-mcp"],
      "env": {
        "DEVDB_URL": "postgres://localhost/myapp"
      }
    }
  }
}

Configuration

Connections are configured with environment variables. No config files.

Single connection

DEVDB_URL=postgres://localhost/myapp

Multiple named connections

Any DEVDB_<NAME> variable registers a named connection. The suffix is lowercased and underscores become hyphens.

DEVDB_URL=postgres://localhost/myapp          # "default"
DEVDB_STAGING=mysql://staging.internal/myapp  # "staging"
DEVDB_LOCAL=sqlite:///absolute/path/to/dev.db # "local"

Claude selects a connection by name: run_query({ sql: "...", connection: "staging" }). If no connection is specified, the default is used.

Supported dialects

Dialect

URL prefix

Example

PostgreSQL

postgres:// or postgresql://

postgres://user:pass@localhost:5432/mydb

MySQL

mysql://

mysql://user:pass@localhost:3306/mydb

SQLite

sqlite:// or .db / .sqlite path

sqlite:///Users/you/dev.db

Claude Desktop: multiple connections

{
  "mcpServers": {
    "sqlens": {
      "command": "npx",
      "args": ["-y", "sqlens-mcp"],
      "env": {
        "DEVDB_URL": "postgres://localhost/myapp",
        "DEVDB_ANALYTICS": "postgres://localhost/analytics",
        "DEVDB_LOCAL": "sqlite:///Users/you/local.db"
      }
    }
  }
}

Safety

  • SELECT only — every query is validated before execution. Anything other than SELECT or WITH is rejected with a typed error before it reaches the database.

  • SQLite readonly mode — SQLite connections use readonly: true at the better-sqlite3 level. Writes are blocked by the OS, not just by the check above.

  • Credential maskinglist_connections shows URLs with passwords replaced by ****. Credentials never appear in tool output.

  • Row caprun_query returns at most 500 rows; default is 50.


Architecture

src/
├── providers/
│   ├── db.ts                 # IDbProvider interface + shared types
│   ├── postgres.ts           # PostgresProvider  — pg.Pool, information_schema + pg_index
│   ├── mysql.ts              # MySqlProvider     — mysql2/promise, information_schema
│   ├── sqlite.ts             # SqliteProvider    — better-sqlite3 (readonly: true), PRAGMAs
│   └── connection-config.ts  # env parsing, createProvider() factory, maskCredentials()
├── errors/
│   └── index.ts              # DevDbError hierarchy (ConnectionNotFoundError, ReadOnlyViolationError, …)
├── tools/                    # One directory per tool: schema.ts + handler.ts + handler.test.ts
└── registry/
    └── tool-registry.ts      # resolveProvider(), per-call provider lifecycle

Design principles:

  • Single interface, three dialectsIDbProvider exposes listTables, describeTable, runQuery, explainQuery, and close. Tool handlers never import a concrete provider class.

  • Connection-per-call — each tool call opens a fresh provider and closes it in a finally block. No shared state between calls, no connection leaks.

  • One Zod schema per tool — the same schema drives both MCP input validation and TypeScript types. No duplication.

  • Typed error hierarchyConnectionNotFoundError, ReadOnlyViolationError, TableNotFoundError, and others. The registry catches DevDbError and formats each one as a clear message for Claude rather than a stack trace.


Development

npm run dev          # build in watch mode
npm run typecheck    # tsc --noEmit
npm run lint         # biome check
npm run lint:fix     # biome check --write
npm run test         # vitest run
npm run test:watch   # vitest (interactive)
npm run ci           # typecheck + lint + test + build
npm run demo         # run the demo script (Node 20+ required)

Adding a new dialect

  1. Implement IDbProvider in src/providers/<dialect>.ts

  2. Add the URL pattern to detectDialect() in connection-config.ts

  3. Add the case to createProvider() in connection-config.ts

Adding a new tool

  1. Create src/tools/your-tool/schema.ts — Zod input schema

  2. Create src/tools/your-tool/handler.ts — pure function, injected IDbProvider

  3. Create src/tools/your-tool/handler.test.ts — mock IDbProvider, not a real database

  4. Register in src/registry/tool-registry.ts


Tech stack

Runtime

Node.js 20+

MCP SDK

@modelcontextprotocol/sdk

Validation

zod

PostgreSQL

pg

MySQL

mysql2

SQLite

better-sqlite3

Build

tsup

Tests

vitest

Lint + format

biome

Available Tools

5 tools
describe_tableA

Show columns (types, nullability, defaults, primary keys), indexes, and foreign keys for a table or view.

ParametersJSON Schema
NameRequiredDescriptionDefault
tableYesTable or view name to describe
connectionNoNamed connection to use. Defaults to the default connection.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Although no annotations are provided, the description clearly states what the tool returns (columns, indexes, foreign keys) and is a read-only operation. It does not discuss permissions or error handling, but for a descriptive tool, the transparency is adequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that front-loads the main action and outputs. No filler words; every piece of information is necessary and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity and the absence of an output schema, the description is complete: it lists all major output categories (columns, indexes, foreign keys) and specifies it works for tables or views. No critical information is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with both parameters documented in the schema. The tool description adds no additional meaning beyond what the schema already provides, resulting in a baseline score.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb 'Show' and clearly defines the resource: columns (with types, nullability, defaults, primary keys), indexes, and foreign keys for a table or view. It distinguishes itself from sibling tools like list_tables (which only lists tables) and explain_query (which explains queries).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus alternatives (e.g., list_tables for listing tables, explain_query for query analysis). Usage context is implied from the sibling names but not directly provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

explain_queryA

Run EXPLAIN ANALYZE (Postgres) or EXPLAIN (MySQL/SQLite) on a SELECT query to show the execution plan. Useful for diagnosing slow queries.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYesSELECT statement to explain
paramsNoPositional parameters matching the query
connectionNoNamed connection to use. Defaults to the default connection.

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full weight but only discloses database-specific syntax differences (Postgres vs MySQL/SQLite). It fails to mention that EXPLAIN is read-only and does not modify data, and omits permission or side-effect details.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no fluff, front-loading the action and purpose, then adding a use case. Every sentence provides value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given three parameters, no output schema, and no annotations, the description adequately conveys the tool's purpose but is incomplete. It does not describe the output format (execution plan structure) or potential errors, which would help the agent understand return values.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description does not add parameter-specific meaning beyond what the schema already provides (e.g., describing 'sql' as 'SELECT statement to explain' is similar).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool runs EXPLAIN ANALYZE on Postgres and EXPLAIN on MySQL/SQLite for SELECT queries to show execution plans, differentiating it from sibling tools like run_query which executes queries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions it is 'useful for diagnosing slow queries,' providing basic usage context. However, it lacks explicit guidance on when not to use this tool (e.g., for non-SELECT statements) or direct comparisons to alternatives like run_query.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_connectionsA

List all configured database connections and their dialects. Call this first to see what databases are available.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, but description implies a read-only operation without side effects. Sufficiently transparent for a simple list tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no waste. Front-loaded with the verb 'List' and immediately conveys purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, but description hints at return content (connections and dialects). Could specify format, but adequate for a simple list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters, so schema coverage is 100%. Description adds no parameter info but none is needed. Baseline for 0 params is 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states 'List all configured database connections and their dialects' - specific verb and resource, and distinguishes from siblings by suggesting it be called first.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'Call this first to see what databases are available', providing clear usage guidance relative to other tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_tablesA

List all tables and views in a database with row counts and sizes.

ParametersJSON Schema
NameRequiredDescriptionDefault
connectionNoNamed connection to use. Defaults to the default connection.

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It describes listing metadata, implying a read operation, but does not explicitly state it is non-destructive or discuss any side effects, authentication, or error conditions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, no wasted words, front-loaded with the core action and details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Adequate for a simple tool with one optional parameter. Could be slightly more explicit about being scoped to the specified connection, but generally complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single parameter (connection). The tool description adds no additional meaning about the parameter beyond what is in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists all tables and views in a database with row counts and sizes. It distinguishes from siblings like describe_table (single table details) and list_connections.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus siblings. The description does not mention alternatives or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

run_queryA

Execute a read-only SELECT query and return results as a formatted table. Only SELECT and WITH statements are permitted.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYesSQL SELECT statement to execute. Only read-only queries are permitted.
paramsNoPositional parameters for parameterized queries ($1/$2 in Postgres, ? in MySQL/SQLite)
max_rowsNoMaximum rows to return (default 50, max 500)
connectionNoNamed connection to use. Defaults to the default connection.

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description states it is read-only and returns formatted table, but with no annotations, it leaves gaps about error handling, timeout, multiple statements, and exact output format. It adds modest value over the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, focused sentence that efficiently conveys the core functionality and constraint. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 4 parameters and no output schema, the description provides adequate context for the purpose but lacks details on return format, error handling, and query execution behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the description adds no additional parameter meaning beyond the schema definitions. The description does not elaborate on how parameters are used or constraints beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool executes a read-only SELECT query and returns results as a formatted table, specifying only SELECT and WITH statements are permitted, which distinguishes it from sibling tools like describe_table, explain_query, etc.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly limits usage to SELECT and WITH statements, indicating when not to use (e.g., DML statements). However, it does not provide guidance on when to prefer run_query over sibling tools like explain_query for analysis.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 5 tool updatesv0.1.0
    • First observeddescribe_table
    • First observedexplain_query
    • First observedlist_connections
    • First observedlist_tables
    • First observedrun_query

TDQS

A4.1/5.0
Disambiguation5/5

Each tool has a distinct purpose: schema description, query explanation, connection listing, table metadata, and query execution. No overlapping functionality.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (e.g., describe_table, list_tables). No deviations.

Tool Count5/5

5 tools is well-scoped for a SQL analysis server, covering essential database introspection and querying operations without excess.

Completeness5/5

The tool set provides a complete surface for read-only SQL analysis: schema exploration, query execution, execution plans, and connection management. No obvious gaps.

Maintenance

ActivityStale
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides Claude Desktop with secure access to multiple database connections, allowing users to query MySQL, PostgreSQL, SQLite, and SQL Server databases directly through natural language.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides Claude with direct access to databases including SQLite, SQL Server, PostgreSQL, and MySQL, enabling execution of SQL queries and table management through natural language.
    806
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables Claude Desktop to interact with MySQL, PostgreSQL, and Redis databases using natural language for data querying and schema analysis. It provides a secure interface with a default read-only mode to prevent unauthorized database modifications.
    115
    922
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables natural language interaction with local SQLite databases through Claude Desktop, translating plain English queries into SQL for data analysis and exploration.
    3
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dicoy/sqlens-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server