Skip to main content

Module wire

Module wire 

Source
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 \n included).
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 .. So contextgraph/1.0-draft and contextgraph/1.0 interoperate (both contextgraph/1), while contextgraph/2.0 does not. This is what lets the public v1.0 freeze drop the -draft suffix without a flag day (SPEC.md).