Governance

Rules a laptop cannot argue with.

Decide centrally which MCP servers and which tools each team may use. The policy is signed with your key and checked on every call, so editing it locally does not widen access — it revokes it.

ed25519 signedFails closedSIEM export
policy

allowed: allowed by rule allow_tools "list_*"
 

DENIED: denied by rule deny_tools "delete_*"
 
# edit the policy file on this laptop and:

DENIED: the installed MCP policy failed verification:
  signature does not match (tampered or wrong key)

How it holds

Three properties, each of which is the point.

01 Written

A policy is a file you can read.

Scopes, servers, and glob rules for which tools each scope may call. mcp-policy init prints a working template to edit.

Writing a policy →
init

{
  "name": "example-corp",
  "default_scope": "engineering",
  "scopes": [{
    "name": "engineering",
    "servers": [{
      "server": "github",
      "allow_tools": ["list_*", "get_*", "search_*"],
      "deny_tools": ["*_delete", "delete_*"]
    }]
  }]
}
02 Signed

Tamper with it and it stops working.

The active policy is verified against your organisation's public key before every decision. A local edit breaks the signature, and a broken signature denies — it does not fall back to allowing.

ed25519signature, your key
verification
# a policy that verifies

allowed: allowed by rule allow_tools "list_*"
 
# one byte changed in the installed policy

DENIED: the installed MCP policy failed verification:
  signature does not match (tampered or wrong key)
  ↑ it denies. It does not fall back to allow.
03 Recorded

Every decision, in a format your SIEM already reads.

Each check is written to a sealed record with an event id, and exports as JSONL or CEF. The record lives on the machine, so you can recount it and nobody can quietly amend it.

SIEM export →
export

allowed: github/list_issues for scope engineering
  event: 30df5d9210b5c8967046e43c1c54f3f60e1156a2d54d0f3cc…
 

CEF:0|kosa8|kosa8|1|mcp.tool.allow|mcp.tool.allow|2|rt=2026-07-30T00:26:14Z
  suser=human act=mcp.tool.allow dst=github/list_issues outcome=allow
  cs1Label=scope cs1=engineering cs2Label=rule cs2=allow_tools cs4=30df5d92…

Honest about it

What this does not do.

It governs MCP, not everything

The policy covers which MCP servers and tools an assistant may call. It is not a network firewall and not a device-management product.

It is client-side enforcement

Signature checking happens on the machine. That defeats a careless edit and an assistant going off-script; it does not defeat someone with root who is determined to run a patched binary.

You hold the key

Signing uses your own ed25519 key. There is no kosa8 service in the loop, which also means there is nobody to ask if you lose it.

Write it once, sign it, ship it.

The template is one command, and it is a plain JSON file you can read.