MCPのOAuth2認可フローをAmazon Bedrock AgentCore Gatewayで検証してみる
みなさま、こんにちは。自分のMCPをリモートで公開したいなあ、そんなことはありませんか?そこで悩ましい点が、「Remote MCPをセキュアに公開する方法」です。非常に多くの企業が検討を進めているテーマですね。
2025年10月時点では、まだRemote MCPにおける安心安全な認証認可フローは議論が進んでおり、すでにGitHubなど様々な企業がRemote MCPを公開する中、企業によって対応状況はまちまちであり、標準的なフローは定まっていません。
そこで現時点で対応しておくべき標準的な認可フローについて、実装レベルで検証してみました。加えて、私が今後推そうと思っているAmazon Bedrock AgentCore Gateway(以降 AgentCore Gatewayとします)を利用して、この認可フローに準拠してるかも合わせて検証してみたので、その結果をまとめていきたいと思います。
Remote MCPの標準的な認可フローとは?
一般的にローカルMCPにおける課題は以下のようなものでした。
- 事前に発行されたアクセス用トークンを持ち続ける必要がある(Tokenは手動でリフレッシュが必要)
- ローカルモジュールを参照しているので、複数メンバーが利用する場合のバージョン管理や可視性が下がる
対してRemote MCPでは、事前にトークンが不要になり様々なAgentに共通のモジュールを公開できるようになります。これは大きなメリットですね。
では、Remote MCPを公開するにあたって推奨されている認証認可フローはどのようなものでしょうか。MCPの公式ドキュメントでは、以下のような記述がされております。
Overview
- Authorization servers MUST implement OAuth 2.1 with appropriate security measures for both confidential and public clients.
- Authorization servers and MCP clients SHOULD support the OAuth 2.0 Dynamic Client Registration Protocol (RFC7591).
- MCP servers MUST implement OAuth 2.0 Protected Resource Metadata (RFC9728). MCP clients MUST use OAuth 2.0 Protected Resource Metadata for authorization server discovery.
- Authorization servers MUST provide OAuth 2.0 Authorization Server Metadata (RFC8414). MCP clients MUST use the OAuth 2.0 Authorization Server Metadata.
この記事では上記のフローを文章や図で説明するのではなく、実際に実装されたMCPを利用して動きを見ていこうと思います。
実際に認可フローを検証してみる
さきほどのドキュメントから、期待される動作は以下の流れになります。
- MCP ClientからMCP Serverにトークンなしでアクセスした際、HTTP401とともにヘッダーにResource metadata の問い合わせ先が入った状態で買ってくる(RFC9728)
- 1で得たエンドポイントに、認可サーバーの情報を問い合わせ、取得する(RFC9728)
- 認可サーバーに対してAuthorization Server Metadataを問い合わせ、取得する(RFC8414)
- Authorization Server Metadataから取得した
/registerエンドポイントに、クライアント登録のリクエストを送り、認可サーバー側でクライアント登録が完了する(RFC7591) - Authorization Server Metadataから取得した
/authorizeエンドポイントに認可リクエストを送り、認証ページにリダイレクトする - 認証が完了し、アクセストークンを得た状態で元のページに遷移する
これを検証するのに、Cloudflareさんが素晴らしいMCPサーバーのサンプルを公開しているので、こちらを利用していこうと思います。
上記を立ち上げて、MCP Inspectorでアクセスをしてみます。OAuth2のクライアントID/クライアントシークレットや、アクセストークンは特に定義していません。

