MCP database server for PostgreSQL, MySQL, MariaDB, SQLite, MongoDB, and Redis. One connection per instance, per-connection access modes, and a full performance-diagnosis toolkit for dev, SRE, and DBA workflows.
- Supported databases
- Features
- Tools
- Quick start
- Configuration
- Architecture
- Querying
- Docker
- Connecting to each engine
- Development
- References
- License
One connection per instance; the engine is inferred from the URI scheme (override with ENGINE_TYPE).
| Database | URI scheme | ENGINE_TYPE |
Driver | Highlights |
|---|---|---|---|---|
| PostgreSQL | postgresql://, postgres:// |
postgres |
psycopg 3 | pgvector KNN, native full-text search, HypoPG hypothetical indexes, transactional DDL dry-run, planner column stats |
| MySQL | mysql:// |
mysql |
aiomysql | FULLTEXT search, planner column stats + histograms, performance_schema diagnostics |
| MariaDB | mariadb:// |
mariadb |
aiomysql | Follows the MySQL surface with the engine differences absorbed (max_statement_time, SHOW SLAVE HOSTS) |
| SQLite | sqlite:///relative.db, sqlite:////absolute.db |
sqlite |
aiosqlite | File databases with structurally read-only reads (mode=ro), FTS5 text search, EXPLAIN QUERY PLAN |
| MongoDB | mongodb://, mongodb+srv:// |
mongodb |
PyMongo (async) | Atlas $search / $vectorSearch, aggregation reads, replica-set / shard topology |
| Redis | redis://, rediss:// |
redis |
redis-py (async) | Allowlisted command envelope (FLUSH*/EVAL/KEYS never allowed), SCAN-based inspection, SLOWLOG/INFO/ACL diagnostics |
Engine support per tool (some features are engine-specific — e.g. HypoPG is PostgreSQL-only) is in docs/tools.md. CI verifies every tool against real PostgreSQL 16/17, MySQL 8.0/8.4, MariaDB 10.11/11.4, SQLite, MongoDB 7/8, and Redis 7/8 (plus pgvector and Atlas-local images) on every push.
- 39 tools, risk-encoded names.
db_schema_*/db_read_*/db_perf_*never write (safe to always-allow);db_write_*/db_admin_*need approval. - Vector + full-text search. pgvector KNN and FTS (PostgreSQL), FULLTEXT (MySQL), Atlas
$search/$vectorSearch(MongoDB), plus index inspection and quality diagnostics. - Cluster tooling. Replication-lag and topology triage (
db_perf_cluster) with audited actions: promote, start/stop replica, step down, freeze. - Access modes per connection.
read_write,read_only,monitor(perf analysis with no data access, for production with PII). - Fail-closed read validation. sqlglot rejects writes, DDL, multi-statement and dangerous functions; MongoDB is limited to a read-only op allowlist.
- Fine-grained write control.
write_opslimits which operations run;database_modessets a different mode per database. - Write safety belts.
dry_run(execute, roll back, report impact) andexpected_max_rows(auto-abort oversized writes). - PII masking.
redact_fieldsmasks values with***;["*"]shows type placeholders only, never values. - Audit log. Every write, admin and export call is logged as JSONL (mode 600); literals become
?, so PII never touches disk. - Result limits. 500 rows / 1 MiB per response with source-side
LIMITinjection;db_read_exportstreams big results to JSON/CSV.
Full reference with parameters and per-database support indicators: docs/tools.md.
| Class | Tools | Safe to always-allow |
|---|---|---|
db_schema_ |
connections, databases, objects, describe, ddl, search, relationships, users, grants, search_indexes | ✅ |
db_read_ |
query, sample, export, vector_search, text_search | ✅ |
db_perf_ |
explain, column_stats, diagnose, top_queries, active_ops, blocking, index_stats, table_stats, health, replication, settings, logs, vector_stats, cluster | ✅ |
db_write_ |
query (with dry_run / expected_max_rows), search_index |
case by case |
db_admin_ |
kill, analyze, maintain, cluster | case by case |
Access-mode matrix:
| Class | read_write |
read_only |
monitor |
|---|---|---|---|
db_schema_ |
✅ | ✅ | ✅ (no data sampling) |
db_read_ |
✅ | ✅ | ❌ |
db_perf_ |
✅ | ✅ | ✅ |
db_write_ / db_admin_ |
✅ | ❌ | ❌ |
Requirements: Docker (runs both the playground databases and the published server image). uv is only needed for local development.
# 1. Clone (for the playground compose file and seed data)
git clone https://github.com/DiegoBulhoes/mcp-database.git && cd mcp-database
# 2. Start and seed the playground databases (PostgreSQL + MySQL + MongoDB)
make up && make mongo-rs && make seed
# 3. Register with Claude Code — runs the published image, one connection per server entry.
# All configuration lives in --env; the docker -e flags are a fixed forwarding template.
claude mcp add db-postgres \
--env URI="postgresql://dev:dev@localhost:5432/app" \
--env ENGINE_TYPE=postgres \
--env MODE=read_write \
-- docker run -i --rm --network host -e URI -e ENGINE_TYPE -e MODE -e NAME \
ghcr.io/diegobulhoes/mcp-database:latest
--network hostlets the container reachlocalhostdatabases (Linux). On macOS/Windows Docker Desktop, drop it and usehost.docker.internalin the URI instead.
Then ask Claude things like "why is pg_app slow?" and it will chain db_perf_active_ops → db_perf_blocking → db_perf_top_queries → db_perf_explain without a single permission prompt (see below).
You don't call the tools yourself; your AI assistant does, picking the connection by name (it discovers what exists via db_schema_connections). You just ask in natural language:
| You ask | The assistant calls |
|---|---|
| "how many orders over 100 in pg_app?" | db_read_query(conn="pg_app", query="SELECT count(*) FROM orders WHERE total > 100") |
| "top pages by clicks in mongo_app" | db_read_query(conn="mongo_app", query={"collection": "events", "operation": "aggregate", "pipeline": [{"$group": {"_id": "$page", "n": {"$sum": 1}}}]}) |
| "why is pg_app slow?" | db_perf_active_ops → db_perf_blocking → db_perf_top_queries → db_perf_explain (the SRE runbook, no prompts) |
| "upgrade user 42 to the pro plan" | db_write_query(conn="pg_app", query="UPDATE users SET plan = 'pro' WHERE id = 42", expected_max_rows=1) (this one asks for your approval) |
The query argument depends on the connection type:
- PostgreSQL / MySQL: a SQL string.
db_read_queryaccepts only SELECT/UNION/VALUES (parser-validated, fail-closed); everything else goes throughdb_write_query. - MongoDB: a JSON object
{"collection", "operation", ...}. Reads:find,aggregate,countDocuments,distinct,listIndexes; writes (viadb_write_query):insertMany,updateMany,deleteMany,createIndex.
Example query values:
SELECT id, total FROM orders WHERE total > 100 ORDER BY total DESC LIMIT 20{"collection": "events", "operation": "aggregate",
"pipeline": [{"$group": {"_id": "$page", "n": {"$sum": 1}}}, {"$sort": {"n": -1}}]}Write safety belts on db_write_query:
- Unbounded-mutation guard: an
UPDATE/DELETEwith noWHERE(or a MongoDBupdateMany/deleteManywith an empty filter) is rejected outright unless the caller declares intent — either adry_runor anexpected_max_rows. This stops a careless model from wiping a whole table without saying so. (DROP/TRUNCATEare explicit by nature and stay allowed.) dry_run: trueexecutes inside a transaction and rolls back, reporting how many rows would be affected.expected_max_rows: Naborts with rollback if the write would affect more than N rows (catches a missing WHERE before it hurts).
Projects and resources that shaped this server's design:
- Model Context Protocol: protocol specification and the Python SDK (FastMCP) this server is built on.
- anthropics/skills (Anthropic): two skills from this repo are bundled in
.claude/skills/: mcp-builder, whose best practices this server was audited against (tool naming with thedb_service prefix, parameter descriptions, annotations, actionable errors, and the agent evaluations format), and algorithmic-art for generative-art sessions. - postgres-mcp (Crystal DBA): inspiration for access modes, safe SQL execution, and the performance/health tool set.
- mongodb-mcp-server (MongoDB): inspiration for the export tool, byte-based response limits, and server log access.
- mcp-server-mysql (Ben Borla): inspiration for per-operation write permissions (
write_ops) and per-database modes (database_modes).