
1. 为什么 MCP Server 要自动注册到 Nacos如果你正在用 SpringAI 写 MCP Server大概率会遇到一个很现实的问题服务写完了工具方法也暴露了但 AI Agent 那边怎么知道你这个 Server 存在、有哪些 Tool、参数长什么样手动维护一份服务清单改一次工具描述就得同步一次时间一长必然对不上。MCP Server 自动注册 Nacos 解决的正是这件事。它让 MCP Server 在启动时把自己的服务信息、工具元数据、版本信息一并写进 Nacos后续 Agent 通过 Spring AI Alibaba 或 Nacos MCP Router 就能直接发现和调用。适合谁适合正在做本地微服务联调、又想让 AI Agent 动态发现工具能力的后端同学。我这次的目标很明确一个 Spring Boot 3.4.5 JDK 17 的 MCP Server启动后自动出现在 Nacos 3.1.0 的 MCP 列表里工具描述支持热更新Tools 能运行时开关。下面把配置骨架、验证动作和踩坑路径完整走一遍。2. TaoToken 前置统一 Key 接入 MCP 调用链在讲 Nacos 注册之前先把模型调用这一环理顺。MCP Server 本身负责暴露工具但真正驱动 Agent 去调用工具的模型请求需要一个稳定的入口。我这边统一用 TaoToken 来做模型接入好处是 Key 管理集中切换模型不用改一堆配置。TaoToken 的定位是统一模型接入层官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。你需要在控制台创建一个 API Key然后把它配到 SpringAI 的模型客户端里。具体操作路径先打开控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 在 API Keys 页面生成一个 Key页面地址是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。生成后复制保存后面 application.yml 里会用到。如果你只是想先验证模型对话是否通可以直接用模型对话页面 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 发一条消息测试。长期做编码和 Agent 联调的话建议看下 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 额度策略更适合高频调用。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 配置细节以文档为准。注意TaoToken 是模型接入层不是 Nacos 的替代品。Nacos 负责服务注册发现TaoToken 负责模型请求入口两者职责分开别混在一起配。3. 可复制配置application.yml 与依赖骨架先把依赖补齐。MCP Server 的 WebMVC 启动器和 Nacos 注册器是两个核心包版本要对齐。dependencies !-- SpringAI MCP Server WebMVC 依赖包 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webmvc/artifactId version1.0.0/version /dependency !-- SpringAI Alibaba MCP Registry 依赖包 -- dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-starter-mcp-registry/artifactId version1.0.0.4/version /dependency /dependencies基础环境我实测下来是 JDK 17 Spring Boot 3.4.5 Nacos 3.1.0版本不匹配容易出现注册器加载失败。接着是 application.yml 的完整骨架这段可以直接抄改掉 namespace、server-addr 和账号密码即可。spring: application: name: mcp-server-nacos3 ai: mcp: server: name: mcp-server-001 version: 1.0.0 type: ASYNC instructions: This server provides time information tools and resources sse-message-endpoint: /mcp/messages capabilities: tool: true resource: true prompt: true completion: true alibaba: mcp: nacos: namespace: c5a2bef4-1598-4dc9-85f1-462f4f0b3cc1 server-addr: 127.0.0.1:8848 username: nacos password: 123456 register: enabled: true service-name: mcp-server-001 service-group: DEFAULT_GROUP server: port: 10001几个参数说明一下。type: ASYNC对应异步工具调用模式如果你用的是同步工具可以改成 SYNC。sse-message-endpoint是 SSE 消息端点Agent 通过它接收工具执行结果。register.enabled: true是自动注册的总开关关掉它就不会往 Nacos 写任何东西。namespace一定要填对填成 public 命名空间的 ID 或者留空都可能导致注册到错误位置。提示Nacos 3.x 的 namespace 建议用命名空间 ID 而不是名称控制台里复制 ID 更稳妥。4. 服务定义与工具暴露代码配置写完后需要一个具体的工具服务。这里用获取城市时间做例子重点是Tool和ToolParam注解它们决定了注册到 Nacos 里的工具描述和参数定义。Slf4j Service public class TimeService { Tool(description Get the time of a specified city.) public String getCityTime( ToolParam(description Time zone id, such as Asia/Shanghai) String zoneId) { log.info(The current time zone is {}, zoneId); return String.format(The current time zone is %s and the current time is %s, zoneId, ZonedDateTime.now(ZoneId.of(zoneId)) .format(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss z))); } }工具方法写好后要通过ToolCallbackProvider暴露出去否则 MCP Server 不会把它注册成可调用工具。Bean public ToolCallbackProvider timeToolCallbackProvider(TimeService timeService) { return MethodToolCallbackProvider.builder() .toolObjects(timeService) .build(); }这里有个容易忽略的点Tool的 description 会同步到 Nacos 的 mcp-tools.json 里Agent 就是靠这段描述判断什么时候调用这个工具。描述写得太模糊Agent 可能永远不选它。参数描述同理ToolParam里的说明会出现在工具元数据中。5. 验证请求Nacos 控制台与接口确认启动服务后先看日志有没有注册成功的输出。正常情况下会看到向 Nacos 发送注册请求的记录端口是 8848。然后打开 Nacos 控制台做两个验证动作。第一个动作进入 MCP 管理 - MCP 列表应该能看到mcp-server-001这条记录服务分组是 DEFAULT_GROUP状态是上线。点进去能看到工具列表里面应该有getCityTime。第二个动作进入配置管理 - 配置列表搜索mcp-server应该能看到三个配置文件mcp-server.json、mcp-versions.json、mcp-tools.json。其中mcp-tools.json里包含工具的名称、描述、参数 schema这就是 Agent 发现工具的依据。如果你想用接口方式确认可以直接调 Nacos 的 OpenAPI 查询实例列表curl -X GET http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceNamemcp-server-001groupNameDEFAULT_GROUPnamespaceIdc5a2bef4-1598-4dc9-85f1-462f4f0b3cc1返回结果里hosts数组不为空说明服务实例已经注册成功。再确认工具元数据curl -X GET http://127.0.0.1:8848/nacos/v1/cs/configs?dataIdmcp-tools.jsongroupNameDEFAULT_GROUPtenantc5a2bef4-1598-4dc9-85f1-462f4f0b3cc1返回的 JSON 里能看到getCityTime的完整定义。到这一步注册链路就算通了。接下来 Agent 侧通过 Spring AI Alibaba 或 Nacos MCP Router 就能发现这个 Server 并调用工具。6. 本篇常见错排查报错一启动后 Nacos 里什么都没有。先检查register.enabled是不是 true再看 namespace 是否填错。很多人把 namespace 填成命名空间名称而不是 IDNacos 3.x 对这块校验比较严。另外确认spring-ai-alibaba-starter-mcp-registry依赖真的被加载了可以用mvn dependency:tree看一下。报错二注册上了但工具列表是空的。大概率是ToolCallbackProviderBean 没生效或者Tool注解所在类没有被 Spring 扫描到。检查MethodToolCallbackProvider.builder().toolObjects()里传的对象是不是 Spring 管理的 Bean。如果工具方法是 private 的也不会被识别。报错三Nacos 连接超时或认证失败。确认server-addr格式是IP:端口不要带 http 前缀。用户名密码如果 Nacos 开了鉴权就必须填对没开鉴权可以留空但建议还是填上。本地开发常见的是 Nacos 没启动或者端口被占用。报错四工具描述改了但 Nacos 里没更新。描述热更新依赖注册器的同步机制如果没生效先确认是不是改了代码但没重新编译。运行时热更新指的是通过 Nacos 配置中心改 mcp-tools.json 后 Agent 侧能感知不是改 Java 注解不重启就生效。报错五SSE 端点 404。检查sse-message-endpoint配置和实际请求路径是否一致WebMVC 模式下端点注册依赖正确的 starter。如果用的是 WebFlux要换成对应的 starter 包。7. 继续接入与调用验证注册通了之后下一步是让 Agent 真正调用起来。你可以先用模型对话页面发一条请求确认模型侧能正常响应地址是 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。然后在 Spring AI Alibaba 侧配置 MCP Client 去发现 Nacos 里的 Server或者用 Nacos MCP Router 做路由转发。接入过程中如果遇到 Key 或模型配置问题直接查接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有针对 SpringAI 的配置示例。需要重新生成 Key 就去 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。长期跑编码和 Agent 任务的话Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 的额度更划算。最后提醒一句Nacos 里的 mcp-tools.json 是 Agent 发现工具的唯一依据工具描述和参数定义写清楚比多写几个工具更重要。我踩过的坑是描述太笼统Agent 死活不调用改成具体场景描述后立刻就通了。