QueryDeck Docs
MCP Server

MCP safety

Read-only by default, row limits, query timeouts, and how to relax them when you really need to.

For: developers who care about what an AI can and can't do with their database.

The MCP server is conservative by default. This page documents every safety rule, what it blocks, and how to change it.

Defaults at a glance

SettingDefaultWhat it controls
enabledtrueThe MCP server itself. If false, all tools return "MCP disabled".
allowWritesfalseWhen false, write keywords in any query are blocked.
maxRowLimit1000Cap on rows returned by execute_query and explain_query (with analyze: true).
queryTimeoutSeconds30Server-side timeout. Queries that take longer are cancelled.

You'll find these in SettingsMCP in the QueryDeck app. Changes apply immediately — no editor restart needed.

Read-only by default

When allowWrites: false (the default), any query containing one of these keywords is refused:

INSERT  UPDATE  DELETE  DROP  ALTER  TRUNCATE  CREATE  GRANT  REVOKE

Detection is case-insensitive and looks at SQL tokens, not substrings — a column named created_at doesn't trigger the guard.

The error returned to the AI editor is:

Write operations are disabled. Set "Allow writes" in QueryDeck → Settings → MCP.

This is intentional. The AI may, when asked, generate dangerous SQL — but it can't execute it without your explicit opt-in.

When to allow writes

Allow writes only when:

  • You're working on a local dev database where data loss is acceptable.
  • You're using an AI agent to scaffold migrations and you trust its output.
  • You're in a controlled "playground" environment.

Never allow writes when:

  • You're connected to production.
  • You're connected to a staging environment that mirrors production data.
  • The same connection is used by other team members.

How to enable

SettingsMCP → toggle Allow writes. The toggle is per QueryDeck installation, not per connection. If you flip it on and forget, every query the AI generates can mutate.

Recommendation: leave it off, and when you genuinely need writes, run them through the QueryDeck app's SQL editor with the diff preview instead of through MCP.

Row limit

maxRowLimit caps the result of execute_query and explain_query with analyze: true. Default: 1000 rows.

If the AI asks for more, the response is truncated and includes a notice:

[Truncated at 1000 rows. Total rows in result: 24891.]

The AI can then ask for a more specific query (with a WHERE or LIMIT) rather than scrolling through tens of thousands of rows.

Why this matters

Without a row cap:

  • The AI editor's context window fills with row data and the model loses track of the conversation.
  • Large result blobs slow the editor and may hit per-message size limits.
  • Bandwidth and disk go to data nobody is going to read.

Raise the limit only if you have a specific need (e.g., running analytics in the editor with a fixed-size summary).

Query timeout

queryTimeoutSeconds is the per-query wall clock cap. Default: 30 seconds.

When a query exceeds the timeout:

  1. QueryDeck cancels it on the database side (using pg_cancel_backend() for PostgreSQL, KILL QUERY for MySQL).
  2. The MCP response is an error: Query timed out after 30 seconds.
  3. No partial results are returned.

The timeout protects you from runaway queries the AI might generate — accidental cross joins, table scans on huge tables, slow window functions.

Raising the timeout

For analytical workloads, 30 seconds is sometimes short. Bump it in SettingsMCPQuery timeout. Reasonable values:

  • 30 seconds (default): interactive, snappy.
  • 60 seconds: tolerates one-off analytical queries.
  • 300 seconds: for ad-hoc reporting against a read replica.

If you're running real analytics workloads, consider a read replica with no MCP timeout rather than raising it everywhere.

Per-connection scope

MCP runs against the connection that's active in the QueryDeck app at the moment the tool call lands. If you have three connections open and the AI editor calls execute_query without specifying connection, the query goes to whichever connection is in focus.

To pin a specific connection from the AI side, the editor can pass connection: "Production" in the tool call. (Most editors do this automatically when the user clarifies which database they mean.)

License gating

The MCP server is a paid feature. During the 14-day trial it works fully. After the trial expires without an active license:

  • All five tools return Tool unavailable: license required.
  • The QueryDeck app continues to function in read-only mode for direct use.
  • Re-activate the license and the MCP tools are immediately available again — no editor restart.

Audit visibility

Every MCP query is logged in the QueryDeck app's query history. From the app:

  1. Open the History panel.
  2. Filter by source MCP — you'll see every query the AI ran, when, and which tool was used.

Useful for catching the AI doing something unexpected. The history is local to your Mac and not sent anywhere.

What we explicitly don't do

  • No automatic schema mutations. Even with allowWrites: true, the AI can't bypass any QueryDeck guard via a side channel. There is no DROP TABLE button in MCP. If the AI generates DROP TABLE x, it goes through the same write guard as any other query.
  • No credentials in the AI context. Connection passwords, SSH keys, and the contents of .env files are never returned by any tool. The AI knows what the schema looks like, not how QueryDeck got there.
  • No silent retries. If a query fails, the failure is returned to the AI. We don't transparently retry — that could amplify a bad query.

What's next