人工智能(八)- Spring AI 开发 MCP Server(Streamable HTTP)完整开发与测试:把 endpoint 改到 TaoToken
1. 从 stdio 到 Streamable HTTP为什么要把 MCP Server 的 endpoint 改到 TaoToken如果你已经用 Spring AI 写过 stdio 版本的 MCP Server大概率会遇到一个尴尬本地 IDE 能跑但一旦想让远程客户端、团队其他成员或者 CI 环境调用stdio 的进程间通信模型就完全不够用了。stdio 的本质是 MCP Client 和 MCP Server 跑在同一台主机上靠标准输入输出做 JSON-RPC 2.0 的消息交换适合本地工具接入但没法跨网络。Streamable HTTP 就是来解决这个问题的。它基于 HTTP 协议MCP Client 可以远程调用 MCP Server 暴露的 endpoint服务端通过流式响应把工具调用结果推回来。相比早期的 SSE 方案Streamable HTTP 的通信模型更统一新版本的客户端和服务端都更偏向它。Spring AI 从 1.1.x 开始对 Streamable HTTP 的支持已经比较完整依赖是spring-ai-starter-mcp-server-webmvc底层走 Servlet 栈。那为什么要把 endpoint 改到 TaoToken因为 MCP Server 本身只负责暴露工具真正要验证工具调用链路是否正常需要一个能发起模型请求的客户端。TaoToken 提供统一的 API endpoint兼容主流模型调用格式你可以把 MCP Client 的模型请求指向 TaoToken让模型来决定调用哪个工具、传什么参数然后观察 Streamable HTTP 的流式返回是否正常。这样整条链路——模型决策、工具调用、流式响应——就都能在真实请求下验证。这篇面向的是已经了解 MCP 基本概念、想动手把 Spring AI MCP Server 跑起来并完成端到端测试的 Java 开发者。我会从依赖引入开始给出可复制的application.yml、工具注册代码、MCP 客户端配置片段然后演示把 endpoint 改到 TaoToken 后用 curl 和单元测试验证工具调用与流式返回。整个过程我试过几轮踩过的坑会放在排障章节里。2. TaoToken 前置准备API Key、Base URL 与模型 ID 三件套在写代码之前先把 TaoToken 这边的接入信息准备好。不管你是用 Cline、Claude Code 还是自己写的 MCP Client核心就是三件套Base URL、API Key、Model ID。这三个东西缺一个请求就会在鉴权或路由阶段挂掉。Base URL 用https://taotoken.net/api注意这个地址不带任何查询参数直接作为 API 根路径。API Key 需要到控制台创建路径是 console 页面下的 api-keys 管理。创建的时候建议按项目命名比如spring-ai-mcp-demo方便后面排查是哪个 key 在调用。Model ID 根据你要用的模型填比如claude-sonnet-4-20250514这类标识具体以模型列表页为准。如果你用的是 Claude Code 这类工具配置方式会略有不同。Claude Code 的接入文档在 doc 页面有详细说明核心是把 Base URL 指向 TaoToken 的 API 地址然后填入 Key。对于 Spring AI 的 MCP Client我们是在application.yml里配置spring.ai.openai.base-url和spring.ai.openai.api-key模型名通过spring.ai.openai.chat.options.model指定。这里有个容易混淆的点MCP Server 的 endpoint 和模型 API 的 endpoint 是两个不同的东西。MCP Server 暴露的是/mcp这个路径供 MCP Client 调用工具而 TaoToken 的/api是模型推理接口供 MCP Client 内部的 ChatClient 调用。两者不要搞混。我们在application-http.yml里配置的mcp-endpoint: /mcp是前者TaoToken 的 Base URL 是后者。另外如果你打算长期跑编码类 Agent 任务可以了解下 Coding Plan它针对高频编码场景做了额度优化。单纯验证工具调用的话按量调用模型对话接口就够了。需要先拿到 Key 的话直接去 API Keys 页面创建然后对照接入文档确认参数格式。3. 可复制配置application.yml、工具注册与 MCP 客户端片段这一节给出完整的可复制配置。工程结构是标准的 Spring Boot Maven 项目Java 17Spring Boot 3.4.xSpring AI 1.1.4。pom 里需要引入spring-ai-starter-mcp-server-webmvc来启用 Streamable HTTP 模式同时引入spring-ai-starter-model-openai作为 MCP Client 侧的模型调用依赖。先看application.yml的主配置spring: application: name: java-mcp-server-demo profiles: active: http ai: mcp: server: name: java-mcp-server-demo version: 0.0.1 type: SYNC instructions: | This server provides demo tools for Java MCP development. Use getWeather for city weather lookup and sumNumbers for calculation.然后是application-http.yml这是 Streamable HTTP 模式的核心配置spring: config: activate: on-profile: http main: web-application-type: servlet ai: mcp: server: protocol: STREAMABLE streamable-http: mcp-endpoint: /mcp server: port: 8080注意protocol: STREAMABLE和mcp-endpoint: /mcp这两行前者指定传输协议后者定义 MCP Client 要访问的路径。启动后完整的 endpoint 是http://localhost:8080/mcp。工具类用Tool和ToolParam注解标记Service public class WeatherService { Tool(name getWeather, description 根据城市名称获取天气信息) public String getWeather( ToolParam(description 城市名称, required true) String city) { return 城市: city , 温度: 25°C, 天气: 晴; } Tool(name sumNumbers, description 计算两个数字之和) public String sumNumbers( ToolParam(description 第一个数字) double a, ToolParam(description 第二个数字) double b) { return String.valueOf(a b); } }工具注册配置类把WeatherService里的Tool方法注册为 MCP 工具Configuration public class ToolRegistrationConfiguration { Autowired private WeatherService weatherService; Bean public ToolCallbackProvider toolCallbackProvider() { return MethodToolCallbackProvider.builder() .toolObjects(new Object[]{weatherService}) .build(); } }接下来是 MCP Client 侧的配置把模型请求指向 TaoToken。在application-client.yml里spring: ai: openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: claude-sonnet-4-20250514 temperature: 0.7 mcp: client: streamable-http: connections: demo-server: url: http://localhost:8080/mcp这里base-url指向 TaoToken 的 API 地址api-key从环境变量读取避免硬编码。mcp.client.streamable-http.connections下面配置 MCP Server 的地址demo-server是连接名可以自定义。这样 MCP Client 启动时会自动连接本地 MCP Server拉取工具列表然后在模型请求中把工具定义一起发给 TaoToken。如果你用的是 Cline 或 Claude Code 这类外部客户端配置方式类似核心还是 Base URL、Key、Model ID 三件套加上 MCP Server 的 URL。Claude Code 的配置在 doc 里有说明Cline 的 MCP 配置在 settings 里填http://localhost:8080/mcp即可。4. 验证请求curl 与单元测试检查工具调用和流式返回配置写完之后先启动 MCP Server。用mvn spring-boot:run -Dspring-boot.run.profileshttp启动看到 start输出说明服务起来了。然后分两步验证先用 curl 直接打 MCP endpoint确认 JSON-RPC 握手和工具列表正常再用单元测试走完整的模型调用链路。curl 验证 MCP 初始化请求curl -X POST http://localhost:8080/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 1, method: initialize, params: { protocolVersion: 2024-11-05, capabilities: {}, clientInfo: {name: curl-test, version: 1.0} } }正常返回会包含serverInfo和capabilities说明 Streamable HTTP 链路通了。注意Accept头必须同时包含application/json和text/event-stream否则服务端可能拒绝流式响应。接着查工具列表curl -X POST http://localhost:8080/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 2, method: tools/list, params: {} }返回里应该能看到getWeather和sumNumbers两个工具的定义包括参数 schema。如果这里返回空列表说明工具注册配置没生效检查ToolCallbackProvider是否被 Spring 扫描到。单元测试用 Spring AI 的ChatClient发起带工具的请求验证模型是否会调用工具SpringBootTest ActiveProfiles(client) class McpClientIntegrationTest { Autowired private ChatClient.Builder chatClientBuilder; Test void shouldCallWeatherTool() { ChatClient chatClient chatClientBuilder.build(); String response chatClient.prompt() .user(北京今天天气怎么样) .call() .content(); System.out.println(模型返回: response); assertThat(response).isNotBlank(); } }跑这个测试之前确保TAOTOKEN_API_KEY环境变量已设置。测试通过的标准是模型返回了包含天气信息的文本并且日志里能看到工具调用的记录。如果模型直接回答而没有调用工具可能是工具描述不够清晰或者模型不支持 function calling。流式返回的验证用stream()方法Test void shouldStreamResponse() { ChatClient chatClient chatClientBuilder.build(); FluxString stream chatClient.prompt() .user(帮我算一下 12 加 30 等于多少) .stream() .content(); ListString chunks stream.collectList().block(); System.out.println(流式片段数: chunks.size()); assertThat(chunks).isNotEmpty(); }流式返回正常的话chunks会有多个片段而不是一次性返回完整文本。这一步验证的是 Streamable HTTP 的流式推送能力如果只收到一个片段说明流式配置有问题。5. 常见报错排查401、local proxy failed、reading choices 与 OAuth这一节对照几个真实报错给出排查路径。这些错误我在调试过程中都遇到过按顺序检查基本能定位。401 Unauthorized最常见的原因是 API Key 没设置或设置错了。检查TAOTOKEN_API_KEY环境变量是否在当前 shell 会话里生效echo $TAOTOKEN_API_KEY确认一下。如果 Key 是对的检查base-url是否写成了https://taotoken.net/api少写/api或者多写斜杠都会导致鉴权失败。另外注意 Key 有没有多余空格从控制台复制的时候容易带上换行。local proxy failed / connection refused这个报错通常出现在 MCP Client 连接 MCP Server 的阶段。检查 MCP Server 是否真的在 8080 端口监听curl http://localhost:8080/mcp能不能通。如果 Server 没起来检查application-http.yml里的web-application-type: servlet有没有配配成none的话 Web 容器不会启动。还有一种情况是端口被占用换个端口或者杀掉占用进程。reading choices 相关报错这个一般出现在模型返回解析阶段说明请求发出去了但响应格式不对。检查model参数是否填了 TaoToken 支持的模型 ID填错模型名会导致返回体里没有choices字段。另外检查spring.ai.openai.chat.options下的配置有没有拼写错误比如temperature写成temprature这种。OAuth / 鉴权头缺失如果你用的是 Claude Code 或 Cline 这类客户端报 OAuth 相关错误通常是客户端配置里没填 Key或者填到了错误的字段。Claude Code 的配置参考 doc 页面Cline 的 MCP 配置里 Base URL 和 Key 要分开填。对于 Spring AI 的 MCP Client鉴权是通过spring.ai.openai.api-key走的不需要额外配 OAuth。工具列表为空MCP Server 起来了但tools/list返回空。检查ToolRegistrationConfiguration类是否在SpringBootApplication的扫描路径下WeatherService是否被Service标记。还有一个坑是Tool注解的name属性如果和已有工具重名后面的会覆盖前面的导致看起来少了工具。流式返回中断stream()调用收到部分片段后断开。检查Accept头是否包含text/event-stream以及服务端有没有设置响应超时。Spring MVC 的异步请求超时默认是 30 秒长任务需要调spring.mvc.async.request-timeout。6. 把 endpoint 改到 TaoToken 后的完整链路与后续方向整条链路跑通之后回顾一下数据流MCP Client 启动时连接本地 MCP Server 的/mcpendpoint拉取工具列表用户发起请求时ChatClient 把用户消息和工具定义一起发给 TaoToken 的/api接口TaoToken 返回模型决策如果决定调用工具MCP Client 通过 Streamable HTTP 把工具调用请求发给 MCP ServerMCP Server 执行工具方法把结果流式返回给 MCP ClientMCP Client 再把工具结果发给模型生成最终回答。这个链路里TaoToken 承担的是模型推理角色MCP Server 承担的是工具执行角色两者通过 MCP Client 串联。把 endpoint 改到 TaoToken 的意义在于你可以用统一的 API 接口验证不同模型对工具调用的支持情况而不需要为每个模型单独适配。后续如果要扩展几个方向可以考虑一是增加更多工具比如数据库查询、文件操作注意 MCP 的安全边界不要让工具直接访问生产库二是把 MCP Server 部署到远程用真实的 HTTP 地址替代 localhost验证跨网络场景下的流式稳定性三是接入多个 MCP Server在 MCP Client 配置里加多个 connection让模型自己选择调用哪个服务的工具。需要创建 API Key 的话去 API Keys 页面配置细节对照接入文档想先试试模型对话效果可以直接在模型对话页面发几条带工具调用的请求观察返回结构。长期跑编码 Agent 任务的话Coding Plan 的额度模型更适合高频调用场景。

