mahAnuj/mcp-multi-db
๐ ๐ - One MCP server for PostgreSQL, MySQL, and SQLite. Unified read-only tools (listdatabases, listtables, describetable, runquery) across all three engines with two-layer read-only enforcement (SQL-text guard + DB-level read-only transactions). Install: npx -y mcp-multi-db.
Quick Install
{
"mcpServers": {
"mahanuj-mcp-multi-db": {
"command": "npx",
"args": [
"-y",
"mahanuj-mcp-multi-db"
]
}
}
}Using an AI coding agent (Claude Code, Cursor, etc.)? Copy a ready-made prompt that tells it to fetch the setup instructions and install this server for you.
Documentation Overview
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_databases | List configured database connections |
list_tables | List tables/views in a database |
describe_table | Show column metadata for a table |
run_query | Run read-only SQL (SELECT, WITH, EXPLAIN) |
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.
Claude Desktop
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 Code
claude mcp add mcp-multi-db \
--env MCP_DB_CONFIG=/absolute/path/to/databases.json \
-- npx -y mcp-multi-db
Cursor
Add 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"
}
}
}
}
Cline / Windsurf / other MCP clients
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 |
|---|---|---|
id | yes | Unique; the agent references this as database_id |
type | yes | postgres | mysql | sqlite |
connectionString | postgres/mysql | Standard connection URI |
path | sqlite | Absolute path to the .db file |
label | no | Human-friendly name shown to the agent |
description | 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-db
The 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 suite
Tests 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/.
License
ISC โ see LICENSE.