すると、MCP Server側で以下のログがどどっと出てきます。
[wrangler:info] GET /sse 401 Unauthorized (7ms)
[wrangler:info] GET /.well-known/oauth-protected-resource 404 Not Found (2ms)
[wrangler:info] GET /.well-known/oauth-authorization-server 200 OK (1ms)
[wrangler:info] GET /.well-known/oauth-protected-resource/sse 404 Not Found (1ms)
[wrangler:info] GET /.well-known/oauth-protected-resource 404 Not Found (1ms)
[wrangler:info] GET /.well-known/oauth-authorization-server/sse 404 Not Found (1ms)
[wrangler:info] GET /.well-known/oauth-authorization-server 200 OK (2ms)
[wrangler:info] POST /register 201 Created (11ms)
[wrangler:info] GET /authorize 200 OK (9ms)
一つ一つ見ていきましょう。
[wrangler:info] GET /sse 401 Unauthorized (7ms)
こちらは以下のMCPのドキュメントに書かれているように、トークンを入れない状態でMCPにリクエストをかけると、401のUnauthorized responseとresource metadataが埋め込まれたヘッダーが返ってくるというものです。
WWW-Authenticate Header: Include the resource metadata URL in the WWW-Authenticate HTTP header under resource_metadata when returning 401 Unauthorized responses, as described in RFC9728 Section 5.1.
2.3.1 Authorization Server Location
ただ、今回利用しているMCPサーバーはヘッダーにmetadataを入れていないため、MCP Client側の実装により同じエンドポイントにfallbackされています。
[wrangler:info] GET /.well-known/oauth-protected-resource 404 Not Found (2ms)
こちらは、RFC9728で定義されているProtected Resource Metadata Requestに基づいたリクエストになります。resource metadataに付与されたエンドポイントに対して、具体的な認可サーバーの場所が記載されたmetadataを問い合わせしています。
今回のMCPサーバーでは対応しておらず、前段と同様にMCP Client側で認可サーバーへのアクセスパスにfallbackされています。
[wrangler:info] GET /.well-known/oauth-authorization-server 200 OK (1ms)
こちらは、RFC8414で定義されているAuthorization Server Metadataに基づいたリクエストになります。issuer, authorization_endpoint, token_endpointなどが含まれたmetadataを認可サーバーにリクエストします。
Authorization Metadataの例
{
"issuer":
"https://server.example.com",
"authorization_endpoint":
"https://server.example.com/authorize",
"token_endpoint":
"https://server.example.com/token",
"token_endpoint_auth_methods_supported":
["client_secret_basic", "private_key_jwt"],
"token_endpoint_auth_signing_alg_values_supported":
["RS256", "ES256"],
"userinfo_endpoint":
"https://server.example.com/userinfo",
"jwks_uri":
"https://server.example.com/jwks.json",
"registration_endpoint":
"https://server.example.com/register",
....
}
[wrangler:info] POST /register 201 Created (11ms)
こちらでは、RFC7591で定義されているDynamic Client Registrationをリクエストするためのエンドポイントです。今回のClientをMCP側の認可サーバーに登録してもらうようにリクエストします。
[wrangler:info] GET /authorize 200 OK (9ms)
上記は実際に認可リクエストを送った際に出力されたログです。以下のようなURLが返却されブラウザが遷移していることがわかります。PKCEの形式にそってクライアント側で生成したcode_challengeを送っています。
http://localhost:8788/authorize?response_type=code&client_id=xxxx&code_challenge=xxxx&code_challenge_method=S256&redirect_uri=http%3A%2F%2Flocalhost%3A6274%2Foauth%2Fcallback&state=xxxx
ブラウザ上では、/authorize のレスポンスとしてGitHubへのアクセス許可を確認するページを返してブラウザ上で表示されていることがわかります。

