Skip to content

MCP server

PerSQL hosts a Model Context Protocol server at https://mcp.persql.com. Any MCP-aware runtime (Claude Desktop, Cursor, Cline, Continue, OpenAI Agents SDK, …) can be pointed at it with a single config block. The agent gets typed SQL tools immediately — no SDK install, no per-runtime adapter.

OAuth-capable runtimes negotiate access automatically — the URL alone is enough. Older runtimes pass a psql_live_… bearer header; the same token authenticates against the /v1 REST API.

StackURL
Productionhttps://mcp.persql.com
Staginghttps://mcp-staging.persql.com

Transport: streamable-HTTP MCP (JSON-RPC 2.0 over HTTPS POST). Stateless — each tool call is independent, no Mcp-Session-Id required.

Two paths, picked automatically by the runtime:

  1. OAuth 2.1 with PKCE + dynamic client registration (MCP authorization spec). On a 401, the server returns WWW-Authenticate: Bearer resource_metadata=…. The runtime fetches the metadata at /.well-known/oauth-protected-resource, registers a public client at /oauth/register, opens the browser to console.persql.com/oauth-consent, you pick a namespace, the runtime stores the issued token. No copy-paste step.
  2. Static bearer token as fallback for runtimes without OAuth support (Authorization: Bearer psql_live_…). Mint one under console.persql.com → API tokens.

One command, no file editing:

Terminal window
claude mcp add persql --transport http https://mcp.persql.com

The server registers in the current Claude Code session immediately. Use claude mcp list to verify and claude mcp remove persql to undo.

If your Claude Code build doesn’t speak MCP OAuth, append a bearer header:

Terminal window
claude mcp add persql \
--transport http https://mcp.persql.com \
--header "Authorization: Bearer psql_live_…"

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
"mcpServers": {
"persql": {
"url": "https://mcp.persql.com"
}
}
}

Restart Claude Desktop. The first tool call opens the browser to the PerSQL consent screen; pick a namespace and you’re in. Tools appear under the 🔌 plug icon.

Bearer fallback:

{
"mcpServers": {
"persql": {
"url": "https://mcp.persql.com",
"headers": { "Authorization": "Bearer psql_live_…" }
}
}
}

Edit ~/.cursor/mcp.json (global) or .cursor/mcp.json (per-project):

{
"mcpServers": {
"persql": {
"url": "https://mcp.persql.com"
}
}
}

Same fallback shape with a headers block if needed.

Any MCP runtime that speaks streamable-HTTP works. URL alone if it supports OAuth; URL + bearer header if not. Cline, Continue, Sourcegraph Cody, Codeium — the config block is the same.

All tools are scoped to the namespace your token (or OAuth grant) belongs to.

  • query(database, sql, params?) — single statement, ? placeholders, returns { rows, rowsRead, rowsWritten }.
  • batch(database, statements, transaction?) — up to 100 statements; set transaction: true to wrap in a transaction.
  • wait_for_changes(database, since?, waitMs?, tables?) — long-poll the change feed. Returns immediately if there’s already new activity, otherwise blocks up to 25s. Use this instead of polling.
  • validate_sql(database, sql, params?) — parse + bind-check without executing. Cheaper than running the query just to find a typo.
  • list_databases — slug, name, status for every database in the namespace.
  • describe_database(database) — one-call descriptor: every table’s columns, foreign keys, and stored semantic descriptions. The first call to make on a fresh database.
  • list_tables, describe_table, sample_table — the per-table variants when you don’t want the full graph.
  • search_schema(database, query, limit?) — natural-language ranked search across table + column names and stored descriptions.
  • schema_doctor(database) — lints the schema; flags missing primary keys, unindexed foreign keys, ambiguous columns. Read-only.
  • set_database_doc, set_table_doc, set_column_doc, get_docs — write and read the namespace’s stored schema descriptions.
  • ask(database, question) — NL→SQL with a budget cap.
  • claim_branch(database, ref, ttlSec?, role?) — one-shot lease that creates or resets a branch and mints a scoped token. Per-agent-run sandboxes.
  • propose_mutation / apply_mutation — pre-flight a write, inspect the rowcount, redeem with a single-use token.
  • pin_branch(database, branchRef, role, ttlSec?) — mint a single-use handoff token (phand_…) for a sub-agent.
  • claim_handoff(token, name?) — sub-agent side; redeems a phand_… for a regular bearer token scoped to one (database, branch, role).
  • query_log(database, ...) / recent_actions(database, ...) — replay what changed. Also exposed inside the DB as _persql_meta_query_log so an agent can JOIN against its own audit.
  • create_database({ name, slug, region?, ttlDays? }) — spin a new SQLite database in the namespace. ttlDays (1–30) creates a self-deleting DB — useful when you want a sandbox without managing cleanup. Requires an unscoped admin-role token.
  • list_schedules(database) / create_schedule({ database, name, sql, intervalSec, enabled? }) / delete_schedule({ database, scheduleId }) — register cron SQL inside the database’s Durable Object. Useful for periodic maintenance an agent wants to leave running unattended — TTL cleanup, derived- table refresh, agent inbox sweep.
  • list_webhooks(database) / create_webhook({ database, name, url, tables?, events?, enabled? }) / delete_webhook({ database, webhookId }) — register an outbound HMAC-signed webhook. When matching rows change, the DO POSTs JSON to url. Use this to react to writes from outside the runtime — notify a sub-agent, kick off a deploy, page a human.
  • whoami — namespace, role, scopes, plus live spend counters: balanceUsdMicros, graceFloorUsdMicros, and unbilledUsdMicros (debited since the last hourly flush). Self-throttle on these before the gate returns 402.
  • topup_balance({ amountUsd, returnUrl? }) — mint a Stripe Checkout URL to fund the namespace. Requires an unscoped admin-role token. Returns { url, amountUsd, sessionId, expiresAt }. Under an MPP-capable runtime (Stripe Machine Payments Protocol, x402) the runtime can drive Checkout end-to-end; otherwise hand the URL to a human.

Endpoints, branches, snapshots, migrations, saved queries

Section titled “Endpoints, branches, snapshots, migrations, saved queries”

The rest of the surface mirrors the console: list_branches, create_branch, delete_branch, merge_branch, preview_branch_merge, branch_diff, list_snapshots, create_snapshot, restore_snapshot, restore_to_time, list_endpoints, create_endpoint, publish_endpoint, discover_endpoints, endpoint_logs, list_migrations, create_migration, apply_migration, rollback_migration, list_saved_queries, save_query, run_saved_query. Roughly sixty tools total — list them at runtime via your MCP client’s tools panel.

Every query and batch invocation through MCP records the same query event in PerSQL’s analytics dataset as the /v1 REST path. Customer usage dashboards aggregate both surfaces — there’s no separate “MCP usage” view.

ask additionally records an ai_call event with the model used and the tokens consumed — the same event used to bill the AI-tokens meter.

MCP shares the same model as /v1: the prepaid namespace balance is the only spend control. A token spends as fast as you call it until the balance returns 402. The 402 response carries an x402-compatible body (x402Version, accepts[]) so MPP-capable runtimes can complete a top-up programmatically; non-MPP runtimes use topup_balance to mint a Checkout URL.

If you want a tighter blast-radius for a single key, mint a separate namespace with its own balance and scope the token to it.

AI-powered tools (ask) also drain the balance via the AI-tokens meter — see Pricing for the rate.

Idempotency keys for safe retry are not yet exposed via MCP — use the SDK or raw HTTP if you need them.