1. 为什么要在 Spring AI 里自己写 MCP 服务如果你正在用 Spring AI 做应用大概率会遇到一个尴尬模型能聊天但拿不到你系统里的真实数据。想让它查订单、读日志、算指标就得自己写一堆 Function Calling 的胶水代码每个模型厂商的调用格式还不一样。MCPModel Context Protocol就是来解决这个问题的——它把「工具」抽象成标准协议模型侧只认协议不认你底层接的是哪家模型。我这次要落地的是一个典型场景一个 Spring Boot 应用内部有几个业务方法比如查天气、做加减法希望通过 MCP 协议暴露给支持 MCP 的客户端Trae、Cline、Claude Code 这类同时模型调用走 TaoToken 的统一 Key 通道不用在代码里散落一堆厂商 Key。目标很明确一次跑通 Spring AI 侧的调用链本地能调试配置能复制。适合谁看有 Java/Spring Boot 基础、想快速把 MCP 服务跑起来、又不想在模型接入上折腾多套 SDK 的开发者。整篇会给出config.toml、settings.json、mcp.json的可复制骨架以及 MCP 服务注册、工具暴露、本地联调验证的完整动作。踩过的坑我也会标出来尤其是 JDK 版本和 stdio 传输那两个最容易翻车的地方。先说清楚 MCP 在 Spring AI 里的定位。Spring AI 本身提供了 MCP Client 和 MCP Server 的 starterServer 端负责把你的Tool方法注册成 MCP 工具Client 端负责连接这些 Server。传输方式主要有两种stdio标准输入输出适合本地进程和 SSEHTTP 长连接适合远程服务。本地开发用 stdio 最省事一个 jar 包就能起。而 TaoToken 在这里的角色是「统一模型入口」。你的 Spring AI 应用要调模型不管是 Claude 还是别的都通过 TaoToken 的 API 通道走Key 只配一份。这样 MCP 服务负责暴露工具TaoToken 负责模型调用两边解耦配置清晰。2. TaoToken 前置准备Key 与通道配置在写代码之前先把模型通道准备好。TaoToken 提供统一的 API 入口你只需要一个 Key 就能调用多种模型。这一步不做后面 Spring AI 的 ChatClient 起不来。先去官网注册并拿到 API Key官网入口https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content登录后进控制台创建 Key控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite创建完在 API Keys 页面复制Key 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewriteAPI 基础地址是https://taotoken.net/api注意这个地址不带任何查询参数直接作为 base-url 用。拿到 Key 后建议先别急着写 Java 代码用 curl 验证一下通道是否通curl https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-你的Key \ -d { model: claude-3-5-sonnet-20241022, messages: [{role: user, content: ping}], max_tokens: 16 }返回里有choices字段就说明通道正常。这一步能省掉后面大量「到底是 Key 错还是代码错」的排查时间。关于模型选择如果你只是验证 MCP 工具调用链用便宜的小模型就够如果要长期跑编码类 Agent 任务可以考虑 Coding Plan额度更划算Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite接入文档在这里Spring AI 的 OpenAI 兼容配置可以直接参考接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite3. 可复制配置config.toml 与 settings.json 骨架这一节是重点直接给可复制的配置骨架。分三块Spring AI 应用侧的application.yml、MCP 客户端侧的mcp.json、以及如果你用 Claude Code 这类工具的settings.json。3.1 Spring AI 应用侧 application.yml这是你的 Spring Boot 应用连 TaoToken 的配置。关键点是base-url指向 TaoTokenapi-key用环境变量注入别硬编码。spring: ai: openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: claude-3-5-sonnet-20241022 temperature: 0.7 mcp: server: name: spring-ai-mcp-demo version: 1.0.0 stdio: true main: web-application-type: none banner-mode: offweb-application-type: none和banner-mode: off是 stdio 模式必须的否则启动时会往 stdout 打日志污染 MCP 协议流客户端直接解析失败。这个坑我第一次就踩了现象是客户端连上但工具列表为空。3.2 MCP 客户端 mcp.json如果你用 Trae 或 Cline把下面这段加到它们的 MCP 配置里。注意command和args要指向你打包出来的 jar。{ mcpServers: { spring-ai-stdio-mcp: { disabled: false, timeout: 30, type: stdio, command: java, args: [ -jar, D:/mcp/spring-ai-mcp-demo/spring-ai-mcp-stdio-server/target/spring-ai-mcp-stdio-server.jar ], cwd: D:/mcp/spring-ai-mcp-demo/spring-ai-mcp-stdio-server/target, env: { TAOTOKEN_API_KEY: sk-你的Key, TIMEZONE: Asia/Shanghai, spring.ai.mcp.server.stdio: true, spring.main.web-application-type: none, spring.main.banner-mode: off } } } }Windows 路径用正斜杠或双反斜杠都行但别用单反斜杠JSON 会转义出错。cwd一定要设否则相对路径的资源加载会找不到。3.3 Claude Code 侧 settings.json如果你用 Claude Code 作为 MCP 客户端配置放在settings.json里结构略有不同{ mcpServers: { spring-ai-stdio-mcp: { command: java, args: [ -jar, D:/mcp/spring-ai-mcp-demo/spring-ai-mcp-stdio-server/target/spring-ai-mcp-stdio-server.jar ], env: { TAOTOKEN_API_KEY: sk-你的Key, spring.ai.mcp.server.stdio: true, spring.main.web-application-type: none, spring.main.banner-mode: off } } } }Claude Code 的 MCP 接入细节可以看官方文档Claude Code 接入https://taotoken.net/ClaudeCodeAnthropic?utm_sourcetaotoken_aicg_blog_endutm_contentClaudeCodeAnthropicutm_campaignrewrite三份配置的核心逻辑是一致的模型通道走 TaoTokenMCP 传输走 stdio环境变量注入 Key。区别只是不同客户端的字段名。4. 工具暴露与本地联调验证配置给完了现在看代码侧怎么把工具暴露出去以及怎么验证整条链路。4.1 定义 MCP 工具Spring AI 用Tool注解标记方法MCP Server starter 会自动扫描并注册。写一个最简单的加减法工具Component public class MathTools { Tool(description 计算两个整数相加的结果) public int add(int a, int b) { return a b; } Tool(description 计算两个整数相减的结果) public int minus(int a, int b) { return a - b; } }description很重要模型靠它判断什么时候调用这个工具。描述写清楚输入输出别写「处理数据」这种模糊的话。4.2 注册工具到 MCP Server在配置类里把工具注册进去Configuration public class McpServerConfig { Bean public ToolCallbackProvider mathToolCallbackProvider(MathTools mathTools) { return MethodToolCallbackProvider.builder() .toolObjects(mathTools) .build(); } }启动类保持最简SpringBootApplication public class StdioServerApplication { public static void main(String[] args) { SpringApplication.run(StdioServerApplication.class, args); } }4.3 打包与启动验证先确认 JDK 版本和 pom 一致。maven.compiler.source和target都设成 17properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target /properties然后打包mvn clean package -DskipTests打包成功后先别急着接客户端手动跑一下 jar 看有没有报错java -jar spring-ai-mcp-stdio-server.jar如果 stdout 干净、没有 Spring banner、进程挂起等待输入说明 stdio 模式正常。如果看到一堆日志回去检查banner-mode和web-application-type。4.4 客户端联调把 jar 路径填进mcp.json重启客户端。在 Trae 或 Cline 的 MCP 面板里应该能看到spring-ai-stdio-mcp这个服务展开后有两个工具add和minus。然后在对话框里问「用工具算一下 128 加 256 等于多少」。正常的话客户端会调用add工具返回 384。这一步跑通说明 MCP 服务注册、工具暴露、模型调用整条链路都通了。如果你想单独验证模型通道可以用模型对话页面直接测模型对话https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite5. 本篇常见错误排查这一节列几个高频问题都是我实际遇到过的。问题一客户端连上但工具列表为空。九成是 stdout 被日志污染了。检查spring.main.banner-modeoff和spring.main.web-application-typenone是否生效。另外 logback 配置里如果有 console appender 输出到 stdout也要改成 stderr。问题二无效的目标发行版: 21。pom 里写了 21 但本地 JDK 是 17。要么改 pom 成 17要么装 JDK 21。执行java -version确认本地版本再对齐maven.compiler.source/target。问题三MCP 调用超时。默认超时可能太短尤其是模型响应慢的时候。在mcp.json里把timeout调到 30 或 60。如果是 SSE 模式检查端口是否被占用。问题四401 或 403。TaoToken 的 Key 没配对或者环境变量没传进子进程。检查mcp.json的env字段里TAOTOKEN_API_KEY是否正确注意别有多余空格。问题五Windows 路径报错。JSON 里路径用正斜杠/最稳或者双反斜杠\\。单反斜杠会被 JSON 解析器当成转义符。问题六jar 启动即退出。检查是不是漏了spring.ai.mcp.server.stdiotrue。没有这个Server 不知道用 stdio 传输启动完就结束了。排查顺序建议先 curl 验证 TaoToken 通道再手动跑 jar 看 stdout最后接客户端。逐层排除别一上来就怀疑代码。6. 长期编码场景的接入建议如果你只是偶尔验证 MCP 工具上面的配置够用了。但如果你要长期跑编码类 Agent 任务比如让 Claude Code 持续调用你的 MCP 服务做代码生成、重构那模型调用量会上去建议用 Coding Plan 的额度方案比按量计费省心Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite另外生产环境别把 Key 写死在mcp.json里用系统环境变量或密钥管理服务注入。本地开发图方便可以写但提交到 Git 前记得清掉。MCP 服务本身建议做成无状态的工具方法只做纯计算或只读查询写操作走单独的审批通道。这样即使模型误调用也不会造成数据污染。最后Spring AI 的 MCP starter 还在快速迭代版本升级时注意看 changelog尤其是Tool注解和ToolCallbackProvider的 API 可能有变动。锁定一个稳定版本别盲目追新。 SEO 优化官网定制响应式建站教育培训建站