MCP协议Streamable HTTP

一、概述

2025 年 3 月 26 日,模型上下文协议(Model Context Protocol,简称 MCP)引入了一项关键更新:用 Streamable HTTP 替代原先的 HTTP + SSE 作为默认传输方式。
这一变更在解决原有方案中连接不可恢复、服务端长连接压力大等问题的同时,依然保留了 SSE 带来的流式响应优势。

HTTP + SSE 的缺陷

远程 MCP 通过 HTTP + SSE 的传输方式工作,存在以下问题,这也是它所被替换的根本原因:

  • 不支持恢复连接
  • 要求服务器保持高可用的长连接
  • 服务器只能通过 SSE 发送消息

不支持恢复连接

如果客户端和服务器之间的 SSE 连接中断了,就无法 “从端点继续”,只能重新开始新的连接,之前的上下文可能会丢失。

要求服务器保持高可用的长连接

服务器必须一直保持一个稳定、不中断的 SSE 长连接,否则通信就中断。

服务器只能通过 SSE 发送消息

服务器无法在已有的请求之外,主动地发送消息给客户端,除了通过专门的 /sse 通道。换句话说,它是“单向被动响应”,而不是“任意时机推送”。

 

二、Streamable HTTP

Streamable HTTP 并不是传统意义上的 流式 HTTPStreaming HTTP),它指的是一种 兼具以下特性的传输机制

  • 以普通 HTTP 请求为基础,客户端用 POST/GET 发请求;

  • 服务器可选地将响应升级为 SSE 流,实现 流式传输 的能力(当需要时);

  • 去中心化、无强制要求持续连接,支持 stateless 模式;

  • 客户端和服务端之间的消息传输更加灵活,比如同一个 /message 端点可用于发起请求和接收 SSE 流;

  • 不再需要单独的 /sse 端点,一切通过统一的 /message 协议层处理。

Streamable HTTP 的优势

  • 支持无状态服务器:无需维持高可用的长连接

  • 纯 HTTP 实现:MCP 可在纯 HTTP 服务中实现,无需 SSE 支持

  • 兼容基础设施:因为 “只是 HTTP”,可以与中间件和现有基础设施良好集成

  • 向后兼容:是当前 HTTP+SSE 传输方式的渐进式改进

  • 灵活的传输方式:服务器可选择是否使用 SSE 进行流式响应

从 HTTP+SSE 到 Streamable HTTP 的变化

  • 移除了 /sse 端点

  • 所有客户端 → 服务端的消息都通过 /message(或类似端点)发送

  • 所有客户端 → 服务端的请求都可以被服务器升级为 SSE,以发送通知或请求

  • 服务器可以选择建立会话 ID 以维护状态

  • 客户端可以通过对 /message 发送一个空的 GET 请求启动 SSE 流

  • 该方法兼容旧版本的实现,并允许服务器保持无状态(如果有需要)

Streamable HTTP请求示例

无状态服务器模式

场景:简单工具 API 服务,如数学计算、文本处理等。

实现

复制代码
客户端                                 服务器
   |                                    |
   |-- POST /message (计算请求) -------->|
   |                                    |-- 执行计算
   |<------- HTTP 200 (计算结果) --------|
   |                                    |
复制代码

优势:极简部署,无需状态管理,适合无服务器架构和微服务。

流式进度反馈模式

场景:长时间运行的任务,如大文件处理、复杂 AI 生成等。

实现

复制代码
客户端                                 服务器
   |                                    |
   |-- POST /message (处理请求) -------->|
   |                                    |-- 启动处理任务
   |<------- HTTP 200 (SSE开始) ---------|
   |                                    |
   |<------- SSE: 进度10% ---------------|
   |<------- SSE: 进度30% ---------------|
   |<------- SSE: 进度70% ---------------|
   |<------- SSE: 完成 + 结果 ------------|
   |                                    |
复制代码

优势:提供实时反馈,但不需要永久保持连接状态。

复杂 AI 会话模式

场景:多轮对话 AI 助手,需要维护上下文。

实现

复制代码
客户端                                 服务器
   |                                    |
   |-- POST /message (初始化) ---------->|
   |<-- HTTP 200 (会话ID: abc123) -------|
   |                                    |
   |-- GET /message (会话ID: abc123) --->|
   |<------- SSE流建立 ------------------|
   |                                    |
   |-- POST /message (问题1, abc123) --->|
   |<------- SSE: 思考中... -------------|
   |<------- SSE: 回答1 -----------------|
   |                                    |
   |-- POST /message (问题2, abc123) --->|
   |<------- SSE: 思考中... -------------|
   |<------- SSE: 回答2 -----------------|
复制代码

优势:维护会话上下文,支持复杂交互,同时允许水平扩展。

断线恢复模式

场景:不稳定网络环境下的 AI 应用使用。

实现

