
1. 为什么要把 SpringBoot 业务逻辑交给大模型调用很多团队手里已经有一套跑得好好的 SpringBoot 服务里面封装了订单查询、客户检索、库存校验这些核心业务逻辑。与此同时大模型工具链Claude Code、Cursor、Cline 这类客户端越来越能干但它们的默认能力只停留在“读写文件、跑命令”这一层根本碰不到你数据库里的真实数据。于是问题就来了能不能让大模型在受控权限下直接调用我 SpringBoot 里已经写好的方法而不是让它瞎猜答案就是 MCPModel Context Protocol。你可以把它理解成一套“给 AI 用的 USB 接口标准”你的 SpringBoot 应用是设备MCP Server 是那根数据线AI 客户端是主机。只要按协议把业务方法注册成 ToolAI 就能像调用本地函数一样调用你的业务逻辑而且调用范围完全由你决定——你注册哪个方法它才能碰哪个方法。这篇要解决的核心场景很具体你有一个已有的 SpringBoot 服务想通过 MCP 协议把业务能力暴露出去让 AI 大模型在受控权限下直接调用内部逻辑同时用 TaoToken 的统一 Key 完成端到端验证。适合谁看有 SpringBoot 基础、想接入大模型工具链的后端同学以及正在做 AI Agent 落地、需要把内部系统接进模型工具链的工程师。我试过把 CRM 查询、订单状态这类只读逻辑先暴露出去实测下来最稳的路径是SpringBoot 侧用 Spring AI 的 MCP Server starter 注册 Tool客户端侧用 TaoToken 统一 Key 接入模型两边各管各的鉴权互不越界。下面从依赖配置一路写到端到端验证每一步都能直接抄。2. TaoToken 统一 Key 接入前置准备在动手写 MCP Server 之前先把模型侧的入口理清楚。MCP 解决的是“AI 怎么调用你的业务”但 AI 本身得先能跑起来、能连上模型这一步用 TaoToken 来做统一接入最省事。它的作用是给你一个统一的 API 入口和 Key不用在多个模型供应商之间来回切换配置客户端里填一次 Base URL 和 Key 就能用。你需要准备三样东西我把它列成表格方便对照项目值说明Base URLhttps://taotoken.net/api所有客户端统一填这个API Key在控制台创建形如sk-xxxx只显示一次Model ID按需选择例如claude-sonnet-4-5这类模型标识获取 Key 的路径很直接打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 进控制台在 API Keys 页面新建一个 Key。创建完立刻复制保存页面刷新后就看不到完整值了这是很多人第一次踩的坑。注意Key 属于敏感凭证不要写进前端代码、不要提交到 Git 仓库。建议放在环境变量或客户端的本地配置里MCP Server 侧如果需要调用模型也走环境变量注入。如果你只是想先验证模型通不通可以直接用模型对话页面发一条消息试试https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。能正常返回说明 Key 和 Base URL 没问题再往下做 MCP 接入就少一个变量。对于长期做编码和 Agent 的场景可以考虑 Coding Plan它更适合高频调用https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API Keys 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。这几步做完模型侧的前置就算齐了。3. SpringBoot MCP Server 依赖配置与工具注册这一节是全文技术核心篇幅给足。目标是把一个普通 SpringBoot 应用改造成 MCP Server暴露两个业务方法查询全部客户、按姓名查客户。先看依赖。在pom.xml里加 Spring AI 的 MCP Server starter。如果你用 STDIO 传输本地客户端直接拉起 jar用下面这个dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server/artifactId /dependency如果你想让客户端通过 HTTP 远程连接SSE 传输换成 WebMVC 版本dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webmvc/artifactId /dependency两者区别很关键STDIO 是本地进程通信客户端负责启动你的 jar适合个人开发机SSE 是网络通信你的服务部署在哪都行客户端填个 URL 就能连适合团队共享。选哪个取决于你的部署形态不是随便挑的。接着配置application.properties。STDIO 模式下要关掉 Web 容器否则启动会冲突spring.application.namecrm-mcp-server spring.main.web-application-typenone spring.ai.mcp.server.name${spring.application.name} spring.ai.mcp.server.version1.0.0如果是 SSE 模式把web-application-typenone去掉服务启动后会自动发布/sse端点。然后定义数据模型。用 Java record 最干净不可变、自带构造和访问器package com.example.mcpserver; public record Customer(String id, String name, String email, String phone, String company) {}核心在 Service 层。Tool注解负责把方法暴露给 MCP 框架name是 AI 看到的工具名description是 AI 判断何时调用的依据写清楚很重要package com.example.mcpserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.tool.annotation.Tool; import org.springframework.stereotype.Service; import jakarta.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; Service public class CustomerService { private static final Logger log LoggerFactory.getLogger(CustomerService.class); private final ListCustomer customers new ArrayList(); Tool(name get_customers, description 获取 CRM 系统中的全部客户列表) public ListCustomer getCustomers() { log.info(MCP 调用: get_customers, 返回 {} 条, customers.size()); return customers; } Tool(name get_customer_by_name, description 根据姓名查询单个客户信息) public Customer getCustomerByName(String name) { log.info(MCP 调用: get_customer_by_name, name{}, name); return customers.stream() .filter(c - c.name().equals(name)) .findFirst() .orElse(null); } PostConstruct public void init() { customers.addAll(List.of( new Customer(1, 张三, zhangsanexample.com, 13800138001, 示例科技A), new Customer(2, 李四, lisiexample.com, 13800138002, 示例科技B), new Customer(3, 王五, wangwuexample.com, 13800138003, 示例科技C) )); } }最后在主类里把 Service 注册成 ToolCallback。ToolCallbacks.from()会自动扫描所有Tool方法不用一个个手写package com.example.mcpserver; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.ToolCallbacks; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import java.util.List; SpringBootApplication public class McpServerApplication { public static void main(String[] args) { SpringApplication.run(McpServerApplication.class, args); } Bean public ListToolCallback crmTools(CustomerService customerService) { return List.of(ToolCallbacks.from(customerService)); } }到这里 Server 侧就完成了。注意一个安全原则只暴露只读或幂等的方法写操作下单、扣库存要么不暴露要么在方法内部再做一层权限校验。MCP 的“受控”不是自动的是你注册什么它才能调什么。4. 客户端配置与端到端调用验证Server 写完了得让 AI 客户端连上它。这里分两种传输方式讲配置片段都能直接复制。先说 STDIO 方式。先打包mvn clean package -DskipTests产物在target/目录下比如crm-mcp-server-0.0.1-SNAPSHOT.jar。然后在客户端以 Cursor 为例的 MCP 配置里加{ mcpServers: { crm-demo-mcp: { command: java, args: [-jar, /absolute/path/to/crm-mcp-server-0.0.1-SNAPSHOT.jar] } } }路径一定用绝对路径相对路径在客户端拉起进程时经常找不到 jar这是高频坑。再说 SSE 方式。服务正常启动后监听 8080客户端配置改成 URL 形式{ mcpServers: { crm-demo-mcp: { url: http://localhost:8080/sse } } }如果你用的是 Cline 或 Claude Code 这类客户端配置结构类似核心三件套是 Base URL、Key、Model ID。以模型接入为例客户端里填{ baseUrl: https://taotoken.net/api, apiKey: sk-你的Key, model: claude-sonnet-4-5 }MCP Server 的配置和模型配置是两套东西别混在一起前者告诉客户端“去哪调用业务工具”后者告诉客户端“用哪个模型来思考”。配置保存后重启客户端在工具列表里应该能看到get_customers和get_customer_by_name。然后发一条自然语言指令验证使用 MCP 服务器获取所有 CRM 客户信息。预期结果是模型调用get_customers返回三条客户记录。再试一条精确查询使用 MCP 服务器查找姓名为张三的客户信息。模型应该调用get_customer_by_name参数name张三返回对应记录。同时你的 SpringBoot 控制台会打印MCP 调用: get_customer_by_name, name张三这条日志就是端到端打通的铁证。如果日志没打印说明请求根本没到 Server问题在客户端配置或进程启动如果日志打印了但客户端没结果问题在返回序列化。5. 常见报错排查对照接入过程里最容易卡在几个固定报错上我按真实遇到的整理成对照表方便你直接定位。报错/现象根因处理方式401 UnauthorizedKey 错误或未带检查apiKey是否为控制台新建的完整值注意别带空格local proxy failed客户端网络配置异常检查 Base URL 是否为https://taotoken.net/api不要多加斜杠或路径reading choices解析失败返回体非预期 JSON确认 Model ID 拼写正确换一个模型标识重试OAuth 相关报错客户端走了错误的鉴权模式改用 API Key 模式不要启用 OAuth 流程工具列表为空Server 未注册 ToolCallback检查Bean是否返回了ToolCallbacks.from(...)客户端连不上 SSE端口或路径不对确认服务监听 8080 且端点为/sse重点说两个。401和local proxy failed基本都出在模型接入这一层跟 MCP Server 无关先把模型对话页面调通再排查 MCP。reading choices通常是 Model ID 写错客户端拿到的是错误响应体解析自然失败。还有一个隐蔽的坑STDIO 模式下如果application.properties没关 Web 容器jar 启动会卡住或直接退出客户端表现为“连接超时”。这时候去看 Server 的启动日志如果有 Tomcat 相关输出就是这个问题。如果你用的是 Codex 的auth.json或 CC Switch 这类配置管理工具记住三件套必须齐全Base URL、Key、Model ID缺一个都会报鉴权或路由错误。Cline 的 MCP 配置同理Server 配置和模型配置分开写别把 MCP 的 command 塞进模型配置里。6. 把业务逻辑安全交给 AI 的落地建议走到这里你已经有一个能跑的 SpringBoot MCP ServerAI 能通过 TaoToken 统一 Key 接入后调用你的业务方法。最后给几条实战建议都是踩过坑总结的。第一权限边界靠“注册粒度”控制不靠模型自觉。你只注册get_customersAI 就永远调不到删除方法。写操作要暴露的话在方法内部加参数校验和操作日志别指望模型帮你把关。第二Tool 的description要写成人话。模型是根据描述判断该不该调用的写“查询客户”比写“customer query method”命中率高得多。参数名也要语义化name就比n好。第三STDIO 适合本地开发SSE 适合团队共享。本地调试用 STDIO 快但部署到服务器给多人用时SSE 的 URL 接入更省事客户端不用装 jar。第四模型侧和业务侧分开排障。模型不通看401/local proxy failed业务不通看 Server 日志有没有打印调用记录。两边日志一对问题立刻定位。需要长期跑编码和 Agent 任务的Coding Plan 的额度模型更适合高频场景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入细节随时查文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content Key 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。先把只读查询跑通再逐步放开更多业务能力这条路最稳。