MCP
MCP(Model Context Protocol)是 AI 模型与外部工具服务器的标准通信协议。Spring AI 的 MCP 集成让 ChatClient 能够调用任何实现了 MCP 协议的工具服务器——无论使用何种编程语言或运行环境——就像调用本地的 @Tool 方法一样。
Spring AI 1.1.6 内置 MCP SDK 0.18.2(升级自 1.1.5 的 0.17.0)。新增 mcp-annotations-spring 模块(0.9.0),支持 Spring 风格的 MCP 注解。1.1.0 对 MCP 架构进行了全面重构,从单模块拆分为六模块:
客户端:common → httpclient / webflux
服务端:common → webmvc / webflux
新增 Streamable HTTP 传输和 SSE HTTP Client 传输,支持工具回调缓存和客户端注解扫描。
ChatClient → ToolCallback → McpClient → 传输层(STDIO / SSE / Streamable HTTP) → MCP Server → 实际工具
1. 客户端:调用外部 MCP 工具
1.1 自动配置(YAML)
引入 spring-ai-starter-mcp-client 后,通过 YAML 配置 MCP 服务器连接,工具会自动注册到 ChatClient。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
- STDIO
- SSE
- Streamable HTTP(1.1.0 新增)
spring:
ai:
mcp:
client:
enabled: true
type: SYNC
stdio:
connections:
weather-server:
command: python
args: ["/opt/mcp-servers/weather-server.py"]
spring:
ai:
mcp:
client:
enabled: true
type: SYNC
sse:
connections:
weather-server:
url: http://localhost:8080
spring:
ai:
mcp:
client:
enabled: true
type: SYNC
streamable-http:
connections:
weather-server:
url: http://localhost:8080/mcp
客户端配置项:
| 配置项 | 默认值 | 说明 |
|---|---|---|
spring.ai.mcp.client.enabled | true | 是否启用 MCP 客户端 |
spring.ai.mcp.client.type | SYNC | 客户端类型,SYNC 或 ASYNC |
spring.ai.mcp.client.name | spring-ai-mcp-client | 向服务器报告的客户端名称 |
spring.ai.mcp.client.version | 1.0.0 | 客户端版本 |
spring.ai.mcp.client.request-timeout | 20s | 请求超时时间 |
spring.ai.mcp.client.toolcallback.enabled | true | 是否自动注册为 ToolCallback |
spring.ai.mcp.client.stdio.connections.<name>.command | - | STDIO 模式下执行的命令 |
spring.ai.mcp.client.stdio.connections.<name>.args | - | 命令行参数列表 |
spring.ai.mcp.client.sse.connections.<name>.url | - | SSE 服务端点 URL |
spring.ai.mcp.client.streamable-http.connections.<name>.url | - | Streamable HTTP 端点 URL |
配置完成后无需任何 Java 代码——MCP 服务器的工具自动出现在 ChatClient 中:
@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
return builder.build();
}
// MCP 服务器的工具会自动可用
String response = chatClient.prompt()
.user("北京今天天气怎么样?")
.call()
.content();
1.2 编程式创建
适合需要动态管理连接或细粒度控制的场景:
// 创建 STDIO 传输
var transport = new StdioClientTransport(
ServerParameters.builder("python")
.args(List.of("/opt/mcp-servers/weather-server.py"))
.build());
// 创建 MCP 客户端
McpSyncClient mcpClient = McpClient.sync(transport)
.clientInfo(new Implementation("my-app", "1.0.0"))
.requestTimeout(Duration.ofSeconds(20))
.build();
mcpClient.initialize();
// 包装为 ToolCallbackProvider
ToolCallbackProvider provider = new SyncMcpToolCallbackProvider(mcpClient);
// 注册到 ChatClient
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultToolCallbacks(provider)
.build();
2. 工具过滤
当 MCP 服务器提供的工具较多时,可按名称过滤只需部分工具:
// 仅保留以 "weather_" 开头的工具
BiPredicate<McpSyncClient, Tool> weatherOnly =
(client, tool) -> tool.name().startsWith("weather_");
ToolCallbackProvider provider = new SyncMcpToolCallbackProvider(weatherOnly, mcpClient);
2.1 工具回调缓存(1.1.0 新增)
MCP 工具列表通过事件驱动缓存机制(McpAsyncToolsChangeEventEmmiter / McpSyncToolsChangeEventEmmiter)管理,避免每次请求都重复获取工具列表,减少通信开销。
2.2 客户端注解扫描(1.1.0 新增)
McpClientAnnotationScannerAutoConfiguration 自动扫描 @McpTool 注解的方法并注册为工具回调,简化客户端工具接入流程。
3. 自定义客户端
通过实现 McpSyncClientCustomizer 在客户端创建前注入自定义配置:
@Component
public class WeatherClientCustomizer implements McpSyncClientCustomizer {
@Override
public void customize(String serverName, McpClient.SyncSpec spec) {
if ("weather-server".equals(serverName)) {
spec.requestTimeout(Duration.ofSeconds(30));
}
}
}
4. 服务端:将 Spring AI 工具暴露为 MCP 工具
Spring AI 也可以作为 MCP 服务器,将 @Tool 方法暴露给外部 MCP 客户端调用。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
spring:
ai:
mcp:
server:
enabled: true
name: "spring-ai-tools"
version: "1.0.0"
instructions: "提供天气查询、计算等工具"
服务端会自动收集所有 ToolCallback 和 ToolCallbackProvider Bean,转换为 MCP 工具规格。
服务端配置项:
| 配置项 | 默认值 | 说明 |
|---|---|---|
spring.ai.mcp.server.enabled | true | 是否启用 MCP 服务器 |
spring.ai.mcp.server.type | SYNC | 服务器类型 |
spring.ai.mcp.server.name | mcp-server | 服务器名称 |
spring.ai.mcp.server.version | 1.0.0 | 服务器版本 |
spring.ai.mcp.server.instructions | - | 客户端可见的说明文本 |
spring.ai.mcp.server.stdio | false | 启用 STDIO 传输(有 Web 框架时默认禁用以使用 SSE) |
4.1 MCP Server ObjectMapper
Spring AI 1.0.7 新增 McpServerObjectMapperAutoConfiguration,自动注册名为 mcpServerObjectMapper 的 ObjectMapper Bean,配置为符合 MCP 协议规范的 JSON 序列化:
- 禁止将日期写为时间戳(
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) - 忽略未知属性(
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - 序列化时排除 null 值(
JsonInclude.Include.NON_NULL)
如需自定义序列化行为,提供同名的 mcpServerObjectMapper Bean 即可覆盖。
@Bean("mcpServerObjectMapper")
public ObjectMapper customMcpServerObjectMapper() {
return JsonMapper.builder()
.serializationInclusion(JsonInclude.Include.NON_EMPTY)
.build();
}
5. 完整示例:服务端 + 客户端
以下示例展示一个完整的 MCP 调用链路——服务端通过 STDIO 暴露天气工具,客户端连接后由 ChatClient 自动发现并调用。
5.1 服务端(天气 MCP Server)
独立 Spring Boot 应用,使用 @Tool 注解定义工具方法,通过 MCP Server 暴露。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
spring:
ai:
mcp:
server:
enabled: true
name: "weather-mcp-server"
version: "1.0.0"
instructions: "提供全球城市天气查询服务"
stdio: true
@SpringBootApplication
public class WeatherMcpServerApplication {
public static void main(String[] args) {
SpringApplication.run(WeatherMcpServerApplication.class, args);
}
@Bean
public WeatherTools weatherTools() {
return new WeatherTools();
}
static class WeatherTools {
@Tool(description = "获取指定城市的实时天气信息")
public String getWeather(
@ToolParam(description = "城市名称,如 Beijing、Shanghai") String city) {
return city + ":晴,25°C,湿度 60%,风力 3 级";
}
@Tool(description = "获取指定城市未来 N 天的天气预报")
public String getForecast(
@ToolParam(description = "城市名称") String city,
@ToolParam(description = "预报天数") int days) {
return city + "未来" + days + "天天气:以晴为主,22-28°C";
}
}
}
服务端启动后通过 STDIO 监听,等待客户端连接并调用工具。
5.2 客户端(ChatClient + MCP Client)
另一个 Spring Boot 应用,通过 MCP Client 连接上述天气服务器,ChatClient 自动发现并调用天气工具。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>
spring:
ai:
mcp:
client:
enabled: true
stdio:
connections:
weather-server:
command: java
args: ["-jar", "/path/to/weather-mcp-server.jar"]
ollama:
base-url: http://localhost:11434
chat:
options:
model: qwen3:8b
@SpringBootApplication
public class WeatherClientApplication {
public static void main(String[] args) {
var ctx = SpringApplication.run(WeatherClientApplication.class, args);
ChatClient chatClient = ctx.getBean(ChatClient.class);
// MCP 工具已自动注册,直接使用
System.out.println("=== 单工具调用 ===");
String response1 = chatClient.prompt()
.user("北京今天天气怎么样?")
.call()
.content();
System.out.println(response1);
System.out.println("=== 多工具调用 ===");
String response2 = chatClient.prompt()
.user("查询上海今天天气和未来3天的预报")
.call()
.content();
System.out.println(response2);
}
}
5.3 执行流程
1. 启动 weather-mcp-server.jar → STDIO 监听
2. 启动 WeatherClientApplication → McpClientAutoConfiguration 自动创建 McpSyncClient
→ McpToolCallbackAutoConfiguration 自动发现服务端工具并注册为 ToolCallback
3. chatClient.prompt("北京今天天气怎么样?").call()
→ ChatModel 识别到需要调用 getWeather 工具
→ DefaultToolCallingManager 通过 McpSyncClient 向服务端发起调用
→ 服务端执行 getWeather("北京"),返回 "北京:晴,25°C..."
→ ChatModel 基于结果生成最终回复