揭秘 MCP Streamable HTTP 協議親和性的技術內幕
作者:葉浩田
背景
傳統的 Serverless 平臺一般都是面向無狀態應用的,通過將請求分發到不同的可以自動擴展的函數實例,從而為應用提供極致的彈性、按量付費等能力。然而,針對存在會話概念的應用,傳統的 Serverless 平臺就不能夠在后端有多個副本的情況下,將屬于某個會話的請求轉發到服務該會話的函數實例,從而該類應用無法在不引入外部存儲同步會話狀態的情況下運行在 Serverless 平臺上。外部存儲的引入是有代價的,一方面,某個函數的能擴展的副本數量/會話數量,會受到存儲能被多少函數實例并發訪問的限制,另外一方面,訪問持久化存儲/通過網絡訪問外部存儲都會引入額外的開銷。函數計算通過 Session 機制的引入,以一種更簡單的方式支持了該類應用在 Serverless 平臺的運行。
MCP 協議通過標準化的方式,將外部數據源和 LLM 進行了連接,從而 LLM 可以從外部數據源獲取數據,也可以對外部的內容產生作用。在之前的文章中,我們介紹了 MCP SSE 親和的實現,在這篇文章中,我們跟隨社區的升級腳步,將 MCP SSE 協議升級為 MCP Streamable 協議,并在函數計算平臺上,通過對應親和類型的支持,讓最新的 MCP Server 也可以運行在 Serverless 平臺之上。
概念介紹
函數計算:函數計算是事件驅動的全托管計算服務。使用函數計算,您無需采購與管理服務器等基礎設施,只需編寫并上傳代碼或鏡像。函數計算為您準備好計算資源,彈性地、可靠地運行任務,并提供日志查詢、性能監控和報警等功能。
MCP:作為開放標準協議,為 AI 應用構建了通用化上下文交互框架。可以將 MCP 想象成 AI 應用程序的 USB-C 接口。就像 USB-C 為設備連接各種外設和配件提供了標準化方式一樣,MCP 為 AI 模型連接不同的數據源和工具提供了標準化方式。
MCP 的三種 Transport:
- Stdio: Client 和 Server 部署在同一臺機器上,通過標準輸入、輸出傳輸信息。
- MCP SSE: MCP 的 SSE(Server-Sent Events)傳輸方式是一種基于 HTTP 的單向通信協議,允許服務器通過事件流向客戶端推送數據,但需要維護 HTTP POST 和 SSE 兩個端點。
- MCP Streamable HTTP: MCP 的 Streamable HTTP 傳輸方式則是一種更高效的替代方案,它利用標準的 HTTP POST 和 GET 請求來處理多個客戶端連接,旨在解決 SSE 在遠程傳輸中的限制并提供更低的延遲和更好的并發性能。
為什么你的 MCP 服務應該升級到MCP Streamable HTTP 協議
HTTP+SSE 的傳輸方式存在缺陷
1. 不支持重新連接/恢復: 當 SSE 連接斷開時,所有會話狀態都會丟失,需要客戶端重新建立連接并初始化整個會話。例如,正在執行的大文檔分析任務可能會因為不穩定的 WiFi 而完全中斷,迫使用戶重新開始整個過程。
2. 服務器必須保持長連接: 服務器必須為每個客戶端維護一個長時間的 SSE 連接,當大量用戶并發時,這會導致資源消耗顯著增加。當服務器需要重啟或擴展時,所有連接都會中斷,這對用戶體驗和系統可靠性產生負面影響。
3. 服務器消息只能通過 SSE 傳輸:即使對于簡單的請求-響應交互,服務器也必須通過 SSE 通道返回信息,這會帶來不必要的復雜性和開銷。由于需要維護長時間的 SSE 連接。
4. 基礎設施兼容性限制 許多現有的網絡基礎設施,如 CDN、負載均衡器和 API 網關,可能無法正確處理長壽命的 SSE 連接。企業防火墻可能會強制關閉超時連接,導致服務不穩定。
Streamable HTTP 引入關鍵改進
1. 統一端點:移除專用的 /sse 和/message 端點,允許所有通信通過單一端點進行(目前在官方 SDK 中實現為 /mcp)。
-
按需流式傳輸:服務器可以靈活選擇返回標準的 HTTP 響應或將連接升級為 SSE 流。
-
靈活初始化:客戶端可以通過一個空的 GET 請求主動初始化 SSE 流。
-
會話可恢復:Streamable HTTP 協議中,只要客戶端沒有顯式刪除 Session 或者服務端定期清理掉了 Session,因為連接斷開的 Session 都是可以繼續使用的。
從一些實驗的對比中,可以看到:
- 在連接數上, Streamable HTTP 方案的 TCP 連接數明顯低于 HTTP + SSE 方案。
- 在不同并發用戶數下的請求成功率測試中,Streamable HTTP 的成功率顯著高于 HTTP + SSE 方案。
- 在性能上,Streamable HTTP 在響應時間方面具有明顯優勢,Streamable HTTP 的平均響應時間更短,響應時間波動較小,隨并發用戶數增加,響應時間增長更平,而 HTTP + SSE 的平均響應時間更長,在高并發場景下響應時間波動較大。因此,鑒于 MCP Streamable HTTP 服務的各項改進,更推薦將 MCP 服務升級到 Streamable HTTP 傳輸。
兩者更詳細的對比如下:

