ARTICLE DETAIL

资讯详情

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

一个 @McpTool 注解,让 Claude 和 Cursor 直接调用你的 Spring 服务:TaoToken 统一 Key 配置实战

一个 @McpTool 注解,让 Claude 和 Cursor 直接调用你的 Spring 服务:TaoToken 统一 Key 配置实战 1. 从「模型答得挺好就是碰不到我的数据」说起如果你正在用 Claude 或 Cursor 写代码大概率遇到过这个场景你问它「帮我查一下订单 SO-20260825-0001 现在到哪了」它要么礼貌地告诉你「我无法访问你的系统」要么一本正经地编一个物流状态出来。问题不在模型而在于它和你的 Spring 服务之间缺一条标准通道。MCPModel Context Protocol就是这条通道。它把「模型能调用什么」这件事标准化了服务端用 Tools / Resources / Prompts 三种原语描述能力客户端通过 JSON-RPC 2.0 发起调用传输层走 STDIO 或 Streamable HTTP。对 Java 开发者来说最舒服的一点是Spring AI 2.0 已经把注解和传输模块全部收编你现有的 Spring Boot 服务加一个McpTool注解它就成了一个标准 MCP Server。但「服务能跑」和「Claude、Cursor 能稳定连上」之间还差一层客户端配置。Cursor 用settings.json风格的 MCP 配置Claude Code 用config.toml两边字段名、传输类型、鉴权头写法都不一样。更麻烦的是如果你同时接多个模型供应商每个客户端都要单独维护一套 Key改一次配置要动三四个文件。这篇就解决这一层。我会先给出McpTool的最小可跑骨架再用 TaoToken 统一 Key 和 API 通道把 Claude 与 Cursor 的配置收敛成一份可复制的模板最后演示一次从注解扫描到客户端调用成功的完整验证动作。适合已经写过 Spring Boot、想把自己的业务能力接进 AI 客户端的开发者也适合正在给团队搭内部工具链的同学。版本坐标先交代清楚避免踩坑本文基于 Spring AI 2.0.1当前稳定版与 MCP Java SDK 2.0.x对应 2025-11-25 版 MCP 规范。规范本身已经跑到 2026-07-28但 Java 服务端生态还在 2025-11-25这个差值不影响本文的所有操作因为 Streamable HTTP 和无状态变体在 2025-11-25 里就已经齐了。2. 前置准备TaoToken 统一 Key 与通道在写客户端配置之前先把「Key 从哪来、请求打到哪」这件事定下来。TaoToken 在这里扮演的角色是统一入口你不需要为 Claude、Cursor、以及后续可能接入的其他客户端分别申请和管理不同的 Key而是用一份 Key 走同一个 API 通道。具体操作路径是这样的。先访问官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册并登录然后在控制台里创建 API Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite API Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。创建完记得立刻复制页面刷新后完整 Key 就不再显示了。API 的基础地址是 https://taotoken.net/api 注意这个地址不带任何查询参数配置时直接填这一串就行。如果你用的是兼容 Anthropic 协议的客户端Claude Code 就是这一类走的是 https://taotoken.net/api 下的 Anthropic 兼容路径具体可以参考文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。这里有个容易混淆的点值得单独说MCP Server 的地址和模型 API 的地址是两回事。你的 Spring 服务暴露出来的 MCP 端点是http://localhost:8080/mcp这是「工具通道」TaoToken 的https://taotoken.net/api是「模型通道」。Claude 和 Cursor 在运行时同时需要这两条通道——通过模型通道做推理通过工具通道调你的服务。配置时不要把两者填串了。如果你打算长期在编码场景里用比如让 Cursor 持续调用你的内部工具可以看一下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。它更适合高频、长会话的编码与 Agent 场景比按次调用更省心。3. 可复制配置从 McpTool 到 settings.json 与 config.toml这一节是全文的核心分三块服务端注解骨架、Cursor 的配置、Claude Code 的配置。每一块都给可直接复制的完整内容。3.1 服务端一个 McpTool 注解的最小骨架先建项目。Spring Boot 4.x Spring AI 2.0.1只需要一个 starterparent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version4.1.1/version /parent properties spring-ai.version2.0.1/spring-ai.version /properties dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webmvc/artifactId /dependency /dependencies dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version${spring-ai.version}/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement然后写工具类。注意包名是org.springframework.ai.mcp.annotation.*2.0 起注解已经完全融入 Spring AI扫描默认开启不需要额外加EnableMcpServer之类的开关import org.springframework.ai.mcp.annotation.McpTool; import org.springframework.ai.mcp.annotation.McpToolParam; import org.springframework.stereotype.Component; Component public class OrderTools { private final OrderService orderService; OrderTools(OrderService orderService) { this.orderService orderService; } McpTool( name get_order, description 根据订单号查询订单状态与物流信息订单号格式为 SO-YYYYMMDD-XXXX, annotations McpTool.McpAnnotations( readOnlyHint true, destructiveHint false, idempotentHint true ) ) public OrderView getOrder( McpToolParam(description 订单号例如 SO-20260825-0001, required true) String orderNo) { return orderService.findByNo(orderNo); } }description不是注释它是模型判断「何时调用、怎么传参」的唯一依据值得当成 prompt 来打磨。annotations里的 hints 会被客户端用于交互确认比如readOnlyHint true告诉客户端这个工具不改数据调用前不必反复询问用户。异常语义有一条隐形分界线实测下来很关键工具方法里抛RuntimeException会被转成isErrortrue的工具结果传回给模型模型能读到错误信息并自行纠正而抛受检异常或Error会直接导致调用失败模型看不到原因。所以参数校验失败时抛一个带可读信息的RuntimeException比如「订单号格式不合法应为 SO-YYYYMMDD-XXXX」下一轮模型通常能自己改对。3.2 服务端配置application.ymlspring: ai: mcp: server: protocol: STREAMABLE name: order-mcp-server version: 1.0.0 instructions: 订单查询服务支持按订单号查询状态与物流 streamable-http: mcp-endpoint: /mcp启动后http://localhost:8080/mcp就是 MCP 端点。instructions相当于服务端的自我介绍带规划能力的客户端会把它纳入上下文。3.3 Cursor 配置settings.json 骨架Cursor 的 MCP 配置走 JSON 结构。在项目级或全局配置里加入{ mcpServers: { order-service: { url: http://localhost:8080/mcp, transport: streamable-http, headers: { Authorization: Bearer ${env:TAOTOKEN_API_KEY} } } } }三个字段值得说明。url指向你的 Spring 服务端点不是 TaoToken 的地址。transport显式写成streamable-http避免客户端回退到已弃用的 HTTPSSE。headers里放鉴权信息用环境变量引用而不是硬编码明文 Key这样配置文件可以进版本库。如果你在 Cursor 里同时配置了模型供应商把模型侧的 base URL 指向https://taotoken.net/apiKey 用同一个TAOTOKEN_API_KEY这样模型通道和工具通道共用一份凭据改 Key 只需要改一个环境变量。3.4 Claude Code 配置config.toml 骨架Claude Code 走 TOML 格式字段名和 JSON 那套不同别直接照搬[[mcp_servers]] name order-service url http://localhost:8080/mcp transport streamable-http [mcp_servers.headers] Authorization Bearer ${TAOTOKEN_API_KEY}模型侧如果走 Anthropic 兼容协议在 Claude Code 的环境配置里设置[env] ANTHROPIC_BASE_URL https://taotoken.net/api ANTHROPIC_API_KEY ${TAOTOKEN_API_KEY}注意ANTHROPIC_BASE_URL填的是不带路径的根地址客户端会自己拼接后续路径。填成带/v1之类的地址反而会 404这是我自己踩过的坑。4. 验证请求从注解扫描到客户端调用成功配置写完不算完得验证整条链路真的通了。分三步走每步都有明确的成功标志。第一步确认注解被扫描到。启动服务观察启动日志里有没有工具注册相关的记录。如果日志里出现类似「Registered tool: get_order」的行说明 annotation-scanner 正常工作。如果没有任何相关日志先检查工具类是否被 Spring 扫描到包路径是否在启动类同级或子级以及依赖是否真的引入了spring-ai-starter-mcp-server-webmvc。第二步用 MCP Inspector 做协议层自测。这是官方调试工具能让你看到原始 JSON-RPC 报文npx modelcontextprotocol/inspector浏览器打开调试界面后Transport Type 选 Streamable HTTPURL 填http://localhost:8080/mcp点 Connect。左侧日志里应该能看到完整的initialize握手报文。切到 Tools 标签页点 List Tools应该列出get_order。填入SO-20260825-0001点 Call Tool右侧会返回 JSON-RPC 格式的结果。这一步的价值在于把模糊问题变具体。如果 List Tools 是空的问题在服务端注册如果 Call Tool 报 500问题在你的业务代码如果连接就失败问题在传输配置。三种情况排查方向完全不同。第三步在真实客户端里验证。打开 Cursor新建对话输入「帮我查一下订单 SO-20260825-0001 到哪了」。观察对话过程模型应该先决定调用get_order工具界面上会显示工具调用卡片然后基于返回结果组织回答。如果模型直接编了一个答案而没调工具回到 Inspector 检查工具的description是否足够清晰——描述模糊是模型不调工具的头号原因。Claude Code 侧同理在终端里发起对话观察是否有工具调用记录。两边都验证通过说明你的 Spring 服务已经能被主流 AI 客户端稳定调用了。5. 本篇常见错排查报错一客户端连接 MCP 端点返回 404。最常见的原因是端点路径不对。Spring AI 默认端点是/mcp如果你在application.yml里改过mcp-endpoint客户端配置里的 URL 要同步改。另一个原因是服务没起在 8080检查server.port。报错二List Tools 返回空数组。注解没被扫描到。检查三点工具类有没有Component包路径是否在启动类的扫描范围内依赖是不是spring-ai-starter-mcp-server-webmvc写成 webflux 版本在同步场景下会有行为差异。报错三模型不调用工具直接编答案。九成是description写得太笼统。把「查询订单」改成「根据订单号查询订单状态与物流信息订单号格式为 SO-YYYYMMDD-XXXX」调用准确率会有肉眼可见的提升。参数描述同理McpToolParam的description要给出格式示例。报错四切换 STATELESS 后工具消失。无状态模式下注解方法不能使用双向通信的上下文。如果你的方法签名里有McpSyncRequestContext并且调用了elicit()、sample()、roots()Spring AI 启动时会过滤掉这个方法并记警告日志。解决办法是把这些调用去掉改用轻量的McpTransportContext或者干脆不带上下文参数。切换模式后记得看一眼启动日志。报错五Claude Code 报鉴权失败。检查ANTHROPIC_BASE_URL是否填成了带路径的地址。正确写法是根地址https://taotoken.net/api不要自己拼/v1。另外确认环境变量TAOTOKEN_API_KEY在当前 shell 里真的导出了echo $TAOTOKEN_API_KEY验证一下。报错六多副本部署时会话丢失。有状态模式下服务端维护会话多副本需要会话亲和或共享存储。如果你的工具是纯查询类直接切protocol: STATELESS端点不变可以随便挂到轮询负载均衡后面。6. 把两条通道收敛成一份配置回到最开始的问题Claude 和 Cursor 要同时接入你的 Spring 服务最烦的不是写McpTool而是维护两套客户端配置加两套 Key。用 TaoToken 统一 Key 之后模型通道的地址和凭据只有一份工具通道的地址指向你自己的服务两边配置结构不同但内容可以对照着改。如果你还在选型阶段想先验证模型对某个工具描述的理解是否准确可以直接在模型对话里试https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 。把工具描述贴进去问它「什么情况下你会调用这个工具」能快速发现描述里的歧义。接入过程中遇到协议层的具体问题接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite API Key 的创建和管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。长期在编码场景里高频使用的话Coding Plan 的路径是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。最后留一个实操建议先把 Inspector 那一步跑通再动客户端配置。很多人一上来就改 Cursor 的 JSON结果连接失败时分不清是服务端问题还是客户端问题来回折腾半小时。Inspector 能让你在协议层确认服务端没问题之后客户端配置就只是填空题了。
返回列表