MCP Client 接入
本教程共 45 篇 · 第 28 篇 · 更新于 2026-08-16 · 约 8 分钟阅读
本节目标:在自己的 Spring Boot 应用里接入 MCP 客户端,连接本地或远程 MCP 服务器,把远程工具变成 ChatClient 可调用的工具。学完你就能在对话里使用任何 MCP 服务器提供的能力。
28.1 加依赖
MCP 客户端有两个 Starter 可选。
spring-ai-starter-mcp-client 是标准版,支持 STDIO、SSE、Streamable-HTTP 和 Stateless Streamable-HTTP 四种传输。HTTP 相关的传输基于 JDK HttpClient 实现,不需要额外配置。
spring-ai-starter-mcp-client-webflux 是 WebFlux 版,HTTP 传输改用 WebClient 实现,适合响应式应用。官方建议生产环境用 WebFlux 版。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
版本由 spring-ai-bom 统一管理,不需要手写。BOM 的引入方式前面章节讲过,这里不重复。
Tip一个应用可以同时连接多个 MCP 服务器,每个连接会创建独立的客户端实例。标准版和 WebFlux 版别混用,选一个就行。
28.2 公共配置项
加完依赖,先认识几个常用配置。它们都以 spring.ai.mcp.client 开头:
- enabled:是否启用 MCP 客户端,默认 true。
- name / version:客户端标识,默认 spring-ai-mcp-client / 1.0.0,会发给服务器。
- request-timeout:请求超时,默认 20s。
- type:SYNC 或 ASYNC,默认 SYNC。
- initialized:是否在创建时初始化连接,默认 true。
- toolcallback.enabled:是否把 MCP 工具接入工具执行框架,默认 true。
这些值一般不用改。真正要动手的是下面三组连接配置。
28.3 配置连接
客户端要连接服务器,先得告诉它服务器在哪。三种传输对应三组配置,都以 spring.ai.mcp.client 开头。
STDIO 连接本地进程。服务器是另一个程序,由客户端启动,双方通过标准输入输出通信。下面配置了一个官方文件系统服务器,npx 会自动下载并运行它:
spring:
ai:
mcp:
client:
stdio:
connections:
filesystem:
command: npx
args:
- -y
- "@modelcontextprotocol/server-filesystem"
- /Users/me/Documents
也可以用外部 JSON 文件管理连接,格式和 Claude Desktop 兼容。把文件放到 classpath 下,配置指向它:
spring:
ai:
mcp:
client:
stdio:
servers-configuration: classpath:servers.json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/Documents"]
}
}
}
这种 JSON 格式目前只支持 STDIO 连接。
SSE 和 Streamable-HTTP 连接远程服务器,配置结构类似:
spring:
ai:
mcp:
client:
sse:
connections:
weather-server:
url: http://localhost:8080
streamable-http:
connections:
weather-server:
url: http://localhost:8080
sse 连接默认访问 /sse 端点,streamable-http 连接默认访问 /mcp 端点。服务器改了路径,就用 sse-endpoint 或 endpoint 属性指定。
Note每个 connection 的名字(如 weather-server)是连接标识。后面的客户端注解、工具过滤都会用到它,起名要见名知意。
TipSSE 报 404 时,先检查 url 拆分:base url 只放协议、域名、端口,路径全部放进 sse-endpoint,并以 / 开头。比如完整地址是 http://localhost:3000/mcp-hub/sse/token123,就拆成 url: http://localhost:3000 和 sse-endpoint: /mcp-hub/sse/token123。
28.4 Windows 下连 STDIO 的坑
Windows 上 npx、npm、python 都是 .cmd 批处理文件,不是原生可执行文件。Java 的 ProcessBuilder 无法直接执行批处理,必须用 cmd.exe 包一层。
{
"mcpServers": {
"filesystem": {
"command": "cmd.exe",
"args": ["/c", "npx", "-y", "@modelcontextprotocol/server-filesystem", "C:\\Users\\me\\Documents"]
}
}
}
Linux 和 macOS 不需要这层包装,直接写 npx。想让同一份配置跨平台跑,可以写 @Bean 方法,运行时检测操作系统再构建 ServerParameters。官方示例仓库 spring-ai-examples 里有现成实现,需要时去参考。
顺带说一句生命周期:应用关闭时,框架会自动关闭所有客户端连接、回收子进程,不需要手动清理。这一点对 STDIO 尤其重要,进程没退干净会留下僵尸进程。
28.5 把远程工具交给 ChatClient
配置好连接,启动时框架会自动完成三件事:连接服务器、发现工具、把全部工具打包成一个 ToolCallbackProvider Bean。把它传给 ChatClient 就能用。
@Bean
public CommandLineRunner demo(ChatClient chatClient, ToolCallbackProvider mcpTools) {
return args -> {
String response = chatClient
.prompt("What's the weather like in Paris?")
.tools(mcpTools)
.call()
.content();
System.out.println(response);
};
}
第 4 章讲过 .prompt().call().content() 的链式写法,这里只是多了一个 .tools()。模型根据对话内容决定是否调用远程工具,调用结果会作为上下文继续生成回答。模型眼里只有工具名和参数,不关心它住在哪个进程。
底层发生了什么?每个连接对应一个 McpSyncClient 实例,工具回调提供器把 MCP 工具包装成 ToolCallback。你也可以注入 List
Note客户端类型由 spring.ai.mcp.client.type 控制,默认 SYNC,可选 ASYNC。所有连接必须统一,不能混用。SYNC 模式只注册同步的注解处理方法,ASYNC 反之。
想快速验证接入是否成功,可以写一个测试接口:
@RestController
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder, ToolCallbackProvider mcpTools) {
this.chatClient = builder
.defaultTools(mcpTools)
.build();
}
@PostMapping("/chat")
public String chat(@RequestParam String query) {
return chatClient.prompt(query).call().content();
}
}
这里用 defaultTools 把远程工具设成全局默认,每个对话自动带上。和 .tools() 的区别是:.tools() 只对当前一次调用生效。
如果只想给部分对话开工具,用 .tools();希望全应用统一,用 defaultTools。两种写法都接受 ToolCallbackProvider,也可以混传本地工具和 MCP 工具,框架会自动合并。
28.6 工具过滤与命名
接入了多个服务器,工具可能重名或太多。框架提供了两个扩展点。
McpToolFilter 按条件过滤工具。实现接口并声明为 Bean,test 方法返回 true 保留、false 剔除。比如只保留某前缀的工具,或者过滤掉描述里带 experimental 的实验性工具。注意全应用只能有一个过滤器 Bean,多个条件就合并到一个实现里。
McpToolNamePrefixGenerator 控制工具名前缀。默认的 DefaultMcpToolNamePrefixGenerator 保证名字唯一:同名工具自动加 alt_1_、alt_2_ 前缀,非法字符替换成下划线,最终名字不超过 64 字符。想彻底去掉前缀,可以注册 McpToolNamePrefixGenerator.noPrefix(),但多服务器时同名工具会抛 IllegalStateException。
大多数项目用默认行为即可。这两个接口属于”需要时再看文档”的进阶能力。
还有一个相关的小知识:调用工具时可以用 ToolContext 携带额外上下文(比如用户 ID),框架默认会把上下文转成 MCP 调用的 _meta 元数据传过去。想控制转换逻辑,实现 ToolContextToMcpMetaConverter 即可,默认行为是过滤空值和内部键。
28.7 客户端注解与安全
客户端还支持注解式处理器和 OAuth2 授权,内容较多,第 31 章统一讲。这里先记住一个关键约束:注解处理器的 clients 参数必须和配置里的连接名一致,比如上面配的 weather-server。
28.8 参考实现
想看完整的可运行例子,官方仓库 spring-ai-examples 的 model-context-protocol 目录下有全套:默认客户端、WebFlux 客户端、Brave 搜索聊天机器人等。社区视频教程 spring-ai-yt-series 的 mcp-app 也是一个入门参考,它用 servers.json 连接文件系统服务器,再用 ChatClient 对话。注意它基于 Spring AI 1.1.x,2.0 里 defaultToolCallbacks 已改为 .tools() 系列 API,看代码时留意版本差异。
28.9 小结
接入 MCP 客户端只要三步:加 starter 依赖、配置连接、把 ToolCallbackProvider 传给 ChatClient。STDIO 连本地进程,Windows 上要记得 cmd.exe 包装;SSE 和 Streamable-HTTP 连远程服务,配好 url 就行。工具自动发现、自动注册,远程工具用起来和本地 @Tool 一样顺手。