Aprroveをクリックすると、GitHubの認証エンドポイント( https://github.com/login/oauth/authorize)にリダイレクトされ、GitHubの認証画面に飛びます。
https://github.com/login/oauth/authorize?client_id=xxxx&redirect_uri=http%3A%2F%2Flocalhost%3A8788%2Fcallback&scope=read%3Auser&state=xxxxxxxxxx&response_type=code

こちらをログインすると、アクセストークンが付与された状態でもともと開いていたMCP Inspectorの画面にcallbackされていることが確認できます。
http://localhost:6274/oauth/callback?code=kishi-k%3A{client_id}%{secret}&state=xxxxxxxx
試しに Toolsをアクセスすると、上記のトークン情報をヘッダーに入れてアクセスできていることが確認できました。
POST /sse/message?sessionId=3fddd2a701911972a706df7959e7e331c8965a6342cb116f77c5218bbf768e28 HTTP/1.1
Accept: text/event-stream
Authorization: Bearer kishi-k:{client_id}:{secret}
MCP Inspectorでは以下のようになります。

これでURLだけでRemote MCPにアクセスしてから、返ってきたアクセストークンを利用してMCPにアクセスできるところまで確認できました🎉
Amazon Bedrock AgentCore Gatewayの立ち位置
前段ではMCPにおける標準的な認可フローの確認ができました。今後MCPサーバー側がこのフローに準拠しなければいけないということは、自分自身でMCPを公開するときに、これらのリクエストにもMCPサーバー側が答えられるようにしなければいけないということになります。
一方でAWSでは「Amazon Bedrock AgentCore」というAgentやMCPを開発・公開するためのマネージドなサービスが最近GAとなりました。そのうちの一つに、「Amazon Bedrock AgentCore Gateway (以降 AgentCore Gatewayとします)」というMCPifyとしてMCPをマネージドでリモートに公開するサービスがあります。
個人的にAgentCoreのサービス群のうち、AgentCore Gatewayが最も魅力を感じているサービスなので、それについても記載しておきます。
従来ではRemoteMCPを公開するにあたって、以下のような課題を感じていました。
-
Agent側の課題:複数のMCPを扱うことで、アクセス情報が肥大化し管理が煩雑になる。MCP側のアクセス方法も統一化されておらず、Agent側の管理負荷は増すばかり。加えて、Agentごとにアクセス情報の管理を任せることになり、セキュリティリスクが懸念される
-
MCP側の課題:リモートに公開する際、公開方法をセキュアにやらなければならない。MCP側で定められている標準機能を独自で実装する必要がある

これをAgentCore Gatewayを利用することで、Agent側のアクセス管理の負荷、MCP側の共通機能部分の実装をGatewayに集約することができます。そのため、MCPの開発者は個々のMCP機能の実装に集中し、共通部分はAgentCore Gatewayに任せることができます。Agent側も、エンドポイントひとつを意識するだけで様々なMCPを活用することができます。これは個人的に大変魅力的でした。

ただまだGAしたてということもあり、まだすべてのユースケースに対応できているかは怪しいので、今後のリリース機能に期待したいところです。
もしAgentCore Gatewayがこのフローに対応していれば、ユーザー側は認可フローの実装を気にせずMCPに準拠し公開することができますが、このAgentCore Gatewayでは、OAuth2の認可フローに対応状況は公式には言及されていません。なので、試してみることにしました。
AgentCore Gatewayで検証してみる
実際に検証してみましょう。私のほうでAgentCoreでAgent+MCPの構成を簡単に立ち上げるサンプルを作成したので、もしよろしければご活用ください。Gatewayを作成するパートだけ実施いただければ大丈夫です。 この構成では、MCPサーバー側がAgentCore Gateway, 認可サーバー側がAmazon Cognito ユーザープールになります。
まずは、トークンを付与せずAgentCore GatewayのエンドポイントにGETしてみます。
curl -i -X POST https://github-mcp-xxxxxxxxxx.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp \
-H 'Content-Type: application/json'
HTTP/2 401
date: Wed, 15 Oct 2025 12:53:40 GMT
content-type: application/json
content-length: 86
x-amzn-requestid: 3caa9769-cbda-4568-8cb2-4e1149ab28f5
www-authenticate: **Bearer resource_metadata="https://github-mcp-xxxxxxxxxx.gateway.bedrock-agentcore.us-west-2.amazonaws.com/.well-known/oauth-protected-resource"**
x-amzn-remapped-content-type: application/json
{"jsonrpc":"2.0","id":"ping","error":{"code":-32001,"message":"Missing Bearer token"}}
そうするとHTTP 401が返り、ヘッダーにresource_metadataのアクセス先が付与されています。こちらに対して、Resource Metadataをリクエストしてみると、AgentCore Gatewayで設定した認可サーバー(今回はAmazon Cognitoを指定)のエンドポイントが表示されていることがわかります。
curl https://github-mcp-xxxxxxxxxx.gateway.bedrock-agentcore.us-west-2.amazonaws.com/.well-known/oauth-protected-resource
{
"authorization_servers":["https://cognito-idp.us-west-2.amazonaws.com/us-west-2_xxxxxxxxx"],
"resource":"https://github-mcp-xxxxxxxxxx.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp"
}
これで、AgentCore GatewayがRFC9728に準拠していることが確認できました!🎉
ここからはおまけですが今回設定している認可サーバーに対して、認可サーバーのAuthorization Metadataを取得してみます。AmazonCognitoは、OpenID Connectの方式に準拠しているので、以下のようなリクエストを投げます。
curl -i https://cognito-idp.us-west-2.amazonaws.com/us-west-2_xxxxxxxxc/.well-known/openid-configuration
すると、以下のようなメタデータを取得できます。
{
"authorization_endpoint":"https://agentcore-xxxxxxxx.auth.us-west-2.amazoncognito.com/oauth2/authorize",
"end_session_endpoint":"https://agentcore-xxxxxxxx.auth.us-west-2.amazoncognito.com/logout",
"id_token_signing_alg_values_supported":["RS256"],
"issuer":"https://cognito-idp.us-west-2.amazonaws.com/us-west-2_xxxxxxxx",
"jwks_uri":"https://cognito-idp.us-west-2.amazonaws.com/us-west-2_xxxxxxxx/.well-known/jwks.json",
"response_types_supported":["code","token"],
"revocation_endpoint":"https://agentcore-xxxxxxxx.auth.us-west-2.amazoncognito.com/oauth2/revoke",
"scopes_supported":["openid","email","phone","profile"],
"subject_types_supported":["public"],
"token_endpoint":"https://agentcore-xxxxxxxx.auth.us-west-2.amazoncognito.com/oauth2/token",
"token_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post"],
"userinfo_endpoint":"https://agentcore-xxxxxxxx.auth.us-west-2.amazoncognito.com/oauth2/userInfo"
}
Amazon Cognitoを利用することで、RFC8414にも準拠したフローが実現可能そうです。
最後に
公式では記されていませんが、Remote MCPで標準化されつつある認証認可フローを確認し、AgentCore Gatewayでの対応状況を確認しました。AgentCore GatewayにもしMCPの認可フローを集約できれば、AgentCore Gatewayの価値もグッとあがってくると思います。
今回途中で紹介したサンプルは、AgentCoreを活用したAgentとRemote MCPの構成を簡単に実装したサンプルになっています。Agentの本番利用を見据えた最小構成として、ぜひご参考ください。
それでは!
Discussion