返回資料庫
MCP

MCP Events:當訂閱變成無法撤銷的憑證

最後更新:2026年10月3日

核心重點

  • MCP Events 為代理新增了第三種喚醒觸發器 —— 除了排程任務與人類訊息之外,MCP 伺服器現在可以在連線應用程式發生變化時,向 ChatGPT 推送簽名的 webhook。
  • 訂閱的壽命超過建立它的存取權杖 —— ttlMs: null 會請求一個永不過期的訂閱,而用以識別訂閱的元組不含權杖、範圍與到期時間。
  • ChatGPT 支援 webhook 傳遞模式,但不支援草稿中的 terminated 撤銷信封 —— 僅存的撤銷訊號是一次失敗的重新整理,回傳 -32012 Forbidden。
  • 工作小組自己的成功準則 —— 提交一份 SEP —— 尚未交付 —— 章程表格仍顯示 "Ideating",負責人為 "TBD",且僅有 2026 年 3 月 24 日的一筆變更紀錄。
  • WorkOS 將訂閱界定為一份憑證 —— 一筆在某個使用者的存取權杖下建立的持久紀錄,即使權杖早已過期,它仍授權你的伺服器把該使用者的資料推送給代理。

在此之前,AI 代理的喚醒只有兩種原因:排程任務觸發,或人類輸入訊息。2026 年 9 月 29 日,OpenAI 在 DevDay 上宣布支援擬議的 MCP Events 規範,讓外掛能在連線應用程式中發生某件事時啟動自動化。官方文件描述了 MCP 伺服器如何向 ChatGPT 推送更新 —— 依頻道篩選的 message.created 事件,或依文件篩選的 comment.created 事件 —— 讓代理在錯誤報告送達或審閱留言發布時立即行動,而不是等你想起来才去問。在 Notion 擔任產品設計的 Nathan Baschez 於 10 月 3 日發文表示:「事件驅動觸發器是一件大事」,而他從未見過如此少的熱情。

本文梳理 MCP Events 實際上實作了什麼、其核心的憑證壽命缺口,以及生產級 MCP 伺服器在發送 webhook 前必須儲存與驗證的內容。本文承襲 MCP 2026-07-28: What the Stateless Protocol Means for B2B Agent Deployments 一文,該篇涵蓋了無狀態核心;此處聚焦事件驅動擴充,以及工作小組尚未定稿的訂閱生命週期問題。

ChatGPT 實際上實作了什麼

MCP Triggers and Events 工作小組章程僅列出一個進行中的工作項目:"SEP: Events in MCP v1 RFC",狀態 "Ideating",目標日期 "End April",負責人 "TBD"。章程只有一筆變更紀錄,日期為 2026-03-24:"Initial charter"。工作小組由 AWS 的 Clare Liguori 與 Anthropic 的 Peter Alexander 領導。

孵化儲存庫呈現了另一番景象。其中有一份標注 "Status: Draft proposal" 的設計草圖,作者 Peter Alexander,日期 2026-02-19。README 的措辭很直接:內容屬探索性質,「不代表 MCP 的官方規範或建議」。實作者已針對它提交實戰回報。但並不存在已提交的 SEP —— 也就是章程自己聲明的成功準則:「一份被接受的 SEP,定義觸發/回呼機制及其訂閱生命週期。」

ChatGPT 實作了這份未完成文件的一部分。OpenAI 的 MCP Events 指南要求 MCP 2.0、協定版本 2026-07-28,並支援草稿中的 webhook 傳遞與回呼驗證。輪詢、串流,以及草稿的 gap 與 terminated 控制通知皆不支援。最後這一點至關重要。

機制本身很直接。伺服器在 server/discover 回應中宣告 events 能力。使用者告訴 ChatGPT 要監測什麼以及如何回應。ChatGPT 呼叫 events/subscribe,附上事件名稱、篩選參數、回呼 URL 與簽名密鑰。伺服器以一次性挑戰驗證回呼,儲存訂閱,然後把符合條件的事件以簽名 webhook 推送出去。三個方法 —— events/list、events/subscribe、events/unsubscribe —— 與工具運行在同一個經過驗證的端點上。

訂閱是一份憑證

值得警惕的是草稿要求你的伺服器儲存什麼。正如 WorkOS 的分析所界定的:事件訂閱是一份憑證 —— 一筆在某個使用者的存取權杖下建立的持久紀錄,即使建立它的權杖早已過期,它仍授權你的 MCP 伺服器把該使用者的資料推送給代理。

