OpenAIは9月29日のDevDayで、ChatGPTが下書き段階のMCP Events仕様に対応したと発表した。これまでMCPのサーバーは、エージェントに呼ばれたときだけ答えていた。今後は、サーバーの側で起きた出来事をwebhookで知らせることもできる。エージェントが外の世界の変化を待って動く仕組みが、標準のプロトコルの上に載ったことになる。
ただ、この下書きの仕様には欠けているところがある。購読を作ったあとで、利用者の権限をいつ確かめ直すかを決めていない。購読はいったん作られると、それを作った利用者のトークンより長く残る。そのため、権限を外された人のデータや、権限を外された人に宛てたデータが流れ続けるおそれがある。この記事では、新しい機能の中身と、仕様に残っている権限の穴を順に見ていく。
呼ばれて答える形から、サーバーが知らせる形へ
OpenAIの開発者向けの文書は、この機能を次のように説明している。
MCP Events lets ChatGPT subscribe to updates from your MCP server, such as new messages, content updates, or status changes.
訳: MCP Eventsを使うと、ChatGPTはMCPサーバーからの更新(新しいメッセージ、内容の更新、状態の変化など)を購読できる。
これまでのMCPでは、エージェントがツールを呼んだときにしかサーバーは答えなかった。新しいメッセージが届いたか、文書が書き換わったか、処理が終わったかを知るには、エージェントの側から聞きに行くしかなかった。購読を使えば、サーバーは変化が起きた時点でChatGPTに知らせられる。ChatGPTが何かのきっかけで自動的に動き出す機能(いわゆる自動化)は、この上に作ることになる。一部の報道は、これでエージェントの通信の形がそろったと評している。
ChatGPTが対応する範囲は狭い。9月28日〜10月2日のChatGPTの更新情報には、次の条件が書かれている。
This integration requires MCP 2.0. ChatGPT supports webhook delivery from the draft MCP Events specification; polling and streaming aren't supported.
訳: この連携にはMCP 2.0が必要。ChatGPTが対応するのは、下書きのMCP Events仕様のうちwebhookによる配信で、ポーリングとストリーミングには対応しない。
前提はMCP 2.0で、配信の方法はwebhookの1つだけである。下書きの仕様にあるポーリングとストリーミングは使えない。サーバーを作る側から見ると、外から届く通知を受け取る口をChatGPTが持ち、そこへ自分のサーバーが送り込む形に決まったことになる。仕様が下書きのままなのに、利用者の多い製品が先に1つの方式に決めたので、各社のサーバーの実装はこの形にそろっていくだろう。
購読は、長く残る資格情報になる
問題は、購読をどう扱うかにある。認証基盤を手がけるWorkOSは10月1日のブログで、購読を資格情報として扱うべきだと論じた。筆者のMaria Paktitiは次のように書いている。
an event subscription is a credential: a durable record, created under one user's access token, that authorizes your MCP server to push that user's data at an agent long after the token that created it has expired.
訳: イベントの購読は資格情報だ。ある利用者のアクセストークンのもとで作られて長く残る記録で、そのトークンが切れたずっと後も、MCPサーバーがその利用者のデータをエージェントに送り続けることを許してしまう。
ふだんのツールの呼び出しでは、呼ぶたびに利用者のアクセストークンが送られ、サーバーはそのつど権限を確かめられる。トークンが切れたり、管理者が利用者の権限を外したりすれば、次の呼び出しは失敗する。ところが購読は、作った時点のトークンのもとで登録されたあと、サーバーの側に記録として残る。通知を送るたびに利用者がトークンを出し直すわけではない。だから、作ったときの許可が、トークンの寿命を超えて生き続ける。
具体的には次のようなことが起こりうる。退職した社員や、プロジェクトから外れた人が、以前にChatGPTで社内のチャットや文書の更新を購読していたとする。サーバーが送る前に権限を確かめ直さなければ、その人のChatGPTには新しいメッセージや文書の変更が届き続ける。
「定期的に」という言葉しか無い
下書きの仕様も、この問題にまったく触れていないわけではない。Paktitiによれば、仕様には権限を「定期的に」確かめ直すという趣旨の一文がある。しかし、その書き方は弱い。
Periodically is doing a lot of work in that sentence. There is no interval, no MUST, and no conformance test behind it.
訳: 仕様のその一文は「定期的に」という言葉に頼りすぎている。間隔の定めも、MUST(必須)の指定も、適合テストも無い。
仕様の文書で「MUST」と書かれていない決まりは、実装する側にとっては守らなくてよい推奨にすぎない。間隔の定めが無いので、1分ごとに確かめるのも1か月ごとに確かめるのも、同じように仕様に合っていることになる。適合テストも無いので、確かめ直しをまったくしないサーバーでも、ChatGPTにはつながってしまう。
その結果、取り消しがどれだけ効くかは、購読の有効期限で決まる。
The TTL you grant is your revocation window. Whether data keeps flowing inside it depends on whether you recheck access on delivery.
訳: 購読に与える有効期限(TTL)が、そのまま取り消しの効かない時間になる。その間もデータが流れ続けるかどうかは、配信のたびに権限を確かめ直すかどうかで決まる。
有効期限を1週間にすれば、権限を外しても最長で1週間はデータが届きうる。この穴をふさげるのは、通知を送るたびに、その時点の権限を確かめ直すことだけである。下書きの仕様は、これを義務にしていない。
MCPの権限の扱いは、通知の側でも試される
MCPの認可は、今週すでに別の形で問題になっている。公式のPython SDKで、悪意あるサーバーがOAuthのトークンの送り先を差し替えられる欠陥が見つかった(既報)。あちらは、トークンを取るときの穴だった。今回の購読は、トークンを取ったあとの穴である。仕様の中で「誰がいつ何を読めるか」を決める部分の弱さが、別の場所から続けて出てきたことになる。
組織の単位でアクセスを管理するEnterprise-Managed Authorizationの考え方を取り入れても、それだけではこの穴は埋まらない。管理者が権限を外しても、サーバー側に残った購読がその変更を見に行かなければ、通知は止まらないからである。
サーバーを作る側が今できることは、仕様の外で決めておくしかない。たとえば次のようなことである。
・通知を送るたびに、購読を作った利用者の今の権限を確かめる。
・購読の有効期限を短くし、延長のたびに改めて認可を求める。
・利用者の権限が外されたり、トークンが取り消されたりしたら、その利用者の購読をまとめて消す。
・エージェントの監視(Agent Observability)の記録に、購読ごとの送り先と、作ったときのトークンを残しておく。
OpenAIの文書と更新情報には、ChatGPTの側が受け取った通知について権限をどう扱うかは書かれていない。下書きの仕様が確定するまでに、確かめ直しをMUSTにし、間隔を決め、適合テストを付けるかどうかが次の焦点になる。それまでのあいだ、サーバーからの通知は便利になる代わりに、権限を外したあとも閉じない口になりうる。




