governed-mcp
by rsiraj0
README.md
# governed-mcp
Governance that travels over the Model Context Protocol.
The `governed` co-workers — **Understander**, **Calibrator**, **Navigator** —
exposed as an MCP server. Any MCP-capable client (Claude, or a platform built
on Claude) mounts governance at the two points where it actually bites: the
**input** and the **handoff**. Every decision leaves an **owned, auditable
evidence record** as a byproduct — not by convention, but because the server
can't act without writing one.
This is the thesis made literal: you don't attach governance to one system,
you publish it and it travels to wherever it's mounted.
## The interface
**Tools** (model-controlled actions)
- `understand(action, context, principal)` — reads intent, scope, sensitivity,
and consequence class. Opens the evidence record under an owning principal.
- `calibrate(decision_id, model_confidence)` — is that confidence sufficient
*for this consequence*? Not a flat threshold: the Calibrator tracks the
outcomes of past decisions per consequence class and discounts stated
confidence by an online **reliability** estimate before comparing it to the
floor. A class whose confidence has proven only 80% trustworthy sees the same
stated 0.85 fall to an effective 0.69. With no history reliability is 1.0, so
it reduces exactly to a flat floor — a strict generalization, not a
replacement. Every adjustment is returned in the record, so calibration is
itself auditable. (This is a reliability-weighted estimator with shrinkage,
not a trained calibrator; it depends on resolved outcomes fed via
`Calibrator.observe()`, and that labeling is its own hard problem.)
- `navigate(decision_id)` — the handoff: `proceed`, `gate`, or `block`, plus
the exact rule that fired.
**Resources** (read-only data)
- `governance://policy` — the versioned ruleset, as an auditable artifact.
- `governance://evidence/{decision_id}` — one decision's full record: inputs,
every tool result, the route, timestamps, and the owning principal. This is
the underwriter's read.
**Prompt**
- `escalation_review(decision_id)` — what the gate presents to the accountable
human: the evidence, then *"Would you sign your name to this outcome?"*
## Run the demo (no dependencies)
```bash
python examples/walkthrough.py
```
**Act 1** — three decisions, three routes:
| Action | Class | Confidence | Route |
|---|---|---|---|
| Read Q3 summary, draft internal note | reversible | 0.88 | **proceed** |
| Transfer $250k to external account | irreversible | 0.99 | **gate** |
| Bulk-modify customer PII records | bounded | 0.79 | **block** |
**Act 2** — calibration learns. The *same* action at the *same* stated
confidence, judged differently as the agent builds a track record:
| Pass | Reliability | Effective conf. | Floor | Route |
|---|---|---|---|---|
| cold start (no history) | 1.00 | 0.85 | 0.80 | **proceed** |
| after 40 overconfident outcomes | 0.81 | 0.69 | 0.80 | **block** |
Nothing about the request changed — the system's earned trust in that
confidence did, and the evidence record shows exactly why. That flip is the
thing to screen-record.
## Run the MCP server
```bash
pip install "mcp[cli]"
python -m governed_mcp.server # stdio transport
```
To mount it in Claude Code / the desktop app, add it as an MCP server (stdio,
command `python -m governed_mcp.server`). Then ask Claude to run an action
through `understand` → `calibrate` → `navigate` and read back
`governance://evidence/{id}`.
## Design principle
Two things are enforced by the interface, not left to discipline:
1. **Every tool call writes evidence.** A decision cannot progress silently.
2. **`principal` is required to open a decision.** "Whoever deploys the agent
owns the outcome" is captured mechanically — the record always answers
*who owns this*.
## Swapping in the real `governed`
The co-workers here are transparent stand-ins with the right interfaces. The
real depth lives in your library's internals — the consequence classifier, the
calibration thresholds, the policy engine. Replace the bodies of
`Understander.read`, `Calibrator.check`, and `Navigator.route` in
`governed_mcp/coworkers.py`; the server, resources, prompt, and evidence store
stay as-is. The MCP layer is deliberately thin — the point it proves is that
you know *where* governance attaches in an agentic system.
## Tests
```bash
python tests/test_governance.py # no pytest needed; pytest also works
```
Asserts the decisions a governance tool must get right: routes match
consequence, sensitive scope raises the floor, every step writes evidence under
a principal, and calibration flips a verdict as overconfidence accumulates.
## Layout
```
governed-mcp/
├── governed_mcp/
│ ├── policy.py # consequence bands, classification, calibration floors
│ ├── coworkers.py # Understander, Calibrator (reliability-weighted), Navigator
│ ├── evidence.py # EvidenceStore, Decision, owned records
│ └── server.py # FastMCP: 3 tools, 2 resources, 1 prompt
├── policy.yaml # editable ruleset (overrides default when pyyaml present)
├── examples/
│ └── walkthrough.py # runnable, dependency-free demo (Act 1 + Act 2)
├── tests/
│ └── test_governance.py
├── requirements.txt
└── pyproject.toml
```
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues