Skip to main content
The Docker image ships a single midplane binary. With no subcommand it runs the MCP server. Run the other (operator) commands inside the container with docker exec.
Output convention. Every command prints human-readable colored output on a TTY and JSON lines when piped. --json / --pretty force one or the other; color respects NO_COLOR.

midplane server

Run the MCP server. This is the default command, run by the image entrypoint with no arguments. Reads configuration from environment variables (DATABASE_URL, MIDPLANE_POLICY_FILE, PORT, MIDPLANE_TRANSPORT, …) and serves the MCP endpoint at /mcp.

midplane init

Interactive setup wizard. Connects with DATABASE_URL (or a masked prompt; the DSN is never echoed or written), introspects information_schema. You pick per-table read_write grants and denys; it writes a schema-validated, linted policy file and prints the docker command, agent MCP config, and verification steps.
Synopsis: midplane init [--url <dsn>] [-o <file>]
init needs a TTY. In a script or CI, use midplane policy init instead.

midplane query

Send one statement through the server’s full policy and audit pipeline, over Streamable HTTP, as an agent would. Calls stamp agent_name=midplane-cli on their audit rows. One shot, no REPL.
Synopsis: midplane query --sql "<query>" [--intent "<why>"] [--server <url> | --stdio] [--database <name>] [--json] Exit codes: 0 on ALLOW; 1 on DENY or error; 2 on a usage error.

midplane doctor

Preflight and smoke checks in boot order: env config, policy file (validate plus the policy lint findings), per-database connectivity (SELECT 1), the audit store, /health, and an end-to-end MCP canary (a SELECT 1 through the query tool).
Synopsis: midplane doctor [--server <url>] [--no-canary] [--json] Exit codes: any FAIL exits nonzero; warnings don’t.

midplane policy

Author, validate, lint, and dry-run a MIDPLANE_POLICY_FILE — without hand-editing YAML blind or connecting an agent. Four subcommands, run in order for a typical author flow:
At an interactive terminal, midplane init is the friendlier path — the same scaffold generator with a per-table wizard that validates and lints before writing. midplane policy init is the flag-driven form for scripts and CI.

policy init

Scaffold a commented policy file. With --url, connect read-only, list every table in the public schema, and emit each under table_access with default: read. The DSN is never printed or written into the scaffold.
Exit codes: 0 on success; 1 if the output file already exists or the introspection connection fails.

policy validate

Validate a file against the server’s schema plus the loader’s semantic rules (mappings / overrides conflict, reserved or duplicate database names, the name regex). Prints OK, or INVALID followed by each error as path: message.
Synopsis: midplane policy validate <file> Exit codes: 0 when valid (OK); 1 when invalid; 2 on a usage error (no <file>).

policy lint

Report security-posture findings the schema can’t see. Findings are graded:
Lint exits nonzero only on an error-level finding, which makes it a good CI gate — wire it in so a default: read_write can’t merge. Synopsis: midplane policy lint <file> Exit codes: 0 when there are no error-level findings (warnings and info still exit 0); 1 on any [ERROR] finding; 2 if the file isn’t schema-valid (run validate first) or <file> is missing.

policy test

Evaluate a query and print ALLOW or DENY, the deciding rule, and the exact agent-facing denial message. Pass exactly one of <file> (offline, no database connection) or --server (the /admin/dry-run endpoint of a running server’s currently-loaded policy, which also prints the server’s policy_hash).
An ALLOW prints the statement and that it would reach the database; a DENY prints the deciding rule and the exact agent-facing message:
Synopsis: midplane policy test (<file> | --server [url]) --sql "<query>" [--token <token>] [--db <name>] [--json] Exit codes: 0 on ALLOW; 1 on DENY (or a load error); 2 on a usage error (missing --sql, both/neither of <file>/--server, or an unknown --db).

policy help

midplane audit

Read the local SQLite audit log. All five subcommands are read-only against DB_PATH (default /data/audit.db) and open SQLite directly, so they don’t need INDEXER_TOKEN. See reading the audit log.

audit tail

Stream audit events as JSON lines: backfill recent rows, then poll for new ones (Ctrl-C to stop).
Synopsis: midplane audit tail [--backfill N] [--no-follow]

audit since

Dump every event whose timestamp falls within a duration window. Durations are sums of N + s|m|h|d tokens: 1h, 30m, 7d, 1d12h.
Synopsis: midplane audit since <duration> Exit codes: 2 on a missing or malformed duration.

audit denies

Show what got blocked and why. Joins each DENY decision to its ATTEMPTED row, printing the blocked SQL, the deciding rule, the agent-facing reason, and the agent’s stated intent together. Truncation is announced, never silent.
Synopsis: midplane audit denies [--since DURATION] [--limit N]

audit show

Show every event for one query: agent, intent, full SQL, and the ATTEMPTED → DECIDED → EXECUTED/FAILED chain. Takes the qid=… that tail / denies print (an individual event id also works).
Synopsis: midplane audit show <query_id> Exit codes: 2 on a missing <query_id>; 1 if no event matches it.

audit stats

Group-by summary over a window: event types, top deny rules, top allow statement types, and top agents.
Synopsis: midplane audit stats [--since DURATION] [--json] Exit codes: 2 on a malformed --since duration.

audit help

midplane version and midplane help

Common exit codes

Policy file schema

What policy init / validate / lint operate on.

Audit events

The rows audit tail / since / stats read.