Governance
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.
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
Scopes, servers, and glob rules for which tools each scope may call. mcp-policy init prints a working template to edit.
{ "name": "example-corp", "default_scope": "engineering", "scopes": [{ "name": "engineering", "servers": [{ "server": "github", "allow_tools": ["list_*", "get_*", "search_*"], "deny_tools": ["*_delete", "delete_*"] }] }] }
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.
# 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.
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 →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
The policy covers which MCP servers and tools an assistant may call. It is not a network firewall and not a device-management product.
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.
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.
The template is one command, and it is a plain JSON file you can read.