MCP (Model Context Protocol) 学习:从 STDIO 到 SSE 的 Spring AI 接入实践

发布时间:2026/10/8 12:30:18

MCP (Model Context Protocol) 学习:从 STDIO 到 SSE 的 Spring AI 接入实践 1. 为什么要在 Spring AI 里区分 STDIO 和 SSEMCP 全称 Model Context Protocol你可以把它理解成给大模型外接工具和数据源的一根“标准插头”。模型本身只会生成文本但通过 MCP它能调用天气查询、数据库读取、文件操作这类真实能力。Spring AI 把这套协议封装成了 Starter让 Java 开发者不用手写协议解析直接写Tool方法就能暴露给模型。真正落地时第一个卡住大多数人的问题不是“怎么写工具”而是“用哪种传输方式”。Spring AI 的 MCP Server 提供了三种模式spring-ai-starter-mcp-serverSTDIO、spring-ai-starter-mcp-server-webmvcSpring MVC SSE、spring-ai-starter-mcp-server-webfluxWebFlux SSE。名字看着像只是依赖不同实际决定了你的服务是本地进程还是远程 HTTP 服务。我试过把同一个天气工具分别用 STDIO 和 SSE 跑一遍差异非常直观。STDIO 模式下客户端启动一个子进程通过标准输入输出传 JSON没有端口、没有网络适合本地 CLI 工具、单机脚本、IDE 插件这类场景。SSE 模式下服务端是一个真正的 Web 服务客户端通过text/event-stream长连接接收流式响应适合把工具能力暴露给多个远程调用方比如 Dify、其他微服务或者跨机器的 Agent。选型判断其实就一句话工具和调用方在同一台机器、同一进程生命周期内优先 STDIO需要跨网络、多客户端、独立部署选 SSE。但这句话背后有一堆配置细节比如 STDIO 的command和args怎么写、SSE 的端点路径和超时怎么设、客户端连不上时日志里会报什么错。这篇就按“先跑通 STDIO再跑通 SSE最后排错”的顺序把可复制的配置和验证动作都列出来。热词里提到的 Spring AI、STDIO、SSE 三个词正好对应三种依赖和两套代码结构。下面从依赖开始一步步来。2. TaoToken 前置准备与 Spring AI 依赖配置在写 MCP 代码之前需要先确认模型侧能正常调用。MCP 本身只负责“工具怎么暴露和发现”真正决定模型能不能用工具的是模型服务端是否支持 function calling / tool use。我这边习惯用 TaoToken 作为模型接入层它兼容 OpenAI 风格的接口Spring AI 的 OpenAI Starter 可以直接指向它。先拿 Key。打开https://taotoken.net/api-keys创建一个 API Key复制出来。注意这个 Key 只在创建时显示一次丢了就重新建。然后确认你要用的模型 ID比如claude-sonnet-4-20250514这类支持工具调用的模型。Base URL 用https://taotoken.net/api不要加多余路径。Spring AI 的依赖版本建议统一用 1.0.0-M6 或更高MCP 相关 Starter 在这个版本之后才比较稳定。下面是一个最小可运行的pom.xml依赖片段包含 MCP Server STDIO、MCP Client、以及 OpenAI 兼容的模型 Starterproperties spring-ai.version1.0.0-M6/spring-ai.version /properties dependencies !-- MCP ServerSTDIO 模式 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server/artifactId version${spring-ai.version}/version /dependency !-- MCP Client用于连接 STDIO 或 SSE 服务 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-client/artifactId version${spring-ai.version}/version /dependency !-- OpenAI 兼容模型接入 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-model-openai/artifactId version${spring-ai.version}/version /dependency /dependencies如果你要用 SSE 模式的服务端把第一个依赖换成spring-ai-starter-mcp-server-webmvc或spring-ai-starter-mcp-server-webflux。WebMVC 适合传统 Servlet 应用WebFlux 适合响应式高并发场景。两者在 MCP 协议层面行为一致只是底层 I/O 模型不同。application.yml里模型侧配置如下Base URL 和 Key 都指向 TaoTokenspring: ai: openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: claude-sonnet-4-20250514 temperature: 0.7环境变量TAOTOKEN_API_KEY在启动前 export 进去不要硬编码在文件里。到这里模型侧和 MCP 依赖都齐了接下来写工具。3. STDIO 模式可复制配置与工具代码STDIO 的核心是“服务端作为一个可执行进程被客户端启动”。在 Spring AI 里服务端和客户端可以写在同一个项目里也可以分开。先看服务端。服务端只需要一个SpringBootApplication加一个带Tool方法的 Bean。Tool是 Spring AI 提供的注解方法参数和返回值会被自动转成 MCP 工具描述。下面是一个查询天气的工具import org.springframework.ai.tool.annotation.Tool; import org.springframework.stereotype.Service; Service public class WeatherTools { Tool(description 根据城市名称查询当前天气返回温度和天气状况) public String getWeather(String city) { // 这里用模拟数据实际可替换为真实 API 调用 if (北京.equals(city)) { return 北京晴26℃湿度 40%; } return city 多云22℃湿度 55%; } }服务端启动类里把工具注册进去import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.ai.tool.method.MethodToolCallbackProvider; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; SpringBootApplication public class McpStdioServerApplication { public static void main(String[] args) { SpringApplication.run(McpStdioServerApplication.class, args); } Bean public ToolCallbackProvider weatherToolProvider(WeatherTools weatherTools) { return MethodToolCallbackProvider.builder() .toolObjects(weatherTools) .build(); } }application.yml里 STDIO 服务端配置spring: ai: mcp: server: name: weather-stdio-server version: 1.0.0 stdio: true注意stdio: true表示这个进程通过标准输入输出通信不要同时开 Web 端口否则会冲突。打包成 jar 后客户端通过java -jar启动它。客户端侧配置 STDIO 连接在application.yml里写spring: ai: mcp: client: stdio: connections: weather-server: command: java args: - -jar - /path/to/mcp-stdio-server.jarcommand是启动命令args是参数列表。客户端启动时会自动拉起这个子进程通过 stdin/stdout 交换 JSON-RPC 消息。这里有个坑如果 jar 路径写错客户端不会立刻报“文件不存在”而是卡在初始化阶段日志里只有超时。所以路径建议用绝对路径并且先手动java -jar确认能跑起来。工具调用时模型返回的 tool call 会被 Spring AI 转成对子进程的请求子进程执行getWeather后把结果写回 stdout。整个过程没有网络端口适合本地开发和单机部署。4. SSE 模式服务端与客户端验证请求SSE 模式把 MCP Server 变成一个 HTTP 服务客户端通过text/event-stream接收流式响应。服务端依赖换成spring-ai-starter-mcp-server-webmvcdependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webmvc/artifactId version${spring-ai.version}/version /dependency工具代码和 STDIO 完全一样WeatherTools不用改。区别在application.ymlserver: port: 8080 spring: ai: mcp: server: name: weather-sse-server version: 1.0.0 stdio: false启动后MCP 的 SSE 端点默认在/sse消息端点默认在/mcp/message。你可以先用 curl 验证服务端是否活着curl -N http://localhost:8080/sse-N表示禁用缓冲你会看到类似这样的流式输出event: endpoint data: /mcp/message?sessionIdabc123这说明 SSE 通道建立成功服务端返回了一个 sessionId。接下来客户端用这个 sessionId 发 JSON-RPC 请求。Spring AI 的 MCP Client 会自动处理这些你只需要在客户端application.yml里配置 SSE 连接spring: ai: mcp: client: sse: connections: weather-sse: url: http://localhost:8080客户端启动后会先请求/sse拿到 sessionId再通过/mcp/message发送tools/list和tools/call。验证工具是否被发现可以在客户端写一个测试import org.springframework.ai.mcp.SyncMcpClient; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; Component public class McpSseTestRunner implements CommandLineRunner { private final SyncMcpClient mcpClient; public McpSseTestRunner(SyncMcpClient mcpClient) { this.mcpClient mcpClient; } Override public void run(String... args) { var tools mcpClient.listTools(); System.out.println(发现工具数量 tools.size()); tools.forEach(t - System.out.println(工具名 t.name())); var result mcpClient.callTool(getWeather, java.util.Map.of(city, 北京)); System.out.println(调用结果 result); } }运行后终端应该输出工具列表和“北京晴26℃”。如果listTools返回空说明客户端没连上 SSE 端点先检查端口和路径。SSE 模式的好处是服务端可以独立部署多个客户端同时连接每个连接有独立 sessionId。缺点是长连接会占用线程或连接资源WebFlux 版本用非阻塞 I/O 能缓解但配置复杂度更高。5. 本篇常见错排查401、local proxy failed、reading choices排错部分按真实报错来。第一个高频错误是模型侧 401401 Unauthorized: Incorrect API key provided这个和 MCP 无关是 TaoToken 的 Key 没配好。检查TAOTOKEN_API_KEY环境变量是否 export 成功base-url是否是https://taotoken.net/api不要多写/v1。如果 Key 刚创建确认没有多余空格。第二个错误是 STDIO 客户端启动子进程失败local proxy failed: Cannot run program java: No such file or directory这说明command里的java不在 PATH 里。解决办法是写绝对路径比如/usr/lib/jvm/java-17/bin/java。Windows 下写java.exe的完整路径。另外args里的 jar 路径也要绝对路径相对路径会以客户端工作目录为基准容易找不到。第三个错误出现在模型调用工具后解析响应时Error reading choices: Cannot deserialize value of type java.util.ArrayList from Object value这通常是模型返回的 tool call 格式和 Spring AI 期望的不一致。检查模型 ID 是否支持 function calling有些模型虽然能对话但不支持工具调用。换成claude-sonnet-4-20250514这类明确支持 tool use 的模型再试。如果还报错把spring.ai.openai.chat.options.temperature调低到 0.2减少模型输出格式抖动。第四个错误是 SSE 连接建立后工具调用超时MCP client request timeout after 30000msSSE 模式下服务端处理工具调用如果超过客户端超时时间就会断。检查application.yml里有没有配spring.ai.mcp.client.request-timeout默认 30 秒。如果工具本身耗时调大到 60000。另外确认服务端/mcp/message端点没有被 Spring Security 拦截拦截了会返回 403客户端日志里会看到OAuth或unauthorized相关提示。如果你用的是 Claude Code 或 Cline 这类工具连接 MCP Server配置里需要同时写全三件套Base URL、Key、Model ID。Base URL 用https://taotoken.net/apiKey 用 TaoToken 创建的 KeyModel ID 用支持工具调用的模型。缺任何一个都会在初始化阶段失败。6. 从 STDIO 到 SSE 的选型与接入路径跑通两种模式后选型其实看三个维度部署位置、客户端数量、生命周期。STDIO 适合工具和调用方在同一台机器客户端数量少进程随客户端启动和退出。SSE 适合工具独立部署多个客户端共享服务端需要长期运行。实际项目里我倾向于先用 STDIO 把工具逻辑跑通因为调试简单日志直接打在终端。确认工具描述和参数没问题后再换成 SSE 依赖把同一套Tool代码暴露成 HTTP 服务。这样切换成本很低只需要改依赖和application.ymlJava 代码不动。如果你要把 MCP 能力接到长期运行的编码 Agent 或自动化流程里建议用 SSE 模式配合 Coding Plan服务端独立部署客户端按需连接。模型侧继续用 TaoToken 的接口Base URL 保持https://taotoken.net/apiKey 从https://taotoken.net/api-keys创建。接入文档在https://taotoken.net/doc里面有不同语言的调用示例。最后留一个实用技巧STDIO 模式下子进程的 stderr 默认不会显示在客户端控制台调试时可以在服务端启动类里加一行System.setErr(System.out)把错误输出重定向到 stdout这样客户端日志里就能看到工具内部的异常堆栈。SSE 模式下直接在服务端看日志即可每个 sessionId 对应一条调用链排查起来更清晰。
延伸阅读

