A request’s payload begins with one tag byte designating the endpoint; twenty-four endpoints are defined, and a request the server cannot read is answered by a bare response finish.
A request opens a scope for exactly one
endpoint. The request’s payload begins with a single tag byte
designating the endpoint; the remainder of the payload is the
endpoint’s request content, in the form the endpoint defines.
The tag values are normative as tabulated. Each endpoint has its own
section. Every section of this layer states requirements of the
server only: a sentence describing what the client sends states the
input the server serves, and imposes no requirement on the client.
An unreadable request is answered, not dropped. A request whose
payload the server cannot read — a tag the server does not define,
or content that does not conform to the endpoint’s form — is
answered by a response finish with no response preceding it. The
scope opens and closes; the client observes an unanswered request.
Growth is new tag values. A future endpoint is a new tag value
in this table. The frame types of the Frames layer are
unaffected by the addition of endpoints.
Capabilities. The server states in the capabilities object
of its info response which of the parts of this
layer it serves, as the Capabilities layer
defines, and answers every request past a part it does not serve by
the response that layer names for the endpoint. Every requirement
of this layer on an endpoint a capability governs holds subject to
that layer.
The JSON payloads of this layer are defined by type declarations,
written as Rust with serde attributes. The declarations are normative
for the JSON they describe — the protocol is not Rust, and the
notation binds no implementation language — under the following
reading:
A struct is a JSON object. A field is a member of the same name,
unless #[serde(rename = "…")] states the wire name; r#type is
the member type.
A field marked #[serde(default, skip_serializing_if = …)] may be
absent, and absence has the marked default’s meaning. An Option
field without that marking is present, and may be null.
An enum marked #[serde(untagged)] is exactly one of its variants’
shapes, with no wrapper naming the variant.
An enum of unit variants is a string: each variant’s
#[serde(rename = "…")] value, or its name in snake_case where
#[serde(rename_all = "snake_case")] is stated. A one-variant enum
is thereby a constant.
A field marked #[serde(flatten)] contributes its members to the
containing object; the field’s own name never appears.
String is a string; bool is a boolean; u64 and i64 are
integers; f64 and Decimal are numbers; Vec<T> is an array;
Vec<u8> is an array of integers; a map is an object;
serde_json::Value is any JSON value.
Types named from rmcp::model are the types of the
Model Context Protocol specification,
serialized as MCP defines them; they are incorporated by reference
and not restated. Wherever a declaration references one, its
definition in rmcp 3.1.2 — the MCP
implementation this revision builds against — is linked beneath the
declaration.
The binary payloads of this layer that a page marks as postcard are
defined by the same type declarations, under the following reading,
which is the postcard wire format:
A struct is its fields, in declaration order, with no delimiter
between them and no name before them.
u16, u32, u64 and usize are unsigned LEB128 varints: seven
bits of the value per byte, least significant first, the high bit
of every byte but the last set. A u64 occupies at most 10 bytes.
u8 is one byte. bool is one byte, 0 or 1.
String is a varint byte length followed by that many bytes of
UTF-8.
Vec<T> is a varint count followed by that many elements, each
encoded as T.
An enum is a varint discriminant, the index of the variant in
declaration order counted from 0, followed by the variant’s
fields in declaration order.
Option<T> is the byte 0, or the byte 1 followed by T.