相关新闻

透视变换原理与OpenCV实战:从数学到文档矫正

透视变换原理与OpenCV实战:从数学到文档矫正

拍身份证、拍试卷、拍发票,基本上只要用手机拍过任何带角度的纸质文件,都会遇到同一个问题:原本方方正正的文档,在照片里变成了一个梯形或不规则四边形,四边向内收拢,文字也跟着歪斜。这个现象在计算机视觉…

2026/10/17 3:21:48 阅读更多 →
智能PPT生成工具实操指南:从大纲到成稿的高效工作流

智能PPT生成工具实操指南:从大纲到成稿的高效工作流

我见过太多人在PPT前死磕一整天,改完配色改字号,调完动画调间距,最后交付的时候还是觉得哪儿不对。做PPT这件事,真正花时间的从来不是写内容,而是把内容排得好看、讲得清楚。而PPT智能生成工具的出现,把这两…

2026/10/17 3:21:48 阅读更多 →
降AI率实战指南:从困惑度与突发性原理到论文写作自然化调整

降AI率实战指南:从困惑度与突发性原理到论文写作自然化调整

1. 先弄明白检测工具到底在看什么:困惑度、突发性与句式惯性1.1 "顺滑"是AI最容易露出的马脚2025届的毕业季比往年更特殊:答辩前,不少同学拿着自己的论文找我帮忙看,打开检测系统一看,"AI疑似率"不…

