PluginWorld
Ke

keyward-mcp-server

MCP

Enables AI assistants to run SQL queries on PostgreSQL databases through a credential-isolated proxy, with read-only queries by default and write operations requiring explicit confirmation.

@gwdmnn · Apache-2.0 · updated today

SECURITY

B

SCORE

60

STARS

0

PLUG IN

git clone https://github.com/gwdmnn/keyward-mcp-server.git

See the README to configure this MCP server

README

db-mcp-server

A local MCP server that gives an AI coding assistant (e.g. Claude Code) credential-isolated access to your PostgreSQL databases. The assistant sends only SQL and receives only rows — database usernames, passwords, and SSH keys never enter the model's context or the conversation transcript.

Why

Wiring an AI assistant to a database usually means putting connection strings and passwords somewhere the model (and its transcript) can read them. This server keeps that boundary: it owns the encrypted credentials and the SSH tunnels, exposes a small SQL-only tool surface, and defaults to read-only.

How it works

  • Catalog (registry.yaml) — non-secret routing. Organized as customers → environments → services; each service maps to a database name and a secret_ref (a pointer into the vault — never a credential).
  • Vault (vault.enc) — AES-256-GCM with a scrypt-derived key. Holds the DB credentials, decrypted into memory once at launch using a passphrase.
  • Tunnel pool — one SSH tunnel per (customer, environment) via sshtunnel, bound to an ephemeral 127.0.0.1 port.
  • Executorpsycopg. run_query runs in a Postgres READ ONLY transaction (the engine rejects any write); run_write_query requires confirm=true.

Install

python -m venv .venv
# Windows PowerShell: .venv\Scripts\Activate.ps1   (bash: source .venv/Scripts/activate)
pip install -e ".[dev]"

Configure

Configuration comes from environment variables; defaults resolve relative to the project root.

Variable Purpose Default
DB_MCP_PASSPHRASE Vault passphrase (required to run the server)
DB_MCP_REGISTRY Path to registry.yaml ./registry.yaml
DB_MCP_VAULT Path to vault.enc ./vault.enc
DB_MCP_KEYS_DIR Directory holding the SSH PEM keys ./keys
DB_MCP_BOOTSTRAP Path to bootstrap.yaml ./bootstrap.yaml

Provision (first-time setup)

  1. Copy the template and fill in real values:
    cp bootstrap.example.yaml bootstrap.yaml
    
  2. Put your SSH private keys in keys/ (filenames must match the pem_key fields in the catalog).
  3. Generate the non-secret catalog and the encrypted vault (prompts for the passphrase you'll reuse to run the server):
    python -m db_mcp_server.bootstrap --dry-run   # preview, writes nothing
    python -m db_mcp_server.bootstrap             # writes registry.yaml + vault.enc
    python -m db_mcp_server.vault_admin verify     # expect {"ok": true}
    

bootstrap.yaml holds plaintext credentials — it is git-ignored; delete it or keep it offline once the vault exists.

Command-line tools

Command Purpose
db-mcp-server The MCP server (stdio). Launched by the MCP client, not by hand.
db-vault Manage credentials in the vault: set / rm / list / verify.
db-bootstrap Split bootstrap.yaml into registry.yaml + vault.enc.

(Console commands exist after pip install -e .; the python -m db_mcp_server.<module> form always works.)

Tools exposed to the assistant

  • list_databases() — the catalog (customers → environments → services); no secrets.
  • run_query(customer, environment, service, sql, max_rows?) — read-only.
  • run_write_query(customer, environment, service, sql, confirm) — gated write.

Domain failures come back as a structured {error_code, message} rather than an exception, so the assistant can react.

Register with an MCP client

Example .mcp.json (adjust paths). Use ${DB_MCP_PASSPHRASE} so the passphrase is read from the shell instead of being written into the file:

{
  "mcpServers": {
    "db": {
      "command": "/absolute/path/to/db-mcp-server/.venv/Scripts/python.exe",
      "args": ["-m", "db_mcp_server.server"],
      "env": {
        "DB_MCP_PASSPHRASE": "${DB_MCP_PASSPHRASE}"
      }
    }
  }
}

Security notes

  • vault.enc, keys/, bootstrap.yaml, *.env, and *.pem are git-ignored — never commit them.
  • The vault passphrase is supplied via DB_MCP_PASSPHRASE (or a prompt) — never stored in registry.yaml, argv, or logs.
  • db-vault reads the DB password via a hidden prompt (getpass), never via argv.
  • run_query is read-only at the Postgres engine level; writes require confirm=true.

Tests

pip install -e ".[dev]" && python -m pytest -q

The DB integration test is skipped unless DB_MCP_TEST_DSN points at a reachable PostgreSQL.

Roadmap (not in this build)

Persistent audit trail, multi-user operation, external secret-manager backing, schema-introspection tools, and a permission denylist to turn the credential isolation into a hard boundary.

SIMILAR PLUGINS