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

2. 通過 SSE 返回調(diào)用結(jié)果:

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

同時,如果在 GET 請求中攜帶了 Last-Event-ID 頭,則表明該 SSE 連接是針對前述客戶端請求的錯誤回復(fù),MCP Server 可以在該 SSE 流上繼續(xù)傳輸之前沒有傳輸完成的消息,實現(xiàn)錯誤回復(fù)。
會話管理
MCP SSE
在 MCP SSE 的官方協(xié)議說明中,并沒有看到關(guān)于 Session 說明,在其他的三方文檔和 SDK 的實現(xiàn)中,可以看到有關(guān)的約定。
會話管理:
每個 SSE 連接都有唯一的會話標(biāo)識,在 Message 請求中會包含該會話標(biāo)識:
1. 客戶端發(fā)起 SSE 連接;
2. 服務(wù)端通過 Endpoint URL 消息,發(fā)送 SessionID 信息;
3. 客戶短通過 Endpoint URL 發(fā)送后續(xù)的消息。
抓包的結(jié)果也和有關(guān) SDK 的說明吻合:
# 客戶端發(fā)起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返回結(jié)果,異步返回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
# 客戶端發(fā)送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響應(yīng)
HTTP/1.1 202 Accepted
date: Thu, 31 Jul 2025 08:51:27 GMT
server: uvicorn
content-length: 8
# Client發(fā)起后續(xù)請求
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)是指客戶端與服務(wù)器之間映射關(guān)系,通過 initialize 階段發(fā)起。一個支持 Session 管理的 MCP 服務(wù)需要滿足:
1. 使用Streamable HTTP 傳輸?shù)姆?wù)器在初始化時分配一個會話 ID,將其包含 InitializeResult 的 HTTP 響應(yīng)的頭部字段 Mcp-Session-Id 中。
- 會話 ID 應(yīng)該是全局唯一且密碼學(xué)安全的(例如:安全生成的 UUID、JWT 或加密哈希值)。
- 會話 ID 必須僅包含可見 ASCII 字符(范圍從 0x21 到 0x7E)。
2. 如果服務(wù)器在初始化過程中返回了 Mcp-Session-Id,則使用 Streamable HTTP 傳輸?shù)目蛻舳吮仨氃谒泻罄m(xù)的 HTTP 請求中包含該 Mcp-Session-Id 頭字段。
- 支持會話的 MCP 服務(wù)器應(yīng)該對缺少 Mcp-Session-Id 頭字段(除初始化請求外)的請求返回 HTTP 400 Bad Request。
3. 服務(wù)器可以在任意時間終止會話,之后它必須對包含該會話 ID 的請求返回 HTTP 404 Not Found。
4. 當(dāng)客戶端收到一個包含 Mcp-Session-Id 的請求返回 HTTP 404 時,它必須通過發(fā)送一個新的不帶會話 ID 的 InitializeRequest 來啟動一個新會話。
5. 當(dāng)客戶端不再需要某個特定會話時(例如用戶正在退出客戶端應(yīng)用),它應(yīng)該向 MCP 端點發(fā)送一個帶有 Mcp-Session-Id 頭字段的 HTTP DELETE 請求,以顯式終止該會話。
- 服務(wù)器可以對該請求返回 HTTP 405 Method Not Allowed,表示服務(wù)器不允許客戶端主動終止會話。
兼容性
服務(wù)端:服務(wù)端如果要保持向后兼容,則必須同時支持兩種通信方式:
- POST+SSE:需要有兩個端點,/sse 和/messge,分別支持 SSE 和 POST 請求
- Streamable Http:一個新的端點/mcp,支持新版通信方式。
也就是說,服務(wù)端要有三個端點,兩種通信方式互相獨立同時存在。官方不建議將兩者融合在一起。
客戶端:客戶端可以直接嘗試將 InitializeRequest POST 到服務(wù)器 URL。
- 如果成功,客戶端可以假定這是支持新 Streamable HTTP 傳輸?shù)姆?wù)器。
- 如果失敗且服務(wù)端返回 HTTP 4xx 狀態(tài)代碼,則向服務(wù)器 URL 發(fā)出 GET 請求,期望這將打開 SSE 流并返回 endpont 事件(舊版通信方式中的一個事件)作為第一個事件。當(dāng) endpoint 事件到達(dá)時,客戶端可以假定這是運行舊 HTTP+SSE 傳輸?shù)姆?wù)器,并應(yīng)將該傳輸用于所有后續(xù)通信。
整體的流程圖
圖片
FC MCP Streamable HTTP 親和機(jī)制
FC 為 MCP Streamable HTTP 單獨增加了一種親和類型,通過配置該親和類型,如果函數(shù)運行的是 MCP Streamable HTTP 傳輸?shù)?Server,同一個 Session 的請求都會被轉(zhuǎn)發(fā)到會話所屬的函數(shù)實例上。
會話管理
函數(shù)計算作為集調(diào)度、計算托管、免運維等特性于一身的 Serverless 服務(wù),可將函數(shù)計算核心組件抽象為三部分:
1. Gateway:網(wǎng)關(guān)層,用戶流量入口,負(fù)責(zé)接收用戶請求、鑒權(quán)、流控等功能。
2. Scheduler:調(diào)度引擎層,負(fù)責(zé)將用戶的請求調(diào)度到合適的節(jié)點和實例。
3. VMS:資源層,函數(shù)執(zhí)行環(huán)境。
根據(jù) Session 階段的不同,將 Session 的生命周期分為三部分:會話初始化、會話中以及會話結(jié)束三部分分別介紹函數(shù)計算在三個階段如何實現(xiàn)的會話管理。
會話初始化

