如果 MCP 變成 Stateless,那購物車放哪裡?
瀏覽器 agent 已經開了 12 個頁籤,下一次 tool call 怎麼知道該接哪個 browser context?一個做到一半的 workspace,又怎麼在下一個 request 繼續?
這幾個問題比「Stateless 比 Stateful 更好擴展」更值得先弄懂。因為只要把 Stateless 誤解成「Server 不能記住任何東西」,後面的 Serverless、Load Balancing、Failover,甚至 MCP Gateway 都會一起理解歪掉。
MCP 在 2026-07-28 做的事,是拿掉 protocol-level session。initialize / initialized 握手與 Mcp-Session-Id 離開新協議核心,每一個 Request 改成攜帶自己需要的 protocol context。這讓 Request 不必回到建立 Session 的那一台 Server。[1]
如果 client 想在正式呼叫前先看 server 的 capabilities,可以選擇呼叫 server/discover;它不是 initialize 的新替代 handshake,也不是 modern request 的必經步驟。一般 modern request 本身已帶著完成這次呼叫所需的 protocol context。[1]
但應用程式仍然可以保存狀態。
這篇要處理的就是這條邊界。
版本範圍:本文以 MCP
2026-07-28為準,最後核對日期為 2026-08-18。舊版 Client / Server 的 compatibility 與 migration 留到 Part 03。
先把四種常被混在一起的 State 拆開
談 Stateful / Stateless 時,第一個麻煩通常出在用詞:大家嘴裡的「State」根本不是同一件事。
可以先分成四層:
| 層 | 例子 | 2026-07-28 後怎麼處理 |
|---|---|---|
| Protocol context | protocol version、client info、capabilities | 隨 Request 攜帶,不再靠 protocol session 保存 |
| Application / workflow state | basket_id、browser_id、workspace_id | 可用 explicit state handle 傳遞/定位,真實狀態由應用程式後端保存 |
| Domain data | Google Sheet、CRM record、issue、invoice、database row | 繼續留在原本的資料真實來源(source of truth) |
| Identity / authorization | 使用者、token、principal、permission | 和 Handle 分開判斷,需要時每次 Call 重新驗證 |
這四層一拆開,Stateless MCP 就沒有那麼玄。
協議不再替你維持一張看不見的「這個 Client 現在是哪個 Session」表。Application 如果需要跨 Request 記住事情,就自己把那個狀態變成可指向、可傳遞的東西。

