MCP-OAUTH2-PROXY について
OAuth2 で保護されたリモート MCP サーバーをデスクトップや IDE のクライアントから利用するための、ローカル stdio プロキシです。ブラウザーでの PKCE ログインまたはサービス用認証情報、トークンのキャッシュと更新を処理し、Streamable HTTP の上流へ要求を中継します。
主な機能
- 01ブラウザーでの PKCE ログイン
- 02client_credentials グラント対応
- 03OAuth エンドポイント検出
- 04更新トークンの暗号化キャッシュ
- 05トークン更新と 401 リトライ
- 06Streamable HTTP と SSE の中継
活用シーン
- 01MCP クライアントから OAuth2 保護サーバーへ接続
- 02ブラウザーでログインして MCP サーバーを利用
- 03ユーザーログインなしのサービス間 MCP 接続
MCP 対応
クライアントにはローカル stdio MCP サーバーとして接続し、Bearer トークン付きの JSON-RPC を単一のリモート Streamable HTTP MCP サーバーへ転送します。JSON、SSE 応答と、任意のサーバー起点通知に対応します。
詳細
mcp-oauth2-proxy
リモートの OAuth2 で保護された HTTP MCP サーバー にプロキシする、ローカルの stdio MCP サーバー です。Claude Desktop、Cursor、VS Code Copilot、その他の MCP クライアントに追加すれば、ブラウザーで一度ログインするだけで利用できます。
MCP client ─stdio (JSON-RPC)─▶ mcp-oauth2-proxy ─HTTP+SSE + Bearer─▶ upstream MCP server
│
└─ OAuth2 token endpoint (IdP)
ドキュメント
この README はクイックスタートです。詳しいドキュメントは Wiki にあります。
| ページ | 内容 |
|---|---|
| はじめに | インストール、初回起動、クライアントへの組み込み。 |
| 設定 | 各フィールドと環境変数の説明。 |
| OAuth2 グラントとトークン | グラント、対話型ログイン、トークンとキャッシュのライフサイクル。 |
| ディスカバリー | RFC 9728 / RFC 8414 によるエンドポイントのディスカバリー。 |
| セキュリティ | 脅威モデルと組み込みの防御策。 |
| リモートホスト(SSH ポートフォワーディング) | プロキシがリモートで実行されている場合のログイン方法。 |
| トラブルシューティング | よくある問題と FAQ。 |
| アーキテクチャ · ブリッジ · OAuth2 の内部構造 | 内部の仕組み。 |
| コントリビューションとリリース | 開発環境のセットアップ、テスト、リリースプロセス。 |
目次
機能
- 組み込みのローカルブラウザーコールバックリスナーを使用した 対話型
authorization_code+ PKCE フロー。コードの手動コピー&ペーストは不要です。 - ディスク上の リフレッシュトークンキャッシュ(AES‑256‑GCM、
0600)により、ブラウザーを開くのはマシンごとに一度だけです。 - ヘッドレス環境やサービス間の利用に対応する
client_credentialsグラント。 - 上流サーバーからトークンおよび認可エンドポイントを RFC 9728 + RFC 8414 に基づいてディスカバリー します。通常、OAuth 設定は不要です。
- スキュー、処理中リクエストの重複排除、401 → 無効化 → 再試行ループによる プロアクティブなトークン更新。
- Streamable-HTTP 上流サーバーに対応しています。単一応答の JSON、SSE の
text/event-stream応答、任意の長時間接続のサーバー通知チャネルをサポートします。Mcp-Session-Idを尊重します。 - トークン、シークレット、
Authorizationヘッダーを秘匿する stderr のみのロギング(pino)により、stdout はクリーンな JSON-RPC チャネルとして維持されます。
仕組み
- 検出。 必要に応じて RFC 9728/8414 のメタデータを取得し、
tokenUrl、authorizationUrl、scope、resourceを補完します。 - トークンマネージャー。 設定済みの
Grantを、キャッシュ、 更新時の余裕時間、実行中リクエストの重複排除、401 の無効化機能でラップします。 - 事前取得。 起動時に一度
getToken()を呼び出し、必要な場合は最初の MCP メッセージが届く前に 対話型のブラウザーフローを実行します。 - ブリッジ。 stdin の各 JSON-RPC 行について、
Bearerトークンを付けてupstream.urlに POST します。単一応答の JSON は stdout の 1 行になり、SSE 応答はイベントごとに 1 行になります。401が発生した場合はinvalidate()を呼び出し、 1 回だけ再試行します。 - サーバーストリーム。
initializeの後、サーバー起点の通知を受け取るため、 必要に応じてGET text/event-streamチャネルを開いたままにします。
内部の詳細については、Wiki の アーキテクチャ、 ブリッジの内部、 OAuth2 の内部 をご覧ください。
要件
- Node.js 20+
- Streamable HTTP MCP transport を使用する、OAuth2 で保護された MCP サーバー。
- IdP に登録済みの OAuth2 クライアント。対話型フローを使用する場合は、
リダイレクト URI として
http://127.0.0.1:53682/callbackを登録してください(または、OAUTH2_CALLBACK_PORTに設定した値に合わせてください)。
インストール
インストールは不要です。MCP クライアントから npx を使ってプロキシを
直接起動できます。
npx -y mcp-oauth2-proxy
ローカルのチェックアウトを使って開発する場合:
git clone https://github.com/ChengleiYuan/mcp-oauth2-proxy.git
cd mcp-oauth2-proxy
npm install
npm run build
クイックスタート
対話型ログイン(エンドユーザーに推奨)
UPSTREAM_URL=https://mcp.example.com/mcp \
OAUTH2_GRANT=authorization_code \
OAUTH2_CLIENT_ID=<your-client-id> \
npx -y mcp-oauth2-proxy
初回起動時、プロキシは OAuth エンドポイントを検出し、PKCE ログインのためにブラウザーを開き、
http://127.0.0.1:53682/callback でコードを受け取り、OS の設定ディレクトリに
更新トークンを暗号化してキャッシュした後、ブリッジを起動します。2 回目以降の起動では、
キャッシュ済みトークンを使って、ユーザーに知らせずに再開します。詳細については、
OAuth2 グラントとトークンをご覧ください。
ヘッドレス/サービスアカウント
UPSTREAM_URL=https://mcp.example.com/mcp \
OAUTH2_GRANT=client_credentials \
OAUTH2_TOKEN_URL=https://idp.example.com/oauth2/token \
OAUTH2_CLIENT_ID=my-service \
OAUTH2_CLIENT_SECRET='…' \
OAUTH2_SCOPE='mcp:read mcp:write' \
npx -y mcp-oauth2-proxy
MCP クライアントに接続する
{
"mcpServers": {
"remote-oauth2-mcp": {
"command": "npx",
"args": ["-y", "mcp-oauth2-proxy"],
"env": {
"UPSTREAM_URL": "https://mcp.example.com/mcp",
"OAUTH2_GRANT": "authorization_code",
"OAUTH2_CLIENT_ID": "<your-client-id>"
}
}
}
}
.cmd のシムを解決できない Windows ホストでは(そのため command: "npx"
の起動に失敗する場合は)、明示的な形式を使用してください。
{
"command": "cmd",
"args": ["/c", "npx", "-y", "mcp-oauth2-proxy"]
}
env ブロック内のパスは絶対パスとし、すべてのプラットフォームでスラッシュを使用してください。
設定
プロキシは JSON ファイル(MCP_PROXY_CONFIG)、環境変数、またはその両方で設定できます。
環境変数はファイルの値より優先され、マージ後の設定が検証されます。最小限の設定例:
{
"upstream": { "url": "https://mcp.example.com/mcp" },
"oauth2": {
"grant": "authorization_code",
"clientId": "my-client",
"scope": "mcp:read mcp:write",
"resource": "https://mcp.example.com/mcp"
}
}
より詳しいサンプルについては、config.example.jsonをご覧ください。
よく使われる環境変数:
| 環境変数 | 対応する設定項目 |
|---|---|
UPSTREAM_URL | upstream.url |
OAUTH2_GRANT | oauth2.grant |
OAUTH2_CLIENT_ID | oauth2.clientId |
OAUTH2_CLIENT_SECRET | oauth2.clientSecret |
OAUTH2_TOKEN_URL | oauth2.tokenUrl |
OAUTH2_SCOPE | oauth2.scope |
OAUTH2_RESOURCE | oauth2.resource |
LOG_LEVEL | log.level |
完全なリファレンス: すべてのフィールド、デフォルト値、環境変数については、 Wiki の 設定 ページで説明しています。エンドポイントの自動検出については 検出をご覧ください。 リモートマシンでプロキシを実行しますか?リモートホスト(SSH ポートフォワーディング)をご覧ください。 問題が発生しましたか?トラブルシューティングをご覧ください。
セキュリティ
- トークンはプロキシ自体が取得します。上流の
Authorizationヘッダーは常にプロキシが設定し、クライアントから引き継ぐことはありません。 - アクセストークンはメモリ上にのみ保持されます。リフレッシュトークンは暗号化してキャッシュされます
(AES‑256‑GCM、キー ファイルのモードは
0600)。これは、通常のディスク読み取りを防ぐための 実用的な難読化であり、同じ OS ユーザーで実行されるプロセスから保護するものではありません。 - ループバック以外のホストへの平文の
http://は起動時に拒否されます (ALLOW_INSECURE_HTTP=trueで上書きできます)。https://とループバックへのhttp://は常に許可されます。インタラクティブなコールバックリスナーは、 DNS リバインディングを防ぐためにHostヘッダーを検証します。 - すべてのログは stderr に出力され、トークン、シークレット、
Authorizationヘッダーは マスキングされます。stdout は JSON-RPC 専用です。
完全な脅威モデルと防御策: セキュリティ。
開発
npm install
npm run build # compile TS to dist/
npm run dev # tsx watch
npm test # vitest (unit + integration)
統合テストでは、モックの OAuth2 トークンエンドポイントとモックの MCP 上流をプロセス内で起動し、
PassThrough
ストリームを介して実際のブリッジを実行します。ネットワークは不要です。プロジェクトの構成、
テスト戦略の全容、自動リリースプロセスについては、
貢献とリリースに記載されています。
対象外
- 1 プロセスあたり複数の上流 MCP サーバー
- OS キーチェーンを利用したリフレッシュトークンの保存(DPAPI / Keychain / libsecret)
- mTLS / JWT ベアラー / デバイスコード / ROPC グラント
- HTTP / SSE インバウンドトランスポート(これは stdio MCP サーバーです)
ライセンス
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。