|
25 | 25 | import java.util.Map; |
26 | 26 |
|
27 | 27 | import org.junit.jupiter.api.Test; |
| 28 | +import org.springframework.ai.chat.model.ToolContext; |
| 29 | +import org.springframework.ai.mcp.McpToolUtils; |
28 | 30 | import org.springframework.ai.mcp.client.common.autoconfigure.McpClientAutoConfiguration; |
29 | 31 | import org.springframework.ai.mcp.client.common.autoconfigure.McpToolCallbackAutoConfiguration; |
30 | 32 | import org.springframework.ai.mcp.client.webflux.autoconfigure.StreamableHttpWebFluxTransportAutoConfiguration; |
|
33 | 35 | import org.springframework.ai.mcp.server.common.autoconfigure.properties.McpServerStreamableHttpProperties; |
34 | 36 | import org.springframework.ai.mcp.server.common.autoconfigure.McpServerStatelessAutoConfiguration; |
35 | 37 | import org.springframework.ai.mcp.server.common.autoconfigure.StatelessToolCallbackConverterAutoConfiguration; |
| 38 | +import org.springframework.ai.tool.function.FunctionToolCallback; |
36 | 39 | import org.springframework.beans.factory.ObjectProvider; |
37 | 40 | import org.springframework.boot.autoconfigure.AutoConfigurations; |
38 | 41 | import org.springframework.boot.test.context.runner.ApplicationContextRunner; |
@@ -123,7 +126,7 @@ void clientServerCapabilities() { |
123 | 126 | // TOOLS / SAMPLING / ELICITATION |
124 | 127 |
|
125 | 128 | // tool list |
126 | | - assertThat(mcpClient.listTools().tools()).hasSize(2); |
| 129 | + assertThat(mcpClient.listTools().tools()).hasSize(3); |
127 | 130 | assertThat(mcpClient.listTools().tools()) |
128 | 131 | .contains(Tool.builder().name("tool1").description("tool1 description").inputSchema(""" |
129 | 132 | { |
@@ -167,6 +170,18 @@ void clientServerCapabilities() { |
167 | 170 | .isEqualTo(json(""" |
168 | 171 | {"result":5.0,"operation":"2 + 3","timestamp":"2024-01-01T10:00:00Z"}""")); |
169 | 172 |
|
| 173 | + // TOOL FROM MCP TOOL UTILS |
| 174 | + // Call the tool to ensure arguments are passed correctly |
| 175 | + CallToolResult toUpperCaseResponse = mcpClient |
| 176 | + .callTool(new McpSchema.CallToolRequest("toUpperCase", Map.of("input", "hello world"))); |
| 177 | + assertThat(toUpperCaseResponse).isNotNull(); |
| 178 | + assertThat(toUpperCaseResponse.isError()).isFalse(); |
| 179 | + assertThat(toUpperCaseResponse.content()).hasSize(1) |
| 180 | + .first() |
| 181 | + .isInstanceOf(TextContent.class) |
| 182 | + .extracting("text") |
| 183 | + .isEqualTo("\"HELLO WORLD\""); |
| 184 | + |
170 | 185 | // PROMPT / COMPLETION |
171 | 186 |
|
172 | 187 | // list prompts |
@@ -255,7 +270,20 @@ public List<McpStatelessServerFeatures.SyncToolSpecification> myTools() { |
255 | 270 | }) |
256 | 271 | .build(); |
257 | 272 |
|
258 | | - return List.of(tool1, tool2); |
| 273 | + // Tool 3 |
| 274 | + |
| 275 | + // Using a tool with McpToolUtils |
| 276 | + McpStatelessServerFeatures.SyncToolSpecification tool3 = McpToolUtils |
| 277 | + .toStatelessSyncToolSpecification(FunctionToolCallback |
| 278 | + .builder("toUpperCase", (ToUpperCaseRequest req, ToolContext context) -> req.input().toUpperCase()) |
| 279 | + .description("Sets the input string to upper case") |
| 280 | + .inputType(ToUpperCaseRequest.class) |
| 281 | + .build(), null); |
| 282 | + |
| 283 | + return List.of(tool1, tool2, tool3); |
| 284 | + } |
| 285 | + |
| 286 | + record ToUpperCaseRequest(String input) { |
259 | 287 | } |
260 | 288 |
|
261 | 289 | @Bean |
|
0 commit comments