mcp-multi-db
This server lets an AI agent discover and query multiple SQL databases (PostgreSQL, MySQL, SQLite) through one read-only MCP interface.
List all configured databases and their IDs, types, labels, and descriptions
List tables and views in a selected database, optionally filtered by schema
Describe a table's columns and metadata before writing queries
Run read-only SQL queries (SELECT, WITH, EXPLAIN) with configurable row limits
Work across Postgres, MySQL, and SQLite simultaneously via a single server
Query is enforced read-only at both the SQL-text and database transaction level
Results are capped and queries are time-bounded to prevent runaway operations
Provides read-only SQL querying and schema discovery for MySQL databases.
Provides read-only SQL querying and schema discovery for PostgreSQL databases.
Provides read-only SQL querying and schema discovery for SQLite databases.
mcp-multi-db
One MCP server for all your SQL databases — read-only and safe by default.
Connect an AI agent to PostgreSQL, MySQL, and SQLite at the same time through a
single Model Context Protocol server. List
your databases in one config file and the agent picks which one to query by
database_id. Every query is enforced read-only at the database level, so it's
safe to point at real data.
Multi-engine, one server — Postgres, MySQL, and SQLite side by side; no separate server per database.
Read-only & safe by default — two-layer enforcement (SQL-text guard + database-level read-only transactions) plus row limits and query timeouts. See SECURITY.md.
Schema-aware — the agent can discover databases, tables/views, and column metadata before it writes a query.
Zero query language to learn — just ask in natural language.

