8.3 流式 HTTP:生产级传输 本节摘要:流式 HTTP(Streamable HTTP)是 2025-03-26 协议引入的生产级传输,取代了旧版 SSE。它让 MCP 服务端跑成一个真正的 HTTP 服务,支持远程访问、多客户端并发、现代基础设施(负载均衡、反代)。本节讲透它的两种启动方式( 一行启动、 拿 ASGI app 嵌入),关键配置项,以及它为什么比 SSE 更好。 一、流式 HTTP 是什么 流式 HTTP 让 MCP 服务端跑成一个 HTTP 服务——监听一个端口,接受 HTTP 请求,用 HTTP 承载 MCP 消息: 与 stdio(子进程)不同,流式 HTTP 是个真正的网络服务——可以远程访问、可以多客户端连、可以放在负载均衡后面。这就是它「生产级」的含义。
本节摘要:流式 HTTP(Streamable HTTP)是 2025-03-26 协议引入的生产级传输,取代了旧版 SSE。它让 MCP 服务端跑成一个真正的 HTTP 服务,支持远程访问、多客户端并发、现代基础设施(负载均衡、反代)。本节讲透它的两种启动方式(
mcp.run("streamable-http")一行启动、mcp.streamable_http_app()拿 ASGI app 嵌入),关键配置项,以及它为什么比 SSE 更好。
流式 HTTP 让 MCP 服务端跑成一个 HTTP 服务——监听一个端口,接受 HTTP 请求,用 HTTP 承载 MCP 消息:
客户端 服务端 ┌──────────────┐ HTTP POST/GET ┌──────────────┐ │ Client │ ───────────────────► │ MCPServer │ │ │ ◄─────────────────── │ (HTTP 服务) │ └──────────────┘ HTTP 响应/SSE 流 └──────────────┘ 监听端口
与 stdio(子进程)不同,流式 HTTP 是个真正的网络服务——可以远程访问、可以多客户端连、可以放在负载均衡后面。这就是它「生产级」的含义。
流式 HTTP 有两种启动方式,适合不同场景:
最简单的方式,mcp.run 指定传输:
from mcp.server import MCPServer mcp = MCPServer("Demo") @mcp.tool() def add(a: int, b: int) -> int: """Add two numbers.""" return a + b if __name__ == "__main__": mcp.run("streamable-http") # 跑成独立 HTTP 服务
mcp.run("streamable-http") 会启动一个 HTTP 服务,默认监听 localhost:8000,路径 /mcp。客户端用 Client("http://localhost:8000/mcp") 连接。
如果你想把 MCP 服务端嵌入现有的 Web 服务(如 FastAPI/Starlette 应用),用 streamable_http_app 拿到 ASGI app:
mcp = MCPServer("Demo") # ... 注册工具/资源/提示词 ... # 拿到 ASGI app,可挂到任何 ASGI 服务器或现有应用 app = mcp.streamable_http_app()
这个 app 可以:
uvicorn.run(app)💡 技巧:独立服务用方式一(一行启动),嵌入现有服务用方式二(ASGI app)。方式一简单,适合纯 MCP 服务;方式二灵活,适合「我的 Web 应用里要加一块 MCP 能力」的场景。
流式 HTTP 有几个关键配置项,影响服务行为:
| 配置项 | 默认值 | 作用 |
|---|---|---|
host |
localhost | 监听地址 |
port |
8000 | 监听端口 |
streamable_http_path |
/mcp |
MCP 端点路径 |
json_response |
False | 是否用 JSON 响应(而非 SSE 流) |
stateless_http |
False | 是否无状态(每次请求独立) |
max_request_body_size |
(有限) | 请求体大小上限 |
event_store |
(无) | 事件存储(支持断线恢复) |
最常用的是 host/port(监听地址)与 streamable_http_path(端点路径):
mcp.run( "streamable-http", host="0.0.0.0", # 监听所有网卡(可远程访问) port=9000, # 端口 streamable_http_path="/mcp" # 端点路径 )
json_response 配置项决定响应形态,值得单独讲:
默认(json_response=False):SSE 流响应 客户端 POST 请求 服务端用 SSE(Server-Sent Events)流式返回 → 支持服务端持续推送(进度、日志、引导填写问题) → 适合需要流式交互的场景 json_response=True:普通 JSON 响应 客户端 POST 请求 服务端用普通 JSON 一次性返回 → 简单,但不能流式推送 → 适合简单请求-响应场景
多数场景用默认(SSE 流),因为它支持第 7 章讲的进度上报、日志通知、引导填写问题——这些都需要服务端持续推送。如果你的场景纯是「请求-响应」无推送,可设 json_response=True 简化。
流式 HTTP 在 2025-03-26 取代了旧版 SSE 传输。为什么?
| 维度 | SSE(旧) | 流式 HTTP(新) |
|---|---|---|
| 连接模型 | 双连接(POST + SSE) | 单端点(POST 或 SSE 响应) |
| 复杂度 | 高(两个连接要协调) | 低(单一端点) |
| 基础设施友好 | 一般(双连接,有些反代不支持) | 好(标准 HTTP) |
| 无状态支持 | 难 | 易(stateless_http) |
| 现代化 | 已弃用 | 主力 |
简单说:流式 HTTP 更简单、更适配现代基础设施。SSE 的双连接模型(一个 POST 发请求,一个 SSE 收响应)在反代、负载均衡下问题多;流式 HTTP 用单一端点,与普通 HTTP 服务无异。
⚠️ 注意:新代码用流式 HTTP,别用 SSE。SSE 仍能工作但已弃用,官方未来可能移除。如果你维护用 SSE 的老代码,规划迁移到流式 HTTP。
把流式 HTTP 服务端部署到生产,有几个考量:
| 考量 | 建议 |
|---|---|
| 监听地址 | 生产用 0.0.0.0(可远程访问),别用 localhost |
| 传输安全 | 默认 DNS 重绑定防护只允许 localhost,公网要配置(第 8.5 节) |
| 认证 | 公网暴露必须加认证(第 11 章 OAuth) |
| 反向代理 | 可放 nginx 后面,流式 HTTP 兼容 |
| 负载均衡 | 多实例可负载均衡(配合无状态模式) |
| HTTPS | 生产用 HTTPS,nginx 或 ASGI 服务器配 TLS |
# 生产部署的概念性配置 mcp.run( "streamable-http", host="0.0.0.0", # 远程可访问 port=8000, transport_security=..., # DNS 重绑定防护配置(第 8.5 节) # 认证由第 11 章的 OAuth 中间件处理 )
最后总结流式 HTTP 相对其他传输的优势:
| 优势 | 说明 |
|---|---|
| 远程访问 | 真正的网络服务,可跨机器 |
| 多客户端 | 一个服务可同时服务多个客户端 |
| 现代基础设施 | 兼容反代、负载均衡、HTTPS |
| 无状态模式 | stateless_http=True 支持水平扩展 |
| 嵌入性 | ASGI app 可嵌入现有 Web 服务 |
| 协议现代化 | 2025-03-26 主力,长期支持 |
这些优势使流式 HTTP 成为「生产部署的首选传输」——任何需要远程访问、多客户端、高可用的场景,都该用它。
mcp.run("streamable-http") 独立服务;方式二 streamable_http_app() 拿 ASGI app 嵌入。host/port(监听)、streamable_http_path(端点,默认 /mcp)、json_response、stateless_http。json_response 决定响应形态:默认 SSE 流(支持推送),True 用普通 JSON(简单)。流式 HTTP 清楚了,下一节讲它取代的 SSE——旧版遗留,知道即可。