AI 知識
MCP 無狀態化,改變的是狀態責任邊界
MCP 2026-07-28 版本最容易被誤解的一句話,就是「協定變成無狀態」。
乍聽之下,這像是每一次工具呼叫都要從零開始。AI 不記得上一個動作,Server 也不知道 Client 是誰,所有需要多步驟的工作都會斷掉。
實際情況正好相反。這次改版不是禁止狀態,而是把狀態從隱含的連線與 transport session 中搬出來,要求系統明確回答:哪些資料需要跨呼叫保存、由誰保存、下一次請求要如何帶回,以及 Server 要怎麼驗證。
這是一個協定設計上的大轉彎,也會直接改變遠端 MCP Server 的部署、擴充、故障切換與安全邊界。
舊版 MCP 為什麼需要 Session
在先前的 Streamable HTTP 流程中,Client 會先送出 initialize,與 Server 交換 protocol version、能力與 Client 資訊。Server 可以回傳 Mcp-Session-Id,後續請求再帶著這個 ID 回來。
這個流程讓 Server 能把某些資訊保存在 session 裡。對單機或小型部署來說,它很直覺:只要看到同一個 session ID,就能找回同一段連線狀態。
問題會在系統開始橫向擴充時浮現。
假設一個 MCP Server 後面有五台 instance。第一個請求落到 A,session 狀態也在 A;第二個請求若被負載平衡器送到 B,B 就不一定知道前面發生了什麼。
常見解法有兩種:用 sticky routing 把同一個 Client 固定送回 A,或讓所有 instance 共用一個 session store。兩者都能工作,但會增加部署與故障處理的複雜度。
Sticky routing 讓流量分配不再完全自由;共享 session store 則增加額外依賴、延遲與一致性問題。如果 A 突然故障,系統還必須確認 session 狀態是否已經安全保存,否則 Client 可能只能重新開始。
新版把 Handshake 與 Session 拿掉
在 2026-07-28 版本裡,initialize/initialized handshake 與 Mcp-Session-Id 被移除。
原本在連線開始時交換一次的 protocol version、Client 資訊與能力,改成跟著每次請求傳遞。Client 若需要先查詢 Server 支援哪些版本與能力,可以呼叫新的 server/discover。
這使單一請求本身就帶有足夠資訊,任何可用的 Server instance 都能處理,不必先找到建立 session 的那一台機器。
對基礎設施來說,最直接的好處是普通 round-robin load balancing 變得可行。Server 可以更自由地擴充或替換 instance,單一 instance 故障也不必把協定層 session 一起帶走。
但這不代表系統會自動變快,也不代表所有 MCP 實作都不必修改。真正受影響的是那些把業務或工作狀態直接綁在 session 上的程式。
無狀態不等於沒有記憶
協定層無狀態,和應用程式是否保存狀態,是兩個不同問題。
HTTP 本身是無狀態協定,但網站仍然有購物車、登入狀態、訂單與長時間工作。做法不是要求 HTTP 自己記住所有事情,而是讓應用程式用 cookie、token、資料庫 ID 或其他明確識別碼找到需要的資料。
MCP 採用相同概念。
如果一個工具建立購物籃,可以回傳 basket_id;下一個工具呼叫要加入商品,就把同一個 basket_id 當成參數帶回。如果工具建立瀏覽器工作階段,可以回傳 browser_id。長時間工作則可以回傳 task handle,讓 Client 後續查詢或更新。
狀態沒有消失,只是不再藏在 transport session 裡。
這種顯式 handle 還有一個重要特性:模型看得到它。模型可以在不同工具之間傳遞 handle,也能在規劃下一步時理解某個 ID 代表哪一段工作。相較於完全隱藏在連線 metadata 裡的狀態,資料流反而更容易被追蹤與審查。
多輪互動改用 MRTR
有些 MCP 工具無法在一次請求內完成。例如 Server 執行到一半,需要 Client 確認是否刪除檔案,或要求補充一個欄位。
新版透過 Multi Round-Trip Requests 處理這種情況。Server 不必依賴長時間存在的 session 或任意發起推送,而是回傳 InputRequiredResult,列出需要 Client 補充的資料,並附帶 requestState。
Client 收集答案後,重新送出原始請求,同時帶回 inputResponses 與 requestState。因為完成下一步所需的資訊已經跟著 payload 回來,任何 Server instance 都能接手。
這裡最重要的安全提醒是:requestState 會經過 Client。
因此 Server 不能把它當成可信任的內部 session。TypeScript SDK 遷移文件明確建議對這段資料做完整性保護,並綁定使用者身分、原始方法、參數與有效期限。回到 Server 時必須先驗證,不能直接反序列化後照單全收。
無狀態化減少了一種隱含耦合,但不會自動消除安全責任。相反地,它要求安全邊界被更清楚地寫進資料流。
哪些實作可能需要修改
如果現有 MCP Server 只是接收一個請求、執行工具並回傳結果,而且沒有依賴 session 保存跨呼叫資訊,遷移範圍可能有限。
需要特別檢查的通常是以下幾類:
- 用
Mcp-Session-Id當成使用者或工作識別碼。 - 把權限、暫存資料或工具執行上下文存在 server memory,並假設後續請求一定回到同一台 instance。
- 依賴 Server 在 Client 沒有發起請求時主動推送互動。
- 把 session lifetime 當成資源清理或稽核的唯一依據。
- 直接信任由 Client 帶回的
requestState或其他狀態 handle。
這些情況不是把一個 header 刪掉就能完成。系統需要重新決定狀態的正式擁有者、儲存位置、生命週期與驗證規則。
相容性不等於所有人同一天切換
協定版本更新不代表所有 Client 與 Server 會在同一天升級。
官方 SDK 文件仍保留與 2025-11-25 及更早版本協商的路徑。新 Client 遇到只支援舊流程的 Server,可以回到 initialize handshake;需要 session 相依功能的系統,也可以繼續走舊版本相容模式。
因此,實務上的遷移重點不是假設整個生態已經同步,而是清楚測試兩端支援的 protocol version,以及新舊路徑是否具有一致的權限、錯誤處理與資料生命週期。
真正值得記住的改變
MCP 無狀態化最重要的不是少了一個 header,也不是 Server 再也不能記住任何事。
它真正拿掉的是「只要連線還在,狀態自然會被記住」這個隱含假設。
在新的模型裡,每個請求必須帶上理解它所需的協定資訊;需要跨呼叫的應用狀態,要透過明確 handle 或外部儲存管理;需要多輪互動時,狀態也必須能安全地往返與驗證。
這讓遠端 MCP Server 更容易放進一般雲端基礎設施,也讓狀態的擁有者與安全責任更難被藏起來。
如果一個系統拔掉 Session 後就完全不知道自己正在處理哪個使用者、哪個任務或哪份資料,問題可能不在無狀態協定,而在於原本的狀態設計從來沒有被明確定義。
查證摘要
- MCP
2026-07-28移除initialize/initializedhandshake、Mcp-Session-Id與協定層 session。 - 每次請求帶上 protocol version、Client 資訊與能力,
server/discover提供能力探索。 - 應用程式仍可用顯式 handle、資料庫或外部儲存保存跨呼叫狀態。
- Multi Round-Trip Requests 以
InputRequiredResult、inputResponses與requestState完成多輪互動。 requestState經 Client 往返,Server 必須視為不可信輸入並驗證。- 官方 SDK 仍提供舊版本協商與相容路徑,不代表所有既有實作同時失效。
參考資料
- MCP 官方:The 2026-07-28 MCP Specification Release Candidate
- MCP TypeScript SDK:Supporting protocol revision 2026-07-28
- MCP C# SDK:Stateless and stateful mode
- MCP Go SDK releases
