remote MCP server を社内で使い始めると、最初は「OAuth でログインできるか」だけを見がちです。ですが、実務で止まりやすいのはログイン後です。どの scope を要求するのか、MCP server と下流 API の token を混ぜていないか、write tool だけ後から追加承認へ戻せるか、401 と 403 をどう扱うか。ここを曖昧にすると、MCP は便利な接続面ではなく、権限の抜け道になります。
この記事では、MCP の authorization / OAuth scope 設計 に絞って整理します。MCP server を組織で許可する台帳は MCP サーバーカタログ設計ガイド、MCP 全体の認証・監査・配布統制は MCP エンタープライズ運用ガイド、未信頼入力や tool poisoning は MCP prompt injection 対策ガイド、Claude Code から接続する手順は Claude Code MCP ガイド に分けています。
今回は、remote MCP server を OAuth 2.1 の protected resource として扱い、scope、resource indicator、audience validation、step-up authorization、token passthrough 禁止をどう運用設計に落とすかだけを扱います。
先に結論: MCP authorization は「ログイン」ではなく「どの resource へ何を許すか」
私なら、remote MCP の authorization は次の5点で設計します。
| 設計項目 | 決めること | 事故りやすい状態 |
|---|---|---|
| resource | MCP endpoint の正規 URL | 同じ token を複数 server で使い回す |
| authorization server | どの IdP / tenant が token を発行するか | server ごとに issuer が曖昧 |
| scope | read / draft / write / admin の最小権限 | mcp:* のような広い scope |
| audience validation | token の aud がその MCP server 宛てか | 下流 API token をそのまま受ける |
| step-up | 追加権限が必要なときの 403 と再承認 | write tool が黙って失敗または通る |
OAuth によるログインは入口でしかありません。MCP authorization の本体は、MCP server がどの resource で、どの token なら受け付け、どの操作で追加 scope を要求するかです。
現行仕様で押さえるべき4つの部品
2026-07-28 の MCP authorization 仕様では、protected MCP server は OAuth 2.1 の resource server として扱われます。authorization server は user interaction と token 発行を担い、MCP client は resource owner の代理で protected resource request を投げます。
実装で見るべき部品は4つです。
1. Protected Resource Metadata
MCP server は OAuth 2.0 Protected Resource Metadata を実装し、どの authorization server を使うかを client に示します。client は 401 応答の WWW-Authenticate header にある resource_metadata を優先し、なければ well-known URI を探します。
実務では、ここを「MCP server の名刺」として扱います。
{
"resource": "https://mcp.example.com/github",
"authorization_servers": ["https://idp.example.com"],
"scopes_supported": ["repo:read", "issues:read", "pull_requests:write"]
}
この metadata がない remote MCP は、どの authorization server と組み合わせる前提なのかが見えません。個人検証なら手元設定で逃げられても、組織配布では catalog に載せにくいです。
2. WWW-Authenticate による 401 challenge
未認証の client が protected MCP endpoint に来たら、server は 401 と WWW-Authenticate で authorization 情報を返します。MCP 仕様では、resource_metadata に加えて scope を返す設計も示されています。
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource",
scope="repo:read issues:read"
これにより client は、最初から過大な scope を要求せず、今の resource に必要な scope だけを選びやすくなります。
3. resource indicator と audience validation
MCP authorization で特に重要なのは、token がその MCP server 宛てに発行されたものかを確認することです。MCP 仕様は、client が authorization / token request に resource parameter を含め、server が token の audience を検証する前提を置いています。
ここを省くと、別 API 用の token、別 tenant 用の token、別 MCP server 用の token が通ってしまう可能性があります。
私なら、remote MCP server では最低限これを検証します。
type TokenClaims = {
iss: string;
aud: string | string[];
scope?: string;
exp: number;
sub?: string;
};
function assertTokenForMcpServer(claims: TokenClaims, expected: URL) {
const audiences = Array.isArray(claims.aud) ? claims.aud : [claims.aud];
if (!audiences.includes(expected.toString())) {
throw new Error("access token audience does not match this MCP resource");
}
if (claims.exp * 1000 < Date.now()) {
throw new Error("access token expired");
}
}
本番では JWT 検証、introspection、issuer / key rotation、clock skew も見ます。ここでの要点は、認証済み token かどうかではなく、この MCP resource 用の token かどうかを見ることです。
4. 403 insufficient_scope と step-up authorization
初回は read-only でつながり、write tool を使う段階で追加 scope が必要になる。これは remote MCP では自然な流れです。
このとき、server は黙って generic error を返すのではなく、403 と insufficient_scope を返します。
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope",
scope="pull_requests:write",
resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource"
client はこの情報をもとに step-up authorization を試みます。実務では、ここを human approval とつなげるのが重要です。write scope が必要になった瞬間に、人間へ「どの tool が、どの resource に、どの scope を追加要求しているか」を見せます。
token passthrough を禁止する
remote MCP の実装で一番やってはいけないのは、client が持っている下流 SaaS の access token を MCP server にそのまま渡し、MCP server がそれをさらに下流 API へ流すことです。
MCP 仕様では、client は MCP server の authorization server から発行された token 以外を MCP server に送るべきではなく、MCP server も自分の resource 用ではない token を受け入れたり転送したりしてはいけない、という境界が置かれています。
この禁止の意味は実務上かなり大きいです。
- GitHub token を MCP server に丸投げしない
- Google Drive token を汎用 proxy server に渡さない
- IdP token を MCP server から別 API へ横流ししない
- user token と service token の監査主体を混ぜない
token passthrough を許すと、誰が何を許可したのか、どの resource に向けた token なのか、下流 API での操作主体が誰なのかが崩れます。便利に見えますが、後から監査できません。
scope は tool risk tier から逆算する
OAuth scope は IdP や API の都合だけで決めると広くなります。MCP では、tool の危険度から scope を逆算した方が安全です。
私なら、MCP tool を次のように分けます。
| tool tier | MCP tool の例 | scope の考え方 |
|---|---|---|
| read | issue / docs / customer record の検索 | read:* だけ。write scope を混ぜない |
| inspect | diff / audit / config の確認 | read より狭く、対象 resource を限定 |
| draft | PR comment 下書き、CRM 更新案の生成 | API write ではなく draft 保存に限定 |
| write | PR comment 投稿、ticket 更新 | 操作別 scope と human approval を要求 |
| external action | 配信、課金、削除、本番変更 | 原則禁止。必要なら個別承認と短命 token |
この分け方は AIエージェント tool risk tier 設計ガイド と同じ考え方です。MCP authorization では、それを OAuth scope と 401/403 の設計に接続します。
たとえば GitHub MCP を1つだけ許可するのではなく、catalog と scope を分けます。
mcp_servers:
github_readonly:
resource: https://mcp.example.com/github-readonly
scopes:
- repo:read
- issues:read
allowed_tools:
- search_issues
- read_pull_request
github_pr_writer:
resource: https://mcp.example.com/github-pr-writer
scopes:
- pull_requests:write
allowed_tools:
- create_pr_comment
approval:
required: true
approver: repo_owner
同じ vendor でも、read server と write server を分けると運用がかなり楽になります。scope も audit log も approval も、resource 単位で追えるからです。
401 と 403 を運用上の signal にする
MCP authorization では、401 と 403 をただの HTTP error として扱わない方がよいです。
| status | 意味 | 運用上の扱い |
|---|---|---|
| 401 | token がない、無効、期限切れ | login / refresh / re-auth へ戻す |
| 403 | token はあるが scope が足りない | step-up と human approval へ戻す |
| 400 | request が壊れている | client 実装か tool schema を直す |
特に 403 は、MCP server が「この操作には追加 scope が必要」と説明する signal です。ここを permission denied の一文で潰すと、client は再承認すべきか、ユーザーに聞くべきか、そもそも禁止すべきか判断できません。
私は 403 を監査ログにも残します。
{
"event": "mcp_scope_challenge",
"resource": "https://mcp.example.com/github-pr-writer",
"tool": "create_pr_comment",
"current_scopes": ["repo:read"],
"required_scopes": ["pull_requests:write"],
"decision": "waiting_human_approval"
}
このログがあると、後から「なぜ追加承認が出たのか」「どの scope が増えたのか」「誰が許可したのか」を追えます。
local stdio と remote HTTP で auth の前提を分ける
MCP authorization は HTTP transport 向けの話です。local stdio server は同じ OAuth flow を必ず使う前提ではありません。
ここを混ぜると設計が歪みます。
| transport | 認証の主な置き場所 | 向いている用途 |
|---|---|---|
| stdio | ローカル環境変数、OS keychain、client 設定 | 個人端末の補助 tool、閉じた開発補助 |
| remote HTTP | OAuth、Protected Resource Metadata、resource indicator | 組織配布、SaaS 連携、監査対象 |
stdio は簡単ですが、組織配布では「誰がどの token を使っているか」が端末に寄りやすいです。remote HTTP は実装が重い代わりに、authorization server、scope、audience、ログを中央で扱いやすい。
Claude Code から MCP を追加する具体手順は Claude Code MCP ガイド で扱っています。この記事では、remote HTTP を組織で許可するなら OAuth 境界まで持つべき、という設計判断だけを押さえます。
実務テンプレ: remote MCP を許可する前の authorization review
私なら、remote MCP server を組織に入れる前に次のチェックを通します。
- Protected Resource Metadata を公開しているか
authorization_serversが明示されているかresourceが MCP endpoint と一致しているか- client が authorization / token request に
resourceparameter を付けるか - server が token の audience を検証するか
- scope が read / draft / write / admin に分かれているか
- write tool で 403
insufficient_scopeを返せるか - step-up authorization に retry limit があるか
- token passthrough をしていないか
- scope challenge と承認結果を audit log に残すか
この10項目が見えない server は、個人検証までに留めます。組織標準に入れるなら、MCP サーバーカタログ設計ガイド の catalog 行にも同じ情報を持たせます。
ありがちな失敗
mcp:tools だけで全 tool をまとめる
最初の PoC では動きますが、read と write の差がなくなります。最低でも read / write / admin は分けます。
401 と 403 を同じエラーにする
401 は認証の問題、403 は scope の問題です。client 側の UX も監査ログも分けた方がよいです。
下流 API の token をそのまま受ける
token passthrough は避けます。MCP server 宛ての token を受け、必要なら server 側で適切な downstream credential を管理します。その credential も resource / user / service account の責任境界を分けます。
scope を prompt で補う
「危険な操作はしないで」と prompt に書いても、OAuth scope にはなりません。prompt は意図を伝えるだけです。止める場所は authorization server、MCP server、tool policy、approval gate に置きます。
まとめ: MCP authorization は AI エージェントの実行境界になる
MCP authorization は、ログイン画面を出すためだけの仕様ではありません。remote MCP server を protected resource として扱い、scope、resource indicator、audience validation、401/403、step-up authorization を使って、AI エージェントがどこまで外部 system を操作できるかを決める実行境界です。
私なら、まず read-only の remote MCP を1つ選び、Protected Resource Metadata、audience validation、403 insufficient_scope、audit log まで通します。そこから write tool を足す。最初から広い scope を渡して「後で運用で縛る」は避けます。
MCP を組織で安全に広げるには、server catalog、prompt injection 防御、監査ログだけでは足りません。authorization を「ログインできるか」ではなく「どの resource に、どの scope で、どの操作を許したか」として設計することが必要です。