Governing MCP tools
MCP gives an agent a menu of tools. Some read, some change the world. @senscheck/governance-mcp governs the ones that change it.
Agent → MCP request → governed handler → canonical effect → policy → authority → approval → your original tool
Classify your tools
| Class | Treated as | Default |
|---|---|---|
READ_ONLY | LOW risk read | Passes through, no receipts (opt in to govern reads) |
MUTATING | MEDIUM risk | Policy decides |
PRIVILEGED | HIGH risk | Needs human approval |
DESTRUCTIVE | CRITICAL risk | Needs human approval |
EXTERNAL_EFFECT | HIGH risk | Needs human approval |
Unclassified tools default to PRIVILEGED. A tool you forgot to classify is treated cautiously, not trusted.
Annotations are claims
MCP tools can describe themselves with hints like readOnlyHint. A server can say anything. SensCheck ignores those hints unless you explicitly set trustAnnotations, because trusting a tool's description of its own safety is a self-authorization.
Schemas stay intact
Names, descriptions and input schemas are preserved, so clients see the same tools. A blocked call returns a normal MCP error result naming the decision, reason codes and receipt ID. If human approval is needed, it says so.
Two ways to bypass it (avoid both)
- Registering a tool on the raw server object instead of the governed one. Keep the raw server private.
- Using the deprecated
tool()overloads. The governed server refuses them rather than leaving a tool ungoverned.
SensCheck does not run an MCP endpoint, hold your keys, or proxy many servers. It is in-process governance for your own server.