Skip to content

Commit c0e3129

Browse files
committed
WIP: Sync server builder tests
Signed-off-by: Dariusz Jędrzejczyk <[email protected]>
1 parent 92ca81f commit c0e3129

File tree

5 files changed

+159
-120
lines changed

5 files changed

+159
-120
lines changed

mcp-spring/mcp-spring-webflux/src/test/java/io/modelcontextprotocol/server/WebFluxSseMcpSyncServerTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ class WebFluxSseMcpSyncServerTests extends AbstractMcpSyncServerTests {
3232
private WebFluxSseServerTransportProvider transportProvider;
3333

3434
@Override
35-
protected McpServerTransportProvider createMcpTransportProvider() {
35+
protected McpServer.SyncSpecification<?> prepareSyncServerBuilder() {
36+
return McpServer.sync(createMcpTransportProvider());
37+
}
38+
39+
private McpServerTransportProvider createMcpTransportProvider() {
3640
transportProvider = new WebFluxSseServerTransportProvider.Builder().objectMapper(new ObjectMapper())
3741
.messageEndpoint(MESSAGE_ENDPOINT)
3842
.build();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2024-2024 the original author or authors.
3+
*/
4+
5+
package io.modelcontextprotocol.server;
6+
7+
import com.fasterxml.jackson.databind.ObjectMapper;
8+
import io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider;
9+
import io.modelcontextprotocol.server.transport.WebFluxStreamableServerTransportProvider;
10+
import io.modelcontextprotocol.spec.McpStreamableServerTransportProvider;
11+
import org.junit.jupiter.api.Timeout;
12+
import org.springframework.http.server.reactive.HttpHandler;
13+
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
14+
import org.springframework.web.reactive.function.server.RouterFunctions;
15+
import reactor.netty.DisposableServer;
16+
import reactor.netty.http.server.HttpServer;
17+
18+
/**
19+
* Tests for {@link McpAsyncServer} using {@link WebFluxSseServerTransportProvider}.
20+
*
21+
* @author Christian Tzolov
22+
*/
23+
@Timeout(15) // Giving extra time beyond the client timeout
24+
class WebFluxStreamableMcpSyncServerTests extends AbstractMcpSyncServerTests {
25+
26+
private static final int PORT = TestUtil.findAvailablePort();
27+
28+
private static final String MESSAGE_ENDPOINT = "/mcp/message";
29+
30+
private DisposableServer httpServer;
31+
32+
private McpStreamableServerTransportProvider createMcpTransportProvider() {
33+
var transportProvider = new WebFluxStreamableServerTransportProvider(new ObjectMapper(), MESSAGE_ENDPOINT);
34+
35+
HttpHandler httpHandler = RouterFunctions.toHttpHandler(transportProvider.getRouterFunction());
36+
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
37+
httpServer = HttpServer.create().port(PORT).handle(adapter).bindNow();
38+
return transportProvider;
39+
}
40+
41+
@Override
42+
protected McpServer.SyncSpecification<?> prepareSyncServerBuilder() {
43+
return McpServer.sync(createMcpTransportProvider());
44+
}
45+
46+
@Override
47+
protected void onStart() {
48+
}
49+
50+
@Override
51+
protected void onClose() {
52+
if (httpServer != null) {
53+
httpServer.disposeNow();
54+
}
55+
}
56+
57+
}

mcp-spring/mcp-spring-webmvc/src/test/java/io/modelcontextprotocol/server/WebMvcSseSyncServerTransportTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ public RouterFunction<ServerResponse> routerFunction(WebMvcSseServerTransportPro
4949
private AnnotationConfigWebApplicationContext appContext;
5050

5151
@Override
52-
protected WebMvcSseServerTransportProvider createMcpTransportProvider() {
52+
protected McpServer.SyncSpecification<?> prepareSyncServerBuilder() {
53+
return McpServer.sync(createMcpTransportProvider());
54+
}
55+
56+
private WebMvcSseServerTransportProvider createMcpTransportProvider() {
5357
// Set up Tomcat first
5458
tomcat = new Tomcat();
5559
tomcat.setPort(PORT);

mcp-test/src/main/java/io/modelcontextprotocol/server/AbstractMcpSyncServerTests.java

Lines changed: 31 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public abstract class AbstractMcpSyncServerTests {
4040

4141
private static final String TEST_PROMPT_NAME = "test-prompt";
4242

43-
abstract protected McpServerTransportProvider createMcpTransportProvider();
43+
abstract protected McpServer.SyncSpecification<?> prepareSyncServerBuilder();
4444

4545
protected void onStart() {
4646
}
@@ -68,28 +68,28 @@ void testConstructorWithInvalidArguments() {
6868
.isInstanceOf(IllegalArgumentException.class)
6969
.hasMessage("Transport provider must not be null");
7070

71-
assertThatThrownBy(() -> McpServer.sync(createMcpTransportProvider()).serverInfo(null))
71+
assertThatThrownBy(() -> prepareSyncServerBuilder().serverInfo(null))
7272
.isInstanceOf(IllegalArgumentException.class)
7373
.hasMessage("Server info must not be null");
7474
}
7575

7676
@Test
7777
void testGracefulShutdown() {
78-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider()).serverInfo("test-server", "1.0.0").build();
78+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
7979

8080
assertThatCode(() -> mcpSyncServer.closeGracefully()).doesNotThrowAnyException();
8181
}
8282

8383
@Test
8484
void testImmediateClose() {
85-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider()).serverInfo("test-server", "1.0.0").build();
85+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
8686

8787
assertThatCode(() -> mcpSyncServer.close()).doesNotThrowAnyException();
8888
}
8989

9090
@Test
9191
void testGetAsyncServer() {
92-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider()).serverInfo("test-server", "1.0.0").build();
92+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
9393

9494
assertThat(mcpSyncServer.getAsyncServer()).isNotNull();
9595

@@ -111,8 +111,7 @@ void testGetAsyncServer() {
111111
@Test
112112
@Deprecated
113113
void testAddTool() {
114-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider())
115-
.serverInfo("test-server", "1.0.0")
114+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
116115
.capabilities(ServerCapabilities.builder().tools(true).build())
117116
.build();
118117

@@ -126,8 +125,7 @@ void testAddTool() {
126125

127126
@Test
128127
void testAddToolCall() {
129-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider())
130-
.serverInfo("test-server", "1.0.0")
128+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
131129
.capabilities(ServerCapabilities.builder().tools(true).build())
132130
.build();
133131

@@ -145,8 +143,7 @@ void testAddToolCall() {
145143
void testAddDuplicateTool() {
146144
Tool duplicateTool = new McpSchema.Tool(TEST_TOOL_NAME, "Duplicate tool", emptyJsonSchema);
147145

148-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider())
149-
.serverInfo("test-server", "1.0.0")
146+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
150147
.capabilities(ServerCapabilities.builder().tools(true).build())
151148
.tool(duplicateTool, (exchange, args) -> new CallToolResult(List.of(), false))
152149
.build();
@@ -163,8 +160,7 @@ void testAddDuplicateTool() {
163160
void testAddDuplicateToolCall() {
164161
Tool duplicateTool = new McpSchema.Tool(TEST_TOOL_NAME, "Duplicate tool", emptyJsonSchema);
165162

166-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider())
167-
.serverInfo("test-server", "1.0.0")
163+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
168164
.capabilities(ServerCapabilities.builder().tools(true).build())
169165
.toolCall(duplicateTool, (exchange, request) -> new CallToolResult(List.of(), false))
170166
.build();
@@ -183,8 +179,7 @@ void testDuplicateToolCallDuringBuilding() {
183179
Tool duplicateTool = new Tool("duplicate-build-toolcall", "Duplicate toolcall during building",
184180
emptyJsonSchema);
185181

186-
assertThatThrownBy(() -> McpServer.sync(createMcpTransportProvider())
187-
.serverInfo("test-server", "1.0.0")
182+
assertThatThrownBy(() -> prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
188183
.capabilities(ServerCapabilities.builder().tools(true).build())
189184
.toolCall(duplicateTool, (exchange, request) -> new CallToolResult(List.of(), false))
190185
.toolCall(duplicateTool, (exchange, request) -> new CallToolResult(List.of(), false)) // Duplicate!
@@ -206,8 +201,7 @@ void testDuplicateToolsInBatchListRegistration() {
206201
.build() // Duplicate!
207202
);
208203

209-
assertThatThrownBy(() -> McpServer.sync(createMcpTransportProvider())
210-
.serverInfo("test-server", "1.0.0")
204+
assertThatThrownBy(() -> prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
211205
.capabilities(ServerCapabilities.builder().tools(true).build())
212206
.tools(specs)
213207
.build()).isInstanceOf(IllegalArgumentException.class)
@@ -218,8 +212,7 @@ void testDuplicateToolsInBatchListRegistration() {
218212
void testDuplicateToolsInBatchVarargsRegistration() {
219213
Tool duplicateTool = new Tool("batch-varargs-tool", "Duplicate tool in batch varargs", emptyJsonSchema);
220214

221-
assertThatThrownBy(() -> McpServer.sync(createMcpTransportProvider())
222-
.serverInfo("test-server", "1.0.0")
215+
assertThatThrownBy(() -> prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
223216
.capabilities(ServerCapabilities.builder().tools(true).build())
224217
.tools(McpServerFeatures.SyncToolSpecification.builder()
225218
.tool(duplicateTool)
@@ -238,8 +231,7 @@ void testDuplicateToolsInBatchVarargsRegistration() {
238231
void testRemoveTool() {
239232
Tool tool = new McpSchema.Tool(TEST_TOOL_NAME, "Test tool", emptyJsonSchema);
240233

241-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider())
242-
.serverInfo("test-server", "1.0.0")
234+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
243235
.capabilities(ServerCapabilities.builder().tools(true).build())
244236
.toolCall(tool, (exchange, args) -> new CallToolResult(List.of(), false))
245237
.build();
@@ -251,8 +243,7 @@ void testRemoveTool() {
251243

252244
@Test
253245
void testRemoveNonexistentTool() {
254-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider())
255-
.serverInfo("test-server", "1.0.0")
246+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
256247
.capabilities(ServerCapabilities.builder().tools(true).build())
257248
.build();
258249

@@ -264,7 +255,7 @@ void testRemoveNonexistentTool() {
264255

265256
@Test
266257
void testNotifyToolsListChanged() {
267-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider()).serverInfo("test-server", "1.0.0").build();
258+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
268259

269260
assertThatCode(() -> mcpSyncServer.notifyToolsListChanged()).doesNotThrowAnyException();
270261

@@ -277,7 +268,7 @@ void testNotifyToolsListChanged() {
277268

278269
@Test
279270
void testNotifyResourcesListChanged() {
280-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider()).serverInfo("test-server", "1.0.0").build();
271+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
281272

282273
assertThatCode(() -> mcpSyncServer.notifyResourcesListChanged()).doesNotThrowAnyException();
283274

@@ -286,7 +277,7 @@ void testNotifyResourcesListChanged() {
286277

287278
@Test
288279
void testNotifyResourcesUpdated() {
289-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider()).serverInfo("test-server", "1.0.0").build();
280+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
290281

291282
assertThatCode(() -> mcpSyncServer
292283
.notifyResourcesUpdated(new McpSchema.ResourcesUpdatedNotification(TEST_RESOURCE_URI)))
@@ -297,8 +288,7 @@ void testNotifyResourcesUpdated() {
297288

298289
@Test
299290
void testAddResource() {
300-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider())
301-
.serverInfo("test-server", "1.0.0")
291+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
302292
.capabilities(ServerCapabilities.builder().resources(true, false).build())
303293
.build();
304294

@@ -314,8 +304,7 @@ void testAddResource() {
314304

315305
@Test
316306
void testAddResourceWithNullSpecification() {
317-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider())
318-
.serverInfo("test-server", "1.0.0")
307+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
319308
.capabilities(ServerCapabilities.builder().resources(true, false).build())
320309
.build();
321310

@@ -328,9 +317,7 @@ void testAddResourceWithNullSpecification() {
328317

329318
@Test
330319
void testAddResourceWithoutCapability() {
331-
var serverWithoutResources = McpServer.sync(createMcpTransportProvider())
332-
.serverInfo("test-server", "1.0.0")
333-
.build();
320+
var serverWithoutResources = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
334321

335322
Resource resource = new Resource(TEST_RESOURCE_URI, "Test Resource", "text/plain", "Test resource description",
336323
null);
@@ -343,9 +330,7 @@ void testAddResourceWithoutCapability() {
343330

344331
@Test
345332
void testRemoveResourceWithoutCapability() {
346-
var serverWithoutResources = McpServer.sync(createMcpTransportProvider())
347-
.serverInfo("test-server", "1.0.0")
348-
.build();
333+
var serverWithoutResources = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
349334

350335
assertThatThrownBy(() -> serverWithoutResources.removeResource(TEST_RESOURCE_URI)).isInstanceOf(McpError.class)
351336
.hasMessage("Server must be configured with resource capabilities");
@@ -357,7 +342,7 @@ void testRemoveResourceWithoutCapability() {
357342

358343
@Test
359344
void testNotifyPromptsListChanged() {
360-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider()).serverInfo("test-server", "1.0.0").build();
345+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
361346

362347
assertThatCode(() -> mcpSyncServer.notifyPromptsListChanged()).doesNotThrowAnyException();
363348

@@ -366,8 +351,7 @@ void testNotifyPromptsListChanged() {
366351

367352
@Test
368353
void testAddPromptWithNullSpecification() {
369-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider())
370-
.serverInfo("test-server", "1.0.0")
354+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
371355
.capabilities(ServerCapabilities.builder().prompts(false).build())
372356
.build();
373357

@@ -378,9 +362,7 @@ void testAddPromptWithNullSpecification() {
378362

379363
@Test
380364
void testAddPromptWithoutCapability() {
381-
var serverWithoutPrompts = McpServer.sync(createMcpTransportProvider())
382-
.serverInfo("test-server", "1.0.0")
383-
.build();
365+
var serverWithoutPrompts = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
384366

385367
Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", "Test Prompt", List.of());
386368
McpServerFeatures.SyncPromptSpecification specification = new McpServerFeatures.SyncPromptSpecification(prompt,
@@ -393,9 +375,7 @@ void testAddPromptWithoutCapability() {
393375

394376
@Test
395377
void testRemovePromptWithoutCapability() {
396-
var serverWithoutPrompts = McpServer.sync(createMcpTransportProvider())
397-
.serverInfo("test-server", "1.0.0")
398-
.build();
378+
var serverWithoutPrompts = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
399379

400380
assertThatThrownBy(() -> serverWithoutPrompts.removePrompt(TEST_PROMPT_NAME)).isInstanceOf(McpError.class)
401381
.hasMessage("Server must be configured with prompt capabilities");
@@ -408,8 +388,7 @@ void testRemovePrompt() {
408388
(exchange, req) -> new GetPromptResult("Test prompt description", List
409389
.of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content")))));
410390

411-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider())
412-
.serverInfo("test-server", "1.0.0")
391+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
413392
.capabilities(ServerCapabilities.builder().prompts(true).build())
414393
.prompts(specification)
415394
.build();
@@ -421,8 +400,7 @@ void testRemovePrompt() {
421400

422401
@Test
423402
void testRemoveNonexistentPrompt() {
424-
var mcpSyncServer = McpServer.sync(createMcpTransportProvider())
425-
.serverInfo("test-server", "1.0.0")
403+
var mcpSyncServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
426404
.capabilities(ServerCapabilities.builder().prompts(true).build())
427405
.build();
428406

@@ -442,8 +420,7 @@ void testRootsChangeHandlers() {
442420
var rootsReceived = new McpSchema.Root[1];
443421
var consumerCalled = new boolean[1];
444422

445-
var singleConsumerServer = McpServer.sync(createMcpTransportProvider())
446-
.serverInfo("test-server", "1.0.0")
423+
var singleConsumerServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
447424
.rootsChangeHandlers(List.of((exchange, roots) -> {
448425
consumerCalled[0] = true;
449426
if (!roots.isEmpty()) {
@@ -461,8 +438,7 @@ void testRootsChangeHandlers() {
461438
var consumer2Called = new boolean[1];
462439
var rootsContent = new List[1];
463440

464-
var multipleConsumersServer = McpServer.sync(createMcpTransportProvider())
465-
.serverInfo("test-server", "1.0.0")
441+
var multipleConsumersServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
466442
.rootsChangeHandlers(List.of((exchange, roots) -> {
467443
consumer1Called[0] = true;
468444
rootsContent[0] = roots;
@@ -474,8 +450,7 @@ void testRootsChangeHandlers() {
474450
onClose();
475451

476452
// Test error handling
477-
var errorHandlingServer = McpServer.sync(createMcpTransportProvider())
478-
.serverInfo("test-server", "1.0.0")
453+
var errorHandlingServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
479454
.rootsChangeHandlers(List.of((exchange, roots) -> {
480455
throw new RuntimeException("Test error");
481456
}))
@@ -486,7 +461,7 @@ void testRootsChangeHandlers() {
486461
onClose();
487462

488463
// Test without consumers
489-
var noConsumersServer = McpServer.sync(createMcpTransportProvider()).serverInfo("test-server", "1.0.0").build();
464+
var noConsumersServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0").build();
490465

491466
assertThat(noConsumersServer).isNotNull();
492467
assertThatCode(() -> noConsumersServer.closeGracefully()).doesNotThrowAnyException();

0 commit comments

Comments
 (0)