本文へ移動
AI Dev Lab Japan AI開発ツール、AIコーディングエージェント、M...

MCP OAuthを実装する前に:Protected Resource Metadata・resource・audience検証の確認ポイント

MCP OAuthを実装する前に:Protected Resource Metadata・resource・audience検証の確認ポイントの判断ポイントを表す抽象サムネイル

3行まとめ

VisualMCP OAuthで先に見る5点ログイン画面より先に、resource境界を固定します。
Metadata

MCPサーバーをOAuth protected resourceとして発見できるようにします。

resource

authorization requestとtoken requestの両方で宛先を伝えます。

scope

Tools、Resources、Promptsと副作用で権限を分けます。

audience

別resource向けtokenをMCPサーバーで拒否します。

passthrough

受け取ったaccess tokenを下流APIへそのまま流しません。

MCP OAuthは、誰がログインしたかだけでなく、どのresource向けに何を許したかを確認します。

MCPサーバーにOAuthを入れるなら、まず見る対象はログイン画面ではなく、そのMCPサーバーがどのOAuth protected resourceとして扱われるかです。

MCP Authorization仕様では、MCPサーバーのProtected Resource Metadata、authorization requestとtoken requestのresource、サーバー側のtoken検証がつながって扱われます。

特に危ないのは、署名検証だけで安心すること、scopeを広く始めること、受け取ったaccess tokenを下流APIへそのまま流すことです。

この記事でわかること

Visual公開前レビューで決める項目実装前に迷いやすい認可の境界です。
責任分界

MCP ServerとAuthorization Serverの役割を分けます。

発見

Protected Resource Metadataをclient discoveryに使える状態にします。

要求

authorization requestとtoken requestでresourceを落としません。

権限

read、write、admin、人間承認をscopeで分けます。

検証

audience検証とpassthrough禁止をtestへ落とします。

仕様名を覚えるより、公開前にどの境界を確認するかへ落とすことが重要です。

  • Streamable HTTPのMCPサーバーでOAuthを入れる前に決める責任分界
  • Protected Resource Metadataを「出しているか」だけでなく「発見に使えるか」で見る方法
  • authorization requestとtoken requestにresourceを入れる理由
  • scopeをMCPのTools、Resources、Prompts、副作用、人間承認に合わせて分ける考え方
  • audience検証とtoken passthrough禁止を、公開前レビューとテストに落とす方法
  • TypeScript SDKのauth helperを使うときに、アプリ側で決めるべき範囲

この記事は2026年6月15日に、MCP Authorization 2025-11-25版、MCP Security Best Practices、RFC 9728、RFC 8707、MCP TypeScript SDK README、npm上の@modelcontextprotocol/sdk 1.29.0を確認して書いています。X/Twitter上のMCP OAuth関連の話題は需要シグナルにとどめ、仕様の根拠には使っていません。

前提知識

VisualMCP OAuthの登場人物単なるログイン導線ではなく、複数の境界を扱います。
項目内容見方
MCP Clientmetadataを見て認可処理へ進み、token付きでMCP Serverを呼びます。
MCP Servertokenの宛先になるprotected resourceとして検証します。
Authorization Serverissuer、認可endpoint、token発行、resource indicatorを扱います。
下流APIMCP Serverとは別resourceとして権限設計します。
Host Apptool実行、承認UI、監査の入口になります。

stdioのローカル実験とHTTP公開サーバーでは、認可で見る境界が変わります。

MCP OAuthは「ログインを付ける話」だけではない

MCPでOAuthというと、まずブラウザでログインして、access tokenをもらい、MCPサーバーへBearer tokenを付けて呼ぶ流れを想像しがちです。そこだけ見ていると、一般的なAPI認証の延長に見えます。

ただしMCPでは、MCPクライアント、MCPサーバー、Authorization Server、下流API、ホストアプリケーションが混ざります。さらにMCP serverは、モデルがToolsを呼び出したり、Resourcesを読んだり、Promptsを参照したりする入口になります。つまり、単に「ユーザーがログイン済みか」では足りません。

先に決めたいのは次の5点です。

見るもの何を決めるか失敗すると起きること
Protected Resource MetadataMCPサーバー自身のresource識別子と認可サーバーの見つけ方クライアントが別の認可設定を見に行く
resourceパラメータどのMCPサーバー向けのtokenを要求するか別resource向けtokenが混ざる
scopeどのTools、Resources、Prompts、操作を許すかread-onlyとwriteが同じ扱いになる
audience検証tokenがこのMCPサーバー向けか確認する署名は正しいが宛先が違うtokenを受理する
token passthrough禁止受け取ったtokenを下流APIへ横流ししないconfused deputyや権限境界の崩壊につながる

