Database MCP

Security

How Database MCP protects your data

Database MCP is designed with security as a primary concern. When you give an AI assistant access to your database, you need confidence that your data is protected. Here is how Database MCP keeps your data safe.

Read-Only Mode

By default, Database MCP runs in read-only mode. This controls which tools the AI assistant can see and use.

Tool-Level Access Control

In read-only mode, write tools (writeQuery, createDatabase, dropDatabase, dropTable) are not registered with the MCP client. The AI assistant never sees them in the tool list, which prevents it from attempting write operations entirely.

When read-only mode is disabled, the full tool set becomes available. See Features for the complete tool availability matrix.

SQL Validation in readQuery

The readQuery tool enforces AST-based SQL validation as defence-in-depth. Only the following SQL operations are permitted:

  • SELECT — read data from tables
  • SHOW — view database and table metadata
  • DESCRIBE / DESC — inspect table structure
  • USE — switch between databases
  • EXPLAIN — view query execution plans

This validation is always enforced, even when read-only mode is disabled, preventing write statements from being smuggled through the read tool.

Blocked Operations

The following are always blocked regardless of mode:

  • LOAD_FILE() — prevents reading files from the server filesystem
  • SELECT INTO OUTFILE / SELECT INTO DUMPFILE — prevents writing files to the server filesystem

SQL comments and string contents are stripped before validation to prevent bypass attempts.

Injection Prevention

Database MCP implements multiple layers of protection against SQL injection:

Multi-Statement Blocking

The server never enables multi-statement execution on database connections. This prevents an attacker from appending malicious statements (such as ; DROP TABLE users) to a legitimate query.

Parameterized Queries

User-provided values are never interpolated into SQL strings. All values are passed through parameterized queries, which ensures the database treats them as data rather than executable SQL.

Identifier Validation

Database and table names are validated to contain only alphanumeric characters and underscores. Names are then properly quoted using each database backend's native quoting mechanism, preventing injection through crafted identifiers.

HTTP Transport Authentication

The http transport serves the database to any caller that can reach the port, using the server's own database credentials. Set HTTP_AUTH_TOKEN (or --auth-token) to require Authorization: Bearer <token> on every request. Missing or wrong tokens get 401 Unauthorized with WWW-Authenticate: Bearer realm="dbmcp"; tokens are compared in constant time and never logged.

  • Loopback binds (the default 127.0.0.1, ::1, localhost) work without a token.
  • Non-loopback binds (e.g. --host 0.0.0.0) refuse to start without a token. --dangerously-allow-unauthenticated overrides this — use it only behind a reverse proxy that authenticates callers.

The Origin and Host allowlists remain enforced alongside the token. They stop browser-driven DNS-rebinding attacks, but a direct HTTP client can send any header value, so they are not authentication.

SSH Host-Key Verification

When the SSH tunnel is enabled, the SSH server's host key is verified against known_hosts before any password or key signature is sent. Under yes and accept-new, credentials never reach an impostor that known_hosts would reject; under no they can (see below).

  • yes (default) — only hosts already recorded in known_hosts are accepted. Add a host by checking its fingerprint out-of-band, then running the ssh-keyscan command from the error message.
  • accept-new — trust on first use: the first key seen for an unknown host is recorded and trusted from then on. If an attacker intercepts that first connection, their key is recorded instead. Use it only on networks you trust for the initial connect, or pre-seed known_hosts. Afterwards it behaves like yes; a known host that offers a key of an unrecorded type is rejected rather than learned.
  • no — verification is disabled and a warning is logged at startup. Anyone on the network path can impersonate the SSH server. A changed key is still logged, and password authentication is skipped for that session, but key authentication proceeds. Avoid outside throwaway test setups.
  • @revoked entries are rejected under every policy, provided known_hosts is readable. Under no, an unreadable known_hosts is skipped with a warning, so revocations in it are not enforced.

Secrets are protected the same way as database credentials: SSH_PASSWORD and SSH_KEY_PASSPHRASE are printed as [REDACTED] in debug output and are never logged; SSH error messages never include passwords, passphrases, or key material (the key path may appear). The private key is decrypted once at startup and kept only in memory.

On Unix, a private key accessible by group or others triggers a startup warning suggesting chmod 600, but is still used. Windows does not get a key-permission check — protect the key file with NTFS ACLs yourself. When accept-new creates known_hosts, the file gets mode 0600 and any directories it creates get 0700 on Unix (subject to your umask); an existing ~/.ssh keeps its current mode, so check it is not world-writable. On Windows the file inherits its folder's ACL.

PII Redaction

Database MCP ships an optional PII redactor as defence-in-depth: even when the AI assistant has SELECT access to a table containing sensitive values, those values can be rewritten in tool output before they reach the model. The feature is opt-in and off by default — operators must enable it explicitly via --pii / PII_ENABLE. Detection can be scoped to a subset of categories via --pii-categories / PII_CATEGORIES.

Scope

Redaction applies only to query tool output payloads — readQuery results, plus any future query tools that route through the same redactor. The following are not redacted:

  • Server logs and structured tracing output
  • Error messages returned to the client
  • Schema-discovery tool responses (listTables, listViews, listTriggers, etc.)
  • Tool arguments supplied by the assistant

Redaction recurses into json and jsonb columns: every string leaf at any depth is rewritten with the same operator a flat text column would use. JSON object keys are preserved verbatim — only values are inspected. Non-string scalars (numbers, booleans, null) and the surrounding JSON shape (key names, array indexes, container ordering) are unchanged.

Treat PII redaction as a layer that reduces what an enabled assistant sees in result rows; it is not a blanket guarantee that no sensitive string ever leaves the server. Pair it with database-level controls (least-privilege roles, column masking views) for sensitive datasets.

See Features for the supported entity list and operator semantics, and Configuration for the toggle and operator-selection flags.

Disabling Read-Only Mode

Read-only mode can be explicitly disabled if you need write access. Set the DB_READ_ONLY environment variable to false or pass the --db-read-only false flag. This makes writeQuery, createDatabase, dropDatabase, and dropTable (where supported) available to the AI assistant. Only disable read-only mode in environments where you trust the AI assistant to make changes to your data.

On this page