LLM - MCP传输协议解读:从SSE的单向奔赴到Streamable HTTP的双向融合
文章目录
- 前言
- SSE (Server-Sent Events) 基础
- 连接建立与数据传输
- 客户端接收机制
- SSE vs. WebSocket
- MCP的早期探索:SSE + HTTP POST
- 逻辑双向通信原理
- 为何选择SSE?
- HTTP+SSE 的痛点
- 下一代传输机制:Streamable HTTP
- 核心特性与改进
- Streamable HTTP 工作流程
- Streamable HTTP 请求示例
- 无状态服务器模式(如:工具API)
- 流式进度反馈模式(如:长文生成)
- 复杂AI对话模式(有状态)
- 断线恢复模式(有状态)
- 总结
- 参考资料

前言
Model Context Protocol (MCP) 旨在规范和简化大型语言模型(LLM)应用与客户端之间的交互。一个高效、可靠的传输层是实现这一目标的核心。
接下来我们将深入剖析MCP传输协议的演进之路——从早期采用的服务器推送事件(Server-Sent Events, SSE),到为克服其局限性而引入的、更现代化和灵活的Streamable HTTP方案。我们将一同探究这两种技术的核心原理、实现细节及其在MCP中的应用与权衡。
SSE (Server-Sent Events) 基础
Server-Sent Events (SSE) 是一种标准的HTTP协议,允许服务器向客户端进行单向的实时数据推送。它是构建许多实时更新功能(如新闻源、状态更新)的基石。
连接建立与数据传输
客户端发起请求
客户端通过浏览器内置的 EventSource
API,向服务器发送一个特殊的HTTP GET请求。关键在于其请求头 Accept: text/event-stream
,它向服务器声明:“我准备好接收一个事件流了。”
GET /sse-endpoint HTTP/1.1
Host: example.com
Accept: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
服务器响应
服务器返回 200 OK
状态码,并在响应头中明确 Content-Type: text/event-stream
,同时通过 Transfer-Encoding: chunked
告知客户端,数据将以流式(分块)的方式发送,而不是一次性返回。
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Transfer-Encoding: chunked
数据推送格式
连接建立后,服务器就可以随时向客户端推送格式化的消息。每条完整的SSE消息以两个连续的换行符 (\n\n
) 作为结束。
event: status_update
id: 20240514_001
data: {"temperature": 23.5, "humidity": 60%}
retry: 5000
event
(可选): 事件类型。客户端可以据此监听特定事件。id
(可选): 消息的唯一标识。如果连接中断,客户端会自动在重连请求的Last-Event-ID
头中带上此ID,便于服务器从断点处继续推送。data
(必需): 消息的实际内容。retry
(可选): 指定断线后客户端重连的等待时间(毫秒)。
客户端接收机制
客户端的实现非常简洁,EventSource
API 封装了所有复杂的细节,包括自动重连。
const source = new EventSource('/sse-endpoint');// 监听特定事件 'status_update'
source.addEventListener('status_update', (e) => {const eventData = JSON.parse(e.data);console.log('Received status update:', eventData);
});// 监听默认的 'message' 事件
source.onmessage = (e) => {console.log('Received generic message:', e.data);
};source.onerror = (e) => {if (source.readyState === EventSource.CLOSED) {console.error('SSE connection closed.');} else {console.error('SSE error:', e);}
};
SSE vs. WebSocket
特性 | SSE (Server-Sent Events) | WebSocket |
---|---|---|
通信方向 | 单向(服务端 → 客户端) | 双向(全双工) |
协议基础 | 标准HTTP/HTTPS | 独立协议 (ws://, wss://) |
协议开销 | 基于HTTP,头部相对较大 | 握手后头部轻量 |
自动重连 | 内建支持 (retry , Last-Event-ID ) | 需手动实现 |
适用场景 | 实时状态更新、新闻推送、数据大屏 | 实时聊天、在线游戏、高频交互 |
SSE的核心局限在于其单向性:客户端只能被动接收,无法通过同一连接向服务器发送消息。
MCP的早期探索:SSE + HTTP POST
为了在利用SSE流式推送优势的同时,实现客户端到服务器的通信,早期的MCP采用了一种“组合拳”模式:SSE + 独立的HTTP POST。
逻辑双向通信原理
- 下行通道 (Server → Client): 客户端通过SSE建立一个长连接,专门用于接收LLM生成的内容、状态更新等流式数据。
- 上行通道 (Client → Server): 当客户端需要发送用户输入或控制指令时,它会向另一个独立的HTTP端点(如
/mcp/message-endpoint
)发起一个标准的POST请求。
这种设计将双向通信在逻辑上分离到了两个不同的HTTP连接中。
客户端示例 (JavaScript):
// 1. 接收SSE推送
const source = new EventSource('/mcp/sse-endpoint');
source.onmessage = (e) => {console.log('MCP Server Message:', e.data);
};// 2. 通过独立的HTTP POST发送消息
async function sendMessageToMcpServer(message) {try {const response = await fetch('/mcp/message-endpoint', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ message: message }),});if (!response.ok) {console.error('Failed to send message:', response.statusText);}} catch (error) {console.error('Error sending message:', error);}
}sendMessageToMcpServer('你好,模型');
为何选择SSE?
MCP初期青睐SSE,主要看中了它的几大优点:
- 开发简单:
EventSource
API非常易用,降低了客户端开发成本。 - 流式友好: 完美契合LLM逐步生成长文本的场景,用户可以即时看到结果。
- 内建重连: 对网络不稳定的环境有很好的容错性,对于长时间运行的AI任务至关重要。
- 优于轮询: 相比传统的客户端轮询,极大减少了服务器资源消耗和网络延迟。
HTTP+SSE 的痛点
然而,这种看似简单的模式在复杂的实际应用中逐渐暴露出一些难以忽视的短板:
- 复杂的会话恢复:
Last-Event-ID
只能恢复消息流,但无法恢复整个对话的上下文。连接一旦中断,复杂的会话状态(如多轮对话历史)很可能丢失。 - 服务器长连接压力: 每个客户端都需要一个持久的TCP连接,当并发量激增时,服务器的内存和文件描述符等资源将面临巨大压力。
- 基础设施兼容性差: 许多API网关、负载均衡器和CDN并非为SSE这种长连接模式优化,可能会因超时而主动切断连接,导致服务不稳定。
- 对Serverless不友好: 依赖长连接状态的模式与云函数/Serverless等追求无状态、按需执行的架构理念相悖。
下一代传输机制:Streamable HTTP
为了解决上述痛点,MCP引入了新一代传输机制——Streamable HTTP。它并非一个全新的协议,而是对标准HTTP协议的一种更灵活、更强大的运用模式,旨在提供一个更健壮、对云原生架构更友好的传输层。
核心特性与改进
Streamable HTTP的核心思想是将所有通信统一到一个端点上,并根据需求动态“升级”为流式传输。
- 统一端点: 不再需要区分
/sse
和/message
端点。所有通信都通过一个端点(如/message
)完成,简化了协议和配置。 - 按需流式传输: 服务器可以智能地选择响应方式。
- 普通HTTP响应: 对于简单的请求(如工具调用),直接返回一个完整的HTTP响应体(
Content-Length
)。 - 升级为SSE流: 对于需要流式返回的任务(如文本生成),在同一次HTTP响应中,以
Content-Type: text/event-stream
和Transfer-Encoding: chunked
开始推送SSE事件流。
- 普通HTTP响应: 对于简单的请求(如工具调用),直接返回一个完整的HTTP响应体(
- 会话ID与无状态支持: 引入
Mcp-Session-Id
HTTP头。客户端在每次请求中都携带此ID,使得服务器可以识别会话。这让服务器端可以设计成无状态的,极大地提升了其水平扩展能力,并完美适配Serverless架构。 - 增强的兼容性: 由于其行为更接近标准的HTTP请求-响应模式,它能更好地与Nginx、CDN等现有网络基础设施协同工作。
Streamable HTTP 工作流程
- 会话初始化: 客户端向统一端点发送一个POST请求,服务器在响应中返回一个
Mcp-Session-Id
。 - 客户端通信: 客户端后续所有请求都通过POST到该端点,并在请求头中带上
Mcp-Session-Id
。 - 服务器响应:
- 非流式: 返回一个普通的
application/json
响应。 - 流式: 返回
Content-Type: text/event-stream
,并立即开始在该连接上推送SSE事件。
- 非流式: 返回一个普通的
- 断线恢复: 如果连接中断,客户端只需使用同一个
Mcp-Session-Id
重新发起请求。如果服务器端设计了状态恢复逻辑(例如,将上下文存储在Redis中),就可以从中断处无缝继续。
Streamable HTTP 请求示例
下面我们通过几个典型场景来感受Streamable HTTP的强大之处。
无状态服务器模式(如:工具API)
每次请求都是一次独立的计算,服务器无需记录任何状态。
步骤 | 客户端 | 服务器 |
---|---|---|
请求 | POST /message <br>{"tool": "calculator", "input": "2+2"} | 处理计算 |
响应 | 接收数据 | HTTP 200 OK <br>Content-Type: application/json <br>{"result": 4} |
优点: 极致简单,易于部署和无限扩展,是Serverless的最佳实践。
流式进度反馈模式(如:长文生成)
任务执行时间长,需要实时反馈进度或部分结果。
步骤 | 客户端 | 服务器 |
---|---|---|
请求 | POST /message <br>{"prompt": "写一首关于宇宙的诗"} | 启动AI模型生成 |
响应(流式) | 接收SSE事件流 | HTTP 200 OK <br>Content-Type: text/event-stream <br><br>data: 在无垠的 …<br><br>data: 黑暗中 …<br><br>event: done … |
优点: 显著改善用户体验,任务完成后连接即可关闭,节约资源。
复杂AI对话模式(有状态)
需要维护上下文的多轮对话。
步骤 | 客户端 | 服务器 |
---|---|---|
请求1 | POST /message <br>{"prompt": "你好"} | 生成会话ID sess-123 ,处理请求 |
响应1 | 存储 Mcp-Session-Id: sess-123 | Mcp-Session-Id: sess-123 <br>data: 你好!有什么可以帮你的吗? |
请求2 | POST /message <br>Mcp-Session-Id: sess-123 <br>{"prompt": "MCP是什么?"} | 根据 sess-123 恢复上下文,处理请求 |
响应2 | 接收流式回答 | Mcp-Session-Id: sess-123 <br>data: MCP是模型上下文协议... |
优点: 即使服务器是无状态、可水平扩展的(会话状态可存储在外部),也能支持复杂的多轮交互。
断线恢复模式(有状态)
在移动端等网络不稳定的环境下,保证任务不因断网而失败。
步骤 | 客户端 | 服务器 |
---|---|---|
请求 | POST /message <br>Mcp-Session-Id: sess-456 <br>{"task": "分析这份100页的文档"} | 开始分析并流式返回进度 |
…网络中断… | ||
重连请求 | POST /message <br>Mcp-Session-Id: sess-456 <br>{"action": "resume"} | 根据 sess-456 找到任务状态 |
响应(恢复) | 从中断处继续接收进度 | 从上次中断的地方继续推送SSE事件 |
优点: 极大地提升了应用的可靠性和鲁棒性,是打造专业级AI应用的关键。
总结
MCP传输协议的演进,是从一个简单直观但有所局限的HTTP+SSE模式,迈向一个更强大、更灵活、更适应现代云原生架构的Streamable HTTP模式的历程。通过统一端点、按需流式传输、会话标识等关键设计,Streamable HTTP不仅解决了前者在会话管理、服务器负载和基础设施兼容性方面的痛点,更为构建高可伸缩、高可用的MCP应用提供了坚实的基础。
MCP仍在快速发展,社区也在积极地推动新规范的生态建设。理解其传输层的演进,不仅能帮助我们更好地应用该协议,也能为我们设计自己的分布式系统提供宝贵的思路。
参考资料
- Significant Upgrade to the MCP Protocol: Spring AI Alibaba and Higress Release the Industry’s First Streamable HTTP Implementation Solution
- 使用 Amazon Lambda 快速部署 Streamable HTTP Github MCP Server
- Bringing streamable HTTP transport and Python language support to MCP servers
- 官方Specification (2025-03-26)