在现代 AI Agent 和 MCP (Model Context Protocol) 架构中,通信方式主要分为以下三种。它们的演进路线是:本地交互 -> Web 广播 (SSE) -> 无状态高速流 (Streamable HTTP)。
1. Stdio (Standard Input/Output) ------ 本地管道
核心定位 :本地 (Local) 、隐私 、零网络开销 。
适用场景:本地 Agent(如 Cursor, Windsurf)调用本机运行的工具或模型。
-
原理:
- 不走网络 :基于操作系统的标准输入 (
stdin) 和标准输出 (stdout)。 - 进程通信:Client 启动 Server 作为子进程,直接通过管道"递纸条"。
- 不走网络 :基于操作系统的标准输入 (
-
数据格式 :通常是 NDJSON (换行符分隔的 JSON),直接在控制台输出。
-
优点:
- 🚀 速度最快:没有 HTTP 握手、TLS 加密等网络开销。
- 🔒 最安全:数据完全不出本机,防火墙无法拦截。
-
缺点 :无法跨机器使用。调试时需注意区分
stdout(数据)和stderr(日志),否则会破坏 JSON 结构。
2. SSE (Server-Sent Events) ------ 传统的 Web 订阅流
核心定位 :浏览器 (Browser) 、有状态订阅 、Legacy (旧标准) 。
适用场景:Web 前端应用(ChatGPT 网页版)、需要服务器主动推送的场景。
-
原理:
- 有状态连接:客户端建立连接后,连接保持打开,服务器随时可以推送数据。
- 协议封装 :强制 MIME 类型
text/event-stream。
-
数据格式 :穿制服的 JSON 。必须包含
data:前缀和双换行。
text
data: {"result": "Hel"}\n\n
data: {"result": "lo"}\n\n
-
优点:
- 🌐 浏览器原生支持:Chrome/Edge 调试工具可直接查看 EventStream。
- 🔥 防火墙友好:基于标准 HTTP 端口 (80/443)。
-
缺点:
- 连接限制:浏览器对 SSE 连接数有限制(通常 6 个)。
- 有状态负担:在最新的 MCP 规范中,这种维持长连接的方式被认为扩展性较差(Stateful),正逐渐被 Streamable HTTP 取代。
3. Streamable HTTP ------ 现代的无状态高速流
核心定位 :后端 (Backend) 、无状态 (Stateless) 、高并发 。
适用场景:后端微服务互调、Ollama API、最新的 MCP 协议传输层。
-
原理:
- 无状态模型 :不同于 SSE 的"长连接订阅",它更像标准的 HTTP POST 请求,只是响应是流式的。发一个请求,回一串流,流完即断,服务器不保存会话状态。
- 传输层 :利用 HTTP
Transfer-Encoding: chunked。
-
数据格式 (分两种流派):
-
NDJSON (主流):Ollama、Docker 均采用此方式。裸 JSON,一行一个。
json{"response": "Hel"}\n {"response": "lo"}\n -
SSE 兼容模式 :为了兼容部分客户端,部分 Streamable HTTP 也会在内部使用 SSE 的格式(
data:),但交互模式是 Request-Response(无状态),而不是 Subscribe-Publish(有状态)。特性 传统 SSE (订阅-发布) SSE 兼容模式 (请求-响应) 触发方式 客户端连接一次,服务器被动推送消息 客户端发送 Prompt 指令,服务器执行任务 连接时长 长期保持 (Long-lived) 任务处理结束即断开 (Short-lived) 状态维护 服务器需要维护在线用户列表 (Stateful) 服务器不保存会话状态 (Stateless) 应用场景 类似直播间弹幕、实时股价更新 类似 AI 聊天回复、长文本生成过程
- 优点 :
- ⚡ 高并发扩展:因为是无状态的,负载均衡器(Nginx/LB)更容易处理。
- 🛠 支持 POST:完美支持携带大量 Prompt 上下文(解决了 SSE 原生不支持 POST 的痛点)。
- 🧹 纯净高效:NDJSON 模式下无任何协议废话,载荷有效率最高。
📊 终极对比表 (可直接复制)
| 特性 | Stdio | SSE (Legacy/Web) | Streamable HTTP (Modern) |
|---|---|---|---|
| 通信介质 | 本地管道 (Pipe) | 网络 (HTTP 长连接) | 网络 (HTTP 请求-响应流) |
| 典型用户 | 本地 Agent (Cursor) | 浏览器前端 (JS) | 后端服务 (Python/Go), Ollama |
| 数据外观 | {"a":1}\n |
data: {"a":1}\n\n |
{"a":1}\n (NDJSON) |
| HTTP 方法 | N/A | 原生 GET (fetch 可模拟 POST) | 原生 POST |
| 状态管理 | 进程生命周期 | Stateful (有状态) | Stateless (无状态) |
| MCP 支持 | ✅ 官方推荐 (本地) | ⚠️ 逐步废弃 / 仅用于特定场景 | ✅ 官方推荐 (远程) |
| 调试难度 | 困难 (需分离日志) | 简单 (浏览器 DevTools) | 中等 (需抓包或 curl -N) |
💡 关键结论
- 做本地插件 :无脑选 Stdio。
- 做 Web 网页 :选 SSE 格式(但建议用 POST fetch 方式调用,即"Streamable HTTP 的行为 + SSE 的皮肤")。
- 做后端服务/网关 :选 Streamable HTTP (NDJSON),这是目前大模型 API (如 Ollama, vLLM) 的事实标准,也是 MCP 协议推崇的未来方向。
好的,我们一起来梳理这份笔记。要把"传统 SSE 被取代"这个逻辑讲清楚,核心在于对比浏览器接口的能力差异,而不仅仅是协议本身。
这份笔记的核心逻辑是:底层协议没变(都是分块传输),变的是客户端的"遥控器" (从旧的 EventSource 换成了新的 fetch)。
以下是为你整理的笔记结构:
📝 为什么现代 AI 选择 Streamable HTTP (fetch) 而非传统 SSE ?
1. 核心概念辨析 🧠
- 底层技术(没变): 依然是基于 HTTP 的分块传输(Chunked Transfer Encoding)。
- 传统 SSE: 特指浏览器提供的老旧接口
EventSourceAPI。 - Streamable HTTP: 特指使用现代
fetchAPI 配合ReadableStream来手动处理流式数据。
2. 被取代的三大原因 (The "Why")
① 运载能力的硬伤 (GET vs. POST) 📦
-
传统 SSE (
EventSource):- 强制使用 GET 请求。
- 痛点: 数据必须放在 URL 参数中。由于浏览器和服务器对 URL 长度有限制(通常几 KB),无法承载 AI 对话中动辄几万 token 的 Prompt(提示词)和上下文历史。
-
Streamable HTTP (
fetch):- 支持 POST 请求。
- 优势: 数据放在 Body 中,容量几乎无限制,完美适配 RAG(检索增强生成)和长上下文场景。
② 鉴权的安全性 (Headers) 🛡️
-
传统 SSE (
EventSource): -
不支持自定义请求头(Headers)。
-
痛点: 无法传递标准的
Authorization: Bearer token。只能将 Token 拼在 URL 里(如?token=xyz),极易在历史记录或日志中泄露。 -
Streamable HTTP (
fetch):- 完全支持自定义 Headers。
- 优势: 符合现代 API 安全标准,Token 隐蔽且安全。
③ 流程的掌控权 (Control) 🎮
-
传统 SSE (
EventSource): -
全自动:连接断开会自动重连。
-
痛点: 在 AI 生成场景下,如果生成一半断网,自动重连可能导致后台重新生成、重复扣费,且难以处理具体的业务错误(如"余额不足")。
-
Streamable HTTP (
fetch): -
全手动:建立、解析、断开全由代码控制。
-
优势: 可以精确控制何时停止接收(AbortController),如何处理错误,以及是否需要重试。
3. 总结对比表 📊
| 特性 | 传统 SSE (EventSource) |
Streamable HTTP (fetch) |
|---|---|---|
| HTTP 方法 | 🚫 仅 GET (容量受限) | ✅ POST (容量无限) |
| 鉴权方式 | ⚠️ URL 参数 (不安全) | ✅ Custom Headers (安全) |
| 控制机制 | 🤖 自动重连 (不可控) | ⚙️ 手动控制 (灵活) |
| 适用场景 | 简单的消息推送、监控数据 | 大模型对话、复杂 API 交互 |