Install
$ agentstack add mcp-arun-kc-schemabrain ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.6.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
About
Stop giving AI agents raw database connection strings.
Give them SchemaBrain instead — a read-only trust and intelligence layer where the agent never writes SQL, PII is refused before the query runs, and every call lands in a tamper-evident audit log.
Works with Claude Desktop · Claude Code · Cursor · Windsurf · any MCP host
SchemaBrain compiles every query from definitions you control — no path from a prompt to raw SQL at your database.
Three guarantees that close the trust gap between AI agents and your database:
- [Read-only by architecture](#1-read-only-by-architecture-not-configuration) — twelve MCP tools, none of which can write. No
execute()tool, noquery()tool, no path from agent prompt to a write at your database. - [PII-aware refusal at retrieval](#2-pii-aware-refusal-at-the-get_metric-tool-boundary) — PII tags propagate from the physical schema through joins and metrics. If a query touches a blocked category, SchemaBrain refuses before the database is queried.
- [Cryptographic audit chain](#3-tamper-evident-audit-log) — every call, refusal, and recovery is recorded in a SHA256-hashed append-only log (best-effort: a disk-full or no-writer configuration logs a warning and continues rather than failing the query).
audit verifyexits non-zero if any past row was rewritten.
See it in action — ask for something the schema can't answer, and it refuses instead of fabricating a join:
> You: compute usage volume by plan tier > > SchemaBrain → agent: { "kind": "unreachable_entity", "recovery": { "suggested_tool": "resolve_join" } } — there's no plan_id on usage events, so it won't invent one. > > Claude: I can't fake that join — here's contracted revenue by plan tier instead, which actually resolves. ✓
→ [Full session, with the SQL and results](#sample-session)
Watch it run — a live Postgres schema becomes a governed knowledge graph, the firewall computes the safe metric and refuses the leaks, and every call lands in a tamper-evident audit log. No agent, no API key:
uvx schemabrain init
# then: Cmd+Q Claude Desktop, relaunch, and ask: "list the entities SchemaBrain knows about"
# prefer a persistent install? pipx install schemabrain (or) pip install schemabrain
Cost: $0 to run the bundled demo (pre-curated pack, no API key) · ~$0.03 to LLM-index a fresh 84-column schema · $0 to re-index unchanged schemas. Detail in [Sample session](#sample-session).
Status: 0.6.0 (beta). Postgres supported today (the local store itself is SQLite). SQLite / Snowflake / BigQuery / MySQL source connectors on the roadmap.
Contents
Read next based on what you need:
| Goal | Where to go | |---|---| | Try it on the bundled fixture | [Quickstart](#quickstart) | | Understand the safety guarantees | [Safety guarantees](#safety-guarantees) | | Wire up your MCP client | [Claude Desktop](docs/setup/claude-desktop.md) · [Claude Code](docs/setup/claude-code.md) · [Cursor](docs/setup/cursor.md) · [Windsurf](docs/setup/windsurf.md) · [Cline](docs/setup/cline.md) · [ChatGPT (roadmap)](docs/setup/chatgpt.md) | | Plug into your own agent loop | [docs/setup/manual.md](docs/setup/manual.md#3-wire-your-own-agent-anthropic-sdk) | | Build a semantic layer | [docs/semantic-layer.md](docs/semantic-layer.md) | | Run in production (audit, drift, Docker) | [docs/operations.md](docs/operations.md) | | Observe the agent (tail, audit log, OTel) | [docs/observability.md](docs/observability.md) | | Compare with Querybear / Anthropic reference Postgres MCP | [vs Querybear](docs/compare/querybear.mdx) · [vs Anthropic reference](docs/compare/anthropic-postgres-mcp.mdx) | | Compare with Vanna / Atlan / dbt-mcp / WrenAI | [docs/landscape.md](docs/landscape.md) |
Quickstart
> Just want to see what it does? uvx schemabrain demo — one command, zero prompts. Builds the sample SaaS layer, then lets you open the dashboard or run a terminal firewall showcase. No API key, and no Docker for the dashboard / showcase paths. The steps below are for wiring SchemaBrain into your own agent against your own database.
Three steps from uvx schemabrain init to a working Claude Desktop integration. If you paste your own Postgres URL — no Docker needed, ~30s. Press Enter for the bundled demo and init invokes Docker + downloads a ~67 MB embedding model first time; ~45s once cached.
1. Install
uvx schemabrain init # zero-install: runs the wizard in one shot
# or install persistently first:
pipx install schemabrain # (or) pip install schemabrain
schemabrain --version
Source install (git clone + uv sync --extra dev) is documented in [docs/setup.md](docs/setup.md#1-install--run-the-wizard).
2. Run the activation wizard
schemabrain init
init is a seven-stage wizard that takes you from "I have a Postgres database" to "Claude Desktop can answer questions about it" in one command. On first run it prompts for what it needs:
- A Postgres URL — paste your own connection string, or press Enter to spin up a local demo Postgres container with the bundled SaaS fixture (Docker is invoked automatically; idempotent on re-runs).
- An
ANTHROPIC_API_KEY— optional. Skip and the wizard still wires Claude Desktop. On the demo path, entities + metrics + joins are pre-curated from a bundled YAML pack — the semantic layer works zero-config. On your own database, entity curation can run later viaschemabrain entities suggest --applyonce you have a key.
SchemaBrain init — activation wizard
[1/7] Source check ✓ source reachable + read-only
[2/7] Index schema ✓ 12 tables, 84 columns indexed
[3/7] Curate entities ✓ 12 entities applied (bundled demo pack)
[4/7] Curate metrics ✓ 5 metrics applied (bundled demo pack)
[5/7] Curate joins ✓ 11 canonical joins applied (bundled demo pack)
[6/7] Wire host ✓ wrote schemabrain entry to claude_desktop_config.json
(default; switch with --host claude-code|cursor|windsurf|manual)
[7/7] Next ✓ restart your MCP host, then ask: "list the entities SchemaBrain knows about"
Full wizard reference (stages explained, flags, dbt auto-detection, --print-only for non-Claude-Desktop hosts, --no-entities / --no-metrics / --no-joins opt-outs, cost-cap pauses): [docs/setup.md](docs/setup.md#2-what-the-wizard-does).
3. Restart Claude Desktop and ask
- Quit Claude Desktop fully — Cmd+Q, not just close the window. The MCP config is only read on cold start.
- Relaunch.
- New conversation:
> list the entities SchemaBrain knows about
If Claude calls list_entities and reports user, order, etc., you're done. If not, see [Troubleshooting](#troubleshooting).
After the wizard, schemabrain inspect shows what the agent has and schemabrain tail streams every tool call live — see [docs/operations.md](docs/operations.md).
Your project files
init writes just ./schemabrain.db (the local store — gitignore it) plus your host config. To tune the PII policy and semantic layer as editable YAML, re-run with --emit-yaml-dir:
schemabrain init --url-env DATABASE_URL --emit-yaml-dir ./schemabrain
# → ./schemabrain/pii_policy.yaml + entities/ + metrics/ + joins/
Edit a file, schemabrain apply ./schemabrain, schemabrain check to validate, restart serve. There is no schemabrain.yaml — config is CLI flags + SCHEMABRAIN_* env vars (auto-loaded from .env) + that YAML tree. Full map: [Your project](docs/your-project.md).
Safety guarantees
Six properties SchemaBrain enforces at the SQL boundary today:
1. Read-only by architecture, not configuration
The MCP surface exposes twelve tools — none of which can write. No execute(), no query(), no path from agent prompt to a write at your database, regardless of session state — the guarantee is structural, not a flag the agent can flip. schemabrain serve also pins default_transaction_read_only=on as belt-and-suspenders. [Read-only by architecture →](docs/mechanism/read-only.mdx)
2. PII-aware refusal at the get_metric tool boundary
Any get_metric touching a blocked PII category returns a refused envelope — the compiled SQL never runs and the refusal lands in mcp_audit. describe_entity enforces the same at the column level (blocked columns ship redacted=True). init blocks the catastrophic-leak set by default (credential,payment_card,government_id); --pii-block replaces the set, so widen by listing the full target. Detection is column-name pattern matching across twelve GDPR / CCPA / HIPAA / PCI categories; content-aware classification is on the roadmap. [PII taxonomy & propagation →](docs/mechanism/pii-taxonomy.mdx)
3. Tamper-evident audit log
Every tool call writes one row to an append-only mcp_audit table — PII categories, content-addressable fingerprints, sha256 hash chain. audit verify re-walks the chain and exits non-zero if any past row was rewritten.
schemabrain audit verify # exit 0 = chain clean
[Tamper-evident audit chain →](docs/mechanism/audit-chain.mdx)
4. Failure is a contract, not a string
Every non-success call — refused, error, or degraded — returns a structured recovery.suggested_args block, not a message to parse. PII blocks (status: "refused") ship the entity to retry; ambiguous dimensions and unreachable entities (status: "error") ship the candidate to pick or the next tool to call. Only policy refusals are refused; "I won't guess" is error with a recovery payload.
{ "status": "error", "kind": "ambiguous_time_dimension",
"recovery": { "suggested_tool": "get_metric",
"suggested_args": {"time_dimension": "order.placed_at"} } }
[Structured recovery →](docs/mechanism/structured-recovery.mdx)
5. Compile path: definitions → parameterized SQL
Entities, metrics, and canonical joins compile to parameterized SQL SchemaBrain runs on its side. The agent sees rows + the SQL that ran — never arbitrary statements at your database. LLM-suggested definitions during init are reviewed and applied explicitly. [Build your semantic layer →](docs/semantic-layer.md)
6. Pluggable into any agent loop
The same MCP stdio surface Claude Desktop sees is exposed to any MCP host — your own Anthropic, OpenAI, or LangGraph loop included. [examples/anthropic_demo.py](examples/anthropic_demo.py) is a ~260-LOC drop-in that wires Claude Haiku 4.5 to schemabrain serve and prints exactly which tools the agent chose. [Anthropic SDK walkthrough →](docs/setup/manual.md#3-wire-your-own-agent-anthropic-sdk)
Observability dashboard
SchemaBrain ships an opt-in, read-only dashboard over the same audit + PII + refusal data the MCP server is already writing. schemabrain dashboard boots a local FastAPI sidecar serving a pre-built static UI — no Node runtime, no network exposure, no write paths.
pip install "schemabrain[ui]"
schemabrain dashboard
# → http://127.0.0.1:7878
It's a viewer, not a console — no settings, no SQL pad, no write path. Nine read-only surfaces, each answering an operator question the MCP envelope alone never surfaces visually. The signature surface is the Knowledge Graph — your schema rendered as the same entity-relationship projection the semantic layer compiles joins against:
- Knowledge Graph (
/graph) — how does my schema actually connect? Entities as nodes, canonical joins as edges (solid for declared FKs, dashed for log-mined), PII-bearing entities flagged, and refusal hotspots highlighted, with declared-FK cardinality shown on the highlighted join path — the schema as a graph, not a table list. - Overview (
/overview) — the home surface: entity / metric / join / catastrophic-PII counts at a glance. - Entities (
/entities) — a sortable index; drill into any entity's columns, PII, metrics, and canonical joins. - Data Dictionary (
/dict) — every table, column, type, PII class, join, and metric, with one-click Markdown export (the same artifactschemabrain docswrites). - PII matrix (
/pii) — which columns carry sensitive data? A heatmap with one row per classified column and one cell per PII category, each column tagged block / redact / allow by its advisory band. Columns in a catastrophic-leak category (credential,payment_card,government_id) are hard-blocked regardless of policy and pinned to the top — so you catch apayment_cardcolumn hiding insideusersbefore you point an agent at a new schema, and see at a glance what trips the default--pii-blockpolicy. Select any row to drill into its entity's columns, metrics, and joins. - Refusals (
/refusals) — what did SchemaBrain block, and what did the agent see? A chronological feed of held calls; expand any row to reveal the full envelope inline — the reason that fired (pii_blocked,allowlist_violation,fragment_unsafe,cost_cap_exceeded,ambiguous_resolution,schema_drift), the exact category set that intersected the policy, and the structurederror.recovery(suggested tool + args) the agent got back to recover. Use it to triage "the agent says it can't access that" and to review whether those hints actually helped. - Audit Viewer (
/audit) — is the audit chain still intact? The visual face of the tamper-evident log: every tool call writes exactly one row — whatever the outcome — anchored bychain_hash = sha256(prev_hash || canonical(row)). An integrity strip readsnot verified this sessionuntil you run a pass, thenverified · n/N intact(or flagsN rows edited after write); the Verify button re-walks the chain server-side and recomputes each visible row's RFC-6962 Merkle inclusion proof in your browser. Selecting a row opens the full body (tool, status, cost class, PII categories, fingerprint,chain_hash, and the proof ladder up to the root). Reload to pick up new calls. - Policy (
/policy) — the block / redact / allow grid the firewall enforces, with the always-on catastrophic-leak floor disclosed (it can't be removed). Changes are made via copy-the-CLI actions — the dashboard never writes. - Drift (
/drift) — config and enrichment drift the store can detect, each with a copy-the-CLI fix.
Knowledge Graph — your schema as the entity-relationship projection the semantic layer compiles joins against; catastrophic-PII entities flagged, the canonical join path traced.
More dashboard views — Overview, PII matrix, Refusals, Audit, Entities, Data Dictionary, Policy & Drift
Overview — the whole boundary on one screen: what's bound, what's protected, what's drifted.
PII matrix — which columns carry sensitive data, and what the default policy blocks.
Refusals — every blocked call, the reason that fired, and the recovery hint the agent received.
Audit Viewer — the tamper-evident chain, verified server-side down to each row's hash linkage.
Entities — every business entity bound out of the raw schema, with PII exposure and join counts.
Data Dictionary — every table, column, type, and join, exportable to Markdown for your repo or wiki.
Policy — the block / redact / allow grid the firewall enforces, with the always-on floor disclosed.
Drift — config and enrichment drift the store can detect, each with a copy-the-CLI fix.
The dashboard binds 127.0.0.1 only — there is no --host flag, by design. It's read-only and reads the same SQLite store serve writes to. No agent talks to it.
[Dashboard guide →](docs/dashboard/overview.mdx) · [PII matrix →](docs/dashboard/pii-matrix.mdx) · [Refusals →](docs/dashboard/refusals.mdx) · [Audit Viewer →](docs/dashboard/audit-viewer.mdx)
Works with
SchemaBrain speaks the [
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Arun-kc
- Source: Arun-kc/schemabrain
- License: Apache-2.0
- Homepage: https://www.schemabrain.dev
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.6.0 Imported from the upstream source.