MCP Server
turbine mcp starts a Model Context Protocol server that lets an AI agent, Claude Code, Cursor, or any MCP client, inspect your database safely. It speaks JSON-RPC 2.0 over stdio, ships with the package (no extra dependency), and exposes read-only tools only. There is no write surface and no free-form SQL input: the same safety stance as Studio.
DATABASE_URL=postgres://user:pass@localhost:5432/mydb npx turbine mcpThe server handles the MCP initialize handshake (protocol version 2025-06-18, server name turbine-orm), then serves tools/list and tools/call. Malformed input returns a JSON-RPC error and never crashes the process.
The tools#
Six read-only tools. Every database access runs inside a BEGIN READ ONLY transaction with a statement timeout, an agent physically cannot mutate your data through them.
| Tool | What it returns |
|---|---|
schema_overview | Tables, columns, relations, indexes, and estimated row counts for the schema. |
table_detail | Columns, indexes, and relations for one named table. |
migrate_status | Migration files and the tracking table, applied vs pending, without applying anything. |
doctor_report | Missing relation indexes, from the same index advisor turbine doctor uses. |
explain_query | EXPLAIN (FORMAT JSON) for a schema-validated findMany plan (see below). |
sample_rows | Up to 50 rows from a table whose name is validated against the introspected schema. PII-tagged columns come back redacted. |
explain_query never accepts free-form SQL. You pass a subset of Studio’s builder args (table + optional where / orderBy / limit / select, not with / omit). Turbine validates identifiers against the introspected schema, builds parameterized SQL via QueryInterface.buildFindMany, then runs EXPLAIN (FORMAT JSON) on that SQL with bound params only.
| Argument | Required | Description |
|---|---|---|
table | yes | Table name; must exist in the live schema. |
where | no | findMany-style where clause (field names validated). |
orderBy | no | findMany-style orderBy (object or array). |
limit | no | Positive integer row limit for the planned query. |
select | no | Field selection map ({ field: true }). |
sample_rows caps at 50 rows, validates the table name against the live schema, and redacts PII-tagged columns before the rows reach the agent's context (the response lists which columns were redacted). Tags are a code-first declaration that introspection never infers, so the server reads them from the generated metadata in your out directory: with no generated metadata there is nothing to redact, and rows come back whole. Together, an agent can explore query plans and real data without a path to writing or to arbitrary SQL.
Options#
| Option | Description |
|---|---|
--url, -u <url> | Postgres connection string. Overrides DATABASE_URL. |
--schema, -s <name> | Postgres schema (default: public). |
--include <tables> | Comma-separated tables to include. |
--exclude <tables> | Comma-separated tables to exclude. |
Connect it to Claude Code#
Add the server to your project's .mcp.json:
{
"mcpServers": {
"turbine": {
"command": "npx",
"args": ["turbine", "mcp"],
"env": { "DATABASE_URL": "postgres://user:pass@localhost:5432/mydb" }
}
}
}Claude Code launches npx turbine mcp on startup and can then answer questions like "what indexes is the orders table missing?" or "show me a few rows from users", grounded in your real schema.
Connect it to Cursor#
Cursor uses the same shape in .cursor/mcp.json:
{
"mcpServers": {
"turbine": {
"command": "npx",
"args": ["turbine", "mcp"],
"env": { "DATABASE_URL": "postgres://user:pass@localhost:5432/mydb" }
}
}
}See also#
- Studio, the same read-only stance, as a web UI for humans.
- CLI,
turbine doctorandmigrate statuson the command line. - Schema & Migrations, what the schema tools introspect.