更多相关文章

2026/10/8 12:25:18

SLES 15 下 Nginx 与 PHP-FPM 高并发调优实战

电商大促那几天,最怕的往往不是业务代码出 Bug,而是服务器在流量冲上来之后突然从 500 毫秒变成 3 秒,紧接着后台飘红一片 502。如果你手里跑的是 SUSE Linux Enterprise Server 15,应用栈又是经典的 Nginx PHP-FPM,那…

2026/10/8 12:25:18

MacBook Air安装Windows全攻略:Boot Camp原理与避坑指南

简介:面向刚接触 Mac 且希望在苹果笔记本上同时运行 Windows 双系统的用户,这份图解文档以图文对照形式,完整梳理了用 Boot Camp 助理在英特尔处理器 Mac 上安装 Windows 的全部过程。文档覆盖前置环境检查、磁盘分区规划、安装光盘引导、安装…

2026/10/8 13:20:50

Agent-Reach 实战:用 Python CLI 快速构建可调试的 AI Agent

1. 从零认识 Agent-Reach:它到底解决什么问题Agent-Reach 这个名字,第一次看到的时候我以为是某个网络探测工具,后来翻了一圈资料才搞明白,它本质上是一个面向 AI Agent 的 CLI 工具层,用 Python 写的,核心…

