リモートMCPのOAuth認証 — 401起点の流れとClaude CodeのCIMD対応
リモートMCPのOAuth認証を、401応答から認可サーバー発見、CIMD(Client ID Metadata Documents)での登録、PKCE付きトークン取得まで追います。Claude Codeでの挙動も扱います。
リモートMCPサーバーに接続するとき、Claude CodeはAPIキーではなくOAuth 2.1ベースの認可フローでアクセストークンを取得します。トークンなしでリクエストを送ると401が返り、そこから認可サーバーを見つけ、クライアントとして登録し、PKCE(Proof Key for Code Exchange、認可コード横取り対策)付きの認可コードを交換してようやくトークンにたどり着く手順です。MCPの認可仕様は2026-07-28版で改訂されました。Dynamic Client Registration(DCR)を非推奨にし、Client ID Metadata Documents(CIMD)へ主軸を移す変更です。仕様のRFCレベルの中身と、Claude Codeが2025年6月の初対応からどう実装を積み重ねてきたかをまとめます。
なぜリモートMCPにAPIキーでなくOAuthが必要なのか
MCPのトランスポートはstdioとStreamable HTTPが主流で、認可の要不要はここで分かれます。stdio接続はクライアントがサーバーをローカルの子プロセスとして起動するため、ネットワークを介さず環境変数でクレデンシャルを渡せば足ります。MCP仕様自身も、stdioトランスポートの実装には認可フローを適用しないよう求める立場です。
一方Streamable HTTPで接続するリモートサーバーは、クライアントとサーバーが初対面であることが前提です。GitHubやSentry、Slackのようなリモートサーバーは不特定多数のクライアントから接続され、あらかじめクライアントIDを交換しておく関係が成立しません。「初対面の相手にどうやって安全にトークンを渡すか」が、リモートMCPの認可仕様が解く課題です。人間が都度ログインしない連携にはMCPのOAuth Client Credentials拡張 — 人間不在の認証という別の答えもあります。
仕様はOAuth 2.1をベースにしています。保護リソースメタデータ(RFC9728)・認可サーバーメタデータ(RFC8414)・PKCE・Resource Indicators(RFC8707)を組み合わせた答えです。Claude.ai・Claude Desktop・Claude Codeの3面での対応表はMCPとはにまとめてあります。本記事はそのうち、リモートサーバーとのOAuth認可フローの仕組み自体に絞ります。
MCPで401が返るとどうなるか — 認可フローの7段階
リモートMCPの認可フローは、401応答をきっかけに次の7段階で進みます。各段階が異なるRFCに対応しており、どれか1つでも欠けると接続できません。
401からトークン取得までの7段階
- 1
未認証リクエストと401応答
クライアントがトークンなしでMCPサーバーへリクエストを送ると、サーバーは401 Unauthorizedを返します。
WWW-Authenticateヘッダーには保護リソースメタデータのURLが載ります。 - 2
保護リソースメタデータの取得(RFC9728)
ヘッダーの
resource_metadataが示すURL、無ければ/.well-known/oauth-protected-resourceを叩きます。authorization_serversフィールドが認可サーバーの手がかりです。 - 3
認可サーバーメタデータの発見(RFC8414 / OIDC)
/.well-known/oauth-authorization-serverと/.well-known/openid-configurationを優先順位付きで試します。メタデータのissuer値が問い合わせ先URLと一致しなければ、そのメタデータは使いません。 - 4
クライアント登録
Client ID Metadata Documents・事前登録・Dynamic Client Registrationの3方式から選びます。詳しくは次の節です。
- 5
PKCEとresourceパラメータ付きの認可リクエスト
クライアントは
code_challengeを生成し、接続先MCPサーバーの正規URIをresourceパラメータとして認可リクエストとトークンリクエストの両方に含めます(RFC8707)。ブラウザでユーザーが認可すると、認可サーバーはコールバックへ認可コードとiss(発行者識別子)を返します。 - 6
iss検証とトークン交換
クライアントは事前に記録した発行者識別子と
issを突き合わせ、一致しなければコードをトークンエンドポイントへ渡しません(RFC9207)。一致すればcode_verifierとresourceを添えてトークンを要求します。 - 7
Bearerトークンでのリクエスト
以降のMCPリクエストには
Authorization: Bearer <token>ヘッダーを毎回付けます。トークンをURLのクエリ文字列に含めることは、仕様で禁止されています。
クライアント登録の3方式とDCR非推奨
クライアントは認可リクエストを送る前に、認可サーバーへ自分の身元を示すクライアントIDを持っている必要があります。仕様は3つの登録方式と優先順位を定義しています。
| 方式 | 事前関係 | 仕組み |
|---|---|---|
| 事前登録 | 事前関係必要 | 仕組み固定のclient_id / client_secretをハードコードするか、UIで入力する |
| Client ID Metadata Documents(CIMD) | 事前関係不要 | 仕組みhttpsのURLをclient_idとして使い、認可サーバーがそのURLからJSONメタデータを取得・検証する |
| Dynamic Client Registration(DCR) | 事前関係不要 | 仕組みPOST /registerでクライアント情報を送信し、認可サーバーがclient_idを発行する |
優先順位は「事前登録済みなら事前登録 → 認可サーバーがCIMDに対応していればCIMD → DCRに対応していればDCR → どれも無ければユーザーに手入力させる」の順です。2026-07-28版の仕様は、DCR(RFC7591)をクライアント登録メカニズムとして非推奨にしました。CIMDに対応していない認可サーバーとの後方互換にのみ残す位置づけです。廃止までの猶予期間は12か月以上あり、既存のDCR対応サーバーがすぐ動かなくなるわけではありません。
CIMDが解決するのは、DCRの構造的な弱点です。DCRで発行されたクライアントIDは、発行した認可サーバーに紐づきます。仕様は「クライアント認証情報は発行元の認可サーバーのissuer識別子で管理し、認可サーバーが変わったら再登録が必要」と定めており、サーバーを乗り換えるたびに登録し直す手間が生じます。CIMDのクライアントIDは自分がホストするHTTPS URLそのものなので、認可サーバーが変わってもURLは変わらず、再登録が不要です。
Claude CodeがCIMDに対応したのはv2.1.81(2026年3月)で、DCR非対応サーバーへの主要な回避策として実装されました。DCRにもCIMDにも対応していないサーバーでは、開発者ポータルで事前にOAuthアプリを登録し、発行された認証情報を渡します。
# 事前登録した client_id / client_secret でリモートサーバーを追加
claude mcp add --transport http \
--client-id your-client-id --client-secret --callback-port 8080 \
my-server https://mcp.example.com/mcpCIMDとは何か — Claude Codeでの使われ方
CIMD(Client ID Metadata Documents)は、クライアントIDを自分がホストするHTTPS URLにする登録方式です。認可サーバーはそのURLを取りに行き、返ってきたJSONでクライアントの身元を確かめます。
Claude CodeはDCRに頼れないサーバーで、CIMDを自動で見つけて使います。利用者が設定するものはありません。DCRにもCIMDにも対応しない場合だけ、事前登録の認証情報が要ります。
仕様が求める条件は次のとおりです。
- クライアントIDのURLは
httpsで、パス部分を含む(例:https://example.com/client.json) - そのURLが返すJSONに、
client_id・client_name・redirect_urisを含める - 認可サーバーは、メタデータの
client_id_metadata_document_supportedをtrueにして対応を宣言する
クライアントは、この宣言を見てCIMDを選びます。サーバーがCIMD対応かどうかは、認可サーバーメタデータを取得すると確かめられます。
curl -s https://auth.example.com/.well-known/oauth-authorization-server \
| grep client_id_metadata_document_supportedtrueが返れば、Claude Codeは追加の設定なしでCIMDを使います。項目自体が無いサーバーは、DCRか事前登録で接続することになります。
スコープの決め方と追加認可(step-up)の流れ
MCPクライアントは、必要最小限のスコープだけを要求する原則(least privilege)に従います。優先順位は明確です。まず401応答のWWW-Authenticateヘッダーにあるscopeパラメータを使い、それが無ければ保護リソースメタデータのscopes_supported全体を使います。
Claude Codeはこの原則をv2.1.196(2026年6月)で仕様どおりに徹底しました。それ以前は、自動発見した認可サーバーメタデータのscopes_supportedカタログを丸ごと要求していました。その結果、GitLab self-hosted等の一部のエンタープライズIdPで問題が起きていました。MCPのEnterprise Authorization拡張 — IdPで一元管理する仕組みも参考になります。管理者専用やテンプレート用のスコープまで宣伝するID基盤が、invalid_scopeエラーで認可リクエストを拒否していたのです。現在はWWW-Authenticateか保護リソースメタデータが示す範囲だけを要求し、どちらも無ければscopeパラメータ自体を送りません。
組織のセキュリティ方針でスコープをさらに絞りたい場合は、.mcp.jsonのoauth.scopesにスペース区切りの文字列を設定します。認可サーバーがより広いスコープを宣伝していても、要求範囲をその設定に固定できるからです。認可サーバーがoffline_accessをscopes_supportedに含めている場合、Claude Codeはこれを自動で追加します。ブラウザでの再ログインなしにトークンを更新するための措置です。
実行中のツール呼び出しが403 insufficient_scopeで拒否されると、クライアントは不足分のスコープを既存のスコープと合わせて要求し直します。これがstep-up認可フローです。仕様は「前回までに要求したスコープと、今回のエラーが示すスコープの和集合を取る」ことを求めており、再認可のたびに以前の権限が失われないようにする設計です。Claude Codeも、固定したoauth.scopesの範囲内でこの再認可を行います。
Claude CodeでリモートMCPを認証する手順
OAuth対応のリモートサーバーは、追加してからセッション内で/mcpを実行し、ブラウザでログインするだけで接続が完了します。取得したトークンは安全に保存され、期限が切れると自動で更新されます。RailwayのMCPサーバーもこの方式で、接続手順はRailwayのMCPサーバーが扱います。
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp/mcpセッションを開かずに認証したい場合は、claude mcp login <name>がシェルから直接OAuthフローを実行します(v2.1.186から)。SSHセッションやディスプレイの無いLinux環境ではローカルブラウザが検出できないため、認可URLをそのまま表示するモードに自動で切り替わります(v2.1.191)。--no-browserを付けると、ブラウザがある環境でも強制的にこのモードにできます。
claude mcp login sentry --no-browser--callback-portは特定のリダイレクトURIをあらかじめ登録しているサーバー向けに、コールバックポートを固定するオプションで、既定ではポートはランダムに選ばれます。一方、.mcp.jsonでheaders.Authorizationを設定したサーバーがそのヘッダーを拒否した場合、Claude CodeはOAuthへフォールバックせず、接続失敗として報告します。トークンの有効性を確認するか、OAuthを使うならヘッダー設定を外します。
非対話モード(claude -pやAgent SDK実行)には/mcpパネルが無いため、Claude Code自身が認可フローを代行できません。v2.1.196からは、ツール検索が有効な状態で未認証のサーバーがあると、Claudeにそのサーバーのツールが使えないことを伝えるようになりました。設定が読めていないかのように振る舞う代わりに、どのサーバーへのサインインが必要かを名指しできます。サインイン自体は対話セッションの/mcpかclaude mcp loginで完了させます。
Claude Codeにclaude.aiのサブスクリプションでログインしていれば、claude.aiで追加して認証済みのコネクタ(Google Drive・GitHub・Slack等)は自動的に使えます。APIキーやapiKeyHelper、Bedrockなどのサードパーティプロバイダー、claude setup-tokenで得たCLAUDE_CODE_OAUTH_TOKENが有効なときは読み込まれません。ただしMicrosoft 365・Gmail・Google Calendarは例外です。アップストリームのIDプロバイダーがclaude.aiの登録済みリダイレクトURLしか受け付けないため、Claude Codeからのローカル認証には対応していません。
これらのホストを指すサーバーにサインインすると、is Anthropic-hosted and doesn't support local OAuthと表示されます。先にclaude mcp remove <name>で自分の登録を外し、claude.aiのコネクタ画面(claude.ai/customize/connectors)で接続します。外さないと、同じURLのコネクタが隠れたままになります。
v2.1.287のclaude mcpで確認できるOAuth関連オプション
手元のv2.1.287で、サブコマンドのヘルプだけを実行して確認しました。ログインやサーバー追加は行っていません。
claude mcp login --helpUsage: claude mcp login [options] <name>
Authenticate with an MCP server (HTTP, SSE, or claude.ai connector)
Options:
-h, --help Display help for command
--no-browser Print the authorization URL instead of opening a browser (for
SSH/headless sessions — paste the redirect URL back when
prompted)対象に「claude.ai connector」が入っている点に注目できます。claude mcp add側のヘルプでは、OAuthに関わるオプションは次の3つです。
--callback-port <port> Fixed port for OAuth callback (for servers
requiring pre-registered redirect URIs)
--client-id <clientId> OAuth client ID for HTTP/SSE servers
--client-secret Prompt for OAuth client secret (or set
MCP_CLIENT_SECRET env var)
-t, --transport <transport> Transport type (stdio, sse, http). Defaults to
stdio if not specified.--transportが受け付けるのはstdio・sse・httpの3種類で、WebSocketはありません。--client-idの説明は「HTTP/SSEサーバー向け」です。シークレットは引数に直接書かず、プロンプトか環境変数MCP_CLIENT_SECRETで渡す作りになっています。保存済みの認証情報を消すclaude mcp logout <name>も同じ階層にあります。ヘルプの説明は「Clear stored OAuth credentials for an MCP server」です。
Claude CodeのOAuth対応はどこまで自動化されたか
Claude Codeのリモートサーバー対応は2025年6月のOAuth初対応から始まり、1年強かけて仕様の主要な要素を取り込んできました。
Claude CodeのリモートMCP OAuth対応の積み上がり
- 2025年6月v1.0.27 リモートMCPサーバー(SSE・HTTP)がOAuthに対応
- 2025年6月v1.0.35 認可サーバーの自動発見に対応
- 2026年2月v2.1.30 事前設定クレデンシャル(--client-id / --client-secret)を追加
DCR非対応サーバー向けです。
- 2026年2月v2.1.49 step-up認可とディスカバリーキャッシュに対応
- 2026年2月v2.1.63 コールバック失敗時にURLを手動で貼り付けるフォールバックを追加
- 2026年3月v2.1.69 authServerMetadataUrl でメタデータ発見を上書き可能に
- 2026年3月v2.1.81 Client ID Metadata Document(CIMD)に対応
- 2026年3月v2.1.85 RFC9728の保護リソースメタデータでの発見に対応
RFC9728を優先し、RFC8414へフォールバックする発見チェーンが揃いました。
- 2026年6月v2.1.186 claude mcp login でシェルから直接OAuthを実行可能に
- 2026年6月v2.1.196 scopes_supported の丸ごと要求をやめ、invalid_scope を回避
- 2026年7月v2.1.206 一過性のトークン更新エラーで再認証扱いにしない修正
以前はセッションの終わりまで、認証が必要なサーバーとして扱われていました。
CIMDへの対応は2026年3月、スコープ要求の見直しは6月で、仕様の変化に実装が少し遅れて追いかける形です。ADFSやGitLab self-hostedのようなエンタープライズIdP向けの修正は、v2.1.97やv2.1.196のように後から入っています。
エンタープライズ環境でよくあるつまずき
認可サーバーが企業の内製IDプロバイダーだと、公開SaaS向けの実装では想定していない挙動に当たりやすくなります。まず、Claude Codeがどの応答を「サインインが必要」と見なすかを分けておくと切り分けが早くなります。
401・403を受けたときの扱いの違い
OAuthの入口に案内される
未サインインのサーバーは、401でも403でも/mcpに「認証が必要」として並びます。サインイン済みのサーバーが401を返したときは、保存済みトークンを更新して一度だけ再試行し、それも失敗した場合にだけ並びます。
接続失敗として報告される
headersやheadersHelperでAuthorizationを自分で設定したサーバーは、401や403でも認証待ちにはなりません。接続失敗として扱われ、直すのは設定した側の資格情報です。ヘルパーの場合のエラー文と切り分けはheadersHelperのServer rejectedエラーにあります。
claude.aiコネクタには例外が2つあります。claude.ai側がセッションのトークンを拒否した401では、認証待ちになりません。クラウドセッションに届いたコネクタの再認可は、claude.ai側で行います。
症状ごとの原因と対処は次のとおりです。
- 「Incompatible auth server: does not support dynamic client registration」: 認可サーバーがCIMDにもDCRにも対応していません。開発者ポータルで事前にOAuthアプリを登録し、
--client-idと--client-secret、登録済みリダイレクトURIと一致する--callback-portを指定して追加し直します invalid_scopeで認可リクエストが拒否される: 認可サーバーが管理者専用スコープまでscopes_supportedに宣伝しているケースで、v2.1.195以前ではその全体を要求してしまっていました。v2.1.196以降なら、自動発見したメタデータからは要求しません- リダイレクトURIの不一致で拒否される: v2.1.229だけ、コールバックを
http://127.0.0.1:PORT/callbackで送っていました。リダイレクトURIを完全一致で照合するサーバーはこれを弾き、v2.1.231でlocalhostの形に戻っています OAuth callback port <port> is already in useで始まる失敗:--callback-portや環境変数MCP_OAUTH_CALLBACK_PORTでポートを固定していると起きやすくなります。メッセージ中のlsof -ti:<port> -sTCP:LISTENで占有プロセスを探せます。Windowsではnetstat -ano | findstr :<port>が案内されますNo available ports for OAuth redirect: ローカルの127.0.0.1でリッスンできないときの失敗です。セキュリティソフトやサンドボックスの方針が原因になり得ます。v2.1.268より前は、OSに任せたポートへのフォールバックが無く、WindowsでHyper-Vが予約したポート範囲に当たった場合にも出ることがありましたauthServerMetadataUrlを設定したのに再起動後に効いていない: v2.1.97 / v2.1.98で修正された、トークン更新時に設定が読み込まれない不具合です。ADFSのような独自のディスカバリー経路を持つIdPで顕在化していました。設定の書き方と効き方はauthServerMetadataUrlでMCPのOAuth検出を指定する手順にあります- 複数のOAuth対応MCPサーバーを使うとキーチェーンが壊れる(macOS): 大きなOAuthメタデータが
securityコマンドの標準入力バッファを超え、認証情報が破損する不具合でした。他にもキーチェーンの競合や読み取りタイムアウトの修正が複数バージョンに分かれて入っています - リフレッシュトークンが拒否された: 通知で
/mcpが案内されるので、サーバーを選んでRe-authenticateを実行します。ツール呼び出しの途中で切れたときは、MCP server "<name>" needs you to sign in again (run /mcp to re-authenticate)が出ます
v2.1.193以降は、認証が必要な設定済みサーバーがあると起動時に通知が出ます。通知は各サーバーにつき1回で、/mcpには認証待ちのサーバーが全部並びます。
よくある質問
すべてのトランスポートでOAuthが使えるか
使えません。OAuthに対応するのはStreamable HTTP(と後方互換のSSE)だけです。サーバーからClaudeへ予告なくイベントを送るWebSocketトランスポートは、双方向の常時接続という性質上、OAuthもclaude mcp add --transportフラグも非対応です。認証には別の方式を用意する必要があります。
同じサーバーをClaude Codeとclaude.aiの両方に追加したらどちらが優先されるか
同じURLを指すサーバーがClaude Code側にもclaude.aiのコネクタ側にも存在する場合、Claude Code側で追加したものが優先されます。コネクタは/mcpで非表示(hidden)として一覧に出て、重複を外す方法も併せて示されます。
OAuthトークンを取り消したいときはどうするか
/mcpメニューの「Clear authentication」で、そのサーバーへのアクセスを取り消せます。シェルからならclaude mcp logout <name>が保存済みのOAuth認証情報を消します。次回接続時はブラウザでの認可からやり直しです。
認可後のブラウザリダイレクトが失敗したらどうするか
自動的なlocalhostへのリダイレクトが接続エラーで失敗した場合でも、認可自体はサーバー側で完了しています。ブラウザのアドレスバーに表示されているコールバックURLをコピーし、Claude Codeが表示するURL入力プロンプトに貼り付ければ、そのまま認証を完了できます。
組織はメンバーが使えるコネクタのツールを制限できるか
組織はclaude.aiコネクタのツールごとに「ask」または「blocked」を設定できます。Claude Codeは起動時にこの設定を読み、ローカルで強制します。
- ask: 呼び出しのたびに
Your organization requires approval for this toolという理由で確認が出ます。acceptEdits・auto・bypassPermissionsでも省略されず、「今後は確認しない」の選択肢もありません。一致する許可ルールがあっても確認は消えず、確認を出さないdontAskモードでは拒否になります - blocked: Claudeがツールを見る前に除外されます。
/mcpのツール一覧にはdisabled by your organizationとして残ります
例外はデスクトップアプリのローカル・SSHセッションです。blockedはアプリ側で外されますが、askはClaude Codeに届かず、通常の権限ルールが適用されます。
まとめ
日常の接続はclaude mcp addと/mcpで済みます。DCRにもCIMDにも対応しない認可サーバーや企業IdPが相手のときだけ、事前登録クレデンシャルとスコープ固定が要ります。失敗したときは、エラー文言と、サインイン済みかどうかの2点から切り分けられます。
claude mcp addの全オプションとスコープ管理はClaude Code MCP設定ガイドにあります。症状別の切り分けはMCPサーバーに接続できないときの切り分け手順、OAuth対応サーバーを作る側の実装はMCPサーバー自作ガイドが扱っています。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。
- modelcontextprotocol.io/specification/2026-07-28/basic/authorization
- modelcontextprotocol.io/specification/2026-07-28/basic/authorization/client-regist…
- modelcontextprotocol.io/specification/2026-07-28/basic/authorization/authorization…
- modelcontextprotocol.io/specification/2026-07-28/changelog
- code.claude.com/docs/en/mcp
- code.claude.com/docs/en/changelog
- code.claude.com/docs/en/errors