让Spring Boot项目秒变MCP服务:加1个类把Controller改到TaoToken
发布时间:2026/10/2 17:06:17来源:尧图网络
1. 存量 Spring Boot 项目接入 MCP 的真实痛点很多团队手里已经有一套跑了两三年的 Spring Boot 业务系统Controller 里堆着商品查询、订单创建、客户管理这些接口前端、定时任务、内部调用方都在用。现在想让 AI Agent 直接调用这些能力第一反应往往是「重写一套工具层」——把每个 Service 方法再包一层 Function Calling 描述或者干脆另起一个 Python 服务做桥接。这条路我走过代价是接口一改就要同步维护两份定义时间一长必然漂移。Model Context Protocol简称 MCP解决的正是这个问题。它是一套让 AI 客户端发现并调用外部工具的开放协议Claude Desktop、CherryStudio、Cline 这类客户端都支持。你只要把现有 Spring Boot 项目暴露成一个 MCP 服务AI 就能像调用内置工具一样调用你的query_products、create_order。关键在于不需要动原有 Controller也不需要改业务逻辑新增一个类即可。这篇面向的是「已有 Spring Boot 存量项目、想快速接入 MCP 协议」的场景。我会从现有 Controller 出发给出可复制的配置类代码、Maven 依赖坐标、启动验证步骤并说明如何把服务端点统一改到 TaoToken 通道最后用一次真实的工具调用确认 MCP 服务能被客户端发现。适合谁手上有 Spring Boot 项目、想让 AI Agent 调用自己业务接口、又不想大改架构的后端同学。读完你能拿到一个能跑起来的最小闭环而不是一堆概念。2. TaoToken 前置准备与 MCP 服务端点规划在写代码之前先把「AI 客户端怎么找到你的服务」这件事想清楚。MCP 服务本质是一个 HTTP 端点客户端通过它拉取工具列表tools/list并执行工具tools/call。本地开发时你直接连http://localhost:8080/mcp就行但一旦要跨网络、多客户端共用、或者做统一鉴权和用量观测就需要一个稳定的统一通道。我实测下来把 MCP 服务端点接到 TaoToken 的统一通道上能省掉不少重复配置。原因是多个 AI 客户端Claude Desktop、Cline、CherryStudio各自要填 Base URL、Key、Model ID如果每个客户端都直连你本地服务鉴权、日志、限流都得自己再写一遍。走统一通道后客户端只认一个地址你的 Spring Boot 服务也只需要暴露标准 MCP 端点。前置准备分三步。第一步拿到访问凭证。打开 https://taotoken.net/api-keys 创建 API Key这个 Key 后面会同时用于 MCP 服务鉴权和模型调用。第二步确认你的 Spring Boot 项目版本建议 Spring Boot 3.x JDK 17 以上因为 MCP 的 Java 实现依赖较新的语言特性。第三步规划端点路径我习惯用/mcp作为 MCP 服务的根路径和原有/api/**业务接口完全隔离互不影响。这里要强调一个容易踩的坑MCP 服务和普通 REST 接口的请求体格式不同。普通接口是{name:张三}MCP 走的是 JSON-RPC 2.0形如{jsonrpc:2.0,method:tools/list,id:1}。所以你不能直接把现有 Controller 的方法签名套上去而是要在新增的类里做一层「协议适配」——把 MCP 的tools/call请求翻译成对你现有 Service 的调用。这也是为什么「加一个类」就够了这个类承担协议转换职责业务逻辑一行不改。关于统一通道的地址模型对话入口在 https://taotoken.net/api 对应的对话能力编码类长期任务可以看 Coding Plan接入文档在 https://taotoken.net/doc。MCP 服务本身作为你自建的服务端点由你的 Spring Boot 应用提供TaoToken 通道负责的是客户端侧的模型调用与统一接入。两者配合起来AI 客户端既能发现你的工具又能通过统一通道完成推理。3. 可复制的 MCPController 配置类与依赖坐标这一节是核心直接给能跑的代码。先加依赖Maven 坐标如下放在pom.xml的dependencies里dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.fasterxml.jackson.core/groupId artifactIdjackson-databind/artifactId /dependency如果你用的是 Gradle对应写法implementation org.springframework.boot:spring-boot-starter-web implementation com.fasterxml.jackson.core:jackson-databind接下来是新增的MCPController.java。它的职责有三个暴露/mcp端点、处理 JSON-RPC 的tools/list和tools/call、把工具调用转发到你现有的 Service。下面这段可以直接复制把your-secret-api-key-2025换成你自己的 Keypackage com.example.demo.mcp; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import java.util.*; RestController RequestMapping(/mcp) public class MCPController { private static final String API_KEY your-secret-api-key-2025; private final ObjectMapper mapper new ObjectMapper(); PostMapping(consumes MediaType.APPLICATION_JSON_VALUE, produces MediaType.APPLICATION_JSON_VALUE) public ObjectNode handle(RequestBody JsonNode request, RequestHeader(value Authorization, required false) String auth) { ObjectNode response mapper.createObjectNode(); response.put(jsonrpc, 2.0); response.put(id, request.path(id).asInt()); if (auth null || !auth.equals(Bearer API_KEY)) { ObjectNode error mapper.createObjectNode(); error.put(code, -32001); error.put(message, Unauthorized); response.set(error, error); return response; } String method request.path(method).asText(); switch (method) { case tools/list - response.set(result, buildToolsList()); case tools/call - response.set(result, executeToolCall(request.path(params))); default - { ObjectNode error mapper.createObjectNode(); error.put(code, -32601); error.put(message, Method not found: method); response.set(error, error); } } return response; } private ObjectNode buildToolsList() { ObjectNode result mapper.createObjectNode(); ArrayNode tools mapper.createArrayNode(); tools.add(createTool(query_products, Query Products, Search and filter products with various criteria)); tools.add(createTool(create_order, Create Order, Create a new order in the system)); tools.add(createTool(generate_report, Generate Business Report, Generate comprehensive business reports and analytics)); result.set(tools, tools); return result; } private ObjectNode createTool(String name, String title, String description) { ObjectNode tool mapper.createObjectNode(); tool.put(name, name); tool.put(description, description); ObjectNode schema mapper.createObjectNode(); schema.put(type, object); schema.set(properties, mapper.createObjectNode()); tool.set(inputSchema, schema); return tool; } private ObjectNode executeToolCall(JsonNode params) { String toolName params.path(name).asText(); JsonNode arguments params.path(arguments); String output switch (toolName) { case query_products - query_products executed with arguments; case create_order - create_order executed with arguments; case generate_report - generate_report executed with arguments; default - ERROR: Unknown tool: toolName; }; ObjectNode result mapper.createObjectNode(); ArrayNode content mapper.createArrayNode(); ObjectNode text mapper.createObjectNode(); text.put(type, text); text.put(text, output); content.add(text); result.set(content, content); return result; } }上面executeToolCall里的三个 case 是占位实现实际使用时替换成对你现有 Service 的调用即可比如productService.query(arguments)。这就是「零侵入」的含义你的ProductService、OrderService完全不用改MCPController 只做协议翻译。如果你用 Claude Code 或 Cline 这类客户端配置片段settings 风格如下注意 Base URL、Key、Model ID 三件套要写全{ mcpServers: { spring-boot-mcp: { url: http://localhost:8080/mcp, headers: { Authorization: Bearer your-secret-api-key-2025 } } } }Codex 的auth.json风格配置则是{ base_url: https://taotoken.net/api, api_key: your-secret-api-key-2025, model: claude-sonnet-4-5 }注意base_url指向 TaoToken 的 API 地址model填你实际使用的模型 ID。MCP 服务地址和模型地址是两个概念别混在一起填。4. 启动验证与一次真实的工具调用代码写完启动项目。控制台看到Tomcat started on port(s): 8080就说明服务起来了。先用 curl 验证tools/list能不能正常返回curl -X POST http://localhost:8080/mcp \ -H Content-Type: application/json \ -H Authorization: Bearer your-secret-api-key-2025 \ -d {jsonrpc:2.0,method:tools/list,id:1}预期返回里能看到query_products、create_order、generate_report三个工具说明 MCP 服务已经能被发现。如果返回Unauthorized检查 Authorization 头是否带了Bearer前缀。接着验证tools/callcurl -X POST http://localhost:8080/mcp \ -H Content-Type: application/json \ -H Authorization: Bearer your-secret-api-key-2025 \ -d {jsonrpc:2.0,method:tools/call,id:2,params:{name:query_products,arguments:{keyword:手机}}}返回的result.content[0].text里应该包含你传入的参数说明调用链路通了。这一步成功后再去 CherryStudio 或 Claude Desktop 里配置 MCP 服务地址填http://localhost:8080/mcp鉴权头填上 Key。客户端刷新后工具列表里会出现你定义的三个工具点开对话窗口让 AI 调用query_products能看到它真的发起了请求并拿到返回。我试过在 CherryStudio 里做这个验证第一次没成功原因是客户端把 MCP 服务当成了 SSE 长连接而我的实现是普通 POST。解决办法是在客户端配置里明确指定传输方式为 HTTP或者确认客户端版本支持 streamable HTTP。这个细节在文档里往往一笔带过但实际配置时很容易卡住。验证通过后把服务端点改到 TaoToken 统一通道。做法是在客户端侧把模型调用的 Base URL 指向https://taotoken.net/apiMCP 服务地址仍指向你的 Spring Boot 应用。这样 AI 的推理走统一通道工具调用走你的本地服务两边各司其职。如果你要做长期编码或 Agent 任务可以看 Coding Plan它更适合高频、长会话的场景。5. 常见报错排查401、local proxy failed 与 reading choices接入过程中最容易撞上的几类报错我按实际遇到的频率排一下。401 Unauthorized。这个最常见两种原因一是 MCPController 里的 API_KEY 和客户端配置的 Key 不一致二是 Authorization 头格式不对。注意必须是Bearer加空格再加 Key少一个空格都会 401。排查方法是用 curl 直接打端点排除客户端配置干扰。local proxy failed。这个报错通常出现在客户端侧意思是客户端连不上你配置的地址。先确认 Spring Boot 服务是否真的在监听 8080用netstat -ano | findstr 8080Windows或lsof -i:8080Mac/Linux看一眼。如果服务正常检查客户端填的地址是不是localhost——有些客户端在容器或远程环境里跑localhost指向的是它自己而不是你的宿主机这时要换成实际 IP。reading choices 相关报错。这类报错一般出现在模型调用侧说明请求发出去了但响应格式不符合预期。常见原因是 Base URL 填错比如把 MCP 服务地址填到了模型 Base URL 的位置。记住模型 Base URL 是https://taotoken.net/apiMCP 服务地址是你自己的http://localhost:8080/mcp两者不能互换。另外 Model ID 要填对填一个不存在的模型名也会导致解析失败。OAuth 相关报错。如果你的客户端要求 OAuth 流程而你的 MCP 服务只做了 Bearer 鉴权就会报这个。解决办法是在客户端里选择 API Key 鉴权方式而不是 OAuth。如果客户端强制 OAuth那就需要额外实现一个 OAuth 端点这超出了「加一个类」的范围建议先用支持 API Key 的客户端验证。工具列表为空。客户端连上了但看不到工具检查tools/list返回的 JSON 结构是否符合 MCP 规范。result.tools必须是数组每个工具要有name、description、inputSchema三个字段。少一个字段客户端可能直接忽略。排查时有个通用思路先用 curl 确认服务端没问题再排查客户端配置。服务端和客户端之间的问题九成出在地址、Key、格式这三样上。把这三样对齐基本都能通。6. 把 MCP 服务接到 TaoToken 统一通道的完整配置最后把客户端侧的完整配置给全方便你直接复制。以 Cline 的 MCP 配置为例cline_mcp_settings.json内容如下{ mcpServers: { spring-boot-mcp: { url: http://localhost:8080/mcp, headers: { Authorization: Bearer your-secret-api-key-2025 }, disabled: false, autoApprove: [query_products] } } }模型侧的配置Base URL 填https://taotoken.net/apiAPI Key 填你在 https://taotoken.net/api-keys 创建的 KeyModel ID 填你实际使用的模型。这样一套配置下来AI 客户端通过统一通道做推理通过你的 Spring Boot 服务做工具调用两边解耦互不干扰。如果你想让 AI 直接对话验证模型通道是否正常可以用模型对话入口先测一轮确认 Key 和 Base URL 没问题再回来配 MCP。接入文档在 https://taotoken.net/doc里面有各客户端的详细配置说明。长期跑编码 Agent 的话Coding Plan 的额度模型更适合持续调用不用每次担心额度。配置完成后回到对话窗口让 AI 执行一次query_products看到它返回你 Service 的真实数据整条链路就闭环了。你的 Spring Boot 项目一行业务代码没改却多了一个能被 AI Agent 调用的 MCP 服务能力。后续要加新工具只需要在buildToolsList里加一行createTool在executeToolCall里加一个 case转发到对应的 Service 方法即可。
网站建设高端定制企业官网