エンタープライズMCP認証: エージェントがついにサービスアカウントを手にした
SEP-1046はMCP上の無人エージェントに本物のOAuthを与える。client_credentialsとprivate_key_jwtで何が解決し、何が残り、どう導入するかを解説する。

MCPに、人間を介在させずにエージェントが認証するための仕様化された方法がついに用意された。 SEP-1046はOAuthのclient_credentialsグラントを公式拡張としてModel Context Protocolに追加する。推奨のクライアント認証方式はprivate_key_jwt (RFC 7523のJWTクライアントアサーション)で、互換性のために素のクライアントシークレットも許容される。2025年10月に受理され、ここ数か月でTypeScript、Python、そして今回はRubyのSDKにも実装が入った。エンタープライズでエージェントを運用しているなら、SEP番号を知っていたかどうかに関係なく、これこそが待っていたパズルのピースだ。
本題に入る前に告白しておくと、この記事は危うく書かれずに終わるところだった。エージェント型AIの世界は動きが速く、それについて書くこと自体がスケジューリング問題になっている。SEP-1046は下書きフォルダに眠ったまま、他の3件が先に世に出た。今になって時間を作れたのは、Brad Webbによるエンタープライズ向けMCP認可パターンの概説が読書キューに届き、全体像が読者の時間に見合うほど揃ったからだ。彼の記事もぜひ読んでほしい。この記事は、エンタープライズのチームにとって本当に重要な点に絞った、より短く、より意見の強い私見だ。
GitHubのissueがセキュリティレイヤーになるまで
2025年7月24日、Darin McAdamsがMCP仕様リポジトリにissue #1046を立てた。ここでは提案者の経歴が意味を持つ。McAdamsはAmazonに26年近く在籍し、最後の期間はSenior Principal Software Engineerを務め、アイデンティティセキュリティ企業Defakto SecurityにArchitectとして移る直前の最後の数週間にこの提案を書き上げた。提案は短く、外科手術のように的確だ。元々のMCP認可仕様はclient credentialsフローに触れていたのに、後の改訂で削られ、結果として仕様は、エンタープライズで最もありふれたシナリオについて何も語らなくなっていた。つまり、対話的な同意画面をクリックしてくれるエンドユーザーが不在のまま、ワークロードがMCPサーバーを呼び出す必要があるケースだ。
提案はSEP-1046として受理され、2025年10月30日に確定した。コア仕様の変更ではなく、MCP拡張io.modelcontextprotocol/oauth-client-credentialsとして出荷された。その後、実装が続いた。TypeScript SDKのPrivateKeyJwtProvider、Python SDKのPrivateKeyJWTOAuthProvider、そして直近ではKoichi ITO (RuboCopで知られるkoic)によるコミットが、公式Ruby SDKにprivate_key_jwtサポートを追加し、コンフォーマンスシナリオまで揃えた。提案から受理済みSEPへ、そして共有のコンフォーマンススイートを通る独立した複数実装へ、という流れは、プロトコルが大人になっていく姿そのものだ。2年前、「MCPの認証」と言えば、環境変数に入れたベアラートークンと祈りのことだった。
client credentialsが重要な理由: エージェントはブラウザを持たない
MCPの基本仕様が土台にしているOAuthの認可コードフローは、人間の存在を前提にしている。誰かが同意画面を見て、アイデンティティプロバイダーに対して認証し、自分の権限の一部をクライアントに委譲する。このモデルは、Claude DesktopがあなたのCRMに接続する場面には合う。しかし、エンタープライズが実際にデプロイするワークロードには合わない。夜間の突合処理エージェント、社内MCPサーバーに問い合わせるCIパイプライン、午前3時に専門エージェント群へ処理を振り分けるスーパーバイザーエージェント。誰も起きていないのだから、「許可」をクリックする人はいない。
client credentialsは、あらゆるエンタープライズIAMプレイブックにあるサービスアカウントのパターンを、MCPに適用したものだ。ワークロードは自分自身のアイデンティティを持ち、アイデンティティ基盤に事前登録され、自分自身として認証する。借り物のユーザーセッションも、人間のふりをするヘッドレスブラウザ自動化も、シークレットマネージャーにガムテープで貼り付けた長命のパーソナルアクセストークンもない。エージェントは、自分の権限、自分の監査証跡、自分のライフサイクルを持つ一級のプリンシパルになる。セキュリティチームが「エージェントがDaveとして認証しているから」という理由でMCP展開をブロックしてきたなら、これが彼らに渡すべき答えだ。
private_key_jwt: 正しいデフォルトと、その代償
SEP-1046は、クライアント認証を意図的に2つの選択肢に絞っている。HTTP Basicによるクライアントシークレットは許容される。地球上のすべてのアイデンティティプロバイダーが今日サポートしているからだ。しかし推奨方式はprivate_key_jwtで、クライアントが短命のJWTアサーションを秘密鍵で署名し、シークレットの代わりに提示する。SDK実装の設計の細部は読む価値がある。そこには本物のセキュリティ判断が織り込まれている。
- アサーションは、クライアントIDを設定した
issとsub、認可サーバーのissuer識別子を設定したaud、300秒のexp、一意のjtiを運ぶ。盗まれたアサーションは5分で失効し、リプレイもできない。 - 秘密鍵はクライアントの外に出ることがなく、トークンストレージにも書き込まれない。認可サーバーのデータベースに、ダンプされるのを待つ共有シークレットが眠っていることはない。
client_idはリクエストボディから完全に省かれ、アイデンティティは署名済みアサーションの中を移動する。トークンリクエストはRFC 8707のresourceパラメータも運ぶため、返ってくるトークンは特定の1つのMCPサーバーに束縛され、そのissuerを受け入れるあらゆる相手に使えるものにはならない。
代償は鍵管理だ。非対称鍵には生成、配布、ローテーション、失効が必要になる。そしてSEP-1046は、アサーション検証のためにサーバーがクライアントのJWKSをどう発見するかを、意図的にまだ仕様化していない。それはWIMSEのheadless JWTの作業と、IETFで成熟しつつあるClient ID Metadataドラフトを待っている。実務的には、ほとんどのチームがまずクライアントシークレットで出荷し、アイデンティティ基盤のツーリングが追いついた時点でJWTアサーションに移行することになる。それでいい。仕様化されたアップグレードパスを持った上で今日は互換性のある選択肢を選ぶことと、パスが全くないことは別物だ。
issueスレッドで議論を呼んだ意図的な省略が1つある。mTLSだ。RFC 8705のクライアント証明書をスコープに入れたいというコメントが複数あったが、入れない理由の説明は明快だった。現実のデプロイでは、TLSはCDNかロードバランサーで終端し、MCPが実際に動くアプリケーション層の何ホップも手前にある。インフラの曲芸なしには、サーバーはクライアント証明書を目にすることがない。動く社内PKIを持つエンタープライズは、自社サービス間でmTLSを使い続ければいい。仕様は、その前提を他の全員に背負わせることを拒んだだけだ。
エンタープライズとの接触に耐えるパターン
Webbの記事は、どのプロトコル比較表よりもうまく意思決定を枠付けている。OAuthフローのメニューからではなく、エージェントの権限がどこから発生するかから始めよ、と。他のすべてはその問いから導かれる。エンタープライズのほぼすべてのケースは、3つのパターンでカバーできる。
- ユーザー権限の委譲は対話的ツール向け。人間の権限が認可コードフローを通じてエージェントに流れる。ここでの罠はトークンパススルー、つまり上流のアイデンティティプロバイダーのトークンをそのままMCPサーバーに横流しすることだ。デモでは動くが、本番ではエージェント基盤を他所のトークン形式と信頼モデルに結合してしまう。トークンは、対象のMCPサーバー専用に発行された短命のものに交換し、audience検証を強制すること。仕様のRFC 8707リソースインジケーター要件は、まさに汎用トークンのロンダリングを失敗させるために存在する。
- マシンアイデンティティは無人ワークロード向け。SEP-1046のclient credentialsを使い、
private_key_jwtを優先し、エージェントワークロードごとに1つの登録済みクライアントを持つ。プラットフォーム全体で1つの共有「agents」クライアントを使い回してはならない。爆発半径は登録の粒度に従う。 - デュアルアイデンティティは興味深い中間層向け。ユーザーの代理で動くが、無人で走るエージェントだ。トークンはアクター (エージェント)とサブジェクト (ユーザー)の両方を表現すべきで、これはトークン交換がサポートしており、いまでは多くの認可サーバーが表現できる。監査で「この操作の責任者はどの人間か」に答え続けられるのはこのパターンであり、コンプライアンスチームが実際に尋ねるのはその問いだ。
登録そのものについて。SEP-991は、事前の関係を持たないクライアントとサーバーに対して、OAuth Client ID Metadata Documents、つまりHTTPS URLをクライアント識別子とするパターンを推奨とした。オープンなエコシステムにはエレガントだ。しかし閉じたエンタープライズでは、社内アイデンティティ基盤を通じた事前登録の方が依然として強いデフォルトだ。所有権、許可リスト、ライフサイクル管理が手に入り、メタデータ取得に伴うSSRF懸念という一群を脅威モデルから丸ごと消せるからだ。
SEP-1046は一つの車線であり、道路全体ではない
仕様リポジトリのauthラベルを1時間眺めれば、単一SEPという見方は崩れる。定例で集まる常設のauthワーキンググループがあり、エンタープライズMCP認可の次の一手を描く提案のキューがある。SEP-1488は混在認証サーバー向けにツールメタデータへsecuritySchemesを追加する。公開ツールとOAuthで保護されたツールを一つのサーバーが並べて公開するケースだ。SEP-1489はセッション途中でOAuthフローを起動するツールエラーを標準化する。エージェントの言葉で言えばstep-up認可だ。SEP-2742はリモートサーバーに認証方式の事前宣言を求め、クライアントが接続前に何に向き合うのか分かるようにする。HTTPメッセージ署名はSEP-1415の休眠後、PR #2752として戻ってきた。大きなSEPの合間にも強化は積み上がる。mix-up攻撃を防ぐRFC 9207のissuer検証の必須化(#1721)、RFC 9396のRich Authorization Requests(#1670)、オフラインアクセスのためのrefresh token転送(#1735)、そして認可仕様を土台のOAuth RFC群へ委譲してスリム化する進行中の取り組み(#3054)。企業でエージェントのセキュリティを担っているなら、このissueキューがそのままロードマップだ。自分のバックログを読むように読んでほしい。
月曜日にやるべきこと
組織内にMCPを展開するプラットフォームチームやセキュリティチームがやるべきことを、具体的に挙げる。
- すべてのMCP連携を棚卸しして分類する。対話的か、無人か、代理実行か。フローは分類に従う。決して逆ではない。
- すべての無人エージェントに、アイデンティティプロバイダー上の専用の登録済みクライアントを与える。ツーリングの都合でクライアントシークレットから始めるのは構わないが、
private_key_jwtを今すぐロードマップに載せ、使っているSDKが既に対応しているか確認する。TypeScript、Python、Rubyは対応済みだ。 - 運用するすべてのMCPサーバーでaudience検証を強制する。あるサーバー向けに発行されたトークンは、別のサーバーで失敗しなければならない。これはスタック全体で最も安上がりで、最もよく省略されるコントロールだ。
- 文字列連結のSQLを禁じるのと同じように、コードレビューでトークンパススルーを禁じる。これはエージェントアイデンティティにおけるSQLインジェクションだ。便利で、どこにでもあり、間違っている。
- エージェントの権限はデフォルトで読み取り専用に保ち、すべての変更系パスにゲートを置く。Agents on Callのゲートウェイ回でインフラ層について主張したのと同じ姿勢だ。認証はエージェントが誰かを教えてくれるが、何を許されるべきかについては何も語らない。
より大きな論点はこうだ。毎月どこかのGitHub issueで、「Xがあるからエンタープライズはエージェントを採用できない」の一片が静かに解消されていく。認証は最大のXだった。1年前、「無人エージェントはMCPサーバーにどう認証するのか」への正直な答えは肩をすくめることだった。今では、SEP番号が1つ、クライアント認証方式が2つ、3つのSDKにコンフォーマンステストがある。何をどう作れるのか、私たちは毎週少しずつ学んでいる。こうした継ぎ目が閉じていく様子を追い続けるチームは、完成した教科書を待つチームより1年先に出荷する。教科書が完成する日は来ないからだ。
次に読む
アイデンティティはエージェントセキュリティの半分にすぎない。IAM for LLM Apps: Least Privilege When the Caller Is a ModelはAWSにおける認可の側を扱う。姉妹サイトでは、Agent Toolkit for AWS: The Docs Have a New Readerが、インフラを消費するエージェントがマニュアルの読み手にもなったとき何が起きるかを見ている。そしてercanermis.comには、私がどこで何を書いているかの全体マップがある。
参考資料
- SEP-1046: Support OAuth client credentials flow in authorization (modelcontextprotocol#1046)
- PR #1047: SEP-1046 and SEP-1502, client credentials flow via the MCP extension mechanism
- modelcontextprotocol/ext-auth: the oauth-client-credentials extension
- Ruby SDK commit 4327fc8: private_key_jwt client authentication (Koichi ITO)
- TypeScript SDK #1157: PrivateKeyJwtProvider
- Python SDK #1663: PrivateKeyJWTOAuthProvider
- MCP specification: Authorization
- RFC 7523: JWT Profile for OAuth 2.0 Client Authentication and Authorization Grants
- RFC 8707: Resource Indicators for OAuth 2.0
- Brad Webb: Enterprise MCP authorisation patterns, a detailed synopsis
- MCP spec repo: the auth label (working group notes and open SEPs)
Ercan の他のサイト
同じ著者、別の領域のサイトが2つ。