Spring-AI MCP 源码浅析

MCP

  • MCP是模型上下文协议,它能使LLM大语言模型能够以结构化的方式与外部工具和资源进行交互。
    • MCP本质是一个远程的工具,它也需要转换为ToolCallback才能让LLM调用
    • MCP不只是远程工具,还包括上下文管理,比如:传递会话上下文(如用户 ID、权限)
    • MCP支持跨语言、跨服务的调用,基于传输层来屏蔽差异

MCP Java SDK 实现

  • 客户端/服务器层: McpClient 处理客户端操作,而McpServer 管理服务器端协议操作。两者都使用 McpSession 进行通信管理。
  • 会话层 (McpSession): 通过 DefaultMcpSession 实现管理通信模式和状态。
  • 传输层 (McpTransport): 处理 JSON-RPC 消息的序列化和反序列化,支持多种传输实现。

image-20260127170447695

McpClient(客户端)

用于创建MCP客户端的工厂类,提供了同步、异步客户端的方法,并支持多种配置,提供如下核心功能

  • 配置选项:运行设置请求超时、客户端能力、客户端信息、根URI等
  • 工具和资源管理:支持工具发现、资源访问、提示模版处理等
  • 实时更新:通过变更消费者接收工具、资源和提示的实时更新
  • 日志记录:支持结构化日志记录,提供多种日志级别和日志消费者配置

内部类

  • AsyncSpec:配置异步 MCP Client的构建器类
  • SyncSpec:配置同步 MCP Client的构建器类

源码实例

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:同步关闭会话并释放相关资源
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中定义异步传输层的核心接口,负责管理客户端和服务器端之间的双向通信,提供了自定义传输机制的基础,具体功能如下:

  • 管理传输连接的生命周期:包括连接到建立、关闭和资源释放
  • 处理来自服务器的消息和错误:
  • 将客户端生成的消息发送到服务器
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 之间的连接

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:用于接收客户端消息
private WebFluxSseServerTransportProvider(McpJsonMapper jsonMapper, String baseUrl, String messageEndpoint,
			String sseEndpoint, Duration keepAliveInterval,
			McpTransportContextExtractor<ServerRequest> contextExtractor) {

		this.jsonMapper = jsonMapper;
		this.baseUrl = baseUrl;
		this.messageEndpoint = messageEndpoint;
		this.sseEndpoint = sseEndpoint;
		this.contextExtractor = contextExtractor;
		this.routerFunction = RouterFunctions.route()
			//GET/see:用于建立SSE连接
			.GET(this.sseEndpoint, this::handleSseConnection)
			//POST/message:用于接收客户端消息
			.POST(this.messageEndpoint, this::handleMessage)
			.build();
		if (keepAliveInterval != null) {

			this.keepAliveScheduler = KeepAliveScheduler
				.builder(() -> (isClosing) ? Flux.empty() : Flux.fromIterable(sessions.values()))
				.initialDelay(keepAliveInterval)
				.interval(keepAliveInterval)
				.build();

			this.keepAliveScheduler.start();
		}
	}

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集成

img

Server自动注入

  • ToolCallbackConverterAutoConfiguration

    • SyncToolSpecification:ToolCallback转换为对外暴露的Tool
  • McpServerSpecificationFactoryAutoConfiguration

    • 用于扫描带注解的:@McpTool、@McpResource、@McpPrompt、@McpComplete 映射 SyncToolSpecification、SyncResourceSpecification、SyncPromptSpecification、SyncCompletionSpecification
  • McpServerSseWebFluxAutoConfiguration

    • WebFluxSseServerTransportProvider:提供了处理SSE连接和消息的能力,处理 Client 连接和请求
  • McpServerAutoConfiguration

    • McpSyncServer:暴露工具、提供资源访问、管理提示模版
# org.springframework.ai.mcp.server.common.autoconfigure.McpServerAutoConfiguration

@Bean
  @ConditionalOnProperty(prefix = McpServerProperties.CONFIG_PREFIX, name = "type", havingValue = "SYNC",
                         matchIfMissing = true)
