Skip to content

fix: remove server_info from DiscoverResult - #1065

Merged
alexhancock merged 1 commit into
modelcontextprotocol:mainfrom
howardjohn:modern/server-info
Jul 28, 2026
Merged

fix: remove server_info from DiscoverResult#1065
alexhancock merged 1 commit into
modelcontextprotocol:mainfrom
howardjohn:modern/server-info

Conversation

@howardjohn

Copy link
Copy Markdown
Contributor

Motivation and Context

Fixes #1064

Replaces #1044

This removes the server_info field which is not part of the spec:
https://modelcontextprotocol.io/specification/draft/schema#discoverresult.

1044 add a synthetic server_info field; this PR removes it. This aligns with other types in this repo (using _meta as the source of truth, not a projection) and with other SDKS (Go and TypeScript do not have a server_info) field. Instead, users can use the helper accessors.

How Has This Been Tested?

Tested proxying to copilot MCP

Breaking Changes

Breaking from beta3 - the server_info field is removed

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@howardjohn
howardjohn requested a review from a team as a code owner July 27, 2026 23:15
@github-actions github-actions Bot added T-test Testing related changes T-config Configuration file changes T-core Core library changes T-service Service layer changes labels Jul 27, 2026
@howardjohn
howardjohn force-pushed the modern/server-info branch from 7c53e17 to 6b9c7b5 Compare July 27, 2026 23:17

@tsarlandie-oai tsarlandie-oai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving serverInfo into _meta for serialization makes sense, but clients must remain able to consume legacy top-level serverInfo, and must not fail when server identity is absent: the specification makes this metadata optional. The current MissingServerInfo path already causes 15 client conformance failures and bypasses the conservative fallback in #1045. We should preserve the legacy deserialization test, emit only the modern representation, and accept both representations on input.


