ARTICLE DETAIL

资讯详情

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

Spring AI 番外篇01:MCP Streamable HTTP 模式接入 TaoToken 统一 Key 配置实战

Spring AI 番外篇01:MCP Streamable HTTP 模式接入 TaoToken 统一 Key 配置实战 1. 为什么要在 Spring AI 里折腾 MCP Streamable HTTP如果你正在用 Spring AI 做 MCP 服务端大概率踩过这样的坑1.0.x 版本只支持 SSE 协议客户端一断线就得重建连接上下文全丢用户问了一半的问题得从头再来。更难受的是每个客户端都要挂一条 SSE 长连接并发一上来服务器 TCP 连接数直接飙红横向扩容也麻烦。MCP 规范后来把默认传输方式切到了 Streamable HTTPSpring AI 从 1.1.0-M1 开始跟进到 1.1.0-M3 已经能比较顺手地用了。它保留了 SSE 的流式推送能力同时把通信整合到统一端点支持会话状态管理和断线重连服务器不用再为每个客户端维持长连接。对用 WebFlux 或 WebMVC 的 Java 开发者来说这意味着你可以用熟悉的 Spring Boot 那套东西把 MCP 服务端和客户端都跑起来。这篇是番外篇重点不在讲原理而是把 MCP Streamable HTTP 模式接入 TaoToken 统一 Key 的完整配置走一遍。我会给出 application.yml、config.toml、settings.json 三份骨架再附上启动验证和请求连通性检查的步骤。适合已经写过 Spring Boot、想快速把 MCP 服务端到客户端联调跑通的人。TaoToken 在这里的角色是统一 API 通道你只需要维护一个 Key就能让 MCP 客户端背后的模型调用走同一条路省得在多个平台之间来回切配置。2. TaoToken 前置准备统一 Key 与 API 通道在动手改代码之前先把 TaoToken 这边的准备工作做完。它的官网是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 注意 API 地址不带 UTM 参数配置里填这个就行。你需要拿到一个统一 Key。登录后进控制台在 API Keys 页面创建一个复制出来先存好。这个 Key 后面会同时出现在 MCP 客户端的 settings.json 和 Spring AI 的 application.yml 里所以别弄丢。如果你还没建过 Key直接去 https://taotoken.net/console/api-keys 操作创建时给个容易认的名字比如 spring-ai-mcp。TaoToken 的定位是统一 API 通道不是让你替换掉 Spring AI 或 MCP 本身而是把模型调用的出口收敛到一处。MCP 服务端负责暴露工具MCP 客户端负责调用工具并驱动模型模型这一层的请求就走 TaoToken。这样你在 config.toml 和 settings.json 里配一次后面换模型或者加通道都不用改业务代码。有一点要提醒TaoToken 不是编辑器插件也不是 MCP 直连生产库的工具。它只处理 API 通道这一层你的数据库连接、业务逻辑还是在自己代码里。配置的时候把 Key 放在环境变量或本地配置文件里别硬编码进 Git 仓库。3. 可复制配置application.yml、config.toml、settings.json 三件套先看 MCP 服务端。父项目里引入 spring-ai-bom版本用 1.1.0-M3这样依赖版本统一不会出现 starter 和核心包对不上的情况。!-- extra01/pom.xml -- dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version1.1.0-M3/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement服务端模块 extra-mcp-server 引入 WebMVC 版的 MCP starter。如果你用 WebFlux把 artifactId 换成 spring-ai-starter-mcp-server-webflux 即可配置项基本一致。!-- extra01/extra-mcp-server/pom.xml -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webmvc/artifactId /dependency写一个简单的 Service用 Tool 注解暴露工具。这里模拟通过城市名字获取温度实际项目里换成你的业务方法就行。// extra01/extra-mcp-server/src/main/java/com/kaifamiao/extra01/service/WeatherService.java Service public class WeatherService { Tool(description 通过城市名字获取温度) public String getWeatherByCity(ToolParam(description 城市名称) String cityName) { return cityName 今天的温度是 (new java.util.Random().nextInt(9) 1) * 6; } }注册工具的时候加 Primary避免多个 ToolCallbackProvider 冲突。// extra01/extra-mcp-server/src/main/java/com/kaifamiao/extra01/configuration/McpServerConfig.java Configuration public class McpServerConfig { Bean Primary public ToolCallbackProvider toolProvider(WeatherService weatherService) { return MethodToolCallbackProvider.builder().toolObjects(weatherService).build(); } }服务端的 application.yml 是核心。protocol 填 streamabletype 填 syncstreamable-http 下面指定 mcp-endpoint 和 keep-alive-interval。端口我用了 8081你按自己环境改。# extra01/extra-mcp-server/src/main/resources/application.yml spring: ai: mcp: server: name: streamable-weather-server version: 0.0.1 protocol: streamable type: sync streamable-http: mcp-endpoint: /mcp keep-alive-interval: 30s server: port: 8081在 IDEA 里敲 protocol 的时候如果补全能提示 streamable说明依赖版本对了。1.0.0 版本是没有这个选项的这也是判断版本是否升级成功的一个小技巧。客户端这边extra-mcp-client 引入 dashscope starter 和 mcp-client starter。dashscope 负责模型调用mcp-client 负责连服务端。!-- extra01/extra-mcp-client/pom.xml -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-starter-dashscope/artifactId /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-client/artifactId /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency客户端的 application.yml 里mcp.client.streamable-http.connections 下面配服务端 URL。这里我把 dashscope 的 api-key 用环境变量占位实际值从 TaoToken 那边拿。# extra01/extra-mcp-client/src/main/resources/application.yml spring: ai: dashscope: api-key: ${TAOTOKEN_API_KEY} chat: options: model: qwen-plus temperature: 0.7 mcp: client: streamable-http: connections: server1: url: http://127.0.0.1:8081/mcp如果你用的是 Claude Code 或类似客户端settings.json 的骨架长这样。把 base_url 指向 TaoToken 的 API 入口api_key 填你的统一 Key。{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: 你的统一Key }, mcpServers: { streamable-weather: { url: http://127.0.0.1:8081/mcp } } }config.toml 这边如果你用支持 TOML 配置的客户端结构类似重点是 base_url 和 api_key 两项。# config.toml [api] base_url https://taotoken.net/api api_key 你的统一Key [mcp.servers.streamable-weather] url http://127.0.0.1:8081/mcp三份配置里TaoToken 的 Key 只出现一次其他客户端都引用同一个值。这就是统一 Key 的好处改一处全生效。4. 启动验证与请求连通性检查配置写完先启动服务端。在 extra-mcp-server 目录下执行mvn spring-boot:run看到日志里出现 MCP server started on /mcp 之类的字样说明服务端起来了。如果端口被占用改 application.yml 里的 server.port 再试。服务端起来后先用 curl 探一下端点是否可达。Streamable HTTP 模式下MCP 端点接受 POST 请求返回可能是 JSON 也可能是 SSE 流。curl -i -X POST http://127.0.0.1:8081/mcp \ -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}}}如果返回 200 并且 body 里有 serverInfo 或 capabilities 字段说明服务端正常。返回 404 的话检查 mcp-endpoint 是不是 /mcp返回 415 检查 Content-Type 头。接着跑客户端的测试用例。这个测试注入 ChatClient.Builder 和 SyncMcpToolCallbackProvider让模型带着 MCP 工具回调去回答天气问题。// extra01/extra-mcp-client/src/test/java/com/kaifamiao/extra01/StreamableWeatherServerTest.java SpringBootTest Slf4j public class StreamableWeatherServerTest { Test void testMcpServer(Autowired ChatClient.Builder chatClientBuilder, Autowired SyncMcpToolCallbackProvider syncMcpToolCallbackProvider) { ChatClient chatClient chatClientBuilder.build(); String response chatClient.prompt() .toolCallbacks(syncMcpToolCallbackProvider) .user(北京现在的天气如何) .call() .content(); log.info(response: {}, response); } }运行测试前确保环境变量 TAOTOKEN_API_KEY 已经设置。Linux 或 macOS 下export TAOTOKEN_API_KEY你的统一Key mvn test -DtestStreamableWeatherServerTest控制台如果输出类似「北京今天的温度是36℃。请注意防暑降温」的内容说明整条链路通了客户端连上 MCP 服务端模型通过 TaoToken 通道调用工具回调正常执行。如果输出里没有温度数字可能是模型没触发工具调用检查 Tool 的 description 是否清晰或者把 temperature 调低一点让模型更倾向走工具。想单独验证模型通道是否通可以打开模型对话页面发一条简单消息确认 Key 和 base_url 没问题。这一步能帮你把「模型通道问题」和「MCP 连接问题」分开排查。5. 本篇常见错排查启动报 protocol 不识别。多半是 spring-ai-bom 版本没到 1.1.0-M1 以上。检查父项目 dependencyManagement 里的版本号1.0.x 是不支持 streamable 的。改完记得 mvn clean让依赖重新解析。客户端连不上服务端报 Connection refused。先确认服务端端口和 URL 里的端口一致再看服务端是否真的启动完成。Streamable HTTP 模式下客户端连的是 /mcp 这个统一端点不是以前的 /sse。如果你从旧配置迁移过来把 url 里的 /sse 改成 /mcp。工具回调不触发模型直接编答案。这是最常见的问题。检查三点Service 类是否被 Spring 扫描到McpServerConfig 里的 Primary 是否加上Tool 的 description 是否写清楚。description 太模糊模型不知道什么时候该调这个工具。另外客户端测试里要确保 .toolCallbacks(syncMcpToolCallbackProvider) 这行没漏。TaoToken Key 报 401 或 403。先确认 Key 是从控制台复制的完整字符串没有多余空格。再确认 base_url 填的是 https://taotoken.net/api 不要带 UTM 参数。如果用的是环境变量检查 export 是否在当前 shell 生效IDEA 里跑测试的话要在 Run Configuration 里单独配环境变量。keep-alive-interval 设了但连接还是断。Streamable HTTP 的保活机制依赖服务端和客户端都支持。如果中间有反向代理检查代理的超时时间是否小于 keep-alive-interval。一般把 keep-alive-interval 设成 30s代理超时设成 60s 以上比较稳。WebFlux 和 WebMVC 混用导致冲突。服务端和客户端可以用不同的编程模型但同一个模块里别同时引 web 和 webflux starter。如果你服务端用 WebMVC客户端也用 WebMVC那就都引 spring-boot-starter-web。要换 WebFlux 的话把 starter 换成对应的 webflux 版本配置项不用大改。6. 接入之后怎么继续往下走把上面这套跑通之后你手里就有了一个能用的 MCP Streamable HTTP 服务端和客户端模型调用统一走 TaoToken。接下来可以做的事把 WeatherService 换成你真实的业务工具比如查订单、查库存、调内部 API在客户端加更多 MCP 连接让一个模型同时挂多个工具服务或者把配置抽到配置中心让 Key 和 URL 支持动态刷新。如果你在排障阶段卡住了优先去看接入文档里面有针对 Streamable HTTP 的端点说明和错误码解释。验证模型通道是否正常直接开模型对话发一条消息最快。要是你打算长期跑编码类或 Agent 类任务Coding Plan 那边有更完整的通道配置建议适合把 MCP 和日常开发流串起来。我自己的习惯是每加一个新 MCP 工具先用 curl 打一次 initialize确认服务端活着再跑客户端测试。这样出问题的时候能立刻判断是服务端没起来还是客户端配置错了省得两边瞎猜。
返回列表