目次
- 1. はじめに
- 2. アーキテクチャ概要
- 3. 前提条件と環境準備
- 4. 保護されたToDo APIの構築
- 5. リモートMCPサーバーの実装
- 6. 認証フローとOAuth 2.0の理解
- 7. エンドツーエンドのテスト
- 8. Cloud Desktopとの統合
- 9. まとめと次のステップ
1. はじめに
人工知能(AI)アプリケーションが普及するにつれて、これらのアプリケーションを外部APIやサービスに安全に接続する必要性が高まっています。Model Context Protocol(MCP)は、大規模言語モデル(LLM)を外部ツールやAPIと標準化された方法で接続するためのプロトコルです。
しかし、MCPを使用する際の重要な課題の一つがセキュリティです。AIアプリケーションが外部サービスに接続するとき、適切な認証と認可が必要です。
この記事では、Auth0の認証サービスとCloudflare Workersのサーバーレスプラットフォームを使用して、セキュアなクラウドネイティブなMCPサーバーを構築する方法を説明します。このアプローチにより、AIアプリケーションは認証されたユーザーの代わりに安全に外部APIを呼び出すことができるようになります。
具体的なユースケースとして、AIアプリケーション(Cloud Desktop)を保護されたToDo APIに接続するリモートMCPサーバーを実装します。このパターンは、様々な外部APIやサービスにAIアプリケーションを接続するための基盤となります。
2. アーキテクチャ概要
私たちが構築するシステムは、以下のコンポーネントで構成されています:
主要コンポーネント 🔍:
-
Cloud Desktop: MCPクライアントとしてのAIアプリケーション。ローカル接続のみをサポートするため、外部のAPIに直接接続できません。
-
MCP Remote: ローカルMCPクライアントとリモートMCPサーバーの間のギャップを埋める軽量プロキシ。HTTP/SSEリクエストをリモートMCPサーバーに転送し、認証・認可を処理します。
-
リモートMCPサーバー: Cloudflare Workersにデプロイされ、Auth0との認証フローを管理し、保護されたAPIへのアクセスを仲介します。MCPクライアントに対してはOAuthサーバーとして機能し、Auth0に対してはOpenID Connectクライアントとして機能します。
-
Auth0: 認証・認可のためのサードパーティサービス。JWTトークンの発行と検証を担当します。
-
保護されたToDo API: Cloudflare Workersにデプロイされた、Auth0ベースの認証で保護されたAPIです。
3. 前提条件と環境準備
このガイドに従うには、以下のアカウントとツールが必要です:
- Auth0アカウント: 無料で作成できます(Auth0サインアップ)
- Cloudflareアカウント: 無料で作成できます(Cloudflareサインアップ)
- Node.js: バージョン18以上
- Git: 最新バージョン
- コードエディタ: VSCode, Cursor など
- Cloudflare Wrangler CLI: Cloudflare Workersのデプロイに使用
Wrangler CLIのインストール:
npm install -g wrangler
サンプルコードのクローン:
git clone https://github.com/cloudflare/ai.git
cd ai/demos/remote-mcp-auth0/
このリポジトリには、2つの主要なディレクトリがあります:
-
todos-api
: 保護されたToDo APIの実装 -
mcp-auth0-oidc
: Auth0と統合するリモートMCPサーバーの実装
4. 保護されたToDo APIの構築
まず、Auth0で保護されたToDo APIを構築し、デプロイします。
4.1 APIの実装を理解する
todos-api
ディレクトリに移動し、必要な依存関係をインストールします:
cd todos-api
npm install
このAPIの主な実装はindex.js
にあります:
// Honoフレームワークを使用したWebサーバーの実装
import { Hono } from 'hono';
import { faker } from '@faker-js/faker';
import { jwt, requireScope } from './middleware/jwt';
// アプリケーションの初期化
const app = new Hono();
// ヘルスチェックエンドポイント
app.get('/', (c) => c.text('Hello World!'));
// すべてのルートにJWT検証ミドルウェアを適用
app.use('*', jwt());
// ユーザー情報エンドポイント
app.get('/api/me', (c) => {
// JWTペイロードからユーザークレームを取得
const payload = c.get('jwtPayload');
return c.json(payload);
});
// ToDosエンドポイント - 'read:todos'スコープを要求
app.get('/api/todos', requireScope('read:todos'), (c) => {
// フェイカーを使用してランダムなToDosを生成
const todos = Array.from({ length: 5 }, () => ({
id: faker.string.uuid(),
title: faker.lorem.sentence(),
completed: faker.datatype.boolean(),
}));
return c.json(todos);
});
// 請求情報エンドポイント - 'read:billing'スコープを要求
app.get('/api/billing', requireScope('read:billing'), (c) => {
// 静的な請求情報を返す
return c.json({
plan: 'Pro',
amount: 99.99,
nextBillingDate: faker.date.future(),
});
});
export default app;
このAPIは、JWT(JSON Web Token)を使用して認証を行い、特定のエンドポイントにはスコープベースの認可を実装しています。
middleware/jwt.js
ファイルには、JWTの検証やスコープの要求などの認証ロジックが実装されています。
JWTとは、情報を安全に送信するためのコンパクトで自己完結型の方法です。JWTの情報はJSON形式であり、デジタル署名されているため、信頼性が検証できます。
4.2 Auth0でのAPIの設定
-
Auth0ダッシュボードにログインします。
-
Applications > APIsに移動し、Create APIをクリックします。
-
以下の値を入力します:
-
Name:
Todos API
-
Identifier:
urn:todos-api
-
Name:
-
Createをクリックします。
-
APIの設定画面で、Settingsタブに移動します。
-
Access Settingsセクションまでスクロールし、Allow Offline Accessをオンにします。
-
Saveをクリックします。
-
Permissionsタブに移動し、以下のパーミッションを追加します:
-
read:todos
- "ToDo リストを読み取る"権限 -
read:billing
- "請求情報を読み取る"権限
-
4.3 環境変数の設定
プロジェクトのルートディレクトリに.dev.vars
ファイルを作成し、以下の内容を追加します:
AUTH0_DOMAIN=あなたのAuth0ドメイン(例:dev-xxxx.us.auth0.com)
AUTH0_AUDIENCE=urn:todos-api
Auth0ドメインは、Auth0ダッシュボードの**Applications > Applications > Todos API (Test Application)**から取得できます。
4.4 ローカルでのAPIのテスト
APIをローカルで実行します:
npm run dev
APIはlocalhost:8789
で実行されます。
Auth0ダッシュボードから一時的なアクセストークンを取得してAPIをテストします:
- Applications > APIs > Todos API > Testタブに移動します。
- 表示されているcURLコマンドをコピーして実行します:
curl --request POST \
--url https://あなたのドメイン.auth0.com/oauth/token \
--header 'content-type: application/json' \
--data '{"client_id":"...","client_secret":"...","audience":"urn:todos-api","grant_type":"client_credentials"}'
返されたアクセストークンを使用してAPIにリクエストを送信します:
curl --request GET \
--url http://localhost:8789/api/me \
--header 'Authorization: Bearer あなたのアクセストークン'
4.5 Cloudflare Workersへのデプロイ
APIをCloudflare Workersにデプロイするには、まず環境シークレットを設定します:
wrangler secret put AUTH0_DOMAIN
wrangler secret put AUTH0_AUDIENCE
プロンプトが表示されたら、対応する値を入力します。
次に、APIをデプロイします:
wrangler deploy
デプロイが成功すると、Cloudflare WorkersのURLが表示されます。例:https://todos-api.あなたのサブドメイン.workers.dev
5. リモートMCPサーバーの実装
次に、Auth0と統合するリモートMCPサーバーを構築します。
5.1 Auth0でのアプリケーションの作成
-
Auth0ダッシュボードのApplications > Applicationsに移動し、Create Applicationをクリックします。
-
以下の値を入力します:
-
Name:
Remote MCP Server
-
Application Type:
Regular Web Applications
-
Name:
-
Createをクリックします。
-
作成したアプリケーションのSettingsタブに移動します。
-
Application URIsセクションまでスクロールし、Allowed Callback URLsに以下を追加します:
- ローカルテスト用:
http://localhost:8788/callback
- Cloudflareデプロイ用:
https://mcp-auth0-oidc.あなたのサブドメイン.workers.dev/callback
- ローカルテスト用:
-
Save Changesをクリックします。
5.2 Cloudflare KVの設定
Cloudflare Workers KVネームスペースを作成します:
wrangler kv namespace create "OAUTH_KV"
表示されたIDをコピーし、mcp-auth0-oidc
ディレクトリ内のwrangler.jsonc
ファイルを編集します:
{
"kv_namespaces": [
{
"binding": "OAUTH_KV",
"id": "コピーしたID"
}
]
}
Cloudflare Workers KVは、サーバーレス環境でのキー値ストレージサービスです。OAuthフローで必要な状態やトークンを保持するために使用します。
5.3 環境変数の設定
mcp-auth0-oidc
ディレクトリに.dev.vars
ファイルを作成し、以下の内容を追加します:
AUTH0_DOMAIN=あなたのAuth0ドメイン
AUTH0_CLIENT_ID=Remote MCPサーバーのクライアントID
AUTH0_CLIENT_SECRET=Remote MCPサーバーのクライアントシークレット
AUTH0_AUDIENCE=urn:todos-api
AUTH0_SCOPE=openid email profile offline_access read:todos
NODE_ENV=development
API_BASE_URL=http://localhost:8789
5.4 MCP Remote Serverコードの理解
リモートMCPサーバーの実装を見てみましょう。主なコードはsrc/index.ts
にあります:
// MCPサーバーの実装
import { MCPServer } from '@cloudflare/mcp/server';
import { OAuthProvider } from 'workers-oauth-provider';
// 環境変数の取得
const {
AUTH0_DOMAIN,
AUTH0_CLIENT_ID,
AUTH0_CLIENT_SECRET,
AUTH0_AUDIENCE,
AUTH0_SCOPE,
API_BASE_URL,
} = env;
// MCPサーバーの作成
const mcpServer = new MCPServer();
// ToDosツールの実装
mcpServer.defineTool({
name: 'list-todos',
description: 'List user todos',
async handler(params, context) {
// アクセストークンを使用してToDo APIにリクエスト
const response = await fetch(`${API_BASE_URL}/api/todos`, {
headers: {
Authorization: `Bearer ${context.token}`,
},
});
if (!response.ok) {
throw new Error(`Failed to fetch todos: ${response.status}`);
}
return await response.json();
},
});
// その他のツール実装(whoami, list-billing)...
// OAuthプロバイダーの設定
const oauthProvider = new OAuthProvider({
// OIDC設定
oidc: {
issuer: `https://${AUTH0_DOMAIN}`,
client_id: AUTH0_CLIENT_ID,
client_secret: AUTH0_CLIENT_SECRET,
redirect_uri: '/callback',
// その他の設定...
},
// OAuth設定
oauth: {
// デフォルトスコープなど
},
// KVストレージの設定
storage: env.OAUTH_KV,
});
// OAuth関連のルートハンドラー
export default {
// SSEエンドポイント - MCPサーバー処理
async fetch(request, env, ctx) {
const url = new URL(request.url);
// OAuthエンドポイントの処理
if (
url.pathname === '/authorize' ||
url.pathname === '/authorize/consent' ||
url.pathname === '/callback' ||
url.pathname.startsWith('/.well-known/') ||
url.pathname === '/token' ||
url.pathname === '/register'
) {
return oauthProvider.handle(request, env, ctx);
}
// MCPサーバーのSSEエンドポイント
if (url.pathname === '/sse') {
// 認証確認
const token = await oauthProvider.validateRequest(request);
if (!token) {
return new Response('Unauthorized', { status: 401 });
}
// MCPサーバーへのリクエスト処理
return mcpServer.handleRequest(request, {
token: token.access_token,
});
}
// その他のリクエスト処理...
}
};
このサーバーは主に2つの役割を果たしています:
- MCPサーバーとして 🛠️: AIアプリケーションにツール(list-todos, whoami, list-billing)を提供
- OAuthサーバーとして 🔐: 認証と認可のフローを処理
5.5 ローカルでのMCPサーバーのテスト
まず、Todo APIサーバーが実行されていることを確認します(localhost:8789
)。
次に、MCPサーバーをローカルで実行します:
cd mcp-auth0-oidc
npm run dev
MCPサーバーはlocalhost:8788
で実行されます。
テストにはMCP Inspectorを使用します:
npx @modelcontextprotocol/inspector
MCP Inspectorが起動したら、「Connect to MCP Server」セクションで以下の設定でサーバーに接続します:
- Protocol:
sse
- URL:
http://localhost:8788/sse
「Connect」ボタンをクリックすると、OAuth同意画面が表示されます。ここで「Allow Access」をクリックすると、Auth0の認証画面にリダイレクトされます。認証に成功すると、MCP Inspectorに利用可能なツールが表示されます。
5.6 Cloudflare Workersへのデプロイ
MCPサーバーをCloudflare Workersにデプロイするには、まず環境シークレットを設定します:
wrangler secret put AUTH0_DOMAIN
wrangler secret put AUTH0_CLIENT_ID
wrangler secret put AUTH0_CLIENT_SECRET
wrangler secret put AUTH0_AUDIENCE
wrangler secret put AUTH0_SCOPE
wrangler secret put API_BASE_URL
API_BASE_URLには、デプロイしたToDo APIのCloudflare WorkersのURLを指定します:
https://todos-api.あなたのサブドメイン.workers.dev
次に、MCPサーバーをデプロイします:
wrangler deploy
デプロイが成功すると、Cloudflare WorkersのURLが表示されます:
https://mcp-auth0-oidc.あなたのサブドメイン.workers.dev
6. 認証フローとOAuth 2.0の理解
このシステムで使用されているOAuth 2.0認証フローを詳しく見てみましょう。
6.1 OAuthの基本概念
OAuth 2.0の主要なエンティティは次のとおりです:
- リソースオーナー 👤: データの所有者(ユーザー)
- クライアント 💻: アクセスを要求するアプリケーション(MCPクライアント/Inspector)
- リソースサーバー 🗄️: 保護されたデータを提供するサーバー(ToDo API)
- 認可サーバー 🔑: 認証と認可を処理するサーバー(Auth0)
OAuth 2.0は、アプリケーションがユーザーのリソースに安全にアクセスするための標準プロトコルです。ユーザーは自分の認証情報を共有せずに、アプリケーションに特定のアクセス権を付与できます。
6.2 認証フローの図解
6.3 フローの詳細な説明
-
初期接続とディスカバリー 🔍:
- MCPクライアントがリモートMCPサーバーに接続を試みます。
- サーバーは401 Unauthorizedを返します。
- クライアントは
.well-known/oauth-authorization-server
エンドポイントを使用してOAuth設定情報を取得します。 - クライアントは
/register
エンドポイントでクライアント登録を行います。
-
認可リクエスト 🔒:
- クライアントは
/authorize
エンドポイントに認可リクエストを送信します。 - MCPサーバーは同意画面を表示します。
- ユーザーがアクセスを許可すると、MCPサーバーはユーザーをAuth0の認証画面にリダイレクトします。
- クライアントは
-
認証と認可コードの交換 🔄:
- ユーザーがAuth0で認証すると、Auth0はMCPサーバーの
/callback
エンドポイントに認可コードを送信します。 - MCPサーバーはクライアントをクライアントの
/oauth/callback
エンドポイントにリダイレクトします。 - クライアントはこの認可コードを使用して
/token
エンドポイントでアクセストークンとリフレッシュトークンを取得します。
- ユーザーがAuth0で認証すると、Auth0はMCPサーバーの
-
保護されたAPIの呼び出し 🔌:
- クライアントはアクセストークンを使用してMCPサーバーにツール呼び出しリクエストを送信します。
- MCPサーバーはこのトークンを使用して保護されたAPIにリクエストを送信します。
- APIはレスポンスをMCPサーバーに返し、MCPサーバーはそれをクライアントに転送します。
6.4 重要なセキュリティの考慮事項
- JWT検証 ✅: APIはAuth0で発行されたJWTの署名を検証して、改ざんされていないことを確認します。
- スコープの検証 🔍: APIは各エンドポイントで必要なスコープをチェックして、クライアントが適切な権限を持っていることを確認します。
- リフレッシュトークン 🔄: リフレッシュトークンを使用すると、ユーザーは再認証せずに新しいアクセストークンを取得できます。
- KVストレージ 💾: Cloudflare Workers KVは、認可コードとトークンの安全な保存に使用されます。
7. エンドツーエンドのテスト
システムの全コンポーネントがデプロイされたら、エンドツーエンドでテストしましょう。
7.1 MCPインスペクターを使用したテスト
MCPインスペクターを使用して、デプロイされたMCPサーバーに接続します:
npx @modelcontextprotocol/inspector
「Connect to MCP Server」セクションで以下の設定で接続します:
- Protocol:
sse
- URL:
https://mcp-auth0-oidc.あなたのサブドメイン.workers.dev/sse
認証フローを完了すると、利用可能なツールが表示されます:
-
list-todos
: ToDoリストを取得 -
whoami
: 現在のユーザー情報を表示 -
list-billing
: 請求情報を取得(read:billing
スコープがない場合はアクセス拒否)
7.2 ツールの呼び出しとレスポンスの確認
各ツールを呼び出して、期待どおりに動作することを確認します:
-
whoami:
{ "sub": "auth0|1234567890", "email": "your-email@example.com", "iss": "https://your-domain.auth0.com/", "aud": "urn:todos-api", "iat": 1682345678, "exp": 1682349278, "scope": "openid email profile read:todos" }
-
list-todos:
[ { "id": "123e4567-e89b-12d3-a456-426614174000", "title": "Complete project documentation", "completed": false }, { "id": "223e4567-e89b-12d3-a456-426614174001", "title": "Buy groceries", "completed": true }, // その他のToDoアイテム... ]
-
list-billing (アクセス拒否の場合):
{ "error": "Insufficient scope", "required": "read:billing", "provided": "openid email profile read:todos" }
8. Cloud Desktopとの統合
最後に、このMCPサーバーをCloud DesktopなどのAIアプリケーションと統合します。
8.1 MCP Remoteの設定
MCP Remoteは、ローカルのMCPクライアント(Cloud Desktop)とリモートMCPサーバーの間のプロキシとして機能します。Cloud Desktopを設定するには、以下の手順に従います:
- Cloud Desktopを開き、Settings > Developerに移動します。
- Edit Configをクリックして、設定ファイル(
claude_desktop_config.json
)を開きます。 - 以下の設定を追加します:
{
"mcpServers": {
"remote-todos": {
"command": "npx",
"args": [
"mcp-remote",
"https://mcp-auth0-oidc.あなたのサブドメイン.workers.dev/sse"
]
}
}
}
8.2 Cloud Desktopでのテスト
設定が完了したら、Cloud Desktopを再起動して、リモートMCPサーバーを使用してみましょう。
Cloud Desktopを起動すると、自動的にOAuth認証フローが開始されます。認証が完了すると、AIアシスタントに以下のようなプロンプトを試すことができます:
- "私のToDoリストを表示して"
- "自分の認証情報を教えて"
AIアシスタントは、リモートMCPサーバーを通じてこれらのリクエストを処理し、保護されたAPIからデータを取得して応答します。
9. まとめと次のステップ
この記事では、Auth0とCloudflare Workersを使用して、セキュアなクラウドネイティブMCPサーバーを構築しました。このアプローチにより、AIアプリケーションは認証されたユーザーの代わりに安全に外部APIを呼び出すことができるようになります。
実装のポイント:
- 保護されたAPI 🛡️: Auth0の認証と認可を使用してAPIを保護する方法
- リモートMCPサーバー 🌐: OAuthフローを処理し、保護されたAPIへのアクセスを仲介するサーバー
- MCP Remote 🔄: ローカルのAIアプリケーションとリモートMCPサーバーの間のギャップを埋めるプロキシ
このパターンは、さまざまな外部APIやサービスにAIアプリケーションを接続するための基盤となります。
次のステップ
- カスタムツールの追加: 独自のツールを実装して、MCPサーバーの機能を拡張
- 追加のAPIの統合: 他の保護されたAPIをシステムに統合
- セキュリティの強化: JWTの有効期限やスコープの細かい制御など、追加のセキュリティ機能の実装
- モニタリングとロギング: システム全体のモニタリングとロギングの実装
知識確認クイズ
-
MCPサーバーの主な役割は何ですか?
- a) AIモデルのトレーニング
- b) AIアプリケーションと外部APIを接続
- c) ユーザー認証のみ
- d) データの暗号化
-
Auth0がこのアーキテクチャで果たす役割は?
- a) APIのホスティング
- b) MCPサーバーのホスティング
- c) 認証と認可の提供
- d) AIモデルの提供
-
Cloudflare Workers KVの主な用途は?
- a) AIモデルの保存
- b) ユーザーデータの保存
- c) OAuth認可コードとトークンの保存
- d) 静的ファイルのホスティング
-
MCPサーバーがOAuthサーバーとして機能するとき、クライアントは何ですか?
- a) Auth0
- b) Cloudflare Workers
- c) ToDo API
- d) MCPクライアント(Inspector/Cloud Desktop)
-
MCPサーバーがOpenID Connectクライアントとして機能するとき、サーバーは何ですか?
- a) Auth0
- b) Cloudflare Workers
- c) ToDo API
- d) MCPクライアント
答え:
- b
- c
- c
- d
- a