2026/10/17 3:21:48 阅读更多 →

最新新闻

从数字分身到AI员工:企业级Agent的可靠、可控与可审计实践

从数字分身到AI员工:企业级Agent的可靠、可控与可审计实践

OpenClaw 最近确实带起了一波“数字分身”热潮。我前后折腾了两周,最大的感受是:让 AI 模仿我的知识库、口吻和日常动作,确实能把不少琐碎工作自动化,还能用自然语言指挥它干活。但个人版玩得越爽,越能感觉到一个反差—…

2026/10/17 4:04:00 阅读更多 →
多轮强化学习训练LLM智能体:从环境设计到长程决策实战

多轮强化学习训练LLM智能体:从环境设计到长程决策实战

如果你已经试过让一个大模型智能体去完成"查资料→对比→写报告→发邮件"这样四段式的任务,大概率会遇到同一个现象:前几步做得漂漂亮亮,到了第三步开始跑偏,最后一步直接给你一个格式全错的附件。我去年在重构内部智能…

2026/10/17 4:04:00 阅读更多 →
本地部署Openclaw接入飞书:搭建AI代理自动生成PPT的完整实战

本地部署Openclaw接入飞书:搭建AI代理自动生成PPT的完整实战

折腾了一个多星期,总算是把本地部署的Openclaw和飞书串起来了。现在团队群里的PPT汇报基本都被它包了,大家只需要在群里喊一句“龙虾,帮我做个季度汇报PPT,8页,市场风格”,过个两三分钟,一个像模…

