Skip to main content
The standalone engine is Midplane’s query path on its own: parse, policy, audit, execute. It guards one database for one agent on one machine, keeps its audit log in a local SQLite file, and needs no account and no server of yours. It’s the same enforcement code that runs behind Cloud and self-host — a query denied here is denied there, for the same reason. It’s the right shape when you want the guardrails and nothing else: a database on your laptop, a CI pipeline, a scratch environment. When you want a dashboard, a searchable audit log across a team, per-agent OAuth scope, or write approvals, you want a control plane — Cloud is the fastest way to get one.

Point an agent at it

npx fetches the midplane package on first run, so there’s nothing to install ahead of time. Add this to your MCP client’s config — Claude Code, Claude Desktop, and Cursor all take this shape:
Restart the client and the Midplane tools appear. That config is already the safe default: reads allowed, writes and DDL denied, every query audited. There’s nothing to configure to be safe — you configure only to open things up.
Keep the connection string in the env block, never in args. A DSN on a command line leaks to ps aux and your shell history. The block still lands in a plaintext config file, so give Midplane its own least-privilege Postgres role: it governs which SQL runs, not what the role underneath it can reach. See connect your database for the role recipe.

Requirements

Node 22.16+ or 24+ (the audit log uses the node:sqlite builtin), or Bun 1.3+. npx ships with Node, so there’s nothing else to install — no native modules, no compiler. On anything older the binary refuses to start and says so, rather than failing partway through with a stack trace from whichever dependency reached a newer builtin first.

Try it

Ask your agent to list the tables — an allowed read that goes straight through. Then ask it to delete a row. Midplane denies it before it runs: writes deny by default under table_access, even a bounded one-row DELETE … WHERE, until you grant read_write on that table. Read the denial back from the local audit log:
The intent is the agent’s own plain-language “why,” recorded next to the SQL and the decision. Nothing was modified, and the attempt is on the record either way — see the audit trail. The log is a SQLite database at ~/.midplane/audit.db (override with DB_PATH). midplane audit also has tail, since, show, and stats; see the CLI reference.

Open specific tables up

The default denies every write. To grant some, generate a policy file:
It connects read-only, introspects your schema, suggests a tenant column, and writes a schema-validated midplane.policy.yaml. Point the server at it by adding MIDPLANE_POLICY_FILE to the same env block:
init needs a terminal; npx -y midplane policy init is the flag-driven equivalent for CI. See writing policies and the policy schema.

In CI, or as a long-lived sidecar

For anything that isn’t a local MCP client, run the same engine as a container serving Streamable HTTP instead of stdio — self-contained, with no Node or node_modules inside it:
The MCP endpoint comes up at http://localhost:8080/mcp. Audit lands in the mounted volume, and DB_PATH defaults to /data/audit.db inside a container. Both artifacts are built from the same source at the same version.
--stdio and --http on midplane server override MIDPLANE_TRANSPORT. The npm package defaults to HTTP like the image does, which is why the client config above passes --stdio explicitly.

What ships, and how to check it

Midplane publishes two artifacts per release, plus a registry entry, all at the same version: Because this is a security tool you’re being asked to run with npx, the package is built to be checked rather than trusted:
  • Not minified, deliberately — anyone evaluating what npx midplane does should be able to read the artifact.
  • No install scripts and no native modules — nothing executes at install time.
  • Runtime dependencies stay external rather than vendored, so npm audit and Dependabot can still see them.
Releases are published through trusted publishing over OIDC, which attests provenance automatically. Verify any release with npm view midplane dist.attestations.
0.19.0 carries no provenance attestation; later releases do. Creating a package on npm requires setting its access, which a bypass-2FA token may no longer perform — so the first publish of any package has to come from an interactive session, which has no CI identity to sign with. That applies once, to the release that created the package.
See the threat model for what the engine defends against and what it doesn’t.

What you don’t get

Compared to Cloud or a self-hosted control plane:
  • No dashboard. The audit log is read from the CLI, not a UI.
  • No per-agent OAuth scope. Scope comes from the policy file and the database role, not a consent screen — see what you grant at consent.
  • No write approvals. Holding a write for a human needs a control plane for the human to review it in.
  • Audit is local and per-machine. A SQLite file on the box, not a searchable store across a team.
Column masking and multi-database policies both work standalone. Moving up doesn’t change your policy: the same table access model and the same YAML carry over, and the control plane spawns this same engine.

Next steps

Try Cloud instead

Dashboard, hosted audit log, and per-agent scope — the recommended path.

Write a policy

Grant the reads and writes your agent actually needs.

CLI reference

Every subcommand, flag, and exit code.