Expand description
The CGP wire envelope and its framing (SPEC.md §Transport bindings).
§This is not JSON-RPC
Earlier revisions of this module claimed CGP “rides MCP’s transport and
lifecycle conventions (JSON-RPC 2.0, …)”. That was not true of the wire it
described, and the claim has been withdrawn — see
ADR 0002.
CGP’s envelope is a bespoke type-tagged JSON object: there is no
jsonrpc member, no method/params split. Its lifecycle is informed by
MCP (a handshake that negotiates version and capabilities before any
payload moves), but the framing is its own.
A JSON-RPC binding — an alternate encoding of this same semantic layer — may be specified later without touching frame or query semantics and without a new protocol family. Keeping the semantic layer and the transport binding separate is what makes that possible.
§Framing
Every message is newline-delimited JSON (NDJSON): exactly one
serde_json value per line — the simplest thing that is unambiguous over
a pipe and trivially reimplementable in a provider kit in any language. HTTP
providers receive the same envelope as a JSON request body and reply with
one as the response body.
The envelope is versioned: the handshake negotiates the protocol family
up front, and a mismatch is a named error, never a hang (SPEC.md §H3).
§Correlation
query, frames, and error carry an optional id. A
provider MUST echo the id of the request it is answering. An envelope
with no id is a notification: it expects no reply, which is the shape a
future push-invalidation extension needs
(docs/sketches/push-invalidation.md).
id is optional so that a provider written against an earlier revision
stays conformant: it is queried in lock-step and is fully conformant.
Correlation is negotiated explicitly, via
Capabilities::correlation
— a host MUST NOT send an id to a provider that did not declare it
(SPEC.md §3.2). This paragraph previously said the opposite (“negotiated
by observation, not by a capability flag”), which predates the capability
and inverts a MUST NOT: a reply carrying no id is ambiguous between “does
not implement correlation” and “implements it incorrectly”, and a guarantee
whose violation is indistinguishable from legitimate behaviour cannot be
checked.
Note that verify/verified carry no id at all: a verdict echoes the
frame identity it answers in full, so those exchanges correlate by
matching rather than by envelope id (SPEC.md §9).
Enums§
- Envelope
- One Context Graph Protocol message. Every variant is a small, versioned,
type-tagged JSON object; the host writes exactly one per line (NDJSON) over stdio and one per HTTP body (SPEC.md§2).
Functions§
- decode_
line - Parse one NDJSON line into an envelope. A garbage line is a clean
HostError::Wire, never a panic — the crash-consistency contract (task deliverable 5). - encode_
line - Serialize an envelope to a single NDJSON line (trailing
\nincluded). - envelope_
kind - The human name of an envelope variant, for error messages that report “expected X, got Y”.
- next_
correlation_ id - Mint a fresh correlation id.
- verify_
correlation - Check that a reply carries the correlation id of the request it answers
(
SPEC.md§H4). - versions_
compatible - Two protocol version strings interoperate when they share a major
family — the substring up to the first
.. Socontextgraph/1.0-draftandcontextgraph/1.0interoperate (bothcontextgraph/1), whilecontextgraph/2.0does not. This is what lets the public v1.0 freeze drop the-draftsuffix without a flag day (SPEC.md).