
1. 传统 Spring Boot 服务接入大模型生态的真实困境很多团队手里都有一套跑了三五年的 Spring Boot 业务系统接口稳定、逻辑清晰但一到要接大模型就犯难。最直接的做法是在业务代码里硬编码调用某个模型的 SDK结果就是换模型要改代码、加模型要加依赖、每个模型一套 Key 分散在配置文件里运维排查时根本不知道哪个请求走了哪条通道。我见过一个项目光是模型鉴权配置就散落在四个 yml 文件里出问题只能一个个 grep。MCPModel Context Protocol出现之后思路变了。它不要求你把业务逻辑重写成大模型能懂的格式而是把现有 HTTP 接口包装成「工具」让支持 MCP 的客户端自动发现并调用。Spring AI 从 1.0.0-M6 开始提供了 MCP Server 的 starter意味着一个普通的 Spring Boot 3.x 项目加几个依赖、写一个Tool注解的方法就能把自己的接口暴露成 MCP Server。原来的 Controller、Service、DAO 一行不用动这就是标题里说的「零代码改造」——改造的是接入层不是业务层。但这里有个容易被忽略的环节MCP Server 本身不负责模型调用它只负责把工具描述给客户端。真正跑模型的那一端鉴权和通道管理还是散的。所以本文的落地路径是两段前半段用 Spring AI MCP 把传统服务变成可被发现的工具提供方后半段用 TaoToken 的统一 Key 和 API 通道把模型调用这一侧的鉴权收拢到一个地方。这样整条链路是客户端 → MCP Server你的 Spring Boot 服务→ 业务接口以及客户端 → 模型通道TaoToken→ 大模型。两边各管各的互不污染。适合谁看手上有 Spring Boot 3.x 项目、想让现有接口被大模型或 AI 客户端调用的后端同学正在做企业内部 AI 助手、需要把内部系统能力接进去的架构同学以及被多模型 Key 管理折磨过、想找个统一入口的运维同学。下面从环境准备开始一步步给可复制的配置。2. TaoToken 统一 Key 与 API 通道的前置准备在写 MCP Server 之前先把模型调用这一侧的通道理清楚。原因很简单MCP Server 暴露出去之后客户端会频繁调用模型来理解工具返回、决定下一步调哪个工具。如果每个客户端、每个环境都配一套模型 Key很快就会乱。TaoToken 在这里的角色是统一入口——你只需要在它这里拿一个 Key后面无论客户端用哪个模型都走同一个 Base URL 和同一个 Key。先明确三个东西后面配置里会反复出现Base URL 用https://taotoken.net/api注意这个地址不带任何查询参数是纯 API 端点。Key 在控制台的 API Keys 页面创建创建后只显示一次复制下来存好。Model ID 按你实际要用的模型填比如做代码理解可以用 claude 系列做通用对话可以用 gpt 系列具体以控制台模型列表为准。操作路径是这样的打开 https://taotoken.net/api-keys 创建 Key然后到 https://taotoken.net/doc 看接入文档确认当前支持的模型名和参数格式。如果你后面要长期跑编码类 Agent可以顺带看下 https://taotoken.net/coding-plan 它针对高频编码场景做了通道优化比按次调用更划算。想先验证模型通不通直接去 https://taotoken.net/model-chat 发一条消息能返回就说明 Key 和通道没问题。这里有个细节要注意MCP Server 本身不直接调模型所以 Spring Boot 项目里其实不需要配 TaoToken 的 Key。TaoToken 的 Key 是配在「客户端」那一侧的——也就是 Cursor、Cline、Claude Code 这些支持 MCP 的工具里。很多同学第一次做会搞混把模型 Key 塞进 Spring Boot 的 application.yml结果 MCP Server 启动正常但客户端调模型时 401。记住分工Spring Boot 管工具暴露TaoToken 管模型鉴权。如果你用的是 Claude Code 这类命令行客户端它的配置方式和 GUI 客户端不同需要单独设置环境变量或配置文件。这部分在第四节验证环节会给出具体写法。现在先把 Spring Boot 这边的依赖和配置搭起来。3. Spring AI MCP Server 可复制配置与依赖环境基线定死Spring Boot 3.4.2 JDK 17。Spring AI 的 MCP starter 对 Spring Boot 版本有要求3.4.2 是当前验证过的组合别用 3.2 以下会缺自动配置类。MCP Server 的传输方式有三种本文选 Spring MVC SSE原因是它和传统 Web 应用集成最自然你原来的 Tomcat 线程模型不用改调试也方便浏览器直接能看 SSE 流。先看 Maven 依赖。父 POM 里用 dependencyManagement 锁版本然后引入 MCP Server 的 webmvc starterdependencyManagement dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-dependencies/artifactId version3.4.2/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-mcp-server-webmvc-spring-boot-starter/artifactId version1.0.0-M6/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies注意 artifactId 是spring-ai-mcp-server-webmvc-spring-boot-starter不是spring-ai-starter-mcp-server-webmvc这两个名字在不同版本里出现过M6 用的是前者。写错了会报找不到依赖。然后是 application.yml。这里的关键是spring.ai.mcp.server这一段type 用 SYNCsse-endpoint 指定 SSE 的路径spring: application: name: smd-mcp-server ai: mcp: server: name: smd-mcp-server version: 1.0.0 type: SYNC sse-endpoint: /sse server: port: 8089 smd: service: url: http://localhost:8080smd.service.url是你原有业务服务的地址MCP Server 通过 HTTP 转发调用它。这样做的意义是MCP Server 和业务服务可以分开部署业务服务该干嘛干嘛MCP Server 只做协议转换。接下来是工具类。核心是用Tool注解标记方法ToolParam描述参数Spring AI 会自动把这些方法注册成 MCP 工具Service public class SmdMcpService { Autowired private RestTemplate restTemplate; Value(${smd.service.url}) private String smdServiceUrl; Tool(name getSmdInfo, description 获取表结构信息) public String getSmdInfo( ToolParam(description 业务系统) String businessSystem, ToolParam(description 表名) SetString tableNames) { MapString, Object params new HashMap(); params.put(businessSystem, businessSystem); params.put(tableNames, tableNames); ResponseEntityString response restTemplate.postForEntity( smdServiceUrl /mcp/api/getSmdInfo, params, String.class); return response.getBody(); } Tool(name getCRUDCode, description 根据表名生成增删改查代码) public ListMapString, Object getCRUDByTable( ToolParam(description 业务系统) String businessSystem, ToolParam(description 表名) SetString tableNames, ToolParam(description 模块名非必填) String moduleName) { MapString, Object params new HashMap(); params.put(businessSystem, businessSystem); params.put(tableNames, tableNames); params.put(moduleName, moduleName); params.put(author, smd-mcp); HttpEntityMapString, Object httpEntity new HttpEntity(params); ResponseEntityListMapString, Object response restTemplate.exchange( smdServiceUrl /mcp/api/crud, HttpMethod.POST, httpEntity, new ParameterizedTypeReferenceListMapString, Object() {}); return response.getBody(); } }最后是注册配置把工具类交给 MCP 框架Configuration Slf4j public class McpConfig { Bean public ToolCallbackProvider smdToolCallbackProvider(SmdMcpService smdMcpService) { return MethodToolCallbackProvider.builder() .toolObjects(smdMcpService) .build(); } }到这里 Spring Boot 侧的配置就齐了。启动后访问http://localhost:8089/sse如果看到 SSE 流保持连接说明 MCP Server 起来了。注意 SSE 是长连接用浏览器直接打开会一直转圈这是正常的用 curl 加-N参数能看到事件流。4. 验证 MCP 工具调用链路与客户端配置服务起来之后要验证工具能不能被客户端发现和调用。这里分两步先验证 MCP Server 本身再验证客户端到模型的整条链路。第一步用 curl 确认 SSE 端点活着curl -N http://localhost:8089/sse正常会返回类似event: endpoint和data: /mcp/message?sessionIdxxx的内容。这个 sessionId 后面客户端会用到。第二步配置客户端。以 Cursor 或 Trae 这类支持 MCP 的工具为例在 mcp.json 里加{ mcpServers: { smd-mcp-server: { url: http://localhost:8089/sse, env: { API_KEY: 你的TaoToken Key } } } }注意这里的 API_KEY 是给客户端调模型用的走的是 TaoToken 的通道。客户端在理解工具返回、决定下一步调用时会拿这个 Key 去请求模型。所以这个 Key 必须是 TaoToken 控制台创建的那个Base URL 在客户端设置里填https://taotoken.net/api。如果你用的是 Claude Code配置方式不一样它读的是环境变量或 settings 文件。在项目根目录建.claude/settings.json{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: 你的TaoToken Key } }然后在 Claude Code 里通过 MCP 配置命令添加 server指向http://localhost:8089/sse。这样 Claude Code 既能调模型又能发现你 Spring Boot 服务暴露的工具。配置完成后在客户端里问一句「帮我看看 user 表的结构」如果 MCP 链路通了客户端会先调用getSmdInfo工具拿到表结构再让模型组织语言返回。你可以在 Spring Boot 控制台看到对应的 HTTP 转发日志说明工具被真实调用了。这一步常见的成功标志是客户端工具列表里出现getSmdInfo和getCRUDCode并且调用后返回的是你业务接口的真实数据而不是模型编的。如果返回的是模型编的内容说明工具没被发现客户端直接让模型瞎猜了。5. 本篇常见报错排查401、local proxy failed、reading choices做这个链路报错基本集中在几个地方。我按实际遇到的频率排一下。401 Unauthorized。这个几乎都是 Key 或 Base URL 配错。先确认客户端里填的 Base URL 是https://taotoken.net/api不是首页地址也不是带 UTM 的地址。然后确认 Key 是从 https://taotoken.net/api-keys 创建的没有多余空格。如果用的是 Claude Code检查ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY两个环境变量都设了只设一个也会 401。local proxy failed。这个报错通常出现在客户端试图连接 MCP Server 时。先确认 Spring Boot 服务真的在 8089 端口监听curl -N http://localhost:8089/sse能返回事件流。如果服务没起来检查spring-ai-mcp-server-webmvc-spring-boot-starter依赖是否引入成功启动日志里有没有MCP Server started之类的字样。另一个原因是端口被占换个端口重试。reading choices 相关报错。这个一般出现在模型返回格式不符合预期时根因往往是模型 ID 填错或者客户端把非 chat 模型的响应当 chat 解析。去 https://taotoken.net/doc 确认当前模型列表把 Model ID 改成文档里明确支持的。如果用的是 coding-plan 通道确认调用方式符合它的约定。工具被发现但调用返回空。检查smd.service.url指向的业务服务是否可达以及业务接口的路径、参数名是否和Tool方法里写的一致。MCP Server 只是转发业务接口 404 它也会把 404 的 body 返回给客户端。SSE 连接频繁断开。Spring MVC 的 SSE 默认超时时间可能偏短可以在 application.yml 里加spring.mvc.async.request-timeout: 300000延长到 5 分钟。另外确认没有中间层比如某些网关把长连接掐了。排查顺序建议先 curl SSE 确认 MCP Server 活着再在客户端里看工具列表有没有出现最后发一条会触发工具调用的消息看日志。三步定位比盲目改配置快得多。6. 把统一 Key 通道用起来的后续路径整条链路跑通之后你会发现真正省事的地方在于Spring Boot 那边完全不用管模型是谁、Key 是什么它只负责把工具暴露好客户端那边只认一个 TaoToken 的 Base URL 和 Key换模型只改 Model ID不用动 MCP 配置。这种分工让后续扩展变得简单——再加一个业务工具就在SmdMcpService里加一个Tool方法再加一个客户端就复制一份 mcp.json 改个名字。如果你打算把这个模式用到团队里建议把 MCP Server 的配置模板化application.yml里的smd.service.url按环境注入工具类按业务域拆成多个 Service每个 Service 一个ToolCallbackProvider。这样不同业务线可以各自维护自己的工具互不影响。模型通道这边短期验证用 https://taotoken.net/model-chat 就够长期跑编码类任务可以看 https://taotoken.net/coding-plan 的通道策略。Key 的管理统一在 https://taotoken.net/api-keys 做接入细节以 https://taotoken.net/doc 为准。把这两侧都收拢好传统服务接大模型这件事就从「每个项目重来一遍」变成了「配一次到处复用」。