Open5

MCP Server における Authorization RFC の動向キャッチアップ

hassaku63hassaku63

2025-03-26 ChangeLog をざっと眺めてみる

https://modelcontextprotocol.io/specification/2025-03-26/changelog

2025-03-26 以前のバージョンは 2024-11-05 まで遡るので、当座は見なくてよさそう。スルーする。

この時点で、OAuth2.1 ベースの認可の仕組みは導入されている。PR #133

https://github.com/modelcontextprotocol/specification/pull/133

また、以前まであった HTTP + SSE による transport は Stream に置き換わる模様 #206

https://github.com/modelcontextprotocol/specification/pull/206

他の話... JSON-RPC batching と、tool annotations については、発散しそうなので一旦おいておく。

hassaku63hassaku63

Sequence & Session

シーケンス図が割とわかりやすい。

https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#sequence-diagram

個人的にアンテナに引っかかった話をメモっていく(下記)

HTTP + SSE をベースとする(stdio ではない)トランスポートでは、Server 側が能動的に Client にデータを送る手段は SSE しかない。つまり最初の1回 (?) は Client からリクエストをもらう必要がある。Client は Server からのイベントを Listen する意志を HTTP リクエストで明示する必要があって、そこで初めて Server は(MCP 上の概念として)自発的に Client 対するデータ送信ができるようになってる。

HTTP (+SSE) 的には複数回のリクエストだが、MCP 上のやり取りとしては1回分、という感じになる。んで、MCP 上でのセッションを表現するために Mcp-Session-Id というヘッダが考案されている。これは Initialization 時に Server 側が InitializaResult のレスポンスでそういう HTTP ヘッダを含める必要がある。これはプロトコル的には任意。これで「セッション」の概念が使えるようになる。このへんは、なんだか TCP/IP のスタックで既視感がある。ID は UUID みたいなグローバルユニークな値で、かつ 暗号的に 安全なものであるべき。

Server が Mcp-Session-Id を付与するかは任意だが、Client はこのヘッダを受け取ったら必ず以降の通信でその ID使う必要がある(それはそう)。で、セッションID が必要な Server は、Mcp-Session-Id がない (Initialization 以外での) 通信を弾くべき。具体的には 400 Bad Request 応答。

Mcp-Session-Id を伴う 404 レスポンスがあった場合、Client は新しいセッションを開始しなければならない。
つまり、Session Id を持たない InitializeRequest を送る必要がある。

Client 側からセッションを閉じたい場合は、Client から Mcp-Session-Id をくっつけた DELETE を送るのが推奨。こうすることで明示的にセッションを閉じる意思表明になる。ここで、Server はその要求を拒否するために 405 Not Allowed を送ってもよい。(?この応答の必要性はあんまり良くわかっていない。Server が拒否したいシチュエーションがぱっと出てこなかった)

hassaku63hassaku63

Authorization

https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization

※あくまで認可なので、認証とは切り分ける

Transport レベルでの認可を実現する。Authorization は MCP の実装において任意。

Authorization をサポートする HTTP-based な transport は、この仕様を実装すべきである。

Authorization をサポートする STDIO transport は、この仕様に準拠すべきではない。その代わりに、環境からクレデンシャルを取得する

他の Transport は、(このプロトコル仕様に限らず)その通信プロトコル上で確立しているベスプラに従わねばならない。

...要するに、HTTP ベースな Transport で、この OAuth ベースの仕組みが適用されるという話

MCP における Authorization は次の3つを基礎としているが、全部ではなくサブセットに準拠している

hassaku63hassaku63

Authorization (2/n)

Grant Type はそのユースケースに応じて選択するべき、とある

例えば、Authorization Code は人間に代わって仕事をするような性質のものに。

Client Credentials は、人間ではない、(OAuth Client とは) 別のアプリケーションがクライアントである場合。人間 (end user) に成り代わる必要がない。

ここでもシーケン図がわかりやすい

https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization#2-2-example%3A-authorization-code-grant