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消息发送到 Server
  • eventStream:初始化并启动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-webapache-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 上下文信息

参考文档

相关推荐
HyperAI超神经2 小时前
在线教程丨微软开源3D生成模型TRELLIS.2,3秒生成高分辨率的全纹理资产
人工智能·深度学习·机器学习·3d
永霖光电_UVLED2 小时前
连续波 UV-B 激光二极管问世,实现全球首次
大数据·人工智能·uv
有Li2 小时前
LoViT:用于手术阶段识别的长视频Transformer/文献速递-基于人工智能的医学影像技术
论文阅读·人工智能·深度学习·文献·医学生
油泼辣子多加2 小时前
【信创】华为昇腾NLP算法训练
人工智能·算法·机器学习·华为·自然语言处理
2 小时前
java关于数组
java
杨_晨2 小时前
大模型微调训练FAQ - Batch Size与参数配置
人工智能·机器学习·ai·语言模型·batch
不吃香菜学java2 小时前
springboot左脚踩右脚螺旋升天系列-入门程序
java·spring boot·后端
测试_AI_一辰2 小时前
Agent & RAG 测试工程 02:RAG 从最小闭环到可信
开发语言·前端·人工智能·github·ai编程
浔川python社2 小时前
《C++ 小程序编写系列》(第七部):C++11 + 新特性实战 —— 性能与稳定性双提升
java·c++·小程序