1. Client 根據(jù)協(xié)議的約定,通過 Initialize 請求,發(fā)起 MCP 會話的初始化,網(wǎng)關(guān)節(jié)點權(quán)限校驗通過后轉(zhuǎn)發(fā)至調(diào)度模塊 Scheduler。
2. 調(diào)度模塊根據(jù)特定標(biāo)識識別出請求類型為 MCP Streamable HTTP 時,將調(diào)度到一臺可用實例。
3. 當(dāng)請求和實例綁定時,實例將啟動用戶代碼。
4. 用戶代碼啟動完成后,會將會話信息通過響應(yīng)的 Mcp-Session-Id 頭部返回。
5. 在 response 返回經(jīng)過 Gateway 網(wǎng)關(guān)層時,網(wǎng)關(guān)層將攔截 Mcp Initialize請求的首個回包,解析 SessionID 信息,并將 SessionID 和實例的映射關(guān)系持久化到 DB。
整體流程和 MCP SSE 親和的會話初始化階段相同,區(qū)別是提取會話標(biāo)識的方式不同。
數(shù)據(jù)鏈路(會話中)

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

鏈路和會話初始化是類似的,區(qū)別是服務(wù)端返回之后,函數(shù)計算網(wǎng)關(guān)會更新 DB 中的會話狀態(tài),標(biāo)識會話已結(jié)束。
同時,MCP Streamable HTTP 還在協(xié)議層的生命周期的約定的基礎(chǔ)上,增加了其他的親和生命周期約束,包括 SessionTTL 和 SessionIdleTimeout 機(jī)制。
SessionTTL:限制 Session 的最大生命周期,TTL 之前,如果客戶端沒有發(fā)起 DELETE 請求結(jié)束會話,函數(shù)計算調(diào)度層會清理過期的會話數(shù)據(jù),釋放 Session 占用的相關(guān)資源。
SessionIdleTimeout:限制 Session 的空閑時間,超過 IdleTimeout 之后,如果客戶端沒有發(fā)起 DELETE 請求結(jié)束會話,函數(shù)計算調(diào)度層會清理過期的會話數(shù)據(jù),釋放 Session 占用的相關(guān)資源。
通過會話層的 DELETE 結(jié)束約定以及平臺側(cè)的生命周期管理機(jī)制,函數(shù)計算在 MCP Streamable HTTP 場景下,提供了完善的 MCP Session 的生命周期管理。
Session 配額
引入 Session Concurrency 策略,即結(jié)合函數(shù)實例的并發(fā)度配置,限制每個實例最多綁定 n 個 Session??蛻粜杞Y(jié)合實際業(yè)務(wù)場景需求配置合理的限制項:
- 親和模式場景僅限制實例最大并發(fā) Session 數(shù),單實例下所有 session 并發(fā)請求數(shù)最大 200。
圖片
優(yōu)雅升級/輪轉(zhuǎn)
在 MCP 場景下,數(shù)據(jù)請求從請求級無狀態(tài)變?yōu)闀捈壗壎?,?UpdateFunction 后,如果存量 Session 關(guān)聯(lián)的請求路由到新實例,則新增無法識別到 SessionID 信息,返回錯誤。為解決這類問題,函數(shù)計算優(yōu)雅更新能力從無狀態(tài)請求級別升級至有狀態(tài) Session 級別,在用戶更新函數(shù)后,存量 Session 關(guān)聯(lián)的請求仍路由到舊實例,新建 Session 請求路由至新實例,優(yōu)雅實現(xiàn) MCP 親和場景下的升級需求。
圖片
演示
1. 創(chuàng)建[1]一個 Web 函數(shù),親和類型選擇 MCP Streamable HTTP 親和;
圖片
2. 函數(shù)創(chuàng)建完成之后,選擇觸發(fā)器,配置 HTTP 的訪問方式為 Bearer,為該函數(shù)的訪問入口配置安全措施;
3. 本地啟動 Mcp Inspector,將 Bearer Token 信息和觸發(fā)器的地址信息拼接 MCP 的服務(wù)端點,填入 Mcp Inspector 的對應(yīng)配置選項中。(詳情可參考官網(wǎng):https://modelcontextprotocol.io/docs/tools/inspector)
圖片
點擊 Connect 之后,發(fā)起會話,后續(xù)就可以使用 MCP Streamable HTTP 提供的服務(wù)了。
總結(jié)
函數(shù)計算跟隨 MCP 社區(qū)的動態(tài),在 MCP SSE 親和之后,推出了 MCP Streamable HTTP 親和,讓廣大開發(fā)者可以將自己的服務(wù)升級到 MCP Streamable HTTP 傳輸,并結(jié)合 Bearer 認(rèn)證,即獲得性能上的提升,也更安全的暴露自己的服務(wù)。
相關(guān)鏈接:
[1] 創(chuàng)建:https://fcnext.console.aliyun.com/cn-hangzhou/functions/create?type=web




