MCP Streamable HTTP 協議傳輸解析
客戶端主動發送消息到服務端
MCP SSE
在 SSE 方式下,Client 向 Server 發送請求通過/message 端點實現,每個請求是一個異步的 HTTP 請求,如果 MCP Server 接收該請求,則在響應中返回 202 狀態碼,后續的請求處理結果則會通過 Client 和 Server 維持的 SSE 長鏈接返回。

在該方式下,請求中會攜帶 id 信息,在后續 SSE 的響應中,針對同一個請求的 Response,id 設置為相同的值,client 就可以知道響應是針對哪個請求返回的(json-rpc 的約定)。
# client發送給server的請求
POST /messages/?session_id=706c5bb094fe43c89a6cb33fb96f470d HTTP/1.1
host: 127.0.0.1:8000
connection: keep-alive
Accept: text/event-stream
content-type: application/json
accept-language: *
sec-fetch-mode: cors
user-agent: node
accept-encoding: gzip, deflate
content-length: 8
{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{"_meta":{"progressToken":1}}}
# server的異步返回
HTTP/1.1 202 Accepted
date: Thu, 31 Jul 2025 07:50:51 GMT
server: uvicorn
content-length: 8
# sse的返回結果
event: message
data: {"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"calculate_bmi","description":"Calculate BMI given weight in kg and height in meters","inputSchema":{"properties":{"weight_kg":{"title":"Weight Kg","type":"number"},"height_m":{"title":"Height M","type":"number"}},"required":["weight_kg","height_m"],"title":"calculate_bmiArguments","type":"object"},"outputSchema":{"properties":{"result":{"title":"Result","type":"number"}},"required":["result"],"title":"calculate_bmiOutput","type":"object"}},{"name":"fetch_weather","description":"Fetch current weather for a city","inputSchema":{"properties":{"city":{"title":"City","type":"string"}},"required":["city"],"title":"fetch_weatherArguments","type":"object"},"outputSchema":{"properties":{"result":{"title":"Result","type":"string"}},"required":["result"],"title":"fetch_weatherOutput","type":"object"}}]}}
MCP Streamable HTTP
根據協議的約定,可以有如下兩種工作的流程。
- 同步返回結果:

- 通過 SSE 返回調用結果:

區別
MCP SSE 中 Client 和 Server 始終要保持一個長鏈接,請求通過新的短連接發起,通過 SSE 長鏈接返回調用結果。而在 MCP Streamable HTTP 中,針對處理速度比較快或者不能分批返回的調用,Server 可以同步在響應中返回調用結果,針對處理速度比較慢可以分批返回的結果,Server 可以將鏈接升級為 SSE 連接,將調用結果分批返回(比如其他大語言模型的輸出)。在對應的請求處理結束后,與 MCP SSE 仍然保持著 SSE 連接用于后續請求的結果返回不同,Streamable HTTP 會在對應的請求處理結果都通過對應的 SSE 連接返回后,關閉其使用的 SSE 連接,新的請求需要發起新的 SSE 連接而不能復用之前的 SSE 連接。
服務端消息推送機制
MCP SSE
在 SSE 方式下,由于 Client 和 Server 維持著 SSE 的長鏈接,因此,Server 到 Client 的 Notifications 都可以通過這條 SSE 鏈接發送。
MCP Streamable HTTP
在 MCP Streamable HTTP 下,Server 如果要發送消息到 Client,是沒有辦法實現的,因此,協議在/mcp(也可以是自定義的其他路徑上)支持了 GET 請求,用于建立 Client 到 Server 的一條 SSE 的長鏈接。

同時,如果在 GET 請求中攜帶了 Last-Event-ID 頭,則表明該 SSE 連接是針對前述客戶端請求的錯誤回復,MCP Server 可以在該 SSE 流上繼續傳輸之前沒有傳輸完成的消息,實現錯誤回復。
會話管理
MCP SSE
在 MCP SSE 的官方協議說明中,并沒有看到關于 Session 說明,在其他的三方文檔和 SDK 的實現中,可以看到有關的約定。
會話管理:
每個 SSE 連接都有唯一的會話標識,在 Message 請求中會包含該會話標識:
-
客戶端發起 SSE 連接;
-
服務端通過 Endpoint URL 消息,發送 SessionID 信息;
-
客戶短通過 Endpoint URL 發送后續的消息。
抓包的結果也和有關 SDK 的說明吻合:
# 客戶端發起SSE連接
GET /sse HTTP/1.1
host: 127.0.0.1:8000
connection: keep-alive
Accept: text/event-stream
accept-language: *
sec-fetch-mode: cors
user-agent: node
pragma: no-cache
cache-control: no-cache
accept-encoding: gzip, deflate
# Server返回結果,異步返回endpoint信息
HTTP/1.1 200 OK
date: Thu, 31 Jul 2025 08:51:27 GMT
server: uvicorn
cache-control: no-store
connection: keep-alive
x-accel-buffering: no
content-type: text/event-stream; charset=utf-8
Transfer-Encoding: chunked
# SSE返回Endpoint
event: endpoint
data: /messages/?session_id=c6cf551d4d5a4594961b18a8d74998b7
# 客戶端發送initialized通知
POST /messages/?session_id=c6cf551d4d5a4594961b18a8d74998b7 HTTP/1.1
host: 127.0.0.1:8000
connection: keep-alive
Accept: text/event-stream
content-type: application/json
accept-language: *
sec-fetch-mode: cors
user-agent: node
accept-encoding: gzip, deflate
content-length: 222
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{"sampling":{},"elicitation":{},"roots":{"listChanged":true}},"clientInfo":{"name":"mcp-inspector","version":"0.16.2"}}}
# Server返回initialized響應
HTTP/1.1 202 Accepted
date: Thu, 31 Jul 2025 08:51:27 GMT
server: uvicorn
content-length: 8
# Client發起后續請求
POST /messages/?session_id=c6cf551d4d5a4594961b18a8d74998b7 HTTP/1.1
host: 127.0.0.1:8000
connection: keep-alive
Accept: text/event-stream
content-type: application/json
accept-language: *
sec-fetch-mode: cors
user-agent: node
accept-encoding: gzip, deflate
content-length: 222
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{"sampling":{},"elicitation":{},"roots":{"listChanged":true}},"clientInfo":{"name":"mcp-inspector","version":"0.16.2"}}}
#其他的忽略
MCP Streamable HTTP
一個 MCP “會話”(session)是指客戶端與服務器之間映射關系,通過 initialize 階段發起。一個支持 Session 管理的 MCP 服務需要滿足:
-
使用Streamable HTTP 傳輸的服務器在初始化時分配一個會話 ID,將其包含 InitializeResult 的 HTTP 響應的頭部字段 Mcp-Session-Id 中。
- 會話 ID 應該是全局唯一且密碼學安全的(例如:安全生成的 UUID、JWT 或加密哈希值)。
- 會話 ID 必須僅包含可見 ASCII 字符(范圍從 0x21 到 0x7E)。
-
如果服務器在初始化過程中返回了 Mcp-Session-Id,則使用 Streamable HTTP 傳輸的客戶端必須在所有后續的 HTTP 請求中包含該 Mcp-Session-Id 頭字段。
- 支持會話的 MCP 服務器應該對缺少 Mcp-Session-Id 頭字段(除初始化請求外)的請求返回 HTTP 400 Bad Request。
-
服務器可以在任意時間終止會話,之后它必須對包含該會話 ID 的請求返回 HTTP 404 Not Found。
-
當客戶端收到一個包含 Mcp-Session-Id 的請求返回 HTTP 404 時,它必須通過發送一個新的不帶會話 ID 的 InitializeRequest 來啟動一個新會話。
-
當客戶端不再需要某個特定會話時(例如用戶正在退出客戶端應用),它應該向 MCP 端點發送一個帶有 Mcp-Session-Id 頭字段的 HTTP DELETE 請求,以顯式終止該會話。
- 服務器可以對該請求返回 HTTP 405 Method Not Allowed,表示服務器不允許客戶端主動終止會話。
兼容性
服務端:
服務端如果要保持向后兼容,則必須同時支持兩種通信方式:
- POST+SSE:需要有兩個端點,/sse 和/messge,分別支持 SSE 和 POST 請求
- Streamable Http:一個新的端點/mcp,支持新版通信方式。
也就是說,服務端要有三個端點,兩種通信方式互相獨立同時存在。官方不建議將兩者融合在一起。
客戶端:
客戶端可以直接嘗試將 InitializeRequest POST 到服務器 URL。
- 如果成功,客戶端可以假定這是支持新 Streamable HTTP 傳輸的服務器。
- 如果失敗且服務端返回 HTTP 4xx 狀態代碼,則向服務器 URL 發出 GET 請求,期望這將打開 SSE 流并返回 endpont 事件(舊版通信方式中的一個事件)作為第一個事件。當 endpoint 事件到達時,客戶端可以假定這是運行舊 HTTP+SSE 傳輸的服務器,并應將該傳輸用于所有后續通信。
整體的流程圖

