Denied queries
A denial is usually correct: Midplane is doing its job. But if a query you expected to succeed was denied, the reason string names the rule and the table. Match it to one of these.My SELECT was denied
My SELECT was denied
The likely cause: the table is set to
deny. A table marked deny allows neither reads nor writes. Check your policy — if the table’s access is deny (or your default is deny and the table isn’t listed), reads are blocked. Set it to read (or read_write) to allow SELECTs. See table access.My write was denied
My write was denied
Writes deny by default. To allow a write, mark the table Note that
read_write in your policy:- Cloud (dashboard)
- Self-host (YAML)
Open the database’s policy grid and set a per-table override to
read_write. Cloud hot-reloads the change.read_write grants ordinary DML only. Side-effecting statements — COPY, LOCK, CALL, NOTIFY, SET — deny regardless of YAML, because the policy can’t grant a per-table target for them.Agent connection problems
Claude Code can't connect
Claude Code can't connect
The most common cause is a missing transport flag. Claude Code defaults to stdio and will treat your URL as a launcher command, failing silently. Add Verify it registered with
--transport http:claude mcp list. See Claude Code setup.Claude Desktop rejects my localhost URL
Claude Desktop rejects my localhost URL
Claude Desktop’s Custom Connectors UI enforces HTTPS and rejects This requires
http://localhost (and won’t accept a self-signed cert against localhost). For a local self-host instance, use the mcp-remote shim in the config file instead:npx (Node.js) on your PATH. Restart Claude Desktop after editing the file. Hosted Midplane (an HTTPS endpoint) uses Custom Connectors normally. See Claude Desktop setup.Connecting to your Postgres
Agent query fails with 'self signed certificate'
Agent query fails with 'self signed certificate'
Your database presents a self-signed or private-CA TLS certificate and its DSN uses
sslmode=require (or prefer). Since engine 0.15.0 Midplane follows libpq’s TLS semantics, where require encrypts without verifying the certificate — so a self-signed cert connects. On an older engine, require was upgraded to full verification and rejected the cert with a bare self signed certificate the moment an agent ran its first query.- Encryption is enough (a self-signed or private cert) —
sslmode=requireconnects on0.15.0+; upgrade the engine if you’re behind. - You want the cert verified — add
sslrootcert=/path/to/ca.crtto the DSN and Midplane verifies against that CA (likeverify-ca).verify-ca/verify-fullare unchanged. - Encryption isn’t needed (a private, trusted network) —
sslmode=disableturns TLS off.
sslmode behaves exactly as before. On Cloud the managed engine already runs 0.15.0+, so this applies to whichever database you connect.Boot failures
Boot fails with an unset ${VAR}
Boot fails with an unset ${VAR}
Midplane interpolates
${ENV_VAR} references in databases[].url so DSNs stay out of your YAML. If a referenced variable isn’t set in the environment, the URL can’t resolve and the server fails to boot.Check that every variable named in your policy file is present in your --env-file (or compose environment). For example, a policy with url: ${PROD_DATABASE_URL} needs PROD_DATABASE_URL defined.You can structurally validate a policy offline without the variables set — midplane policy validate <file> doesn’t fail on an unset ${VAR}, so it checks the YAML shape independent of the environment. The variable only has to resolve at server boot.When in doubt, read the audit log.
midplane audit tail streams every attempt and decision, including the rule that denied — so you can see exactly what your agent sent and why it was blocked. See the self-host audit log.FAQ
Short, grounded answers to the questions that come up most.Can Midplane see my data?
Can Midplane see my data?
Yes — and we don’t claim otherwise. Midplane logs every query as the audit record, and results pass through its memory on the way back to your agent (never persisted). On self-host none of this leaves your environment; on Cloud, operators with database access can read audit data until retention expires. See what we claim, and what we don’t.
Does it replace my database roles?
Does it replace my database roles?
No. Midplane is a second layer. It enforces policy on top of your database’s own permissions — it doesn’t replace role-based access control. If the connection string belongs to a privileged role, Midplane operates on top of those permissions. Give the agent a least-privilege database role as well. See the threat model.
Can an agent wipe or drop a table I marked read_write?
Can an agent wipe or drop a table I marked read_write?
No, not by default.
read_write grants row writes; whole-table destruction is a separate net. The dangerous_statement guardrails — on by default since 0.9.0 — deny a DELETE/UPDATE with no WHERE clause and any DROP/TRUNCATE/ALTER, regardless of table access, so granting a write can’t be escalated into DELETE FROM orders or DROP TABLE orders. They’re configurable per flag in the guardrails block if you really need to allow one.Which databases does it support?
Which databases does it support?
Postgres, since
0.1.0 — it’s the only dialect supported today. The dialect: key accepts only postgres. See the policy engine.What does it cost?
What does it cost?
Self-host is free — MIT open source, no hosted dependency. Midplane Cloud has a Free tier plus Pro and Team plans, gating on projects, MCP tokens, and seats rather than query volume. The policy engine, audit logging, and credential isolation are on every tier. See plans.
Is there telemetry?
Is there telemetry?
Self-host sends anonymous, aggregate telemetry by default — no SQL, no table or column names, no query results, no credentials. Disable it with
MIDPLANE_TELEMETRY=0 or DO_NOT_TRACK=1; inspect what’s sent with MIDPLANE_TELEMETRY=debug. See telemetry.Get help
If the fixes above don’t cover it:- Cloud
- Self-host & community
Email support@midplane.ai — also the Email support link in the dashboard sidebar. A human reads and answers.
Still stuck?
Denial reasons reference
Every denial message Midplane returns, and what to do about it.
How Midplane works
The parse → policy → audit → execute pipeline behind every decision.