2026/10/8 13:20:50

2026深圳罗湖大创客节:校园跳绳挑战赛解析

引言 健康生活与信息科技正在校园里越走越近。在 2026 深圳市罗湖区中小学第九届大创客节人工智能编程设计赛 的图形化赛项中,评委非常看重「用程序解决真实场景问题」的能力——把体育锻炼变成一款可玩、可计数的小游戏,正是这类赛事喜欢的方向。 今天…

2026/10/8 13:20:50

PA Agent 演示模式使用教程:零API成本回放历史K线分析记录

PA Agent 演示模式使用教程:零API成本回放历史K线分析记录 【免费下载链接】PA_Agent 项目地址: https://gitcode.com/gh_mirrors/pa/PA_Agent PA Agent 是一款基于价格行为学(Price Action)的 AI K 线分析工具,而它的演示…

2026/10/8 13:20:50

PS5串流全攻略:从局域网到远程,打造AnyPS5方案

如果你家里有一台PS5,大概率经历过这样的场景:客厅电视被家人占着,你想推两把游戏,却只能对着手机发呆。我试过把主机搬到卧室,结果第二天又得搬回去,HDMI线在背包里绕成一团麻花。后来我把目光转向了串流&…

2026/10/8 13:15:50

Spring Boot零基础入门:从环境搭建到MyBatis数据库实战

