DEV Community

Cover image for We Gave Claude Code Access to Our Production Database. Here's How It Doesn't Go Wrong.
Muhammad Awais
Muhammad Awais

Posted on

We Gave Claude Code Access to Our Production Database. Here's How It Doesn't Go Wrong.

We Gave Claude Code Access to Our Production Database. Here's How It Doesn't Go Wrong.

Every team building with AI agents eventually hits the same wall: the agent needs to query a real database to be useful, and every way of doing that looks bad. A DATABASE_URL in the agent's config is a credential sitting on a laptop. A shared read replica with a shared login means "who ran that query" is unanswerable. And a hand-rolled MCP wrapper around your DB driver is a security review waiting to happen. We built db-mcp-gateway to make that a solved problem instead of a judgment call. It's a self-hosted, MIT-licensed gateway, written in Rust,that sits between your AI agents and your databases. The agent never holds a credential not once, not cached, not in a log line.

The one-minute model

Deploy the gateway once. Developers add one URL to their MCP config:

claude mcp add --transport http db-gateway --scope project https://db.internal.acme.com
Enter fullscreen mode Exit fullscreen mode

That's the entire client-side setup. First call to any gateway tool returns
401, the agent surfaces an SSO login link, you authenticate through your
org's actual identity provider (Okta, Google Workspace, Entra, Authentik,
Keycloak), and the token lands in your system keychain — never in a config
file, never in the agent's context.

┌─────────┐    MCP/HTTPS    ┌──────────────┐    pg wire    ┌──────────┐
│ agent   │ ──────────────▶ │   gateway    │ ────────────▶ │ target   │
│ (Claude │   bearer: jwt   │              │  ro role per  │  DBs     │
│  Code)  │ ◀────────────── │  authz+audit │ ◀──────────── │          │
└─────────┘   tool result   └──────┬───────┘   result rows └──────────┘
                                   │
                                   ▼
                            ┌──────────────┐
                            │ state DB     │
                            │ (sessions +  │
                            │  audit log)  │
                            └──────────────┘
Enter fullscreen mode Exit fullscreen mode

Permissions are YAML, reviewed by PR not a UI

There's deliberately no admin UI. Access lives in a config file your team
reviews the same way you review any other production change:

permissions:
  - group: data-analysts        # matches an SSO group from the IdP claim
    grants:
      - server: prod
        database: "*"
        action: query_read      # SELECT + schema reads, never writes
        constraints:
          require_reason: true  # agent must justify the query → audit log
          row_limit: 1000       # gateway truncates beyond this
          statement_timeout_ms: 5000
Enter fullscreen mode Exit fullscreen mode

Actions are hierarchical (query_writequery_readschema_read), and
when multiple grants match, the most restrictive constraint wins. Writes are
opt-in per grant and, even then, capped hard: a query_write grant permits
a single INSERT/UPDATE/DELETE per call, through the same timeout and
row-cap path as a read. CREATE, ALTER, DROP, TRUNCATE, GRANT,
REVOKE, and multi-statement bodies are rejected with forbidden_sql
always, regardless of grant. The gateway never issues DDL, full stop.

What the agent actually sees

You:    What databases can I see through db-gateway?

Claude: [calls list_servers → list_databases]

        You have access to:
        • staging (postgres) — staging/app, staging/billing
        • prod (postgres)    — prod/billing (read-only, reason required)

You:    How many users signed up in staging/app over the last 7 days?

Claude: [calls run_query staging/app]
          select count(*) from users where created_at > now() - interval '7 days';

        → 412 (returned in 38ms)
Enter fullscreen mode Exit fullscreen mode

Cross a boundary and the failure is explicit, not silent: forbidden if
your group's grant doesn't cover it, timeout if the query exceeds
statement_timeout_ms, row_limit_exceeded/truncated: true if the result
is bigger than the grant allows, or a reason_required prompt if the grant
demands one — typically anything touching prod. The agent asks you for the
reason and it lands verbatim in the audit row. "checking stuff" versus
"verifying SUPPORT-4421 root cause" is the difference between an audit log
that's useless in six months and one that isn't.

Every run_query call writes that audit row user, SQL, reason, row
count, duration, outcome — before the result comes back to the agent, not
after. Hot retention lives in Postgres; there's an optional archive sink to
S3/GCS/Azure and streaming export via OTLP/syslog/stdout for teams who
already have a SIEM.

The stack, if you're curious

Rust, tokio for async, axum for HTTP, sqlx for the DB layer, config in
YAML validated at boot with line:column error pointers on typos. The
gateway also speaks the MCP Authorization spec (OAuth 2.1 + PKCE) itself —
it is the authorization server, brokering your IdP login internally, so
Claude Code and other MCP clients authenticate with zero manual credential
wiring on the client side.

What's not done yet

In the interest of not doing the thing every "launch" post does: this is a
young project (first commit May 2026) and a few pieces referenced in the
docs aren't real yet. There's no Helm chart docker-compose or hand-rolled
k8s manifests today. vault:/aws-sm:/gcp-sm: secret backends are
recognized in config but rejected at boot until they land; use ${ENV:...}
or ${FILE:...} refs for now. Session revocation is a manual psql insert
into a denylist table until the planned gateway admin CLI ships. None of
that blocks running it in production we do but it's not the finished
enterprise product yet, and I'd rather say that here than have someone find
out from the roadmap doc after trying it.

Why this exists

db-mcp-gateway is built and maintained largely by AI agents at
developerz.ai, under human review, with every change going through CI
before merge. It's also, not coincidentally, a small working demo of the
same idea developerz.ai sells as a product: agents should never hold raw
credentials, and every action they take should be attributable and
auditable. The gateway is the free, self-hosted version of that philosophy.

docker pull ghcr.io/developerz-ai/db-mcp-gateway:1.1.1
Enter fullscreen mode Exit fullscreen mode

MIT-licensed. Repo, docs, and the full permissions reference are at
github.com/developerz-ai/db-mcp-gateway.

Top comments (0)