Open-source reference · Verifiable MCP Governance

Govern any MCP server

MCP servers let agents act through tools — but most ship with no authorisation boundary and no record of what an agent actually did. This is a drop-in fix: every tool call is authorised against a deny-by-default policy and fails closed, and each call leaves a signed, hash-chained receipt that rolls up into an independently-verifiable evidence bundle.

The boundary, in four steps

  1. 1Authorise every call. 100% of invocations hit the OAA tool-boundary guard, evaluated against a deny-by-default policy: allow, deny, charge, or review.
  2. 2Fail closed. Any non-allow verdict stops before execution — the tool handler runs on 0% of denied calls.
  3. 3Signed receipt before execution. An ed25519-signed, hash-chained receipt is written first, so the audit trail can’t be backfilled or quietly altered.
  4. 4Verifiable evidence bundle. Receipts roll up into an immutable bundle anyone can re-verify offline — no actions removed, reordered, or forged.

What changes when you govern an MCP call?

Ungoverned MCP tool callGoverned with OAA
AuthorisationNone — the tool handler runs on request.Deny-by-default policy returns 1 of 4 verdicts: allow, deny, charge, review.
On a denied callNo concept of denial.Fails closed — the handler never runs.
RecordNo record of what the agent did.ed25519 (256-bit) signed, hash-chained receipt, written before execution.
AuditNot independently verifiable.Immutable evidence bundle, re-verifiable offline by anyone.

Source: the OAA tool-boundary guard and evidence bundle in oaa-mcp-governance (Apache-2.0).

Drop it into your MCP server

Register your tools; the guard, receipts, and evidence bundle come with it. A sub-30-minute quickstart:

import { GovernedMcpServer } from '@kirkelabs/oaa-mcp-governance'
import { createReceiptSigningKeyPair } from '@kirkelabs/open-agent-access-core'

const server = new GovernedMcpServer(tools, {
  policy,                                  // deny-by-default
  signing: createReceiptSigningKeyPair(),  // ed25519 signed receipts
})

const r = await server.call('read_record', input, agent)
if (!r.ok) return mcpError(r.reason)       // denied → handler never ran
// every call → a signed, chained receipt → a verifiable evidence bundle

Full quickstart and runnable demos in the reference repo: github.com/KirkeLabs/oaa-mcp-governance. Built on the published @kirkelabs Open Agent Access packages (Apache-2.0), with an OAA v0.1 conformance runner and 2 runnable demos.

Why now

MCP adoption is moving fast and its security practices are still immature. Security research on MCP servers keeps surfacing the same gaps — over-privileged tokens, missing authorisation, and no consistent record of tool calls. The MCP specification added an OAuth 2.1 authorisation model in 2025, but it governs access, not a verifiable record of every action a tool takes. According to the MCP security best-practices guidance, end-to-end auditability of agent actions is a named requirement for safe enterprise MCP — one existing AI-governance frameworks don’t yet cover.

The architecture here is deliberately conventional: a deny-by-default boundary with 4 verdicts (allow, deny, charge, review), plus tamper-evident, hash-chained logs in the lineage of RFC 6962 Certificate Transparency — so a downstream party can verify that nothing was removed, reordered, or forged. Each receipt is an ed25519 (256-bit) signature written before execution. According to the EU AI Act (in force since 2024), Article 12 sets a record-keeping duty for high-risk AI — a tailwind, not the trigger.