1. 从单端点到多端点MCP 服务在 Spring Boot 里的真实困境如果你正在用 Java 做 MCPModel Context Protocol服务端大概率会遇到这样一个场景一开始只做了一个/sse端点所有客户端都往这里连工具也全塞在一个 McpSyncServer 里。跑通 Demo 没问题但一旦业务方说“通知服务走一套工具、聊天服务走另一套工具、报表服务再单独隔离”代码就开始失控了。MCP 本身是给大模型提供工具、资源、提示的协议SSE 负责服务器到客户端的单向推送消息端点负责客户端到服务器的请求上行。两者配合客户端先通过 SSE 建立长连接“收听”再通过消息端点“打电话”下发指令。问题在于当多个业务场景需要独立会话池、独立工具集、独立鉴权时单端点架构根本撑不住。我试过把所有工具注册到一个 McpSyncServer 里结果 A 场景的客户端能看到 B 场景的工具列表会话串扰、鉴权配置散落在各个 Controller 里改一个场景要动三处代码。更麻烦的是每个场景对接的大模型客户端可能来自不同厂商API Key 管理完全失控。这篇要解决的就是这件事用 Spring Boot HttpServletSseServerTransport实现多 SSE 端点监听每个端点独立会话、独立工具同时把大模型调用通道统一收敛到 TaoToken 的 API 通道上Key 只配一次所有场景共用。适合已经跑通单端点 MCP、准备做工程化落地的 Java 后端。2. TaoToken 前置统一 Key 与 API 通道为什么必要多端点架构里每个 MCP 服务器最终都要调用大模型。如果每个场景各自配一套 Key、各自写一套 HTTP 客户端配置会迅速膨胀成灾难。TaoToken 在这里扮演的角色是统一的大模型 API 通道你只需要在控制台创建一个 API Key所有 MCP 服务器通过同一个 base URL 和同一个 Key 发起请求鉴权逻辑收敛到一处。具体来说TaoToken 提供兼容 OpenAI 风格的接口base URL 是https://taotoken.net/api模型对话、编码类请求都走这个入口。对 MCP 服务端而言这意味着工具回调函数里调用大模型时不需要关心底层是哪家模型只认一个 endpoint 和一个 Key。你需要提前准备两样东西第一一个可用的 API Key。到控制台创建路径是https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content创建后复制保存后面配置里会用到。第二确认你要用的模型名称。可以在模型对话页面先手动测一次地址是https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content选一个模型发一条消息确认通道正常。注意API Key 不要硬编码进代码或提交到 Git。本文示例用环境变量注入生产环境建议配合配置中心。如果你后续要做长期编码类 Agent 或高频工具调用可以了解 Coding Plan地址是https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content这里不展开。3. 可复制配置application.yml 与多端点注册骨架先看依赖。MCP Java SDK 的核心包是mcp-coreServlet 传输实现也在其中。Spring Boot 用 3.x因为HttpServletSseServerTransport依赖 Servlet 6.0 的异步能力。dependency groupIdio.modelcontextprotocol.sdk/groupId artifactIdmcp-core/artifactId version0.10.0/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependencyapplication.yml里把 TaoToken 通道和场景端点配置抽出来避免硬编码taotoken: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} model: gpt-4o-mini timeout: 30000 mcp: scenes: - name: notifications sse-path: /sse/notifications/* message-endpoint: /mcp/notifications/message - name: chat sse-path: /sse/chat/* message-endpoint: /mcp/chat/message - name: report sse-path: /sse/report/* message-endpoint: /mcp/report/message这里的关键设计是场景列表从配置读取而不是写死在Bean方法里。每个场景对应一个HttpServletSseServerTransport实例和一个ServletRegistrationBean两者通过 Bean 名称配对。配置类骨架如下用ConfigurationProperties绑定场景列表再动态注册Configuration EnableWebMvc public class McpServerConfig implements WebMvcConfigurer { Bean ConfigurationProperties(prefix mcp) public McpSceneProperties mcpSceneProperties() { return new McpSceneProperties(); } Bean public ObjectMapper objectMapper() { return new ObjectMapper(); } Bean public ListServletRegistrationBeanHttpServletSseServerTransport mcpServletBeans( McpSceneProperties props, ObjectMapper mapper) { ListServletRegistrationBeanHttpServletSseServerTransport beans new ArrayList(); for (McpSceneProperties.Scene scene : props.getScenes()) { HttpServletSseServerTransport transport new HttpServletSseServerTransport(mapper, scene.getMessageEndpoint()); ServletRegistrationBeanHttpServletSseServerTransport bean new ServletRegistrationBean(transport, scene.getSsePath()); bean.setName(scene.getName() SseServlet); beans.add(bean); } return beans; } }McpSceneProperties就是一个普通的 POJO字段ListScene scenesScene 里放name、ssePath、messageEndpoint。这样新增场景只改 YAML不动 Java 代码。每个HttpServletSseServerTransport实例内部维护独立的会话池。客户端连/sse/notifications时请求由 notifications 对应的 transport 处理会话存在它自己的池子里连/sse/chat则完全隔离。消息端点同理POST /mcp/notifications/message只会路由到 notifications 实例。4. 验证请求curl 测多端点连通与 TaoToken 鉴权生效配置写完启动服务用 curl 验证。先测 SSE 端点是否正常建立长连接curl -N -H Accept: text/event-stream http://localhost:8080/sse/notifications正常返回会看到event: endpoint和data: /mcp/notifications/message这样的初始事件连接保持不关闭。-N参数关闭 curl 缓冲方便实时看事件流。再开一个终端测 chat 端点curl -N -H Accept: text/event-stream http://localhost:8080/sse/chat两个连接同时存在互不干扰说明多端点监听生效。接着验证消息端点。MCP 的消息端点接收 JSON-RPC 格式请求先发一个initializecurl -X POST http://localhost:8080/mcp/notifications/message \ -H Content-Type: application/json \ -d {jsonrpc:2.0,id:1,method:initialize,params:{protocolVersion:2024-11-05,capabilities:{},clientInfo:{name:curl-test,version:1.0}}}返回里应该包含serverInfo和capabilities。如果返回 404说明消息端点路径和 transport 构造时传的不一致返回 500 则看日志里 transport 的异常栈。最后验证 TaoToken 鉴权。在工具回调里调用大模型时请求头带Authorization: Bearer ${TAOTOKEN_API_KEY}。你可以单独用 curl 测通道curl -X POST https://taotoken.net/api/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d {model:gpt-4o-mini,messages:[{role:user,content:ping}]}返回正常 completion 说明 Key 和通道都没问题。把这个调用封装进 MCP 工具的处理函数里所有场景共用同一个WebClient或RestTemplateBeanKey 从环境变量读。5. 本篇常见错排查错误一SSE 连接建立后立刻断开。最常见原因是 Servlet 异步支持没开。检查EnableWebMvc是否加上以及ServletRegistrationBean是否设置了setAsyncSupported(true)。Spring Boot 默认对注册的 Servlet 开启异步但如果你手动new ServletRegistrationBean后没配可能被覆盖。错误二多个端点串会话。如果你把多个场景的 transport 注册到了同一个 URL 前缀或者用了/*通配导致路径重叠Servlet 容器会按注册顺序匹配。确保每个场景的sse-path前缀唯一比如/sse/notifications/*和/sse/chat/*不会冲突但/sse/*和/sse/notifications/*会。错误三消息端点返回 405。HttpServletSseServerTransport的消息端点只接受 POST。如果你用 GET 请求会返回 405。另外确认messageEndpoint路径和客户端从 SSE 初始事件里拿到的路径一致客户端应该用服务端下发的 endpoint而不是自己拼。错误四TaoToken 调用返回 401。检查环境变量TAOTOKEN_API_KEY是否真的注入到进程里。System.getenv在 IDE 里跑和打包后跑结果可能不同。另外确认请求头格式是Bearer加 Key中间一个空格不要多也不要少。错误五动态新增场景后旧连接失效。这是 Servlet 特性决定的ServletRegistrationBean在容器启动后无法动态增删。新增场景必须重启服务。但每个 transport 内部的工具可以在运行时通过McpSyncServer的 API 动态注册配合定时任务或消息队列刷新工具列表不需要重启。提示如果你在排查 SSE 连接问题时看到AsyncContext相关异常优先检查 Tomcat 版本和 Servlet API 版本是否匹配。Spring Boot 3.2 配 Tomcat 10.1 是稳妥组合。6. 接入落地Key 管理与文档入口多端点跑通后下一步是把鉴权配置彻底收敛。所有 MCP 服务器调用大模型时统一走 TaoToken 的 API 通道Key 只在环境变量或配置中心维护一份。这样新增场景时你只需要在 YAML 里加一段不用再碰 Key。创建和管理 Key 的入口在控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI Keys 管理页可以直接生成和吊销https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。接入细节和参数说明看文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。如果你用的是 Claude Code 或 Anthropic 风格的客户端对应入口在https://taotoken.net/claudecode-anthropic?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。实测下来把多端点注册和统一 Key 这两件事拆开处理后新增一个业务场景的成本从“改三个类 重启 配 Key”降到“改一段 YAML 重启”。工具的动态刷新则完全不用重启定时任务拉一次数据库重建SyncToolSpecification注册进去就行。唯一要记住的坑是Servlet 注册是启动期行为端点本身没法热加这是 Servlet 规范的限制不是 MCP 的问题。
企业数字化 ERP 产品动态
相关推荐
How to GraphQL 实战:React + urql 实现邮箱密码登录与请求认证 【免费下载链接】howtographql The Fullstack Tutorial for GraphQL 项目地址: https://gitcode.com/gh_mirrors/ho/howtographql 点击查看 免费下载 本文是 How to GraphQL 教程(前端 urql 技术栈)中“认证”章节的完整实战指南,… · 2026/9/26 15:44:31
使用 AWS SDK for Kotlin 操作 AWS Step Functions:示例场景与实战指南 示例工程教程后端 【免费下载链接】aws-doc-sdk-examples Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below. 项目地… · 2026/9/26 15:44:19
MQTT协议深度解析:从发布订阅到QoS的工业物联网实战指南 MQTT这三个字母,但凡做过物联网项目的人都不会陌生。但我在带团队和做技术评审的这些年里,发现一个很普遍的现象:很多人能照着Demo把设备连上、把消息发出去,可一旦遇到连接频繁断开、消息重复、订阅收不到、QoS选了2反而更慢这类… · 2026/9/26 16:24:00
Claw Agent 日志分析工作原理详解:基于 WorkBuddy 的配置与验证 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 16:24:00
不用写代码!OpenClaw 配 TaoToken 一键自动盯盘、抓热点、筛牛股 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 16:23:54
AI领域技术进展速览:从模型更新到硬件竞争,TaoToken统一Key接入配置实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 16:23:48
手写前端Ax调度器:解决请求竞态与并发控制的完整实践 做前端这几年,我踩过一个特别典型的坑:用户在一个页面上快速切换筛选条件,A条件下拉的数据还没回来,B条件的请求先到了,等A的结果返回来,直接覆盖了页面,界面上一片错乱。接口全部正常ÿ… · 2026/9/26 16:23:41
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46