Figure 1-1|Stateless 拿掉的是 protocol session。Application state、domain data 與 authorization 仍然存在,只是責任邊界變得更明確。
2026-07-28 到底拿掉了什麼?
先看舊模式。
在 2025-11-25 的 Streamable HTTP 模式下,Client 會先做 initialize,Server 可以建立一個 Mcp-Session-Id。後面的 Requests 帶著這個 Session ID 回來。[5]
如果 Server 把很多東西掛在這個 Session 上,例如:
- 這個 Client 已經初始化過哪些 Capability
- 現在的 Browser Context 是哪一個
- 目前購物車裡有什麼
- 正在編輯哪個 Workspace
- 某個中間流程跑到哪一步
那 Load Balancer 就會開始有壓力。
因為下一個 Request 如果跑到另一台完全不知道這個 Session 的 Instance,事情就斷了。
常見處理方式有兩種。
第一種是 sticky routing,同一個 Session 一直送回原本那台 Instance。
第二種是把 Session State 放到共享儲存,例如 Redis 或其他 Session Store,讓所有 Instance 都讀得到。
這兩種都能做,只是它們讓 protocol session 開始滲進 deployment architecture。
2026-07-28 把這個 coupling 拿掉。現在每個 JSON-RPC Message 以獨立 HTTP POST 為基本單位,Request 帶著自己的 protocol version 與 client metadata,不再要求 Protocol Session。[1][3]
因此,從 MCP Protocol 本身 的角度,下一個 Request 可以落到另一台 Instance。
這裡要特別把一句話框起來:
「不再需要 shared protocol-session store」和「Application 不再需要 shared state」是兩件不同的事。
假設你的工具真的在維護一個多人共用 Workspace,那個 Workspace 的資料還是要存。假設你有 Idempotency Record、Job Queue、Database Transaction 或 Lock,那些基礎設施也不會因為 MCP Stateless 就蒸發。
協議少背了一個責任;業務真正需要的記憶仍由應用程式保存。
Explicit State Handle:把隱藏的 Session State 變成工具資料
MCP 官方在 SEP-2567 裡給了一個很實用的模式:Explicit State Handle。[2]
假設你有一個購物流程。
舊做法可能是:
Session abc123
└── basket = [shoe, sock]
後面的 add_item 不需要告訴 Server 自己操作哪個 basket,因為 Server 默認「這個 Session 的 basket」。
新的做法會比較像:
create_basket()
→ basket_id = bsk_a1b2c3
add_item(
basket_id = "bsk_a1b2c3",
sku = "shoe"
)
basket_id 就是一個普通 Tool Result 裡的欄位,之後再當普通 Tool Argument 傳回去。
它不是 MCP 新增的 handles/* RPC,也沒有特殊的 Handle Type。對 Protocol 來說,它就是一段 Tool Data。[2]
這個差別看起來很小,實際上很有用。
同一個 Agent 可以同時持有多種 State Scope
假設一個 Parent Agent 開了三個 Subagents 幫忙買東西。
三個 Subagents 應該共用同一個 Shopping Basket,但每個 Subagent 又要有自己的 Browser Context。
只有一個 Session Scope 時,這件事很尷尬:
- 共用 Session,Basket 對了,但 Browser State 可能互相踩掉
- 各自 Session,Browser State 對了,但 Basket 又被切成三份
Explicit Handle 可以直接表達:
shared basket_id
browser_id_A
browser_id_B
browser_id_C
State 的共享邊界不再被一個 transport session 強迫決定。Orchestrator 可以按資料本身決定哪些要 share,哪些要 isolate。[2]
這也是 Stateless MCP 不只影響擴展性的地方。
它把一部分原本藏在 Transport 裡的狀態,逼回 Application Design 裡。
Handle 後面的 State 存在哪裡?
Handle 只是地址,不是房子。
basket_id = bsk_a1b2c3 本身通常不會裝下整個購物車。Server 收到這個 ID 之後,還是要到自己的應用程式後端找出真正資料。
那個 Backend 可以是:
- relational database
- key-value store
- object store
- Durable Object
- workflow engine
- application service 本身管理的 durable resource
MCP 不替你指定其中一種。
這裡也不要把「External State Store」理解成新規範要求。SEP-2567 明確把 Handle 定義成 Tool Design Pattern,而不是新的 Protocol Primitive。Server 要怎麼存真正的狀態,是應用程式架構的問題。[2]
另外有一條安全邊界很容易漏掉:
Handle 不能自動等於 Authorization。
如果 Server 有登入與權限模型,就不應該因為 Request 知道一個 basket_id,就直接假設它可以操作那個 Basket。官方 guidance 是在每次 Call 重新驗證 (handle, auth_context)。[2]
這和一般 Web API 很像。知道 /orders/12345 不代表你有權讀 Order 12345。
Cloud Architecture 為什麼因此變簡單?
把 Protocol Session 拿掉後,Remote MCP Server 的 deployment model 會靠近一般 stateless HTTP service。
以前如果 Session 綁 Instance:
Client
↓
Load Balancer
↓ sticky route
MCP Server A
↓
Protocol Session State
Server A 掛掉時,Failover 不只是「找另一台 Server」。另一台還得知道剛剛那個 Session 發生過什麼。
或者你得改成:
MCP Server A ─┐
MCP Server B ─┼→ Shared Session Store
MCP Server C ─┘
2026-07-28 之後,Protocol 層可以變成:
Client
↓
Round-robin Load Balancer
↓
MCP Server A / B / C
任何 instance 都可以處理新的 request。應用程式如果真的需要 durable state,再讓各 instance 去讀同一個應用程式後端。[1][3]

Figure 1-2|新的 MCP Protocol 不再要求 Sticky Session 或 Shared Protocol Session Store。應用程式後端是否共享,取決於你的業務狀態,而不是 Protocol 強迫。
這讓幾件事變得比較普通:
- Round-robin load balancing
- Instance replacement
- Rolling deployment
- Autoscaling
- Serverless / edge hosting
- Failover
Netlify 在 2026-07-28 的官方文章裡直接把新 MCP Server 描述成 ordinary HTTP workload,重點也是不再需要圍著 Session Management 設計 hosting。[4]
但這裡還是要留一條界線。
Stateless MCP 不等於 Serverless MCP。
Serverless 是託管/執行模式。Stateless 是協議屬性。
你完全可以把 Stateless MCP 跑在長駐 VM、Kubernetes、Container Service,也可以跑在 Function / Worker 類平台。Stateless 只是讓後者不必先解決 Protocol Session Affinity,所以適配得更自然。
一個 Google Sheets MCP 的例子:資料到底存哪?
假設有一個很簡單的 Tool:
append_row(sheet_id, values)
Agent 要求 MCP Server 幫忙往 Google Sheet 新增一列。
一個 Serverless 部署可以長這樣:
Agent / MCP Client
↓
MCP Request
↓
Serverless MCP Handler
↓
Google Sheets API
↓
Google Sheet
這個例子裡,至少有三種完全不同的「資料」:
1. 這一次 MCP Request
它在 Request Lifecycle 裡存在。Handler 處理完就可以消失。
2. Google Sheet 裡的資料
它真正存放在 Google Sheets。下一次 Serverless Instance 換了一台,Sheet 裡那列資料還是在。
3. 如果流程本身還有跨 Call State
例如你不是單純 append_row,而是建立了一個「尚未提交的批次匯入工作區」。Server 可以回傳:
workspace_id = ws_7f29
之後 Tool Call 再把 workspace_id 傳回來,而 ws_7f29 背後真正的資料放在 Database、Durable Object 或其他 Application Store。
因此,「MCP 連 Google Sheet,資料是不是存在 MCP?」這個問法本身就少了一層。
比較準確的問法是:
這筆資料是 protocol context、workflow state,還是業務資料?誰是它的 source of truth?
這個示意只在畫責任邊界;實際的 hosting 與 storage design 可以不同。
如果資料不想被記錄呢?Stateless 也不會替你自動解決
另一個常見誤會是:既然 Protocol Stateless,是不是代表資料「用完就沒了」?
不一定。
Stateless Protocol 只保證 Protocol 不需要依賴跨 Request 的隱藏 Session。以下這些地方仍然可能留下資料:
- Tool 背後的 Business System
- Application Database
- Log / Trace / Audit System
- Queue / Workflow Backend
- Explicit State Handle 指向的 Durable State
- Client 自己保存的 Chat / Tool Result
所以資料保留政策仍然要逐層定義。
如果一筆資料不應該被持久化,你要問的是:
- Tool 有沒有真的寫入 source of truth?
- 應用程式後端有沒有保存?
- Log / Trace 是否收到了 Payload?
- Handle 的 State 何時 Expire / Destroy?
- Client 是否保存 Tool Result?
「Stateless」不應被當成 Data Retention Policy 的替代品。
Enterprise Gateway 為什麼更容易做,但不是 MCP 規定
Stateless Core 還帶來另一個架構效果。
當 Request 不再需要 Session Affinity,而且重要 operation metadata 可以在 HTTP 邊界被看見,Load Balancer、Gateway、WAF、Rate Limiter 與 Observability tooling 就比較容易用既有 HTTP infrastructure 處理 MCP traffic。[1][3]
這會讓企業常見的 MCP Gateway / Registry / Control Plane pattern 更好落地,例如把:
- Identity
- Routing
- Rate Limit
- Policy
- Audit
- Registry / Discovery
- PII handling
集中在比較明確的 platform boundary。
不過這個 topology 不該被寫成 MCP 的標準架構。
MCP Spec 沒有要求「企業一定要有 Gateway」,也沒有因為 Stateless 就自動得到 Tenant Isolation、Authorization 或 Audit。
比較精確的說法是:
新 Wire Semantics 降低了 Gateway 對 Protocol Session 的 coupling,企業既有的 HTTP Control Plane 因此更容易理解與治理 MCP。
至於 Mcp-Method、Mcp-Name、cache hints、Trace Context 到底怎麼工作,Part 02 再拆。
實作時,先沿著這幾個邊界檢查
如果你現在有一個 Remote MCP Server,先不用急著換成 Worker 或 Function。
比較值得先沿著這些邊界檢查:
- Failover: 某台 instance 掛掉後,下一個 request 能不能由另一台接?不能的話,先找出依賴的是 protocol session,還是 application state。
- State identifier: 跨 tool call 的 state 有沒有明確 identifier?如果只存在某個 process memory 裡,failover 還是會斷。
- Handle storage: Handle 背後真正的資料在哪裡?
workspace_id有了,不代表 durability 問題自動解決。 - Authorisation boundary: Handle 和 authorization 有沒有分開?知道 ID 不應自動等於有權操作。
- Lifetime: State lifetime 誰定義?Browser context、basket、workspace、transaction 不一定該活一樣久。Expiry / cleanup 最好成為 tool contract 的一部分。
其中第二點尤其容易做出「假的 Stateless」。
HTTP Request 看起來沒有 Session ID,Application 卻把 current_workspace 偷放在某台 Instance 的 global memory。平常 Demo 完全正常,Autoscaling 或 Restart 一來,State 就跟著 Process 一起蒸發。
Protocol stateless 讓這種架構更容易落地,但 durability、lifetime 與 cleanup 仍由應用程式自己處理。
回到最初的問題:State 到底去哪了?
MCP 2026-07-28 把 State 的責任重新畫了一次。
Protocol 不再持有跨 request session。需要延續的 application state,可以用普通 tool data 表達成 explicit handle;真正資料交給應用程式後端;業務資料繼續待在原本的 source of truth;authorization 仍然是另一條獨立邊界。
這個改變帶來的好處,不只是「少一個 Session ID」。
它讓 Load Balancing、Failover、Autoscaling 與 Serverless Hosting 不必再先配合一個隱藏的 Protocol Session Scope。也讓 State 的 Sharing、Isolation、Lifetime 與 Authorization 變成 Application 必須明講的設計決策。
下一篇會接著處理另一個問題:
沒有長駐 Session 之後,MCP 怎麼做 Human-in-the-loop、多輪輸入、長時間工作、Gateway Routing、Caching 與 Tracing?
這時才會進到 MRTR、HTTP Headers、Tasks Extension 與 Trace Context。
參考資料
- Model Context Protocol, The 2026-07-28 Specification, 28 July 2026. https://blog.modelcontextprotocol.io/posts/2026-07-28/
- Model Context Protocol, SEP-2567: Sessionless MCP via Explicit State Handles. https://modelcontextprotocol.io/seps/2567-sessionless-mcp
- Model Context Protocol, Streamable HTTP: 2026-07-28 Specification. https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http
- Netlify, MCP goes stateless and extensible, 28 July 2026. https://www.netlify.com/blog/mcp-goes-stateless-and-extensible/
- Model Context Protocol, The 2026-07-28 MCP Specification Release Candidate, 21 May 2026. https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/