FC MCP Streamable HTTP 親和機制
FC 為 MCP Streamable HTTP 單獨增加了一種親和類型,通過配置該親和類型,如果函數運行的是 MCP Streamable HTTP 傳輸的 Server,同一個 Session 的請求都會被轉發到會話所屬的函數實例上。
會話管理
函數計算作為集調度、計算托管、免運維等特性于一身的 Serverless 服務,可將函數計算核心組件抽象為三部分:
1. Gateway:網關層,用戶流量入口,負責接收用戶請求、鑒權、流控等功能。
2. Scheduler:調度引擎層,負責將用戶的請求調度到合適的節點和實例。
3. VMS:資源層,函數執行環境。
根據 Session 階段的不同,將 Session 的生命周期分為三部分:會話初始化、會話中以及會話結束三部分分別介紹函數計算在三個階段如何實現的會話管理。
會話初始化

-
Client 根據協議的約定,通過 Initialize 請求,發起 MCP 會話的初始化,網關節點權限校驗通過后轉發至調度模塊 Scheduler。
-
調度模塊根據特定標識識別出請求類型為 MCP Streamable HTTP 時,將調度到一臺可用實例。
-
當請求和實例綁定時,實例將啟動用戶代碼。
-
用戶代碼啟動完成后,會將會話信息通過響應的 Mcp-Session-Id 頭部返回。
-
在 response 返回經過 Gateway 網關層時,網關層將攔截 Mcp Initialize請求的首個回包,解析 SessionID 信息,并將 SessionID 和實例的映射關系持久化到 DB。
整體流程和 MCP SSE 親和的會話初始化階段相同,區別是提取會話標識的方式不同。
數據鏈路(會話中)

