MCP サーバー認証実装ガイド:最新仕様の活用
2025-06-18 仕様に準拠した MCP サーバー認証実装の主要なポイントを解説します。
2025-06-18 仕様に準拠した MCP サーバー認証実装の主要なポイントを解説します。
数日前(2025年6月18日)、MCP(Model Context Protocol)チームは MCP 仕様書(2025-06-18) の最新版をリリースしました。このアップデートでは、認証仕様における重要な変更が含まれています。MCP サーバーは今後、認可サーバー として アクセストークン を発行しなくなります。代わりに、アクセストークンを受け入れ、リソースサーバー としてリソースを提供する形となります。
MCp Auth(プラグアンドプレイな MCP サーバー認証ライブラリ)のメンテナーの 1 人として、私は本プロジェクトで最新版の MCP 認証仕様へ対応を行いました。実践経験を元に、最新仕様に準拠する MCP サーバーの認証機能をどのように実装できるかを解説します。
本記事では、以下の内容を扱います:
注意事項:
最新 MCP 認証仕様 に基づき、MCP 認証フローは次の図のように動作します:
MCP クライアントは https://github-tools.com の MCP サーバーからリソースを要求します。まだ認証していないため、このリクエストの HTTP 認可ヘッダーにはアクセストークンが含まれていません。
MCP サーバーはリクエストの認可ヘッダーからアクセストークンを取得できません。HTTP 401 エラーを MCP クライアントに返却し、エラーレスポンスには WWW-Authenticate ヘッダーとして MCP サーバーのリソースメタデータ(resource_metadata フィールドの値)の URL を含めます。
MCP クライアントは返却された WWW-Authenticate ヘッダーから resource_metadata の値(例: https://github-tools.com/.well-known/oauth-protected-resource)を取り出し、このアドレスからリソースサーバーとしての MCP サーバーが提供するリソースメタデータを取得します。このメタデータには authorization_servers や scopes_supported などの情報が含まれており、MCP サーバーへアクセスするためにどの認可サーバーからどんな権限付きトークンを取得すべきかを MCP クライアントは理解できます。
4-8. MCP クライアントはリソースメタデータから得た認可サーバーメタデータ URL を元に認可サーバーメタデータ情報をリクエストし、OAuth 2.1 認可フローを通じて認可サーバーからアクセストークンを取得します。
MCP クライアントは取得したアクセストークンを認可ヘッダーに付与して再度 MCP サーバーへリソースアクセスリクエストを送信します。
MCP サーバーはトークンが有効であることを確認後、リクエストされたリソースを返します。この後も有効なトークンを使って MCP クライアントと MCP サーバー間で通信を継続できます。
次に、MCP 認証ワークフローに基づき、サーバー側の認証メカニズム実装方法をステップごとに解説します。
上記のフローの通り、MCP クライアントがアクセストークンなしで MCP サーバーにリクエストを送信した場合、サーバーはリソースメタデータの URL を含んだ WWW-Authenticate ヘッダー付きの 401 Unauthorized エラーを返却する必要があります。
MCP 認証仕様のエラーハンドリング規定 に従い、MCP クライアントのリクエストにアクセストークンが含まれない場合だけでなく、MCP サーバーが無効なアクセストークンを受信した場合も WWW-Authenticate ヘッダー付き 401 エラーを返すべきです。
ここで、401 エラーを返却するタイミングが分かったら、どのように WWW-Authenticate ヘッダーを構築すれば良いのでしょうか?
RFC9728 Section 5.1 によれば、 WWW-Authenticate ヘッダーに resource_metadata パラメーターを含めて、保護リソースメタデータの URL を示します。
基本形は次のようになります:
ここで Bearer は認証スキームであり、OAuth 2.0 による保護リソースへのアクセスには Bearer トークンが必要であることを意味します(MDN ドキュメント 参照)。続く resource_metadata パラメーターの値は MCS サーバーが提供するリソースメタデータエンドポイントの完全な URL です。
コード例:
MCP クライアントは上記のような 401 エラーを受信した場合、WWW-Authenticate ヘッダー内の resource_metadata URL から MCP サーバーのリソースメタデータを取得し、記載の情報に基づいて指定された認可サーバーに認可リクエストを送信して、MCP サーバーアクセス用のアクセストークンを取得します。
これで 401 エラー返却のタイミングや resource_metadata URL の必要性が分かりました。次はこのリソースメタデータ URL の組み立て方や中身について説明します。
MCP 認証フローでは、MCP クライアントが 401 エラーを受信した直後、すぐに MCP サーバーにリソースメタデータのリクエストを送信します。従って、MCP サーバー(リソースサーバー)はリソースメタデータディスカバリ機構を実装する必要があります。
OAuth システムでは、URL でリソースアドレス(リソースインジケーター)を識別します。RFC9728 に従い、リソースメタデータは /.well-known パス配下でホストします。
MCP サーバー(例: https://github-tools.com)が 1 つのサービスのみを提供している場合、メタデータエンドポイントは:
1 つのホストで複数の MCP サービスを提供する場合、それぞれ独立したメタデータエンドポイントを用意します。たとえば、https://api.acme-corp.com で次のサービスがある場合:
https://api.acme-corp.com/github - GitHub 連携サービスhttps://api.acme-corp.com/slack - Slack 連携サービスhttps://api.acme-corp.com/database - データベースクエリサービスそれぞれのメタデータエンドポイント:
https://api.acme-corp.com/.well-known/oauth-protected-resource/githubhttps://api.acme-corp.com/.well-known/oauth-protected-resource/slackhttps://api.acme-corp.com/.well-known/oauth-protected-resource/databaseこの設計により、各サービス毎に異なる権限制御や認可サーバー構成が可能になります。例えば:
github:read、github:write 権限が必要slack:channels:read、slack:messages:write 権限が必要db:query 権限が必要まとめると、メタデータエンドポイントの URL 規則:
このようにリソース識別子からメタデータエンドポイント URL を組み立てできます:
エンドポイント URL パスを決めたら、このエンドポイントが RFC9728 に準拠した JSON 形式のメタデータを返すようにします。
実装では、主に次の 4 つのコアフィールドを意識してください。
まず resource フィールドはリソース識別子であり、MCP クライアントがアクセスしたいリソースアドレスと一致させる必要があります。
次に authorization_servers フィールドは、MCP クライアントがどの認可サーバーへアクセストークンを要求すべきか指定する配列です。OAuth 2.0 Protected Resource Metadata(RFC 9728)では任意ですが、MCP 認証仕様では必須です。この情報が無ければ MCP クライアントは OAuth フローを完遂できません。
scopes_supported フィールドはリソースサーバーがサポートするすべての権限スコープを列挙します。
最後に bearer_methods_supported フィールドは、このサーバーがアクセストークン受け取りにサポートするメソッド種別を記載します。通常は ["header"] とし、認可サーバーから取得したトークンを HTTP Authorization ヘッダーで MCP サーバーに送信するよう MCP クライアントに示します。
具体例。https://github-tools.com MCP サーバー向けのリソースメタデータ:
この設定は MCP クライアントに、https://github-tools.com を利用するためには https://auth.github-tools.com 認可サーバーから github:read、github:write、repo:admin などの権限付きトークンを取得し、そのトークンを HTTP Authorization ヘッダーで送信すべきと伝えています。
一般的な用途では、この 4 つだけで十分 MCP クライアントが正常動作します。より複雑な設定は RFC9728 の全項目リストを参考にしてください。
MCP クライアントが認可サーバーからアクセストークンを発行された後、そのトークンを MCP サーバーへ添えてアクセスします。
このとき、MCP サーバーが意識すべき検証ポイント:
MCP サーバーがアクセストークンを受信したとき、多くの場合トークン内部に認可サーバー情報(issuer)があるため、その情報から自動的に検証先サーバーを決めようとしがちです。特に MCP サーバーのリソースメタデータで複数の認可サーバーが設定されている場合:
このとき、未検証トークンから issuer を抽出して該当認可サーバーのデータで検証します。しかし攻撃者が悪意の認可サーバーで偽アクセストークンを発行した場合、その issuer に基づいて(正当認可サーバーと見なして)検証してしまうと、不正トークンも通ってしまいます。
正しい検証方法:
issuer を抽出し、MCP サーバー設定値の中から該当認可サーバーを探して検証。見つからない場合は無効とするトークン検証時は issuer を厳格に検証してください。
jose JWT 検証ライブラリ例:
MCP 認証仕様内「Token Audience Binding and Validation」 の規定で、クライアントがアクセストークンを認可サーバーにリクエストする際、どのリソース用なのか resource パラメーターで明示し、サーバー側も受信したトークンの audience(aud)が自身かどうか必ず検証すべきとされています。
この仕組みは Resource Indicators for OAuth 2.0(RFC 8707)に準拠します。
要点ワークフロー:
クライアントは認可サーバーへのアクセストークンリクエスト時に resource パラメーターでリソースサーバー(例: https://github-tools.com)を指定
認可サーバーは発行時に audience フィールド(JWT なら aud claim)に上記リソースを埋め込み
MCP サーバーは受信したトークンの audience が自身と一致するか検証
例: https://github-tools.com MCP サーバーの場合
この audience チェックはトークン悪用防止の重要なセキュリティ技法です。これが抜けていると、攻撃者が他サービス用のアクセストークンで API に不正アクセスする恐れがあります。
一部 MCP サーバーは内部リソース管理時、ユーザー毎に異なる権限スコープを割り当てます。
従い、トークン検証が通った後も、 scope claim に現在操作に必要なパーミッションが含まれるかチェックします:
MCP 認証仕様エラーハンドリング に沿って、トークンに必要スコープがなければ 403 Forbidden を返してください。
本記事を通じて、MCP サーバーの最新仕様に準拠した認証機能が実装できるはずです。ポイントは「安全なトークン検証」「正しいメタデータ設定」「audience の厳格検証」の 3 つ。
もし MCP サーバー構築中であれば、MCP Auth ライブラリも利用してください。本記事で解説した機能すべて実装済で、迅速な認証統合が可能です。
質問は GitHub でいつでも歓迎です。MCP エコシステムを一緒に発展させましょう!