Database MCP server
Commit Nov 12, 2026Lets an AI client connect to MySQL, MariaDB, PostgreSQL, or SQLite to discover schemas, run queries, and manage tables.
Also known as haymon-ai/database
- Stars
- 33
- Tools
- —
- Downloads, 30 days
- —
- Latest version
- 0.7.0
- Last commit
- Nov 12, 2026
- License
- MIT
What is Database MCP?
Database is an MCP server. Lets an AI client connect to MySQL, MariaDB, PostgreSQL, or SQLite to discover schemas, run queries, and manage tables.
Summary generated from the project's README
How to install Database MCP
Formats verified 10 Nov 2026Install Database MCP in Claude Code
$ claude mcp add database -- docker run -i --rm ghcr.io/haymon-ai/database:0.7.0Install Database MCP in Cursor
~/.cursor/mcp.json
{
"mcpServers": {
"database": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/haymon-ai/database:0.7.0"
]
}
}
}Install Database MCP in VS Code
.vscode/mcp.json
{
"servers": {
"database": {
"type": "stdio",
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/haymon-ai/database:0.7.0"
]
}
}
}Install Database MCP in Claude Desktop
claude_desktop_config.json
{
"mcpServers": {
"database": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/haymon-ai/database:0.7.0"
]
}
}
}Install Database MCP in Codex
~/.codex/config.toml
[mcp_servers.database] command = "docker" args = ["run", "-i", "--rm", "ghcr.io/haymon-ai/database:0.7.0"]
Install Database MCP in Gemini CLI
~/.gemini/settings.json
{
"mcpServers": {
"database": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/haymon-ai/database:0.7.0"
]
}
}
}Configuration
DBMCP_DB_BACKENDDBMCP_DB_HOSTDBMCP_DB_NAMEDBMCP_DB_PASSWORDDBMCP_DB_PORTDBMCP_DB_USERDBMCP_HTTP_AUTH_TOKENDBMCP_SSH_HOSTDBMCP_TRANSPORTDB_PASSWORDHTTP_ALLOWED_HOSTSAllowed host names (comma-separated)
HTTP_ALLOWED_ORIGINSAllowed CORS origins (comma-separated)
HTTP_HOSTHTTP bind host
HTTP_PORTHTTP bind port
| Name | Description | |
|---|---|---|
| DBMCP_DB_BACKEND | — | |
| DBMCP_DB_HOST | — | |
| DBMCP_DB_NAME | — | |
| DBMCP_DB_PASSWORD | — | |
| DBMCP_DB_PORT | — | |
| DBMCP_DB_USER | — | |
| DBMCP_HTTP_AUTH_TOKEN | — | |
| DBMCP_SSH_HOST | — | |
| DBMCP_TRANSPORT | — | |
| DB_PASSWORD | — | |
| HTTP_ALLOWED_HOSTS | Allowed host names (comma-separated) | |
| HTTP_ALLOWED_ORIGINS | Allowed CORS origins (comma-separated) | |
| HTTP_HOST | HTTP bind host | |
| HTTP_PORT | HTTP bind port |
Automated checks
Ran Nov 12, 2026Full report →Not verified yet. A server needs a score of 80, no serious finding, and enough data for us to check. How checks work
- Source repository linked and reachablePass
- Open source license (OSI)Pass
- Commit or release in the last yearPass
- Package name not close to a popular packageNot checked
- Remote endpoint uses HTTPSNot checked
- Destructive tools are labelledNot checked
- No hidden instructions to the modelPass
- No critical advisory in the package or its dependenciesNot checked
README
View on GitHubDatabase MCP
A single-binary MCP server for SQL databases. Connect your AI assistant to MySQL/MariaDB, PostgreSQL, or SQLite with zero runtime dependencies.
Website · Documentation · Releases

