金色农场种植
46.30M · 2026-02-24
MCP(Model Context Protocol) 是一种让 LLM 与外部工具/资源交互的标准化协议:
在 Spring AI 1.1.2 之前,要给模型接外部工具需要手写 @Tool 或 FunctionCallback。MCP 的好处在于:你不需要自己写工具实现,直接复用社区已有的 MCP Server(数百个可用),配置即集成。
| 组件 | 版本 |
|---|---|
| Spring Boot | 3.5.9 |
| Spring AI | 1.1.2 |
| Spring AI MCP Client Starter | 1.1.2 |
| Java | 17 |
| MCP Server 示例 | tavily-mcp (via npx) |
在父 pom.xml 的 <properties> 中声明版本号:
<properties>
<spring-ai.version>1.1.2</spring-ai.version>
</properties>
在 <dependencyManagement> 中引入 BOM,这样所有子模块无需重复写版本号:
<dependencyManagement>
<dependencies>
<!-- Spring AI BOM -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- MCP Client Starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
<version>${spring-ai.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
我把 AI 相关能力封装在 framework-ai 模块中,核心依赖如下:
<dependencies>
<!-- Spring AI - OpenAI Starter(兼容 OpenAI 协议的模型均可用) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<!-- Spring AI MCP Client Starter(关键!) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<!-- WebFlux(用于流式输出) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
MCP 支持多种传输方式(stdio、HTTP/SSE 等)。这里演示最常用的 stdio 模式——Spring 应用启动一个子进程,通过标准输入输出与 MCP Server 通信。
在 application.yml(或对应 profile 配置)中添加:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
base-url: ${OPENAI_BASE_URL}
embedding:
options:
model: ${OPENAI_EMBEDDING_MODEL}
# MCP 客户端配置
mcp:
client:
type: SYNC # 同步模式(适配 Servlet 应用)
request-timeout: 60s # 工具调用超时时间
initialized: true # 启动时初始化连接并拉取工具列表
stdio:
connections:
tavily: # 连接名称(可自定义)
command: cmd.exe # Windows 下使用 cmd
args:
- /c
- npx
- -y
- tavily-mcp@latest
env:
TAVILY_API_KEY: ${TAVILY_API_KEY}
**type: SYNC**Spring AI MCP Client 支持 SYNC 和 ASYNC 两种模式。如果你是传统 Servlet 应用(Spring MVC),选 SYNC;如果是全响应式应用(Spring WebFlux),选 ASYNC。
**initialized: true**启动时立即初始化 MCP 连接并拉取工具列表。如果设为 false,第一次调用时才会初始化,可能导致首次响应慢或"工具未生效"的问题。强烈建议设为 true。
**stdio.connections.tavily**定义一个名为 tavily 的 stdio 连接:
command + args:拼起来就是 cmd.exe /c npx -y tavily-mcp@latest,即通过 npx 拉取并运行 tavily-mcpenv:只注入到子进程的环境变量,API Key 不会暴露给模型直接在 stdio.connections 下添加更多连接即可,例如同时接入搜索和文件系统:
spring:
ai:
mcp:
client:
type: SYNC
initialized: true
stdio:
connections:
tavily:
command: cmd.exe
args: ["/c", "npx", "-y", "tavily-mcp@latest"]
env:
TAVILY_API_KEY: ${TAVILY_API_KEY}
filesystem:
command: cmd.exe
args: ["/c", "npx", "-y", "@anthropic/mcp-filesystem@latest", "D:/docs"]
所有连接的工具会自动合并,模型可以同时使用多个 MCP Server 提供的工具。
spring-ai-starter-mcp-client 会自动完成以下工作:
ToolCallbackToolCallbackProvider Bean 到 Spring 容器你要做的只有一件事:把 ToolCallbackProvider 挂到 ChatClient 上。
@Configuration
public class LanjiiAiAutoConfiguration {
/**
* 聊天记忆(滑动窗口,保留最近 20 条消息)
*/
@Bean
public ChatMemory chatMemory() {
return MessageWindowChatMemory.builder()
.maxMessages(20)
.build();
}
/**
* 向量存储(用于 RAG,非 MCP 必须)
*/
@Bean
public VectorStore vectorStore(EmbeddingModel embeddingModel) {
return SimpleVectorStore.builder(embeddingModel).build();
}
}
@Component
@RequiredArgsConstructor
public class DynamicChatClientFactory {
private final AiModelConfigService aiModelConfigService;
private final AiRolePromptService aiRolePromptService;
private final ModelChatStrategyFactory modelChatStrategyFactory;
private final ChatMemory chatMemory;
private final ToolCallbackProvider toolCallbackProvider; // MCP 自动注入
public ChatClient buildDefaultClient() {
AiModelConfig config = aiModelConfigService.getDefaultConfig();
if (config == null) {
throw new BizException(ResultCode.NOT_FOUND,
"未找到默认启用的模型配置,请先在模型配置中设置默认模型");
}
// 通过策略模式动态构建 ChatModel(支持 OpenAI/DeepSeek/智谱 等)
ModelChatStrategy strategy = modelChatStrategyFactory
.getStrategy(config.getApiProvider());
ChatModel chatModel = strategy.buildChatModel(toModelConfig(config));
String systemPrompt = "你是一个智能助手...";
// 如果配置了角色提示词,优先使用
if (config.getRoleId() != null) {
AiRolePrompt rolePrompt = aiRolePromptService.getById(config.getRoleId());
if (rolePrompt != null && rolePrompt.getSystemPrompt() != null) {
systemPrompt = rolePrompt.getSystemPrompt();
}
}
return ChatClient.builder(chatModel)
.defaultSystem(systemPrompt)
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(chatMemory).build()
)
.defaultToolCallbacks(toolCallbackProvider) // 关键:挂载 MCP 工具
.build();
}
}
核心就一行:.defaultToolCallbacks(toolCallbackProvider)
这行代码的效果是:
@Service
@RequiredArgsConstructor
public class ChatServiceImpl implements ChatService {
private final DynamicChatClientFactory dynamicChatClientFactory;
@Override
public Flux<String> chatStream(String message, String conversationId) {
ChatClient chatClient = dynamicChatClientFactory.buildDefaultClient();
return chatClient.prompt()
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
.user(message)
.stream()
.content();
}
}
@RestController
@RequestMapping("/chat")
@RequiredArgsConstructor
public class ChatBotController {
private final ChatService chatService;
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(String message, String conversationId) {
return chatService.chatStream(message, conversationId);
}
}
启动应用后,你会在控制台看到 MCP 初始化日志:
i.m.client.transport.StdioClientTransport:106 - MCP server starting.
i.m.client.transport.StdioClientTransport:137 - MCP server started
然后向 /chat/stream?message=今天杭州天气怎么样&conversationId=test1 发请求,模型会:
tavily_search 工具整个过程模型自主决策,你不需要写任何 if-else 判断"什么时候该搜索"。
cmd.exe /c在 Windows 环境下,npx 实际是 .cmd 脚本,不能直接作为 command 启动。必须通过 cmd.exe /c npx ... 来执行,否则会报进程启动失败。
initialized: true 不可省略如果不设置 initialized: true,MCP Client 不会在启动时主动初始化,可能导致:
spring-boot-starter-web(Servlet)→ 选 SYNCASYNCSYNCstdio 方式使用 npx 运行 MCP Server,前提是服务器上已安装 Node.js。验证方式:
node -v # 确保有输出,建议 >= 18
npx -v # 确保 npx 可用
默认超时可能不够,尤其是 Tavily 搜索可能耗时较长。建议设置 request-timeout: 60s 或更大值。
完整源码:gitee.com/leven2018/l…
欢迎 Star ⭐ 和 Fork,项目包含本文涉及的所有代码(MCP 集成、多模型动态切换、RAG 知识库等)。
在线体验:
可以直接登录后台,在 AI 对话模块中体验 MCP 工具调用的实际效果。
一天一个开源项目(第31篇):awesome-openclaw-usecases - OpenClaw 真实用例集合
打造 ML/AI 系统的内部开发者平台(IDP)——设计可靠的机器学习(ML)系统
2026-02-24
2026-02-24