我最近在带几个完全零基础的同事转Java方向,发现一个很普遍的现象:大家一说学Spring Boot,第一反应就是去搜“SSM框架教程”,然后从Spring的IOC容器、Bean生命周期开始啃,啃了两个星期连一个能跑的HelloWorld都没写出来…

2026/10/8 10:03:18

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/8 10:03:20

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

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

2026/10/8 0:02:17

自然数立方等于连续奇数之和:从证明到编程验证

十几年来我一直游走在数学科普和编程教学这两块内容之间,对“看起来像魔法、拆开全是数学”的结论总是格外敏感。最近翻资料时又撞见一句话:任何一个自然数 m 的立方,都可以写成 m 个连续奇数之和。2 的立方等于 3 加 5,3 的立方等…

2026/10/8 0:02:17

C#上位机SSH连接实战:用SSH.NET补齐超时、批量与密钥认证

简介:这是一份基于 C# 开发的 SSH 连接功能半成品工程,原本作为另一个主项目的子功能模块,现独立打包分享。工程采用 WinForms 界面,包含源码、解决方案、安装部署工程、NuGet 依赖包及说明文档,适合正在做远程连接、网…

2026/10/8 0:02:17

Java SpringBoot一体化智能售后系统设计与实现全解析

毕业设计年年做,Java Web 方向的题目翻来覆去就那么几个,但“一体化智能售后系统”这个题,每次看到我都觉得值得认真聊一聊。它不是一个简单 curd 堆出来的管理系统,而是把客户、工单、派单、处理、回访、统计整条链路串起来的一套…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