MCP 進入 Stateless 時代:開始為大規模使用做準備

目錄

前陣子我寫了一篇關於 MCP 產品化的文章,當時我感覺 MCP 正在從單純的 Connector 慢慢往 Agent Infrastructure 的方向走。那篇文章比較著重在產品設計的邊界,像是工具太多會不會塞爆 LLM 的 context,還有哪些能力該留給後端自己處理。

結果 MCP 在 2026 年 7 月 28 日發布的 stable release,直接從更底層的地方動手了。

這次官方沒有加什麼很潮的新功能,他們直接重整了 session、請求流程、Server 跟 Client 的互動方式,連功能該怎麼擴充也一起調整。說白了,MCP 開始認真面對一件事,就是如果真的有很多產品在 production 使用,這套協議要怎麼穩定地活下去 😅

alt text

最關鍵的變化:Server 不用一直記得你是誰

舊版 MCP 有個 session 機制,Client 第一次連上 Server 時要先完成一段握手,拿到 Server 發的 Session ID 後,後面的每次請求都要帶上這個 ID。這就像你去餐廳拿到一個號碼牌,之後每次加點店家都靠這個號碼確認你是哪一桌。

在本機跑 demo 時這沒什麼問題,但當服務開始擴充,前面放了 load balancer 後面又同時跑著多個 Server instance,號碼牌就會變得超級麻煩。你得確保同一個人的請求一直被送回原本那台 Server,不然就是要另外準備 shared session store 讓每台機器都知道前面發生過什麼,光是維持這段關係就多了一堆跟工具本身無關的基礎設施成本 😭

新版乾脆把 protocol-level session 拿掉了。原本的 initializeinitialized 握手流程被移除,Mcp-Session-Id 也沒了。現在每個 request 都會自己帶上 protocolVersioncapabilities,像是一張已經把必要資料填好的訂單,任何一台 Server 都能接手處理。

Client 如果想先確認對方支援哪些版本與能力,可以呼叫 server/discover。這個方法是 Server 必須提供的,但 Client 不一定要先呼叫才能工作。這就是這次一直強調的 stateless。

不過 stateless 不代表產品不能保存狀態。購物車、瀏覽器操作或長流程如果真的需要延續,Server 還是可以回傳一個明確的 ID,下次呼叫時再把它當成普通參數傳回來。狀態沒有消失,只是從藏在協議底層的 session,變成產品自己管理的資料。

我個人覺得這個差異滿重要的。因為狀態被明確表示之後,我們才比較容易追蹤、測試,也比較知道是哪一段流程出了錯,而不是遇到 bug 時對著一個 Session ID 痛苦地通靈。 🫠

缺資料時,先說缺什麼,補完再送一次

但是拿掉長時間維持的 session 後,另一個問題也來了。

以前 Server 可以在執行途中主動敲 Client。假設工具跑到一半,突然需要使用者確認退款金額,Server 可以回頭要求 Client 處理。但在 stateless 的情況下,Server 不應該假設原本的 Client 還在線上等它。

所以新版加入了 Multi Round-Trip Requests,簡稱 MRTR。簡單來說,就是 Server 發現資料不夠時,先把還缺哪些東西當成結果回傳。Client 收集好資料後,再帶著前一次的狀態,重送原本的 request。

技術上,Server 會回傳 resultType: "input_required",並附上 inputRequestsrequestState。Client 補上 inputResponses 和原本的 requestState 後,再送一次。新版也要求所有 result 都明確帶上 resultType,讓 Client 知道接下來該怎麼處理。欄位名稱可以先不用背,真正重要的是互動不再依賴 Server 主動回頭敲 Client。每一步都有明確的 request 與 result,也比較容易追蹤和重試。

通知機制也走同一個方向。Client 透過 subscriptions/listen 主動等待自己在意的變化,Server 再從 response stream 傳回通知。原本的 GET、subscribe 與 unsubscribe 路徑則被移除。

真正麻煩的工作沒有消失,只是換地方

Stateless 解決的是協議層的 session,不是所有產品狀態;而 MRTR 也會帶來新的實作責任。

購物車、長任務或瀏覽器操作還是需要保存進度,只是現在由應用自己決定怎麼存、保存多久,以及誰有權限拿回來。如果這一層沒設計好,狀態只是從 MCP Server 的記憶體,搬到另一個比較難看的地方。

以退款為例,Client 補完資料後會重送原本的 request。Server 必須知道這是延續前一次操作,而不是再退一次款。requestState 提供了協議上的線索,但 idempotency、逾時、重複提交與失敗恢復,最後還是產品要處理。

Cache 也是一樣。工具清單可以共用,不代表所有結果都該跨使用者共用。企業系統還是要確認 tenant、權限與 cache scope,不然省下幾次查詢,卻換來資料邊界出錯,怎麼看都不划算。有了 trace context,也不代表系統會自動變得好除錯。Gateway、MCP Server 與後端服務都要正確傳遞資料,trace 才不會走到一半就斷掉。

協議把問題整理得更清楚了,但沒有替產品把問題做完。

核心變小,其他能力改用 Extensions 發展

