Spring-AI MCP 源码浅析
文章目录
- [Spring-AI MCP 源码浅析](#Spring-AI MCP 源码浅析)
MCP
- MCP是模型上下文协议,它能使LLM大语言模型能够以结构化的方式与外部工具和资源进行交互。
- MCP本质是一个远程的工具,它也需要转换为ToolCallback才能让LLM调用
- MCP不只是远程工具,还包括上下文管理,比如:传递会话上下文(如用户 ID、权限)
- MCP支持跨语言、跨服务的调用,基于传输层来屏蔽差异
MCP Java SDK 实现
- 客户端/服务器层 : McpClient 处理客户端操作,而McpServer 管理服务器端协议操作。两者都使用 McpSession 进行通信管理。
- 会话层 (McpSession): 通过 DefaultMcpSession 实现管理通信模式和状态。
- 传输层 (McpTransport): 处理 JSON-RPC 消息的序列化和反序列化,支持多种传输实现。

McpClient(客户端)
用于创建MCP客户端的工厂类,提供了同步、异步客户端的方法,并支持多种配置,提供如下核心功能
- 配置选项:运行设置请求超时、客户端能力、客户端信息、根URI等
- 工具和资源管理:支持工具发现、资源访问、提示模版处理等
- 实时更新:通过变更消费者接收工具、资源和提示的实时更新
- 日志记录:支持结构化日志记录,提供多种日志级别和日志消费者配置
内部类
- AsyncSpec:配置异步 MCP Client的构建器类
- SyncSpec:配置同步 MCP Client的构建器类
源码实例
java
public class McpConfig {
@Value("${spring.ai.mcp.client.streamable.connections.server1.url}")
private String mcpServerUrl;
@Bean
public WebClientStreamableHttpTransport mcpTransport(ObjectMapper objectMapper) {
return WebClientStreamableHttpTransport.builder(WebClient.builder())
.endpoint(mcpServerUrl)
.resumableStreams(true)
.objectMapper(objectMapper)
.openConnectionOnStartup(true)
.build();
}
@Bean
public McpAsyncClient mcpAsyncClient(WebClientStreamableHttpTransport transport) {
return McpClient.async(transport).build();
}
@Bean
public McpSchema.Tool startNotificationTool() {
// Maintain consistency py server list_tools
String inputSchema = """
""";
return McpSchema.Tool.builder()
.name("start-notification-stream")
.description("Sends a stream of notifications with configurable count and interval")
.inputSchema(inputSchema)
.build();
}
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
@Bean
public AsyncMcpToolCallback mcpToolCallback(
McpAsyncClient mcpAsyncClient,
McpSchema.Tool startNotificationTool) {
return new AsyncMcpToolCallback(mcpAsyncClient, startNotificationTool);
}
}
McpServer(服务端)
用于创建MCP Server 的工厂类,提供了同步、异步 Server 的方法,提供如下核心功能
- 暴露工具:允许AI模型调用 Server 提供的工具来执行特定操作
- 提供资源访问:为AI模型提供上下文数据,如文件、数据库等
- 管理提示模版:提供结构化的提示模版,用于与AI模型的交互
- 处理 Client 连接和请求:管理 Client 的连接,并处理其请求
内部类
- AsyncSpecification:配置异步 MCP Server 的构建器类
- SyncSpecification:配置同步 MCP Server 的构建器类
MCPSeesion(会话层)
处理客户端与服务器之间的通信,支持请求-响应、通知等两种模式,支持同步、异步的会话管理
- sendRequest:向模型端发送请求,返回指定类型的响应
- sendNotification:向客户端或服务端发送通知,适用于不需要响应的通知模式
- closeGracefully:异步关闭会话并释放资源
- close:同步关闭会话并释放相关资源
java
public interface McpSession {
<T> Mono<T> sendRequest(String method, Object requestParams, TypeReference<T> typeRef);
default Mono<Void> sendNotification(String method) {
return sendNotification(method, null);
}
Mono<Void> sendNotification(String method, Map<String, Object> params);
Mono<Void> closeGracefully();
void close();
}
McpClientSession
客户端会话实现类,负责管理与服务端之间的双向JSON-RPC通信,提供了如下核心功能
- 管理通信:处理客户端与服务器之间的请求,响应和通知
- 异步操作:基于Project Reactor的Mono实现非阻塞通信
- 会话管理:支持会话的创建、关闭(优雅关闭、立即关闭)
- 消息处理:管理请求的响应超时、消息的路由和错误处理
McpServerSession
服务端会话管理类,负责管理与客户端的双向JSON-RPC通信,提供了如下核心功能
- 管理会话周期:会话的初始化、消息处理、关闭等
- 处理JSON-RPC消息:请求、响应和通知的处理
- 维护会话状态:通过状态机管理会话的初始化状态(未初始化0、初始化中1、已初始化2)
- 与传输层交互:通过McpServerServerTransport与客户端进行消息的发送和接收
McpTransport(传输层接口)
MCP中定义异步传输层的核心接口,负责管理客户端和服务器端之间的双向通信,提供了自定义传输机制的基础,具体功能如下:
- 管理传输连接的生命周期:包括连接到建立、关闭和资源释放
- 处理来自服务器的消息和错误:
- 将客户端生成的消息发送到服务器
java
public interface McpTransport {
// 关闭传输连接并释放相关资源
default void close() {
this.closeGracefully().subscribe();
}
// 异步关闭传输连接并释放相关资源
Mono<Void> closeGracefully();
// 异步发送消息到服务器
Mono<Void> sendMessage(JSONRPCMessage message);
// 将给定数据反序列化为指定类型的对象
<T> T unmarshalFrom(Object data, TypeReference<T> typeRef);
}
McpClientTransport(客户端传输层接口)
通过connect方法,建立 Client 与 MCP Server 之间的连接
java
public interface McpClientTransport extends McpTransport {
Mono<Void> connect(Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler);
}
StdioClientTransport
通过标准输入输出流(stdin/stdout)与 Server 进程进行通信
connect:启动服务器进程并初始化消息处理流。设置进程的命令、参数和环境,然后启动输入、输出和错误处理线程sendMessage:发送JSON-RPC消息到 Server 进程closeGracefully:优雅地关闭传输、销毁进程并释放调度器资源,发送TERM信号给进程并等待其退出
WebFluxSseClientTransport
基于Server-Sent Events(SSE)的MCP客户端传输实现类,用于与 MCP Server 建立双向通信通道,基于Spring WebFlux的响应式编程,适用于Spring Boot WebFlux 应用(非阻塞)
- connect :与MCP Server 建立SSE连接,并设置消息处理管道
- 建立SSE连接
- 等待 Server 发送包含端点的endpoint事件
- 设置处理传入JSON-RPC消息的处理器
sendMessage:将JSON-RPC消息发送到 ServereventStream:初始化并启动SSE事件处理流
HttpClientSseClientTransport
基于Server-Sent Events(SSE)的MCP客户端传输实现类,用于与 MCP Server 建立双向通信通道。使用Java的HttpClient进行通信,通常为阻塞或 Future 异步,需适配为 Flux,适用于Spring Boot Web MVC 应用(阻塞)或通用 Java 应用
- connect:与 MCP Server 建立SSE连接,并设置消息处理管道
- 建立SSE连接(订阅SSE事件 + 处理SSE事件)
- 等待服务器发送包含端点的endpoint事件
- 设置处理传入JSON-RPC消息的处理器
sendMessage:将JSON-RPC消息发送到服务器
McpClientTransport对比总结
| 特性 | StdioClientTransport |
WebFluxSseClientTransport |
HttpClientSseClientTransport |
|---|---|---|---|
| 通信协议 | 标准输入/输出(stdin/stdout) | HTTP + SSE(Server-Sent Events) | HTTP + SSE(模拟或原生) |
| 部署模式 | 子进程(本地工具) | 远程 HTTP 服务(WebFlux) | 远程 HTTP 服务(通用) |
| 典型用途 | 调用本地 CLI 工具(如 Python 脚本) | 调用响应式 MCP Server(Netty) | 调用任意 HTTP MCP Server(Tomcat/Jetty/Go/Python 等) |
| I/O 模型 | 阻塞(但进程隔离) | 非阻塞、响应式(Reactor) | 阻塞 或 异步(依赖底层 HttpClient) |
| 跨语言支持 | ✅ 极强(任何能读 stdin 写 stdout 的程序) | ⚠️ 仅支持 HTTP/SSE 服务 | ⚠️ 仅支持 HTTP/SSE 服务 |
| 网络依赖 | ❌ 无(本地进程) | ✅ 需网络 + HTTP | ✅ 需网络 + HTTP |
| 安全性 | ⚠️ 进程逃逸风险(需沙箱) | ✅ 可加 TLS、认证、限流 | ✅ 可加 TLS、认证、限流 |
| 调试难度 | 中(需看子进程日志) | 低(标准 HTTP 日志) | 低(标准 HTTP 日志) |
| Spring Boot 依赖 | 无特殊要求 | spring-boot-starter-webflux |
spring-boot-starter-web 或 apache-httpclient |
McpServerTransport(服务端传输层接口)
StdioServerTransportProvider
创建StdioMcpSessionTransport实例类,通过标准输入输出流进行通信
WebFluxSseServerTransportProvider
创建WebFluxMcpSessionTransport实例,提供基于WebFlux的传输层实现。
- getRouterFunction:返回WebFlux的路由函数,定义了传输层的HTTP端点。
- GET/see:用于建立SSE连接
- POST/message:用于接收客户端消息
HttpServletSseServerTransportProvider
创建HttpServletMcpSessionTransport实例,基于Servlet API的HTTP服务器传输提供者
- doGet:处理客户端的GET请求,建立SSE连接
- doPost:处理客户端的POST请求,接收和处理客户端发送的消息
WebMvcSseServerTransportProvider
创建WebMvcMcpSessionTransport实例,基于Spring WebMVC的服务端传输提供者,支持通过SSE实现服务端与客户端之间的双向通信
- getRouterFunction:返回Web MVC的路由函数,定义了传输层的HTTP端点。
- GET/see:用于建立SSE连接
- POST/message:用于接收客户端消息
Spring AI MCP集成

SyncMcpToolCallbackProvider
集成 MCP 同步客户端的 ToolCallbackProvider,负责从一个或多个 MCP 同步服务器(通过 McpSyncClient)自动发现、收集所有可用的工具,支持对工具进行过滤,确保工具名唯一
List<McpSyncClient> mcpClients:存储所有需要集成的 MCP 同步客户端实例,用于从多个 MCP 服务器拉取工具列表BiPredicate<McpSyncClient, Tool> toolFilter:工具过滤器,允许根据客户端和工具元数据自定义过滤逻辑,决定哪些工具被暴露
java
public class SyncMcpToolCallbackProvider implements ToolCallbackProvider, ApplicationListener<McpToolsChangedEvent> {
private final List<McpSyncClient> mcpClients;
private final McpToolFilter toolFilter;
@Deprecated
public SyncMcpToolCallbackProvider(McpToolFilter toolFilter, List<McpSyncClient> mcpClients) {
this(toolFilter, McpToolNamePrefixGenerator.noPrefix(), mcpClients,
ToolContextToMcpMetaConverter.defaultConverter());
}
@Override
public ToolCallback[] getToolCallbacks() {
if (this.invalidateCache) {
this.lock.lock();
try {
if (this.invalidateCache) {
//负责从一个或多个 MCP 同步服务器(通过 McpSyncClient)自动发现、收集所有可用的工具
this.cachedToolCallbacks = this.mcpClients.stream()
.flatMap(mcpClient -> mcpClient.listTools()
.tools()
.stream()
//工具过滤器,允许根据客户端和工具元数据自定义过滤逻辑,决定哪些工具被暴露
.filter(tool -> this.toolFilter.test(connectionInfo(mcpClient), tool))
//MCP 同步工具适配为 SpringAI 中 ToolCallback 的桥接实现,详见: SyncMcpToolCallback
.<ToolCallback>map(tool -> SyncMcpToolCallback.builder()
.mcpClient(mcpClient)
.tool(tool)
.prefixedToolName(
this.toolNamePrefixGenerator.prefixedToolName(connectionInfo(mcpClient), tool))
.toolContextToMcpMetaConverter(this.toolContextToMcpMetaConverter)
.build()))
.toList();
this.validateToolCallbacks(this.cachedToolCallbacks);
this.invalidateCache = false;
}
}
finally {
this.lock.unlock();
}
}
return this.cachedToolCallbacks.toArray(new ToolCallback[0]);
}
}
SyncMcpToolCallback
MCP 同步工具适配为 SpringAI 中 ToolCallback 的桥接实现
McpSyncClient mcpClient:MCP 同步客户端实例,负责与 MCP 服务器通信、发起工具调用Tool tool:MCP 工具定义对象,包含工具的名称、描述、输入参数 schema 等元数据
java
public String call(String toolCallInput, @Nullable ToolContext toolContext) {
Map<String, Object> arguments = ModelOptionsUtils.jsonToMap(toolCallInput);
CallToolResult response;
try {
var mcpMeta = toolContext != null ? this.toolContextToMcpMetaConverter.convert(toolContext) : null;
var request = CallToolRequest.builder()
.name(this.tool.name())
.arguments(arguments)
.meta(mcpMeta)
.build();
// MCP远程调用工具
response = this.mcpClient.callTool(request);
}
catch (Exception ex) {
}
return ModelOptionsUtils.toJsonString(response.content());
}
AsyncMcpToolCallbackProvider
集成 MCP 异步客户端的 ToolCallbackProvider,其余同 SyncMcpToolCallbackProvider 一致
List<McpAsyncClient> mcpClients:存储所有需要集成的 MCP 同步客户端实例,用于从多个 MCP 服务器拉取工具列表BiPredicate<McpAsyncClient, Tool> toolFilter:工具过滤器,允许根据客户端和工具元数据自定义过滤逻辑,决定哪些工具被暴露
McpToolUtils
作为 SpringAI 与 MCP 协议集成的工具类,负责将 SpringAI 的 ToolCallback 转换为 MCP 协议兼容的同步/异步工具规范
| 方法名称 | 描述 |
|---|---|
| prefixedToolName | 避免工具名冲突,确保命名唯一性 |
| toSyncToolSpecification | 将ToolCallback转换为SyncToolSpecification |
| toSyncToolSpecifications | 批量将ToolCallback转换为SyncToolSpecification |
| getToolCallbacksFromSyncClients | 从多个同步 MCP 客户端中提取ToolCallback |
| toAsyncToolSpecification | 将ToolCallback转换为AsyncToolSpecification |
| toAsyncToolSpecifications | 批量将ToolCallback转换为AsyncToolSpecification |
| getToolCallbacksFromAsyncClients | 从多个异步 MCP 客户端中提取ToolCallback |
| getMcpExchange | 从 ToolContext 中提取 MCP 交换对象,用于在工具调用时传递 MCP 上下文信息 |