Why every MCP request repeats its metadata
RolesAgent Systems EngineeringCustomer AI Deployment
The question
A colleague ports an MCP server from the 2025 revision. The port keeps the initialize handshake and stores the client's declared capabilities on the connection object for later requests. All the old tests pass. What breaks under the current revision, and where does the metadata have to live instead?
Answer it first, aloud or on paper. Then open the answer.
The answer
Show short answer
The current revision has no handshake and no protocol session. A server that remembers capabilities from an earlier message can apply the wrong permissions or the wrong wire shape to the next request, which may come from another client on the same process or land on another worker. Every request carries io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities in params._meta, and the server validates them on each request and forgets them after it answers.
Show full answer
The request is the unit of interpretation
{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"io.modelcontextprotocol/clientInfo": {"name": "course-client", "version": "1.0.0"}
}
}
}The version and the capabilities are required. clientInfo is recommended, self-reported, and never a credential. The server must not infer any of these from an earlier request, a stdio process, an HTTP connection or a transport header alone.
What the server returns
Every successful result includes resultType: "complete" and should carry io.modelcontextprotocol/serverInfo in its _meta. The list results, resources/read and server/discover also carry ttlMs and cacheScope, with deterministic ordering so that equal results give stable cache keys.
Discovery is a method, not a gate
Every server must implement server/discover. It returns supportedVersions, capabilities, optional instructions and server identity. A client may call it first, but it may also send tools/list at once, because that request already carries its metadata.
The error codes that replace negotiation
| Case | Code |
|---|---|
| metadata missing or malformed | -32602 |
| header disagrees with body at an HTTP boundary | -32020 |
| version matched but unsupported | -32022, with requested and supported |
The client picks a mutually supported version from supported and retries with a new request id.
Keep the eras apart
Revisions through 2025-11-25 use initialize, notifications/initialized and connection-scoped capabilities. A dual-era server may keep that path as an isolated legacy adapter that it selects only when it receives initialize. It never routes a current request through the handshake path and never stamps resultType onto legacy results.
Application state is still allowed
A workflow or a draft can live behind an opaque handle in a shared store. The client sends the handle as an ordinary argument, and every replica authenticates and authorizes its use. Protocol context must not leak into that store as a substitute for the removed session.
Follow-ups
L2WorkingIs
clientInforequired, and can you authorize on it?Show expected answer
it is recommended, not required; it is display and debugging data and never a credential.
L2WorkingA client sends
tools/listwithout callingserver/discover. Does the server reject it?Show expected answer
no; the request carries its version and capabilities, so discovery is not a gate.
L3SeniorWhat does closing stdin or ending an HTTP response terminate?
Show expected answer
transport activity only; there is no protocol session to end, and the next request must still describe itself.
L4StaffWhere does a multi-step workflow keep its state now?
Show expected answer
behind a server-minted opaque handle in a shared durable store, returned as a normal result, bound to the authenticated principal, expired, and authorized on every use.
Wrong answers
Show the wrong answers that interviewers hear
“Stateless means the server cannot keep any state at all.”
Durable application state behind an explicit handle is allowed. Only hidden protocol context is removed.
“Send
initializefirst to be safe with every server.”A current server must not receive
initializeby default. Legacy is a documented fallback for a pinned peer.“The connection identifies the client, so one capability check per connection is enough.”
Two clients can share one process or HTTP worker in sequence, and a remote request can land on any replica.
Taught in
The fundamentals lesson traces one request from validation to a complete result, and the server lesson builds the dispatch loop.