stdioのローカル実験とHTTP公開サーバーは分ける

この記事で扱うのは、Streamable HTTPなどで外部のMCPクライアントから到達できるMCPサーバーです。ローカルのstdioサーバーを自分の端末だけで動かす実験とは、脅威モデルが違います。

stdioなら、OSユーザー、ローカルファイル、起動コマンド、エージェント側の承認設定が主な境界になります。一方、HTTPでMCPサーバーを公開すると、MCPクライアントがどのAuthorization Serverへ向かうか、どのresource向けにtokenを要求するか、サーバーがtokenをどう検証するかが公開前レビューの対象になります。

結果: MCP OAuthはresource境界からレビューする

Visual合格ラインの確認表OAuthを入れた状態を公開前に確認します。
項目内容見方
resource識別子productionとstagingが混ざらず、公開URLや論理resourceと一致している。
MetadataclientがAuthorization Server discoveryへ進める情報を持つ。
resourceauthorization requestとtoken requestの両方で落ちていない。
scoperead、write、admin、副作用ありtool、人間承認を分けている。
token検証issuer、署名、期限、audience、scopeを検証し、不一致を拒否する。
passthroughMCPサーバー向けaccess tokenを下流APIへそのまま渡さない。
ログtoken本体を残さず、拒否理由とrequest idを追える。

曖昧なresource境界は、AIエージェントのtool実行リスクとして表れます。

実務では、MCP OAuthを「あとからmiddlewareで足す認証」として扱うより、resource境界を先に固定した方が安全です。

レビューで合格にする最低ラインは、次の状態です。

レビュー項目合格条件
resource識別子productionとstagingで混ざらず、MCPサーバーの公開URLや論理resourceと一致している
Protected Resource MetadataクライアントがAuthorization Server discoveryへ進める情報を持つ
resourceauthorization requestとtoken requestの両方で落ちていない
scoperead、write、admin、副作用ありtool、人間承認が必要な操作を分けている
token検証issuer、署名、期限、audience、scopeを検証し、不一致を拒否する
passthroughMCPサーバー向けaccess tokenを下流APIへそのまま渡さない
ログtoken本体を残さず、拒否理由とrequest idを追える

この表を満たさない状態で公開すると、OAuthを入れたのに「誰の、どのresource向けの、どの操作権限か」が曖昧なままになります。AIエージェントに接続させるMCPでは、この曖昧さがそのままtool実行の危険になります。

Streamable HTTPのMCPサーバーで先に決める責任分界

VisualMCP OAuthの責任分界tokenを受け取る場所ではなく、tokenの宛先として見ます。
  1. 1Host App

    ユーザー操作、tool実行承認、監査の入口になります。

  2. 2MCP Client

    Protected Resource Metadataを取得し、認可処理を開始します。

  3. 3MCP Server

    protected resourceとしてresource URL、scope、token検証を持ちます。

  4. 4Authorization Server

    issuer、authorization endpoint、token endpointを提供します。

  5. 5下流API

    必要なら別resourceとして権限を取り直します。

Authorization ServerとMCP Serverの責任を混ぜると、誰が何を検証するかが曖昧になります。

MCP ServerをOAuth protected resourceとして扱う

根拠

RFC 9728は、OAuth protected resourceが自分の設定をメタデータとして公開するための仕様です。MCP Authorization仕様では、MCPサーバーがOAuth 2.0 Protected Resource Metadataを実装し、MCPクライアントがそれをAuthorization Server discoveryに使う前提が置かれています。

ここで大事なのは、MCPサーバーを「tokenを受け取る場所」ではなく「tokenの宛先になるresource」として見ることです。resourceが曖昧なままだと、クライアントがtokenを要求するときも、サーバーがtokenを検証するときも、何に対する権限なのかを判断できません。

確認項目

設計メモには、少なくとも次を書きます。

MCP Resource ID: https://mcp-dev.internal.invalid
MCP Endpoint: https://mcp-dev.internal.invalid/mcp
Protected Resource Metadata: https://mcp-dev.internal.invalid/.well-known/oauth-protected-resource
Expected Authorization Server: https://auth-dev.internal.invalid
Accepted Audience: https://mcp-dev.internal.invalid
Environment: production

実際のURLは自社環境に合わせてください。ここではダミーのinternal.invalidを使っています。

Authorization ServerとMCP Serverの責任を混ぜない

条件

Authorization Serverは、ユーザー認証、同意、authorization code、access token発行、refresh token管理などを担います。MCP Serverは、そのtokenを受け取るprotected resourceとして、自分に向けて発行されたtokenかを検証し、scopeに応じてMCP操作を許可または拒否します。

