Schema introspection for MCP: why your AI agent needs more than SQL
Raw SQL access gives AI agents a firehose. Schema introspection gives them a map. Here's why the difference matters for MCP servers.
- mcp
- schema
- database
- introspection
Most MCP database servers do one thing: let an AI agent run SQL. That’s useful. Connect Claude or Cursor to Postgres, ask a question, get rows back.
The problem is what happens between the question and the query. The agent has to guess.
It guesses column names. It guesses join paths. It doesn’t know whether orders.customer_id points to customers.id or accounts.customer_ref. It can’t tell which tables are related, which are stale, or what a schema change two weeks ago broke. These aren’t edge cases — they’re the default state of every warehouse that’s been running for more than a quarter.
Schema introspection — building a structural model of the database before the agent writes its first query — changes the dynamic. The agent goes from guessing to knowing. This is the thing Pretensor does that most MCP database tools don’t.
The problem with raw SQL access
When you wire up an MCP server that exposes a SQL execution tool, here’s what actually happens:
- The agent asks the human what tables exist.
- The human pastes DDL, or the agent queries
information_schema. - The agent holds the DDL in its context window and tries to reason about relationships.
- It writes a query. If it gets the join wrong, the human corrects it.
- Next session, repeat from step 1.
This works for small schemas. It breaks down at scale, and it breaks down silently. The agent doesn’t know it’s wrong — it just produces incorrect answers with the same confidence as correct ones.
Three specific failure modes:
Implicit relationships. Foreign keys are explicit, but most real schemas have implicit joins: columns named user_id that aren’t formally constrained, tables that share domain prefixes, columns that reference an external system. Raw information_schema won’t surface these. The agent has to guess.
Undiscoverable join paths. Given tables users and invoices, is there a path from one to the other? Through which intermediate tables? With information_schema alone, the agent can answer this only by iterating — asking the human, checking column names, trying joins. It’s mechanical discovery work that should be precomputed once, not repeated per-session.
No semantic labels. information_schema tells you a table is called fact_sales_2023 but not that it’s a fact table, or that it’s part of a sales domain cluster, or that it’s stale (no new rows since 2023). Without classification, every table looks equally important — which means no table is prioritized.
What a schema graph gives you
Pretensor doesn’t just dump information_schema into a chat. It builds a Kuzu graph — tables as nodes, columns as properties, foreign keys as edges, plus several layers the raw database doesn’t expose:
| Layer | What it captures | How it helps the agent |
|---|---|---|
| Table classification | Fact vs. dimension vs. bridge vs. reference | Prioritizes which tables matter for a question |
| Inferred joins | Columns that look like FKs but aren’t formally constrained | Discovers implicit relationships |
| Join-path precomputation | Shortest paths between any two tables, including cross-database | Answers “how do I get from A to B?” in one query |
| Community clustering | Louvain groups of related tables | Groups tables into domains (sales, billing, users) |
| Staleness tracking | Last indexed snapshot vs. live schema | Detects what changed since the agent’s last context refresh |
This isn’t DDL copy-paste with better formatting. It’s a precomputed structural index that the agent queries before writing its first SQL. The agent says “give me context for orders” and gets back columns, relationships, join paths, cluster membership, and lineage — not just column name and type.
How Pretensor works (the 3-step flow)
pretensor index postgresql://user:pass@host:5432/dbnamepretensor serveStep 1: Index. The index command connects to your database (Postgres, Snowflake, or BigQuery), reads information_schema plus additional metadata, and writes a Kuzu graph to .pretensor/. This step is deterministic — no LLM involved. The classification system, join inference, and clustering run in vanilla Python on the local machine. Your schema never leaves your network.
Step 2: Graph. The graph lives on disk as a Kuzu database. It persists between sessions, so the agent doesn’t re-discover your schema every time. Run pretensor reindex to refresh when the schema changes. Run pretensor detect_changes to compare the indexed snapshot against the live database without the agent guessing what moved.
Step 3: MCP tools. pretensor serve starts an MCP server that exposes 12 tools to Claude, Cursor, Windsurf — any MCP client. The agent can search tables by keyword, inspect schema structure, traverse join paths, check impact, and detect changes. It can also run read-only Cypher queries against the graph for ad-hoc exploration.
Why determinism matters
One point worth dwelling on: the introspection layer has zero LLM dependency.
The table classifier is a Python module that looks at column names, types, and row counts. The join inference uses column-name heuristics and type matching. Community detection runs Louvain, a deterministic graph algorithm.
This matters because LLM-based schema analysis — “here’s my DDL, tell me what I have” — produces different answers across sessions. The same schema analyzed twice can produce different classifications, different join suggestions, different priority rankings. For impact analysis (“what breaks if I rename this column?”), non-deterministic answers are worse than no answer.
Pretensor’s graph is reproducible. Index the same database twice, get the same graph. The agent can rely on it.
What this enables
Once the agent has a schema graph, the interaction changes:
Instead of “what tables do we have?” → the agent uses list_databases + schema to discover the graph structure on its own. The human never pastes DDL.
Instead of “how do I join sales to customers?” → the agent calls traverse to find join paths. No guessing, no manual correction cycle.
Instead of “did anyone change the schema?” → the agent calls detect_changes before writing queries. If the schema moved, the agent knows before it breaks.
Instead of “which tables are related?” → the agent uses context to see cluster membership and relationship edges for any table.
This is the shift from “AI assistant with database access” to “AI agent with database understanding.” The tools are the same (MCP), the protocol is the same (JSON-RPC), but the agent’s model of your data goes from flat column lists to a traversable graph.
Getting started
pip install pretensorpretensor index postgresql://user:pass@host:5432/dbnamepretensor serve --config-only # prints mcpServers JSON for Claude / CursorMerge the output into your MCP config, restart your editor, and the tools appear. No API keys, no cloud dependency, no schema exfiltration. The graph lives next to your code.
Read the full quickstart for details on Snowflake/BigQuery setup, CLI options, and graph visualization.
Further reading: MCP tools reference, architecture pipeline, schema graph documentation.