Skip to main content
Glama
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
```