小さなPoCでは、1つのアプリケーションにAuthorization Server相当の処理とMCP Serverを同居させることもあります。ただし設計レビューでは、役割を別の箱として書いた方が判断しやすくなります。

役割主な責任MCP実装での確認
Hostユーザー体験、MCP client管理、承認UIどのserverへ接続しているかユーザーに見えるか
MCP Clientmetadata discovery、authorization flow、MCP requestresourceとscopeを期待どおり送るか
Authorization Server認可、同意、token発行resource indicatorとscopeを扱えるか
MCP ServerProtected Resource Metadata、token検証、tool/resource/prompt制御audienceとscope不一致を拒否するか
Downstream API実データや外部操作MCP向けtokenをそのまま受け取らない設計か

Protected Resource Metadataで何を発見させるか

Visualmetadata discoveryの流れJSONが返るだけでなく、client discoveryへ進めることを見ます。
  1. 1MCP endpoint

    MCPサーバーの公開URLや論理resourceを固定します。

  2. 2Protected Resource Metadata

    resource、authorization_servers、scopes_supportedなどを公開します。

  3. 3Authorization Server discovery

    issuerやauthorization endpointへ機械的に進めます。

  4. 4Client request

    metadataで得た情報を認可要求とtoken要求に反映します。

  5. 5Server validation

    metadataの値と実際のtoken検証が食い違わないことを確認します。

メタデータの有無だけではなく、発見された情報で正しいresource向けtokenになるかを見ます。

metadataはクライアントの発見処理に使われる

根拠

Protected Resource Metadataは、MCPサーバーが「自分にアクセスするにはどの認可サーバーを見るべきか」「どのscopeを使う可能性があるか」などを機械的に伝えるための入口です。

RFC 9728では、protected resource metadataの主なパラメータとしてresourceauthorization_serversjwks_uriscopes_supportedbearer_methods_supportedなどが定義されています。MCPではこの仕組みを使って、クライアントがAuthorization Server discoveryへ進みます。

最小のレビューでは、次のようなJSONを確認します。

{
  "resource": "https://mcp-dev.internal.invalid",
  "authorization_servers": ["https://auth-dev.internal.invalid"],
  "scopes_supported": [
    "mcp:tools:read",
    "mcp:tools:call:read",
    "mcp:resources:read"
  ],
  "bearer_methods_supported": ["header"]
}

この例は説明用です。実際のmetadataは、MCP仕様、RFC 9728、利用するAuthorization Server、MCPクライアントの対応状況に合わせて決めます。

メタデータの有無だけで合格にしない

評価基準

よくある失敗は、.well-known/oauth-protected-resourceが200を返すだけで合格にしてしまうことです。公開前レビューでは、値の整合性まで見ます。

確認項目見る理由
resourceが期待するMCPサーバーを指しているtokenの宛先になるresourceがずれるとaudience検証も崩れる
authorization_serversが本番のissuerと一致するstagingや別tenantの認可サーバーへ誘導しないため
scope候補が広すぎないclientが過剰scopeを要求する誘因を減らすため
reverse proxy配下のURLが正しい/mcpなどのpathとorigin-level metadataの解決を混同しないため
cache更新手順があるkey rotationやissuer変更時に古いmetadataを使い続けないため

特にreverse proxyやmulti-tenant構成では、外から見えるURL、内部service名、Authorization Serverのissuerがずれがちです。metadataは、そのずれを隠す場所ではありません。クライアントとサーバーが同じresourceを見ているかを確認する場所です。

resourceパラメータをauthorization requestとtoken requestに入れる

Visualresourceが落ちていないかを見るどのAPI向けのtokenかを、認可開始からcode交換まで保ちます。
  1. 1authorization request

    clientがアクセスしたいprotected resourceをresourceで示します。

  2. 2user consent

    ユーザーが許可する対象resourceとscopeを確認します。

  3. 3authorization code

    認可結果をtoken requestへつなぎます。

  4. 4token request

    code交換時にもresourceを含め、宛先を落としません。

  5. 5access token

    MCPサーバーがaudienceとscopeを検証できるtokenにします。

authorization requestだけでなくtoken requestでもresourceを見ると、別resource向けtokenの混入を見つけやすくなります。

resourceは「どのAPI向けのtokenか」を伝える

根拠

RFC 8707は、OAuthのauthorization requestで、クライアントがアクセスしたいprotected resourceをresourceパラメータで示す仕組みを定義しています。MCP Authorization仕様では、MCPクライアントがauthorization requestとtoken requestにresourceパラメータを含めることが求められます。

