refactor: migrate to spring-ai-mcp-client-spring-boot-starter
- Replace spring-ai-mcp dependency with spring-ai-mcp-client-spring-boot-starter - Update import statements from org.springframework.ai.mcp.* to io.modelcontextprotocol.client.* - Replace McpFunctionCallback with SyncMcpToolCallbackProvider - Update Spring AI version from 1.0.0-M5 to 1.0.0-SNAPSHOT in multiple projects - Enable tool callback auto-configuration with spring.ai.mcp.client.toolcallback.enabled Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
This commit is contained in:
@@ -1,20 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.3.6</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>ai-mcp-brave</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>Spring AI - Model Context Protocol - Brave</name>
|
||||
<description>Simple AI Application using MCP client to use Brave for Internet search</description>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -22,7 +25,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-bom</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<version>${spring-ai.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -40,13 +43,11 @@
|
||||
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-mcp</artifactId>
|
||||
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -78,4 +79,4 @@
|
||||
</repositories>
|
||||
|
||||
|
||||
</project>
|
||||
</project>
|
||||
@@ -1,14 +1,13 @@
|
||||
package org.springframework.ai.mcp.samples.brave;
|
||||
|
||||
import io.modelcontextprotocol.client.McpClient;
|
||||
import java.util.List;
|
||||
|
||||
import io.modelcontextprotocol.client.McpSyncClient;
|
||||
import io.modelcontextprotocol.client.transport.ServerParameters;
|
||||
import io.modelcontextprotocol.client.transport.StdioClientTransport;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.mcp.SyncMcpToolCallback;
|
||||
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@@ -26,16 +25,12 @@ public class Application {
|
||||
|
||||
@Bean
|
||||
public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder,
|
||||
McpSyncClient mcpSyncClient, ConfigurableApplicationContext context) {
|
||||
List<McpSyncClient> mcpSyncClients, ConfigurableApplicationContext context) {
|
||||
|
||||
return args -> {
|
||||
|
||||
var chatClient = chatClientBuilder
|
||||
.defaultTools(mcpSyncClient.listTools(null)
|
||||
.tools()
|
||||
.stream()
|
||||
.map(tool -> new SyncMcpToolCallback(mcpSyncClient, tool))
|
||||
.toArray(SyncMcpToolCallback[]::new))
|
||||
.defaultTools(new SyncMcpToolCallbackProvider(mcpSyncClients))
|
||||
.build();
|
||||
|
||||
String question = "Does Spring AI supports the Model Context Protocol? Please provide some references.";
|
||||
@@ -45,20 +40,4 @@ public class Application {
|
||||
context.close();
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public McpSyncClient mcpClient() {
|
||||
|
||||
// https://github.com/modelcontextprotocol/servers/tree/main/src/brave-search
|
||||
var stdioParams = ServerParameters.builder("npx")
|
||||
.args("-y", "@modelcontextprotocol/server-brave-search")
|
||||
.addEnvVar("BRAVE_API_KEY", System.getenv("BRAVE_API_KEY"))
|
||||
.build();
|
||||
|
||||
var mcpClient = McpClient.sync(new StdioClientTransport(stdioParams)).build();
|
||||
var init = mcpClient.initialize();
|
||||
logger.info("MCP Initialized: {}", init);
|
||||
return mcpClient;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,8 @@ spring.main.web-application-type=none
|
||||
|
||||
spring.ai.openai.api-key=${OPENAI_API_KEY}
|
||||
|
||||
spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json
|
||||
|
||||
# Logging configuration
|
||||
logging.level.root=INFO
|
||||
logging.level.org.springframework.ai.mcp=WARN
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"brave-search": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-brave-search"
|
||||
],
|
||||
"env": {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,4 +14,6 @@ spring.ai.mcp.client.stdio.connections.brave-search.args=-y,@modelcontextprotoco
|
||||
logging.level.io.modelcontextprotocol.client=WARN
|
||||
logging.level.io.modelcontextprotocol.spec=WARN
|
||||
|
||||
ai.user.input=What tools are available?
|
||||
ai.user.input=What tools are available?
|
||||
|
||||
spring.ai.mcp.client.toolcallback.enabled=true
|
||||
@@ -13,4 +13,7 @@ spring.ai.mcp.client.stdio.connections.brave-search.args=-y,@modelcontextprotoco
|
||||
logging.level.io.modelcontextprotocol.client=WARN
|
||||
logging.level.io.modelcontextprotocol.spec=WARN
|
||||
|
||||
ai.user.input=What tools are available?
|
||||
ai.user.input=What tools are available?
|
||||
|
||||
# Enable the mcp client tool-callback auto-configuration
|
||||
spring.ai.mcp.client.toolcallback.enabled=true
|
||||
@@ -22,7 +22,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-bom</artifactId>
|
||||
<version>1.0.0-M5</version>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -41,9 +41,8 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.experimental</groupId>
|
||||
<artifactId>spring-ai-mcp</artifactId>
|
||||
<version>0.6.0</version>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -2,14 +2,14 @@ package org.springframework.ai.mcp.samples.filesystem;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
import io.modelcontextprotocol.client.McpClient;
|
||||
import io.modelcontextprotocol.client.McpSyncClient;
|
||||
import io.modelcontextprotocol.client.transport.ServerParameters;
|
||||
import io.modelcontextprotocol.client.transport.StdioClientTransport;
|
||||
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.mcp.client.McpClient;
|
||||
import org.springframework.ai.mcp.client.McpSyncClient;
|
||||
import org.springframework.ai.mcp.client.transport.ServerParameters;
|
||||
import org.springframework.ai.mcp.client.transport.StdioClientTransport;
|
||||
import org.springframework.ai.mcp.spring.McpFunctionCallback;
|
||||
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@@ -25,22 +25,22 @@ public class Application {
|
||||
|
||||
@Bean
|
||||
public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder,
|
||||
List<McpFunctionCallback> functionCallbacks, ConfigurableApplicationContext context) {
|
||||
McpSyncClient mcpClient, ConfigurableApplicationContext context) {
|
||||
|
||||
return args -> {
|
||||
var chatClient = chatClientBuilder
|
||||
.defaultFunctions(functionCallbacks.toArray(new McpFunctionCallback[0]))
|
||||
.defaultTools(new SyncMcpToolCallbackProvider(mcpClient))
|
||||
.build();
|
||||
|
||||
System.out.println("Running predefined questions with AI model responses:\n");
|
||||
|
||||
// Question 1
|
||||
String question1 = "Can you explain the content of the spring-ai-mcp-overview.txt file?";
|
||||
String question1 = "Can you explain the content of the target/spring-ai-mcp-overview.txt file?";
|
||||
System.out.println("QUESTION: " + question1);
|
||||
System.out.println("ASSISTANT: " + chatClient.prompt(question1).call().content());
|
||||
|
||||
// Question 2
|
||||
String question2 = "Pleses summarize the content of the spring-ai-mcp-overview.txt file and store it a new summary.md as Markdown format?";
|
||||
String question2 = "Pleses summarize the content of the target/spring-ai-mcp-overview.txt file and store it a new target/summary.md as Markdown format?";
|
||||
System.out.println("\nQUESTION: " + question2);
|
||||
System.out.println("ASSISTANT: " +
|
||||
chatClient.prompt(question2).call().content());
|
||||
@@ -50,17 +50,6 @@ public class Application {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public List<McpFunctionCallback> functionCallbacks(McpSyncClient mcpClient) {
|
||||
|
||||
var callbacks = mcpClient.listTools(null)
|
||||
.tools()
|
||||
.stream()
|
||||
.map(tool -> new McpFunctionCallback(mcpClient, tool))
|
||||
.toList();
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "close")
|
||||
public McpSyncClient mcpClient() {
|
||||
|
||||
|
||||
@@ -44,17 +44,16 @@ public class McpClientApplication {
|
||||
|
||||
@Bean
|
||||
public CommandLineRunner predefinedQuestions(OpenAiChatModel openAiChatModel,
|
||||
ConfigurableApplicationContext context, ObjectProvider<List<McpSyncClient>> mcpClientsProvider) {
|
||||
ConfigurableApplicationContext context, List<McpSyncClient> mcpClients) {
|
||||
|
||||
return args -> {
|
||||
|
||||
var mcpToolProvider = new SyncMcpToolCallbackProvider(
|
||||
mcpClientsProvider.stream().flatMap(List::stream).toList());
|
||||
var mcpToolProvider = new SyncMcpToolCallbackProvider(mcpClients);
|
||||
|
||||
ChatClient chatClient = ChatClient.builder(openAiChatModel).defaultTools(mcpToolProvider).build();
|
||||
|
||||
String userQuestion = """
|
||||
What is the wather in Amsterdam right now?
|
||||
What is the weather in Amsterdam right now?
|
||||
Please incorporate all createive responses from all LLM providers.
|
||||
After the other providers add a poem that synthesizes the the poems from all the other providers.
|
||||
""";
|
||||
@@ -69,8 +68,8 @@ public class McpClientApplication {
|
||||
@Bean
|
||||
McpSyncClientCustomizer samplingCustomizer(Map<String, ChatClient> chatClients) {
|
||||
|
||||
return (name, spec) -> {
|
||||
spec.sampling(llmRequest -> {
|
||||
return (name, mcpClientSpec) -> {
|
||||
mcpClientSpec.sampling(llmRequest -> {
|
||||
var userPrompt = ((McpSchema.TextContent) llmRequest.messages().get(0).content()).text();
|
||||
String modelHint = llmRequest.modelPreferences().hints().get(0).name();
|
||||
|
||||
|
||||
@@ -11,3 +11,6 @@ spring.ai.mcp.client.sse.connections.server1.url=http://localhost:8080
|
||||
|
||||
logging.level.io.modelcontextprotocol.client=WARN
|
||||
logging.level.io.modelcontextprotocol.spec=WARN
|
||||
|
||||
|
||||
# spring.ai.mcp.client.toolcallback.enabled=false
|
||||
@@ -22,7 +22,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-bom</artifactId>
|
||||
<version>1.0.0-M5</version>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -41,9 +41,8 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.experimental</groupId>
|
||||
<artifactId>spring-ai-mcp</artifactId>
|
||||
<version>0.6.0</version>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -5,14 +5,15 @@ import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
import io.modelcontextprotocol.client.McpClient;
|
||||
import io.modelcontextprotocol.client.McpSyncClient;
|
||||
import io.modelcontextprotocol.client.transport.ServerParameters;
|
||||
import io.modelcontextprotocol.client.transport.StdioClientTransport;
|
||||
|
||||
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.mcp.client.McpClient;
|
||||
import org.springframework.ai.mcp.client.McpSyncClient;
|
||||
import org.springframework.ai.mcp.client.transport.ServerParameters;
|
||||
import org.springframework.ai.mcp.client.transport.StdioClientTransport;
|
||||
import org.springframework.ai.mcp.spring.McpFunctionCallback;
|
||||
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@@ -28,12 +29,12 @@ public class Application {
|
||||
|
||||
@Bean
|
||||
public CommandLineRunner interactiveChat(ChatClient.Builder chatClientBuilder,
|
||||
List<McpFunctionCallback> functionCallbacks,
|
||||
List<McpSyncClient> mcpClients,
|
||||
ConfigurableApplicationContext context) {
|
||||
return args -> {
|
||||
|
||||
var chatClient = chatClientBuilder
|
||||
.defaultFunctions(functionCallbacks.toArray(new McpFunctionCallback[0]))
|
||||
.defaultTools(new SyncMcpToolCallbackProvider(mcpClients))
|
||||
.defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory()))
|
||||
.build();
|
||||
|
||||
@@ -61,16 +62,6 @@ public class Application {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public List<McpFunctionCallback> functionCallbacks(McpSyncClient mcpClient) {
|
||||
|
||||
var callbacks = mcpClient.listTools(null)
|
||||
.tools()
|
||||
.stream()
|
||||
.map(tool -> new McpFunctionCallback(mcpClient, tool))
|
||||
.toList();
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "close")
|
||||
public McpSyncClient mcpClient() {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-bom</artifactId>
|
||||
<version>1.0.0-M5</version>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -41,9 +41,8 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.experimental</groupId>
|
||||
<artifactId>spring-ai-mcp</artifactId>
|
||||
<version>0.6.0</version>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,12 +4,13 @@ import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
import io.modelcontextprotocol.client.McpClient;
|
||||
import io.modelcontextprotocol.client.McpSyncClient;
|
||||
import io.modelcontextprotocol.client.transport.ServerParameters;
|
||||
import io.modelcontextprotocol.client.transport.StdioClientTransport;
|
||||
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.mcp.client.McpClient;
|
||||
import org.springframework.ai.mcp.client.McpSyncClient;
|
||||
import org.springframework.ai.mcp.client.transport.ServerParameters;
|
||||
import org.springframework.ai.mcp.client.transport.StdioClientTransport;
|
||||
import org.springframework.ai.mcp.spring.McpFunctionCallback;
|
||||
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@@ -25,11 +26,11 @@ public class Application {
|
||||
|
||||
@Bean
|
||||
public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder,
|
||||
List<McpFunctionCallback> functionCallbacks, ConfigurableApplicationContext context) {
|
||||
List<McpSyncClient> mcpClients, ConfigurableApplicationContext context) {
|
||||
|
||||
return args -> {
|
||||
var chatClient = chatClientBuilder
|
||||
.defaultFunctions(functionCallbacks.toArray(new McpFunctionCallback[0]))
|
||||
.defaultTools(new SyncMcpToolCallbackProvider(mcpClients))
|
||||
.build();
|
||||
System.out.println("Running predefined questions with AI model responses:\n");
|
||||
|
||||
@@ -59,17 +60,6 @@ public class Application {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public List<McpFunctionCallback> functionCallbacks(McpSyncClient mcpClient) {
|
||||
|
||||
var callbacks = mcpClient.listTools(null)
|
||||
.tools()
|
||||
.stream()
|
||||
.map(tool -> new McpFunctionCallback(mcpClient, tool))
|
||||
.toList();
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "close")
|
||||
public McpSyncClient mcpClient() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user