1. Client 完成 MCP Initialize 請求后,將發起 MCP 的后續請求,由于函數計算網關節點無狀態, Message 請求將打散到多個網關節點。
2. 當 Gateway 收到 MCP 請求,將檢查網關節點 cache 中是否存在 MCP 請求攜帶的 SessionID 親和信息,如果 cache 中無記錄,將回源到 DB 獲取相關數據。
3. Gateway 通過 cache 或 DB 拿到 SessionID 和實例的綁定關系時,將攜帶相關信息轉發至調度模塊。
4. 調度模塊根據 SessionID 信息,根據歷史的會話狀態,將請求定向調度到特定實例。
5. 后續請求被正確轉發到對應的實例,MCP Server 返回 SSE 數據或者是同步的 HTTP 響應。
整體流程和 SSE 是類似的,區別是 MCP Streamable HTTP 中,不區分 Message 消息和管控消息。
會話結束
由于 MCP 本身協議的約定,在 MCP SSE 傳輸方式下,SSE 連接斷開就標識著會話的結束。但是在 MCP Streamable HTTP 場景下,會話在被客戶端顯示 DELETE 之后,才會結束,因此有如下的會話結束的鏈路。

鏈路和會話初始化是類似的,區別是服務端返回之后,函數計算網關會更新 DB 中的會話狀態,標識會話已結束。
同時,MCP Streamable HTTP 還在協議層的生命周期的約定的基礎上,增加了其他的親和生命周期約束,包括 SessionTTL 和 SessionIdleTimeout 機制。
SessionTTL:限制 Session 的最大生命周期,TTL 之前,如果客戶端沒有發起 DELETE 請求結束會話,函數計算調度層會清理過期的會話數據,釋放 Session 占用的相關資源。
SessionIdleTimeout:限制 Session 的空閑時間,超過 IdleTimeout 之后,如果客戶端沒有發起 DELETE 請求結束會話,函數計算調度層會清理過期的會話數據,釋放 Session 占用的相關資源。
通過會話層的 DELETE 結束約定以及平臺側的生命周期管理機制,函數計算在 MCP Streamable HTTP 場景下,提供了完善的 MCP Session 的生命周期管理。
Session 配額
引入 Session Concurrency 策略,即結合函數實例的并發度配置,限制每個實例最多綁定 n 個 Session。客戶需結合實際業務場景需求配置合理的限制項:
- 親和模式場景僅限制實例最大并發 Session 數,單實例下所有 session 并發請求數最大 200。

