Skip to content

Commit 6db4a9c

Browse files
committed
test(mcp-test): deflake streamable HTTP version-negotiation integration test
- tolerate an absent MCP-Protocol-Version header in the context extractor: Map.of rejects null values while spec-correct clients legitimately omit the header on initialize requests - await the asynchronously opened GET /mcp stream before asserting recorded calls; observed intermittently in CI as AssertionError Expected size: 3 but was: 2 (evidence: actions/run/33069467622 Jackson 2 Integration Tests)
1 parent b31841e commit 6db4a9c

1 file changed

Lines changed: 13 additions & 2 deletions

File tree

mcp-test/src/test/java/io/modelcontextprotocol/common/HttpClientStreamableHttpVersionNegotiationIntegrationTests.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
package io.modelcontextprotocol.common;
66

7+
import java.time.Duration;
78
import java.util.List;
89
import java.util.Map;
10+
import java.util.Objects;
911
import java.util.function.BiFunction;
1012

1113
import io.modelcontextprotocol.client.McpClient;
@@ -22,6 +24,7 @@
2224
import org.apache.catalina.LifecycleException;
2325
import org.apache.catalina.LifecycleState;
2426
import org.apache.catalina.startup.Tomcat;
27+
import static org.awaitility.Awaitility.await;
2528
import org.junit.jupiter.api.AfterEach;
2629
import org.junit.jupiter.api.Test;
2730

@@ -37,8 +40,10 @@ class HttpClientStreamableHttpVersionNegotiationIntegrationTests {
3740

3841
private final HttpServletStreamableServerTransportProvider transport = HttpServletStreamableServerTransportProvider
3942
.builder()
40-
.contextExtractor(
41-
req -> McpTransportContext.create(Map.of("protocol-version", req.getHeader("MCP-protocol-version"))))
43+
// The MCP-Protocol-Version header may legitimately be absent on initialize
44+
// requests, so a missing header must not break context extraction.
45+
.contextExtractor(req -> McpTransportContext
46+
.create(Map.of("protocol-version", Objects.requireNonNullElse(req.getHeader("MCP-protocol-version"), ""))))
4247
.build();
4348

4449
private final McpSchema.Tool toolSpec = McpSchema.Tool.builder("test-tool")
@@ -72,6 +77,12 @@ void usesLatestVersion() {
7277
McpSchema.CallToolResult response = client
7378
.callTool(McpSchema.CallToolRequest.builder("test-tool").arguments(Map.of()).build());
7479

80+
// The GET /mcp stream is opened asynchronously once the initialize response
81+
// creates the session, so wait for it to be recorded before asserting.
82+
await().atMost(Duration.ofSeconds(5))
83+
.untilAsserted(() -> assertThat(requestRecordingFilter.getCalls()).filteredOn(c -> "GET".equals(c.method()))
84+
.hasSize(1));
85+
7586
var calls = requestRecordingFilter.getCalls();
7687

7788
assertThat(calls).filteredOn(c -> !c.body().contains("\"method\":\"initialize\""))

0 commit comments

Comments
 (0)