拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

【AI】Spring AI+MCP实战:零代码改造将传统服务接入大模型生态|TaoToken统一Key打通调用链路

【AI】Spring AI+MCP实战:零代码改造将传统服务接入大模型生态|TaoToken统一Key打通调用链路

1. 传统 Spring Boot 服务接入大模型生态的真实困境

很多团队手里都有一套跑了三五年的 Spring Boot 业务系统,接口稳定、逻辑清晰,但一到要接大模型就犯难。最直接的做法是在业务代码里硬编码调用某个模型的 SDK,结果就是:换模型要改代码、加模型要加依赖、每个模型一套 Key 分散在配置文件里,运维排查时根本不知道哪个请求走了哪条通道。我见过一个项目,光是模型鉴权配置就散落在四个 yml 文件里,出问题只能一个个 grep。

MCP(Model 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 starter:

<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.4.2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId> <version>1.0.0-M6</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</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 用 SYNC,sse-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:8080

smd.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 = "表名") Set<String> tableNames) { Map<String, Object> params = new HashMap<>(); params.put("businessSystem", businessSystem); params.put("tableNames", tableNames); ResponseEntity<String> response = restTemplate.postForEntity( smdServiceUrl + "/mcp/api/getSmdInfo", params, String.class); return response.getBody(); } @Tool(name = "getCRUDCode", description = "根据表名生成增删改查代码") public List<Map<String, Object>> getCRUDByTable( @ToolParam(description = "业务系统") String businessSystem, @ToolParam(description = "表名") Set<String> tableNames, @ToolParam(description = "模块名,非必填") String moduleName) { Map<String, Object> params = new HashMap<>(); params.put("businessSystem", businessSystem); params.put("tableNames", tableNames); params.put("moduleName", moduleName); params.put("author", "smd-mcp"); HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params); ResponseEntity<List<Map<String, Object>>> response = restTemplate.exchange( smdServiceUrl + "/mcp/api/crud", HttpMethod.POST, httpEntity, new ParameterizedTypeReference<List<Map<String, 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?sessionId=xxx的内容。这个 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 为准。把这两侧都收拢好,传统服务接大模型这件事就从「每个项目重来一遍」变成了「配一次,到处复用」。

返回列表