尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

零代码革命!Spring AI+MCP实战:把传统服务Base URL改到TaoToken接入大模型生态

零代码革命!Spring AI+MCP实战:把传统服务Base URL改到TaoToken接入大模型生态 1. 传统 Spring Boot 服务接入大模型生态卡在哪一步很多后端团队手里已经有一套跑得很稳的 Spring Boot 服务REST 接口写得清清楚楚业务逻辑也经过线上验证。现在想让这些接口被大模型调用第一反应往往是重写一遍——把接口改成 Function Calling 格式、再包一层 SDK、还要处理不同模型厂商的协议差异。改完之后发现换一个模型又得改一遍。MCPModel Context Protocol解决的正是这个重复适配的问题。它把服务能做什么抽象成 Tools模型侧只要支持 MCP就能发现并调用这些 Tools不需要为每个模型单独写胶水代码。Spring AI 从 1.0.0-M6 开始提供了spring-ai-mcp-server-webmvc-spring-boot-starter意味着你可以在现有 Spring MVC 工程里用注解把已有 HTTP 接口暴露成 MCP Server原有 Controller 一行不动。这篇面向的是已经有 REST 接口、想快速对接 AI 能力的后端团队。核心链路是现有 HTTP 接口 → 用Tool注解包装成 MCP Tools → MCP Server 通过 SSE 暴露 → 客户端Cursor、Claude Code 等连接 → 模型调用 Tool 时底层请求的 Base URL 指向 TaoToken 统一通道。这样模型侧只需要一个 Key、一个 Base URL就能同时调度多个模型而你的业务服务保持零侵入。我试过在一个内部数据字典服务上走完整条链路从加依赖到 Cursor 里看到 Tools 列表大概二十分钟。下面把每一步拆开讲包括踩过的坑。2. TaoToken 前置准备统一 Key 与 Base URL 怎么拿在动手改 Spring Boot 之前先把模型侧的通道准备好。TaoToken 的作用是提供一个统一的 API 入口你不需要为每个模型厂商单独申请 Key、单独记 Base URL。对于 MCP 场景这一点很关键MCP Server 本身不绑定模型但客户端在调用模型时需要一个稳定的 Base URL 和 Key。第一步打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册并登录。进入控制台后找到 API Keys 页面创建一个新的 Key。建议按用途命名比如spring-mcp-dev方便后面排查是哪个环境在用。创建完成后你会拿到两样东西API Key一串以sk-开头的字符串只显示一次复制保存好。Base URLhttps://taotoken.net/api注意这个地址不带任何查询参数直接作为 OpenAI 兼容接口的 base 使用。如果你用的是 Claude Code 这类工具Base URL 的填法会略有不同需要指向 Anthropic 兼容路径。具体可以在接入文档里对照文档地址是 https://taotoken.net/doc 。控制台里也能直接看到当前 Key 的用量和余额方便做成本观察。这里有个容易忽略的点MCP Server 本身不直接调用模型它只负责暴露 Tools。真正调用模型的是客户端Cursor、Claude Code、Cline 等。所以 TaoToken 的 Key 和 Base URL 是配在客户端那一侧的不是配在 Spring Boot 工程里。Spring Boot 工程里配的是 MCP Server 的 SSE 端点。两者不要混。把 Key 和 Base URL 先放在手边下一节开始改工程。3. 可复制配置pom.xml、application.yml 与 MCP Tool 包装这一节是全文的核心所有片段都可以直接复制。技术选型按 Spring Boot 3.4.2 JDK 17 spring-ai-mcp-server-webmvc-spring-boot-starter1.0.0-M6。Spring AI 目前支持 Spring Boot 3.4.x3.5.x 要等后续版本。3.1 pom.xml 依赖片段在dependencyManagement里锁定 Spring Boot 版本然后加入 MCP starter 和 HTTP 客户端dependencyManagement dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-dependencies/artifactId version3.4.2/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement dependencies !-- MCP Server (Spring MVC / SSE) -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-mcp-server-webmvc-spring-boot-starter/artifactId version1.0.0-M6/version /dependency !-- Lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- Apache HttpClient 5用于转发已有 HTTP 接口 -- dependency groupIdorg.apache.httpcomponents.client5/groupId artifactIdhttpclient5/artifactId /dependency dependency groupIdorg.apache.httpcomponents.core5/groupId artifactIdhttpcore5/artifactId /dependency dependency groupIdorg.apache.httpcomponents.core5/groupId artifactIdhttpcore5-h2/artifactId /dependency !-- Spring Boot Starter -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency /dependencies注意spring-ai-mcp-server-webmvc-spring-boot-starter这个 artifact 名它对应的是 Spring MVC SSE 的方式。Spring AI 还提供 STDIO 和 WebFlux 两种选 webmvc 是因为大多数传统服务本来就是 Spring MVC改动最小。3.2 application.yml 配置spring: application: name: smd-mcp-server ai: mcp: server: name: smd-mcp-server version: 1.0.0 type: SYNC sse-endpoint: /sse smd: service: url: http://localhost:8080sse-endpoint: /sse是客户端要连的路径。type: SYNC表示同步模式适合大多数 CRUD 类接口。smd.service.url是你已有服务的地址MCP Tool 内部会转发到这个地址。3.3 把已有 HTTP 接口包装成 MCP Tool核心思路不修改原有 Controller新建一个 Service用Tool注解描述能力内部用RestTemplate转发到已有接口。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(); } }Tool的name是模型看到的工具名description是模型判断何时调用的依据写清楚。ToolParam的description同样重要模型靠它理解参数含义。3.4 注册 ToolCallbackProviderConfiguration Slf4j public class McpConfig { Bean public ToolCallbackProvider smdToolCallbackProvider( SmdMcpService smdMcpService, RulesMcpService rulesMcpService) { return MethodToolCallbackProvider.builder() .toolObjects(smdMcpService, rulesMcpService) .build(); } }把多个 Service 一起注册进去MCP Server 启动时就会扫描所有Tool方法并暴露。3.5 客户端侧 settings 示例以 Cursor 为例MCP Server 跑起来后客户端要连它。Cursor 的mcp.json配置如下{ mcpServers: { smd-mcp-server: { url: http://localhost:8089/sse, env: { API_KEY: value } } } }这里的url指向 Spring Boot 工程的 SSE 端点端口按你实际启动的来。API_KEY是 MCP Server 侧的鉴权如果开了的话不是 TaoToken 的 Key。TaoToken 的 Key 和 Base URL 配在 Cursor 的模型设置里Base URL 填https://taotoken.net/apiKey 填控制台创建的那串。这样模型调用走 TaoToken 通道MCP Tool 调用走本地 SSE两条链路分开。4. 验证请求从启动日志到一次成功的 Tool 调用配置写完启动 Spring Boot 工程。控制台会打印 MCP Server 注册的 Tools 列表类似Registered tools: [getSmdInfo, getCRUDCode, ...] MCP Server started on /sse看到这两行说明 Server 侧就绪。接下来在 Cursor 里打开 MCP 设置如果配置正确能看到smd-mcp-server处于 connected 状态展开后列出所有 Tools。验证 Tool 调用是否打通最直接的方式是在 Cursor 对话框里用自然语言触发。比如输入帮我查一下订单系统里 order_main 表的结构。模型会判断需要调用getSmdInfo参数是businessSystem订单系统、tableNames[order_main]。调用发生时你会在 Spring Boot 控制台看到转发请求的日志同时 Cursor 里会显示 Tool 调用结果。如果返回了表结构 JSON说明整条链路通了模型 → TaoToken 通道 → 模型决策 → MCP Client → SSE → Spring Boot MCP Server → 已有 HTTP 接口 → 返回。也可以用 curl 直接验证 SSE 端点是否存活curl -N http://localhost:8089/sse正常会保持连接并输出事件流。如果立即断开或返回 404说明sse-endpoint配置或端口有问题。验证模型侧通道是否正常可以在模型对话页面发一条简单请求确认 Key 和 Base URL 生效。这一步和 MCP 无关但能排除模型通道的问题。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth实际跑下来报错集中在几个地方。逐个对照。401 Unauthorized两种可能。一是 TaoToken 的 Key 填错或过期去控制台重新生成一个注意 Base URL 是https://taotoken.net/api不要多加/v1之类的路径。二是 MCP Server 侧开了鉴权但客户端env.API_KEY没填对。先确认报错来自哪一侧看 Spring Boot 日志里有没有收到请求。local proxy failed客户端连不上 MCP Server 的 SSE 端点。检查三件事Spring Boot 是否真的启动在配置的端口sse-endpoint是否是/sse防火墙或容器网络是否放行了该端口。本地开发常见的是端口写错比如工程启动在 8080但mcp.json里写了 8089。reading choices 相关报错这类通常出现在模型侧返回格式不符合预期时。检查 Base URL 是否指向了正确的兼容路径以及请求体里的 model 字段是否是 TaoToken 支持的模型 ID。如果用的是 Claude Code 这类走 Anthropic 协议的工具Base URL 的填法和 OpenAI 兼容不同需要对照接入文档调整。OAuth 报错部分客户端在连接远程 MCP Server 时会尝试 OAuth 流程。本地 SSE 场景一般不需要 OAuth如果客户端强制走 OAuth检查mcp.json里是否多写了auth相关字段。删掉后重连。Tools 列表为空MCP Server 启动了但客户端看不到 Tools。检查McpConfig里的ToolCallbackProvider是否被 Spring 扫描到Configuration注解是否生效以及Tool方法所在的 Service 是否被注册进toolObjects。另外确认spring-ai-mcp-server-webmvc-spring-boot-starter版本是 1.0.0-M6版本不匹配会导致扫描逻辑不同。转发请求超时MCP Tool 内部调用已有 HTTP 接口时超时。给RestTemplate配置合理的超时时间默认值在高延迟场景下偏短。可以在RestTemplateBean 里设置connectTimeout和readTimeout。排查顺序建议先确认 MCP Server 启动日志有 Tools 注册再确认客户端 connected最后确认模型通道正常。三段分开定位比一起猜快得多。6. 把 Key 和 Base URL 收拢到一处后续换模型不用改代码整条链路跑通后你会发现一个实际好处Spring Boot 工程里没有任何模型相关的配置。Tool方法只关心业务参数和转发地址模型是谁、走哪个通道全在客户端侧决定。这意味着后续换模型、加模型只需要在 TaoToken 控制台调整Spring Boot 代码一行不动。对于团队协作建议把 MCP Server 的 SSE 端点、TaoToken 的 Base URL 和 Key 统一记录在内部文档里按环境dev/staging/prod分开。Key 不要硬编码进代码库用环境变量或配置中心注入。如果后续要接更多客户端Claude Code、Cline、Codex 等MCP Server 侧不需要改每个客户端各自配自己的mcp.json和模型通道即可。Codex 的auth.json里填 Base URL 和 KeyCline 的 MCP 设置里填 SSE 地址逻辑一致。长期做编码类 Agent 的话可以考虑把常用 Tools 沉淀成一套内部 MCP Server 集合配合 Coding Plan 统一管理调用额度。这样新项目接入时直接复用已有 Tools不用每次从零包装。最后留一个实用技巧在Tool的description里写清楚返回值的结构模型在决定是否调用、如何解析结果时会更有把握。描述写得越具体Tool 调用的准确率越高返工越少。
返回列表