Skip to main content

Hardware-attested MCP runtime — TEE-enforced policy and TRACE Claim generation

Project description

cMCP

cMCP: Confidential MCP Runtime

Enforce MCP tool policy where it cannot be tampered with

Documentation

Quick Start · Architecture · Configuration · CLI · Changelog

CI License: MIT PyPI OpenSSF Scorecard

Developer Preview - launching at Confidential Computing Summit, June 23 2026. May have breaking changes before v1.0.

Your agent calls Snowflake, Salesforce, a dozen APIs. What stops it from leaking a customer's data on one of those calls? If a regulator asks, could you prove it didn't?


The problem

An agent calls a tool. The policy engine says allow. The tool call goes through.

None of that proves the policy engine itself was not compromised. Software-only MCP governance cannot guarantee:

  • The Cedar policy on disk is the one that ran. A rogue admin can swap the bundle after approval; the hash check runs inside the same OS the admin controls.
  • The allow/deny decision was not flipped in memory. A supply chain CVE in the evaluator runs in the same address space as the attacker.
  • The audit log reflects what actually happened. Any party holding the software signing key can reconstruct a valid audit chain after the fact.

The control plane that governs tool calls must run where it cannot be reached by the process it governs.

Hardware-attested policy enforcement for MCP tool calls. Every tool call is intercepted, evaluated against a Cedar policy bundle, and enforced by a policy engine running inside a Trusted Execution Environment (TEE). The policy bundle hash is measured into the hardware attestation report before any code runs.

Unlike tunnel-based connectivity solutions, the cMCP Runtime processes tool-call payloads inside the TEE. The connectivity provider sees ciphertext, not plaintext. The only thing that leaves the enclave is the signed TRACE claim.


Quick Start

pip install cmcp-gateway

Create cmcp-config.yaml:

attestation:
  provider: auto
  enforcement_mode: advisory
policy_bundle_path: ./policies/
catalog_path: ./catalog.json

Start the gateway:

CMCP_DEV_MODE=1 cmcp start --config cmcp-config.yaml

Make a tool call:

curl -X POST http://localhost:8443/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"salesforce.contacts","arguments":{"query":"Acme Corp"},"_cmcp":{"session_id":"s1","workflow_id":"demo-agent"}}}'

See docs/quickstart.md for the full walkthrough: Cedar policy, tool catalog, first TRACE Claim, and verification (no hardware TEE required).


How it works

  1. The agent sends every tool call to the cMCP Gateway instead of directly to MCP servers.
  2. At startup the gateway measures the Cedar policy bundle hash into the hardware attestation report. No code runs before this measurement.
  3. Each incoming tool call is evaluated by the Cedar policy engine running inside the TEE. The result is allow, deny, or redact. The call and its decision are appended to the hardware-sealed audit chain.
  4. At the end of the session the gateway produces a TRACE Claim: a signed, hardware-attested artifact that records which tools ran, which policy decided each call, and the full audit chain. A verifier checks this without trusting the operator.
Agent -> cMCP Runtime -> Cedar Policy Engine (TEE) -> Tool
                     |
               GatewayClaim (TRACE Profile)
               +-- trace.eat_profile
               +-- trace.runtime.platform + measurement
               +-- trace.policy.bundle_hash
               +-- trace.cnf.jwk  (Ed25519 confirmation key)
               +-- gateway.audit_chain (root/tip/length)
               +-- signature (Ed25519 over canonical JSON)

Hardware providers

Provider Platform Assurance Notes
tpm TPM 2.0 / vTPM (Azure, AWS, GCP Trusted Launch) Medium Local TPM quote
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)

Provider auto-detects: SEV-SNP -> TDX -> TPM -> software. opaque is explicit opt-in via OPAQUE_ATTESTATION_URL and is never selected automatically.

from cmcp_gateway.config import TEEProvider

# Auto-detect (default)
# attestation.provider: auto  ->  sev-snp -> tdx -> tpm -> software

# Explicit hardware selection
# attestation.provider: sev-snp

# Opaque Managed Runtime (explicit opt-in only)
# OPAQUE_ATTESTATION_URL=https://... cmcp start --config cmcp-config.yaml

Enforcement modes

Mode Behavior Use case
enforcing Policy denies return HTTP 403; call is not forwarded Production
advisory Policy denies are logged; call proceeds First deployment, policy tuning
silent Policy is evaluated but nothing is logged or blocked Baselining

Default is enforcing. Set enforcement_mode: advisory in cmcp-config.yaml to use advisory mode.


Configuration

cmcp-config.yaml full reference:

