|
46 | 46 | import org.springframework.mock.web.MockHttpServletRequest; |
47 | 47 | import org.springframework.mock.web.MockHttpServletResponse; |
48 | 48 | import org.springframework.web.client.RestClient; |
49 | | -import reactor.core.publisher.Mono; |
50 | 49 |
|
51 | 50 | import static io.modelcontextprotocol.server.transport.HttpServletStatelessServerTransport.APPLICATION_JSON; |
52 | 51 | import static io.modelcontextprotocol.server.transport.HttpServletStatelessServerTransport.TEXT_EVENT_STREAM; |
@@ -110,64 +109,49 @@ public void after() { |
110 | 109 | // --------------------------------------- |
111 | 110 | // Tools Tests |
112 | 111 | // --------------------------------------- |
113 | | - @Test |
114 | | - void testStatelessAsyncBulkToolMutations() { |
115 | | - var mcpServer = McpServer.async(mcpStatelessServerTransport) |
116 | | - .capabilities(ServerCapabilities.builder().tools(true).build()) |
117 | | - .build(); |
118 | | - |
119 | | - mcpServer |
120 | | - .addTools(List.of(asyncToolSpecification("duplicate-tool", "First tool"), |
121 | | - asyncToolSpecification("middle-tool"), asyncToolSpecification("duplicate-tool", "Last tool"))) |
122 | | - .block(); |
123 | | - |
124 | | - List<Tool> tools = mcpServer.listTools().collectList().block(); |
125 | | - assertThat(tools).extracting(McpSchema.Tool::name).containsExactly("middle-tool", "duplicate-tool"); |
126 | | - assertThat(tools.get(1).title()).isEqualTo("Last tool"); |
127 | | - |
128 | | - mcpServer |
129 | | - .addTools(List.of(asyncToolSpecification("middle-tool", "Replacement tool"), |
130 | | - asyncToolSpecification("new-tool"))) |
131 | | - .block(); |
132 | | - |
133 | | - tools = mcpServer.listTools().collectList().block(); |
134 | | - assertThat(tools).extracting(McpSchema.Tool::name).containsExactly("duplicate-tool", "middle-tool", "new-tool"); |
135 | | - assertThat(tools.get(1).title()).isEqualTo("Replacement tool"); |
136 | | - |
137 | | - mcpServer.removeTools(List.of("duplicate-tool", "missing-tool")).block(); |
138 | | - |
139 | | - tools = mcpServer.listTools().collectList().block(); |
140 | | - assertThat(tools).extracting(McpSchema.Tool::name).containsExactly("middle-tool", "new-tool"); |
| 112 | + @ParameterizedTest(name = "{0} : {displayName} ") |
| 113 | + @ValueSource(strings = { "httpclient" }) |
| 114 | + void testStatelessSyncBulkToolMutations(String clientType) { |
141 | 115 |
|
142 | | - mcpServer.closeGracefully().block(); |
143 | | - } |
| 116 | + var clientBuilder = clientBuilders.get(clientType); |
144 | 117 |
|
145 | | - @Test |
146 | | - void testStatelessSyncBulkToolMutations() { |
147 | 118 | var mcpServer = McpServer.sync(mcpStatelessServerTransport) |
148 | 119 | .capabilities(ServerCapabilities.builder().tools(true).build()) |
149 | 120 | .build(); |
150 | 121 |
|
151 | | - mcpServer.addTools(List.of(syncToolSpecification("duplicate-tool", "First tool"), |
152 | | - syncToolSpecification("middle-tool"), syncToolSpecification("duplicate-tool", "Last tool"))); |
| 122 | + try (var mcpClient = clientBuilder.build()) { |
| 123 | + InitializeResult initResult = mcpClient.initialize(); |
| 124 | + assertThat(initResult).isNotNull(); |
| 125 | + assertThat(mcpClient.listTools().tools()).isEmpty(); |
153 | 126 |
|
154 | | - List<Tool> tools = mcpServer.listTools(); |
155 | | - assertThat(tools).extracting(McpSchema.Tool::name).containsExactly("middle-tool", "duplicate-tool"); |
156 | | - assertThat(tools.get(1).title()).isEqualTo("Last tool"); |
| 127 | + mcpServer.addTools(List.of(syncToolSpecification("duplicate-tool", "First tool"), |
| 128 | + syncToolSpecification("middle-tool"), syncToolSpecification("duplicate-tool", "Last tool"))); |
157 | 129 |
|
158 | | - mcpServer.addTools( |
159 | | - List.of(syncToolSpecification("middle-tool", "Replacement tool"), syncToolSpecification("new-tool"))); |
| 130 | + await().atMost(Duration.ofSeconds(5)).untilAsserted(() -> { |
| 131 | + List<Tool> tools = mcpClient.listTools().tools(); |
| 132 | + assertThat(tools).extracting(McpSchema.Tool::name).containsExactly("middle-tool", "duplicate-tool"); |
| 133 | + assertThat(tools.get(1).title()).isEqualTo("Last tool"); |
| 134 | + }); |
160 | 135 |
|
161 | | - tools = mcpServer.listTools(); |
162 | | - assertThat(tools).extracting(McpSchema.Tool::name).containsExactly("duplicate-tool", "middle-tool", "new-tool"); |
163 | | - assertThat(tools.get(1).title()).isEqualTo("Replacement tool"); |
| 136 | + mcpServer.addTools(List.of(syncToolSpecification("middle-tool", "Replacement tool"), |
| 137 | + syncToolSpecification("new-tool"))); |
164 | 138 |
|
165 | | - mcpServer.removeTools(List.of("duplicate-tool", "missing-tool")); |
| 139 | + await().atMost(Duration.ofSeconds(5)).untilAsserted(() -> { |
| 140 | + List<Tool> tools = mcpClient.listTools().tools(); |
| 141 | + assertThat(tools).extracting(McpSchema.Tool::name) |
| 142 | + .containsExactly("duplicate-tool", "middle-tool", "new-tool"); |
| 143 | + assertThat(tools.get(1).title()).isEqualTo("Replacement tool"); |
| 144 | + }); |
166 | 145 |
|
167 | | - tools = mcpServer.listTools(); |
168 | | - assertThat(tools).extracting(McpSchema.Tool::name).containsExactly("middle-tool", "new-tool"); |
| 146 | + mcpServer.removeTools(List.of("duplicate-tool", "missing-tool")); |
169 | 147 |
|
170 | | - mcpServer.closeGracefully().block(); |
| 148 | + await().atMost(Duration.ofSeconds(5)) |
| 149 | + .untilAsserted(() -> assertThat(mcpClient.listTools().tools()).extracting(McpSchema.Tool::name) |
| 150 | + .containsExactly("middle-tool", "new-tool")); |
| 151 | + } |
| 152 | + finally { |
| 153 | + mcpServer.closeGracefully().block(); |
| 154 | + } |
171 | 155 | } |
172 | 156 |
|
173 | 157 | @ParameterizedTest(name = "{0} : {displayName} ") |
@@ -712,18 +696,6 @@ private double evaluateExpression(String expression) { |
712 | 696 | }; |
713 | 697 | } |
714 | 698 |
|
715 | | - private McpStatelessServerFeatures.AsyncToolSpecification asyncToolSpecification(String name) { |
716 | | - return asyncToolSpecification(name, name); |
717 | | - } |
718 | | - |
719 | | - private McpStatelessServerFeatures.AsyncToolSpecification asyncToolSpecification(String name, String title) { |
720 | | - return McpStatelessServerFeatures.AsyncToolSpecification.builder() |
721 | | - .tool(McpSchema.Tool.builder().name(name).title(title).inputSchema(EMPTY_JSON_SCHEMA).build()) |
722 | | - .callHandler( |
723 | | - (context, request) -> Mono.just(CallToolResult.builder().content(List.of()).isError(false).build())) |
724 | | - .build(); |
725 | | - } |
726 | | - |
727 | 699 | private McpStatelessServerFeatures.SyncToolSpecification syncToolSpecification(String name) { |
728 | 700 | return syncToolSpecification(name, name); |
729 | 701 | } |
|
0 commit comments