このresourceは、単なるURLメモではありません。Authorization Serverが、どのresource向けのaccess tokenを発行するかを判断する材料になります。

概念的には、次のような流れです。

1. MCP Client -> MCP Server
   GET /mcp
   Authorizationなし

2. MCP Server -> MCP Client
   401 Unauthorized
   WWW-Authenticate: Bearer resource_metadata="https://mcp-dev.internal.invalid/.well-known/oauth-protected-resource", scope="mcp:tools:read"

3. MCP Client -> Authorization Server
   authorization request
   resource=https://mcp-dev.internal.invalid
   scope=mcp:tools:read

4. MCP Client -> Authorization Server
   token request
   resource=https://mcp-dev.internal.invalid
   code=...

5. MCP Client -> MCP Server
   Authorization: Bearer <access-token-for-https://mcp-dev.internal.invalid>

authorization requestだけでなくtoken requestも見る

確認項目

レビューでは、認可開始のURLだけを見ても足りません。code交換時のtoken request、refresh時のtoken request、再認可時のrequestでresourceが落ちていないかも確認します。

タイミング確認すること失敗時の扱い
authorization requestresource=https://mcp-dev.internal.invalidが入る認可開始を失敗させる
token request同じresourceが入るtoken取得を失敗させる
refreshresourceが意図せず変わらない再認可または設定修正を要求する
MCP requestBearer tokenが毎HTTP requestに付く401にする
server-side validationtokenのaudience/resourceが期待値と一致する403または401相当で拒否する

Authorization Serverやライブラリによって、resourceの扱い、audience claimへの反映、scopeとの関係は違います。ここを「ライブラリがいい感じにするはず」で済ませず、発行されたtokenが本当にMCPサーバー向けになっているかをテストで見るのが安全です。

scopeはMCPの操作とデータ範囲から選ぶ

Visualscope設計の分け方大きなロール名ではなく、操作と副作用で分けます。
項目内容見方
Resources read読み取り対象、tenant、データ範囲を分けます。
Tools read-only一覧取得、diff取得、集計など副作用のない操作を分けます。
Tools writeコメント投稿、更新、削除、外部送信をread-onlyと分けます。
Prompts参照できるpromptやテンプレートの範囲を見ます。
Human approval人間承認が必要な操作は別scopeや承認境界にします。
Admin設定変更、key rotation、tenant管理を通常操作から分けます。

MCP toolは見た目が同じtool callでも、データ範囲と副作用が大きく違います。

広いロール名より小さい操作単位で見る

条件

MCPのscope設計で避けたいのは、adminuserreadのような大きすぎる名前だけで始めることです。AIエージェントが呼び出すMCP toolは、見た目は同じ「tool call」でも、影響範囲が大きく違います。

たとえば、GitHub連携のMCPサーバーでも、Issue一覧の取得、PR diffの取得、コメント投稿、ラベル変更、workflow再実行は別の権限です。社内DB連携なら、SELECT、集計、エクスポート、更新、削除、外部送信は分けて考えるべきです。

MCPでは、Tools、Resources、Promptsごとに次の軸でscopeを考えます。

MCP要素scope設計で見ること
Toolssearch_issues, create_ticket, deploy_preview副作用、外部API、承認要否
Resourcesrepo://docs/security.md, db://schema/orders読ませる範囲、機密度、tenant境界
Promptsincident_summary, release_note入力source、出力先、社内ルール
Sampling/Elicitationなどユーザー確認、追加入力人間承認、PII、再実行性

read-onlyとwriteを同じscopeにしない

注意点

read-only MCP serverから始める方針はよい出発点です。ただし、read-onlyでも安全の完成形ではありません。Issue、ドキュメント、Slackログ、問い合わせ本文などは、prompt injectionを含む未信頼入力になり得ます。

write操作を入れるなら、最低でも次を分けます。

操作scope例人間承認ログ
tool一覧取得mcp:tools:read不要なことが多い接続元とserver id
read-only tool実行mcp:tools:call:readデータ次第tool名、対象resource、件数
write tool実行mcp:tools:call:write原則必要diff、対象、承認者、request id
admin操作mcp:admin必須before/after、承認、rollback
resource読み取りmcp:resources:read機密度次第URI、tenant、分類

scopeは認可サーバーだけで完結しません。MCPサーバー側でも、toolごと、resourceごと、操作種別ごとにscopeを見て拒否できる必要があります。

audience検証で別resource向けtokenを止める

