|
20 | 20 | import java.util.List;
|
21 | 21 | import java.util.function.BiConsumer;
|
22 | 22 | import java.util.function.BiFunction;
|
| 23 | +import java.util.stream.Collectors; |
23 | 24 |
|
24 | 25 | import io.modelcontextprotocol.server.McpAsyncServer;
|
25 | 26 | import io.modelcontextprotocol.server.McpAsyncServerExchange;
|
@@ -145,12 +146,25 @@ public List<McpServerFeatures.SyncToolSpecification> syncTools(ObjectProvider<Li
|
145 | 146 |
|
146 | 147 | private List<McpServerFeatures.SyncToolSpecification> toSyncToolSpecifications(List<ToolCallback> tools,
|
147 | 148 | McpServerProperties serverProperties) {
|
148 |
| - return tools.stream().map(tool -> { |
149 |
| - String toolName = tool.getToolDefinition().name(); |
150 |
| - MimeType mimeType = (serverProperties.getToolResponseMimeType().containsKey(toolName)) |
151 |
| - ? MimeType.valueOf(serverProperties.getToolResponseMimeType().get(toolName)) : null; |
152 |
| - return McpToolUtils.toSyncToolSpecification(tool, mimeType); |
153 |
| - }).toList(); |
| 149 | + |
| 150 | + // De-duplicate tools by their name, keeping the first occurrence of each tool |
| 151 | + // name |
| 152 | + return tools.stream() |
| 153 | + .collect(Collectors.toMap(tool -> tool.getToolDefinition().name(), // Key: |
| 154 | + // tool |
| 155 | + // name |
| 156 | + tool -> tool, // Value: the tool itself |
| 157 | + (existing, replacement) -> existing)) // On duplicate key, keep the |
| 158 | + // existing tool |
| 159 | + .values() |
| 160 | + .stream() |
| 161 | + .map(tool -> { |
| 162 | + String toolName = tool.getToolDefinition().name(); |
| 163 | + MimeType mimeType = (serverProperties.getToolResponseMimeType().containsKey(toolName)) |
| 164 | + ? MimeType.valueOf(serverProperties.getToolResponseMimeType().get(toolName)) : null; |
| 165 | + return McpToolUtils.toSyncToolSpecification(tool, mimeType); |
| 166 | + }) |
| 167 | + .toList(); |
154 | 168 | }
|
155 | 169 |
|
156 | 170 | @Bean
|
@@ -231,12 +245,24 @@ public List<McpServerFeatures.AsyncToolSpecification> asyncTools(ObjectProvider<
|
231 | 245 |
|
232 | 246 | private List<McpServerFeatures.AsyncToolSpecification> toAsyncToolSpecification(List<ToolCallback> tools,
|
233 | 247 | McpServerProperties serverProperties) {
|
234 |
| - return tools.stream().map(tool -> { |
235 |
| - String toolName = tool.getToolDefinition().name(); |
236 |
| - MimeType mimeType = (serverProperties.getToolResponseMimeType().containsKey(toolName)) |
237 |
| - ? MimeType.valueOf(serverProperties.getToolResponseMimeType().get(toolName)) : null; |
238 |
| - return McpToolUtils.toAsyncToolSpecification(tool, mimeType); |
239 |
| - }).toList(); |
| 248 | + // De-duplicate tools by their name, keeping the first occurrence of each tool |
| 249 | + // name |
| 250 | + return tools.stream() |
| 251 | + .collect(Collectors.toMap(tool -> tool.getToolDefinition().name(), // Key: |
| 252 | + // tool |
| 253 | + // name |
| 254 | + tool -> tool, // Value: the tool itself |
| 255 | + (existing, replacement) -> existing)) // On duplicate key, keep the |
| 256 | + // existing tool |
| 257 | + .values() |
| 258 | + .stream() |
| 259 | + .map(tool -> { |
| 260 | + String toolName = tool.getToolDefinition().name(); |
| 261 | + MimeType mimeType = (serverProperties.getToolResponseMimeType().containsKey(toolName)) |
| 262 | + ? MimeType.valueOf(serverProperties.getToolResponseMimeType().get(toolName)) : null; |
| 263 | + return McpToolUtils.toAsyncToolSpecification(tool, mimeType); |
| 264 | + }) |
| 265 | + .toList(); |
240 | 266 | }
|
241 | 267 |
|
242 | 268 | @Bean
|
|
0 commit comments