Database MCP server for MySQL, MariaDB, PostgreSQL & SQLite with PII redaction and write-prevention
ai.haymon/dbmcp โ Database MCP Server
This Model Context Protocol (MCP) server provides a single-binary interface to SQL databases. It supports MySQL, MariaDB, PostgreSQL, and SQLite, and includes PII redaction with write-prevention. The project is published under the MIT license and documented at dbmcp.haymon.ai.
Environment variables are typically set by your MCP client (via env or envFile in the server config).
Subcommands
Subcommand
Description
stdio
Run in stdio mode
http
Run in HTTP/SSE mode
version
Print version information and exit
A subcommand is required โ running dbmcp with no subcommand prints usage help and exits with a non-zero status.
Database Options (shared across subcommands)
Flag
Env Variable
Default
Description
--db-backend
DB_BACKEND
(required)
mysql, mariadb, postgres, or sqlite
--db-host
DB_HOST
localhost
Database host
--db-port
DB_PORT
backend default
3306 (MySQL/MariaDB), 5432 (PostgreSQL)
--db-user
DB_USER
backend default
root (MySQL/MariaDB), postgres (PostgreSQL)
--db-password
DB_PASSWORD
(empty)
Database password
--db-name
DB_NAME
(empty)
Database name or SQLite file path
--db-charset
DB_CHARSET
Character set (MySQL/MariaDB only)
SSL/TLS Options
Flag
Env Variable
Default
Description
--db-ssl
DB_SSL
false
Enable SSL
--db-ssl-ca
DB_SSL_CA
CA certificate path
--db-ssl-cert
DB_SSL_CERT
Client certificate path
--db-ssl-key
DB_SSL_KEY
Client key path
--db-ssl-verify-cert
DB_SSL_VERIFY_CERT
true
Verify server certificate
Server Options
Flag
Env Variable
Default
Description
--db-read-only
DB_READ_ONLY
true
Block write queries
--db-max-pool-size
DB_MAX_POOL_SIZE
5
Max connection pool size (min: 1)
--db-connection-timeout
DB_CONNECTION_TIMEOUT
(unset)
Connection timeout in seconds (min: 1)
--db-query-timeout
DB_QUERY_TIMEOUT
30
Query execution timeout in seconds
--db-page-size
DB_PAGE_SIZE
100
Max items per paginated tool response (range 1โ500)
Logging Options
Flag
Env Variable
Default
Description
--log-level
LOG_LEVEL
info
Log level (trace/debug/info/warn/error)
HTTP-only Options (only available with http subcommand)
Flag
Default
Description
--host
127.0.0.1
Bind host
--port
9001
Bind port
--allowed-origins
localhost variants
Allowed browser origins (comma-separated). Drives both CORS preflight and server-side Origin rejection.
--allowed-hosts
localhost,127.0.0.1,::1
Trusted Host headers (comma-separated). Enforced server-side; HTTP/2 :authority is honored.
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) โ tables is a sorted JSON array of bare table-name strings.
Detailed (detailed: true) โ tables is a JSON object keyed by table name; each value carries the table's schema, kind, owner, comment, columns[], constraints[], indexes[], and triggers[]. 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) โ views is a sorted JSON array of bare view-name strings. View names are unique per schema, so no duplicates appear.
Detailed (detailed: true) โ views is a JSON object keyed by bare view name; each value carries the per-backend metadata payload. PostgreSQL exposes schema, owner, description, definition. MySQL/MariaDB exposes schema, definer, security, checkOption, updatable, characterSetClient, collationConnection, definition. See the listViews reference for source columns, enumerated value sets, and intentional omissions per backend.
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) โ triggers is a sorted JSON array of bare trigger-name strings.
Detailed (detailed: true) โ triggers is a JSON object keyed by trigger name; each value carries the per-backend metadata payload (timing, events, definition, and backend-specific extras like PostgreSQL status/functionName or MySQL/MariaDB session-context fields). See the listTriggers reference for the full per-backend field list.
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) โ functions is a sorted JSON array of bare function-name strings. PostgreSQL overloads appear once per overload (duplicate name strings are expected).
Detailed (detailed: true) โ functions is 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 PostgreSQL volatility/strict/parallelSafety or MySQL/MariaDB session-context fields). PostgreSQL keys are name(arguments) (overloads disambiguate); MySQL/MariaDB keys are bare names (no overloading). See the listFunctions reference for the full per-backend field list.
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) โ procedures is a sorted JSON array of bare procedure-name strings. PostgreSQL overloads appear once per overload (duplicate name strings are expected).
Detailed (detailed: true) โ procedures is 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 PostgreSQL owner or MySQL/MariaDB deterministic/sqlDataAccess/session-context fields). PostgreSQL keys are name(arguments) (overloads disambiguate; zero-arg procedures key as name()); MySQL/MariaDB keys are bare names (no overloading). See the listProcedures reference for the full per-backend field list.
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) โ materializedViews is a sorted JSON array of bare matview-name strings. Matview names are unique per schema, so no duplicates appear.
Detailed (detailed: true) โ materializedViews is a JSON object keyed by bare matview name; each value carries schema, owner, description (or null when no COMMENT ON MATERIALIZED VIEW), definition (the SELECT body verbatim from pg_matviews.definition), populated (false for matviews created WITH NO DATA and never refreshed), and indexed (true when at least one index exists; REFRESH MATERIALIZED VIEW CONCURRENTLY additionally requires a unique index). Detailed mode deliberately omits column metadata, tablespace, storage parameters, and unique-index detection โ recoverable via definition, listTables(detailed=true), or readQuery against pg_indexes. See the listMaterializedViews reference for source columns and operational semantics.
Executes a read-only SQL query (SELECT, SHOW, DESCRIBE, USE, EXPLAIN). Always enforces SQL validation as defence-in-depth. Parameters: query, database, cursor. SELECT results paginate via cursor / nextCursor; SHOW, DESCRIBE, USE, 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. SQLite uses EXPLAIN QUERY PLAN (no ANALYZE support). Always available regardless of read-only mode. Parameters: query, database, analyze (PostgreSQL/MySQL only).
Security ๐
Read-only mode (default) โ write tools hidden from AI assistant; readQuery enforces AST-based SQL validation
Single-statement enforcement โ multi-statement injection blocked at parse level
Dangerous function blocking โ LOAD_FILE(), INTO OUTFILE, INTO DUMPFILE detected in the AST
Identifier validation โ database/table names validated against control characters and empty strings
Origin + Host allowlists โ server-side rejection (403) plus CORS preflight; configurable for HTTP transport
SSL/TLS โ configured via individual DB_SSL_* variables
PII redaction(opt-in, off by default) โ when enabled, query tool output passes through a regex-based redactor that rewrites detected PII spans across 46 built-in entity types spanning seven categories: personal (email), financial (cards, IBAN, UK bank accounts, sort and US ABA routing codes, CVV), government IDs (SSN, ITIN, EIN, UK/US passports, NHS, NINO, SIN, VAT), contact (phone), network (IP, URL, MAC), digital identity (API keys, JWTs, PEM private keys, password hashes), and crypto wallets. Toggle: --pii / PII_ENABLE. Operator: --pii-operator / PII_OPERATOR โ one of replace (default, entity-aware placeholders like <EMAIL_ADDRESS>), mask (length-preserving *), redact (drop), hash (SHA-256 hex). Optional subset via --pii-categories / PII_CATEGORIES (comma-separated, e.g. financial,government); unset enables all built-ins. Scope: query tool output payloads only. See PII configuration for the full surface.
ML/NER redaction(opt-in at runtime, off by default) โ adds PERSON, LOCATION, ORGANIZATION, NATIONALITY_RELIGION_POLITICS, and FACILITY detection that regex cannot catch, enabled via the --pii-ner / PII_NER_ENABLE toggle plus a user-supplied model directory. Which entities are produced depends on the model's labels (CoNLL models give person/location/organization; OntoNotes-class models add NRP and facility). Inference uses ONNX Runtime (model directory holds config.json, tokenizer.json, model.onnx; recommended: the MIT-licensed dslim/bert-base-NER exported to ONNX, int8-quantized for speed). Fail-closed: a model that cannot load aborts startup and an inference error fails the request โ never a silent fallback. Respects --pii-categories. English for v1.
Credential redaction โ database password is never shown in logs or debug output
Testing ๐งช
bash
# Unit tests
cargo test --workspace --lib --bins
# Integration tests (requires Docker)
./tests/run.sh
# Filter by engine
./tests/run.sh --filter mariadb
./tests/run.sh --filter mysql
./tests/run.sh --filter postgres
./tests/run.sh --filter sqlite
# With MCP Inspector
npx @modelcontextprotocol/inspector ./target/release/dbmcp stdio
# HTTP mode testing
curl -X POST http://localhost:9001/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1"}}}'
Project Structure ๐๏ธ
This is a Cargo workspace with the following crates:
Crate
Path
Description
dbmcp
. (root)
Main binary โ CLI, transports, database backends
dbmcp-sql
crates/backend/
Shared error types, validation, and identifier utilities
dbmcp-config
crates/config/
Configuration structs and CLI argument mapping
dbmcp-server
crates/server/
Shared MCP tool implementations and server info
dbmcp-mysql
crates/mysql/
MySQL/MariaDB backend handler and operations
dbmcp-postgres
crates/postgres/
PostgreSQL backend handler and operations
dbmcp-sqlite
crates/sqlite/
SQLite backend handler and operations
sqlx-json
crates/sqlx-json/
Type-safe row-to-JSON conversion for sqlx (RowExt trait)