|
10 | 10 | import java.util.concurrent.atomic.AtomicReference; |
11 | 11 | import java.util.function.BiFunction; |
12 | 12 |
|
| 13 | +import org.slf4j.LoggerFactory; |
| 14 | + |
| 15 | +import ch.qos.logback.classic.Level; |
| 16 | +import ch.qos.logback.classic.Logger; |
| 17 | +import ch.qos.logback.classic.spi.ILoggingEvent; |
| 18 | +import ch.qos.logback.core.read.ListAppender; |
13 | 19 | import io.modelcontextprotocol.client.McpClient; |
14 | 20 | import io.modelcontextprotocol.client.transport.HttpClientStreamableHttpTransport; |
15 | 21 | import io.modelcontextprotocol.common.McpTransportContext; |
|
42 | 48 | import org.junit.jupiter.api.Test; |
43 | 49 | import org.junit.jupiter.api.Timeout; |
44 | 50 |
|
| 51 | +import org.junit.jupiter.params.ParameterizedTest; |
| 52 | +import org.junit.jupiter.params.provider.ValueSource; |
45 | 53 | import org.springframework.mock.web.MockHttpServletRequest; |
46 | 54 | import org.springframework.mock.web.MockHttpServletResponse; |
47 | 55 | import org.springframework.web.client.RestClient; |
@@ -766,61 +774,65 @@ void testThrownMcpErrorAndJsonRpcError() throws Exception { |
766 | 774 | } |
767 | 775 |
|
768 | 776 | @Test |
769 | | - void testInitializedNotificationCallReturnsAccepted() throws Exception { |
770 | | - var mcpServer = McpServer.sync(mcpStatelessServerTransport) |
771 | | - .serverInfo("test-server", "1.0.0") |
772 | | - .capabilities(ServerCapabilities.builder().build()) |
773 | | - .build(); |
774 | | - |
775 | | - McpSchema.JSONRPCNotification notification = new McpSchema.JSONRPCNotification(McpSchema.JSONRPC_VERSION, |
776 | | - McpSchema.METHOD_NOTIFICATION_INITIALIZED, null); |
777 | | - |
778 | | - MockHttpServletRequest request = new MockHttpServletRequest("POST", CUSTOM_MESSAGE_ENDPOINT); |
779 | | - MockHttpServletResponse response = new MockHttpServletResponse(); |
780 | | - |
781 | | - byte[] content = JSON_MAPPER.writeValueAsBytes(notification); |
782 | | - request.setContent(content); |
783 | | - request.addHeader("Content-Type", "application/json"); |
784 | | - request.addHeader("Content-Length", Integer.toString(content.length)); |
785 | | - request.addHeader("Accept", APPLICATION_JSON + ", " + TEXT_EVENT_STREAM); |
786 | | - request.addHeader("Cache-Control", "no-cache"); |
787 | | - request.addHeader(HttpHeaders.PROTOCOL_VERSION, ProtocolVersions.MCP_2025_03_26); |
| 777 | + void testInitializedNotificationDoesNotLogWarn() { |
| 778 | + Logger handlerLogger = (Logger) LoggerFactory |
| 779 | + .getLogger("io.modelcontextprotocol.server.DefaultMcpStatelessServerHandler"); |
| 780 | + ListAppender<ILoggingEvent> logAppender = new ListAppender<>(); |
| 781 | + logAppender.start(); |
| 782 | + handlerLogger.addAppender(logAppender); |
788 | 783 |
|
789 | | - mcpStatelessServerTransport.service(request, response); |
| 784 | + try { |
| 785 | + var mcpServer = McpServer.sync(mcpStatelessServerTransport) |
| 786 | + .serverInfo("test-server", "1.0.0") |
| 787 | + .capabilities(ServerCapabilities.builder().build()) |
| 788 | + .build(); |
790 | 789 |
|
791 | | - assertThat(response.getStatus()).isEqualTo(202); |
792 | | - assertThat(response.getContentAsByteArray()).isEmpty(); |
| 790 | + try (var mcpClient = clientBuilder.build()) { |
| 791 | + mcpClient.initialize(); // automatically sends notifications/initialized |
| 792 | + } |
| 793 | + finally { |
| 794 | + mcpServer.close(); |
| 795 | + } |
| 796 | + } |
| 797 | + finally { |
| 798 | + handlerLogger.detachAppender(logAppender); |
| 799 | + logAppender.stop(); |
| 800 | + } |
793 | 801 |
|
794 | | - mcpServer.close(); |
| 802 | + assertThat(logAppender.list).noneMatch(event -> event.getLevel() == Level.WARN |
| 803 | + && (event.getFormattedMessage().contains(McpSchema.METHOD_NOTIFICATION_INITIALIZED) |
| 804 | + || event.getFormattedMessage().contains("Missing handler for request type"))); |
795 | 805 | } |
796 | 806 |
|
797 | 807 | @Test |
798 | | - void testRootsListChangedNotificationCallReturnsAccepted() throws Exception { |
799 | | - var mcpServer = McpServer.sync(mcpStatelessServerTransport) |
800 | | - .serverInfo("test-server", "1.0.0") |
801 | | - .capabilities(ServerCapabilities.builder().build()) |
802 | | - .build(); |
803 | | - |
804 | | - McpSchema.JSONRPCNotification notification = new McpSchema.JSONRPCNotification(McpSchema.JSONRPC_VERSION, |
805 | | - McpSchema.METHOD_NOTIFICATION_ROOTS_LIST_CHANGED, null); |
806 | | - |
807 | | - MockHttpServletRequest request = new MockHttpServletRequest("POST", CUSTOM_MESSAGE_ENDPOINT); |
808 | | - MockHttpServletResponse response = new MockHttpServletResponse(); |
| 808 | + void testRootsListChangedNotificationDoesNotLogWarn() { |
| 809 | + Logger handlerLogger = (Logger) LoggerFactory.getLogger(DefaultMcpStatelessServerHandler.class); |
| 810 | + ListAppender<ILoggingEvent> logAppender = new ListAppender<>(); |
| 811 | + logAppender.start(); |
| 812 | + handlerLogger.addAppender(logAppender); |
809 | 813 |
|
810 | | - byte[] content = JSON_MAPPER.writeValueAsBytes(notification); |
811 | | - request.setContent(content); |
812 | | - request.addHeader("Content-Type", "application/json"); |
813 | | - request.addHeader("Content-Length", Integer.toString(content.length)); |
814 | | - request.addHeader("Accept", APPLICATION_JSON + ", " + TEXT_EVENT_STREAM); |
815 | | - request.addHeader("Cache-Control", "no-cache"); |
816 | | - request.addHeader(HttpHeaders.PROTOCOL_VERSION, ProtocolVersions.MCP_2025_03_26); |
817 | | - |
818 | | - mcpStatelessServerTransport.service(request, response); |
| 814 | + try { |
| 815 | + var mcpServer = McpServer.sync(mcpStatelessServerTransport) |
| 816 | + .serverInfo("test-server", "1.0.0") |
| 817 | + .capabilities(ServerCapabilities.builder().build()) |
| 818 | + .build(); |
819 | 819 |
|
820 | | - assertThat(response.getStatus()).isEqualTo(202); |
821 | | - assertThat(response.getContentAsByteArray()).isEmpty(); |
| 820 | + try (var mcpClient = clientBuilder.build()) { |
| 821 | + mcpClient.initialize(); |
| 822 | + mcpClient.rootsListChangedNotification(); |
| 823 | + } |
| 824 | + finally { |
| 825 | + mcpServer.close(); |
| 826 | + } |
| 827 | + } |
| 828 | + finally { |
| 829 | + handlerLogger.detachAppender(logAppender); |
| 830 | + logAppender.stop(); |
| 831 | + } |
822 | 832 |
|
823 | | - mcpServer.close(); |
| 833 | + assertThat(logAppender.list).noneMatch(event -> event.getLevel() == Level.WARN |
| 834 | + && (event.getFormattedMessage().contains(McpSchema.METHOD_NOTIFICATION_ROOTS_LIST_CHANGED) |
| 835 | + || event.getFormattedMessage().contains("Missing handler for request type"))); |
824 | 836 | } |
825 | 837 |
|
826 | 838 | private double evaluateExpression(String expression) { |
|
0 commit comments