E55E Fix everything-server-based integration tests (#756) · modelcontextprotocol/java-sdk@fc53c50 · GitHub
[go: up one dir, main page]

Skip to content

Commit fc53c50

Browse files
chemicLtzolov
authored andcommitted
Fix everything-server-based integration tests (#756)
* Pin `npx @modelcontextprotocol/server-everything` version to `2025.12.18`. * Replace `tzolov/mcp-everything-server` Docker image with `node:lts-alpine` + `npx` command. * Handle HTTP 202 special case. * Fix test assertions. The recent rollout of everything-server broke integration tests which take the latest version from the node registry. This PR unifies the everything-server usage - the Testcontainers Docker setup uses the same version as the STDIO npx-based tests and no longer relies on tzolov/mcp-everything-server. Signed-off-by: Dariusz Jędrzejczyk <dariusz.jedrzejczyk@broadcom.com>
1 parent 07b4d51 commit fc53c50

22 files changed

+144
-139
lines changed

mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,9 @@ public Mono<Void> sendMessage(McpSchema.JSONRPCMessage sentMessage) {
491491
.firstValue(HttpHeaders.CONTENT_LENGTH)
492492
.orElse(null);
493493

494-
if (contentType.isBlank() || "0".equals(contentLength)) {
494+
// For empty content or HTTP code 202 (ACCEPTED), assume success
495+
if (contentType.isBlank() || "0".equals(contentLength) || statusCode == 202) {
496+
// if (contentType.isBlank() || "0".equals(contentLength)) {
495497
logger.debug("No body returned for POST in session {}", sessionRepresentation);
496498
// No content type means no response body, so we can just
497499
// return an empty stream

mcp-core/src/test/java/io/modelcontextprotocol/client/AbstractMcpAsyncClientResiliencyTests.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,9 @@ public abstract class AbstractMcpAsyncClientResiliencyTests {
4848
static Network network = Network.newNetwork();
4949
static String host = "http://localhost:3001";
5050

51-
// Uses the https://github.com/tzolov/mcp-everything-server-docker-image
5251
@SuppressWarnings("resource")
53-
static GenericContainer<?> container = new GenericContainer<>("docker.io/tzolov/mcp-everything-server:v3")
54-
.withCommand("node dist/index.js streamableHttp")
52+
static GenericContainer<?> container = new GenericContainer<>("docker.io/node:lts-alpine3.23")
53+
.withCommand("npx -y @modelcontextprotocol/server-everything@2025.12.18 streamableHttp")
5554
.withLogConsumer(outputFrame -> System.out.println(outputFrame.getUtf8String()))
5655
.withNetwork(network)
5756
.withNetworkAliases("everything-server")

mcp-core/src/test/java/io/modelcontextprotocol/client/AbstractMcpAsyncClientTests.java

Lines changed: 50 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ protected Duration getRequestTimeout() {
7272
}
7373

7474
protected Duration getInitializationTimeout() {
75-
return Duration.ofSeconds(2);
75+
return Duration.ofSeconds(20);
7676
}
7777

7878
McpAsyncClient client(McpClientTransport transport) {
@@ -503,57 +503,64 @@ void testRemoveNonExistentRoot() {
503503

504504
@Test
505505
void testReadResource() {
506+
AtomicInteger resourceCount = new AtomicInteger();
506507
withClient(createMcpTransport(), client -> {
507508
Flux<McpSchema.ReadResourceResult> resources = client.initialize()
508509
.then(client.listResources(null))
509-
.flatMapMany(r -> Flux.fromIterable(r.resources()))
510+
.flatMapMany(r -> {
511+
List<Resource> l = r.resources();
512+
resourceCount.set(l.size());
513+
return Flux.fromIterable(l);
514+
})
510515
.flatMap(r -> client.readResource(r));
511516

512-
StepVerifier.create(resources).recordWith(ArrayList::new).consumeRecordedWith(readResourceResults -> {
513-
514-
for (ReadResourceResult result : readResourceResults) {
515-
516-
assertThat(result).isNotNull();
517-
assertThat(result.contents()).isNotNull().isNotEmpty();
518-
519-
// Validate each content item
520-
for (ResourceContents content : result.contents()) {
521-
assertThat(content).isNotNull();
522-
assertThat(content.uri()).isNotNull().isNotEmpty();
523-
assertThat(content.mimeType()).isNotNull().isNotEmpty();
524-
525-
// Validate content based on its type with more comprehensive
526-
// checks
527-
switch (content.mimeType()) {
528-
case "text/plain" -> {
529-
TextResourceContents textContent = assertInstanceOf(TextResourceContents.class,
530-
content);
531-
assertThat(textContent.text()).isNotNull().isNotEmpty();
532-
assertThat(textContent.uri()).isNotEmpty();
533-
}
534-
case "application/octet-stream" -> {
535-
BlobResourceContents blobContent = assertInstanceOf(BlobResourceContents.class,
536-
content);
537-
assertThat(blobContent.blob()).isNotNull().isNotEmpty();
538-
assertThat(blobContent.uri()).isNotNull().isNotEmpty();
539-
// Validate base64 encoding format
540-
assertThat(blobContent.blob()).matches("^[A-Za-z0-9+/]*={0,2}$");
541-
}
542-
default -> {
543-
544-
// Still validate basic properties
545-
if (content instanceof TextResourceContents textContent) {
546-
assertThat(textContent.text()).isNotNull();
517+
StepVerifier.create(resources)
518+
.recordWith(ArrayList::new)
519+
.thenConsumeWhile(res -> true)
520+
.consumeRecordedWith(readResourceResults -> {
521+
assertThat(readResourceResults.size()).isEqualTo(resourceCount.get());
522+
for (ReadResourceResult result : readResourceResults) {
523+
524+
assertThat(result).isNotNull();
525+
assertThat(result.contents()).isNotNull().isNotEmpty();
526+
527+
// Validate each content item
528+
for (ResourceContents content : result.contents()) {
529+
assertThat(content).isNotNull();
530+
assertThat(content.uri()).isNotNull().isNotEmpty();
531+
assertThat(content.mimeType()).isNotNull().isNotEmpty();
532+
533+
// Validate content based on its type with more comprehensive
534+
// checks
535+
switch (content.mimeType()) {
536+
case "text/plain" -> {
537+
TextResourceContents textContent = assertInstanceOf(TextResourceContents.class,
538+
content);
539+
assertThat(textContent.text()).isNotNull().isNotEmpty();
540+
assertThat(textContent.uri()).isNotEmpty();
541+
}
542+
case "application/octet-stream" -> {
543+
BlobResourceContents blobContent = assertInstanceOf(BlobResourceContents.class,
544+
content);
545+
assertThat(blobContent.blob()).isNotNull().isNotEmpty();
546+
assertThat(blobContent.uri()).isNotNull().isNotEmpty();
547+
// Validate base64 encoding format
548+
assertThat(blobContent.blob()).matches("^[A-Za-z0-9+/]*={0,2}$");
547549
}
548-
else if (content instanceof BlobResourceContents blobContent) {
549-
assertThat(blobContent.blob()).isNotNull();
550+
default -> {
551+
552+
// Still validate basic properties
553+
if (content instanceof TextResourceContents textContent) {
554+
assertThat(textContent.text()).isNotNull();
555+
}
556+
else if (content instanceof BlobResourceContents blobContent) {
557+
assertThat(blobContent.blob()).isNotNull();
558+
}
550559
}
551560
}
552561
}
553562
}
554-
}
555-
})
556-
.expectNextCount(10) // Expect 10 elements
563+
})
557564
.verifyComplete();
558565
});
559566
}
@@ -693,7 +700,6 @@ void testInitializeWithAllCapabilities() {
693700
assertThat(result.capabilities()).isNotNull();
694701
}).verifyComplete());
695702
}
696-
697703
// ---------------------------------------
698704
// Logging Tests
699705
// ---------------------------------------
@@ -773,7 +779,7 @@ void testSampling() {
773779
if (!(content instanceof McpSchema.TextContent text))
774780
return;
775781

776-
assertThat(text.text()).endsWith(response); // Prefixed
782+
assertThat(text.text()).contains(response);
777783
});
778784

779785
// Verify sampling request parameters received in our callback

mcp-core/src/test/java/io/modelcontextprotocol/client/AbstractMcpSyncClientTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ void testSampling() {
625625
if (!(content instanceof McpSchema.TextContent text))
626626
return;
627627

628-
assertThat(text.text()).endsWith(response); // Prefixed
628+
assertThat(text.text()).contains(response);
629629
});
630630

631631
// Verify sampling request parameters received in our callback

mcp-core/src/test/java/io/modelcontextprotocol/client/HttpClientStreamableHttpAsyncClientTests.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@ public class HttpClientStreamableHttpAsyncClientTests extends AbstractMcpAsyncCl
1717

1818
private static String host = "http://localhost:3001";
1919

20-
// Uses the https://github.com/tzolov/mcp-everything-server-docker-image
2120
@SuppressWarnings("resource")
22-
static GenericContainer<?> container = new GenericContainer<>("docker.io/tzolov/mcp-everything-server:v3")
23-
.withCommand("node dist/index.js streamableHttp")
21+
static GenericContainer<?> container = new GenericContainer<>("docker.io/node:lts-alpine3.23")
22+
.withCommand("npx -y @modelcontextprotocol/server-everything@2025.12.18 streamableHttp")
2423
.withLogConsumer(outputFrame -> System.out.println(outputFrame.getUtf8String()))
2524
.withExposedPorts(3001)
2625
.waitingFor(Wait.forHttp("/").forStatusCode(404));

mcp-core/src/test/java/io/modelcontextprotocol/client/HttpClientStreamableHttpSyncClientTests.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@ public class HttpClientStreamableHttpSyncClientTests extends AbstractMcpSyncClie
3030

3131
static String host = "http://localhost:3001";
3232

33-
// Uses the https://github.com/tzolov/mcp-everything-server-docker-image
3433
@SuppressWarnings("resource")
35-
static GenericContainer<?> container = new GenericContainer<>("docker.io/tzolov/mcp-everything-server:v3")
36-
.withCommand("node dist/index.js streamableHttp")
34+
static GenericContainer<?> container = new GenericContainer<>("docker.io/node:lts-alpine3.23")
35+
.withCommand("npx -y @modelcontextprotocol/server-everything@2025.12.18 streamableHttp")
3736
.withLogConsumer(outputFrame -> System.out.println(outputFrame.getUtf8String()))
3837
.withExposedPorts(3001)
3938
.waitingFor(Wait.forHttp("/").forStatusCode(404));

mcp-core/src/test/java/io/modelcontextprotocol/client/HttpSseMcpAsyncClientLostConnectionTests.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ public class HttpSseMcpAsyncClientLostConnectionTests {
3636
static Network network = Network.newNetwork();
3737
static String host = "http://localhost:3001";
3838

39-
// Uses the https://github.com/tzolov/mcp-everything-server-docker-image
4039
@SuppressWarnings("resource")
41-
static GenericContainer<?> container = new GenericContainer<>("docker.io/tzolov/mcp-everything-server:v3")
42-
.withCommand("node dist/index.js sse")
40+
static GenericContainer<?> container = new GenericContainer<>("docker.io/node:lts-alpine3.23")
41+
.withCommand("npx -y @modelcontextprotocol/server-everything@2025.12.18 sse")
4342
.withLogConsumer(outputFrame -> System.out.println(outputFrame.getUtf8String()))
4443
.withNetwork(network)
4544
.withNetworkAliases("everything-server")

mcp-core/src/test/java/io/modelcontextprotocol/client/HttpSseMcpAsyncClientTests.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ class HttpSseMcpAsyncClientTests extends AbstractMcpAsyncClientTests {
2323

2424
private static String host = "http://localhost:3004";
2525

26< 1004E /td>-
// Uses the https://github.com/tzolov/mcp-everything-server-docker-image
2726
@SuppressWarnings("resource")
28-
static GenericContainer<?> container = new GenericContainer<>("docker.io/tzolov/mcp-everything-server:v3")
29-
.withCommand("node dist/index.js sse")
27+
static GenericContainer<?> container = new GenericContainer<>("docker.io/node:lts-alpine3.23")
28+
.withCommand("npx -y @modelcontextprotocol/server-everything@2025.12.18 sse")
3029
.withLogConsumer(outputFrame -> System.out.println(outputFrame.getUtf8String()))
3130
.withExposedPorts(3001)
3231
.waitingFor(Wait.forHttp("/").forStatusCode(404));

mcp-core/src/test/java/io/modelcontextprotocol/client/HttpSseMcpSyncClientTests.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ class HttpSseMcpSyncClientTests extends AbstractMcpSyncClientTests {
3636

3737
static String host = "http://localhost:3003";
3838

39-
// Uses the https://github.com/tzolov/mcp-everything-server-docker-image
4039
@SuppressWarnings("resource")
41-
static GenericContainer<?> container = new GenericContainer<>("docker.io/tzolov/mcp-everything-server:v3")
42-
.withCommand("node dist/index.js sse")
40+
static GenericContainer<?> container = new GenericContainer<>("docker.io/node:lts-alpine3.23")
41+
.withCommand("npx -y @modelcontextprotocol/server-everything@2025.12.18 sse")
4342
.withLogConsumer(outputFrame -> System.out.println(outputFrame.getUtf8String()))
4443
.withExposedPorts(3001)
4544
.waitingFor(Wait.forHttp("/").forStatusCode(404));

mcp-core/src/test/java/io/modelcontextprotocol/client/ServerParameterUtils.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ private ServerParameterUtils() {
1010
public static ServerParameters createServerParameters() {
1111
if (System.getProperty("os.name").toLowerCase().contains("win")) {
1212
return ServerParameters.builder("cmd.exe")
13-
.args("/c", "npx.cmd", "-y", "@modelcontextprotocol/server-everything", "stdio")
13+
.args("/c", "npx.cmd", "-y", "@modelcontextprotocol/server-everything@2025.12.18", "stdio")
1414
.build();
1515
}
16-
return ServerParameters.builder("npx").args("-y", "@modelcontextprotocol/server-everything", "stdio").build();
16+
return ServerParameters.builder("npx")
17+
.args("-y", "@modelcontextprotocol/server-everything@2025.12.18", "stdio")
18+
.build();
1719
}
1820

1921
}

0 commit comments

Comments
 (0)
0