From 77d378d99c51abc250b67704cbf6e8848347abaa Mon Sep 17 00:00:00 2001 From: senor14 Date: Thu, 13 Aug 2026 20:52:14 +0900 Subject: [PATCH] fix: do not advertise 2024-11-05 from Streamable HTTP providers McpStreamableServerTransportProvider inherited the default protocolVersions() from McpServerTransportProviderBase, which includes 2024-11-05. Streamable HTTP was introduced in 2025-03-26, so a provider of this transport advertised a version whose transport it cannot serve. Override protocolVersions() on the interface rather than on the servlet implementation so every current and future Streamable HTTP provider is covered, mirroring the existing McpStatelessServerTransport default. Fixes gh-750 --- .../McpStreamableServerTransportProvider.java | 14 ++++ .../ServerTransportProtocolVersionsTests.java | 81 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 mcp-core/src/test/java/io/modelcontextprotocol/spec/ServerTransportProtocolVersionsTests.java diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpStreamableServerTransportProvider.java b/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpStreamableServerTransportProvider.java index 09fe9fb0e..467a432c8 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpStreamableServerTransportProvider.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpStreamableServerTransportProvider.java @@ -4,6 +4,8 @@ package io.modelcontextprotocol.spec; +import java.util.List; + import reactor.core.publisher.Mono; /** @@ -66,4 +68,16 @@ default void close() { */ Mono closeGracefully(); + /** + * Streamable HTTP was introduced in protocol version {@code 2025-03-26}, so providers + * of this transport cannot serve {@code 2024-11-05} clients and must not advertise + * that version. + * @return the protocol versions supported by Streamable HTTP transport providers + */ + @Override + default List protocolVersions() { + return List.of(ProtocolVersions.MCP_2025_03_26, ProtocolVersions.MCP_2025_06_18, + ProtocolVersions.MCP_2025_11_25); + } + } diff --git a/mcp-core/src/test/java/io/modelcontextprotocol/spec/ServerTransportProtocolVersionsTests.java b/mcp-core/src/test/java/io/modelcontextprotocol/spec/ServerTransportProtocolVersionsTests.java new file mode 100644 index 000000000..ec4fc96e1 --- /dev/null +++ b/mcp-core/src/test/java/io/modelcontextprotocol/spec/ServerTransportProtocolVersionsTests.java @@ -0,0 +1,81 @@ +/* + * Copyright 2024-2025 the original author or authors. + */ + +package io.modelcontextprotocol.spec; + +import java.util.List; + +import io.modelcontextprotocol.server.McpStatelessServerHandler; +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Mono; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Verifies that each server transport abstraction advertises only the protocol versions + * it can actually serve. + */ +class ServerTransportProtocolVersionsTests { + + private static final List STREAMABLE_HTTP_VERSIONS = List.of(ProtocolVersions.MCP_2025_03_26, + ProtocolVersions.MCP_2025_06_18, ProtocolVersions.MCP_2025_11_25); + + private static final McpStreamableServerTransportProvider STREAMABLE_PROVIDER = new McpStreamableServerTransportProvider() { + @Override + public void setSessionFactory(McpStreamableServerSession.Factory sessionFactory) { + } + + @Override + public Mono notifyClients(String method, Object params) { + return Mono.empty(); + } + + @Override + public Mono closeGracefully() { + return Mono.empty(); + } + }; + + private static final McpStatelessServerTransport STATELESS_TRANSPORT = new McpStatelessServerTransport() { + @Override + public void setMcpHandler(McpStatelessServerHandler mcpHandler) { + } + + @Override + public Mono closeGracefully() { + return Mono.empty(); + } + }; + + @Test + void streamableProviderDoesNotAdvertiseVersionsPredatingStreamableHttp() { + assertThat(STREAMABLE_PROVIDER.protocolVersions()).doesNotContain(ProtocolVersions.MCP_2024_11_05) + .containsExactlyElementsOf(STREAMABLE_HTTP_VERSIONS); + } + + @Test + void statelessTransportDoesNotAdvertiseVersionsPredatingStreamableHttp() { + assertThat(STATELESS_TRANSPORT.protocolVersions()).doesNotContain(ProtocolVersions.MCP_2024_11_05) + .containsExactlyElementsOf(STREAMABLE_HTTP_VERSIONS); + } + + @Test + void transportsWithoutStreamableHttpConstraintKeepTheFullRange() { + McpServerTransportProviderBase base = new McpServerTransportProviderBase() { + @Override + public Mono notifyClients(String method, Object params) { + return Mono.empty(); + } + + @Override + public Mono closeGracefully() { + return Mono.empty(); + } + }; + + assertThat(base.protocolVersions()).containsExactly(ProtocolVersions.MCP_2024_11_05, + ProtocolVersions.MCP_2025_03_26, ProtocolVersions.MCP_2025_06_18, ProtocolVersions.MCP_2025_11_25); + } + +}