Metadata-Version: 2.4
Name: vouch-mcp
Version: 2.2.0
Summary: Model Context Protocol server that issues and verifies Vouch Credentials to authorize AI agent tool calls.
Author: Ramprasad Gaddam
License: Apache-2.0
Project-URL: Homepage, https://vouch-protocol.com
Project-URL: Source, https://github.com/vouch-protocol/vouch
Keywords: mcp,vouch,ai-agents,verifiable-credentials,identity,eddsa-jcs-2022
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security :: Cryptography
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: vouch-protocol[mcp]>=2.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"

# vouch-mcp

A Model Context Protocol (MCP) server that lets AI agents **issue and verify**
[Vouch](https://vouch-protocol.com) Credentials, so every action an agent takes
carries cryptographic proof of who authorized it.

MCP standardized how agents call tools. It does not say *who* is calling, or on
*whose authority*. `vouch-mcp` adds that layer: every authorized action carries
a W3C Verifiable Credential with an `eddsa-jcs-2022` Data Integrity proof (or the
post-quantum hybrid profile), and any party can verify one over the same MCP
connection.

**The key stays out of the model.** MCP already runs this server in its own
process, so the agent's private key lives here, never in the LLM's context. A
prompt-injected model cannot exfiltrate a key it never holds.

## When to use this vs `vouch.autosign`

Vouch gives you two front doors onto one signing primitive:

- **`vouch.autosign`** (in-process, Python): wrap a tool with `protect([...])`
  and every call is signed deterministically, before the tool runs, with no
  LLM cooperation. Best when your agent is Python and you want zero-effort,
  can't-forget signing.
- **`vouch-mcp`** (this package): the out-of-process, cross-language path. Any
  MCP client in any language calls `sign` / `verify` over the
  wire, and the key is isolated in the server process. Best for non-Python
  agents, key isolation, or exposing verification as a shared service.

Both call the same `sign_intent` core, so credentials are identical either way.

## Install

```bash
pip install vouch-mcp          # or: uvx vouch-mcp
```

This pulls in `vouch-protocol[mcp]`, including the official MCP SDK. For the
post-quantum profile, install `pip install 'vouch-protocol[mcp,pq]'`.

## Configure

```python
from vouch import generate_identity
kp = generate_identity("agent.example.com")
print(kp.did)               # did:web:agent.example.com
print(kp.private_key_jwk)   # set as VOUCH_PRIVATE_KEY
```

## Run

**Local (stdio)** for Claude Desktop, Cursor, and desktop agents:

```bash
VOUCH_PRIVATE_KEY='...' VOUCH_DID='did:web:agent.example.com' vouch-mcp
```

**Remote (Streamable HTTP)** for hosted / networked deployments:

```bash
VOUCH_MCP_TRANSPORT=http VOUCH_MCP_HOST=0.0.0.0 VOUCH_MCP_PORT=8080 \
  VOUCH_PRIVATE_KEY='...' VOUCH_DID='did:web:agent.example.com' vouch-mcp
```

```jsonc
// Claude Desktop / Cursor MCP config
{
  "mcpServers": {
    "vouch": {
      "command": "vouch-mcp",
      "env": {
        "VOUCH_DID": "did:web:agent.example.com",
        "VOUCH_PRIVATE_KEY": "<jwk-json-string>"
      }
    }
  }
}
```

## Tools

| Tool | What it does |
|---|---|
| `sign(action, target, resource, post_quantum=False)` | Issue a credential authorizing one action, bound to that exact resource. Set `post_quantum=True` for the post-quantum profile, which returns a proof set with an `eddsa-jcs-2022` proof and an `mldsa44-jcs-2024` proof. |
| `verify(credential_json, public_key=None)` | Verify a credential another agent or service presented. Any MCP client can verify without installing an SDK. |
| `create_session(purpose, valid_seconds, decay_lambda, initial_trust)` | Issue a trust-decaying session voucher (Heartbeat Protocol). |
| `check_revocation(credential_json)` | Check a credential's `BitstringStatusList` entry: `ACTIVE`, `REVOKED`, or not individually revocable. |
| `get_identity()` | Return the agent's DID. |
| `evaluate_freshness(tier, snapshot_json=None, now_iso=None)` | Bounded-staleness revocation gate for offline/DTN use: decide if a last-synced revocation snapshot is fresh enough for the action's consequence tier, failing closed when too old. |
| `check_intent_freshness(credential_json, last_pulse, tier='high')` | Event-triggered intent recheck: decide if a reasoned action's intent seal is fresh for its tier, requiring a sensitive action to be sealed after the last heartbeat boundary so timing the gap between heartbeats does not help. |
| `verify_disconnected_edge(credential_json, public_key)` | Authenticate any disconnected-edge (DTN) credential type (freshness token, presence, ephemeris grant, revocation, bundle custody, …); returns its type and subject. |
| `scan(text)` | Scan text (a diff, log, message, or file) for leaked Ed25519/hybrid private keys, seed env vars, and DID documents that embed a private key, before it crosses a trust boundary. |
| `decode_did(key)` | Decode a `did:key:z...` identifier or bare Multikey and report its algorithm and public-key size, so you can confirm a peer's key is the algorithm you expect before trusting it. |
| `delegate(action, target, resource, to=None, valid_seconds=None, reputation_score=None)` | Issue a narrowed sub-delegation grant to a worker agent; every action it signs chains under the grant and can only narrow the authority, never widen it (Spec §9.3). |
| `check_action(tool, capabilities_json, requirements_json)` | Decide whether an agent's capabilities (filesystem/network/shell) permit a tool call. This is the authorization gate Vouch Shield applies before a tool runs. |
| `check_trust(voucher_json, threshold=0.5, now_iso=None)` | Recompute a session voucher's *current* trust after decay (Trust Entropy) and compare it to the threshold the action requires; refuse when trust has fallen too far. |
| `disclose_ai_origin(content_hash, content_ref=None)` | Sign a Vouch Credential attesting this agent produced the content at `content_hash`, so downstream parties verify the AI-origin claim instead of trusting an unsigned label. |
| `create_authority_state(authority_epoch, status="active", valid_seconds=300, subject_did=None)` | Publish this authority's current state as a signed credential carrying a monotonic `authorityEpoch` and a status (`active`, `suspended`, `incident`, `exposure_breached`, `revoked`). Bump the epoch on every authority-relevant transition. |
| `verify_authority_state(credential_json, public_key)` | Verify an `AuthorityState` credential another authority published and report its epoch and status, which is what a verifier records as the highest epoch it has seen. |
| `check_authority_freshness(tier, voucher_epoch=None, last_seen_epoch=None, current_status=None, live_cosign_ok=False)` | Authority Freshness gate: refuse a session voucher minted under an epoch older than the highest one this verifier has seen, even when its time-decay trust still passes. `routine` is time-decay only, `sensitive` applies the epoch rule locally, `critical` also requires a live M-of-N quorum co-sign whose outcome you pass in. |
| `reputation(did, events_json)` | Compute an agent's reputation score and success rate from a history of recorded outcomes, to weigh how much to trust a peer with a track record. |
| `attribute(manifest_json, path=None)` | Attribute authorship from a signed attribution manifest: a whole-manifest human/AI/pre-existing split, or per-line blame for one file. |

## Why `verify` matters

Signing proves *you* acted. Verifying is how *everyone else* benefits: any
MCP-capable agent, in any framework, can confirm another agent's credential with
a single tool call and no SDK. That is what turns Vouch Protocol from a per-app
library into an interoperable trust layer.

### Verifying without a key

`verify` checks the cryptographic signature, so a credential that only looks
well-formed will not pass. When you do not pass a key, it resolves the issuer's
key from the credential's DID: `did:key` is
self-certifying and resolves offline, while `did:web` is fetched over HTTPS from
the issuer's own domain. If the key cannot be resolved, the credential is
rejected. To verify fully offline, pass the issuer's key as `public_key`.

## Registry

This package ships a `server.json` manifest for the MCP registry, so it can be
discovered and installed like any other MCP server.

## License

Apache-2.0.

## MCP registry

This server is listed in the Model Context Protocol registry.

mcp-name: io.github.vouch-protocol/vouch-mcp
