首页 / Spring AI 入门教程 / MCP Client 接入

Spring AI 入门教程

MCP Client 接入

本教程共 45 篇 · 第 28 篇 · 更新于 2026-08-16 · 约 8 分钟阅读

Spring AIMCPMCP ClientBoot StarterSTDIOSSEStreamable-HTTP工具调用

本节目标:在自己的 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)是连接标识。后面的客户端注解、工具过滤都会用到它,起名要见名知意。

Tip

SSE 报 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 直接操作客户端,或注入 SyncMcpToolCallbackProvider 拿全部工具回调。日常用 ToolCallbackProvider 就够,另外两个属于进阶用法。

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 一样顺手。