1. 为什么你的 Spring Boot 接口需要一次 MCP 化改造如果你正在维护一套 Spring Boot 后端手里有一堆已经跑稳的 REST 接口最近又被 AI 客户端、智能体、Copilot 这类需求追着跑那你大概率会遇到一个很具体的尴尬接口本身没问题问题是模型不知道怎么调。REST 是给人看的路径、参数、返回结构都靠文档和约定MCP 是给模型看的它需要工具名、参数描述、返回语义还要一条稳定的会话通道。这两者之间的落差就是本文要填的坑。MCP 全称 Model Context Protocol你可以把它理解成“模型和外部能力之间的 USB-C 接口”。它用 JSON-RPC 做双向交互把后端能力抽象成 Tool、Resource、Prompt 三类对象。Tool 是可被模型调用的动作比如“按作者查图书”Resource 是可被读取的上下文比如“某份报表”Prompt 是可复用的提示模板。对 Java 后端来说最直接的收益是你不需要把接口重写一遍而是把已有服务层能力“注册”成工具让 AI 客户端通过标准协议直连。适合谁看这篇三类人最合适。第一类是有 Spring Boot 存量项目、想把查询类接口先开放给 AI 的后端工程师第二类是正在做智能客服、运营助手、数据分析助手需要把多个后端能力编排给模型的产品研发第三类是想搞清楚 MCP Server 到底怎么落地、不想只看概念的同学。整篇我会按“问题场景 → TaoToken 前置 → 可复制配置 → 验证请求 → 报错排查 → CTA”的顺序走每一步都给能直接粘贴的代码和命令。先说清楚边界MCP 不是替代 REST而是给 REST 加一层“模型可调用”的适配层。只读接口优先写操作后置这是我在实际项目里踩过坑之后最想强调的顺序。下面进入正题。2. TaoToken 统一 Key 与 API 通道的前置准备在动手写 MCP Server 之前先把“鉴权和路由”这件事从业务代码里剥出来。原因很简单MCP 工具一旦被 AI 客户端调用调用来源、频率、权限边界都会变得比传统前端复杂。如果每个工具方法里都塞一段 token 校验后面治理会很痛苦。我的做法是用 TaoToken 作为统一 Key 和 API 通道承接鉴权与路由业务侧只关心工具逻辑。TaoToken 在这里扮演的角色是一个统一的模型调用入口和 Key 管理通道。你可以在官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 了解整体能力API 入口是 https://taotoken.net/api这个地址不加 UTM。对 Spring Boot 项目来说你需要准备三样东西Base URL、API Key、Model ID。这三件套在后面配置 MCP 客户端和验证调用时会反复用到。具体操作上先去控制台创建一个 API Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 进去之后新建 Key复制出来保存好它只会完整显示一次。然后确认你要用的模型 ID这个在模型对话页面能看到地址是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。如果你后面要做长期编码或 Agent 类任务可以关注 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 它更适合高频调用场景。这里有个容易忽略的点MCP Server 本身不负责模型推理它只负责把工具暴露出去。真正调用模型的是 MCP Client 或 Host。所以 TaoToken 的 Key 是配在客户端侧的不是配在 Server 侧。Server 侧要做的是把工具注册好、把 SSE 或 WebSocket 通道开好。很多同学第一次配的时候把 Key 塞进 application.yml 的 server 段结果客户端连不上就是因为搞混了这两侧。另外API Key 的权限建议按最小化原则来。只读工具用一个 Key写操作工具用另一个 Key方便后面做审计和限流。如果你用的是 Claude Code 这类客户端接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有 Base URL 和 Key 的填写位置说明。前置准备做完下面进入可复制的配置环节。3. 可复制的 MCP Server 配置与 REST 到 MCP 映射这一节是全文最核心的部分我会给出完整的依赖、配置文件和工具类代码。先看依赖。Spring Boot 3.x 加 WebFlux 是推荐组合因为 MCP 的 SSE 传输依赖事件流。下面是 pom.xml 的关键片段dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-webflux/artifactId /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webflux/artifactId version1.0.0-M7/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-validation/artifactId /dependency /dependencies版本这块要注意MCP Starter 和 Spring Boot 的版本要匹配否则会出现协议层握手失败。我实测下来Spring Boot 3.2.x 配 1.0.0-M7 比较稳。接下来是 application.yml这里配的是 MCP Server 的传输方式和端点spring: ai: mcp: server: enabled: true transport: sse endpoint: /mcp/sse server: port: 8080这个配置的意思是MCP Server 开启用 SSE 传输客户端连接地址是http://localhost:8080/mcp/sse。如果你要做高并发或双向交互可以把 transport 换成 websocket但 SSE 对大多数只读工具场景已经够用。然后是 REST 到 MCP 的映射。假设你原来有一个 REST 接口RestController RequestMapping(/api/books) public class BookController { GetMapping(/{author}) public ListString getBooksByAuthor(PathVariable String author) { return List.of(《 author 的第一本书》, 《 author 的第二本书》); } }这个接口模型看不懂因为它不知道author是什么语义也不知道返回的列表代表什么。改造方式是抽一个 Tool 类用Tool注解注册import org.springframework.stereotype.Component; import org.springframework.ai.tool.annotation.Tool; import jakarta.validation.constraints.NotBlank; Component public class BookTool { Tool(name queryBooks, description 按作者与年份查询图书返回规范化列表) public ListString queryBooks(NotBlank String author, Integer year) { int y (year null || year 0) ? 0 : year; return List.of(《 author ·精选 y 》); } }这里的关键是name和description。name 用领域化命名别用getData这种含糊词description 要写清楚参数含义和返回内容模型靠它决定要不要调用。year 参数允许为空是为了让模型在信息不全时也能调用而不是直接报错。如果你用的是 Cline 或 Claude Code 这类客户端配置里需要填全三件套。以 Cline 的 MCP 配置为例JSON 片段如下{ mcpServers: { spring-boot-tools: { url: http://localhost:8080/mcp/sse, env: { TAOTOKEN_BASE_URL: https://taotoken.net/api, TAOTOKEN_API_KEY: 你的Key, TAOTOKEN_MODEL_ID: 你的ModelID } } } }注意 Base URL 是https://taotoken.net/api不要加 UTM 参数。Key 和 Model ID 从前面控制台和模型页面拿。如果你用的是 Codex 的 auth.json结构类似把 base_url、api_key、model 三个字段填对即可。CC Switch 场景下也是同样的三件套逻辑Base URL 指向 TaoToken 的 API 入口Key 用控制台生成的Model ID 按你实际使用的模型填。配置写完启动项目。如果控制台没有报错并且能看到类似MCP Server started on /mcp/sse的日志说明 Server 侧就绪了。下一节我们用 curl 和 AI 客户端各验证一次。4. 用 curl 与 AI 客户端验证调用链路配置对不对不能靠猜要跑一次完整链路。先做最轻量的验证用 curl 确认 MCP Server 的 SSE 端点活着。命令如下curl -N http://localhost:8080/mcp/sse-N是关闭缓冲让你能实时看到事件流。如果连接成功你会看到类似event: endpoint和data: /mcp/message的输出说明 SSE 通道正常。如果卡住没输出检查端口是否被占用、transport 是否配成 sse。第二步验证工具是否注册成功。MCP 协议里有一个tools/list方法可以用 curl 发一个 JSON-RPC 请求curl -X POST http://localhost:8080/mcp/message \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 1, method: tools/list, params: {} }正常返回里应该能看到queryBooks这个工具以及它的参数 schema。如果返回里没有你的工具大概率是Tool注解没被扫描到检查一下包路径是否在启动类的同级或子级。第三步用 AI 客户端做端到端验证。以 Claude Code 为例接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 按文档把 Base URL、Key、Model ID 填好然后在客户端里输入一句自然语言“帮我查一下作者鲁迅在 2024 年的图书”。如果链路通了客户端会先调用tools/list发现工具再调用tools/call执行queryBooks最后把结果返回给你。你会在客户端里看到工具调用记录和最终回答。这里有个细节模型能不能正确填参数取决于 description 写得好不好。我试过把 description 写成“查询图书”结果模型经常漏填 year改成“按作者与年份查询图书返回规范化列表”之后填充准确率明显提升。所以 description 不是装饰是给模型看的接口文档。如果你用的是模型对话页面做验证地址是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 可以在那里直接测试模型对工具描述的理解。验证通过后说明整条链路AI 客户端 → TaoToken 通道 → MCP Server → Spring Boot 工具方法已经打通。下一节处理常见报错。5. 常见报错排查401、local proxy failed、reading choices、OAuth链路跑通之前报错是常态。我把实际遇到过的几类整理出来对照着查会快很多。第一类401 Unauthorized。这个最常见原因是 Key 没配对或过期。检查三处客户端配置里的TAOTOKEN_API_KEY是否和控制台生成的一致Base URL 是否是https://taotoken.net/api有没有多写斜杠或路径Key 是否被复制时带了空格。如果用的是 Claude Code确认 OAuth 流程是否走完有些客户端需要先完成授权再填 Key。第二类local proxy failed。这个报错通常出现在客户端侧意思是本地代理连接失败。先确认 MCP Server 是否真的在http://localhost:8080/mcp/sse监听用curl -N测一下。如果 Server 正常检查客户端配置里的 url 是否写错比如把/mcp/sse写成了/mcp。还有一种情况是端口冲突换个端口重启即可。第三类reading choices 相关报错。这类通常出现在模型返回解析阶段说明客户端拿到了响应但解析失败。检查 Model ID 是否填对有些模型不支持工具调用换一个支持 function calling 的模型再试。另外确认返回的 JSON 结构是否符合 MCP 协议工具方法的返回类型建议用 List 或 Map 这类可序列化结构别返回自定义对象。第四类OAuth 报错。如果你用的是需要 OAuth 的客户端报错信息里会带invalid_grant或redirect_uri_mismatch。前者通常是授权码过期重新走一遍授权后者是回调地址没在客户端配置里登记。Claude Code 的接入文档里有完整的 OAuth 配置说明地址是 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 照着填就行。第五类工具调用成功但结果为空。这个不是报错但很常见。检查工具方法的参数是否被正确填充可以在方法里加一行日志打印入参。如果入参是 null说明 description 没让模型理解参数含义回去改描述。排查顺序建议先 curl 测 Server再 curl 测 tools/list最后测客户端。一层层往上查比一上来就怀疑客户端要快得多。如果 Key 需要重新生成去 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 操作。6. 把后端能力交给 AI 之前先想清楚这三件事第一件事只读优先。查询、导出、报表这类接口先 MCP 化写操作比如审批、下单、关单放到第二阶段。写操作要加二次确认和严格审计别让模型直接改数据。第二件事工具粒度。一个工具只做一件事别把“查图书”和“借图书”塞进同一个方法。粒度太细会导致工具数量爆炸粒度太粗会让模型误用。我的经验是按业务动作切一个动作一个工具。第三件事观测先行。上线前就把日志和指标接好至少记录调用者、参数摘要、返回摘要、耗时、成功失败。MCP 调用链路比传统 REST 长出问题时没有观测会很难定位。如果你准备长期做编码或 Agent 类任务Coding Plan 会更合适地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。需要管理多个 Key 的话控制台在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。接入过程中卡住了先看接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 大部分配置问题里面都有答案。
阅读完成 · 觉得有帮助?