Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
[![cMCP](https://img.shields.io/badge/Uses-cMCP_Gateway-7c3aed)](https://github.com/agentrust-io/cmcp)
[![Agent Manifest](https://img.shields.io/badge/Uses-Agent_Manifest-0ea5e9)](https://github.com/agentrust-io/agent-manifest)

Expand All @@ -25,7 +25,7 @@ cp examples/startup-tpm/cmcp-config.yaml .
cmcp start --config cmcp-config.yaml --enforcement advisory
```

This starts the gateway in advisory mode (no blocking, full logging) and emits a TRACE Trust Record for every MCP tool call.
This starts the runtime in advisory mode (no blocking, full logging) and emits a TRACE Trust Record for every MCP tool call.

## Prerequisites

Expand Down
36 changes: 18 additions & 18 deletions financial-services/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# financial-services: EU Credit Risk Agent Demo
# financial-services: EU Credit Risk Agent Demo

End-to-end demo of a credit risk agent processing client financial documents through a cMCP gateway with Cedar policy enforcement and TRACE Trust Records for EU regulatory compliance (EU AI Act, MiFID II, DORA, GDPR).
End-to-end demo of a credit risk agent processing client financial documents through a cMCP Runtime with Cedar policy enforcement and TRACE Trust Records for EU regulatory compliance (EU AI Act, MiFID II, DORA, GDPR).

End-to-end example: AI agent compliance for European private banks using cMCP and TRACE attestation.

Expand All @@ -11,7 +11,7 @@ End-to-end example: AI agent compliance for European private banks using cMCP an
This example demonstrates:

**1. Cryptographic proof of which tools an AI agent called**
The cMCP gateway intercepts every MCP tool call and records it in a signed TRACE Trust Record. An auditor or regulator can verify after the fact exactly which tools ran, in what order, with what data classifications — without trusting the agent process itself.
The cMCP Runtime intercepts every MCP tool call and records it in a signed TRACE Trust Record. An auditor or regulator can verify after the fact exactly which tools ran, in what order, with what data classifications — without trusting the agent process itself.

**2. Cedar policy as machine-readable compliance**
The three Cedar rules in `policy/allow.cedar` encode the bank's compliance requirements directly: which workflows may call which tools, when a large credit recommendation must go to a human reviewer, and how to prevent accidental data-class downgrade. Policy-as-code means the same rules that block a call are the rules that go into the audit file.
Expand All @@ -23,7 +23,7 @@ Article 12 requires high-risk AI systems to automatically log sufficient informa
MiFID II Article 25 requires that investment firms document the basis for any investment recommendation. For an AI-assisted credit decision, the TRACE record provides the tool-call audit trail showing that credit bureau data was consulted and a human reviewer was required for exposures above €500k.

**5. DORA Article 9 ICT risk — immutable logs**
The gateway runs in an attested environment (TEE or TPM). The TRACE record is signed by the gateway's attestation key. If a log is tampered with, the signature verification fails.
The runtime runs in an attested environment (TEE or TPM). The TRACE record is signed by the runtime's attestation key. If a log is tampered with, the signature verification fails.

**6. GDPR data minimisation in tool definitions**
The catalog schema enforces `sensitivity_level` and `compliance_domain` on every tool. The Cedar policy forbids confidential-data tools if the session sensitivity has been downgraded to `public`. This is the machine-enforceable equivalent of the GDPR data-minimisation principle.
Expand All @@ -40,7 +40,7 @@ The catalog schema enforces `sensitivity_level` and `compliance_domain` on every
│ tools/call (MCP)
┌─────────────────────────────────────────────────────────────────┐
│ cMCP Gateway :8443 │
│ cMCP Runtime :8443 │
│ │
│ ┌──────────────┐ ┌─────────────────┐ ┌───────────────────┐ │
│ │ Cedar engine │ │ Catalog checker │ │ TRACE recorder │ │
Expand Down Expand Up @@ -70,7 +70,7 @@ The catalog schema enforces `sensitivity_level` and `compliance_domain` on every
| agent-manifest | latest | `pip install agent-manifest` |
| curl | any | For verification steps |

No hardware TEE or TPM is required for this demo. The gateway runs in `CMCP_DEV_MODE=1`.
No hardware TEE or TPM is required for this demo. The runtime runs in `CMCP_DEV_MODE=1`.

---

Expand Down Expand Up @@ -102,7 +102,7 @@ cmcp-verify --version

```
financial-services/
cmcp-config.yaml Gateway configuration
cmcp-config.yaml Runtime configuration
catalog.json Three-tool catalog
policy/
manifest.json Policy bundle metadata
Expand Down Expand Up @@ -164,7 +164,7 @@ forbid (
};
```

Prevents a session that has been flagged `public` from calling tools that handle confidential data. This enforces the GDPR data-minimisation principle at the gateway layer.
Prevents a session that has been flagged `public` from calling tools that handle confidential data. This enforces the GDPR data-minimisation principle at the runtime layer.

**Rule 4 — Catch-all permit**

Expand All @@ -178,7 +178,7 @@ Any call not matched by a forbid is allowed. Removes the need to enumerate every

## Step 5 — Review the catalog

`catalog.json` registers three tools with their approved definitions, data classifications, and definition hashes. The definition hash is `sha256(json.dumps(approved_definition, sort_keys=True, separators=(',',':')))`. The gateway rejects any tool call where the server returns a definition that does not match the hash — preventing prompt-injection via MCP tool description tampering.
`catalog.json` registers three tools with their approved definitions, data classifications, and definition hashes. The definition hash is `sha256(json.dumps(approved_definition, sort_keys=True, separators=(',',':')))`. The runtime rejects any tool call where the server returns a definition that does not match the hash — preventing prompt-injection via MCP tool description tampering.

| Tool | compliance_domain | sensitivity_level | definition_hash (first 16 chars) |
|---|---|---|---|
Expand All @@ -188,7 +188,7 @@ Any call not matched by a forbid is allowed. Removes the need to enumerate every

---

## Step 6 — Start the gateway
## Step 6 — Start the runtime

```bash
CMCP_DEV_MODE=1 cmcp start --config financial-services/cmcp-config.yaml
Expand Down Expand Up @@ -354,7 +354,7 @@ For a production deployment with hardware TEE, the attestation line reads:
| `policy.version` | `credit-risk-v4.2` | From `policy/manifest.json` |
| `data_class` | `confidential` | Highest sensitivity across all calls |
| `tool_transcript` | array | One entry per tool call, in order |
| `cnf.kid` | `cmcp-a1b2c3d4` | Key ID of the gateway signing key |
| `cnf.kid` | `cmcp-a1b2c3d4` | Key ID of the runtime signing key |

---

Expand Down Expand Up @@ -398,7 +398,7 @@ openssl s_client -connect mcp.bank.eu:443 < /dev/null 2>/dev/null \

### Trigger the €500k escalation rule

Edit `credit_risk_agent.py` and change `AMOUNT_EUR = 250_000` to `AMOUNT_EUR = 750_000`. Re-run the agent. The gateway will return an advisory deny for the `finance.risk_report_writer` call:
Edit `credit_risk_agent.py` and change `AMOUNT_EUR = 250_000` to `AMOUNT_EUR = 750_000`. Re-run the agent. The runtime will return an advisory deny for the `finance.risk_report_writer` call:

```json
{
Expand All @@ -418,14 +418,14 @@ Edit `credit_risk_agent.py` and change `AMOUNT_EUR = 250_000` to `AMOUNT_EUR = 7

### Switch to enforcing mode

Change `enforcement_mode: enforcing` in `cmcp-config.yaml` (it is already set to `enforcing`). In dev mode the gateway enforces the policy but the attestation is not hardware-backed. Change `CMCP_DEV_MODE=1` to use a real TPM or TEE for production.
Change `enforcement_mode: enforcing` in `cmcp-config.yaml` (it is already set to `enforcing`). In dev mode the runtime enforces the policy but the attestation is not hardware-backed. Change `CMCP_DEV_MODE=1` to use a real TPM or TEE for production.

### Add a new tool

1. Define the tool in your MCP server.
2. Add an entry to `catalog.json` with the correct `definition_hash`.
3. Add a Cedar rule in `allow.cedar` if needed.
4. Restart the gateway with `cmcp start --config financial-services/cmcp-config.yaml --reload`.
4. Restart the runtime with `cmcp start --config financial-services/cmcp-config.yaml --reload`.

The definition hash is:

Expand All @@ -442,11 +442,11 @@ def definition_hash(approved_definition: dict) -> str:
1. Provision an Azure VM with Trusted Launch enabled (Trusted Launch is the default for most VM sizes as of 2025).
2. Install the vTPM extension if not already present.
3. Remove `CMCP_DEV_MODE=1` from the startup command.
4. The gateway will automatically use the vTPM. The `runtime.tee_type` field in the TRACE record will be `tpm2` and `runtime.measurement` will contain the PCR0 value.
4. The runtime will automatically use the vTPM. The `runtime.tee_type` field in the TRACE record will be `tpm2` and `runtime.measurement` will contain the PCR0 value.

### Connect an agent manifest

If you publish an agent manifest with `agent-manifest`, the gateway can cross-check the manifest's `allowed_tools` list against the catalog:
If you publish an agent manifest with `agent-manifest`, the runtime can cross-check the manifest's `allowed_tools` list against the catalog:

```bash
agent-manifest validate --manifest agent-manifest.json --catalog financial-services/catalog.json
Expand All @@ -456,7 +456,7 @@ agent-manifest validate --manifest agent-manifest.json --catalog financial-servi

## Troubleshooting

**Gateway cannot find the policy bundle**
**Runtime cannot find the policy bundle**

Make sure you run `cmcp start` from the root of the examples repo, or use an absolute path:

Expand All @@ -466,7 +466,7 @@ cmcp start --config /path/to/examples/financial-services/cmcp-config.yaml

**`httpx.ConnectError` in the agent script**

The gateway is not running, or is running on a different port. Check:
The runtime is not running, or is running on a different port. Check:

```bash
curl http://localhost:8443/health
Expand Down
22 changes: 11 additions & 11 deletions startup-tpm/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# startup-tpm: 15-Minute cMCP Quickstart
# startup-tpm: 15-Minute cMCP Quickstart

Get a cMCP gateway running with TPM-backed TRACE Trust Records in under 15 minutes. Works on any cloud VM with TPM 2.0 (Azure Trusted Launch, AWS Nitro, GCP Shielded VM) or with `CMCP_DEV_MODE=1` for local development — no hardware required for testing.
Get a cMCP Runtime running with TPM-backed TRACE Trust Records in under 15 minutes. Works on any cloud VM with TPM 2.0 (Azure Trusted Launch, AWS Nitro, GCP Shielded VM) or with `CMCP_DEV_MODE=1` for local development — no hardware required for testing.

---

## What you will have at the end

- A cMCP gateway running on port 8443
- A cMCP Runtime running on port 8443
- A Cedar policy that permits all tool calls (replace before production)
- A one-tool catalog (`test.echo`)
- A TRACE Trust Record you can inspect and verify
Expand All @@ -24,7 +24,7 @@ Estimated time: 15 minutes on a fresh VM, 5 minutes if Python is already install
| curl | any | For the test tool call |
| TPM 2.0 | optional | Required for hardware attestation; omit with `CMCP_DEV_MODE=1` |

No MCP server is required — the gateway runs a built-in echo responder for the `test.echo` tool.
No MCP server is required — the runtime runs a built-in echo responder for the `test.echo` tool.

---

Expand Down Expand Up @@ -55,7 +55,7 @@ The directory contains:

```
startup-tpm/
cmcp-config.yaml gateway configuration
cmcp-config.yaml runtime configuration
catalog.json one-tool catalog (test.echo)
policy/
manifest.json policy bundle metadata
Expand All @@ -78,29 +78,29 @@ attestation:
enforcement_mode: advisory
```

`enforcement_mode: advisory` means the gateway logs policy violations but does not block calls. Change to `enforcing` before production.
`enforcement_mode: advisory` means the runtime logs policy violations but does not block calls. Change to `enforcing` before production.

`provider: auto` selects the best available attestation source: TPM 2.0 if present, software-only otherwise.

---

## Step 4 — Start the gateway
## Step 4 — Start the runtime

### With hardware TPM (Azure Trusted Launch, AWS Nitro, GCP Shielded VM)

```bash
cmcp start --config startup-tpm/cmcp-config.yaml
```

The gateway will print the TPM attestation measurement on startup.
The runtime will print the TPM attestation measurement on startup.

### Without hardware TPM (local dev, CI)

```bash
CMCP_DEV_MODE=1 cmcp start --config startup-tpm/cmcp-config.yaml
```

`CMCP_DEV_MODE=1` sets `tee_type: dev-mode` in the TRACE record and marks the measurement `DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION`. The gateway is fully functional but the attestation is not hardware-backed.
`CMCP_DEV_MODE=1` sets `tee_type: dev-mode` in the TRACE record and marks the measurement `DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION`. The runtime is fully functional but the attestation is not hardware-backed.

Expected startup output:

Expand Down Expand Up @@ -145,7 +145,7 @@ Expected response:
curl http://localhost:8443/trace | python3 -m json.tool
```

The TRACE record covers the entire session (all tool calls since the gateway started). Example output:
The TRACE record covers the entire session (all tool calls since the runtime started). Example output:

```json
{
Expand Down Expand Up @@ -229,6 +229,6 @@ $env:CMCP_DEV_MODE = "1"
cmcp start --config startup-tpm/cmcp-config.yaml
```

**Gateway exits immediately**
**Runtime exits immediately**

Check that `policy/` and `catalog.json` exist relative to the working directory from which you run `cmcp start`. The `policy_bundle_path` and `catalog_path` in `cmcp-config.yaml` are resolved relative to the config file's location, not the working directory.
Loading