public McpSyncServer mcpSyncServer(McpServerTransportProviderBase transportProvider,
                                     McpSchema.ServerCapabilities.Builder capabilitiesBuilder, McpServerProperties serverProperties,
                                     McpServerChangeNotificationProperties changeNotificationProperties,
                                     ObjectProvider<List<SyncToolSpecification>> tools,
                                     ObjectProvider<List<SyncResourceSpecification>> resources,
                                     ObjectProvider<List<SyncResourceTemplateSpecification>> resourceTemplates,
                                     ObjectProvider<List<SyncPromptSpecification>> prompts,
                                     ObjectProvider<List<SyncCompletionSpecification>> completions,
                                     ObjectProvider<BiConsumer<McpSyncServerExchange, List<McpSchema.Root>>> rootsChangeConsumers,
                                     Environment environment) {

  McpSchema.Implementation serverInfo = new Implementation(serverProperties.getName(),
                                                           serverProperties.getVersion());

  // Create the server with both tool and resource capabilities
  SyncSpecification<?> serverBuilder;
  if (transportProvider instanceof McpStreamableServerTransportProvider) {
    serverBuilder = McpServer.sync((McpStreamableServerTransportProvider) transportProvider);
  }
  else {
    serverBuilder = McpServer.sync((McpServerTransportProvider) transportProvider);
  }
  serverBuilder.serverInfo(serverInfo);

  // Tools
  if (serverProperties.getCapabilities().isTool()) {
    logger.info("Enable tools capabilities, notification: "
                + changeNotificationProperties.isToolChangeNotification());
    capabilitiesBuilder.tools(changeNotificationProperties.isToolChangeNotification());

    List<SyncToolSpecification> toolSpecifications = new ArrayList<>(
      tools.stream().flatMap(List::stream).toList());

    if (!CollectionUtils.isEmpty(toolSpecifications)) {
      serverBuilder.tools(toolSpecifications);
      logger.info("Registered tools: " + toolSpecifications.size());
    }
  }

  // Resources
  if (serverProperties.getCapabilities().isResource()) {
    logger.info("Enable resources capabilities, notification: "
                + changeNotificationProperties.isResourceChangeNotification());
    capabilitiesBuilder.resources(false, changeNotificationProperties.isResourceChangeNotification());

    List<SyncResourceSpecification> resourceSpecifications = resources.stream().flatMap(List::stream).toList();
    if (!CollectionUtils.isEmpty(resourceSpecifications)) {
      serverBuilder.resources(resourceSpecifications);
      logger.info("Registered resources: " + resourceSpecifications.size());
    }
  }

  // Resources Templates
  if (serverProperties.getCapabilities().isResource()) {
    logger.info("Enable resources templates capabilities, notification: "
                + changeNotificationProperties.isResourceChangeNotification());
    capabilitiesBuilder.resources(false, changeNotificationProperties.isResourceChangeNotification());

    List<SyncResourceTemplateSpecification> resourceTemplateSpecifications = resourceTemplates.stream()
      .flatMap(List::stream)
      .toList();
    if (!CollectionUtils.isEmpty(resourceTemplateSpecifications)) {
      serverBuilder.resourceTemplates(resourceTemplateSpecifications);
      logger.info("Registered resource templates: " + resourceTemplateSpecifications.size());
    }
  }

  // Prompts
  if (serverProperties.getCapabilities().isPrompt()) {
    logger.info("Enable prompts capabilities, notification: "
                + changeNotificationProperties.isPromptChangeNotification());
    capabilitiesBuilder.prompts(changeNotificationProperties.isPromptChangeNotification());

    List<SyncPromptSpecification> promptSpecifications = prompts.stream().flatMap(List::stream).toList();
    if (!CollectionUtils.isEmpty(promptSpecifications)) {
      serverBuilder.prompts(promptSpecifications);
      logger.info("Registered prompts: " + promptSpecifications.size());
    }
  }

  // Completions
  if (serverProperties.getCapabilities().isCompletion()) {
    logger.info("Enable completions capabilities");
    capabilitiesBuilder.completions();

    List<SyncCompletionSpecification> completionSpecifications = completions.stream()
      .flatMap(List::stream)
      .toList();
    if (!CollectionUtils.isEmpty(completionSpecifications)) {
      serverBuilder.completions(completionSpecifications);
      logger.info("Registered completions: " + completionSpecifications.size());
    }
  }

  rootsChangeConsumers.ifAvailable(consumer -> {
    BiConsumer<McpSyncServerExchange, List<McpSchema.Root>> syncConsumer = (exchange, roots) -> consumer
      .accept(exchange, roots);
    serverBuilder.rootsChangeHandler(syncConsumer);
    logger.info("Registered roots change consumer");
  });

  serverBuilder.capabilities(capabilitiesBuilder.build());

  serverBuilder.instructions(serverProperties.getInstructions());

  serverBuilder.requestTimeout(serverProperties.getRequestTimeout());
  if (environment instanceof StandardServletEnvironment) {
    serverBuilder.immediateExecution(true);
  }

  return serverBuilder.build();
}