#[test]
fn discover_result_prefers_top_level_server_info_over_namespaced_metadata() {
fn discover_result_ignores_legacy_top_level_server_info() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not change this test. I think it's a useful test to make sure we remain compatible with legacy servers.

@howardjohn
howardjohn force-pushed the modern/server-info branch from 6b9c7b5 to b68d366 Compare July 28, 2026 00:02
@DaleSeo

DaleSeo commented Jul 28, 2026

Copy link
Copy Markdown
Member

@howardjohn Can you take a look at the failing checks?

@howardjohn
howardjohn force-pushed the modern/server-info branch from b68d366 to 475c8c9 Compare July 28, 2026 16:21
@github-actions github-actions Bot added T-CI Changes to CI/CD workflows and configuration T-model Model/data structure changes labels Jul 28, 2026
@howardjohn
howardjohn force-pushed the modern/server-info branch 2 times, most recently from 18d2c58 to 9e1c5e2 Compare July 28, 2026 16:47
@howardjohn

Copy link
Copy Markdown
Contributor Author

@howardjohn Can you take a look at the failing checks?

sorry should be good to go now!

Comment thread crates/rmcp/src/service/client.rs Outdated
Comment on lines +849 to +857
if let Some(server_info) = result.server_info() {
peer.set_peer_info(ServerInfo {
protocol_version: selected.clone(),
capabilities: result.capabilities,
server_info,
instructions: result.instructions,
meta: result.meta,
});
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since serverInfo is optional, this branch leaves peer_info unset even for a valid discovery response. That means the version, capabilities, and instructions were negotiated, but RoleClient::enforce_peer_request_association still treats the connection as legacy and skips the 2026-07-28 guard against unsolicited sampling, roots, or elicitation requests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call.. working on it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have 3 options:

  1. Make PeerInfo a new type with server_info optional (breaking type change)
  2. Make an Implementation with just version, a empty/fake name, and the rest None. No breaking change but pretty wonky
  3. Just pass the version through for enforce_peer_request_association but do not give any peer info (they lose instructions etc)

(1) seems the best option but wanted to check we are ok with the break?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@howardjohn I agree that 1 is the cleanest option, and I'm okay with the break since this is already a breaking change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 sent a change with (1)

@DaleSeo

DaleSeo commented Jul 28, 2026

Copy link
Copy Markdown
Member

For context, I introduced the top-level field in #973 following the accepted SEP-2575 schema. About 15 hours before it merged, modelcontextprotocol/modelcontextprotocol/pull/3002 moved server identity into the optional result _meta field. 😅
I opened modelcontextprotocol/modelcontextprotocol/pull/3159 to make that post-Final change clear to future implementers.

@howardjohn
howardjohn force-pushed the modern/server-info branch from 9e1c5e2 to 0f4d2a2 Compare July 28, 2026 17:53
@github-actions github-actions Bot added the T-examples Example code changes label Jul 28, 2026
@howardjohn
howardjohn force-pushed the modern/server-info branch from 0f4d2a2 to 43fcf67 Compare July 28, 2026 19:19
@alexhancock
alexhancock self-requested a review July 28, 2026 19:35
@alexhancock
alexhancock merged commit 9a41811 into modelcontextprotocol:main Jul 28, 2026
22 checks passed
gocamille added a commit to gocamille/rust-sdk that referenced this pull request Jul 29, 2026
Rebase onto 3.0.0: RoleClient::PeerInfo is now ServerPeerInfo (modelcontextprotocol#1065)
and its constructor takes the protocol version directly.
DaleSeo added a commit that referenced this pull request Jul 29, 2026
…t association (#1055)

* refactor(service): express SEP-2260 receive-side association as an enum

Replaces the has_pending_outbound_request bool on
enforce_peer_request_association with PeerRequestAssociation, so a
stream-separating transport can report per-request association (#1033).
Behavior-preserving: the event loop still passes the coarse signal as
Unknown.

* feat(transport): record inbound stream origin on streamable HTTP client (#1033)

The worker attaches an InboundStreamOrigin extension to each inbound
server request: Unassociated for the standalone GET stream,
OutboundRequest(id) for a POST's SSE stream. Mirror of the
OriginatingRequestId marker used by the server side.

* feat(service): enforce SEP-2260 client receive-side check per stream origin (#1033)

The event loop maps InboundStreamOrigin plus the in-flight responder
pool to PeerRequestAssociation: restricted requests arriving on the
standalone GET stream are now rejected with -32602 even while unrelated
outbound requests are in flight.

* test: end-to-end SEP-2260 stream-based enforcement over streamable HTTP (#1033)

* docs: cross-link SEP-2260 stream markers

* test: origin marker survives SSE resumption per SEP-2260 (#1033)

A POST SSE stream resumed via GET + Last-Event-ID (SEP-1699) reconnects
beneath execute_sse_stream, so requests replayed after a resume keep
their OutboundRequest origin. Pins the layering invariant: hoisting
reconnection above the marker attach point would wrongly reject
associated requests with -32602.

* docs: trim SEP-2260 comments to spec rationale

* docs: align SEP-2577 expect reason with sibling suppressions

* test: harden SEP-2260 stream-enforcement e2e (#1033)

Detect handler invocation via a channel asserted empty instead of a
panic in a spawned task (swallowed, cannot fail the test); surface
scripted-server misuse as transport errors rather than panics in the
transport task; bound the tail awaits with 5s timeouts. Correct the
header comment: a 2026-07-28 server minting a session id is not
spec-legal (SEP-2567 removes sessions and the GET endpoint) — the
scripted server is deliberately non-conforming, which is the point of
receive-side enforcement.

* test: adapt SEP-2260 association tests to ServerPeerInfo

Rebase onto 3.0.0: RoleClient::PeerInfo is now ServerPeerInfo (#1065)
and its constructor takes the protocol version directly.

* chore: add 'Copy' macro to new PeerRequestAssociation

Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>

---------

Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-CI Changes to CI/CD workflows and configuration T-config Configuration file changes T-core Core library changes T-examples Example code changes T-model Model/data structure changes T-service Service layer changes T-test Testing related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DiscoverResult contains invalid server_info field

4 participants