把訂閱與授權這次呼叫的權杖比較。依 2026-07-28 授權規範,伺服器必須驗證存取權杖是專為它簽發的,授權必須包含在每個 HTTP 請求中,而無效或過期的權杖必須收到 401。壽命短、範圍窄、每個請求都重新檢查。訂閱則完全不同。設計草圖以元組 (principal, delivery.url, name, arguments) 作為 webhook 訂閱的鍵 —— principal 是伺服器為受驗證主體設定的規範識別碼。該元組不含權杖本身、其範圍或到期時間。而且壽命可以協商到永遠:ttlMs: null 請求一個不過期的訂閱,同意它的伺服器回傳 refreshBefore: null。

存取權杖 事件訂閱
壽命 短,固定到期 由你授予的 TTL 決定,乃至永不過期(ttlMs: null)
綁定到 你的伺服器作為受眾,外加範圍 (principal, url, name, arguments) —— 無權杖、範圍或到期時間
檢查 每個 HTTP 請求,過期回傳 401 訂閱時必須(MUST);之後「應該」(SHOULD)定期,但無間隔
終止於 權杖過期或授權伺服器撤銷 TTL 到期、用戶端退訂,或你的伺服器終止它

存取權杖會過期。它建立的訂閱卻持續遞送。

在 ChatGPT 中,撤銷是不對稱的

草稿對義務說得很清楚,對節奏卻含糊其詞。訂閱時,主體必須通過驗證與授權。遞送時:「伺服器應該(SHOULD)定期重新驗證權限。若使用者的存取遭撤銷(例如被移出 Slack 頻道),」伺服器便終止訂閱。OpenAI 的指南重申了同樣的義務:「在訂閱生命週期內重新檢查使用者存取,若存取遭撤銷則停止遞送。」

「定期」一詞在這句話裡承擔了太多。沒有間隔,沒有 MUST,背後也沒有一致性測試。

接著是訊號本身。在草稿中,每種傳遞模式都有自己的「停止」方式。對 webhook 而言,是一個簽名的 {"type":"terminated"} 信封,以 POST 傳送到回呼 URL。此後訂閱不復存在,若終止原因仍然成立,後續重新整理會回傳 -32012 Forbidden。這個信封就是協定告訴代理「已經停止,原因如下」的方式。它也是 ChatGPT 整合不支援的兩種控制通知之一。

傳遞模式 草稿如何說「停止」 在 ChatGPT 中
輪詢 下次輪詢出錯 模式不支援
推送串流 notifications/events/terminated 模式不支援
Webhook 簽名的 terminated 信封 POST 至回呼 模式支援,信封不支援
任何模式 下次重新整理失敗,回傳 -32012 Forbidden 僅存的訊號

在 ChatGPT 的整合中,僅存的撤銷訊號是一次失敗的重新整理。若使用者存取遭撤銷而你的伺服器停止了遞送,代理只會在訂閱 TTL 到期、重新整理失敗時才得知。若你授予了 ttlMs: null,代理永遠不會知情。

你的伺服器必須驗證什麼

草稿與 OpenAI 指南共同規定了一個真實的安全面。其中不可協商的部分:

  • 要求經過驗證的主體。 events/subscribe 與 events/unsubscribe 必須以經過驗證的主體呼叫;授權失敗的呼叫回傳 -32012 Forbidden。
  • 在首次真實遞送之前驗證端點。 HMAC 防偽造,不防洪水。在確認端點接收遞送的意願之前 —— 透過挑戰握手、允許清單或事先帶外驗證 —— 伺服器不得開始向回呼 URL 遞送。
  • 在遞送時執行 SSRF 檢查。 回呼 URL 必須使用 HTTPS。每次連線時皆須解析並驗證目標位址,阻擋私有與本地網段,絕不跟隨重新導向,驗證請求與遞送一視同仁。
  • 保持酬載最小。 事件酬載與工具結果具有同樣的注入風險。OpenAI 指南要求發送摘要並提供一個讀取工具以取得完整紀錄,把使用者撰寫的文字當作資料處理,不得在酬載內加入指示模型如何行動的指令。
  • 讓寫入具備冪等性。 事件可能亂序送達,重複呼叫不得重複變更。遞送上限 256 KiB,410 與 413 回應不重試。
  • 在行動時授權,而非接收時。 收到事件不等於取得行動授權。代理回應事件所發起的工具呼叫,仍要經過你的例行檢查 —— 也就是在 OAuth 範圍之外把關 MCP 工具呼叫的那些檢查。

以上內容都寫在文件裡。文件裡沒有的兩件事:你以多高的頻率重新檢查存取,以及使用者或管理員如何查看自己的帳戶正在推送什麼。

三個必須由你自己做出的決定

訂閱生命週期正是工作小組在章程中為自己設定、卻尚未提交 SEP 的事項。在此之前,三個決定只能由你來做,而預設值會做出糟糕的決定。

第一,授予較短的有限 TTL,拒絕 ttlMs: null。TTL 就是被撤銷的訂閱對用戶端可見的間隔。一個永不過期的訂閱,等於一份無人能見的 OAuth 授權。

