From 1ca981eba588d4bb1b26c9f66a4aa306f6309b8e Mon Sep 17 00:00:00 2001 From: Christian Tzolov Date: Thu, 13 Feb 2025 20:36:32 +0100 Subject: [PATCH] refactor(mcp): migrate MCP demos to ToolCallbackProvider - Replace List with ToolCallbackProvider for tool registration - Use MethodToolCallbackProvider.builder() pattern across all modules Signed-off-by: Christian Tzolov --- .../starter-webflux-server/README.md | 30 ++++++++----------- .../sample/server/McpServerApplication.java | 24 +++++++-------- .../ai/mcp/samples/client/Application.java | 6 ++-- .../ai/mcp/samples/client/Application.java | 6 ++-- .../sample/server/McpServerApplication.java | 10 +++---- .../sample/server/McpServerApplication.java | 14 ++++----- .../ai/mcp/samples/brave/Application.java | 3 +- .../web-search/brave-starter/pom.xml | 6 +++- .../ai/mcp/samples/brave/Application.java | 6 ++-- .../src/main/resources/application.properties | 2 ++ 10 files changed, 50 insertions(+), 57 deletions(-) diff --git a/model-context-protocol/book-library/starter-webflux-server/README.md b/model-context-protocol/book-library/starter-webflux-server/README.md index 15d5f15..3354c76 100644 --- a/model-context-protocol/book-library/starter-webflux-server/README.md +++ b/model-context-protocol/book-library/starter-webflux-server/README.md @@ -122,23 +122,19 @@ logging.file.name=./target/mcp.webflux-server-starter.log ```java @SpringBootApplication public class McpServerApplication { - @Bean - public List tools(OpenLibrary openLibrary) { - List tools = new ArrayList<>(); - - // Add OpenLibrary tools - tools.addAll(List.of(ToolCallbacks.from(openLibrary))); - - // Add toUpperCase tool - tools.add(FunctionToolCallback - .builder("toUpperCase", - (Function) s -> s.input().toUpperCase()) - .description("To upper case") - .inputType(ToUpperCaseInput.class) - .build()); - - return tools; - } + @Bean + public ToolCallbackProvider openLibraryTools(OpenLibrary openLibrary) { + return MethodToolCallbackProvider.builder().toolObjects(openLibrary).build(); + } + + @Bean + public ToolCallback tools(OpenLibrary openLibrary) { + return FunctionToolCallback + .builder("toUpperCase", (Function) s -> s.input().toUpperCase()) + .description("To upper case") + .inputType(ToUpperCaseInput.class) + .build(); + } } ``` diff --git a/model-context-protocol/book-library/starter-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java b/model-context-protocol/book-library/starter-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java index 84a0502..c4bb400 100644 --- a/model-context-protocol/book-library/starter-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java +++ b/model-context-protocol/book-library/starter-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java @@ -17,8 +17,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.tool.ToolCallback; +import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.ai.tool.ToolCallbacks; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.tool.method.MethodToolCallbackProvider; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @@ -36,19 +38,17 @@ public class McpServerApplication { } @Bean - public List tools(OpenLibrary openLibrary) { + public ToolCallbackProvider openLibraryTools(OpenLibrary openLibrary) { + return MethodToolCallbackProvider.builder().toolObjects(openLibrary).build(); + } - List tools = new ArrayList<>(); - - tools.addAll(List.of(ToolCallbacks.from(openLibrary))); - - tools.add(FunctionToolCallback - .builder("toUpperCase", (Function) s -> s.input().toUpperCase()) - .description("To upper case") - .inputType(ToUpperCaseInput.class) - .build()); - - return tools; + @Bean + public ToolCallback tools(OpenLibrary openLibrary) { + return FunctionToolCallback + .builder("toUpperCase", (Function) s -> s.input().toUpperCase()) + .description("To upper case") + .inputType(ToUpperCaseInput.class) + .build(); } @Bean diff --git a/model-context-protocol/client-starter/starter-default-client/src/main/java/org/springframework/ai/mcp/samples/client/Application.java b/model-context-protocol/client-starter/starter-default-client/src/main/java/org/springframework/ai/mcp/samples/client/Application.java index 039f247..88392de 100644 --- a/model-context-protocol/client-starter/starter-default-client/src/main/java/org/springframework/ai/mcp/samples/client/Application.java +++ b/model-context-protocol/client-starter/starter-default-client/src/main/java/org/springframework/ai/mcp/samples/client/Application.java @@ -15,10 +15,8 @@ */ package org.springframework.ai.mcp.samples.client; -import java.util.List; - import org.springframework.ai.chat.client.ChatClient; -import org.springframework.ai.tool.ToolCallback; +import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; @@ -37,7 +35,7 @@ public class Application { private String userInput; @Bean - public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder, List tools, + public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools, ConfigurableApplicationContext context) { return args -> { diff --git a/model-context-protocol/client-starter/starter-webflux-client/src/main/java/org/springframework/ai/mcp/samples/client/Application.java b/model-context-protocol/client-starter/starter-webflux-client/src/main/java/org/springframework/ai/mcp/samples/client/Application.java index 97d2138..a603091 100644 --- a/model-context-protocol/client-starter/starter-webflux-client/src/main/java/org/springframework/ai/mcp/samples/client/Application.java +++ b/model-context-protocol/client-starter/starter-webflux-client/src/main/java/org/springframework/ai/mcp/samples/client/Application.java @@ -15,10 +15,8 @@ */ package org.springframework.ai.mcp.samples.client; -import java.util.List; - import org.springframework.ai.chat.client.ChatClient; -import org.springframework.ai.tool.ToolCallback; +import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; @@ -37,7 +35,7 @@ public class Application { private String userInput; @Bean - public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder, List tools, + public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools, ConfigurableApplicationContext context) { return args -> { diff --git a/model-context-protocol/weather/starter-stdio-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java b/model-context-protocol/weather/starter-stdio-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java index 774a2ac..2e96703 100644 --- a/model-context-protocol/weather/starter-stdio-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java +++ b/model-context-protocol/weather/starter-stdio-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java @@ -1,9 +1,7 @@ package org.springframework.ai.mcp.sample.server; -import java.util.List; - -import org.springframework.ai.tool.ToolCallback; -import org.springframework.ai.tool.ToolCallbacks; +import org.springframework.ai.tool.ToolCallbackProvider; +import org.springframework.ai.tool.method.MethodToolCallbackProvider; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @@ -16,8 +14,8 @@ public class McpServerApplication { } @Bean - public List weatherTools(WeatherService weatherService) { - return List.of(ToolCallbacks.from(weatherService)); + public ToolCallbackProvider weatherTools(WeatherService weatherService) { + return MethodToolCallbackProvider.builder().toolObjects(weatherService).build(); } } diff --git a/model-context-protocol/weather/starter-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java b/model-context-protocol/weather/starter-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java index 60af7e7..b150ece 100644 --- a/model-context-protocol/weather/starter-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java +++ b/model-context-protocol/weather/starter-webflux-server/src/main/java/org/springframework/ai/mcp/sample/server/McpServerApplication.java @@ -1,10 +1,9 @@ package org.springframework.ai.mcp.sample.server; -import java.util.List; - import org.springframework.ai.tool.ToolCallback; -import org.springframework.ai.tool.ToolCallbacks; +import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.tool.method.MethodToolCallbackProvider; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @@ -17,20 +16,19 @@ public class McpServerApplication { } @Bean - public List weatherTools(WeatherService weatherService) { - return List.of(ToolCallbacks.from(weatherService)); + public ToolCallbackProvider weatherTools(WeatherService weatherService) { + return MethodToolCallbackProvider.builder().toolObjects(weatherService).build(); } public record TextInput(String input) { } @Bean - public List toUpperCase() { - var tool = FunctionToolCallback.builder("toUpperCase", (TextInput input) -> input.input().toUpperCase()) + public ToolCallback toUpperCase() { + return FunctionToolCallback.builder("toUpperCase", (TextInput input) -> input.input().toUpperCase()) .inputType(TextInput.class) .description("Put the text to upper case") .build(); - return List.of(tool); } } diff --git a/model-context-protocol/web-search/brave-chatbot/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java b/model-context-protocol/web-search/brave-chatbot/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java index e21c7fd..a318f50 100644 --- a/model-context-protocol/web-search/brave-chatbot/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java +++ b/model-context-protocol/web-search/brave-chatbot/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java @@ -7,6 +7,7 @@ import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor; import org.springframework.ai.chat.memory.InMemoryChatMemory; import org.springframework.ai.tool.ToolCallback; +import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -20,7 +21,7 @@ public class Application { } @Bean - public CommandLineRunner chatbot(ChatClient.Builder chatClientBuilder, List tools) { + public CommandLineRunner chatbot(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools) { return args -> { diff --git a/model-context-protocol/web-search/brave-starter/pom.xml b/model-context-protocol/web-search/brave-starter/pom.xml index b14bbb1..54d1749 100644 --- a/model-context-protocol/web-search/brave-starter/pom.xml +++ b/model-context-protocol/web-search/brave-starter/pom.xml @@ -37,9 +37,13 @@ spring-ai-mcp-client-spring-boot-starter - + + + org.springframework.ai + spring-ai-anthropic-spring-boot-starter diff --git a/model-context-protocol/web-search/brave-starter/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java b/model-context-protocol/web-search/brave-starter/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java index cff3dbc..0299055 100644 --- a/model-context-protocol/web-search/brave-starter/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java +++ b/model-context-protocol/web-search/brave-starter/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java @@ -15,10 +15,8 @@ */ package org.springframework.ai.mcp.samples.brave; -import java.util.List; - import org.springframework.ai.chat.client.ChatClient; -import org.springframework.ai.tool.ToolCallback; +import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -33,7 +31,7 @@ public class Application { } @Bean - public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder, List tools, + public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools, ConfigurableApplicationContext context) { return args -> { diff --git a/model-context-protocol/web-search/brave-starter/src/main/resources/application.properties b/model-context-protocol/web-search/brave-starter/src/main/resources/application.properties index 6ad2db5..9200a96 100644 --- a/model-context-protocol/web-search/brave-starter/src/main/resources/application.properties +++ b/model-context-protocol/web-search/brave-starter/src/main/resources/application.properties @@ -1,6 +1,8 @@ spring.application.name=mcp spring.main.web-application-type=none +spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY} + spring.ai.openai.api-key=${OPENAI_API_KEY} # There are two ways to configure the MCP client: