Minor Changes
-
#2501
1480241Thanks @felixweinberger! - Export theProtocolbase class andmergeCapabilitiesfrom the@modelcontextprotocol/clientand@modelcontextprotocol/serverpackage roots, restoring the v1 import for consumers that subclassProtocol(e.g. the MCP Apps SDK). The client and server packages each bundle their own compiled copy of the class, so import it from one package consistently within a process.The codemod now rewrites
ProtocolandmergeCapabilitiesimports fromshared/protocol.jsto the client or server package root, like the module's other symbols, instead of dropping them with an action-required marker. -
#2511
f60dff0Thanks @felixweinberger! -ConnectOptions.prioraccepts a cached era verdict — the new exported typePriorDiscovery.{ kind: 'modern', discover }adopts a previously obtainedDiscoverResultwith zero round trips;{ kind: 'legacy' }skips theserver/discoverprobe and runs the plaininitializehandshake directly, for servers known out-of-band to be legacy — without pinning the client tomode: 'legacy': stop supplying the verdict andconnect()falls back to the configuredversionNegotiationmode (under'auto', it re-probes and rediscovers an upgraded server). Freshness is the supplying host's responsibility — a stale legacy verdict succeeds silently against an upgraded server, so hosts must date cached legacy verdicts in their own storage and stop supplying them past their policy horizon. Persisted-blob plumbing is hardened:prior: nullis treated as absent, the modern arm'sdiscoverpayload is schema-validated before any connection state changes, and an unrecognized shape rejects with a typedSdkError(EraNegotiationFailed)instead of aTypeError. -
#2513
f413763Thanks @felixweinberger! - Align the 2026-07-28 wire with the final revision (spec PR #3002):serverInfomoves from theDiscoverResultbody to the result_meta, and the per-request envelope'sclientInfodemotes from required to SHOULD.Before this change the SDK shipped the pre-#3002 shape in both directions: the client hard-rejected a conforming server's
DiscoverResult(missing bodyserverInfofailed parse, so the probe misclassified the server as legacy and attempted aninitializehandshake against it — a hard connect failure against a modern-only server such as go-sdk v1.7.0-pre.3), and the server rejected conforming clients that omitclientInfo.Now:
- The 2026 wire schemas are the final revision exactly: no body
serverInfoonDiscoverResult, envelopeclientInfooptional (a present-but-malformed value still fails validation). - Servers stamp
_meta['io.modelcontextprotocol/serverInfo']on every 2026-era response (spec SHOULD; a handler-authored value wins, the 2025-era wire is untouched). This includes the entry-builtsubscriptions/listengraceful-close results — the spec'sSubscriptionsListenResultMetaextendsResultMetaObject. - Clients keep sending
clientInfoand read server identity from the discover result's_metaonly. A server that stamps no identity is anonymous:getServerVersion()isundefinedand the response cache partitions under a per-connection surrogate. A malformed_metaserverInfo value is treated as absent on receive (the spec marks the field self-reported, unverified, and display-only). - Breaking type changes:
DiscoverResultno longer declaresserverInfo;RequestMetaEnvelope'sclientInfois optional. New public constantSERVER_INFO_META_KEY('io.modelcontextprotocol/serverInfo').
- The 2026 wire schemas are the final revision exactly: no body
Patch Changes
-
#2514
6fe1963Thanks @felixweinberger! - Probe stdio servers on a disposable sibling process. Some stdio servers exit on any pre-initializerequest (servers built on the official Rust SDK, rmcp, behave this way), so underversionNegotiation: { mode: 'auto' }theserver/discoverprobe previously killed the server andconnect()hard-failed. The probe now runs on a short-lived sibling spawned from the same parameters — its stderr is discarded and it is reaped once the era is known — and the caller's transport spawns exactly once, afterwards: a legacy verdict connects with the plaininitializehandshake (byte-identical tomode: 'legacy'), a modern verdict is adopted directly, and the session wire never carriesserver/discover. Closing the caller's transport during the probe abortsconnect()with the typedSdkError(EraNegotiationFailed)and the session child is never spawned. On HTTP — and on custom stdio-shaped transports, which probe in place — a mid-probe connection close keeps rejecting with the typed connect error, now naming the close in pin-mode and modern-only diagnostics. -
Updated dependencies [
f413763]:- @modelcontextprotocol/core@2.0.0-beta.5