Visualtoken検証の拒否条件署名が正しくても、自分向けtokenとは限りません。
項目内容見方
issuer信頼するAuthorization Serverから発行されたtokenかを見る。
signature公開鍵やkey rotationに沿って署名を検証する。
expiry期限切れtokenを拒否する。
audienceMCPサーバーのresource識別子と一致しないtokenを拒否する。
scope呼び出すtoolやresourceに必要な権限を満たすかを見る。
tenantmulti-tenantではtokenとアプリ側のtenant境界を両方確認する。

audience不一致は警告にとどめず、tool handlerへ進む前に拒否します。

signature検証だけではMCPサーバー向けとは言えない

根拠

JWTの署名が正しいことと、そのtokenが自分のMCPサーバー向けであることは別です。署名が正しく、期限内で、issuerも信頼できても、audienceが別APIなら、そのtokenをMCPサーバーで受け入れてはいけません。

MCP Authorization仕様とSecurity Best Practicesでは、別resource向けtokenの受理、audience検証失敗、token passthroughが重要なリスクとして扱われています。MCPサーバーは、提示されたaccess tokenが自分向けに発行されたものかを検証し、違う場合は拒否する必要があります。

公開前のtoken検証表は、次のように作れます。

検証目的失敗時
issuer信頼するAuthorization Serverか確認する拒否
signature改ざんされていないか確認する拒否
expiry期限切れでないか確認する拒否
audienceこのMCPサーバー向けか確認する拒否
scope要求されたMCP操作を許すか確認する拒否
tenant/resource対象tenantやresource境界が合うか確認する拒否
token type想定したBearer tokenか確認する拒否

audience不一致は警告ではなく拒否にする

評価基準

audience不一致をログだけにして処理を続けると、OAuthを入れた意味が薄れます。環境変数でSKIP_AUDIENCE_CHECK=trueのようなdebug bypassを入れる場合も、本番で有効化されない仕組みと検査が必要です。

失敗ログには、次のような情報だけを残します。

{
  "event": "mcp_auth_denied",
  "reason": "audience_mismatch",
  "expected_resource": "https://mcp-dev.internal.invalid",
  "issuer": "https://auth-dev.internal.invalid",
  "request_id": "req_123",
  "tool": "search_issues"
}

access token本体、authorization code、refresh token、秘密鍵、個人情報はログに出しません。原因調査に必要なのは、tokenそのものではなく、どの検証で拒否したかです。

token passthroughを禁止するレビュー観点

Visualpassthroughで崩れる境界便利に見えるtoken流用ほど、resource境界を壊しやすくなります。
項目内容見方
そのまま下流APIへ送る下流APIがtokenを別の文脈で信頼する可能性があります。
下流API向けtokenを受け入れるMCPサーバーのaudience検証が抜けます。
広いscopeで再試行するscope不足を権限昇格で隠してしまいます。
別API権限を無断で取るconsentと監査の境界が崩れます。
別の正規フローを使う下流APIごとにresourceと権限設計を分けます。

下流APIを呼べないという意味ではなく、別resource向けtokenの横流しを避けるという意味です。

passthroughはconfused deputyを起こしやすい

注意点

token passthroughは、MCPサーバーが受け取ったaccess tokenを下流APIへそのまま渡す設計です。一見便利ですが、resource境界を壊しやすい危険な設計です。

たとえば、MCPサーバー向けに発行されたtokenをGitHub APIへそのまま渡す。あるいは、GitHub API向けtokenをMCPサーバーが受け取り、自分向けtokenのように扱う。どちらも「誰が、どのresourceに、何を許したか」が曖昧になります。

設計何が問題か
受け取ったtokenを下流APIへそのまま送る下流APIがtokenを別の文脈で信頼する可能性がある
下流API向けtokenをMCP tokenとして受け入れるMCPサーバーのaudience検証が抜ける
scope不足時に広いscopeで再試行する最小権限が崩れる
ユーザー同意なしに別API権限を取るconsentと監査の境界が崩れる

下流API呼び出しは別の権限設計として扱う

確認項目

token passthrough禁止は、「MCPサーバーから下流APIを呼んではいけない」という意味ではありません。下流APIを呼ぶなら、MCPサーバー向けtokenの検証とは別に、正規の権限設計を作る必要があるという意味です。

選択肢は構成によって変わります。

  • サービスアカウントで下流APIを呼び、MCP側でユーザー操作を監査する
  • Authorization Serverがon-behalf-of相当の安全なフローを提供する場合だけ使う
  • 下流APIごとに別resourceとしてtokenを取り直す
  • read-only APIから始め、write操作は人間承認と別scopeにする
  • tenant境界をMCPサーバー側と下流API側の両方で検証する

