feat!: implement SEP-2575 stateless MCP - #985
Open
devcrocod wants to merge 2 commits into
Open
Conversation
- split the version registry into handshake and modern revisions - add `resultType` and cache hints to results; result `meta` becomes `ResultMeta` - add error codes -32020/-32021/-32022; stop emitting -32002 - add `server/discover`, registered on every server - gate each method by the eras it exists in - add modern Streamable HTTP: POST-only, sessionless, deferred SSE commit - add client version negotiation (Legacy/Auto/Pin) and a response cache
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
A verified logic issue in ClientConnectionImpl.isMessageAccepted can incorrectly allow log notifications when there is no current request context, which violates the request-scoped opt-in semantics.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Implements SEP-2575 stateless (request-scoped) MCP alongside the legacy initialize-handshake lifecycle. This updates core wire types/serialization, adds dual-era Streamable HTTP routing and classification, introduces discovery/version negotiation, and adds an opt-in client response cache.
Changes:
- Add modern/request-scoped lifecycle support: per-request
_metaenvelope,server/discover, era-gated method surface, and updated error codes. - Update core result wire format:
ResultMeta,resultTypeacross results, and cache directives (ttlMs/cacheScope) on the spec-defined cacheable results. - Add client-side version negotiation (Legacy/Auto/Pin) and a response cache keyed by method/params + invalidated by list-changed notifications.
File summaries
| File | Description |
|---|---|
| kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt | Adjust handshake-era tests for version constant + result meta type. |
| kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StatelessStreamableHttpSessionLifecycleTest.kt | Update stateless HTTP lifecycle tests to use handshake version constant. |
| kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ModernStreamableHttpTest.kt | New tests asserting modern Streamable HTTP contract (status codes, headers, SSE commit behavior). |
| kotlin-sdk-server/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionAssertCapabilityTest.kt | Update tests for renamed handshake version constant. |
| kotlin-sdk-server/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/InboundClassificationTest.kt | New classifier rung-by-rung tests for modern-vs-legacy inbound routing. |
| kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransport.kt | Support dual-era entry by accepting pre-read body; tighten handshake-version validation; use ordered version comparison. |
| kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt | Track negotiated handshake protocol version and expose server-info stamping configuration. |
| kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt | Add server/discover auto-registration; allow non-subscribing request-scoped sessions; modernize error mapping behavior. |
| kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/LoggingLevels.kt | New helper to compute per-request allowed logging levels under modern lifecycle. |
| kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorServer.kt | Route a single POST endpoint across both lifecycles by classifying the body once. |
| kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnection.kt | Enforce per-request capability declaration + modern-era restrictions; update log filtering behavior. |
| kotlin-sdk-server/api/kotlin-sdk-server.api | API dump updates for ServerOptions and ServerSession surface changes. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/WireTest.kt | New tests for lifecycle-specific outbound wire shaping and error code mapping. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ToolsTest.kt | Update expected serialization for ResultMeta, resultType, and caching directives. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/TasksTest.kt | Update expected serialization for resultType + ResultMeta. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/SamplingTest.kt | Update expected serialization for resultType + ResultMeta. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/RootsTest.kt | Update expected serialization for resultType + ResultMeta. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ResultTypeTest.kt | New tests for defaulting/validation of resultType across result types. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ResourcesTest.kt | Update expected serialization for resultType + caching directives + ResultMeta. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/RequestTest.kt | Update request-meta tests to use envelope conversion and new meta APIs. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ProtocolVersionsTest.kt | New tests ensuring version partitioning and ordering semantics. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/PromptsTest.kt | Update expected serialization for resultType + caching directives + ResultMeta. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/MethodEraTest.kt | New tests asserting which methods exist in which lifecycle. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/JsonRpcTest.kt | Update test to use ResultMeta for response meta. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/InitializeTest.kt | Update expected initialize wire shape (now includes resultType in typed form). |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ElicitationTest.kt | Update expected serialization for resultType + ResultMeta. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/DiscoveryTest.kt | Update discovery request/result parsing expectations for envelope + tolerant cache defaults. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/CompletionTest.kt | Update expected serialization for resultType + ResultMeta. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/CommonTypeTest.kt | Update tests for new latest version constants and deprecated union behavior. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/CacheableResultTest.kt | New tests covering cache directive defaults, validation, and round-tripping. |
| kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolOutboundCancellationTest.kt | Update handshake protocol version constant in tests. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/wire.kt | New outbound wire shaping + inbound resultType validation helpers. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredException.kt | Keep deprecated code accepted while documenting modern removal context. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/tools.kt | Add resultType, migrate meta to ResultMeta, implement cacheable result fields/validation. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/tasks.kt | Add resultType, migrate meta to ResultMeta, update payload result meta extraction. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/serializers.kt | Update polymorphic selection rules for empty/discovery/initialize result decoding. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/sampling.kt | Add resultType + ResultMeta to sampling results. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/roots.kt | Add resultType + ResultMeta to roots results. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/resources.kt | Add resultType, cache directives, and ResultMeta to resource results (+ validation). |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/request.kt | Introduce COMPLETE_RESULT_TYPE, reshape RequestResult, add claimedProtocolVersion. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/prompts.kt | Add resultType, cache directives, and ResultMeta to prompt results (+ validation). |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/methods.kt | Add per-method lifecycle availability declarations. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/mcpHeaders.kt | New shared constants + header value encoding/decoding for MCP HTTP headers. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/McpException.kt | Keep accepting deprecated peer error codes while documenting intent. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/jsonRpc.kt | Add new spec-reserved error codes and deprecate retired ones. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/initialize.kt | InitializeResult defaults to latest handshake version; add resultType + ResultMeta. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/era.kt | New internal era model and method availability predicate. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/elicitation.kt | Add resultType + ResultMeta to elicitation results. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/discovery.kt | Discovery request/result types updated for request-scoped lifecycle + cache directives. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/completion.kt | Add resultType + ResultMeta to completion results. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/common.kt | Split protocol versions by lifecycle; add version ordering helpers; introduce ResultMeta. |
| kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/caching.kt | New cache directives model (CacheScope, CacheableResult). |
| kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/VersionNegotiationTest.kt | New tests for modern probe classifier and fallback/pin behavior. |
| kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt | Update expectations for notifications: omit standard MCP headers. |
| kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientAssertCapabilityTest.kt | Update handshake protocol version constant in tests. |
| kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/VersionNegotiation.kt | New client-side discovery probe outcome classifier for lifecycle selection. |
| kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTransport.kt | Use shared header constants/encoding; restrict standard headers to requests (not notifications). |
| kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ResponseCache.kt | New response cache store + invalidation logic driven by notifications. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/testing/ChannelTransportTest.kt | Update handshake protocol version constant in integration tests. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionInitializeTest.kt | Update handshake protocol version constant in integration tests. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerResourceTemplateTest.kt | Update expected error code for resource-not-found behavior. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SamplingTest.kt | Update capability enforcement expectations to structured McpException w/ missing-capability data. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/StreamableHttpSseReconnectTest.kt | Update handshake protocol version constant for SSE reconnect. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/StreamableHttpIntegrationTest.kt | Update handshake protocol version constant in client transport config. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/StreamableHttpHeartbeatIntegrationTest.kt | Update handshake protocol version constant for heartbeat tests. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/ResponseCacheTest.kt | New end-to-end tests for client response cache reuse and invalidation behavior. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/RequestScopedLifecycleTest.kt | New end-to-end tests for request-scoped envelope semantics and modern-vs-legacy behavior. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/ProtocolConcurrencyIntegrationTest.kt | Update decoding path for results given new wire wrapper behavior. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/ModernStreamableHttpStreamTest.kt | New real-engine test asserting committed SSE stream ordering/completeness. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/ModernStreamableHttpDisconnectTest.kt | New real-engine tests for request-scoped cancellation/disconnect behavior. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/MalformedEnvelopeFieldTest.kt | New integration coverage for malformed optional envelope fields handling. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractResourceIntegrationTest.kt | Update resource-not-found expectation to INVALID_PARAMS and document rationale. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/EraInterleavingTest.kt | New integration tests asserting per-request lifecycle interleaving over one connection. |
| integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt | Update legacy tests for protocol version constants + capability-missing exceptions + result read-back. |
Review details
- Files reviewed: 82/82 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+369
to
+377
| private suspend fun isMessageAccepted(level: LoggingLevel): Boolean { | ||
| val extra = currentRequestHandlerExtra() | ||
| // Outside a handler there is no request to have opted in, so nothing is deliverable on | ||
| // the request-scoped lifecycle and the connection-scoped filter applies on the other. | ||
| ?: return session.protocolVersion?.let { isModernProtocolVersion(it) } != true && | ||
| acceptedByLevelSetting(level) | ||
| if (level !in allowedLogLevels(extra.protocolVersion, extra.meta)) return false | ||
| return acceptedByLevelSetting(level) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements SEP-2575 alongside the legacy handshake era.
Closes #815
_metaenvelope;resultTypeon every result, cache hints (ttlMs/cacheScope)-32020/-32021/-32022;-32002no longer emittedserver/discover(auto-registered); era-gated method registryBreaking Changes
RequestResult.meta:JsonObject?->ResultMeta?;resultTypeadded to result data classesLATEST_PROTOCOL_VERSION->2026-07-28,SUPPORTED_PROTOCOL_VERSIONSdeprecated-32601on modern connectionsTypes of changes
Checklist