当前项目把本地作为一个MCP client, 调用外部的MCP Server
引入 Spring AI BOM 和 spring-ai-starter-mcp-client-webflux
xml
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-ai.version>1.1.0</spring-ai.version>
<spring-ai-alibaba.version>1.1.0.0-RC2</spring-ai-alibaba.version>
<spring-ai-alibaba-extensions.version>1.1.0.0-RC2</spring-ai-alibaba-extensions.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-extensions-bom</artifactId>
<version>${spring-ai-alibaba-extensions.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-bom</artifactId>
<version>${spring-ai-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.17.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client-webflux</artifactId>
</dependency>
在配置文件里声明 spring.ai.mcp.client.*
Spring AI Alibaba DashScope 配置
yaml
spring:
ai:
dashscope:
api-key: ${DASHSCOPE_API_KEY:your-api-key-here} # 从环境变量读取或使用默认值
chat:
options:
timeout: 180000 # 超时时间180秒(3分钟)
retry:
max-attempts: 3 # 最大重试次数
backoff:
initial-interval: 2000 # 初始重试间隔2秒
multiplier: 2 # 重试间隔倍数
max-interval: 10000 # 最大重试间隔10秒
启动应用,让 Spring AI 自动装配 MCP Client,并生成 ToolCallbackProvider
看一下源码
java
package org.springframework.ai.tool;
import java.util.List;
/**
* Provides {@link ToolCallback} instances for tools defined in different sources.
*
* @author Thomas Vitale
* @since 1.0.0
*/
public interface ToolCallbackProvider {
ToolCallback[] getToolCallbacks();
static ToolCallbackProvider from(List<? extends ToolCallback> toolCallbacks) {
return new StaticToolCallbackProvider(toolCallbacks);
}
static ToolCallbackProvider from(ToolCallback... toolCallbacks) {
return new StaticToolCallbackProvider(toolCallbacks);
}
}
业务层在 ChatService.java和 ChatController.java注入 ToolCallbackProvider
java
@Autowired
private ToolCallbackProvider tools;
@Autowired
private ToolCallbackProvider tools;
通过 tools.getToolCallbacks() 取出 MCP 工具
/**
* 获取工具回调列表,mcp服务提供的工具
*/
public ToolCallback[] getToolCallbacks() {
return tools.getToolCallbacks();
}
把这些 callback 传给 ReactAgent.builder().tools(...)
java
/**
* 记录可用工具列表:mcp服务提供的工具
*/
public void logAvailableTools() {
ToolCallback[] toolCallbacks = tools.getToolCallbacks();
logger.info("可用工具列表:");
for (ToolCallback toolCallback : toolCallbacks) {
logger.info(">>> {}", toolCallback.getToolDefinition().name());
}
}
如果还有本地 @Tool,用 methodTools(...) 和 MCP 的 .tools(...) 分开挂
总结
启动时序
Main 启动
-> Spring Boot 自动装配
-> 读取 MCP 配置
-> Spring AI MCP Client Starter 初始化
-> 建立 SSE MCP 连接配置
-> 生成 ToolCallbackProvider
-> 注入到 ChatService / ChatController
-> 业务代码创建 ReactAgent 时挂上 MCP tools
调用时序
前端 /api/chat 或 /api/chat_stream
-> ChatController
-> ChatService 创建 DashScopeChatModel
-> ChatService 创建 ReactAgent
-
methodTools(...) 挂本地工具
-
tools(...) 挂 MCP 远端工具
-> agent.call() / agent.stream()
-> 大模型决定是否调用 tool
-> 如果调用的是 MCP tool
-> ToolCallbackProvider 提供的 ToolCallback 被触发
-> Spring AI MCP Client 通过 SSE/HTTP 调外部 MCP Server
-> 工具结果返回给模型
-> 模型继续生成最终答案