どの構成でも、MCPサーバー向けtokenを「便利な万能token」として扱わないことが重要です。

TypeScript SDKを使うときに過信しない範囲

VisualSDKで助かる領域とアプリ側の責任auth helperがあっても、本番認可設計は自動では決まりません。
項目内容見方
型とtransportSDKはMCP protocolの型やStreamable HTTP接続を助けます。
auth helperhelperは実装補助であり、audienceやscope方針の代わりではありません。
resource URL公開URL、reverse proxy、path、tenantをアプリ側で固定します。
issuerとtenantAuthorization Serverとtenant境界をアプリ側で決めます。
監査と運用ログ、承認UI、失敗時の扱い、key rotationを設計します。
環境分離productionとstagingのresourceやissuerを混ぜません。

sampleを写す前に、自社のresource URLと期待するaudienceを固定します。

READMEにあるhelperと本番認可設計は別物

根拠

MCP TypeScript SDKのREADMEでは、MCP server/clientのライブラリ、stdio、Streamable HTTP、auth helpers、ExpressやHonoなどのmiddleware packageが説明されています。2026年6月15日に確認したnpm上の@modelcontextprotocol/sdkは1.29.0でした。

SDKがあることは大きな助けです。ただし、SDK READMEにauth helperがあることを、本番向けの認可設計が自動で完成するという意味に読み替えてはいけません。

SDKで助かる領域アプリ側で決める領域
MCP protocolの型やtransportresource URLと公開URLの確定
Streamable HTTPの接続処理Authorization Serverのissuerとtenant
auth関連helperaudience、scope、tenant検証ポリシー
Express/Honoなどの薄いadapter監査ログ、承認UI、失敗時の運用
examplesproduction/staging分離、key rotation

sampleを写す前に自社のresource URLを固定する

確認項目

サンプル実装を写す前に、次の値を固定してください。

PUBLIC_ORIGIN=https://mcp-dev.internal.invalid
MCP_ENDPOINT=https://mcp-dev.internal.invalid/mcp
PROTECTED_RESOURCE_METADATA=https://mcp-dev.internal.invalid/.well-known/oauth-protected-resource
AUTHORIZATION_SERVER_ISSUER=https://auth-dev.internal.invalid
EXPECTED_AUDIENCE=https://mcp-dev.internal.invalid
ENVIRONMENT=production

reverse proxyやAPI gateway配下では、アプリケーション内部のlocalhost:3000やcontainer名をresourceにしてしまう失敗があります。MCPクライアントとAuthorization Serverが見るresourceは、外部から見た安定した識別子にそろえます。

実装レビューで見るテストケース

Visualnegative test中心の確認表成功系だけでなく、拒否できることを確認します。
項目内容見方
tokenなしMCP endpointで401とWWW-Authenticateが返る。
metadata discoveryProtected Resource MetadataからAuthorization Server discoveryへ進める。
staging混入staging clientでproduction resourceへアクセスしたら拒否される。
audience違い別resource向けtokenを拒否する。
scope不足必要scopeがないtool呼び出しを403にする。
期限切れexpired tokenを拒否し、理由を追える。
署名不正不正署名や未知のkey idを拒否する。

token検証失敗時にtool handlerが呼ばれないことまで確認します。

metadata discoveryのテスト

確認項目

metadataは、静的JSONを返して終わりではありません。クライアントがそこからAuthorization Server discoveryへ進めるか、scopeのヒントが意図どおりか、stagingとproductionが混ざらないかを見ます。

ケース期待結果
tokenなしでMCP endpointへアクセス401とWWW-Authenticateが返る
resource_metadata URLへアクセス正しいProtected Resource Metadataが返る
metadata内のAuthorization Serverを発見issuerやauthorization endpointが取得できる
staging clientでproduction resourceへアクセス拒否される
古いmetadata cacheで接続更新または明確な失敗になる

token検証のnegative test

確認項目

認可のテストは成功ケースより失敗ケースが大事です。少なくとも次をCIまたは手動リリースチェックに入れます。

失敗ケース期待結果ログ
tokenなし401missing_token
期限切れ401token_expired
issuer違い401または403issuer_mismatch
audience違い403audience_mismatch
scope不足403insufficient_scope
署名不正401invalid_signature
read scopeでwrite tool403scope_denied
別tenant resource403tenant_mismatch

MCP toolの実行結果まで進む前に拒否できるかを確認します。失敗ケースでtool handlerが呼ばれているなら、認可middlewareの位置や検証順序を見直します。

ログと運用で見逃さないもの

