feat!: add server discovery and negotiation (SEP-2575)#973
Conversation
ce0b7a9 to
4071398
Compare
| /// The request used a protocol version the server does not support. | ||
| pub const UNSUPPORTED_PROTOCOL_VERSION: Self = Self(-32022); | ||
| /// Processing the request requires a client capability that was not declared. | ||
| pub const MISSING_REQUIRED_CLIENT_CAPABILITY: Self = Self(-32021); |
There was a problem hiding this comment.
I initially set them to -32004 and -32003 following the SEP, but it failed the conformance suite. Then, I noticed that the error codes in the SEP differ from the draft schema. I reported this issue in modelcontextprotocol/modelcontextprotocol/issues/3091
- SEP
- Schema
|
|
||
| /// Select the first client-preferred protocol version supported by the server. | ||
| /// | ||
| /// Returns `None` when no version is shared. |
There was a problem hiding this comment.
What happens in this case? When a client only expresses a preference the server doesn't yet support?
Shouldn't it fall back to the newest one the server does support?
There was a problem hiding this comment.
This is wired up in the follow-up client lifecycle PR, #995. preferred_versions contains every version the client supports in preference order. When the server returns UnsupportedProtocolVersionError, the client selects the first mutually supported unattempted version and retries. If there is no overlap, it returns NoCompatibleProtocolVersion. It intentionally does not select a server version the client does not support. This should match the spec: https://modelcontextprotocol.io/specification/draft/basic/versioning#protocol-version-negotiation
5f0b865 to
2815005
Compare
ca01b27 to
b1bc9fd
Compare
b1bc9fd to
9b69a72
Compare
Motivation and Context
This implements the discovery and negotiation portion of SEP-2575. It adds the
server/discoverRPC, per-request protocol version negotiation, and typed unsupported-version errors so clients can learn a server's versions and capabilities without initializing a session, while preserving the legacy initialization flow.All six protocol union enums generated by
ts_union!are now#[non_exhaustive]. This requires downstream exhaustive matches to add a wildcard arm once, but allows future protocol variants to be added without causing the same Rust API break.How Has This Been Tested?
Added tests with conformance coverage
Breaking Changes
Yes.
ClientRequest,ClientNotification,ClientResult,ServerRequest,ServerNotification, andServerResultare now#[non_exhaustive], so downstream exhaustive matches must add a wildcard arm.DiscoverRequestandDiscoverResultalso add variants toClientRequestandServerResult; subsequent variants can be added without another exhaustive-match break.Types of changes
Checklist