
1. 现有 Spring 服务接入 MCP 的真实痛点如果你手上已经有一批跑得好好的 Spring Boot 服务现在想让它们被 Claude、Cursor 或者自研 Agent 当成工具调用第一反应大概率是难道要把每个 Controller 都重写一遍接口签名、参数校验、返回值结构全都要按 MCP 协议重新包一层这个工作量对存量系统来说基本不可接受。Spring AI Alibaba 配合 NACOS3.0 给出的思路是业务代码不动把「服务怎么被描述、怎么被暴露」这件事下沉到注册中心和配置层。NACOS3.0 的 MCP Registry 负责管理 Tool 元数据工具名、描述、参数 schemaSpring AI Alibaba 负责在应用侧把这些元数据装配成 MCP Server 的声明骨架运行时通过配置动态生效。你原来的RestController还是那个 Controller只是多了一份「MCP 视角」的描述文件。这套方案适合谁已经有 Spring Cloud / Spring Boot 微服务、用 Nacos 做注册配置、想低成本试水 MCP 生态的团队。不适合从零起项目只想跑个 demo 的场景那种直接写 Spring AI 的Tool更快。下面我按「配置骨架 → 启动参数 → 注册验证 → 调用验证 → 排障」的顺序走一遍所有片段都可以直接复制改。2. TaoToken 前置把模型调用通道先备好MCP Server 本身只是「被调用的工具提供方」真正发起tool/call的是 MCP Client 背后的大模型。所以在你验证工具列表能不能拉取之前得先有一个能跑通模型对话的通道否则后面调用验证环节会卡在「模型侧连不上」。我习惯用 TaoToken 来做这一步原因是它的接口形态和主流 OpenAI 兼容协议一致Spring AI Alibaba 里换 base-url 和 key 就能接不用改依赖。你需要准备两样东西第一一个 API Key。到控制台的 API Keys 页面创建注意创建后只显示一次复制下来存好。第二确认接入地址。对话补全走https://taotoken.net/api在 Spring AI 配置里通常填到/v1这一级具体看你用的 starter 版本对 base-url 的拼接规则。# application.yml 片段模型通道配置 spring: ai: openai: api-key: ${TAOTOKEN_API_KEY} base-url: https://taotoken.net/api chat: options: model: claude-sonnet-4-5环境变量里放 key别硬编码进仓库export TAOTOKEN_API_KEYsk-你的key这一步做完你就有了一条可用的模型调用链路。接下来才是重点让 NACOS3.0 认识你的存量服务。3. NACOS3.0 侧MCP Registry 配置骨架NACOS3.0 默认开启鉴权这点和 2.x 差别很大很多人第一次配会卡在 403。先在application.properties里把服务端和客户端的基础项对齐。# nacos server 端关键项standalone 模式示例 nacos.core.auth.enabledtrue nacos.core.auth.server.identity.keyserverIdentity nacos.core.auth.server.identity.valueyourIdentityValue nacos.core.auth.plugin.nacos.token.secret.key请替换为Base64编码的32字节以上密钥客户端注册配置重点是命名空间和分组要和你存量服务保持一致否则 MCP Registry 找不到目标服务# 存量 Spring 服务的 bootstrap 配置 spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848 namespace: public group: DEFAULT_GROUP username: nacos password: 你的密码 config: server-addr: 127.0.0.1:8848 namespace: public group: DEFAULT_GROUP file-extension: yaml然后是 MCP 工具的元数据描述。这份配置是「0 代码」的核心——它告诉 NACOS3.0这个存量服务的哪个 HTTP 接口对应 MCP 里的哪个 Tool。放在 Nacos 配置中心里dataId 建议用服务名-mcp.yaml# dataId: order-service-mcp.yaml group: DEFAULT_GROUP mcp: server: name: order-service version: 1.0.0 tools: - name: queryOrderStatus description: 根据订单号查询订单当前状态 endpoint: /api/order/status method: GET parameters: type: object properties: orderId: type: string description: 订单编号 required: - orderId - name: createOrder description: 创建一个新订单 endpoint: /api/order/create method: POST parameters: type: object properties: userId: type: string amount: type: number required: - userId - amount这份 yaml 里endpoint指向的就是你现有 Controller 的路径parameters是给模型看的 JSON Schema。模型根据 description 和 schema 决定调不调、怎么传参。改完发布Nacos 会推送到订阅的客户端不需要重启业务服务。4. Spring AI Alibaba 侧MCP Server 声明骨架服务端依赖注意版本对齐Spring AI Alibaba 和 Spring AI 的版本错配是高频坑dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-starter/artifactId version1.0.0-M6.1/version /dependency dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-config/artifactId /dependencyMCP Server 的声明骨架核心是让应用启动时从 Nacos 拉取上面那份mcp.server.tools配置并注册成可被发现的 MCP 服务Configuration RefreshScope public class McpServerConfig { Value(${mcp.server.name}) private String serverName; Value(${mcp.server.version}) private String version; Bean public McpServerDescriptor mcpServerDescriptor( NacosMcpToolLoader toolLoader) { ListMcpToolDefinition tools toolLoader.loadTools(); return McpServerDescriptor.builder() .name(serverName) .version(version) .tools(tools) .build(); } }启动参数里显式打开 MCP 注册开关并指定从哪个 dataId 读工具定义spring: ai: alibaba: mcp: enabled: true registry: type: nacos server-addr: 127.0.0.1:8848 tool-config-data-id: order-service-mcp.yaml tool-config-group: DEFAULT_GROUP启动命令带上 profile 和必要环境变量java -jar order-service.jar \ --spring.profiles.activeprod \ --spring.cloud.nacos.discovery.server-addr127.0.0.1:8848 \ --spring.ai.alibaba.mcp.enabledtrue到这里你的存量服务在启动时就会把自己的 MCP 工具清单注册进 NACOS3.0 的 MCP Registry。业务代码一行没改。5. 验证工具列表拉取与一次真实调用先验证注册是否成功。NACOS3.0 控制台里进「MCP 管理」应该能看到order-service这个 MCP Server点进去能看到queryOrderStatus和createOrder两个 Tool 及其 schema。如果列表为空八成是tool-config-data-id写错或者命名空间不匹配。再用接口拉一次工具列表确认数据面能读到curl -X POST http://127.0.0.1:8848/nacos/v3/admin/mcp/list \ -H Content-Type: application/json \ -d {serverName:order-service,namespaceId:public}正常返回类似{ code: 0, data: { serverName: order-service, tools: [ {name: queryOrderStatus, description: 根据订单号查询订单当前状态}, {name: createOrder, description: 创建一个新订单} ] } }最后做一次端到端调用验证。用 MCP Client 发起tool/call或者更直接——在模型对话里让它调这个工具。我用 TaoToken 的模型对话页面测过把 MCP Server 地址配进去后直接问「帮我查一下订单号 A12345 的状态」模型会自己发起tool/call参数orderIdA12345然后你的存量接口被真实调用返回结果再交给模型组织成自然语言。调用链路是这样的用户提问 → 模型判断需要 queryOrderStatus → MCP Client 发 tool/call(orderIdA12345) → NACOS3.0 MCP Registry 路由到 order-service → 转发到 /api/order/status?orderIdA12345 → 存量 Controller 返回 JSON → 结果回传模型 → 生成回答如果这一步能跑通说明「0 代码升级」整条链路是通的。跑不通的话看下一节。6. 本篇常见错排查403 / 鉴权失败NACOS3.0 默认开鉴权客户端配置里必须带username和password且token.secret.key要是 Base64 编码的 32 字节以上。很多人从 2.x 升上来忘了配直接 403。工具列表为空按顺序查三处——tool-config-data-id是否和 Nacos 里的 dataId 完全一致含后缀、namespace和group是否和服务注册时一致、yaml 里mcp.server.tools层级有没有写错。我踩过的坑是 dataId 少写了.yaml后缀排查了半小时。tool/call 报参数校验失败检查parameters里的 JSON Schema 和实际 Controller 的入参类型是否对得上。模型是按 schema 生成参数的schema 写type: string但接口要Long就会在反序列化时炸。改了配置不生效确认类上有RefreshScope且 Nacos 配置的file-extension和实际文件格式一致。MCP 工具定义走的是动态推送不生效通常是订阅没建立。模型侧连不上回到第 2 节先单独验证模型通道能不能通。如果模型对话本身就不通MCP 调用验证无从谈起。这一步用 TaoToken 的模型对话页面单独测一次最快排除掉模型通道问题后再看 MCP 链路。版本冲突Spring AI Alibaba 和 Spring AI 的版本必须按官方兼容矩阵对齐NoSuchMethodError基本都是这个原因。锁定版本别让 Maven 自动仲裁。整条链路跑通后你新增一个工具只需要在 Nacos 里加一段 yaml业务代码依然不动。这才是「0 代码」真正的价值——不是省了第一次的配置而是让后续每次扩展都变成配置操作。