Two decisions carry this. Everything fails closed, so a broken policy or a missing engine denies rather than passing the call through. And the enforcing path runs a self-test at startup and will not arm unless a known-forbidden action is actually blocked — a gate that cannot prove it denies does not start. The receipts are the other half: Ed25519, verifiable offline by anyone holding the public key, so the audit trail does not rest on trusting whoever ran the gate. Shadow mode first and a policy drafted from observed calls is the sane way in.
A policy gate for agent tool calls, offered here as the gate itself: evaluate a proposed call against a Cedar policy, sign the decision as an Ed25519 receipt, verify a receipt offline, and prove the whole loop works with no inputs at all.
- evaluate_action decides a proposed tool call against an inline Cedar policy — the same language AWS uses for IAM — and returns allowed, decision, reason and the policy digest
- Fail-closed by construction: a policy error, a missing engine or an evaluation failure all produce DENY rather than a quiet allow
- sign_decision turns a decision into an Ed25519 signed receipt — a denial signs a gateway_restraint artifact, an allow a decision_receipt — generating an ephemeral key if you do not supply one
- verify_receipt checks a receipt offline against a public key, with no network and no account, returning validity, type, key id and issuer
- self_test takes no inputs and proves the gate end to end: a known-forbidden action is denied, a signed receipt round-trips, and a tampered copy fails
- Receipts are byte-compatible with the ones the gate signs at runtime, so one minted here verifies with the same verifier as any other
- The wider CLI wraps any MCP server in shadow mode first, shows a local dashboard of tool inventory, risk, approvals and receipts, and drafts a reviewable policy from what it observed before anything is enforced
Published as protect-mcp and run as protect-mcp mcp over stdio. No credentials and no account: policies are evaluated locally, no telemetry about decisions is sent anywhere, and the dashboard binds to 127.0.0.1 and reads only local log and receipt files. Cedar policies are passed inline to the tools, or drafted from observed calls through the CLI's recommend step.
One command — npx protect-mcp mcp
