Wymcp.Plugs.ProtocolFields (Wymcp v0.8.7)

View Source

Enforcement of the protocol fields. On every request, params._meta must carry io.modelcontextprotocol/protocolVersion as a string and io.modelcontextprotocol/clientCapabilities as an object — a missing or wrong-typed field answers -32602 + 400, naming the field in the envelope's message — and the version must be one wymcp serves — anything else answers -32022 + 400 with data.supported naming the served versions and data.requested echoing the offer — quoted under the rule Wymcp.Bound states in "What a refusal quotes" — under a fixed message that says what to send. Both messages say the same thing to a client of an earlier revision: the per-request protocol fields go in params._meta, and this server has no initialize handshake.

An initialize request is answered -32022 before its fields are read, whatever it carries: it is the one request a client of an earlier revision sends on its own, and the spec asks a server that speaks this revision alone to name the versions it serves in whatever error it returns to one — data.supported carries them structurally, where the -32602 every other fields-less request meets could name them in prose alone. data.requested is the params.protocolVersion such a request offers, omitted when it offers none as a string, never guessed.

Notifications are exempt: JSON-RPC forbids error responses to notifications, and the core defines no client→server notifications over HTTP — Wymcp.Plugs.Dispatch answers them with the acceptance.

The MCP-Protocol-Version header is deliberately not read here: the protocol fields are authoritative, and comparing the mirrored headers against the body they mirror is the header-binding check's (Wymcp.Plugs.HeaderBinding), which runs directly after this plug — with a body value this one has just proven.