Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,23 @@ private Mono<Disposable> reconnect(McpTransportStream<Disposable> stream) {
if (statusCode >= 200 && statusCode < 300) {

if (MESSAGE_EVENT_TYPE.equals(responseEvent.sseEvent().event())) {
String data = responseEvent.sseEvent().data();
// Per 2025-11-25 spec (SEP-1699), servers may
// send SSE events
// with empty data to prime the client for
// reconnection.
// Skip these events as they contain no JSON-RPC
// message.
if (data == null || data.isBlank()) {
logger.debug("Skipping SSE event with empty data (stream primer)");
return Flux.empty();
}
try {
// We don't support batching ATM and probably
// won't since the next version considers
// removing it.
McpSchema.JSONRPCMessage message = McpSchema.deserializeJsonRpcMessage(
this.jsonMapper, responseEvent.sseEvent().data());
McpSchema.JSONRPCMessage message = McpSchema
.deserializeJsonRpcMessage(this.jsonMapper, data);

Tuple2<Optional<String>, Iterable<McpSchema.JSONRPCMessage>> idWithMessages = Tuples
.of(Optional.ofNullable(responseEvent.sseEvent().id()),
Expand Down Expand Up @@ -503,13 +514,22 @@ public Mono<Void> sendMessage(McpSchema.JSONRPCMessage sentMessage) {
else if (contentType.contains(TEXT_EVENT_STREAM)) {
return Flux.just(((ResponseSubscribers.SseResponseEvent) responseEvent).sseEvent())
.flatMap(sseEvent -> {
String data = sseEvent.data();
// Per 2025-11-25 spec (SEP-1699), servers may send SSE
// events
// with empty data to prime the client for reconnection.
// Skip these events as they contain no JSON-RPC message.
if (data == null || data.isBlank()) {
logger.debug("Skipping SSE event with empty data (stream primer)");
return Flux.empty();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice fix

try {
// We don't support batching ATM and probably
// won't
// since the
// next version considers removing it.
McpSchema.JSONRPCMessage message = McpSchema
.deserializeJsonRpcMessage(this.jsonMapper, sseEvent.data());
.deserializeJsonRpcMessage(this.jsonMapper, data);

Tuple2<Optional<String>, Iterable<McpSchema.JSONRPCMessage>> idWithMessages = Tuples
.of(Optional.ofNullable(sseEvent.id()), List.of(message));
Expand Down Expand Up @@ -641,7 +661,7 @@ public static class Builder {
private Duration connectTimeout = Duration.ofSeconds(10);

private List<String> supportedProtocolVersions = List.of(ProtocolVersions.MCP_2024_11_05,
ProtocolVersions.MCP_2025_03_26, ProtocolVersions.MCP_2025_06_18);
ProtocolVersions.MCP_2025_03_26, ProtocolVersions.MCP_2025_06_18, ProtocolVersions.MCP_2025_11_25);

/**
* Creates a new builder with the specified base URI.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ private HttpServletStreamableServerTransportProvider(McpJsonMapper jsonMapper, S
@Override
public List<String> protocolVersions() {
return List.of(ProtocolVersions.MCP_2024_11_05, ProtocolVersions.MCP_2025_03_26,
ProtocolVersions.MCP_2025_06_18);
ProtocolVersions.MCP_2025_06_18, ProtocolVersions.MCP_2025_11_25);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ private McpSchema() {
}

@Deprecated
public static final String LATEST_PROTOCOL_VERSION = ProtocolVersions.MCP_2025_06_18;
public static final String LATEST_PROTOCOL_VERSION = ProtocolVersions.MCP_2025_11_25;

public static final String JSONRPC_VERSION = "2.0";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ default void close() {
Mono<Void> closeGracefully();

default List<String> protocolVersions() {
return List.of(ProtocolVersions.MCP_2025_03_26, ProtocolVersions.MCP_2025_06_18);
return List.of(ProtocolVersions.MCP_2025_03_26, ProtocolVersions.MCP_2025_06_18,
ProtocolVersions.MCP_2025_11_25);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ void testRequestCustomizer() throws URISyntaxException {

// Verify the customizer was called
verify(mockRequestCustomizer, atLeastOnce()).customize(any(), eq("POST"), eq(uri), eq(
"{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"id\":\"test-id\",\"params\":{\"protocolVersion\":\"2025-06-18\",\"capabilities\":{\"roots\":{\"listChanged\":true}},\"clientInfo\":{\"name\":\"MCP Client\",\"version\":\"0.3.1\"}}}"),
"{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"id\":\"test-id\",\"params\":{\"protocolVersion\":\"2025-11-25\",\"capabilities\":{\"roots\":{\"listChanged\":true}},\"clientInfo\":{\"name\":\"MCP Client\",\"version\":\"0.3.1\"}}}"),
eq(context));
});
}
Expand Down Expand Up @@ -120,7 +120,7 @@ void testAsyncRequestCustomizer() throws URISyntaxException {

// Verify the customizer was called
verify(mockRequestCustomizer, atLeastOnce()).customize(any(), eq("POST"), eq(uri), eq(
"{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"id\":\"test-id\",\"params\":{\"protocolVersion\":\"2025-06-18\",\"capabilities\":{\"roots\":{\"listChanged\":true}},\"clientInfo\":{\"name\":\"MCP Client\",\"version\":\"0.3.1\"}}}"),
"{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"id\":\"test-id\",\"params\":{\"protocolVersion\":\"2025-11-25\",\"capabilities\":{\"roots\":{\"listChanged\":true}},\"clientInfo\":{\"name\":\"MCP Client\",\"version\":\"0.3.1\"}}}"),
eq(context));
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,14 @@ void usesLatestVersion() {
.hasSize(3)
.map(McpTestRequestRecordingServletFilter.Call::headers)
.allSatisfy(headers -> assertThat(headers).containsEntry("mcp-protocol-version",
ProtocolVersions.MCP_2025_06_18));
ProtocolVersions.MCP_2025_11_25));

assertThat(response).isNotNull();
assertThat(response.content()).hasSize(1)
.first()
.extracting(McpSchema.TextContent.class::cast)
.extracting(McpSchema.TextContent::text)
.isEqualTo(ProtocolVersions.MCP_2025_06_18);
.isEqualTo(ProtocolVersions.MCP_2025_11_25);
mcpServer.close();
}

Expand All @@ -93,7 +93,7 @@ void usesServerSupportedVersion() {
startTomcat();

var transport = HttpClientStreamableHttpTransport.builder("http://localhost:" + PORT)
.supportedProtocolVersions(List.of(ProtocolVersions.MCP_2025_06_18, "2263-03-18"))
.supportedProtocolVersions(List.of(ProtocolVersions.MCP_2025_11_25, "2263-03-18"))
.build();
var client = McpClient.sync(transport).build();

Expand All @@ -108,14 +108,14 @@ void usesServerSupportedVersion() {
.hasSize(2)
.map(McpTestRequestRecordingServletFilter.Call::headers)
.allSatisfy(headers -> assertThat(headers).containsEntry("mcp-protocol-version",
ProtocolVersions.MCP_2025_06_18));
ProtocolVersions.MCP_2025_11_25));

assertThat(response).isNotNull();
assertThat(response.content()).hasSize(1)
.first()
.extracting(McpSchema.TextContent.class::cast)
.extracting(McpSchema.TextContent::text)
.isEqualTo(ProtocolVersions.MCP_2025_06_18);
.isEqualTo(ProtocolVersions.MCP_2025_11_25);
mcpServer.close();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ public static class Builder {
private boolean openConnectionOnStartup = false;

private List<String> supportedProtocolVersions = List.of(ProtocolVersions.MCP_2024_11_05,
ProtocolVersions.MCP_2025_03_26, ProtocolVersions.MCP_2025_06_18);
ProtocolVersions.MCP_2025_03_26, ProtocolVersions.MCP_2025_06_18, ProtocolVersions.MCP_2025_11_25);

private Builder(WebClient.Builder webClientBuilder) {
Assert.notNull(webClientBuilder, "WebClient.Builder must not be null");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ private WebFluxStreamableServerTransportProvider(McpJsonMapper jsonMapper, Strin
@Override
public List<String> protocolVersions() {
return List.of(ProtocolVersions.MCP_2024_11_05, ProtocolVersions.MCP_2025_03_26,
ProtocolVersions.MCP_2025_06_18);
ProtocolVersions.MCP_2025_06_18, ProtocolVersions.MCP_2025_11_25);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,22 +105,22 @@ void usesLatestVersion() {
.hasSize(3)
.map(McpTestRequestRecordingExchangeFilterFunction.Call::headers)
.allSatisfy(headers -> assertThat(headers).containsEntry("mcp-protocol-version",
ProtocolVersions.MCP_2025_06_18));
ProtocolVersions.MCP_2025_11_25));

assertThat(response).isNotNull();
assertThat(response.content()).hasSize(1)
.first()
.extracting(McpSchema.TextContent.class::cast)
.extracting(McpSchema.TextContent::text)
.isEqualTo(ProtocolVersions.MCP_2025_06_18);
.isEqualTo(ProtocolVersions.MCP_2025_11_25);
mcpServer.close();
}

@Test
void usesServerSupportedVersion() {
var transport = WebClientStreamableHttpTransport
.builder(WebClient.builder().baseUrl("http://localhost:" + PORT))
.supportedProtocolVersions(List.of(ProtocolVersions.MCP_2025_06_18, "2263-03-18"))
.supportedProtocolVersions(List.of(ProtocolVersions.MCP_2025_11_25, "2263-03-18"))
.build();
var client = McpClient.sync(transport).requestTimeout(Duration.ofHours(10)).build();

Expand All @@ -137,14 +137,14 @@ void usesServerSupportedVersion() {
.hasSize(2)
.map(McpTestRequestRecordingExchangeFilterFunction.Call::headers)
.allSatisfy(headers -> assertThat(headers).containsEntry("mcp-protocol-version",
ProtocolVersions.MCP_2025_06_18));
ProtocolVersions.MCP_2025_11_25));

assertThat(response).isNotNull();
assertThat(response.content()).hasSize(1)
.first()
.extracting(McpSchema.TextContent.class::cast)
.extracting(McpSchema.TextContent::text)
.isEqualTo(ProtocolVersions.MCP_2025_06_18);
.isEqualTo(ProtocolVersions.MCP_2025_11_25);
mcpServer.close();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ private WebMvcStreamableServerTransportProvider(McpJsonMapper jsonMapper, String
@Override
public List<String> protocolVersions() {
return List.of(ProtocolVersions.MCP_2024_11_05, ProtocolVersions.MCP_2025_03_26,
ProtocolVersions.MCP_2025_06_18);
ProtocolVersions.MCP_2025_06_18, ProtocolVersions.MCP_2025_11_25);
}

@Override
Expand Down