ADR-0026 — Response-_meta injection seam; serverInfo SHOULD adherence¶
- Status: Accepted
- Date: 2026-07-17
Context¶
MCP 2026-07-28 PR #3002 reshaped the _meta envelope on both sides of
the wire. On the request side, clientInfo moved from REQUIRED to
OPTIONAL in _meta — a client may omit it, leaving protocolVersion
and clientCapabilities as the only required keys
(MetaEnvelopeParser already tolerates a missing/null clientInfo).
On the response side, the spec now says servers SHOULD include
io.modelcontextprotocol/serverInfo in the _meta of every successful
response, and — as a consequence — DiscoverResult no longer carries
a top-level serverInfo field; identity is conveyed exclusively
through the response _meta envelope, the same way on every method,
not just server/discover.
Before this change, mocapi-server had no general mechanism for
stamping server-controlled keys into a response's _meta after a
handler returns its result — handlers built their own _meta, if any,
and DefaultMcpServer forwarded the JSON-RPC response unmodified. A
SHOULD-level, cross-cutting key like serverInfo doesn't belong in
every handler; it belongs at the one place that sees every successful
response before it reaches the transport.
Decision¶
DefaultMcpServer.handleCall is the canonical seam for injecting
server-side _meta keys into outgoing responses. The rule for that
seam:
- Runs once, after
dispatcher.dispatch(call)returns and beforetransport.send(...)— transport-agnostic, so both Streamable HTTP and stdio get it for free. - Applies only to successful
JsonRpcResultresponses whoseresultis a JSON object; JSON-RPC errors and non-object results pass through untouched. - Merges into the existing
_metaobject (withObjectPropertycreates one if absent) and never clobbers a key the handler already set —if (!meta.has(key))beforeset(...).
Mocapi adopts the serverInfo SHOULD by default: DefaultMcpServer
stamps McpMetaKeys.SERVER_INFO (io.modelcontextprotocol/serverInfo)
with the configured Implementation into every successful response's
_meta, unless a handler already populated that key. This is
default-on with an opt-out: the mocapi.emit-server-info property
(bound from the mocapi-prefixed @ConfigurationProperties record's
emitServerInfo field) defaults to true; setting it false disables
the injection entirely.
The clientInfo-optional request change and the removal of
DiscoverResult.serverInfo are spec-tracking consequences of PR #3002,
not separate decisions — they follow directly from serverInfo moving
to the response _meta as the single source of server identity.
Consequences¶
Future server-side _meta keys that must appear on every successful
response (not just specific handlers) have one obvious place to live:
DefaultMcpServer's injection step, following the same merge-don't-clobber,
successful-results-only, transport-agnostic rules. Handlers remain free
to set their own _meta keys directly on their result; the seam only
fills gaps, it never overrides handler-set values.
Operators who don't want serverInfo on the wire (bandwidth-sensitive
transports, custom identity conventions) set
mocapi.emit-server-info=false. Clients that depended on
DiscoverResult.serverInfo as a top-level field must instead read
_meta["io.modelcontextprotocol/serverInfo"] — acceptable pre-1.0 and
consistent with the clean-break precedent (ADR-0019).
Code anchors: mocapi-server/src/main/java/com/callibrity/mocapi/server/DefaultMcpServer.java, mocapi-model/src/main/java/com/callibrity/mocapi/model/McpMetaKeys.java, mocapi-model/src/main/java/com/callibrity/mocapi/model/DiscoverResult.java.