Extension identifier: org.webgcp/attested-context · Version: 0.1 (draft)
Anchor: the Model Context Protocol, 2026-07-28 specification.
MCP standardises how a client calls tools and receives context. Nothing in it says what context the server is willing to assemble and vouch for. Attested Context is that missing assurance layer: the serving side assembles the context bundle under its own authority, serves it with an independently verifiable vouch, and keeps a receipt of what it served. The payload noun is the Attested Context Bundle.
| MCP 2026-07-28 fact | Why it matters here |
|---|---|
Stateless core — every request self-contained; version + capabilities ride _meta |
A self-verifying, content-addressed bundle is the natural payload of a stateless protocol |
Extensions framework — {vendor-prefix}/{extension-name} identifiers, capability negotiation, settings per extension |
This extension is org.webgcp/attested-context, riding official carrier machinery |
_meta key rules — vendor-prefixed, reverse-DNS |
All wire surfaces below are _meta keys under org.webgcp/ |
| Tool annotations are untrusted ("clients MUST consider tool annotations to be untrusted unless they come from trusted servers") | A vouch cannot be merely asserted — it must be independently verifiable (content address + signature) |
tools/list MAY vary by the authorization presented |
The sanctioned hook audience-scoping rides; this extension supplies the vocabulary and the enforcement rule |
CacheableResult — ttlMs + cacheScope on list/read results |
Composes with audience scoping (a varying list is never publicly cacheable) and bounds the two freshness planes |
Self-reported identity is not a trust surface (serverInfo "SHOULD NOT [be relied on] for security decisions") |
Issuer identity in the vouch binds to a published key, never to serverInfo |
| Property | MCP 2026-07-28 state |
|---|---|
| Provenance per context item | Content annotations are audience / priority / lastModified — display, ranking, and recency hints; no source, no evidence tier |
| Denied fields absent, not masked | "Implement proper access controls" — an obligation without a mechanism |
| Audience-scoped tools | No authorization field on Tool; the content-annotation audience is a display hint, not an authorization boundary |
| Server-held receipt | Clients "SHOULD log tool usage" — client-side, advisory; no signing or content-addressing in core |
| Retrieval comparability | No embedding, vector, or retrieved-item concept — see the webGCP substrate property this extension carries |
The anchor holds on extension point plus governance, not coverage — which is exactly what an extension wants.
Four properties plus one precondition:
The precondition (mediated assembly): the serving side queries its own substrate under its own identity. The client's credentials authorize the MCP call — they are never forwarded to, replayed against, or exchanged for access to the underlying substrate. A client never holds a substrate grant. (AC-5) This is what makes the vouch meaningful: a server that proxies the caller's credentials cannot attest to what it assembled.
Key words MUST / MUST NOT / SHOULD / MAY per BCP 14.
org.webgcp/attested-context in their capabilities extensions; opting
clients declare it in clientCapabilities.extensions per the anchor's negotiation rules._meta entries: a response carrying them is a valid core-MCP
response. Servers MAY emit the attestation _meta regardless of client opt-in.A result serving an Attested Context Bundle MUST carry
_meta["org.webgcp/attested-context"].provenance: a map from JSON Pointer into
structuredContent to a provenance record:
| Field | Req | Meaning |
|---|---|---|
source |
MUST | URI or URN of the item's origin |
tier |
MUST | evidence tier, per the published truth-class ladder (canonical | derived | inferred | synthetic) |
retrieved_at |
MUST | when the item was read from its source (RFC 3339) |
retrieval_mode |
MUST where retrieval ranked results | vector | lexical — declared degradation; a lexical response is honest, never silently counted as semantic |
space |
MUST where retrieval_mode is vector |
the declared space identity (model, dim, distance) per the webGCP Declared Space Identity substrate property — carried, not defined, here |
The map MUST cover every leaf of structuredContent (a record on an ancestor pointer covers its
descendants).
structuredContent.content, or in the provenance map (an omitted field has no
provenance entry; presence in the map is itself disclosure).public or admin
(deployments MAY define more; two classes are the floor), declared in the tool's
_meta["org.webgcp/audience"].tools/call from a caller outside the tool's
audience MUST fail authorization. Client-side hiding is display, not enforcement.tools/list MUST reflect the caller's audience: tools outside it are absent — never
listed-but-disabled. Such responses MUST set cacheScope: "private".audience (user | assistant) —
a display hint on content. They share a word and nothing else.A result serving an Attested Context Bundle MUST carry
_meta["org.webgcp/attested-context"].attestation:
| Field | Req | Meaning |
|---|---|---|
bundle_hash |
MUST | sha256: content address over the RFC 8785 (JCS) canonical form of structuredContent |
issued_at |
MUST | RFC 3339 |
issuer |
MUST | stable issuer identifier resolvable to a published verification key |
sig |
MUST | detached signature (EdDSA RECOMMENDED) over the JCS canonical form of {bundle_hash, issued_at, issuer} — exactly those three fields |
receipt_ref |
MUST at the governed level | the retained receipt's identifier |
sig against the issuer's published key and bundle_hash against the
received content, trusting neither serverInfo nor any annotation.receipt_ref is the receipt's own ledger identifier, so the reference resolves.receipt_ref the ledger never saw. The posture is
declared in the extension settings (receipts: "governed" | "best-effort"), so a consumer can
tell a guaranteed receipt from a best-effort one at the discovery surface. Retention follows the
substrate's declared data-retention contract (≥1 year RECOMMENDED) and MUST NOT be silently
bounded by storage-level expiry — TTLs are retention policy, declared, never incidental.ttlMs/cacheScope govern response caching; retrieved_at and staleness bounds in
provenance govern content currency. An implementation MUST NOT derive one from the other. An
attested bundle MAY be cached within ttlMs and remains verifiable — the vouch binds to content,
not transport.
Twelve assertions across three fixtures, with a stdlib-only runner, golden transcripts, and
negative controls — published at
/conformance/attested-context/:
AC-L0-001 — negotiation + the vouch (extension declared; attestation present; hash matches the
JCS canonical content; signature verifies against the published key)AC-L0-002 — provenance + absence (map present and covering; denied field absent with no mask
token and no provenance entry)AC-L0-003 — audience + freshness (foreign-audience tool absent from the list; call denied
server-side; cacheScope: private on varying lists; both freshness planes expressed)The runner evaluates captured transcripts, never live endpoints, so verdicts are reproducible
from artifacts. It is positive-controlled (a conformant golden transcript must pass 12/12),
negative-controlled (eleven broken variants must each trip their declared assertions — no check in
the suite is incapable of failing), and its embedded Ed25519 verifier is checked against RFC 8032
test vector 1 before any run. Run python3 runner.py --self-test first, then
python3 runner.py --transcripts <your-captured-dir>.
AC-5 deliberately has no fixture assertion: mediation is not observable from the wire; it is verified by architecture review. The governed receipt posture is likewise declared and discoverable rather than L0-asserted.
https://catalog.myparallel.dev. Its
.well-known/webgcp descriptor enumerates
the live endpoints; the attested discovery route it advertises returns this extension's
declaration with receipts: "governed", and the issuer's verification key is served on the
adjacent issuer-key route. Live-captured transcripts pass the L0 suite 12/12 (2026-07-30)._meta and existing MCP messages.