2026/10/17 4:04:00 阅读更多 →
工业智能体架构设计与落地实操:从感知决策到边缘协同

工业智能体架构设计与落地实操:从感知决策到边缘协同

1. 工业智能体到底是什么,为什么突然成了香饽饽工业智能体这个词,最近一两年在制造业圈子里被提得越来越多。我最早接触这个概念是在一次工厂数字化改造的交流会上,当时有个做产线优化的朋友跟我说,他们厂里上了一套系统&#xff…

2026/10/17 4:04:00 阅读更多 →
基于CNN的图像分类在杏仁损伤检测中的应用与工程实现

基于CNN的图像分类在杏仁损伤检测中的应用与工程实现

每年到毕设季,总有人跑来找我,说想做个深度学习视觉方向的项目。与其随大流做猫狗分类、垃圾分拣这种已经被做过无数遍的题目,不如挑一个看起来冷门但工程链条完整、能讲清楚故事的课题。这次我带的这个题目就是这样来的——基于CNN的图像分类…

2026/10/17 4:04:00 阅读更多 →
Python计算机二级题库全解析:考纲、刷题技巧与备考误区

Python计算机二级题库全解析:考纲、刷题技巧与备考误区

简介:面向全国计算机二级Python备考人群,这份题库将近年常考知识点与真题题型整理为可直接刷练的练习集,覆盖选择题、操作题等常见考核模块,并配套参考答案与解析,帮助考生在考前快速定位薄弱环节、掌握得分要点。压缩…

2026/10/17 4:03:00 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式: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/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →