Skip to content

DiscoverResult rejects valid discovery responses with server identity in _meta #1039

Description

@tsarlandie-oai

Summary

rmcp::model::DiscoverResult requires a top-level serverInfo, but the
official MCP conformance server and TypeScript example server return server
identity under _meta["io.modelcontextprotocol/serverInfo"].

Consequently, valid 2026-07-28 discovery responses are rejected or
misclassified as CallToolResult.

Observed against real implementations

The official MCP conformance server directly implements the namespaced response:

The conformance implementation explicitly notes that server identity lives in
result metadata rather than the DiscoverResult body.

Reproduction

Deserialize this conformance-server response as ServerJsonRpcMessage:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "supportedVersions": ["2026-07-28"],
    "capabilities": {},
    "ttlMs": 0,
    "cacheScope": "private",
    "_meta": {
      "io.modelcontextprotocol/serverInfo": {
        "name": "conformance-mock-server",
        "version": "1.0.0"
      }
    }
  }
}

DiscoverResult fails because its server_info: Implementation field expects
the top-level serverInfo member. Since ServerResult is untagged and
CallToolResult accepts _meta, the same payload can then match the wrong
result variant.

Observed client trace:

→ server/discover
← HTTP 200; supportedVersions = ["2026-07-28"]
           _meta["io.modelcontextprotocol/serverInfo"] = {...}
           top-level serverInfo = absent
✗ expect initialized result, but received: Some(CallToolResult(...))

A related rmcp revision produced
expect initialized result, but received: Some(CustomResult(...)).

The client never proceeds to tools/list. Modern stdio inventory, tool calls,
resources, and multi-round operations fail at startup.

As an isolation control, copying the same identity into a synthetic top-level
serverInfo immediately allows discovery and subsequent tool calls to succeed.

Expected behavior

Both top-level serverInfo and
_meta["io.modelcontextprotocol/serverInfo"] should deserialize as
ServerResult::DiscoverResult. The resolved server identity and unrelated
metadata should be preserved, and discovery responses must not be classified
as completed tool-call results.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is not working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions