ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Spring AI MCP 工具调用测试:用 ChatClient 打通 Java 侧配置链路

Spring AI MCP 工具调用测试:用 ChatClient 打通 Java 侧配置链路 1. 为什么 Java 侧 MCP 工具调用总在“最后一公里”翻车如果你正在用 Spring AI 做智能体大概率遇到过这种场景ChatClient 能正常对话模型也能返回一段看起来像工具调用的 JSON但真正落到业务方法上——比如保存一篇文章、查一次订单、写一条记录——就是没执行。日志里没有异常返回值也“像那么回事”可数据库里空空如也。这不是模型的问题而是 Java 侧的配置链路没打通。Spring AI 的 MCPModel Context Protocol支持本质上是把外部工具以标准协议暴露给模型再由 ChatClient 在对话过程中决定是否调用。它适合谁适合已经用 Spring Boot 搭好后端、想让 Java 服务具备“工具调用能力”的开发者尤其是需要把内部 API 包装成模型可调用工具的场景。这篇内容聚焦一件事用 ChatClient 接入 MCP跑通一次真实的工具调用并确认链路生效。我会给出配置骨架、可复制代码以及验证请求的完整动作。实测下来最容易出问题的不是模型而是 ToolCallbackProvider 的注册和 MCP Server 的暴露方式。2. TaoToken 前置先把模型入口和 Key 准备好在写 Java 代码之前得先有一个能稳定调用的模型入口。Spring AI 本身不绑定具体模型服务你需要配置一个兼容 OpenAI 协议的 endpoint 和 API Key。我这边用的是 TaoToken 的模型对话入口它兼容标准 Chat 接口Spring AI 的 OpenAiChatModel 可以直接对接。操作路径很直接先到官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 了解整体能力然后进入控制台创建 API Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。创建后复制那串 sk- 开头的 Key后面配置里要用。注意API Key 只显示一次建议创建后立刻存到环境变量或配置中心不要硬编码进 Git 仓库。模型对话的接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面写清了 base_url 和兼容参数。API 基础地址是 https://taotoken.net/api 注意这个地址不带 UTM 参数配置时直接用。如果你后面要做长期编码或 Agent 任务可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 它更适合高频调用场景。3. 可复制配置ChatClient MCP 的骨架这一节是核心。Spring AI 接入 MCP 需要三块MCP Client 配置、ToolCallbackProvider 注册、ChatClient 构建。我按 Maven 依赖、application.yml、Java 配置类、工具定义四步拆开你可以直接抄。3.1 Maven 依赖Spring AI 的版本迭代较快建议用 1.0.0-M6 及以上。核心依赖是 spring-ai-openai-spring-boot-starter 和 spring-ai-mcp-client-spring-boot-starter。dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId version1.0.0-M6/version /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-mcp-client-spring-boot-starter/artifactId version1.0.0-M6/version /dependency如果你用的是 Gradle把 groupId 和 artifactId 对应替换即可。注意 MCP 相关 starter 在 M6 之后才比较稳定早期版本 API 差异较大。3.2 application.yml 配置这里要配两段模型入口和 MCP Server 连接方式。模型部分对接 TaoToken 的兼容接口。spring: ai: openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: gpt-4o-mini temperature: 0.2 mcp: client: enabled: true name: csdn-mcp-client version: 1.0.0 type: SYNC request-timeout: 30stype: SYNC表示同步调用适合大多数工具调用场景。如果你的工具执行时间长可以改成 ASYNC但要注意线程模型。request-timeout建议设 30 秒以上MCP 握手和工具发现需要时间。3.3 MCP Client 配置类Spring AI 的 MCP Client 支持 stdio 和 SSE 两种传输方式。本地工具用 stdio远程工具用 SSE。下面这个配置类注册一个基于 stdio 的 MCP Client并把它暴露的 ToolCallback 注入到 ChatClient。Configuration public class McpClientConfig { Bean public McpSyncClient mcpSyncClient() { ServerParameters params ServerParameters.builder(node) .args(mcp-server.js) .build(); McpClientTransport transport new StdioClientTransport(params); McpSyncClient client McpClient.sync(transport) .requestTimeout(Duration.ofSeconds(30)) .build(); client.initialize(); return client; } Bean public ToolCallbackProvider toolCallbackProvider(McpSyncClient mcpSyncClient) { return SyncMcpToolCallbackProvider.builder() .mcpClients(List.of(mcpSyncClient)) .build(); } }关键点在SyncMcpToolCallbackProvider它负责把 MCP Server 暴露的工具转换成 Spring AI 能识别的 ToolCallback。如果这一步没注册ChatClient 就不知道有哪些工具可用模型也不会触发调用。3.4 工具定义与 ChatClient 构建假设 MCP Server 暴露了一个saveArticle工具参数是 title 和 content。ChatClient 构建时把 ToolCallbackProvider 传进去。Bean public ChatClient chatClient(ChatClient.Builder builder, ToolCallbackProvider toolCallbackProvider) { return builder .defaultToolCallbacks(toolCallbackProvider) .defaultSystem(你是一个可以调用工具的助手需要保存文章时调用 saveArticle。) .build(); }defaultToolCallbacks是 M6 之后的写法早期版本用defaultFunctions。如果你编译报错先确认版本。系统提示词里明确告诉模型“需要保存文章时调用 saveArticle”能显著提高工具触发率。4. 验证请求一次真实的工具调用配置写完怎么确认链路真的通了我建议分两步先验证工具发现再验证工具执行。4.1 验证工具是否被发现写一个 CommandLineRunner启动时打印当前可用的工具列表。Component public class ToolListRunner implements CommandLineRunner { private final ToolCallbackProvider provider; public ToolListRunner(ToolCallbackProvider provider) { this.provider provider; } Override public void run(String... args) { ToolCallback[] callbacks provider.getToolCallbacks(); System.out.println(发现工具数量: callbacks.length); for (ToolCallback cb : callbacks) { System.out.println(工具名: cb.getToolDefinition().name()); } } }启动应用如果控制台打印出saveArticle说明 MCP Server 连接成功、工具发现正常。如果数量为 0问题在 MCP Client 初始化或 Server 启动参数上先排查这一层。4.2 发起一次工具调用请求工具被发现后用 ChatClient 发一条会触发工具调用的消息。RestController public class ArticleController { private final ChatClient chatClient; public ArticleController(ChatClient chatClient) { this.chatClient chatClient; } GetMapping(/test-save) public String testSave() { String prompt 请调用 saveArticle 工具保存一篇标题为《MCP 测试》的文章内容为链路验证成功。; return chatClient.prompt() .user(prompt) .call() .content(); } }访问/test-save观察三件事第一返回内容里是否提到工具调用第二MCP Server 侧日志是否收到 saveArticle 请求第三目标存储比如 CSDN 后台是否出现这篇文章。三者都满足链路才算真正打通。提示如果模型返回了工具调用意图但没执行检查defaultToolCallbacks是否生效以及 MCP Server 的工具名是否和提示词里写的一致。大小写敏感。5. 本篇常见错排查工具调用链路涉及模型、Spring AI、MCP Client、MCP Server 四层任何一层出问题都会表现为“没反应”。下面是我踩过的几个坑按排查顺序列出来。错误一工具数量为 0。最常见原因是 MCP Server 进程没起来或者 stdio 的 command 路径不对。先手动执行node mcp-server.js确认能启动并响应 initialize 请求。如果 Server 正常检查 Spring AI 的 MCP Client 是否调用了initialize()漏掉这一步工具列表就是空的。错误二模型不触发工具调用。模型返回纯文本没有 tool_calls 字段。原因通常是系统提示词不够明确或者模型本身对工具调用支持弱。换一个工具调用能力强的模型同时在提示词里直接写出工具名和参数格式。另外确认defaultToolCallbacks真的传进去了可以用第 4.1 节的 Runner 验证。错误三工具被调用但参数为空。模型生成了 tool_calls但 arguments 是空对象。这通常是工具的参数 schema 定义不清晰。MCP Server 侧的工具定义要写清 required 字段和类型Spring AI 会把 schema 转给模型。schema 越明确模型填参越准。错误四调用超时。MCP 的 request-timeout 默认值偏短工具执行慢就会中断。把request-timeout调到 30s 以上同时检查 MCP Server 是否有阻塞操作。如果是远程 SSE 方式还要排查网络链路。错误五返回 401 或模型不可用。这是模型入口配置问题和 MCP 无关。检查base-url是否为 https://taotoken.net/api API Key 是否有效。可以先用模型对话入口单独测一次普通对话确认模型层没问题再排查 MCP 层。排查时建议按“模型层 → MCP Client 层 → MCP Server 层 → 工具执行层”的顺序每层单独验证不要一上来就怀疑模型。6. 把链路固定下来接入文档与后续动作链路跑通一次之后建议把配置固化成可复用的模板。API Key 走环境变量MCP Server 的启动参数走配置中心工具列表在启动时打印一次作为健康检查。这样下次换环境或换工具排查成本会低很多。如果你在接入过程中遇到 Key 或模型入口的问题直接看接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面有针对 Spring AI 兼容配置的说明。需要新建或轮换 Key去 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。想先单独验证模型对话是否正常用模型对话入口https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。如果你的场景是长期编码或 Agent 高频调用Coding Plan 会更合适https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后说一个实用技巧在 MCP Server 侧给每个工具加一行入参日志打印收到的 arguments。这样当模型填参不准时你能立刻看到是模型的问题还是工具 schema 的问题。这个日志在排查阶段比任何断点都好用。
返回列表