優雅升級/輪轉
在 MCP 場景下,數據請求從請求級無狀態變為會話級綁定,在 UpdateFunction 后,如果存量 Session 關聯的請求路由到新實例,則新增無法識別到 SessionID 信息,返回錯誤。為解決這類問題,函數計算優雅更新能力從無狀態請求級別升級至有狀態 Session 級別,在用戶更新函數后,存量 Session 關聯的請求仍路由到舊實例,新建 Session 請求路由至新實例,優雅實現 MCP 親和場景下的升級需求。

演示
1. 創建 [ 1] 一個 Web 函數,親和類型選擇 MCP Streamable HTTP 親和;

-
函數創建完成之后,選擇觸發器,配置 HTTP 的訪問方式為 Bearer,為該函數的訪問入口配置安全措施;
-
本地啟動 Mcp Inspector,將 Bearer Token 信息和觸發器的地址信息拼接 MCP 的服務端點,填入 Mcp Inspector 的對應配置選項中。(詳情可參考官網:https://modelcontextprotocol.io/docs/tools/inspector)

點擊 Connect 之后,發起會話,后續就可以使用 MCP Streamable HTTP 提供的服務了。
總結
函數計算跟隨 MCP 社區的動態,在 MCP SSE 親和之后,推出了 MCP Streamable HTTP 親和,讓廣大開發者可以將自己的服務升級到 MCP Streamable HTTP 傳輸,并結合 Bearer 認證,即獲得性能上的提升,也更安全的暴露自己的服務。
相關鏈接:
[1] 創建
https://fcnext.console.aliyun.com/cn-hangzhou/functions/create?type=web
浙公網安備 33010602011771號