Cloudflare Remote MCP に Access 認証・認可をくっつける
はじめに
Cloudflare Remote MCP server を試しているとき、Cloudflare Access を使えば、すでに Access で保護しているアプリケーション(Self-hosted や WARP)の認証に使われたトークンの再利用ができ、業務フローを円滑化できそうだなと思いました。
探してみたら、すでに OAuth のデモがありました(Access のほかにも)。
私の環境では Access アプリケーションに Entra ID と Email one-time Pin を有効にしています。
Access を使えば複数の IdP を同時に利用できるので、異なる IdP を利用する組織でのアプリケーション共用環境など柔軟に利用でき、便利です。
ざっくりで正確性は欠きますが、下記のような構成です。
ローカルテスト
Access
Access アプリケーションを作ります
- この場合は
SaaS
です
-
OIDC
を選択します
-
リダイレクト URL
には暫定でhttp://localhost/
など入れておきます
後で書き換えます
- 必要な情報をメモします
MCP サーバー
-
アプリケーションを作ります
npm create cloudflare@latest -- my-mcp-server-access -template=cloudflare/ai/demos/remote-mcp-cf-access
-
ローカル用の変数を用意します
各項目に Access アプリケーションでの表示内容を入れます。.dev.varsACCESS_CLIENT_ID=677... ACCESS_CLIENT_SECRET=f9a... ACCESS_TOKEN_URL=https://... ACCESS_AUTHORIZATION_URL=https://... ACCESS_JWKS_URL=https://... COOKIE_ENCRYPTION_KEY=417...
対応は下記のとおりです。
変数キー Access OIDC 項目 ACCESS_CLIENT_ID クライアント ID ACCESS_CLIENT_SECRET クライアント シークレット ACCESS_TOKEN_URL(/token) トークン エンドポイント ACCESS_AUTHORIZATION_URL(/authorization) 認証エンドポイント ACCESS_JWKS_URL(/jwks) キー エンドポイント COOKIE_ENCRYPTION_KEY 自作する e.g. openssl rand -hex 32
-
ローカル起動します。
npx wrangler dev
出力
OAUTH_KV: <Add-KV-ID> [simulated locally]
シミュレートされています。: Using vars defined in .dev.vars : Your worker has access to the following bindings: - Durable Objects: - MCP_OBJECT: MyMCP - KV Namespaces: - OAUTH_KV: <Add-KV-ID> [simulated locally] - AI: - Name: AI [connected to remote resource] - Vars: - ACCESS_CLIENT_ID: "(hidden)" - ACCESS_CLIENT_SECRET: "(hidden)" - ACCESS_TOKEN_URL: "(hidden)" - ACCESS_AUTHORIZATION_URL: "(hidden)" - ACCESS_JWKS_URL: "(hidden)" - COOKIE_ENCRYPTION_KEY: "(hidden)" ❓ Your types might be out of date. Re-run `wrangler types` to ensure your types are correct. ▲ [WARNING] Using Workers AI always accesses your Cloudflare account in order to run AI models, and so will incur usage charges even in local development. ⎔ Starting local server... [wrangler:inf] Ready on http://localhost:8788
出力の最後に
Ready on http://localhost:8788
とあるので、Access アプリケーションにもどり、リダイレクト URL
をhttp://localhost:8788/callback
に設定します。
テスト
-
MCP inspectorを立ち上げます
npx @modelcontextprotocol/inspector@latest
出力
Starting MCP inspector... ⚙️ Proxy server listening on port 6277 🔍 MCP Inspector is up and running at http://127.0.0.1:6274 🚀 New SSE connection
running at http://127.0.0.1:6274
で立ち上がりました。 -
MCP サーバーの接続をテストします
- ブラウザーで
http://127.0.0.1:6274
にアクセス -
Transport Type
にSSE
-
URL
にhttp://localhost:8788/sse
を入力 ➜Connect
- MCP Inspector の接続要求を承認するか ➜ 承認
- Access(および連携する IdP)にリダイレクト ➜ 認証のプロセスを踏む
- リモート MCP サーバーの
add
ツールを利用
無事にアクセスできました。
- ブラウザーで
インターネットにデプロイ
うまくいったらインターネットにデプロイします。
シークレット
- それぞれシークレットを追加します
npx wrangler secret put ACCESS_CLIENT_ID npx wrangler secret put ACCESS_CLIENT_SECRET :
出力
それぞれ値を入れていきます。
✔ Enter a secret value: …
KV
- KV を作成し、バインドします
npx wrangler kv namespace create OAUTH_KV
出力
Resource location: remote 🌀 Creating namespace with title "OAUTH_KV" ✨ Success! Add the following to your configuration file in your kv_namespaces array: { "kv_namespaces": [ { "binding": "OAUTH_KV", "id": "< ID >" } ] }
Add the following to your configuration file
と出てくるので、wrangler.jsonc
に追記します。wrangler.jsonc"kv_namespaces": [ { "binding": "OAUTH_KV", "id": "< ID >" } ],
デプロイ
- デプロイします
npx wrangler deploy
出力
Your worker has access to the following bindings: : Deployed my-mcp-server-access triggers (0.94 sec) https://my-mcp-server-access.<your-subdomain>.workers.dev :
https://my-mcp-server-access.<your-subdomain>.workers.dev
とあるので、Access に戻り、リダイレクト URL
をhttps://my-mcp-server-access.<your-subdomain>.workers.dev/callback
に書き換えます。
テスト
MCP inspector
MPC inspector でアクセスすると、同様に Access での認証・認可プロセスを経由し、Tools を利用できました。
Claude デスクトップ
Claude デスクトップに今回のデモが提供するリモート MCP サーバーを math
として追加します。
Claude デスクトップを再起動すると、リモート MCP サーバが提供するツール(足し算)とローカル MCP サーバーが提供するツール(ファイル操作)を利用させることができました。
おまけ
ユーザーに応じた制御
- AI:
- Name: AI [connected to remote resource]
なんで Workers AI をバインドしているのかな?
みると、下記のコードがありました。
// Dynamically add tools based on the user's login. In this case, I want to limit
// access to my Image Generation tool to just me
// @ts-ignore
if (ALLOWED_EMAILS.has(this.props.email)) {
this.server.tool(
'generateImage',
'Generate an image using the `flux-1-schnell` model. Works best with 8 steps.',
:
async ({ prompt, steps }) => {
// @ts-ignore
const response = await this.env.AI.run('@cf/black-forest-labs/flux-1-schnell', {
prompt,
steps,
})
トークン に含まれる Email 参照し、特定のユーザーだけ画像生成 AI モデル flux-1-schnell を使わせる、というデモのようです。
テスト
- 許可する Email を指定します
- 指定したメールアドレスでログインします
generateImage
ツールを選択できるようになり、画像が生成されました。
- その他のメールアドレスでログインします
最初と同じ様にadd
のみ表示され、generateImage
は利用できません。
JWT の要素 Email などを用いた、アクセスコントロールもできそうです。
(README にもしっかり書いてありました…)
まとめ
お使いのアプリケーションを Access アプリケーション化していくことで、業務体験を効率化しつつセキュア化に向けてコントロールすることができそうです。
ご自身の環境に応じ、いろんな可能性がありそうなので、是非お試しを。
つなげよう、ひろげよう、Access の輪
Discussion