The clip drives the real server over stdio (via the MCP SDK) against a seeded SQLite database. Regenerate it with
npm run build && vhs examples/demo.tape.
Tools
Tool | Description |
| List configured database connections |
| List tables/views in a database |
| Show column metadata for a table |
| Run read-only SQL ( |
Related MCP server: dbridge-mcp
Quick start
No install needed — npx fetches the package on first use.
1. Create databases.json
Copy the example and edit with your connection details:
cp databases.example.json databases.json{
"databases": [
{
"id": "local-sqlite",
"type": "sqlite",
"path": "/absolute/path/to/app.db",
"label": "Local dev SQLite"
},
{
"id": "analytics-pg",
"type": "postgres",
"connectionString": "postgresql://user:pass@localhost:5432/analytics",
"label": "Analytics Warehouse"
},
{
"id": "reporting-mysql",
"type": "mysql",
"connectionString": "mysql://user:pass@localhost:3306/reporting",
"label": "Reporting MySQL"
}
]
}Never commit
databases.json— it contains credentials. It's already gitignored if you cloned the repo. Prefer read-only database users (see Security).
2. Register the server with your MCP client
The server speaks MCP over stdio, so it works with any MCP-capable client.
Use npx mcp-multi-db as the command and pass MCP_DB_CONFIG (the path to
your databases.json). See mcp.example.json and
databases.example.json for templates.
Edit claude_desktop_config.json (macOS:
~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"mcp-multi-db": {
"command": "npx",
"args": ["-y", "mcp-multi-db"],
"env": {
"MCP_DB_CONFIG": "/absolute/path/to/databases.json"
}
}
}
}Restart Claude Desktop afterward.
claude mcp add mcp-multi-db \
--env MCP_DB_CONFIG=/absolute/path/to/databases.json \
-- npx -y mcp-multi-dbAdd to ~/.cursor/mcp.json (or .cursor/mcp.json in your project), then open
Cursor Settings → Tools & MCP, restart the server, and use Agent mode:
{
"mcpServers": {
"mcp-multi-db": {
"command": "npx",
"args": ["-y", "mcp-multi-db"],
"env": {
"MCP_DB_CONFIG": "/absolute/path/to/databases.json"
}
}
}
}Any client that supports stdio MCP servers uses the same shape: command npx,
args ["-y", "mcp-multi-db"], and env MCP_DB_CONFIG pointing at your
databases.json. Consult your client's docs for where its MCP config lives.
Prefer a pinned global install?
npm install -g mcp-multi-db, then use commandmcp-multi-dbwith no args.
Configuration reference
Config is loaded from one of two environment variables, in order:
MCP_DB_CONFIG— path to a JSON file (recommended).MCP_DATABASES— inline JSON (useful when a file path is awkward).
The JSON may be either { "databases": [ ... ] } or a bare array. Each entry:
Field | Required | Notes |
| yes | Unique; the agent references this as |
| yes |
|
| postgres/mysql | Standard connection URI |
| sqlite | Absolute path to the |
| no | Human-friendly name shown to the agent |
| no | Extra context shown to the agent |
Example prompts
"List my configured databases"
"What tables are in
local-sqlite?""Describe the
userstable inanalytics-pg""Run
SELECT COUNT(*) FROM ordersonreporting-mysql"
Security
Read-only only.
INSERT,UPDATE,DELETE, DDL, etc. are blocked — both by a SQL-text guard and by running each query inside a database-level read-only transaction (SQLite opens read-only). ASELECTthat calls a side-effecting function is still refused.Row limits. Results are capped (default 100, max 1000).
Query timeouts. Statements are bounded (30s) to avoid runaway queries.
Use least privilege anyway. Prefer dedicated read-only DB users and read replicas. Full details and reporting in SECURITY.md.
Docker
A multi-stage Dockerfile is included. Build and run with your
databases.json mounted in:
docker build -t mcp-multi-db .
docker run --rm -i \
-v /absolute/path/to/databases.json:/config/databases.json:ro \
mcp-multi-dbThe image runs as a non-root user, ships only the built JS and runtime
node_modules (no toolchain), and speaks MCP over stdio just like the npx
install — so it slots into any MCP client by replacing the command and
args with the appropriate docker run -i invocation.
Development
npm install
npm run build # tsc -> build/, the artifact MCP clients run
npm test # builds, then runs the node:test suiteTests use Node's built-in test runner (no extra dependencies) and cover the read-only SQL guard and the SQLite adapter end to end. CI runs build + tests on every push and pull request.
Adding another database engine is a contained change: add the config variant in
src/config.ts, implement the SqlDatabasePort interface in a
new adapter under src/adapters/, and register it in the
adapter factory. New adapters must enforce read-only at the connection level —
not rely on the text guard alone. See docs/extending.md for
the full checklist.
Documentation
Architecture — components, request lifecycle, and the port-family design (with diagrams).
Extending — add a SQL engine or a non-SQL family.
Security — the two-layer read-only model and safe deployment.
The full index is in docs/.
Contributing
Issues and pull requests are welcome — see CONTRIBUTING.md for setup, the read-only invariants, and how to add a database engine.
License
ISC — see LICENSE.
Available Tools
4 toolsdescribe_tableA
Describe columns for a table in a configured database.
| Name | Required | Description | Default |
|---|---|---|---|
| database_id | Yes | Database id from list_databases | |
| table | Yes | Table name | |
| schema | No | Schema name (Postgres/MySQL). Ignored for SQLite. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description bears full responsibility for behavioral disclosure. It only states 'describe columns' with no mention of side effects, permissions, error handling, or return format, leaving significant gaps for a read-like operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with no wasted words, front-loading the core action and target.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the absence of an output schema and low complexity, the description adequately identifies the tool's purpose but lacks details about what the tool returns (e.g., column names, types), which would improve completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the input schema already documents each parameter with descriptions. The tool description adds no additional meaning beyond the schema, meeting the baseline expectation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('describe columns') and the resource ('table in a configured database'), distinguishing it from sibling tools like list_databases (list databases), list_tables (list tables), and run_query (execute arbitrary SQL).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when column details of a specific table are needed, but provides no explicit guidance on when to prefer this tool over alternatives like run_query, nor any 'when not to use' scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_databasesA
List all configured database connections (id, type, label, description). Call this first to discover which database_id to use.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so description carries full burden. It describes a simple list operation (read-only) but does not explicitly state safety or idempotency. However, for a 0-param list tool, the default assumption of no side effects is reasonable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence front-loads action and output fields, with no wasted words. Efficient and clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 0-param discovery tool with no output schema, the description sufficiently covers what it returns and why to call it. No gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters in schema, so schema coverage is 100%. The description adds value by listing returned fields and explaining purpose, making it a baseline 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'List' and resource 'all configured database connections' with fields (id, type, label, description). It clearly differentiates from sibling tools like list_tables and describe_table by indicating this is the first call to discover database_id.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states 'Call this first to discover which database_id to use', providing clear when-to-use guidance and implying it is a prerequisite for other tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tablesB
List tables and views in a configured database.
| Name | Required | Description | Default |
|---|---|---|---|
| database_id | Yes | Database id from list_databases | |
| schema | No | Schema name (Postgres/MySQL). Ignored for SQLite. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, but description does not disclose behavioral traits like read-only nature, authentication needs, or side effects. Minimal information beyond the basic action.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence is concise and front-loaded with key verb and object. No wasted words, but could be more structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema; description does not explain return format (e.g., array of names). Parameters are covered, but the result is missing, making it incomplete for a listing tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for both 'database_id' and 'schema'. Description adds no additional meaning beyond what schema already provides, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states verb 'List', resource 'tables and views', and context 'in a configured database'. This distinguishes it from siblings like 'describe_table' (which describes a specific table) and 'list_databases'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implied usage: use after selecting a database. No explicit when-to-use, when-not-to-use, or alternatives beyond sibling names.
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 SQL query (SELECT, WITH, EXPLAIN) on a configured database. Writes are blocked.
| Name | Required | Description | Default |
|---|---|---|---|
| database_id | Yes | Database id from list_databases | |
| sql | Yes | Read-only SQL query | |
| limit | No | Max rows to return (default 100, max 1000) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must disclose behavior. It clearly states the tool is read-only and blocks writes, a critical safety trait. It does not mention return format or error handling, but for a simple query tool this is sufficient.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no redundant information. It front-loads the key action and constraint, earning its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, high schema coverage, and absence of output schema, the description is mostly complete. It could mention the result format (e.g., JSON array) but omission is minor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the description adds no extra semantic meaning beyond the schema definitions for database_id, sql, and limit. It does not explain parameter interdependencies or formatting rules.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Execute' and the resource 'read-only SQL query on a configured database'. It also explicitly blocks writes, distinguishing it from siblings like describe_table and list_databases which provide metadata.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context by specifying allowed SQL commands (SELECT, WITH, EXPLAIN) and forbidding writes. It does not explicitly list alternative tools for non-query needs, but the sibling list implies usage boundaries.
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.
4 tool updates
v1.0.2- First observed
describe_table - First observed
list_databases - First observed
list_tables - First observed
run_query
TDQS
Each tool has a distinct purpose: describing a table's schema, listing database connections, listing tables in a database, and executing read-only queries. No overlap between tools.
All tool names follow a consistent verb_noun pattern in lower_snake_case (describe_table, list_databases, list_tables, run_query). Perfectly uniform.
With 4 tools, the server covers essential database exploration tasks without being bloated or too sparse. The count is appropriate for a read-only multi-database interface.
The set covers discovering databases, listing tables, describing schemas, and running SELECT queries. Missing are write operations, but they are intentionally blocked. A minor gap is lack of a tool to view recent queries or metadata beyond column types, but core workflow is solid.
Maintenance
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
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
- dataOAuthco.thinair
Read-only PostgreSQL, MySQL, SQL Server access via MCP — 24 dialect-aware hosted tools.
Query 40 databases from Claude, ChatGPT, or Cursor — on any device. Read-only, encrypted, audited.
Related MCP Servers
- FlicenseNot gradedqualityFmaintenanceA read-only MCP server that enables AI agents to explore database schemas and execute safe queries on PostgreSQL and MySQL.-
- AlicenseAqualityAmaintenanceRead-only MCP server that lets AI agents safely query SQLite, PostgreSQL, and MySQL/MariaDB. Enforces read-only transactions with column masking, row caps, query timeouts, EXPLAIN-based cost rejection, and rate limiting.7491MIT
- FlicenseNot gradedqualityBmaintenanceA small MCP server that lets an LLM query PostgreSQL, MySQL, MariaDB, SQL Server, or SQLite databases safely — read-only, role-restricted, and with sensitive data blacked out.-
- AlicenseNot gradedqualityCmaintenanceRead-only MCP server for SQL databases (SQLite/PostgreSQL) that enables listing tables, describing schemas, and executing SELECT queries with safety guardrails.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/mahAnuj/mcp-multi-db'
If you have feedback or need assistance with the MCP directory API, please join our Discord server