Client自动注入

  • Client自动注入:本质是调用McpSyncClient获取Tool必过转换为ToolCallback供大模型调用,基于SyncMcpToolCallbackProvider来集成

  • SseWebFluxTransportAutoConfiguration

    • NamedClientMcpTransport:构建 MCP 客户端传输
  • McpClientAutoConfiguration

    • 基于NamedClientMcpTransport来构建McpSyncClient
@Bean
	@ConditionalOnProperty(prefix = McpClientCommonProperties.CONFIG_PREFIX, name = "type", havingValue = "SYNC",
			matchIfMissing = true)
	public List<McpSyncClient> mcpSyncClients(McpSyncClientConfigurer mcpSyncClientConfigurer,
			McpClientCommonProperties commonProperties,
			ObjectProvider<List<NamedClientMcpTransport>> transportsProvider,
			ClientMcpSyncHandlersRegistry clientMcpSyncHandlersRegistry) {

		List<McpSyncClient> mcpSyncClients = new ArrayList<>();

		List<NamedClientMcpTransport> namedTransports = transportsProvider.stream().flatMap(List::stream).toList();

		if (!CollectionUtils.isEmpty(namedTransports)) {
			for (NamedClientMcpTransport namedTransport : namedTransports) {

				McpSchema.Implementation clientInfo = new McpSchema.Implementation(
						this.connectedClientName(commonProperties.getName(), namedTransport.name()),
						namedTransport.name(), commonProperties.getVersion());

				McpClient.SyncSpec spec = McpClient.sync(namedTransport.transport())
					.clientInfo(clientInfo)
					.requestTimeout(commonProperties.getRequestTimeout())
					.sampling(samplingRequest -> clientMcpSyncHandlersRegistry.handleSampling(namedTransport.name(),
							samplingRequest))
					.elicitation(elicitationRequest -> clientMcpSyncHandlersRegistry
						.handleElicitation(namedTransport.name(), elicitationRequest))
					.loggingConsumer(loggingMessageNotification -> clientMcpSyncHandlersRegistry
						.handleLogging(namedTransport.name(), loggingMessageNotification))
					.progressConsumer(progressNotification -> clientMcpSyncHandlersRegistry
						.handleProgress(namedTransport.name(), progressNotification))
					.toolsChangeConsumer(newTools -> clientMcpSyncHandlersRegistry
						.handleToolListChanged(namedTransport.name(), newTools))
					.promptsChangeConsumer(newPrompts -> clientMcpSyncHandlersRegistry
						.handlePromptListChanged(namedTransport.name(), newPrompts))
					.resourcesChangeConsumer(newResources -> clientMcpSyncHandlersRegistry
						.handleResourceListChanged(namedTransport.name(), newResources))
					.capabilities(clientMcpSyncHandlersRegistry.getCapabilities(namedTransport.name()));

				spec = mcpSyncClientConfigurer.configure(namedTransport.name(), spec);

				var client = spec.build();

				if (commonProperties.isInitialized()) {
					client.initialize();
				}

				mcpSyncClients.add(client);
			}
		}

		return mcpSyncClients;
	}
  • McpToolCallbackAutoConfiguration
    • SyncMcpToolCallbackProvider:通过McpSyncClient调用抓换为ToolCallback

SpringAI下集成MCP的工具

SyncMcpToolCallbackProvider

集成 MCP 同步客户端的 ToolCallbackProvider,负责从一个或多个 MCP 同步服务器(通过 McpSyncClient)自动发现、收集所有可用的工具,支持对工具进行过滤,确保工具名唯一

  • List<McpSyncClient> mcpClients:存储所有需要集成的 MCP 同步客户端实例,用于从多个 MCP 服务器拉取工具列表
  • BiPredicate<McpSyncClient, Tool> toolFilter:工具过滤器,允许根据客户端和工具元数据自定义过滤逻辑,决定哪些工具被暴露
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 等元数据
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 上下文信息

参考文档

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