Visual認可ログの残し方調査できる情報と、残してはいけない情報を分けます。
項目内容見方
残すrequest id、expected resource、issuer、tool名、拒否理由を残します。
残さないaccess token、authorization code、refresh token、client secretを残しません。
集計する401/403、audience mismatch、scope不足、tool別拒否件数を見ます。
rollout公開前後でaudience不一致とscope不足の変化を見ます。
調査token本体ではなく、拒否分類とrequest idで追います。

ログが薄いと、原因調査の代わりにscope拡大や検証無効化へ流れやすくなります。

失敗理由は追えるがtoken本体は残さない

注意点

OAuth実装の初期運用では、401と403が増えます。ここでログが薄いと、原因調査のたびにscopeを広げたり、audience検証を一時的に無効化したりしがちです。それは避けたい。

ログに残す項目と残さない項目を先に決めます。

残す残さない集計する
request idaccess token本体401/403件数
client idのハッシュauthorization codeaudience mismatch件数
expected resourcerefresh tokenscope不足top N
issuer秘密鍵、client secrettool別拒否件数
tool名、resource URI個人情報の生値tenant別エラー率
拒否理由Prompt全文の生ログrollout前後の差分

rollout時はaudience不一致とscope不足を見る

評価基準

導入初期に見るべきメトリクスは、認可成功率だけではありません。むしろ、audience不一致、scope不足、metadata discovery失敗、Authorization Server discovery失敗の件数を見ます。

audience不一致が多いなら、クライアントが別resource向けtokenを取っているか、metadataのresourceがずれています。scope不足が多いなら、scope設計が細かすぎるのではなく、toolごとの権限要求と説明がずれている可能性があります。

「一時的に広いscopeを許す」は最終手段です。先に、どのtoolで、どのclientが、どのscopeを要求して失敗しているかを見ます。

失敗点

Visual公開前に潰す失敗実装できたように見えても、境界が抜ける箇所です。
metadataだけ

.well-knownが返るだけで、client discoveryやtoken検証まで通っていない。

広いscope

あとで絞る前提でread、write、adminを混ぜてしまう。

fallback許可

audience検証失敗時に警告だけで処理を続ける。

環境混在

localhost、internal host、staging issuerがproductionに残る。

tool実行

token検証失敗後もtool handlerへ進んでしまう。

metadata公開、client discovery、token request、server-side validationを通しで確認して合格にします。

metadata endpointだけ作って検証を忘れる

一番起きやすい失敗です。.well-knownが返る、JSONとして読める、というテストだけでは足りません。

合格条件は、metadata公開、client discovery、authorization request、token request、server-side validationまで通ることです。逆に、metadataは返るのにtokenのaudienceが別resourceになるなら、その実装はまだ公開できません。

scopeを広くしてあとで絞る

初期開発では広いscopeの方が楽です。しかしMCP serverでは、後からscopeを細かくすると、既存client、承認UI、監査ログ、運用手順、ドキュメントをまとめて変えることになります。

最初から完璧なscope名にする必要はありません。ただし、read-only、write、副作用あり、admin、人間承認必須の境界は、最初の公開前に分けておくべきです。

audience検証の失敗をfallbackで通す

開発中は、tokenのaudienceが合わずに詰まることがあります。そこでdebug用fallbackを入れること自体はあります。ただし、本番でfallbackが残ると、別resource向けtokenを受け入れる穴になります。

公開前に見る項目は次です。

  • audience検証を無効化する環境変数がproductionで使えない
  • staging issuerとproduction issuerが混ざらない
  • localhostやinternal hostがexpected audienceに残っていない
  • scope不足時に自動で広いscopeへ昇格しない
  • token検証失敗時にtool handlerが呼ばれない

実務で使うなら

Visual導入順チェックリストresource境界から運用ログまで、小さく順番に確認します。
  1. 1. resource

    MCPサーバーのresource識別子と公開URLを決めます。

  2. 2. metadata

    Protected Resource Metadataの公開URLと中身を決めます。

  3. 3. requests

    authorization requestとtoken requestにresourceが入ることを確認します。

  4. 4. validation

    issuer、signature、expiry、audience、scopeを検証します。

  5. 5. scopes

    Tools、Resources、Promptsごとに必要scopeを割り当てます。

  6. 6. passthrough

    下流APIの権限設計を別に作ります。

  7. 7. tests

    negative testをCIまたはリリースチェックに入れます。

  8. 8. logs

    token本体を残さない監査ログを用意します。

resource識別子やAuthorization Serverの扱いが固まらない段階では、先に公開しない判断も必要です。

最初のチェックリスト

確認項目