attestation:
  provider: auto                    # auto | tpm | sev-snp | tdx | opaque | software-only
  enforcement_mode: enforcing       # enforcing | advisory | silent
  validity_seconds: 86400           # attestation freshness window (default: 24 hours)
  staleness_policy: fail_closed     # fail_closed | warn_only
  expected_measurement: ~           # pin a specific PCR/measurement (optional)

policy_bundle_path: policy/         # directory containing .cedar files and manifest.json
catalog_path: catalog.json          # approved tool catalog

listen_addr: "0.0.0.0:8443"
max_response_size_bytes: 2097152    # 2 MB default
policy_reload_interval_seconds: 0   # 0 = disabled; restart required to update policy

Environment variables:

Variable Effect
CMCP_DEV_MODE=1 Use software-only TEE provider; no hardware required
CMCP_BEARER_TOKEN Require this bearer token on all inbound requests
OPAQUE_ATTESTATION_URL Enable Opaque Managed Runtime attestation (explicit opt-in)

CLI reference

Command Flags Description
cmcp start --config PATH (required) Start the gateway
cmcp validate-config --config PATH (required) Validate cmcp-config.yaml without starting
cmcp validate-bundle --bundle-path PATH (required), --expected-hash sha256:<hex> (required) Verify a Cedar bundle hash before deployment

TRACE Claims

A GatewayClaim is the unit of proof handed to an auditor, regulator, or downstream verifier. It is produced per session (or per call, configurable) and signed with a key that never leaves the TEE.

Field Description
trace.eat_profile EAT profile URI: tag:agentrust.io,2026:trace-v0.1
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
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)

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 and the TRACE specification for the full verification protocol.


Standards alignment

Standard Coverage
OWASP Agentic AI Top 10 MCP10 (data leakage via tool calls), MCP02 (unsanctioned tools), MCP08 (provable governance), MCP04 (supply chain)
NIST SP 800-207 Policy decision point inside TEE; no implicit trust in workload identity
EU AI Act Art. 12, 15 Per-decision audit records (Art. 12); TEE-backed cybersecurity controls (Art. 15)
DORA Art. 9 Attestation chain; audit log retention via gateway.audit_chain
RATS/EAT RFC 9711 GatewayClaim is an EAT; eat_profile field identifies the TRACE profile

Security

Tool What it checks
ruff Style and import linting on every PR
bandit Python security linting on every PR
pip-audit Dependency vulnerability scan on every PR
mypy Static type checking on every PR
CodeQL Python SAST, security-extended queries, weekly
OpenSSF Scorecard Weekly scoring, SARIF upload

See SECURITY.md for vulnerability reporting and response SLAs. See LIMITATIONS.md for explicit scope boundaries, including residual risks for APM payload capture, runtime config injection, and P4.1 supply chain (typosquat) that Phase 1 does not close.


Documentation

Page Description
docs/quickstart.md From zero to first TRACE Claim in under 30 minutes
docs/configuration.md Full config reference with all fields and defaults
docs/SPEC.md Product specification: problem taxonomy, architecture, coverage matrix
docs/spec/threat-model.md STRIDE analysis, adversary model, residual risks
docs/spec/cedar-policy.md Cedar policy language reference and schema
docs/testing/benchmarks.md Latency and throughput benchmarks per TEE provider

Contributing

CONTRIBUTING.md · GOVERNANCE.md · Discussions

Using cMCP in production? Add your organization to ADOPTERS.md.


License

MIT - see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cmcp_runtime-0.1.0.tar.gz (229.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cmcp_runtime-0.1.0-py3-none-any.whl (94.3 kB view details)

Uploaded Python 3

File details

Details for the file cmcp_runtime-0.1.0.tar.gz.

File metadata

  • Download URL: cmcp_runtime-0.1.0.tar.gz
  • Upload date:
  • Size: 229.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cmcp_runtime-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8d93eb3dedec3cde3aca09aa7852b2df1aafcf17c33c7a8ede277c595f7d4f53
MD5 434b1e38c79a4d915ee90b01c1be9ce2
BLAKE2b-256 8649385fe6dfb6f0f17674044b816dee6cc30568651f6c6921ed3f2a7ff3d5b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmcp_runtime-0.1.0.tar.gz:

Publisher: publish.yml on agentrust-io/cmcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cmcp_runtime-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: cmcp_runtime-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 94.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cmcp_runtime-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 66d8fdccab264fbb18405e6f3586c9ab732c0bf5740be320645e5d79fff14086
MD5 98ed9f9303df386ca27a9f67c5ead027
BLAKE2b-256 7980511e59a646d68aa9c74d819f76f82221af1f5d08845cd03b489a32c29946

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmcp_runtime-0.1.0-py3-none-any.whl:

Publisher: publish.yml on agentrust-io/cmcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page