diff --git a/mcp-test/src/main/java/io/modelcontextprotocol/AbstractMcpClientServerIntegrationTests.java b/mcp-test/src/main/java/io/modelcontextprotocol/AbstractMcpClientServerIntegrationTests.java index 300f0b534..c0e2509c9 100644 --- a/mcp-test/src/main/java/io/modelcontextprotocol/AbstractMcpClientServerIntegrationTests.java +++ b/mcp-test/src/main/java/io/modelcontextprotocol/AbstractMcpClientServerIntegrationTests.java @@ -91,7 +91,9 @@ void simple(String clientType) { assertThat(client.initialize()).isNotNull(); } - server.closeGracefully(); + finally { + server.closeGracefully().block(); + } } // --------------------------------------- @@ -128,7 +130,9 @@ void testCreateMessageWithoutSamplingCapabilities(String clientType) { .hasMessage("Client must be configured with sampling capabilities"); } } - server.closeGracefully(); + finally { + server.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -195,7 +199,9 @@ void testCreateMessageSuccess(String clientType) { assertThat(result.stopReason()).isEqualTo(CreateMessageResult.StopReason.STOP_SEQUENCE); }); } - mcpServer.close(); + finally { + mcpServer.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -219,11 +225,6 @@ void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws Interr CreateMessageResult.StopReason.STOP_SEQUENCE); }; - var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) - .capabilities(ClientCapabilities.builder().sampling().build()) - .sampling(samplingHandler) - .build(); - // Server CallToolResult callResponse = new McpSchema.CallToolResult(List.of(new McpSchema.TextContent("CALL RESPONSE")), @@ -256,26 +257,31 @@ void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws Interr .requestTimeout(Duration.ofSeconds(4)) .tools(tool) .build(); + try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) + .capabilities(ClientCapabilities.builder().sampling().build()) + .sampling(samplingHandler) + .build()) { - InitializeResult initResult = mcpClient.initialize(); - assertThat(initResult).isNotNull(); + InitializeResult initResult = mcpClient.initialize(); + assertThat(initResult).isNotNull(); - CallToolResult response = mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); + CallToolResult response = mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); - assertThat(response).isNotNull(); - assertThat(response).isEqualTo(callResponse); + assertThat(response).isNotNull(); + assertThat(response).isEqualTo(callResponse); - assertWith(samplingResult.get(), result -> { - assertThat(result).isNotNull(); - assertThat(result.role()).isEqualTo(Role.USER); - assertThat(result.content()).isInstanceOf(McpSchema.TextContent.class); - assertThat(((McpSchema.TextContent) result.content()).text()).isEqualTo("Test message"); - assertThat(result.model()).isEqualTo("MockModelName"); - assertThat(result.stopReason()).isEqualTo(CreateMessageResult.StopReason.STOP_SEQUENCE); - }); - - mcpClient.close(); - mcpServer.close(); + assertWith(samplingResult.get(), result -> { + assertThat(result).isNotNull(); + assertThat(result.role()).isEqualTo(Role.USER); + assertThat(result.content()).isInstanceOf(McpSchema.TextContent.class); + assertThat(((McpSchema.TextContent) result.content()).text()).isEqualTo("Test message"); + assertThat(result.model()).isEqualTo("MockModelName"); + assertThat(result.stopReason()).isEqualTo(CreateMessageResult.StopReason.STOP_SEQUENCE); + }); + } + finally { + mcpServer.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -297,11 +303,6 @@ void testCreateMessageWithRequestTimeoutFail(String clientType) throws Interrupt CreateMessageResult.StopReason.STOP_SEQUENCE); }; - var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) - .capabilities(ClientCapabilities.builder().sampling().build()) - .sampling(samplingHandler) - .build(); - CallToolResult callResponse = new McpSchema.CallToolResult(List.of(new McpSchema.TextContent("CALL RESPONSE")), null); @@ -329,15 +330,21 @@ void testCreateMessageWithRequestTimeoutFail(String clientType) throws Interrupt .tools(tool) .build(); - InitializeResult initResult = mcpClient.initialize(); - assertThat(initResult).isNotNull(); + try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) + .capabilities(ClientCapabilities.builder().sampling().build()) + .sampling(samplingHandler) + .build()) { - assertThatExceptionOfType(McpError.class).isThrownBy(() -> { - mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); - }).withMessageContaining("1000ms"); + InitializeResult initResult = mcpClient.initialize(); + assertThat(initResult).isNotNull(); - mcpClient.close(); - mcpServer.close(); + assertThatExceptionOfType(McpError.class).isThrownBy(() -> { + mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); + }).withMessageContaining("1000ms"); + } + finally { + mcpServer.closeGracefully().block(); + } } // --------------------------------------- @@ -370,7 +377,9 @@ void testCreateElicitationWithoutElicitationCapabilities(String clientType) { .hasMessage("Client must be configured with elicitation capabilities"); } } - server.closeGracefully().block(); + finally { + server.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -425,7 +434,9 @@ void testCreateElicitationSuccess(String clientType) { assertThat(response).isNotNull(); assertThat(response).isEqualTo(callResponse); } - mcpServer.closeGracefully().block(); + finally { + mcpServer.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -440,11 +451,6 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) { return new ElicitResult(ElicitResult.Action.ACCEPT, Map.of("message", request.message())); }; - var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) - .capabilities(ClientCapabilities.builder().elicitation().build()) - .elicitation(elicitationHandler) - .build(); - CallToolResult callResponse = new McpSchema.CallToolResult(List.of(new McpSchema.TextContent("CALL RESPONSE")), null); @@ -471,21 +477,27 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) { .tools(tool) .build(); - InitializeResult initResult = mcpClient.initialize(); - assertThat(initResult).isNotNull(); + try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) + .capabilities(ClientCapabilities.builder().elicitation().build()) + .elicitation(elicitationHandler) + .build()) { - CallToolResult response = mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); + InitializeResult initResult = mcpClient.initialize(); + assertThat(initResult).isNotNull(); - assertThat(response).isNotNull(); - assertThat(response).isEqualTo(callResponse); - assertWith(resultRef.get(), result -> { - assertThat(result).isNotNull(); - assertThat(result.action()).isEqualTo(McpSchema.ElicitResult.Action.ACCEPT); - assertThat(result.content().get("message")).isEqualTo("Test message"); - }); + CallToolResult response = mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); - mcpClient.closeGracefully(); - mcpServer.closeGracefully().block(); + assertThat(response).isNotNull(); + assertThat(response).isEqualTo(callResponse); + assertWith(resultRef.get(), result -> { + assertThat(result).isNotNull(); + assertThat(result.action()).isEqualTo(McpSchema.ElicitResult.Action.ACCEPT); + assertThat(result.content().get("message")).isEqualTo("Test message"); + }); + } + finally { + mcpServer.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -511,11 +523,6 @@ void testCreateElicitationWithRequestTimeoutFail(String clientType) { return new ElicitResult(ElicitResult.Action.ACCEPT, Map.of("message", request.message())); }; - var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) - .capabilities(ClientCapabilities.builder().elicitation().build()) - .elicitation(elicitationHandler) - .build(); - CallToolResult callResponse = new CallToolResult(List.of(new McpSchema.TextContent("CALL RESPONSE")), null); AtomicReference resultRef = new AtomicReference<>(); @@ -541,18 +548,24 @@ void testCreateElicitationWithRequestTimeoutFail(String clientType) { .tools(tool) .build(); - InitializeResult initResult = mcpClient.initialize(); - assertThat(initResult).isNotNull(); + try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) + .capabilities(ClientCapabilities.builder().elicitation().build()) + .elicitation(elicitationHandler) + .build()) { - assertThatExceptionOfType(McpError.class).isThrownBy(() -> { - mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); - }).withMessageContaining("within 1000ms"); + InitializeResult initResult = mcpClient.initialize(); + assertThat(initResult).isNotNull(); - ElicitResult elicitResult = resultRef.get(); - assertThat(elicitResult).isNull(); + assertThatExceptionOfType(McpError.class).isThrownBy(() -> { + mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); + }).withMessageContaining("within 1000ms"); - mcpClient.closeGracefully(); - mcpServer.closeGracefully().block(); + ElicitResult elicitResult = resultRef.get(); + assertThat(elicitResult).isNull(); + } + finally { + mcpServer.closeGracefully().block(); + } } // --------------------------------------- @@ -601,8 +614,9 @@ void testRootsSuccess(String clientType) { assertThat(rootsRef.get()).containsAll(List.of(roots.get(1), root3)); }); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -639,8 +653,9 @@ void testRootsWithoutCapability(String clientType) { assertThat(e).isInstanceOf(McpError.class).hasMessage("Roots not supported"); } } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -668,8 +683,9 @@ void testRootsNotificationWithEmptyRootsList(String clientType) { assertThat(rootsRef.get()).isEmpty(); }); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -701,8 +717,9 @@ void testRootsWithMultipleHandlers(String clientType) { assertThat(rootsRef2.get()).containsAll(roots); }); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -732,8 +749,9 @@ void testRootsServerCloseWithActiveSubscription(String clientType) { assertThat(rootsRef.get()).containsAll(roots); }); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } // --------------------------------------- @@ -793,8 +811,9 @@ void testToolCallSuccess(String clientType) { assertThat(responseBodyIsNullOrBlank.get()).isFalse(); assertThat(response).isNotNull().isEqualTo(callResponse); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -830,8 +849,9 @@ void testThrowingToolCallIsCaughtBeforeTimeout(String clientType) { .isThrownBy(() -> mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of()))) .withMessageContaining("Timeout on blocking read"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -886,8 +906,9 @@ void testToolCallSuccessWithTranportContextExtraction(String clientType) { assertThat(responseBodyIsNullOrBlank.get()).isFalse(); assertThat(response).isNotNull().isEqualTo(expectedCallResponse); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -978,8 +999,9 @@ void testToolListChangeHandlingSuccess(String clientType) { assertThat(toolsRef.get()).containsAll(List.of(tool2.tool())); }); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -995,8 +1017,9 @@ void testInitialize(String clientType) { InitializeResult initResult = mcpClient.initialize(); assertThat(initResult).isNotNull(); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } // --------------------------------------- @@ -1107,7 +1130,9 @@ void testLoggingNotification(String clientType) throws InterruptedException { assertThat(notificationMap.get("Another error message").logger()).isEqualTo("test-logger"); assertThat(notificationMap.get("Another error message").data()).isEqualTo("Another error message"); } - mcpServer.close(); + finally { + mcpServer.closeGracefully().block(); + } } // --------------------------------------- @@ -1212,7 +1237,7 @@ void testProgressNotification(String clientType) throws InterruptedException { assertThat(notificationMap.get("Processing completed").message()).isEqualTo("Processing completed"); } finally { - mcpServer.close(); + mcpServer.closeGracefully().block(); } } @@ -1262,8 +1287,9 @@ void testCompletionShouldReturnExpectedSuggestions(String clientType) { assertThat(samplingRequest.get().argument().value()).isEqualTo("py"); assertThat(samplingRequest.get().ref().type()).isEqualTo("ref/prompt"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } // --------------------------------------- @@ -1324,8 +1350,9 @@ void testPingSuccess(String clientType) { // Verify execution order assertThat(executionOrder.get()).isEqualTo("123"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully().block(); + } } // --------------------------------------- @@ -1400,8 +1427,9 @@ void testStructuredOutputValidationSuccess(String clientType) { .isEqualTo(json(""" {"result":5.0,"operation":"2 + 3","timestamp":"2024-01-01T10:00:00Z"}""")); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -1454,8 +1482,9 @@ void testStructuredOutputValidationFailure(String clientType) { String errorMessage = ((McpSchema.TextContent) response.content().get(0)).text(); assertThat(errorMessage).contains("Validation failed"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -1504,8 +1533,9 @@ void testStructuredOutputMissingStructuredContent(String clientType) { assertThat(errorMessage).isEqualTo( "Response missing structured content which is expected when calling tool with non-empty outputSchema"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -1581,8 +1611,9 @@ void testStructuredOutputRuntimeToolAddition(String clientType) { .isEqualTo(json(""" {"count":3,"message":"Dynamic execution"}""")); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } private double evaluateExpression(String expression) { diff --git a/mcp-test/src/main/java/io/modelcontextprotocol/AbstractStatelessIntegrationTests.java b/mcp-test/src/main/java/io/modelcontextprotocol/AbstractStatelessIntegrationTests.java index 618247d61..777e12a9c 100644 --- a/mcp-test/src/main/java/io/modelcontextprotocol/AbstractStatelessIntegrationTests.java +++ b/mcp-test/src/main/java/io/modelcontextprotocol/AbstractStatelessIntegrationTests.java @@ -66,7 +66,9 @@ void simple(String clientType) { assertThat(client.initialize()).isNotNull(); } - server.closeGracefully(); + finally { + server.closeGracefully().block(); + } } // --------------------------------------- @@ -126,8 +128,9 @@ void testToolCallSuccess(String clientType) { assertThat(response).isNotNull().isEqualTo(callResponse); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -163,8 +166,9 @@ void testThrowingToolCallIsCaughtBeforeTimeout(String clientType) { .isThrownBy(() -> mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of()))) .withMessageContaining("Timeout on blocking read"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -244,8 +248,9 @@ void testToolListChangeHandlingSuccess(String clientType) { mcpServer.addTool(tool2); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -261,8 +266,9 @@ void testInitialize(String clientType) { InitializeResult initResult = mcpClient.initialize(); assertThat(initResult).isNotNull(); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } // --------------------------------------- @@ -339,8 +345,9 @@ void testStructuredOutputValidationSuccess(String clientType) { .isEqualTo(json(""" {"result":5.0,"operation":"2 + 3","timestamp":"2024-01-01T10:00:00Z"}""")); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -394,8 +401,9 @@ void testStructuredOutputValidationFailure(String clientType) { String errorMessage = ((McpSchema.TextContent) response.content().get(0)).text(); assertThat(errorMessage).contains("Validation failed"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -444,8 +452,9 @@ void testStructuredOutputMissingStructuredContent(String clientType) { assertThat(errorMessage).isEqualTo( "Response missing structured content which is expected when calling tool with non-empty outputSchema"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -521,8 +530,9 @@ void testStructuredOutputRuntimeToolAddition(String clientType) { .isEqualTo(json(""" {"count":3,"message":"Dynamic execution"}""")); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } private double evaluateExpression(String expression) { diff --git a/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpClientServerIntegrationTests.java b/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpClientServerIntegrationTests.java index f99edaf95..2e1a12a95 100644 --- a/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpClientServerIntegrationTests.java +++ b/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpClientServerIntegrationTests.java @@ -87,7 +87,9 @@ void simple(String clientType) { assertThat(client.initialize()).isNotNull(); } - server.closeGracefully(); + finally { + server.closeGracefully().block(); + } } // --------------------------------------- @@ -124,7 +126,9 @@ void testCreateMessageWithoutSamplingCapabilities(String clientType) { .hasMessage("Client must be configured with sampling capabilities"); } } - server.closeGracefully(); + finally { + server.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -191,7 +195,9 @@ void testCreateMessageSuccess(String clientType) { assertThat(result.stopReason()).isEqualTo(CreateMessageResult.StopReason.STOP_SEQUENCE); }); } - mcpServer.close(); + finally { + mcpServer.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -215,11 +221,6 @@ void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws Interr CreateMessageResult.StopReason.STOP_SEQUENCE); }; - var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) - .capabilities(ClientCapabilities.builder().sampling().build()) - .sampling(samplingHandler) - .build(); - // Server CallToolResult callResponse = new McpSchema.CallToolResult(List.of(new McpSchema.TextContent("CALL RESPONSE")), @@ -252,26 +253,31 @@ void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws Interr .requestTimeout(Duration.ofSeconds(4)) .tools(tool) .build(); + try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) + .capabilities(ClientCapabilities.builder().sampling().build()) + .sampling(samplingHandler) + .build()) { - InitializeResult initResult = mcpClient.initialize(); - assertThat(initResult).isNotNull(); + InitializeResult initResult = mcpClient.initialize(); + assertThat(initResult).isNotNull(); - CallToolResult response = mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); + CallToolResult response = mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); - assertThat(response).isNotNull(); - assertThat(response).isEqualTo(callResponse); + assertThat(response).isNotNull(); + assertThat(response).isEqualTo(callResponse); - assertWith(samplingResult.get(), result -> { - assertThat(result).isNotNull(); - assertThat(result.role()).isEqualTo(Role.USER); - assertThat(result.content()).isInstanceOf(McpSchema.TextContent.class); - assertThat(((McpSchema.TextContent) result.content()).text()).isEqualTo("Test message"); - assertThat(result.model()).isEqualTo("MockModelName"); - assertThat(result.stopReason()).isEqualTo(CreateMessageResult.StopReason.STOP_SEQUENCE); - }); - - mcpClient.close(); - mcpServer.close(); + assertWith(samplingResult.get(), result -> { + assertThat(result).isNotNull(); + assertThat(result.role()).isEqualTo(Role.USER); + assertThat(result.content()).isInstanceOf(McpSchema.TextContent.class); + assertThat(((McpSchema.TextContent) result.content()).text()).isEqualTo("Test message"); + assertThat(result.model()).isEqualTo("MockModelName"); + assertThat(result.stopReason()).isEqualTo(CreateMessageResult.StopReason.STOP_SEQUENCE); + }); + } + finally { + mcpServer.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -293,11 +299,6 @@ void testCreateMessageWithRequestTimeoutFail(String clientType) throws Interrupt CreateMessageResult.StopReason.STOP_SEQUENCE); }; - var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) - .capabilities(ClientCapabilities.builder().sampling().build()) - .sampling(samplingHandler) - .build(); - CallToolResult callResponse = new McpSchema.CallToolResult(List.of(new McpSchema.TextContent("CALL RESPONSE")), null); @@ -325,15 +326,21 @@ void testCreateMessageWithRequestTimeoutFail(String clientType) throws Interrupt .tools(tool) .build(); - InitializeResult initResult = mcpClient.initialize(); - assertThat(initResult).isNotNull(); + try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) + .capabilities(ClientCapabilities.builder().sampling().build()) + .sampling(samplingHandler) + .build()) { - assertThatExceptionOfType(McpError.class).isThrownBy(() -> { - mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); - }).withMessageContaining("1000ms"); + InitializeResult initResult = mcpClient.initialize(); + assertThat(initResult).isNotNull(); - mcpClient.close(); - mcpServer.close(); + assertThatExceptionOfType(McpError.class).isThrownBy(() -> { + mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); + }).withMessageContaining("1000ms"); + } + finally { + mcpServer.closeGracefully().block(); + } } // --------------------------------------- @@ -366,7 +373,9 @@ void testCreateElicitationWithoutElicitationCapabilities(String clientType) { .hasMessage("Client must be configured with elicitation capabilities"); } } - server.closeGracefully().block(); + finally { + server.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -421,7 +430,9 @@ void testCreateElicitationSuccess(String clientType) { assertThat(response).isNotNull(); assertThat(response).isEqualTo(callResponse); } - mcpServer.closeGracefully().block(); + finally { + mcpServer.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -436,11 +447,6 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) { return new ElicitResult(ElicitResult.Action.ACCEPT, Map.of("message", request.message())); }; - var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) - .capabilities(ClientCapabilities.builder().elicitation().build()) - .elicitation(elicitationHandler) - .build(); - CallToolResult callResponse = new McpSchema.CallToolResult(List.of(new McpSchema.TextContent("CALL RESPONSE")), null); @@ -467,21 +473,27 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) { .tools(tool) .build(); - InitializeResult initResult = mcpClient.initialize(); - assertThat(initResult).isNotNull(); + try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) + .capabilities(ClientCapabilities.builder().elicitation().build()) + .elicitation(elicitationHandler) + .build()) { - CallToolResult response = mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); + InitializeResult initResult = mcpClient.initialize(); + assertThat(initResult).isNotNull(); - assertThat(response).isNotNull(); - assertThat(response).isEqualTo(callResponse); - assertWith(resultRef.get(), result -> { - assertThat(result).isNotNull(); - assertThat(result.action()).isEqualTo(McpSchema.ElicitResult.Action.ACCEPT); - assertThat(result.content().get("message")).isEqualTo("Test message"); - }); + CallToolResult response = mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); - mcpClient.closeGracefully(); - mcpServer.closeGracefully().block(); + assertThat(response).isNotNull(); + assertThat(response).isEqualTo(callResponse); + assertWith(resultRef.get(), result -> { + assertThat(result).isNotNull(); + assertThat(result.action()).isEqualTo(McpSchema.ElicitResult.Action.ACCEPT); + assertThat(result.content().get("message")).isEqualTo("Test message"); + }); + } + finally { + mcpServer.closeGracefully().block(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -507,11 +519,6 @@ void testCreateElicitationWithRequestTimeoutFail(String clientType) { return new ElicitResult(ElicitResult.Action.ACCEPT, Map.of("message", request.message())); }; - var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) - .capabilities(ClientCapabilities.builder().elicitation().build()) - .elicitation(elicitationHandler) - .build(); - CallToolResult callResponse = new CallToolResult(List.of(new McpSchema.TextContent("CALL RESPONSE")), null); AtomicReference resultRef = new AtomicReference<>(); @@ -537,18 +544,24 @@ void testCreateElicitationWithRequestTimeoutFail(String clientType) { .tools(tool) .build(); - InitializeResult initResult = mcpClient.initialize(); - assertThat(initResult).isNotNull(); + try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0")) + .capabilities(ClientCapabilities.builder().elicitation().build()) + .elicitation(elicitationHandler) + .build()) { - assertThatExceptionOfType(McpError.class).isThrownBy(() -> { - mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); - }).withMessageContaining("within 1000ms"); + InitializeResult initResult = mcpClient.initialize(); + assertThat(initResult).isNotNull(); - ElicitResult elicitResult = resultRef.get(); - assertThat(elicitResult).isNull(); + assertThatExceptionOfType(McpError.class).isThrownBy(() -> { + mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of())); + }).withMessageContaining("within 1000ms"); - mcpClient.closeGracefully(); - mcpServer.closeGracefully().block(); + ElicitResult elicitResult = resultRef.get(); + assertThat(elicitResult).isNull(); + } + finally { + mcpServer.closeGracefully().block(); + } } // --------------------------------------- @@ -597,8 +610,9 @@ void testRootsSuccess(String clientType) { assertThat(rootsRef.get()).containsAll(List.of(roots.get(1), root3)); }); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -635,8 +649,9 @@ void testRootsWithoutCapability(String clientType) { assertThat(e).isInstanceOf(McpError.class).hasMessage("Roots not supported"); } } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -664,8 +679,9 @@ void testRootsNotificationWithEmptyRootsList(String clientType) { assertThat(rootsRef.get()).isEmpty(); }); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -697,8 +713,9 @@ void testRootsWithMultipleHandlers(String clientType) { assertThat(rootsRef2.get()).containsAll(roots); }); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -728,8 +745,9 @@ void testRootsServerCloseWithActiveSubscription(String clientType) { assertThat(rootsRef.get()).containsAll(roots); }); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } // --------------------------------------- @@ -789,8 +807,9 @@ void testToolCallSuccess(String clientType) { assertThat(responseBodyIsNullOrBlank.get()).isFalse(); assertThat(response).isNotNull().isEqualTo(callResponse); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -826,8 +845,9 @@ void testThrowingToolCallIsCaughtBeforeTimeout(String clientType) { .isThrownBy(() -> mcpClient.callTool(new McpSchema.CallToolRequest("tool1", Map.of()))) .withMessageContaining("Timeout on blocking read"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -882,8 +902,9 @@ void testToolCallSuccessWithTranportContextExtraction(String clientType) { assertThat(responseBodyIsNullOrBlank.get()).isFalse(); assertThat(response).isNotNull().isEqualTo(expectedCallResponse); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -974,8 +995,9 @@ void testToolListChangeHandlingSuccess(String clientType) { assertThat(toolsRef.get()).containsAll(List.of(tool2.tool())); }); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -991,8 +1013,9 @@ void testInitialize(String clientType) { InitializeResult initResult = mcpClient.initialize(); assertThat(initResult).isNotNull(); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } // --------------------------------------- @@ -1056,7 +1079,7 @@ void testLoggingNotification(String clientType) throws InterruptedException { .build(); var mcpServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0") - .capabilities(ServerCapabilities.builder().logging().tools(true).build()) + .capabilities(ServerCapabilities.builder().tools(true).build()) .tools(tool) .build(); @@ -1103,7 +1126,9 @@ void testLoggingNotification(String clientType) throws InterruptedException { assertThat(notificationMap.get("Another error message").logger()).isEqualTo("test-logger"); assertThat(notificationMap.get("Another error message").data()).isEqualTo("Another error message"); } - mcpServer.close(); + finally { + mcpServer.closeGracefully().block(); + } } // --------------------------------------- @@ -1208,7 +1233,7 @@ void testProgressNotification(String clientType) throws InterruptedException { assertThat(notificationMap.get("Processing completed").message()).isEqualTo("Processing completed"); } finally { - mcpServer.close(); + mcpServer.closeGracefully().block(); } } @@ -1258,8 +1283,9 @@ void testCompletionShouldReturnExpectedSuggestions(String clientType) { assertThat(samplingRequest.get().argument().value()).isEqualTo("py"); assertThat(samplingRequest.get().ref().type()).isEqualTo("ref/prompt"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } // --------------------------------------- @@ -1320,8 +1346,9 @@ void testPingSuccess(String clientType) { // Verify execution order assertThat(executionOrder.get()).isEqualTo("123"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully().block(); + } } // --------------------------------------- @@ -1396,8 +1423,9 @@ void testStructuredOutputValidationSuccess(String clientType) { .isEqualTo(json(""" {"result":5.0,"operation":"2 + 3","timestamp":"2024-01-01T10:00:00Z"}""")); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -1450,8 +1478,9 @@ void testStructuredOutputValidationFailure(String clientType) { String errorMessage = ((McpSchema.TextContent) response.content().get(0)).text(); assertThat(errorMessage).contains("Validation failed"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -1500,8 +1529,9 @@ void testStructuredOutputMissingStructuredContent(String clientType) { assertThat(errorMessage).isEqualTo( "Response missing structured content which is expected when calling tool with non-empty outputSchema"); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -1577,8 +1607,9 @@ void testStructuredOutputRuntimeToolAddition(String clientType) { .isEqualTo(json(""" {"count":3,"message":"Dynamic execution"}""")); } - - mcpServer.close(); + finally { + mcpServer.closeGracefully(); + } } private double evaluateExpression(String expression) { diff --git a/mcp/src/test/java/io/modelcontextprotocol/server/HttpServletStatelessIntegrationTests.java b/mcp/src/test/java/io/modelcontextprotocol/server/HttpServletStatelessIntegrationTests.java index 6a6f6f8b9..bb405b728 100644 --- a/mcp/src/test/java/io/modelcontextprotocol/server/HttpServletStatelessIntegrationTests.java +++ b/mcp/src/test/java/io/modelcontextprotocol/server/HttpServletStatelessIntegrationTests.java @@ -151,8 +151,9 @@ void testToolCallSuccess(String clientType) { assertThat(response).isNotNull(); assertThat(response).isEqualTo(callResponse); } - - mcpServer.close(); + finally { + mcpServer.close(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -167,8 +168,9 @@ void testInitialize(String clientType) { InitializeResult initResult = mcpClient.initialize(); assertThat(initResult).isNotNull(); } - - mcpServer.close(); + finally { + mcpServer.close(); + } } // --------------------------------------- @@ -218,8 +220,9 @@ void testCompletionShouldReturnExpectedSuggestions(String clientType) { assertThat(samplingRequest.get().argument().value()).isEqualTo("py"); assertThat(samplingRequest.get().ref().type()).isEqualTo("ref/prompt"); } - - mcpServer.close(); + finally { + mcpServer.close(); + } } // --------------------------------------- @@ -290,8 +293,9 @@ void testStructuredOutputValidationSuccess(String clientType) { .isEqualTo(json(""" {"result":5.0,"operation":"2 + 3","timestamp":"2024-01-01T10:00:00Z"}""")); } - - mcpServer.close(); + finally { + mcpServer.close(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -342,8 +346,9 @@ void testStructuredOutputValidationFailure(String clientType) { String errorMessage = ((McpSchema.TextContent) response.content().get(0)).text(); assertThat(errorMessage).contains("Validation failed"); } - - mcpServer.close(); + finally { + mcpServer.close(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -391,8 +396,9 @@ void testStructuredOutputMissingStructuredContent(String clientType) { assertThat(errorMessage).isEqualTo( "Response missing structured content which is expected when calling tool with non-empty outputSchema"); } - - mcpServer.close(); + finally { + mcpServer.close(); + } } @ParameterizedTest(name = "{0} : {displayName} ") @@ -465,8 +471,9 @@ void testStructuredOutputRuntimeToolAddition(String clientType) { .isEqualTo(json(""" {"count":3,"message":"Dynamic execution"}""")); } - - mcpServer.close(); + finally { + mcpServer.close(); + } } @Test