MCP OAuthを実務に入れるなら、次の順で確認すると迷いにくいです。

  1. MCPサーバーのresource識別子を決める
  2. Protected Resource Metadataの公開URLと中身を決める
  3. Authorization Serverのissuerとdiscoveryを確認する
  4. authorization requestとtoken requestにresourceが入ることを確認する
  5. access tokenのissuer、signature、expiry、audience、scopeをMCPサーバー側で検証する
  6. Tools、Resources、Promptsごとに必要scopeを割り当てる
  7. read-only、write、admin、人間承認必須の境界を分ける
  8. token passthroughを禁止し、下流APIの権限設計を別に作る
  9. negative testをCIまたはリリースチェックに入れる
  10. token本体を残さない監査ログを用意する

導入しない方がよいケース

次に当てはまるなら、HTTP公開のMCP OAuth実装に進む前に設計を戻した方がよいです。

  • MCPサーバーの公開URLやresource識別子がまだ変わり続けている
  • Authorization Serverがresource indicatorやaudience制御をどう扱うか確認できていない
  • read-only toolとwrite toolが同じscopeになっている
  • token検証の失敗時に、運用上の理由で処理を続ける設計になっている
  • 下流API呼び出しに受け取ったtokenをそのまま使う前提になっている
  • 401/403の原因を追えるログがない

この状態で公開すると、問題が起きたときにscope拡大、検証無効化、ログ出力増加のような危ない応急処置に寄りやすくなります。

セキュリティ・コスト注意

Visual導入時に増える確認事項OAuthを入れた後に残るセキュリティと運用コストです。
項目内容見方
token管理access token、authorization code、refresh tokenをログに残しません。
承認境界user consentとtool実行承認を混同しません。
入力リスクread-only toolでも未信頼入力やprompt injectionを想定します。
権限昇格scope不足時に自動で広い権限へ上げません。
運用変更key rotation、issuer変更、metadata cache更新の手順を決めます。
multi-tenanttenant境界をtokenとアプリ側の両方で見ます。
コストmetadata、test、ログ、監査、承認UIの保守が増えます。

セキュリティは単純な勝敗ではなく、扱う操作、tenant、下流API、運用体制で条件が変わります。

セキュリティ注意

MCP OAuthのセキュリティは、OAuthを入れた時点で終わりではありません。むしろ、OAuthを入れたことで「許可された操作」の範囲が明確になり、そこからMCP toolの副作用やデータ境界を細かく見る必要が出ます。

注意点は次です。

  • access token、authorization code、refresh tokenをログに残さない
  • user consentとtool実行承認を混同しない
  • read-only toolでも、未信頼入力やprompt injectionを想定する
  • MCPサーバー向けtokenを下流APIの認証に流用しない
  • scope不足時に自動で権限昇格しない
  • key rotation、issuer変更、metadata cache更新の手順を決める
  • multi-tenantではtenant境界をtokenとアプリ側の両方で見る

コスト注意

OAuth自体の金銭コストより、運用コストが効きます。scopeを細かくすると、承認UI、ドキュメント、テスト、問い合わせ対応が増えます。逆にscopeを粗くすると、セキュリティレビューと事故対応のコストが増えます。

小さく始めるなら、read-only tool、限定されたResources、短いtoken lifetime、明確なnegative testから始めるのが現実的です。write toolやadmin操作は、MCP OAuthの接続が安定してから、人間承認と監査ログを付けて追加します。

AI Dev Lab Japanでは、MCPやAIコーディングエージェントの仕様更新、権限設計、検証ログの読み方を継続的に扱っています。更新通知を受け取りたい場合は、記事末尾のニュースレター導線から登録できます。

次に読むなら

参照した主な情報源

  • https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization
  • https://modelcontextprotocol.io/specification/2025-11-25/basic/security_best_practices
  • https://datatracker.ietf.org/doc/html/rfc9728
  • https://datatracker.ietf.org/doc/html/rfc8707
  • https://github.com/modelcontextprotocol/typescript-sdk/blob/main/README.md

更新履歴

Visual確認と更新の記録仕様やSDKは更新されるため、確認日を残します。
  1. 2026年6月15日

    MCP Authorization 2025-11-25版、MCP Security Best Practices、RFC 9728、RFC 8707、MCP TypeScript SDK README、@modelcontextprotocol/sdk 1.29.0を確認して初稿を作成しました。

導入時には利用中のMCP仕様、Authorization Server、SDK versionを確認してください。

  • 2026-06-15: MCP Authorization 2025-11-25版、MCP Security Best Practices、RFC 9728、RFC 8707、MCP TypeScript SDK README、@modelcontextprotocol/sdk 1.29.0を確認して初稿を作成。