Spring AI 1.x 系列【44】流式 HTTP 类型 MCP 服务端接入 TaoToken 配置实战

发布时间:2026/9/28 19:35:17
Spring AI 1.x 系列【44】流式 HTTP 类型 MCP 服务端接入 TaoToken 配置实战 1. 为什么要在 Spring AI 里折腾 Streamable HTTP 类型的 MCP 服务端如果你正在用 Spring AI 1.x 做智能体或者工具调用相关的服务大概率已经听过 MCPModel Context Protocol这个词。简单说MCP 就是一套让「模型」和「外部工具/资源」之间用统一协议对话的规范。以前我们写工具调用每个模型厂商的格式都不一样换一个模型就得改一遍代码有了 MCP工具端只要按协议暴露能力客户端按协议调用模型侧换谁都能接。而 Streamable HTTP 是 MCP 协议在 2025-03-26 版本里正式引入的传输方式它取代了早期的 SSE 传输。它最大的特点是MCP 服务端可以作为一个独立的 HTTP 进程跑起来客户端通过 POST/GET 请求跟它交互需要推送多条消息时再走 SSE 流式通道。这意味着你可以把「工具服务」和「模型调用」拆成两个独立部署的单元服务端统一管理工具、资源、提示词客户端只管连上来用。这篇要解决的问题很具体在 Spring AI 1.x 里把 MCP 服务端配成 Streamable HTTP 类型同时让服务端里所有需要调用大模型的地方统一走 TaoToken 的 Key/API 通道。适合谁适合那些不想在每个业务模块里散落一堆模型 Key、希望服务端集中管理模型调用出口的开发者。我会给出可复制的application.yml、MCP 服务端骨架、启动日志以及怎么验证流式响应真的通了。2. 前置准备TaoToken 通道与依赖选型在动手写配置之前先把两件事定下来模型调用通道用谁以及 MCP 服务端用哪个 starter。模型调用通道这块我选的是 TaoToken。它的定位是统一的模型 API 入口你拿到一个 Key就能在服务端统一配置模型调用不用在代码里到处硬编码不同厂商的地址和密钥。对 MCP 服务端这种「工具里可能还要调模型」的场景特别合适——工具执行逻辑里如果需要模型补全直接复用同一套通道配置就行。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end API 入口是 https://taotoken.net/api 注意 API 地址后面不加任何参数。依赖选型上Spring AI 1.x 提供了两个 Streamable HTTP 的 starterstarter底层适用场景spring-ai-starter-mcp-server-webmvcSpring MVC传统阻塞式团队熟悉 MVC 的优先spring-ai-starter-mcp-server-webfluxWebFlux响应式、非阻塞、连接数高的场景两者能力基本对齐都支持工具、资源、提示词、补全、日志、进度、心跳、根路径变更。区别只在底层线程模型。我下面用 WebMVC 版本演示因为大多数 Spring Boot 项目本来就是 MVC 栈迁移成本最低如果你项目已经是 WebFlux把依赖名换掉即可配置项完全一样。依赖这样引dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webmvc/artifactId /dependency版本跟随你项目里的 Spring AI BOM1.x 系列即可。引进来之后MCP 服务端的自动配置就生效了接下来全靠application.yml控制行为。3. 可复制的 application.yml 与 MCP 服务端骨架3.1 核心配置protocol 必须设为 STREAMABLE这是最容易踩的坑不显式设置protocol: STREAMABLE服务端不会按 Streamable HTTP 模式启动。默认值不是它。完整配置如下可以直接抄server: port: 8080 spring: ai: mcp: server: enabled: true protocol: STREAMABLE name: streamable-mcp-server version: 1.0.0 type: SYNC instructions: This streamable server provides real-time notifications resource-change-notification: true tool-change-notification: true prompt-change-notification: true capabilities: tool: true resource: true prompt: true completion: true streamable-http: mcp-endpoint: /api/mcp keep-alive-interval: 30s几个关键项解释一下。protocol: STREAMABLE是总开关决定传输类型。type: SYNC表示同步服务端工具处理器用McpSyncServerExchange如果你的工具里有大量阻塞 IO 想改成异步设成ASYNC处理器换成McpAsyncServerExchange。mcp-endpoint: /api/mcp是客户端要连的路径默认是/mcp我改成/api/mcp是为了跟业务接口区分开。keep-alive-interval: 30s是保活心跳默认禁用开了之后服务端会定期给已连接的客户端发心跳注意目前这个保活只对 SSE 那条「Listening for Messages from the Server」连接生效。3.2 模型调用通道配置MCP 服务端本身不强制你配模型但工具执行逻辑里如果要调模型就得有通道。把 TaoToken 的配置单独放一段方便统一管理spring: ai: openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: gpt-4o-mini这里base-url指向 TaoToken 的 API 入口api-key用环境变量注入别写死在 yml 里。模型名按你实际开通的填。这样服务端里任何需要模型补全的地方都走这一条通道换模型只改这一处。3.3 MCP 服务端骨架工具 资源 提示词光有配置不够得有实际暴露的能力。下面是一个最小可用的服务端骨架包含一个工具、一个资源、一个提示词SpringBootApplication public class McpServerApplication { public static void main(String[] args) { SpringApplication.run(McpServerApplication.class, args); } Bean public ToolCallbackProvider weatherTools(WeatherService weatherService) { return MethodToolCallbackProvider.builder() .toolObjects(weatherService) .build(); } } Service public class WeatherService { Tool(description 根据城市名称获取天气信息) public String getWeather(String cityName) { return 城市 cityName 当前晴气温 22 摄氏度; } }Tool注解的方法会被自动扫描并注册成 MCP 工具ToolCallbackProvider这个 Bean 负责把工具对象转成 MCP 声明。自动配置会检测所有ToolCallback、ToolCallback列表、ToolCallbackProvider类型的 Bean合并注册重名工具以首次出现的为准。如果你想关掉自动转换设spring.ai.mcp.server.tool-callback-converterfalse。资源注册用底层 API 长这样Bean public ListMcpServerFeatures.SyncResourceSpecification myResources() { var systemInfoResource new McpSchema.Resource( system://info, system-info, 系统信息, application/json, null); var spec new McpServerFeatures.SyncResourceSpecification( systemInfoResource, (exchange, request) - { String json {\os\:\linux\,\jdk\:\21\}; return new McpSchema.ReadResourceResult( List.of(new McpSchema.TextResourceContents( request.uri(), application/json, json))); }); return List.of(spec); }提示词注册类似用SyncPromptSpecification包一个McpSchema.Prompt加处理器即可。这三类能力默认全开想关哪个就把capabilities下对应项设成false服务端就不再注册和暴露它。4. 启动验证与流式响应确认4.1 看启动日志确认协议生效启动应用后日志里应该能看到 MCP 服务端初始化的痕迹。重点确认两件事协议是 STREAMABLE端点是/api/mcp。如果日志里出现类似Registered MCP tool(s)或者工具数量统计说明工具注册成功。如果没看到任何 MCP 相关日志八成是protocol没设对或者 starter 没引进来。4.2 用 curl 验证端点先确认端点活着。Streamable HTTP 的交互是 POST 请求带 JSON-RPC 消息体curl -i -X POST http://localhost:8080/api/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 1, method: initialize, params: { protocolVersion: 2025-03-26, capabilities: {}, clientInfo: {name: curl-client, version: 1.0} } }注意Accept头必须同时包含application/json和text/event-stream否则服务端可能拒绝。返回里应该能看到服务端的能力声明包括 tools、resources、prompts 这些。4.3 验证流式响应初始化之后调用工具并观察流式返回。用tools/call方法curl -N -X POST http://localhost:8080/api/mcp \ -H Content-Type: application/json \ -H Accept: text/event-stream \ -d { jsonrpc: 2.0, id: 2, method: tools/call, params: { name: getWeather, arguments: {cityName: 杭州} } }-N关闭 curl 缓冲这样你能实时看到 SSE 事件逐条推过来。如果返回里出现event: message加data:的格式并且内容是工具执行结果说明流式通道通了。这一步是判断 Streamable HTTP 是否真正工作的关键——普通 HTTP 一次性返回和 SSE 流式推送行为完全不同。5. 本篇常见错误排查启动报错说找不到 MCP 端点或者 404先检查mcp-endpoint配的路径和你 curl 的路径是否一致。默认是/mcp我改成了/api/mcp如果你抄配置时只抄了一半很容易对不上。另外确认server.port没被其他配置覆盖。客户端连上但工具列表为空检查capabilities.tool是不是被设成了false以及tool-callback-converter是不是被关了。还有一种情况是工具方法没加Tool注解或者ToolCallbackProviderBean 没被扫描到——确认它在SpringBootApplication所在包或子包下。流式响应收不到只有一次性返回检查请求头Accept是否包含text/event-stream。Streamable HTTP 服务端会根据 Accept 头决定用普通 JSON 还是 SSE 返回。另外keep-alive-interval只影响 SSE 长连接的心跳不影响单次请求的流式行为别把它当成流式开关。模型调用报 401 或地址错误检查base-url是不是https://taotoken.net/api注意 API 地址后面不要带多余路径或参数。api-key确认环境变量注入成功可以在启动日志里打印一下配置别打印 Key 本身。保活心跳没生效目前 Streamable HTTP 的保活只对 SSE 那条监听连接生效普通 POST 请求不会触发。如果你期望每个请求都有心跳那是理解偏差不是配置问题。6. 把通道和 Key 管起来服务端跑通之后下一步就是把模型调用的 Key 和通道真正管起来。TaoToken 的控制台可以创建和管理 API Key建议按环境开发/测试/生产分开建 Key别一个 Key 到处用。创建入口在 https://taotoken.net/api-keys 接入文档在 https://taotoken.net/doc 里面有各语言和框架的接入示例Spring AI 的配置方式也能对上。如果你后面要做长期编码任务或者 Agent 类的持续调用可以看下 Coding Plan它更适合高频、长周期的模型调用场景https://taotoken.net/coding-plan 。想先在网页上直接验证模型通不通用模型对话页面最快https://taotoken.net/chat 。控制台总入口是 https://taotoken.net/console 。我自己的习惯是MCP 服务端里所有模型调用都走同一套base-url 环境变量 Key工具逻辑里不出现任何硬编码密钥。这样换模型、换 Key、加环境都只动配置不动代码。流式这块先用 curl 把initialize和tools/call两步跑通再去接客户端能省掉一大半联调时间。