从 LLM 流式响应说起:一文理清HTTP Streaming、SSE与 MCP Streamable HTTP

从 LLM 流式响应说起:一文理清HTTP Streaming、SSE与 MCP Streamable HTTP 最近在适配各种中转站 LLM以及接入一些 Agent 时经常需要解析不同厂商的流式响应格式。过程中发现之前对 MCP 传输协议、SSE、Streamable HTTP 等概念的理解有些混在一起了。所以这里重新做一次系统梳理也顺便分享出来。HTTP Streaming 流概念解释HTTP Streaming 是一种通信模式不是某一个具体协议。它的核心是基于 HTTP 请求-响应模型但服务端不一次性结束响应而是持续把数据分块写回给客户端。普通 HTTP 是这样Client --- Server: GET /api Client --- Server: 一次性返回完整响应HTTP Streaming 是这样Client --- Server: GET /stream Client --- Server: chunk1 Client --- Server: chunk2 Client --- Server: chunk3 Client --- Server: ...也就是说普通 HTTP一次请求一次完整响应HTTP Streaming一次请求一个持续输出的响应常见的 HTTP 流式形式有SSEChunked TransferNDJSON StreamingMultipart StreaminggRPC StreamingGraphQL over SSE / MultipartHLS / MPEG-DASH需要注意HTTP Streaming 是大类SSE 是 HTTP Streaming 的一种标准化格式SSE (Server-Sent Events)SSE 是一种基于 HTTP 的服务端事件流格式。它解决的问题是客户端先发起一个 HTTP 请求服务端不立刻结束响应而是保持连接持续向客户端推送事件典型请求GET /events HTTP/1.1 Accept: text/event-stream典型响应HTTP/1.1 200 OK Content-Type: text/event-stream; charsetutf-8 Cache-Control: no-cache Connection: keep-aliveContent-Type: text/event-stream 表示这是一个 SSE 流客户端需要持续接收服务端写入的数据而不是按普通 HTTP 响应一次性读取完SSE 的通信模型Client Server GET /events ---------------- 建立 SSE 长连接 ------------------ data: hello ------------------ data: world ------------------ data: {content:你好} ------------------ data: [DONE]SSE 响应数据有固定格式data: hello data: world data: {content:你好} data: [DONE]每条消息之间需要一个空行。也可以带事件名event: message data: {text:hello} event: done data: {}如果没有写event默认就是message事件。SSE 只定义一件事服务端如何通过一个 HTTP 响应持续向客户端发送事件所以最简单的 SSE 服务只需要一个接口GET /events如果客户端也要向服务端发送业务消息一般需要再加一个普通 HTTP 接口GET /events # 建立 SSE 下行通道 POST /message # 客户端向服务端发送消息也就是说SSE 本身主要负责 Server - Client Client - Server 通常还是用普通 HTTP POSTMCP 中的 SSE 和 Streamable HTTPSSE 是一种较早就存在的基于 HTTP 的服务器事件流技术本质是服务端通过text/event-stream响应持续向客户端推送事件。在MCP 早期的 HTTPSSE 传输方案里客户端需要先打开一条 SSE 长连接来接收服务端消息然后再通过另一个普通 HTTP POST endpoint 向服务端发送消息。也就是SSE 负责下行POST 负责上行。官方 2024-11-05 规范明确要求两个 endpoint一个 SSE endpoint一个 POST endpoint。后来 MCP 在 2025-03-26 之后用 Streamable HTTP 替代了旧的 HTTPSSE transport。新的方式不再固定要求“先建立一条独立 SSE 长连接”而是定义一个统一的 MCP HTTP endpoint同时支持 POST 和 GET。客户端消息通过 POST 发送服务端可以直接返回application/json也可以在需要流式输出时返回text/event-stream。Streamable HTTP” 这个名字 是 MCP 规范里给自己新 HTTP 传输方案起的名字。旧版 MCP HTTPSSE 是这样你先连上一根专门收消息的 SSE 管子 之后你 POST 发请求 服务端的回复从这根 SSE 管子里回来。新版 Streamable HTTP 是这样你直接 POST /mcp 发请求 服务端如果能一次性返回就直接 JSON 返回 如果要流式返回就把这次 HTTP 响应变成 SSE 流 如果需要服务端主动推送也可以 GET /mcp 打开 SSE 流。旧版 MCPHTTP SSE有两个 endpoint/messages 只是上行入口 /sse 是下行流server -data- client 客户端发请求POST /messages 服务端回结果通过 /sse 这条已经打开的流返回HTTPSSE 的工作流程客户端连接到服务器上的/sse服务端保持连接开启流通道服务器响应一个 endpoint 地址用于后续 client 发具体请求server 通过/sse流式响应数据新版 MCPStreamable HTTP工作流程客户端向服务端发送请求。请求头标注可 json 可流 POST /mcp HTTP/1.1 Host: example.com Content-Type: application/json Accept: application/json, text/event-stream服务端自己决定是以标准的 HTTP 响应HTTP Response还是流式响应SSE Response的形式返回。所以Streamable HTTP 中的流也用的是 SSE 格式如果 client 要监听来自 Server 的消息可以向同一个 MCP endpoint 发起GET请求GET /mcp HTTP/1.1 Accept: text/event-stream MCP-Session-Id: s_001 GET /mcp 不是普通查询接口 而是用来打开一条 Server - Client 的流式接收通道 Client --- Server: GET /mcp Client --- Server: 打开 SSE 流 Client --- Server: 持续推送消息 Client --- Server: 持续推送消息 ...HTTP SSE vs Streamable HTTP对比点旧版 HTTPSSE新版 Streamable HTTPendpoint两个/sse /messages一个/mcp简单请求也要先连 SSE再 POST再从 SSE 收结果POST /mcp 直接返回 JSON流式响应固定从 /sse 返回POST /mcp 可以直接返回 SSE 流服务端主动推送依赖长期存在的 /sse 连接可选 GET /mcp 打开 SSE 流状态管理要维护 POST 请求和 SSE 连接的对应关系通过统一 endpoint session 管理Session主要靠实现自己维护规范化 Mcp-Session-Id断线恢复不够清晰可用 SSE event id Last-Event-ID多连接路由更复杂容易重复或错发规范约束消息只能发到一条流