第二,以一句能說清的日程重新檢查存取 —— 而不是「定期」。如果你說不出「我們每 15 分鐘重新檢查一次」並指出執行它的排程作業,你依賴的就是一個沒有間隔、沒有一致性測試的 SHOULD。

第三,保留按使用者的訂閱索引。沒有它,為員工辦理離職意味著假設其訂閱已消亡,而不是確認這一點。當一名員工離開,撤銷問題不是「他們的權杖過期了嗎」 —— 而是「他們授權的每一個 webhook 都停止了嗎」。

MCP Events 改變了代理的觸發模型,這才是真正的架構轉變。但憑證壽命缺口才是最先咬到生產部署的部分。協定讓伺服器無狀態;事件擴充又讓伺服器重新有狀態 —— 而它持有的狀態,是一份沒有規定撤銷節奏的憑證。下圖梳理訂閱生命週期、憑證壽命缺口,以及不對稱的撤銷面:

MCP Events:訂閱生命週期與憑證缺口 2026-07-28 無狀態規範之後首個新的 MCP 傳輸原語 1 訂閱 —— events/subscribe ChatGPT 附事件名稱、篩選參數、回呼 URL、簽名密鑰(HMAC)呼叫你的伺服器 伺服器以挑戰握手驗證回呼,儲存訂閱:擁有者、篩選條件、URL、密鑰、到期時間 要求 MCP 2.0,協定版本 2026-07-28 · 面向 12 億 ChatGPT 週活使用者 2 憑證缺口 —— 訂閱比權杖活得更久 存取權杖:短壽命,每個請求檢查範圍,過期回傳 401 訂閱:以 (principal, url, name, arguments) 為鍵 —— 鍵中無權杖、範圍或到期時間 ttlMs: null 請求永不過期 · refreshBefore: null 獲准 · WorkOS:「一份無人能看見的憑證」 權杖:約 1 小時 TTL 每個請求檢查 訂閱:可達永遠 SHOULD「定期」 —— 無間隔 3 遞送 —— 簽名 webhook 至回呼 URL Standard Webhooks:webhook-id、webhook-timestamp、webhook-signature · 上限 256 KiB · 每個請求一個事件 遞送時執行 SSRF 檢查:僅 HTTPS,阻擋私有網段,不跟隨重新導向 · 酬載 = 注入面 寫入冪等(事件亂序送達) · 收到事件 ≠ 行動授權 4 撤銷 —— 在 ChatGPT 中不對稱 草稿:簽名 {"type":"terminated"} 信封 POST 至回呼 → 代理立即得知「已停止及原因」 ChatGPT:支援 webhook 模式,不支援 terminated 信封 草稿撤銷路徑 terminated 信封 → 代理立即收到通知 ChatGPT 撤銷路徑 TTL 到期 → 重新整理失敗 → -32012 Forbidden(僅存訊號) ttlMs: null 永不過期 → 重新整理永不 觸發 → 代理永遠不知情 5 工作小組 —— SEP 尚未提交 負責人:Clare Liguori(AWS)+ Peter Alexander(Anthropic) · 章程變更紀錄:一筆,2026-03-24 進行中項目:「SEP: Events in MCP v1 RFC」 —— 狀態:Ideating · 目標:End April · 負責人:TBD 設計草圖已存在(2026-02-19,草稿) · 實作者提交實戰回報 · 無 SEP = 無一致性測試 訂閱生命週期明確在範圍內,也明確未完成 上線前必須由你做出的三個決定 1. 授予較短的有限 TTL —— 拒絕 ttlMs: null 2. 以一句能說清的日程重新檢查存取 3. 保留按使用者的訂閱索引 —— 離職時確認,而非假設

Related reading


一家中型 SaaS 公司營運著一個客服 MCP 伺服器 —— 把 ChatGPT 連接到工單系統與知識庫的那種 —— 希望新增事件驅動觸發器,讓代理在高優先級新工單送達時起草回覆。工程團隊實作 events/subscribe,儲存訂閱,並交付 webhook。三週後,一名客服同仁離職。其存取權杖一小時後過期,但以該權杖建立的事件訂閱仍持續向 ChatGPT 推送 webhook —— 因為沒有人授予有限 TTL,按使用者的訂閱索引也不存在。本可在整合中告訴 ChatGPT「一切已停止」的 terminated 信封並不受支援。代理持續處理離職同仁在來源系統中已無權檢視的工單。

申請範圍明確的交付。為期一週的深度評估。你將取得系統清單、工作流程地圖與固定範圍 —— 無論是否與我們共建。

想為您的系統建構這個嗎?

這裡的每份文件都來自真實的生產工作。如果您有目標系統和工作流程想法,我們可以在一週內確定範圍。

申請客製開發

為期一週的發掘階段。您會拿到系統清單、工作流程地圖和固定範圍——無論您最終是否與我們合作開發。