复制代码
客户端                                 服务器
   |                                    |
   |-- POST /message (初始化) ---------->|
   |<-- HTTP 200 (会话ID: xyz789) -------|
   |                                    |
   |-- GET /message (会话ID: xyz789) --->|
   |<------- SSE流建立 ------------------|
   |                                    |
   |-- POST /message (长任务, xyz789) -->|
   |<------- SSE: 进度30% ---------------|
   |                                    |
   |     [网络中断]                      |
   |                                    |
   |-- GET /message (会话ID: xyz789) --->|
   |<------- SSE流重新建立 ---------------|
   |<------- SSE: 进度60% ---------------|
   |<------- SSE: 完成 ------------------|
复制代码

优势:提高弱网环境下的可靠性,改善用户体验。


三、Streamable HTTP demo演示

目前我所了解到的,Java,Nodejs,这些都已经支持了Streamable HTTP。

Spring AI Alibaba 官方网站:https://java2ai.com/

 

接下来,使用Nodejs给大家演示一下,如何使用Streamable HTTP

mcp-server-code-runner

mcp-server-code-runner是github里面的一个支持Streamable HTTP的项目,github地址:https://github.com/formulahendry/mcp-server-code-runner

安装 Node.js

从 https://nodejs.org/en 安装 LTS 版的 Node.js 即可。

运行Streamable HTTP

从github上面下载代码之后,进入项目代码目录,运行以下命令即可

npm install
npm run build
npm run start:streamableHttp

执行之后,会输出:

> mcp-server-code-runner@0.1.6 start:streamableHttp
> node dist/streamableHttp.js

Code Runner MCP Streamable HTTP Server listening on port 3088

这里可以看到,监听端口是3088


Cherry Studio添加Streamable HTTP

请确保你的Cherry Studio客户端是最新版本,因为只有最新版本,才支持Streamable HTTP

下载地址:https://github.com/CherryHQ/cherry-studio/releases

目前最新版本是v1.2.7

安装完成后,点击MCP服务器

添加MCP服务器

名称:streamable-http-mcp

类型:Streamable HTTP

URL:http://localhost:3088/mcp

注意:url后面是mcp,因为官方给的sdk,url后面就是mcp

这里新增了请求头,如果你觉得MCP Server暴露在公网,任何人都可以接入MCP Server不安全,这里是可以做token校验的

需要修改MCP Server里面的逻辑代码,建立请求之前,就校验token。如果是非法token,就返回401错误。

 

保存成功后,点击工具

这里可以看到一个工具run-code

 

MCP测试

新建一个默认助手,在对话框,选择MCP设置,选择添加的MCP服务器,streamable-http-mcp

 

 根据github项目提示,演示了3个问题,分别是:

Run the JavaScript Code: console.log(5+6)
Where is temporary folder in my OS? Use run-code tool
How many CPUs do I have in my machine? Use run-code tool

转换为中文

运行JavaScript代码:console.log(5+6)
我的操作系统中的临时文件夹在哪里?使用运行代码工具
我的机器上有多少个CPU?使用运行代码工具

 

分别输入3个问题

运行JavaScript代码:console.log(5+6)

答案是11,是正确的

我的操作系统中的临时文件夹在哪里?使用运行代码工具

答案是,C:\Users\98733\AppData\Local\Temp,也是对的。

我的机器上有多少个CPU?使用运行代码工具

 

打开任务管理,选择性能,右下角可以看到核心数

 确实是8个,也是正确的。

 

如果需要python开发Streamable HTTP MCP应用,请参考文章:https://www.cnblogs.com/xiao987334176/p/18872195


本文参考链接:

https://juejin.cn/post/7493404904725741603

https://www.cnblogs.com/formulahendry/p/18837144

https://www.cnblogs.com/alisystemsoftware/p/18842223

 

