こんにちは、VポイントマーケティングAIエンジニアの三浦です。
最近既存のAPIをMCPを使ってAI Agentに提供できるようにするにはどうしたらいいのか調べていました。どんな機能を提供するのかを考えるのはもちろんなのですが、どうやって安全に機能を提供できるのかについてもしっかりと理解しておく必要があると思っています。
そういった理由から、最近MCP(Model Context Protocol)のドキュメントの認可(Authorization)仕様のページを読んでいます。
このドキュメントではMCPの認可におけるMCPクライアント, MCPサーバー, 認可サーバーそれぞれの実装における要件が説明されています。この中で特に今回はMCPサーバーを開発し、HTTPベースで提供するうえで開発者が知っておかなければならない要件に注目して読み進めています。
今回の記事では全ての内容をまとめることは出来ていませんが、これまで読み進めた中で重要な点を自分の勉強をかねてまとめてみたいと思います。
MCPの認可フローの大まかな流れ
まず今回の認可フローはMCPサーバーをHTTPベースで提供する場合に推奨されるものです。STDIOで使用するMCPサーバーの場合は資格情報は環境変数などから取得することが想定されています。
- MCPクライアントが接続したいMCPサーバーにトークンなしでアクセスする
- MCPサーバーは401 Unauthorizedを返す
- MCPクライアントはMCPサーバーのレスポンスの
WWW-AuthenticateヘッダかWell-Known URI経由でMCPサーバーのProtected Resource Metadataを取得してどの認可サーバーを使うのかを判断する - MCPクライアントはその認可サーバーのメタデータを取得して、認可エンドポイントやトークンエンドポイント、PKCE対応などを確認する
- 事前登録済みのclient_idを使うか、Client ID Metadata Documentsを使うか、必要なら動的クライアント登録を使ってクライアント登録する
- MCPクライアントは PKCEを使い、
resourceパラメーターと必要なscopeを付けて認可を開始する - ユーザーがブラウザー上で認可すると、MCPクライアントは認可コードを受け取る
- MCPクライアントは認可コードを認可サーバーのトークンエンドポイントに送りアクセストークンを取得する
- MCPクライアントはアクセストークンを
Authorization: Bearer <access-token>の形式で付与してリクエストを送る - MCPサーバーはそのトークンが自分向けに発行されたのか、スコープが足りているかを検証してから応答する
この中でMCPサーバーに求められる対応はいくつかありますが、特に重要なのは認可サーバーの情報を公開することと、MCPクライアントから受け取ったアクセストークンが自分向けで有効かを検証することです。今回の記事ではこの2点についてもう少し詳しくまとめてみたいと思います。
Protected Resource Metadataの実装(認可サーバーの情報の公開)
MCPサーバーは認可サーバーの場所をMCPクライアントに示す必要があります。そのために「RFC9728 OAuth 2.0 Protected Resource Metadata」で定められた仕様に従ってJSON形式で記述し、MCPクライアントが見られるように公開する必要があります。認可サーバーのURLはauthorization_serversというフィールドに含めます。
MCPサーバーがResource Metadataを公開する方法は大きく2つあります。1つはMCPクライアントがアクセストークンを設定せずにMCPサーバーにリクエストを送信した際にMCPサーバーから返却する401 UnauthorizedレスポンスのWWW-Authenticateヘッダーのresource_metadataパラメーターに、そのURLを含める方法です。
以下のようになります。
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource",
scope="files:read"
もう一つの方法はRFC9728で定められた"well-known URI"でResource Metadataを配信する方法です。URLは以下のいずれかになります。
- サーバーの MCP エンドポイントのパスに対応する場所:
https://example.com/public/mcpのメタデータはhttps://example.com/.well-known/oauth-protected-resource/public/mcp - ルート:
https://example.com/.well-known/oauth-protected-resource
MCPサーバーはMCPクライアントが認可サーバーに認可を求める際に、現在のリクエストを満たすために必要なスコープの指針を示せるように、scopeパラメーターをWWW-Authenticateヘッダーに含めることが推奨されています。
アクセストークンの検証
MCPサーバーはOAuth2.1のリソースサーバーとしての立場にあります。OAuth 2.1のリソースサーバーとしての要件(Section 5.2)の内容に従ってアクセストークンの検証を実装する必要があります。具体的にはそのアクセストークンがまだ期限切れでないこと、要求されたリソースへのアクセスが認可されていること、適切なスコープで発行されていることを確認します。
もう一点重要なのが、MCPサーバーはアクセストークンを対象のaudienceとして発行されたものであることをRFC8707のSection 2に従って検証することが求められます。
もし無効だったり他のサーバー向けに発行されたアクセストークンの場合は受け取りを拒否しないといけません。無効または期限切れのトークンには401 Unauthorizedを返し、スコープが不足している場合は403 Forbiddenを返すのが基本です。
また、MCPサーバーは自分向けではないトークンを受け入れないだけでなく、MCPクライアントから受け取ったアクセストークンをそのまま下流のAPIへ転送してはいけません。このあたりはMCPの認可において重要な点なのですが、まだ詳細をまとめ切れていないため、次回以降の記事で改めて整理したいと思います。
まとめ
今回は外部向けにMCPサーバーを公開するにあたり、MCPの認可仕様についてドキュメントを読んで学んだことをまとめてみました。OAuthの仕様についても理解が浅いところもあったため、勉強になりました。今回の記事でまだまとめ切れていない内容もあるので、次回以降このテーマでまた記事を書きたいと思います。