☰
Spring AI + MCP 实战:Java 应用调用外部工具的配置与验证
2026/9/28 4:06:26 网站建设 项目流程

1. 为什么 Java 后端要接 MCP:从“写死工具”到“按需调用”

如果你写过 Spring Boot 调大模型,大概率经历过这个阶段:想让模型查个天气、读个数据库、调个内部接口,就得在代码里写一堆if-else或者@Tool注解,工具一多,ChatClient的配置就变成一坨。更麻烦的是,工具逻辑和业务代码耦合在一起,换个模型、加个工具都要重新打包发版。

MCP(Model Context Protocol)解决的正是这个问题。你可以把它理解成“AI 世界的 USB-C 接口”:模型侧不需要知道工具具体怎么实现,工具侧也不需要关心是哪个模型在调用,双方只认一套标准协议。对 Java 开发者来说,Spring AI 已经把 MCP 的客户端能力封装好了,你只需要配置一个McpSyncClient,就能让 Java 应用像调用本地方法一样调用外部工具。

这篇面向的是需要打通 Java 侧工具调用的后端开发者,尤其是已经在用 Spring Boot、想快速验证 MCP 链路的同学。我会给出可复制的 MCP 客户端配置骨架,配合 TaoToken 统一 Key/API 通道接入示例,最后跑一次真实的工具调用验证动作,并告诉你预期结果长什么样。整个过程不需要你改模型代码,也不需要自己实现协议解析。

先说清楚适合谁:如果你只是想让模型聊聊天,那用不上 MCP;但如果你需要让 Java 应用动态发现工具、按需调用、并且工具和模型解耦,那这套组合值得花半小时跟一遍。

2. 前置准备:TaoToken 统一 Key 与依赖坐标

在写配置之前,先把“通道”和“依赖”两件事搞定。MCP 本身只管工具调用协议,模型请求还是得走一个兼容 OpenAI 接口的通道。我这边用的是 TaoToken 的统一 Key,好处是一个 Key 能覆盖模型对话和后续的 coding 场景,不用在多个平台之间来回切。

2.1 拿 Key 与确认 API 地址

登录 TaoToken 控制台后,在 API Keys 页面创建一个新 Key。建议按项目命名,比如spring-ai-mcp-demo,方便后面排查是哪个应用在调用。创建完复制出来,只显示一次。

API 地址用https://taotoken.net/api,注意这个地址不带任何查询参数,直接作为base-url使用。模型对话相关的入口在控制台里也能找到,验证阶段可以直接用模型对话页面确认 Key 是否生效。

注意:Key 不要硬编码进application.yml提交到仓库,本地用环境变量,线上用配置中心。下面示例里我用${TAOTOKEN_API_KEY}占位。

2.2 Maven 依赖

Spring AI 的 MCP 客户端 starter 目前还在快速迭代,建议锁定一个稳定版本。下面这套坐标我实测能跑通:

<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>1.0.0-M6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-client</artifactId> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> </dependencies>

spring-ai-starter-mcp-client负责 MCP 协议通信,spring-ai-openai-spring-boot-starter负责走 OpenAI 兼容接口。两个 starter 分工明确,别只引一个。

2.3 MCP Server 从哪来

MCP 客户端要连一个 Server 才有工具可调。Server 可以是别人写好的(比如文件系统、Git 操作类),也可以是你自己用 Spring AI 的spring-ai-starter-mcp-server起的。本文重点在客户端配置,所以假设你已经有一个可用的 MCP Server,地址形如http://localhost:8081,传输方式用 SSE。

3. 可复制配置:MCP 客户端骨架与 ChatClient 装配

这一章是核心,配置分两块:application.yml里的连接参数,和 Java 配置类里的 Bean 装配。两块都给你完整代码,改改地址就能用。

3.1 application.yml 连接参数

spring: ai: openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: gpt-4o-mini temperature: 0.3 mcp: client: enabled: true name: java-mcp-client version: 1.0.0 type: SYNC request-timeout: 30s sse: connections: demo-server: url: http://localhost:8081 sse-endpoint: /sse

几个参数说明一下。type: SYNC表示用同步客户端,适合大多数后端场景;如果你要并发调多个工具,可以换成ASYNC。request-timeout别设太短,工具执行慢的时候容易误判超时。sse-endpoint要和你的 MCP Server 实际暴露的路径一致,常见的是/sse,也有用/mcp/sse的,连不上先查这里。

3.2 Java 配置类装配 ToolCallbackProvider

@Configuration public class McpClientConfig { @Bean public ToolCallbackProvider toolCallbackProvider( List<McpSyncClient> mcpSyncClients) { return ToolCallbackProvider.from(mcpSyncClients); } @Bean public ChatClient chatClient( ChatClient.Builder builder, ToolCallbackProvider toolCallbackProvider) { return builder .defaultSystem("你是一个 Java 后端助手,需要外部信息时调用可用工具。") .defaultToolCallbacks(toolCallbackProvider) .build(); } }

这里的关键是ToolCallbackProvider.from(mcpSyncClients)。Spring AI 会自动把 yml 里配置的 SSE 连接实例化成McpSyncClient,你只要把它们收集起来交给ToolCallbackProvider,再挂到ChatClient上。挂载之后,模型在对话中就能“看到”这些工具的描述,并决定是否调用。

3.3 工具调用的触发方式

不需要你手动写调用代码。当用户提问涉及工具能力时,模型会返回一个 tool call 请求,Spring AI 拦截后通过 MCP 客户端转发给 Server,拿到结果再回填给模型,最后输出自然语言回答。整个过程对业务代码透明,你只管调chatClient.prompt()。

如果你想让某个工具强制被调用,可以在 prompt 里明确说“请使用工具查询”,但正常场景下让模型自己判断更自然。

4. 验证请求:一次真实工具调用与预期结果

配置写完,跑一个最小验证。假设你的 MCP Server 上挂了一个“查询当前时间”的工具,名字叫get_current_time。

4.1 验证代码

@RestController public class McpDemoController { private final ChatClient chatClient; public McpDemoController(ChatClient chatClient) { this.chatClient = chatClient; } @GetMapping("/ask") public String ask(@RequestParam String q) { return chatClient.prompt() .user(q) .call() .content(); } }

启动应用后,请求:

curl "http://localhost:8080/ask?q=现在几点了,请用工具查一下"

4.2 预期结果与日志特征

正常情况下,你会看到返回类似“当前时间是 2025-01-15 14:32:10”。同时在应用日志里能看到两段关键信息:一段是模型返回的 tool call 请求,包含工具名和参数;另一段是 MCP 客户端把工具执行结果回传后的二次模型请求。这两段日志出现,说明 MCP 链路是通的。

如果返回的是“我无法获取实时时间”,那大概率是工具没被挂载上,或者模型没识别到工具描述。先检查ToolCallbackProvider是否注入了非空的 client 列表。

4.3 用模型对话页面交叉验证

有时候你分不清是 MCP 的问题还是 Key 的问题。这时候可以打开 TaoToken 的模型对话入口,用同一个 Key 直接问一句普通问题。如果那边正常、这边工具调用失败,问题就锁定在 MCP 配置;如果那边也报鉴权错误,那就是 Key 或 base-url 的问题。这个交叉验证能省不少排查时间。

5. 本篇常见错排查:连不上、工具不触发、超时

这一章按报错现象来,都是我实际踩过的。

5.1 SSE 连接 404 或 connection refused

先确认 MCP Server 是否真的在跑,端口对不对。然后检查sse-endpoint路径。有些 Server 的 SSE 路径是/sse,有些是/mcp/sse,还有的区分大小写。用浏览器或 curl 直接访问http://localhost:8081/sse,能看到事件流输出就说明路径对了。

如果 Server 在容器里,注意localhost在容器网络里指向的是容器自己,要换成宿主机 IP 或服务名。

5.2 工具列表为空,模型不触发调用

日志里如果看到No tool callbacks registered,说明ToolCallbackProvider没拿到 client。检查两点:一是 yml 里spring.ai.mcp.client.enabled是否为 true;二是McpSyncClient的 Bean 是否被 Spring 扫描到。有时候 starter 版本不匹配会导致 client 不自动装配,这时候需要手动声明McpClientBean。

另一个常见原因是工具描述太模糊,模型判断不出该不该调。可以在 Server 侧把工具描述写清楚,比如“查询当前系统时间,无需参数,返回 ISO 格式字符串”。

5.3 请求超时但工具实际执行成功

这种多半是request-timeout设太短,或者工具执行本身慢。先把超时调到 60s 观察。如果还是超时,看 MCP Server 侧日志,确认工具是否真的执行完了。有些 Server 在工具执行完后没有正确发送响应事件,客户端就会一直等。这种情况要检查 Server 的 MCP 实现是否符合协议版本。

5.4 鉴权失败 401

如果日志里出现 401,先确认TAOTOKEN_API_KEY环境变量是否真的注入到运行进程里。用System.getenv("TAOTOKEN_API_KEY")打印一下长度,别打印明文。另外确认base-url是https://taotoken.net/api,末尾不要多加/v1,Spring AI 的 OpenAI starter 会自己拼路径。

6. 接入后的下一步:把 Key 和通道固定下来

链路跑通之后,建议做两件事让后续开发更顺。

第一件是把 Key 管理规范化。本地开发用环境变量,CI 用 secret,线上用配置中心。TaoToken 的 Key 可以在控制台按项目拆分,不同环境用不同 Key,出问题好定位。API Keys 页面还能看到调用记录,排查 401 或额度问题很方便。

第二件是确认你的接入方式。如果你只是偶尔验证模型和工具,用模型对话入口就够了;如果你要长期在 IDE 或 Agent 里跑编码任务,建议看一下 Coding Plan,它更适合高频、长会话的场景。接入文档里有完整的参数说明和示例,遇到配置项不确定的时候直接查文档比翻源码快。

我自己的习惯是:新项目先把 MCP 客户端骨架和 TaoToken 通道配好,跑通一次工具调用,再往上叠业务逻辑。这样后面加工具、换模型都只是改配置,不用动业务代码。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询