另一個很關鍵的方向是 MCP 開始把核心協議與額外能力拆開。

如果什麼新功能都直接塞進核心,每個 Client 與 Server 最後都得一起承擔實作成本,規格只要改一次整個生態系就要跟著移動,這其實很不健康。所以新版改成透過 extensions 協商額外能力,讓它們能跟核心規格分開演進。例如 Tasks 原本是核心裡的實驗功能,現在被移到官方的 Tasks extension,MCP Apps 也透過 extension 讓 Server 可以提供互動式 UI。

這也讓我想到之前文章提過的 Skill,我當時覺得 MCP 負責交換 context 與能力,Skill 處理 workflow knowledge。現在確實有 Skills over MCP Working Group 跟 SEP 在推動兩者怎麼合作,不過這件事目前還在 review 跟持續討論,還不是已經定案的 extension。核心維持小一點讓其他能力各自發展,這種結構比較有機會撐住後面的變化。

有些舊功能也準備退場

這次 Roots、Sampling、Logging 跟舊的 HTTP+SSE 都被標記為 deprecated 了。

不過 deprecated 不等於明天就不能用,按照新的生命週期政策,一項功能進入 deprecated 後至少要經過 12 個月才有資格被移除。如果是既有系統,不用看到這個標記就立刻停機重寫,但如果是新專案,我就不太會再把架構壓在這些功能上了。

其實 Sampling 的退場滿能反映 MCP 現在的定位,以前 Server 可以請 Host 幫忙呼叫模型,現在官方更傾向讓應用層自己整合 LLM provider API,不再把模型推論也綁進核心協議裡面。MCP 的任務就是把能力接起來,不需要順便包辦整個 Agent runtime。

對產業的影響:競爭點會從「有沒有」變成「管不管得住」

前一階段大家展示 MCP,通常是在畫面上讓 Agent 成功呼叫一個 tool。只要能跑,就很容易被當成一個產品亮點。

但當 MCP 開始連到企業內部文件、CRM、訂單、金流與客服系統,企業在意的事情會完全不一樣。

他們不只會問能不能接,還會問哪些人可以用、不同部門的資料有沒有隔離、每次操作能不能稽核、Server 掛掉後能不能恢復,以及規格升級會不會讓舊 Client 一起壞掉。

這次更新沒有自動回答這些問題,但它開始補上 Gateway、routing、cache、tracing 與版本演進需要的結構。對我來說,這才是它比較可能進入企業環境的訊號。

我不覺得 MCP 會取代原本的 API。真正做事的仍然是後面的 API、資料庫與服務。MCP 比較像是逐漸成為 Agent 連接這些能力時的共通入口。

如果這個方向繼續走,未來產品之間的差異就不只是「支不支援 MCP」,而是誰能把權限、觀測、相容性與能力邊界一起管好。

支援協議會慢慢變成基本要求,怎麼營運它才是競爭力。

協議變成熟,不代表產品問題就消失

回頭來看,stateless 讓 Server 比較容易水平擴充,Extensions 讓功能可以分開演進,cache 跟 tracing 也補上了正式環境需要的能力。

但上一篇文章提到的產品問題其實都還在。協議不會替你決定該讓 Agent 看見多少 tools,也不會自動幫你設計能力邊界,Gateway 還是得負責控制哪些能力能被誰使用,複雜流程也可能比較適合包在 workflow 或 Agent-backed MCP Tool 後面。

說白了,MCP 現在比較知道該怎麼承載這些能力了,但產品還是要自己決定該讓 Agent 看見什麼。

現在需要急著升級嗎?

如果你手上有新專案,我會建議直接從支援 2026-07-28 的新版官方 SDK 開始。但如果是已經在 production 運作的 MCP Server,我反而不建議看到新版就無腦升上去,至少可以先檢查這幾件事:

  • 是否依賴 initializeMcp-Session-Id 保存狀態
  • 是否使用 Sampling、Roots 這些舊的 server-to-client 流程
  • 是否實作舊版 Tasks API
  • 是否依賴 resources/subscribe 或 SSE resumability
  • Client 是否能正確處理新的 resultType
  • Gateway 與權限層是否認得新的標準 header

其實舊 Client 跟舊 Server 不用在同一天全部換掉,先確認好 SDK 的版本協商與相容路徑再慢慢遷移,通常比一次砍掉重練安全很多。

之前我也還在觀望 MCP 會不會只是大家玩玩就丟的協議,但這次更新後,我感覺它真的能走得長遠了。它沒有突然變得更會思考,也沒有加上什麼會自己通靈的神奇功能。它做的是拿掉 session、整理 request 的生命週期,補上 routing、cache 跟 tracing,再把不一定每個人都需要的能力移到 Extensions。

下次再看到有產品說支援 MCP,我大概還會再多問幾句:Server 能不能水平擴充?不同使用者的權限怎麼隔離?

當大家開始認真面對這些問題,MCP 才算真的從「可以接工具」走進「可以長期承載產品」。有在碰 MCP 的朋友也歡迎在交流,分享一下你們升級時踩過的坑 🙌

參考資料