原创作者: xiao987334176 转载于: https://www.cnblogs.com/xiao987334176/p/18845151
<think>我们正在讨论MCP服务器(可能是某种自定义服务器)的流式HTTP处理。根据用户提供的引用,我们看到一个HTTPPOST请求示例,该请求发送到`/messages/`端点,并且服务器返回了202Accepted状态码。但是,用户现在关心的是流式处理(streamableHTTP)的配置或实现。在HTTP中,流式处理通常意味着服务器能够逐步发送响应(例如使用分块传输编码)或者客户端能够发送流式请求(例如上传大文件时边读边传)。在MCP服务器的上下文中,用户可能希望实现或配置类似的功能。根据引用中的示例,我们注意到:-请求是一个完整的POST请求,不是流式上传。-响应是202Accepted,并且响应体很小(只有8字节),这显然不是流式响应。因此,我们需要考虑如何将MCP服务器配置为支持流式处理。###可能的流式处理场景1.**流式响应(Server-SentEvents,WebSocket,或分块传输编码)**:服务器可以分块发送数据,例如实时更新。2.**流式请求**:客户端可以分块上传数据,服务器边接收边处理。###配置或实现建议####1.使用分块传输编码(ChunkedTransferEncoding)在HTTP/1.1中,分块传输编码允许服务器将响应分成多个部分(块)发送。这通常用于当响应内容长度未知时,或者需要实时生成内容时。在Python中,如果你使用像uvicorn这样的ASGI服务器(如引用中所示),并且你的应用是异步的(例如基于Starlette或FastAPI),你可以返回一个生成器来实现流式响应。示例(FastAPI):```pythonfromfastapiimportFastAPIimportasyncioapp=FastAPI()@app.post("/stream_response/")asyncdefstream_response():asyncdefgenerate():foriinrange(5):awaitasyncio.sleep(1)yieldf"Chunk{i}\n"returnStreamingResponse(generate(),media_type="text/plain")```####2.流式请求对于流式请求,客户端可以分块发送数据。服务器需要能够逐步读取请求体。在FastAPI中,你可以使用`Request`对象直接读取请求体流:```pythonfromfastapiimportFastAPI,Requestapp=FastAPI()@app.post("/stream_request/")asyncdefstream_request(request:Request):#逐块读取请求体asyncforchunkinrequest.stream():#处理每个块process_chunk(chunk)```####3.使用WebSocket如果需要双向流式通信,WebSocket可能是更好的选择。但WebSocket是完全不同的协议,不是HTTP。####4.服务器配置在引用中,服务器是uvicorn。uvicorn支持流式响应和请求,但需要应用程序支持(如上例所示)。因此,配置主要在应用程序代码中实现,而不是在服务器配置文件中。###针对MCP服务器的建议由于用户提到的MCP服务器(可能是自定义服务器)已经使用了uvicorn,因此可以按照上述方式实现流式处理。但是,具体到MCP服务器的实现,我们需要知道它的内部架构。如果MCP服务器是基于类似FastAPI的框架,那么实现流式处理是直接的。如果MCP服务器是用户自己开发的,那么需要:-对于流式响应:在生成响应时,使用分块传输编码。在ASGI中,可以通过返回一个异步生成器来实现。-对于流式请求:在读取请求体时,不要一次性读取,而是逐块读取(通过`request.stream()`)。###注意事项-在HTTP/1.1中,分块传输编码是标准的一部分,但客户端必须支持。-在HTTP/2中,流式处理更加高效,因为它支持多路复用。###引用说明引用[1]中展示的MCP服务器当前的处理方式是非流式的(一次性请求,一次性响应)。因此,要实现流式处理,需要修改端点处理逻辑。§§相关问题§§1.如何测试MCP服务器的流式HTTP端点?2.在流式处理中,如何处理错误和中断?3.MCP服务器支持HTTP/2吗?如何配置?</think>### MCP服务器流式HTTP处理分析 根据您提供的引用信息和需求,MCP服务器的流式HTTP处理涉及以下关键点: 1. **现有通信模式分析** 引用[1]显示当前MCP SSE服务器使用标准HTTP短连接POST请求: ```http POST /messages/?session_id=97a44bcff590415e99cf803350ffd542 HTTP/1.1 Host: 10.0.105.64:8080 Content-Type: application/json {"method":"tools/call","params":{...}} ``` 服务器返回`202 Accepted`状态码,表明请求已被接受但处理未完成[^1]。这种模式**不满足流式处理需求**,因为: - 使用短连接而非持久连接 - 响应为完整一次性返回 - 缺少流式数据传输机制 2. **流式HTTP实现方案** 要实现流式处理,建议采用以下技术: **a) 分块传输编码(Chunked Transfer Encoding)** 在HTTP响应头中添加: ```http HTTP/1.1 200 OK Transfer-Encoding: chunked Content-Type: application/x-ndjson ``` 服务器分段发送数据: ```http 1A // 十六进制块大小 {"event":"update","data":"..."} 0 // 结束块 ``` **b) Server-Sent Events(SSE)** 专为服务器到客户端的单向流设计: ```python # FastAPI示例 @app.get("/stream") async def message_stream(): async def event_generator(): while True: if new_data := await queue.get(): yield f"data: {json.dumps(new_data)}\n\n" return EventSourceResponse(event_generator()) ``` 客户端通过`EventSource` API接收: ```javascript const source = new EventSource('/stream'); source.onmessage = (event) => { ... }; ``` **c) WebSocket双向流** 适用于双向实时通信: ```python # uvicorn+WebSockets实现 @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() while True: data = await websocket.receive_text() # 处理并流式返回 await websocket.send_text(process(data)) ``` 3. **MCP服务器配置建议** - **协议升级**:在现有POST端点添加`Accept: text/event-stream`支持 - **会话保持**:利用现有`session_id`参数维持流连接 - **超时设置**:配置`keepalive_timeout`保持长连接 - **缓冲区管理**:调整`uvicorn`的`max_queued_bytes`防止背压 4. **性能优化方向** - 使用异步框架(如Starlette)处理高并发流 - 实施背压控制(backpressure control) - 添加`Last-Event-ID`头支持断线重连 - 压缩流数据:`Content-Encoding: gzip` > **关键区别**:传统HTTP请求(如引用所示)是事务型交互,而流式HTTP建立持久通道持续传输数据片段[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值