diff --git a/model-context-protocol/brave/pom.xml b/model-context-protocol/brave/pom.xml
index 7399b44..e719089 100644
--- a/model-context-protocol/brave/pom.xml
+++ b/model-context-protocol/brave/pom.xml
@@ -1,20 +1,23 @@
-
4.0.0
org.springframework.boot
spring-boot-starter-parent
3.3.6
-
+
com.example
ai-mcp-brave
0.0.1-SNAPSHOT
Spring AI - Model Context Protocol - Brave
Simple AI Application using MCP client to use Brave for Internet search
+
17
+ 1.0.0-SNAPSHOT
@@ -22,7 +25,7 @@
org.springframework.ai
spring-ai-bom
- 1.0.0-SNAPSHOT
+ ${spring-ai.version}
pom
import
@@ -40,13 +43,11 @@
spring-ai-openai-spring-boot-starter
-
org.springframework.ai
- spring-ai-mcp
+ spring-ai-mcp-client-spring-boot-starter
-
@@ -78,4 +79,4 @@
-
+
\ No newline at end of file
diff --git a/model-context-protocol/brave/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java b/model-context-protocol/brave/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java
index e263869..0a9044a 100644
--- a/model-context-protocol/brave/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java
+++ b/model-context-protocol/brave/src/main/java/org/springframework/ai/mcp/samples/brave/Application.java
@@ -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 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;
- }
-
}
\ No newline at end of file
diff --git a/model-context-protocol/brave/src/main/resources/application.properties b/model-context-protocol/brave/src/main/resources/application.properties
index 861eae3..70c8077 100644
--- a/model-context-protocol/brave/src/main/resources/application.properties
+++ b/model-context-protocol/brave/src/main/resources/application.properties
@@ -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
diff --git a/model-context-protocol/brave/src/main/resources/mcp-servers-config.json b/model-context-protocol/brave/src/main/resources/mcp-servers-config.json
new file mode 100644
index 0000000..df98809
--- /dev/null
+++ b/model-context-protocol/brave/src/main/resources/mcp-servers-config.json
@@ -0,0 +1,13 @@
+{
+ "mcpServers": {
+ "brave-search": {
+ "command": "npx",
+ "args": [
+ "-y",
+ "@modelcontextprotocol/server-brave-search"
+ ],
+ "env": {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/model-context-protocol/client-starter/starter-default-client/src/main/resources/application.properties b/model-context-protocol/client-starter/starter-default-client/src/main/resources/application.properties
index d3b267e..0df91dc 100644
--- a/model-context-protocol/client-starter/starter-default-client/src/main/resources/application.properties
+++ b/model-context-protocol/client-starter/starter-default-client/src/main/resources/application.properties
@@ -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?
\ No newline at end of file
+ai.user.input=What tools are available?
+
+spring.ai.mcp.client.toolcallback.enabled=true
\ No newline at end of file
diff --git a/model-context-protocol/client-starter/starter-webflux-client/src/main/resources/application.properties b/model-context-protocol/client-starter/starter-webflux-client/src/main/resources/application.properties
index 007a113..6d2d730 100644
--- a/model-context-protocol/client-starter/starter-webflux-client/src/main/resources/application.properties
+++ b/model-context-protocol/client-starter/starter-webflux-client/src/main/resources/application.properties
@@ -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?
\ No newline at end of file
+ai.user.input=What tools are available?
+
+# Enable the mcp client tool-callback auto-configuration
+spring.ai.mcp.client.toolcallback.enabled=true
\ No newline at end of file
diff --git a/model-context-protocol/filesystem/pom.xml b/model-context-protocol/filesystem/pom.xml
index 765ca0e..fe874d7 100644
--- a/model-context-protocol/filesystem/pom.xml
+++ b/model-context-protocol/filesystem/pom.xml
@@ -22,7 +22,7 @@
org.springframework.ai
spring-ai-bom
- 1.0.0-M5
+ 1.0.0-SNAPSHOT
pom
import
@@ -41,9 +41,8 @@
- org.springframework.experimental
- spring-ai-mcp
- 0.6.0
+ org.springframework.ai
+ spring-ai-mcp-client-spring-boot-starter
diff --git a/model-context-protocol/filesystem/src/main/java/org/springframework/ai/mcp/samples/filesystem/Application.java b/model-context-protocol/filesystem/src/main/java/org/springframework/ai/mcp/samples/filesystem/Application.java
index 099ab0e..391dbce 100644
--- a/model-context-protocol/filesystem/src/main/java/org/springframework/ai/mcp/samples/filesystem/Application.java
+++ b/model-context-protocol/filesystem/src/main/java/org/springframework/ai/mcp/samples/filesystem/Application.java
@@ -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 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 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() {
diff --git a/model-context-protocol/sampling/mcp-sampling-client/src/main/java/org/springframework/ai/mcp/samples/client/McpClientApplication.java b/model-context-protocol/sampling/mcp-sampling-client/src/main/java/org/springframework/ai/mcp/samples/client/McpClientApplication.java
index c8854fb..5016d21 100644
--- a/model-context-protocol/sampling/mcp-sampling-client/src/main/java/org/springframework/ai/mcp/samples/client/McpClientApplication.java
+++ b/model-context-protocol/sampling/mcp-sampling-client/src/main/java/org/springframework/ai/mcp/samples/client/McpClientApplication.java
@@ -44,17 +44,16 @@ public class McpClientApplication {
@Bean
public CommandLineRunner predefinedQuestions(OpenAiChatModel openAiChatModel,
- ConfigurableApplicationContext context, ObjectProvider> mcpClientsProvider) {
+ ConfigurableApplicationContext context, List 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 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();
diff --git a/model-context-protocol/sampling/mcp-sampling-client/src/main/resources/application.properties b/model-context-protocol/sampling/mcp-sampling-client/src/main/resources/application.properties
index 5d6ea5a..6a2ece5 100644
--- a/model-context-protocol/sampling/mcp-sampling-client/src/main/resources/application.properties
+++ b/model-context-protocol/sampling/mcp-sampling-client/src/main/resources/application.properties
@@ -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
\ No newline at end of file
diff --git a/model-context-protocol/sqlite/chatbot/pom.xml b/model-context-protocol/sqlite/chatbot/pom.xml
index b0eb32f..ef7d1c1 100644
--- a/model-context-protocol/sqlite/chatbot/pom.xml
+++ b/model-context-protocol/sqlite/chatbot/pom.xml
@@ -22,7 +22,7 @@
org.springframework.ai
spring-ai-bom
- 1.0.0-M5
+ 1.0.0-SNAPSHOT
pom
import
@@ -41,9 +41,8 @@
- org.springframework.experimental
- spring-ai-mcp
- 0.6.0
+ org.springframework.ai
+ spring-ai-mcp-client-spring-boot-starter
diff --git a/model-context-protocol/sqlite/chatbot/src/main/java/org/springframework/ai/mcp/samples/sqlite/Application.java b/model-context-protocol/sqlite/chatbot/src/main/java/org/springframework/ai/mcp/samples/sqlite/Application.java
index 0993dfb..83d6254 100644
--- a/model-context-protocol/sqlite/chatbot/src/main/java/org/springframework/ai/mcp/samples/sqlite/Application.java
+++ b/model-context-protocol/sqlite/chatbot/src/main/java/org/springframework/ai/mcp/samples/sqlite/Application.java
@@ -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 functionCallbacks,
+ List 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 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() {
diff --git a/model-context-protocol/sqlite/simple/pom.xml b/model-context-protocol/sqlite/simple/pom.xml
index 0797eb3..b52dec3 100644
--- a/model-context-protocol/sqlite/simple/pom.xml
+++ b/model-context-protocol/sqlite/simple/pom.xml
@@ -22,7 +22,7 @@
org.springframework.ai
spring-ai-bom
- 1.0.0-M5
+ 1.0.0-SNAPSHOT
pom
import
@@ -41,9 +41,8 @@
- org.springframework.experimental
- spring-ai-mcp
- 0.6.0
+ org.springframework.ai
+ spring-ai-mcp-client-spring-boot-starter
diff --git a/model-context-protocol/sqlite/simple/src/main/java/org/springframework/ai/mcp/samples/sqlite/Application.java b/model-context-protocol/sqlite/simple/src/main/java/org/springframework/ai/mcp/samples/sqlite/Application.java
index 4f09466..4db16d4 100644
--- a/model-context-protocol/sqlite/simple/src/main/java/org/springframework/ai/mcp/samples/sqlite/Application.java
+++ b/model-context-protocol/sqlite/simple/src/main/java/org/springframework/ai/mcp/samples/sqlite/Application.java
@@ -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 functionCallbacks, ConfigurableApplicationContext context) {
+ List 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 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() {