Skip to main content
Glama
aminyx

mcp-devdb

by aminyx

mcp-devdb

CI

Safe, read-only MCP server for local development databases. Coding agents constantly need to see your dev database — schema, sample data, query plans, table sizes — but a naive database connector hands them full write access. mcp-devdb is the guarded alternative: a Model Context Protocol server that exposes introspection tools behind a hardened read-only SQL guard, column masking, result caps, and a per-session query budget.

Backends in v1: PostgreSQL (via postgres) and SQLite (via better-sqlite3). The adapter interface is engine-neutral, so MySQL can be added later.

Quickstart

  1. Create mcp-devdb.json next to where the server will run (see mcp-devdb.example.json):

{
  "databases": {
    "app": { "url": "postgres://dev:dev@localhost:5432/app_development" },
    "cache": { "url": "sqlite:./data/cache.db" }
  }
}
  1. Run it:

npx mcp-devdb --config ./mcp-devdb.json

The server speaks MCP over stdio; point your MCP client at that command. Connection strings live only in the config file or environment variables ("url": "env:MY_DB_URL", or the MCP_DEVDB_URL fallback with no config file) — the model can never supply one.

Claude Code

claude mcp add devdb -- npx mcp-devdb --config /absolute/path/to/mcp-devdb.json

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "devdb": {
      "command": "npx",
      "args": ["mcp-devdb", "--config", "/absolute/path/to/mcp-devdb.json"]
    }
  }
}

Related MCP server: MCP PostgreSQL

Tools

Tool

Input

What it returns

list_tables

database?

Schemas, tables, views with row estimates and on-disk sizes

describe_table

database?, table

Columns, types, nullability, defaults, PK, FKs, indexes

sample_rows

database?, table, limit? (max 50)

First N rows; cells > 200 chars truncated; sensitive columns masked as ***

run_query

database?, sql

Guarded read-only query; row cap (200) + byte cap (256 KiB); consumes query budget

explain_query

database?, sql

Execution plan — PostgreSQL EXPLAIN (FORMAT JSON), SQLite EXPLAIN QUERY PLAN; consumes query budget

db_overview

database?

Database name, size, table count, largest tables, extensions (PG)

database is optional when exactly one database is configured; with several, name the one you want.

Configuration

mcp-devdb.json in the working directory, or any path via --config:

{
  "databases": {
    "app": {
      "url": "postgres://dev:dev@localhost:5432/app_development",
      "allowTables": ["users", "orders", "public.events_*"],
      "denyTables": ["audit_log"]
    },
    "billing": { "url": "env:BILLING_DEV_DATABASE_URL" }
  },
  "maskPatterns": ["password", "secret", "token", "key", "hash", "ssn", "card"],
  "queryBudget": 100,
  "rowLimit": 200,
  "byteLimit": 262144,
  "statementTimeoutMs": 5000
}
  • allowTables / denyTables — case-insensitive names with * wildcards; rules containing a dot match schema.table. Deny wins; a non-empty allowlist is exclusive.

  • maskPatterns — case-insensitive regexes matched against column names.

  • CLI flags: --config <path>, --no-mask (disable column masking), --help, --version.

Security model (summary)

The full threat model lives in SECURITY.md. In short:

  • Read-only guard: every run_query/explain_query statement is tokenized (quotes, E'...' escapes, comments, dollar-quoted strings) and must start with SELECT / WITH / EXPLAIN / SHOW / VALUES; multi-statement input and write/DDL keywords anywhere at top level are rejected — a CTE followed by INSERT is caught, SELECT 'DROP TABLE x' is not a false positive.

  • Engine-level enforcement: SQLite files are opened read-only; PostgreSQL sessions run with default_transaction_read_only=on, explicit BEGIN READ ONLY transactions, and statement timeouts.

  • Column masking on by default (--no-mask to opt out), result caps, and a per-session query budget (default 100; exhaustion tells you to restart the server).

  • Credentials never reach the model: connection strings come only from local config/env and are scrubbed from every error message.

Smoke test

scripts/verify-stdio.mjs builds a temp SQLite database, spawns node dist/cli.js, and drives a real MCP handshake over stdio with raw JSON-RPC. Actual output:

$ node scripts/verify-stdio.mjs
initialize -> mcp-devdb 0.1.0 (protocol 2025-06-18)
tools/list -> db_overview, describe_table, explain_query, list_tables, run_query, sample_rows
tools/call list_tables ->
{
  "database": "demo",
  "dialect": "sqlite",
  "tableCount": 2,
  "tables": [
    {
      "schema": null,
      "name": "orders",
      "type": "table",
      "rowEstimate": 3,
      "sizeBytes": 4096,
      "sizePretty": "4.0 KiB"
    },
    {
      "schema": null,
      "name": "users",
      "type": "table",
      "rowEstimate": 2,
      "sizeBytes": 4096,
      "sizePretty": "4.0 KiB"
    }
  ]
}
tools/call run_query "DROP TABLE users" -> isError=true
  Query rejected by read-only guard: Only read-only statements are allowed; the statement must start with one of: SELECT, WITH, EXPLAIN, SHOW, VALUES
SMOKE TEST PASSED

Limitations

  • No MySQL yet. The DbAdapter interface in src/adapters/types.ts is the extension point.

  • Dev databases only. The guard blocks SQL-level writes, but a SELECT can still invoke badly-labeled or extension functions with side effects (e.g. dblink opening its own non-read-only connection). Accepted for development databases; never point this at production. See SECURITY.md.

  • The guard is conservative: unquoted columns named like forbidden keywords (e.g. a column literally named update) are rejected — quote them ("update") to proceed.

  • SELECT ... FOR UPDATE is rejected (it takes row locks).

  • SQLite row counts use COUNT(*); on huge files list_tables can be slow.

Development

npm install
npm run lint && npm run typecheck && npm test && npm run build
node scripts/verify-stdio.mjs

License

MIT — Copyright (c) 2026 Aminyx

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    C
    maintenance
    A lightweight Postgres MCP server for safe database exploration and query analysis, read-only by default, with multi-database support.
    4
    4
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A read-only MCP server for PostgreSQL that enables safe database introspection and querying via natural language.
    300
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Read-only MCP server for SQL databases (SQLite/PostgreSQL) that enables listing tables, describing schemas, and executing SELECT queries with safety guardrails.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides a read-only PostgreSQL MCP server with schema introspection. Enforces least-privilege database roles to prevent any writes, even from malicious SQL.
    MIT