Features ✨
- Multi-database — MySQL/MariaDB, PostgreSQL, and SQLite from one binary
- MCP tools — schema discovery (
listDatabases,listTables,listViews,listTriggers,listFunctions,listProcedures,listMaterializedViews), data access (readQuery,writeQuery), DDL (createDatabase,dropDatabase,dropTable), andexplainQuery. Read-only mode hides the write tools (writeQuery,createDatabase,dropDatabase,dropTable). See MCP Tools for per-backend availability. - Single binary — ~7 MB, no Python/Node/Docker needed
- Multiple transports — stdio (for Claude Desktop, Cursor) and HTTP (for remote/multi-client)
- Layered config —
DBMCP_*environment variables, an env file, and an optional YAML config file with${}interpolation, with sensible defaults per backend - SSH tunnel — reach MySQL/MariaDB/PostgreSQL through an SSH bastion with an embedded client: password or key auth,
known_hostsverification, automatic reconnect
Install 📦
macOS, Linux, WSL:
curl -fsSL https://dbmcp.haymon.ai/install.sh | bash
Windows PowerShell:
irm https://dbmcp.haymon.ai/install.ps1 | iex
Windows CMD:
curl -fsSL https://dbmcp.haymon.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
npm (MCP clients can also launch it with npx -y @haymon-ai/dbmcp):
npm install -g @haymon-ai/dbmcp
See the installation docs for Docker, Cargo, and other methods.
MCP Registry name: mcp-name: ai.haymon/dbmcp
Quick Start 🚀
The buttons launch dbmcp with npx (Node.js 18+). VS Code prompts for the connection settings; Cursor installs placeholders to edit afterwards. For Claude Desktop, Claude Code, Codex, Windsurf, Zed, Gemini CLI, Goose, JetBrains, and LM Studio, see MCP Clients.
Using .mcp.json (recommended)
Add a .mcp.json file to your project root. MCP clients read this file and configure the server automatically.
Stdio transport — the client starts and manages the server process:
{
"mcpServers": {
"dbmcp": {
"command": "dbmcp",
"env": {
"DBMCP_DB_BACKEND": "mysql",
"DBMCP_DB_HOST": "127.0.0.1",
"DBMCP_DB_PORT": "3306",
"DBMCP_DB_USER": "root",
"DBMCP_DB_PASSWORD": "secret",
"DBMCP_DB_NAME": "mydb"
}
}
}
}
HTTP transport — you start the server yourself, the client connects to it:
# Start the server first
DBMCP_TRANSPORT=http DBMCP_DB_BACKEND=mysql DBMCP_DB_USER=root DBMCP_DB_NAME=mydb dbmcp
{
"mcpServers": {
"dbmcp": {
"type": "http",
"url": "http://127.0.0.1:9001/mcp"
}
}
}
Note: The
"type": "http"field is required for HTTP transport. Without it, clients like Claude Code will reject the config.
To require a bearer token, start the server with DBMCP_HTTP_AUTH_TOKEN and send it from the client:
DBMCP_HTTP_AUTH_TOKEN="$(openssl rand -hex 32)" DBMCP_TRANSPORT=http DBMCP_DB_BACKEND=mysql DBMCP_DB_USER=root DBMCP_DB_NAME=mydb dbmcp
{
"mcpServers": {
"dbmcp": {
"type": "http",
"url": "http://127.0.0.1:9001/mcp",
"headers": { "Authorization": "Bearer ${DBMCP_TOKEN}" }
}
}
}
Using environment variables
# MySQL/MariaDB
DBMCP_DB_BACKEND=mysql DBMCP_DB_HOST=localhost DBMCP_DB_USER=root DBMCP_DB_NAME=mydb dbmcp
# PostgreSQL
DBMCP_DB_BACKEND=postgres DBMCP_DB_HOST=localhost DBMCP_DB_USER=postgres DBMCP_DB_NAME=mydb dbmcp
# SQLite
DBMCP_DB_BACKEND=sqlite DBMCP_DB_NAME=./data.db dbmcp
# PostgreSQL through an SSH bastion (DB host is resolved by the bastion)
DBMCP_DB_BACKEND=postgres DBMCP_DB_HOST=db.internal DBMCP_DB_USER=postgres DBMCP_DB_NAME=mydb \
DBMCP_SSH_HOST=bastion.example.com DBMCP_SSH_USER=deploy DBMCP_SSH_KEY=~/.ssh/id_ed25519 dbmcp
# HTTP transport (loopback only, no token required)
DBMCP_TRANSPORT=http DBMCP_DB_BACKEND=mysql DBMCP_DB_USER=root DBMCP_DB_NAME=mydb dbmcp
# HTTP transport on all interfaces — a bearer token is REQUIRED
DBMCP_HTTP_AUTH_TOKEN=change-me DBMCP_TRANSPORT=http DBMCP_HTTP_HOST=0.0.0.0 \
DBMCP_DB_BACKEND=mysql DBMCP_DB_USER=root DBMCP_DB_NAME=mydb dbmcp
Warning: Binding a non-loopback address (e.g.
DBMCP_HTTP_HOST=0.0.0.0) exposes the database to anyone who can reach the port.dbmcprefuses to start in that case unlessDBMCP_HTTP_AUTH_TOKENis set. The Host/Origin allowlists protect against browser DNS rebinding only — they are not authentication.
Using a config file
# dbmcp.yaml
database:
backend: postgres
host: localhost
user: postgres
password: ${DB_PASSWORD:?set DB_PASSWORD}
name: mydb
DB_PASSWORD=secret dbmcp --config-file /path/to/dbmcp.yaml
From an MCP client, pass "args": ["--config-file", "~/path/to/dbmcp.yaml"] or an absolute path; relative paths resolve against the process working directory, which the client controls. See Config File.
Configuration ⚙️
Every setting has a DBMCP_* environment variable and a YAML key. Each setting is resolved with clear precedence:
process environment > env files (--env-file) > config files (--config-file) > defaults
Environment variables are typically set by your MCP client (via env or envFile in the server config). An empty DBMCP_* value counts as unset. Nothing is discovered automatically: a file is read only when you name it.
| Flag | Env Variable | Description |
|---|---|---|
--config-file <PATH> |
DBMCP_CONFIG_FILE |
YAML config file (${} interpolation, strict keys); repeatable (env var: comma list), later wins |
--env-file <PATH> |
DBMCP_ENV_FILE |
Env file of KEY=VALUE lines; repeatable (env var: comma list), later wins |
Layer files by repeating a flag, e.g. a shared base plus local overrides: dbmcp --config-file base.yaml --config-file local.yaml. Each setting comes from the last file that sets it; lists replace.
There are no per-setting flags. Booleans accept true/false, 1/0, t/f (not yes/no); lists are comma-separated in env vars.
- Configuration reference — every setting with its YAML key, env var, type, and default, plus Migrating from CLI flags
- Config File — file schema,
${}interpolation, env file format, path resolution, Docker, and error output
Security note: Read-only mode is on by default (
DBMCP_DB_READ_ONLY=true). The default HTTPOriginallowlist accepts browser pages from any port onlocalhost/127.0.0.1/[::1]; on shared or development machines, setDBMCP_HTTP_AUTH_TOKENor narrowDBMCP_HTTP_ALLOWED_ORIGINSto the explicit origins you trust (e.g.http://localhost:5173).
The SSH tunnel is MySQL/MariaDB/PostgreSQL only and uses an embedded SSH client (no ssh binary). DBMCP_DB_HOST/DBMCP_DB_PORT are resolved by the SSH server. With both a key and a password set, the key is tried first. See SSH Tunnel for host-key policies, limitations, and troubleshooting.
MCP Tools 🧩
listDatabases
Lists accessible databases, paginated via cursor / nextCursor. See Cursor Pagination for iteration details. Not available for SQLite.
listTables
Lists tables in a database, paginated via cursor / nextCursor. See Cursor Pagination for iteration details.
Parameters: database (defaults to the active database; SQLite has no database parameter), cursor, search, detailed.
search is an optional case-insensitive LIKE/ILIKE pattern with % (any sequence) and _ (single character) as wildcards — pass users% to match names beginning with users, or %order% for substring matching. A bare word with no wildcards matches only an exact table name.
detailed (default false) switches the response shape:
- Brief (default) —
tablesis a sorted JSON array of bare table-name strings. - Detailed (
detailed: true) —tablesis a JSON object keyed by table name; each value carries the table'sschema,kind,owner,comment,columns[],constraints[],indexes[], andtriggers[]. One call returns both the table list and the per-table metadata.
listViews
Lists views in a database, paginated via cursor / nextCursor. Available on MySQL/MariaDB, PostgreSQL (public schema), and SQLite. Parameters: database (defaults to the active database; SQLite has no database parameter), cursor, search, detailed. SQLite returns the brief shape only — search and detailed are not accepted there.
search is an optional case-insensitive LIKE/ILIKE pattern with % (any sequence) and _ (single character) as wildcards. The search value must remain identical across paginated calls for cursor continuity.
detailed (default false) switches the response shape:
- Brief (default) —
viewsis a sorted JSON array of bare view-name strings. View names are unique per schema, so no duplicates appear. - Detailed (
detailed: true) —viewsis a JSON object keyed by bare view name; each value carries the per-backend metadata payload. PostgreSQL exposesschema,owner,description,definition. MySQL/MariaDB exposesschema,definer,security,checkOption,updatable,characterSetClient,collationConnection,definition. See thelistViewsreference for source columns, enumerated value sets, and intentional omissions per backend.
See Cursor Pagination for iteration details.
listTriggers
Lists user-defined triggers on tables, paginated via cursor / nextCursor. Internal constraint and foreign-key triggers are excluded. Available on MySQL/MariaDB, PostgreSQL (public schema), and SQLite. Parameters: database (defaults to the active database; SQLite has no database parameter), cursor, search, detailed.
search is an optional case-insensitive LIKE/ILIKE pattern with % (any sequence) and _ (single character) as wildcards. The search value must remain identical across paginated calls for cursor continuity.
detailed (default false) switches the response shape:
- Brief (default) —
triggersis a sorted JSON array of bare trigger-name strings. - Detailed (
detailed: true) —triggersis a JSON object keyed by trigger name; each value carries the per-backend metadata payload (timing, events, definition, and backend-specific extras like PostgreSQLstatus/functionNameor MySQL/MariaDB session-context fields). See thelistTriggersreference for the full per-backend field list.
See Cursor Pagination for iteration details.
listFunctions
Lists user-defined SQL functions, paginated via cursor / nextCursor. PostgreSQL excludes aggregates, window functions, and procedures; MySQL/MariaDB excludes loadable UDFs (mysql.func). Available on MySQL/MariaDB and PostgreSQL (public schema). Not available for SQLite. Parameters: database (defaults to the active database), cursor, search, detailed.
search is an optional case-insensitive LIKE/ILIKE pattern with % (any sequence) and _ (single character) as wildcards. The search value must remain identical across paginated calls for cursor continuity.
detailed (default false) switches the response shape:
- Brief (default) —
functionsis a sorted JSON array of bare function-name strings. PostgreSQL overloads appear once per overload (duplicate name strings are expected). - Detailed (
detailed: true) —functionsis a JSON object keyed by function signature; each value carries the per-backend metadata payload (language, arguments, return type, definition, and backend-specific extras such as PostgreSQLvolatility/strict/parallelSafetyor MySQL/MariaDB session-context fields). PostgreSQL keys arename(arguments)(overloads disambiguate); MySQL/MariaDB keys are bare names (no overloading). See thelistFunctionsreference for the full per-backend field list.
See Cursor Pagination for iteration details.
listProcedures
Lists user-defined stored procedures, paginated via cursor / nextCursor. Available on MySQL/MariaDB and PostgreSQL (public schema, PostgreSQL 11+). Not available for SQLite. Parameters: database (defaults to the active database), cursor, search, detailed.
search is an optional case-insensitive LIKE/ILIKE pattern with % (any sequence) and _ (single character) as wildcards. The search value must remain identical across paginated calls for cursor continuity.
detailed (default false) switches the response shape:
- Brief (default) —
proceduresis a sorted JSON array of bare procedure-name strings. PostgreSQL overloads appear once per overload (duplicate name strings are expected). - Detailed (
detailed: true) —proceduresis a JSON object keyed by procedure signature; each value carries the per-backend metadata payload (language, arguments, security, definition, and backend-specific extras such as PostgreSQLowneror MySQL/MariaDBdeterministic/sqlDataAccess/session-context fields). PostgreSQL keys arename(arguments)(overloads disambiguate; zero-arg procedures key asname()); MySQL/MariaDB keys are bare names (no overloading). See thelistProceduresreference for the full per-backend field list.
See Cursor Pagination for iteration details.
listMaterializedViews
Lists materialized views in the public schema, paginated via cursor / nextCursor. PostgreSQL only — not available for MySQL/MariaDB or SQLite. Parameters: database (defaults to the active database), cursor, search, detailed.
search is an optional case-insensitive ILIKE pattern with % (any sequence) and _ (single character) as wildcards. SQL meta-characters (', ;, --) are bound as parameter values and never interpolated. The search value must remain identical across paginated calls for cursor continuity.
detailed (default false) switches the response shape:
- Brief (default) —
materializedViewsis a sorted JSON array of bare matview-name strings. Matview names are unique per schema, so no duplicates appear. - Detailed (
detailed: true) —materializedViewsis a JSON object keyed by bare matview name; each value carriesschema,owner,description(ornullwhen noCOMMENT ON MATERIALIZED VIEW),definition(the SELECT body verbatim frompg_matviews.definition),populated(falsefor matviews createdWITH NO DATAand never refreshed), andindexed(truewhen at least one index exists;REFRESH MATERIALIZED VIEW CONCURRENTLYadditionally requires a unique index). Detailed mode deliberately omits column metadata,tablespace, storage parameters, and unique-index detection — recoverable viadefinition,listTables(detailed=true), orreadQueryagainstpg_indexes. See thelistMaterializedViewsreference for source columns and operational semantics.
See Cursor Pagination for iteration details.
readQuery
Executes a read-only SQL query (SELECT, SHOW, DESCRIBE, EXPLAIN). Always enforces SQL validation as defence-in-depth. Parameters: query, database, cursor. SELECT results paginate via cursor / nextCursor; SHOW, DESCRIBE, and EXPLAIN return a single page and ignore cursor. See Cursor Pagination for iteration details.
writeQuery
Executes a write SQL query (INSERT, UPDATE, DELETE, CREATE, ALTER, DROP). Only available when read-only mode is disabled. Parameters: query, database.
createDatabase
Creates a database if it doesn't exist. Only available when read-only mode is disabled. Not available for SQLite. Parameters: database.
dropDatabase
Drops an existing database. Refuses to drop the currently connected database. Only available when read-only mode is disabled. Not available for SQLite. Parameters: database.
dropTable
Drops a table from a database. If the table has foreign key dependents, the database error is surfaced to the user. On PostgreSQL, a cascade parameter is available to force the drop with CASCADE. Only available when read-only mode is disabled. Parameters: database, table, cascade (PostgreSQL only).
explainQuery
Returns the execution plan for a SQL query. Supports an optional analyze parameter for actual execution statistics (PostgreSQL and MySQL/MariaDB). In read-only mode, EXPLAIN ANALYZE is only allowed for read-only statements since it actually executes the query. In read-only mode, every EXPLAIN runs inside a read-only transaction, so on MySQL/MariaDB plain EXPLAIN of write statements is rejected. SQLite uses EXPLAIN QUERY PLAN (no ANALYZE support). Always available regardless of read-only mode. Parameters: query, database, analyze (PostgreSQL/MySQL only).
Database MCP questions
How do I add Database MCP to Claude Code?
Run claude mcp add database -- docker run -i --rm ghcr.io/haymon-ai/database:0.7.0 in your terminal. Add --scope user to make it available in every project.
How do I add Database MCP to Cursor?
Open ~/.cursor/mcp.json and add the server under mcpServers, using the Cursor config shown in the install section above.
Which databases does this MCP server support?
It supports MySQL/MariaDB, PostgreSQL, and SQLite from a single binary.
Can the AI client write to the database or only read?
Read-only mode is enabled by default and hides write tools like writeQuery, createDatabase, dropDatabase, and dropTable.
Does it support remote databases behind an SSH bastion?
Yes, it can reach MySQL/MariaDB/PostgreSQL through an SSH bastion with password or key auth and known_hosts verification.
What transports does this MCP server support?
It supports stdio for desktop clients and HTTP for remote or multi-client use, with an optional bearer token.
How is the server configured?
Settings come from DBMCP_* environment variables, env files, or a YAML config file, with process environment taking precedence.