diff --git a/README.md b/README.md
index b0d0864..3ca693b 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
# cMCP: Confidential MCP Runtime
-### Enforce MCP tool policy where it cannot be tampered with
+### Enforce MCP tool policy inside a TEE, where the agent it governs cannot reach it
@@ -24,7 +24,7 @@
[](https://github.com/agentrust-io/cmcp/actions/workflows/ci.yml) [](LICENSE) [](https://pypi.org/project/cmcp-runtime/) [](https://scorecard.dev/viewer/?uri=github.com/agentrust-io/cmcp) [](https://discord.gg/grgzFEHgkj)
-> **Developer Preview** - launching at Confidential Computing Summit, June 23 2026. May have breaking changes before v1.0.
+> **Developer Preview** - launched at the Confidential Computing Summit, June 23 2026. May have breaking changes before v1.0. See [STATUS.md](STATUS.md) for exactly what ships today versus what is on the roadmap.
**cMCP (Confidential MCP Runtime) is the secure, confidential way to run MCP: an open-source gateway that enforces MCP tool-call policy inside a hardware Trusted Execution Environment (TEE).** Every tool call is intercepted, evaluated against a Cedar policy bundle, and enforced where the process it governs cannot reach it. Each session produces a signed, hardware-attested TRACE Claim that a verifier checks without trusting the operator. If you are looking for a secure version of MCP, this is the AgenTrust runtime for it.
@@ -63,7 +63,7 @@ Create `cmcp-config.yaml`:
```yaml
attestation:
provider: auto
- enforcement_mode: advisory
+ enforcement_mode: advisory # advisory eases first-run tuning; the default is `enforcing`
policy_bundle_path: ./policies/
catalog_path: ./catalog.json
```
@@ -115,20 +115,21 @@ Agent -> cMCP Runtime -> Cedar Policy Engine (TEE) -> Tool
| `sev-snp` | AMD SEV-SNP (Azure DCasv5, AWS C6a Nitro) | High | AMD KDS |
| `tdx` | Intel TDX (Azure DCedsv5, GCP C3) | High | Intel PCS |
| `gpu-cc` _(v0.2)_ | NVIDIA H100/H200/Blackwell (CC mode) | High | NVIDIA Remote Attestation Service (NRAS) |
-| `opaque` _(explicit opt-in)_ | OPAQUE Confidential Runtime | High | Set `OPAQUE_ATTESTATION_URL`; not in auto-detect chain (stub: detect() returns False, not yet implemented) |
+| `opaque` _(opt-in)_ | OPAQUE Confidential Runtime | n/a _(not yet implemented)_ | Placeholder: `detect()` returns `False`, so it is never auto-selected until implemented |
-Provider auto-detects: `SEV-SNP -> TDX -> TPM -> software`. `opaque` is explicit opt-in via `OPAQUE_ATTESTATION_URL` and is never selected automatically.
+Provider auto-detect probe order: `tpm -> sev-snp -> tdx -> opaque` — the first provider whose `detect()` succeeds is selected. `opaque` is a not-yet-implemented placeholder and is never auto-selected. If no hardware provider is detected, the gateway starts only under `CMCP_DEV_MODE=1` (a non-attested software-only fallback) and otherwise refuses to start.
```python
-from cmcp_gateway.config import TEEProvider
+from cmcp_runtime.config import TEEProvider
# Auto-detect (default)
-# attestation.provider: auto -> sev-snp -> tdx -> tpm -> software
+# attestation.provider: auto -> tpm -> sev-snp -> tdx -> opaque
+# (software-only is used only under CMCP_DEV_MODE=1)
# Explicit hardware selection
# attestation.provider: sev-snp
-# OPAQUE Managed Runtime (explicit opt-in only)
+# OPAQUE Managed Runtime (opt-in only; not yet implemented)
# OPAQUE_ATTESTATION_URL=https://... cmcp start --config cmcp-config.yaml
```
@@ -196,12 +197,15 @@ A `GatewayClaim` is the unit of proof handed to an auditor, regulator, or downst
| `trace.runtime` | TEE platform and hardware measurement recorded at enclave boot |
| `trace.policy.bundle_hash` | SHA-256 of the Cedar bundle loaded at startup; changing any policy file changes this value |
| `trace.cnf.jwk` | Ed25519 public key bound to the TEE signing key |
+| `trace.tool_transcript` | Audit-chain-derived per-call view: `hash` (binds to the audit chain tip), `call_count`, and privacy-preserving `entries` (tool name, data class, decision) |
| `gateway.audit_chain` | Hash-chained audit log root and tip; verifiable without replaying individual entries |
| `signature` | Ed25519 over canonical JSON of the full claim body (RFC 8785) |
+(This table is a summary of the most-used fields.)
+
Verification with the `cmcp_verify` library does not require trusting the operator. The verifier checks the signature against the TEE-bound key, the policy bundle hash against the approved value, and the audit chain for internal consistency.
-See [docs/spec/verification-library.md](docs/spec/verification-library.md) and the [TRACE specification](https://trace.agentrust-io.com) for the full verification protocol.
+The normative schema is [`schemas/trace-claim.schema.json`](schemas/trace-claim.schema.json), and [docs/quickstart.md](docs/quickstart.md) shows a complete example. See [docs/spec/verification-library.md](docs/spec/verification-library.md) and the [TRACE specification](https://trace.agentrust-io.com) for the full verification protocol.
---
diff --git a/ROADMAP.md b/ROADMAP.md
index 1dd8314..f319213 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -11,11 +11,18 @@ Scope: Minimal viable trust layer for MCP servers, sufficient for early adopters
## v0.2: Released (June 2026)
-Provider-specific attestation verification:
+Provider-specific attestation verification (report parsing plus certificate-chain
+verification, validated against real vendor roots; report-signature paths validated with
+synthetic vectors):
- TPM2 quote verification
- AMD SEV-SNP attestation report parsing and verification
- Intel TDX attestation report parsing and verification
+> Report *generation* requires the corresponding TEE hardware. Until a backend verifies a
+> real quote end to end against a golden measurement on a confidential VM, these verifiers
+> should not be described as fully hardware-attested. This is the same status tracked for
+> the shared verifier code in the sibling [ca2a](https://github.com/agentrust-io/ca2a) repo.
+
Server integration:
- Session-scoped TRACE Claim emission wired into `server.py` request lifecycle
- Claim correlation across multi-turn sessions
diff --git a/STATUS.md b/STATUS.md
new file mode 100644
index 0000000..1b15152
--- /dev/null
+++ b/STATUS.md
@@ -0,0 +1,36 @@
+# cMCP — current status
+
+This file is the single source of truth for what ships today versus what is on the roadmap.
+Other docs (README, SPEC, quickstart) should link here rather than restate status, so the
+picture is stated once. Developer Preview: interfaces may change before v1.0.
+
+## Defaults (from `cmcp_runtime.config`)
+
+| Setting | Default |
+|---|---|
+| `attestation.provider` | `auto` (probe order `tpm -> sev-snp -> tdx -> opaque`) |
+| `attestation.enforcement_mode` | `enforcing` |
+| `attestation.staleness_policy` | `fail_closed` |
+| `attestation.validity_seconds` | `86400` |
+| `policy_reload_interval_seconds` | `0` (disabled; policy change requires an enclave restart) |
+
+## Capabilities
+
+| Capability | Status | Notes |
+|---|---|---|
+| MCP interception + Cedar policy evaluation inside the TEE | Shipped | HTTP/SSE transport. `stdio` is not yet supported (bridge planned, Phase 2). |
+| Enforcement modes (`enforcing` / `advisory` / `silent`) | Shipped | Default is `enforcing`. |
+| Hash-chained audit log, TEE-sealed signing key | Shipped | |
+| `GatewayClaim` (TRACE Claim) generation + signing | Shipped | Normative schema: [`schemas/trace-claim.schema.json`](schemas/trace-claim.schema.json). |
+| Offline verification (`cmcp_verify`) | Shipped | No operator trust required when the verifier independently checks the attestation report. |
+| Agent Manifest identity binding | Shipped | Optional; trust in the issuer key is an out-of-band PKI concern. |
+| Attestation verifiers: `tpm`, `sev-snp`, `tdx` | Partial | Report parsing + certificate-chain verification against real vendor roots; report-signature paths validated with synthetic vectors. End-to-end validation against a real hardware quote on a confidential VM is pending — do not describe as fully hardware-attested until then. |
+| `opaque` provider | Not implemented | Opt-in placeholder; `detect()` returns `False`, so it is never auto-selected until implemented. |
+| `gpu-cc` (NVIDIA H100/H200/Blackwell, via NRAS) | Planned (v0.2) | |
+| Transparency-log anchoring for TRACE Claims | v0.2 | Write and lookup. |
+| Server-side (provider) attestation | Not yet (Phase 2) | Phase 1 attests the gateway boundary only. |
+| Real-time policy update without enclave restart | Not yet | `policy_reload_interval_seconds` is `0`; a policy change requires a restart. |
+| Full RATS/EAT conformance | v1.0 target | Claims are EAT-shaped today; full conformance is tracked for v1.0. |
+
+See [ROADMAP.md](ROADMAP.md) for version sequencing and [LIMITATIONS.md](LIMITATIONS.md) for
+what cMCP does not prevent.
diff --git a/docs/SPEC.md b/docs/SPEC.md
index 5b7d60a..bec0db6 100644
--- a/docs/SPEC.md
+++ b/docs/SPEC.md
@@ -127,45 +127,68 @@ Network position: sits between agent host and MCP servers. The gateway is the on
## 5. TRACE Claim Schema
-The unit of proof handed to an auditor. Produced per-session or per-call (configurable).
+The unit of proof handed to an auditor, produced per session (or per call, configurable).
+The normative schema is [`schemas/trace-claim.schema.json`](../schemas/trace-claim.schema.json),
+and a full worked example is in [the quickstart](quickstart.md). The envelope is a
+`GatewayClaim`: canonical TRACE v0.1 fields live under `trace`, cMCP-specific addenda live
+under `gateway`, and `signature` is detached (computed over every other field).
```json
{
- "trace_version": "1.0",
- "session_id": "",
- "timestamp_utc": "",
- "tee_public_key": "",
- "attestation_report": {
- "provider": "sev-snp | tdx | tpm | opaque",
- "measurement": "",
- "report_data": ""
+ "cmcp_version": "1.0",
+ "trace": {
+ "eat_profile": "tag:agentrust.io,2026:trace-v0.1",
+ "iat": 1730000000,
+ "subject": "spiffe://cmcp.gateway/tee/",
+ "runtime": {
+ "platform": "amd-sev-snp | intel-tdx | tpm2 | software-only",
+ "measurement": "sha256:",
+ "nonce": ""
+ },
+ "policy": {
+ "bundle_hash": "sha256:",
+ "enforcement_mode": "enforce | advisory | silent",
+ "version": ""
+ },
+ "data_class": "",
+ "tool_transcript": {
+ "hash": "sha256:",
+ "call_count": 42,
+ "entries": [
+ { "tool_name": "salesforce.query", "data_class": "pii", "decision": "allow" }
+ ]
+ },
+ "cnf": { "jwk": { "kty": "OKP", "crv": "Ed25519", "x": "", "kid": "cmcp-" } }
},
- "policy_bundle": {
- "hash": "",
- "enforcement_mode": "enforcing | advisory | silent",
- "policy_version": ""
+ "gateway": {
+ "session_id": "",
+ "sequence_number": 1,
+ "audit_chain": { "root": "sha256:", "tip": "sha256:", "length": 43 },
+ "call_summary": {
+ "tool_calls_total": 42,
+ "tool_calls_allowed": 40,
+ "tool_calls_denied": 2,
+ "tool_calls_faulted": 0,
+ "tools_invoked": ["salesforce.query", "snowflake.read"],
+ "session_max_sensitivity": "pii",
+ "call_graph_summary": { "compliance_domains_touched": [], "cross_boundary_events": [] }
+ },
+ "catalog": { "hash": "sha256:", "drift_detected": false },
+ "attestation_generated_at": "",
+ "attestation_validity_seconds": 86400,
+ "attestation_stale": false,
+ "catalog_exceptions": []
},
- "tool_catalog": {
- "hash": ""
- },
- "call_summary": {
- "tool_calls_total": 42,
- "tool_calls_allowed": 40,
- "tool_calls_denied": 2,
- "tools_invoked": ["salesforce.query", "snowflake.read"]
- },
- "audit_chain_root": "",
- "audit_chain_tip": "",
- "signature": ""
+ "signature": ""
}
```
Verification (no operator trust required):
-1. Verify tee_public_key against attestation_report (hardware-rooted)
-2. Verify signature using tee_public_key
-3. Check policy_bundle.hash against the approved hash on record
-4. Check tool_catalog.hash against the approved catalog hash on record
-5. Walk audit_chain_root to audit_chain_tip for call-level detail
+1. Verify the `trace.cnf.jwk` public key against `trace.runtime` (hardware-rooted attestation)
+2. Verify `signature` using that key
+3. Check `trace.policy.bundle_hash` against the approved bundle hash on record
+4. Check `gateway.catalog.hash` against the approved catalog hash on record
+5. Recompute `trace.tool_transcript.hash` and walk `gateway.audit_chain` root to tip for call-level detail
---
@@ -233,9 +256,13 @@ Across the four problems and 13 shapes, Phase 1 covers 11 outright and partially
| tpm | TPM 2.0 / vTPM | Medium |
| sev-snp | AMD SEV-SNP (Azure DCasv5, AWS C6a Nitro) | High |
| tdx | Intel TDX (Azure DCedsv5, GCP C3) | High |
-| opaque | OPAQUE Managed Runtime | Highest |
+| opaque | OPAQUE Managed Runtime (opt-in; not yet implemented) | n/a |
-Auto-detection: tpm -> sev-snp -> tdx -> opaque. Default enforcement_mode: advisory.
+Auto-detection probe order: `tpm -> sev-snp -> tdx -> opaque`. The first provider whose
+`detect()` succeeds is selected. `opaque` is a placeholder whose `detect()` currently returns
+`False`, so it is never auto-selected until it is implemented. If no hardware provider is
+detected, the gateway starts only under `CMCP_DEV_MODE=1` (a non-attested software-only
+fallback) and otherwise refuses to start. Default `enforcement_mode` is `enforcing`.
---
@@ -259,12 +286,12 @@ In scope:
- Session-context sensitivity tagging and bleed detection
- Tool catalog binding (tool name to specific upstream server identity)
- TRACE Claim generation and signing
-- Hardware attestation: TPM, SEV-SNP, TDX, OPAQUE Managed
+- Hardware attestation: TPM, SEV-SNP, TDX (OPAQUE Managed is an opt-in placeholder, not yet implemented)
- Enforcement modes: enforcing, advisory, silent
- Egress policy: allow/deny/redact per tool and per field
- Per-session TRACE Claim with call summary
- Agent-side verification library (cmcp-verify)
-- Python SDK (cmcp-gateway), config file (cmcp-config.yaml)
+- Python SDK (cmcp-runtime), config file (cmcp-config.yaml)
Not in Phase 1:
- MCP server-side attestation (Phase 2)