cloudflare-mcp-server について
cloudflare-mcp-serverは、TypeScriptでCloudflare Workers向けのリモートMCPサーバーを構築・デプロイする開発者向けスキルです。ツール定義、認証、セッション状態、トランスポート、デプロイテストをテンプレートやエラー対策とともに扱います。
主な機能
- 01McpAgentとツール定義のパターン
- 02SSEとStreamable HTTPのトランスポート
- 03JWTとOAuthの認証パターン
- 04Durable Objectsによるセッション状態管理
- 05WebSocketハイバネーション設定
- 06ローカルテストとWorkersのデプロイ手順
活用シーン
- 01テンプレートからリモートMCPサーバーを作成
- 02サーバーへのOAuthやトークン検証の追加
- 03永続的なセッション状態を持つMCPサーバーの構築
- 04Cloudflare MCPのデプロイ問題の調査
MCP 対応
リモートMCPサーバーの開発を案内し、ツール、リソース、プロンプトの登録と、SSEおよびStreamable HTTPリクエストの処理を扱います。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jackspace/ claudeskillz --skill cloudflare-mcp-serverインストール後、Claude Code で/cloudflare-mcp-serverを入力して読み込まれたか確認します。
同梱ファイルREADME.mdSKILL.json
詳細
Cloudflare MCP サーバーのスキル
TypeScript を使って、Cloudflare Workers 上で Model Context Protocol(MCP)サーバーを構築、デプロイします。
このスキルについて
このスキルでは、Cloudflare 上で リモート MCP サーバーを構築する方法を学びます。2025 年現在、公式のリモート MCP サポートを提供している唯一のプラットフォームです。
このスキルは、次の場合にご利用ください:
- TypeScript(@modelcontextprotocol/sdk)で MCP サーバーを構築するとき
- Cloudflare Workers にリモート MCP サーバーをデプロイするとき
- OAuth 認証(GitHub、Google、Azure、カスタム)を実装するとき
- Durable Objects を使ってステートフルな MCP サーバーを作成するとき
- WebSocket ハイバネーションでコストを最適化するとき
- SSE と Streamable HTTP の両方のトランスポートをサポートするとき
- よくある MCP と Cloudflare のエラーを 15 件以上回避するとき
次の内容を学べます:
- McpAgent クラスのパターンとツール定義
- OAuth 統合(4 種類すべての認証パターン)
- セッションごとの状態管理に使う Durable Objects
- WebSocket ハイバネーション API
- デュアルトランスポートの設定(SSE + HTTP)
- 完全なデプロイワークフロー
クイックスタート(5 分)
方法 1:テンプレートからデプロイする
# Create new MCP server from Cloudflare template
npm create cloudflare@latest -- my-mcp-server \
--template=cloudflare/ai/demos/remote-mcp-authless
cd my-mcp-server
npm install
npm run dev
これで、MCP サーバーが http://localhost:8788/sse で実行されます。
方法 2:このスキルのテンプレートをコピーする
# Copy basic MCP server template
cp ~/.claude/skills/cloudflare-mcp-server/templates/basic-mcp-server.ts src/index.ts
cp ~/.claude/skills/cloudflare-mcp-server/templates/wrangler-basic.jsonc wrangler.jsonc
cp ~/.claude/skills/cloudflare-mcp-server/templates/package.json package.json
# Install dependencies
npm install
# Start development server
npm run dev
MCP Inspector でテストする
# In a new terminal, start MCP Inspector
npx @modelcontextprotocol/inspector@latest
# Open http://localhost:5173
# Enter your MCP server URL: http://localhost:8788/sse
# Click "Connect" and test tools
Cloudflare にデプロイする
# Deploy to production
npx wrangler deploy
# Your MCP server is now live at:
# https://my-mcp-server.your-account.workers.dev/sse
基本概念
1. McpAgent クラス
Cloudflare の Agents SDK にある McpAgent 基底クラスは、次の機能を提供します。
- Durable Objects との自動連携
- SQL データベースを使った組み込みの状態管理
- ツール、リソース、プロンプトの登録
- トランスポート処理(SSE + HTTP)
基本パターン:
import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
export class MyMCP extends McpAgent<Env> {
server = new McpServer({
name: "My MCP Server",
version: "1.0.0"
});
async init() {
// Register tools here
this.server.tool(
"tool_name",
"Tool description",
{ param: z.string() },
async ({ param }) => ({
content: [{ type: "text", text: "Result" }]
})
);
}
}
2. ツール定義
ツールは、MCP クライアントが呼び出せる関数です。パラメーターの検証には Zod を使用します。
パターン:
this.server.tool(
"tool_name", // Tool identifier
"Tool description", // What it does (for LLM)
{ // Parameters (Zod schema)
param1: z.string().describe("Parameter description"),
param2: z.number().optional()
},
async ({ param1, param2 }) => { // Handler
// Your logic here
return {
content: [{ type: "text", text: "Result" }]
};
}
);
ベストプラクティス:
- 詳細な説明:LLM がツールの目的を理解しやすくします
- パラメーターの説明:期待される値と制約を説明します
- エラー処理:失敗時には
{ isError: true }を返します - 少数の用途を絞ったツール:細分化された多数のツールよりも効果的です
3. トランスポート方式
MCP は 2 種類のトランスポートをサポートしています。
SSE(Server-Sent Events) — レガシーですが、広くサポートされています:
MyMCP.serveSSE("/sse").fetch(request, env, ctx)
Streamable HTTP — 2025 年の標準で、より効率的です:
MyMCP.serve("/mcp").fetch(request, env, ctx)
最大限の互換性を得るには、両方をサポートします。
export default {
fetch(request: Request, env: Env, ctx: ExecutionContext) {
const { pathname } = new URL(request.url);
if (pathname.startsWith("/sse")) {
return MyMCP.serveSSE("/sse").fetch(request, env, ctx);
}
if (pathname.startsWith("/mcp")) {
return MyMCP.serve("/mcp").fetch(request, env, ctx);
}
return new Response("Not Found", { status: 404 });
}
};
認証パターン
Cloudflare MCP サーバーは、4 種類の認証パターンをサポートしています。
パターン 1:認証なし
用途:内部ツール、開発、公開 API
テンプレート:templates/basic-mcp-server.ts
設定:不要です
セキュリティ:⚠️ 誰でも MCP サーバーにアクセスできます
パターン 2:トークン検証(JWTVerifier)
用途:事前認証済みのクライアント、カスタム認証システム
仕組み:クライアントが Bearer トークンを送信し、サーバーが検証します
テンプレート:カスタムの JWTVerifier ミドルウェアを作成します
設定:
import { JWTVerifier } from "agents/mcp";
const verifier = new JWTVerifier({
secret: env.JWT_SECRET,
issuer: "your-auth-server"
});
// Validate token before serving MCP requests
セキュリティ:✅ トークンが適切に管理されていれば安全です
パターン 3:OAuth プロキシ(workers-oauth-provider)
用途:GitHub、Google、Azure の OAuth 統合
仕組み:Cloudflare Worker が OAuth リクエストをサードパーティープロバイダーに中継します
テンプレート:templates/mcp-oauth-proxy.ts
設定:
import { OAuthProvider, GitHubHandler } from "@cloudflare/workers-oauth-provider";
export default new OAuthProvider({
authorizeEndpoint: "/authorize",
tokenEndpoint: "/token",
clientRegistrationEndpoint: "/register",
defaultHandler: new GitHubHandler({
clientId: (env) => env.GITHUB_CLIENT_ID,
clientSecret: (env) => env.GITHUB_CLIENT_SECRET,
scopes: ["repo", "user:email"],
context: async (accessToken) => {
// Fetch user info from GitHub
const octokit = new Octokit({ auth: accessToken });
const { data: user } = await octokit.rest.users.getAuthenticated();
return {
login: user.login,
email: user.email,
accessToken
};
}
}),
kv: (env) => env.OAUTH_KV,
apiHandlers: {
"/sse": MyMCP.serveSSE("/sse"),
"/mcp": MyMCP.serve("/mcp")
},
allowConsentScreen: true,
allowDynamicClientRegistration: true
});
必須バインディング:
{
"kv_namespaces": [
{ "binding": "OAUTH_KV", "id": "YOUR_KV_ID" }
]
}
セキュリティ:✅✅ 安全で、本番環境に対応しています
パターン 4:DCR を使ったリモート OAuth
用途:完全な OAuth プロバイダー、カスタムの同意画面
仕組み:Worker が OAuth プロバイダーとして機能します
テンプレート:Cloudflare の remote-mcp-authkit デモを参照してください
設定:複雑です。OAuth 2.1 の完全な実装が必要です
セキュリティ:✅✅✅ 最も安全で、完全な制御が可能です
Durable Objects を使ったステートフルな MCP サーバー
MCP サーバーで次の機能が必要な場合は、Durable Objects を使用します。
- セッションごとの永続的な状態
- 会話履歴
- ゲームの状態(チェス、三目並べ)
- API レスポンスのキャッシュ
- ユーザー設定
ストレージ API のパターン
テンプレート:templates/mcp-stateful-do.ts
値を保存する:
await this.state.storage.put("key", "value");
await this.state.storage.put("user_prefs", { theme: "dark" });
値を取得する:
const value = await this.state.storage.get<string>("key");
const prefs = await this.state.storage.get<object>("user_prefs");
キーを一覧表示する:
const allKeys = await this.state.storage.list();
キーを削除する:
await this.state.storage.delete("key");
設定
wrangler.jsonc:
{
"durable_objects": {
"bindings": [
{
"name": "MY_MCP",
"class_name": "MyMCP",
"script_name": "my-mcp-server"
}
]
},
"migrations": [
{ "tag": "v1", "new_classes": ["MyMCP"] }
]
}
重要:初回デプロイ時にはマイグレーションが必要です!
コスト最適化のための WebSocket ハイバネーション
問題:長時間存続する WebSocket 接続は CPU 時間を消費します
解決策:WebSocket ハイバネーション API は、アイドル時に接続を一時停止します
パターン
メタデータをシリアライズする(ハイバネーション中もデータを保持します):
webSocket.serializeAttachment({
userId: "123",
sessionId: "abc",
connectedAt: Date.now()
});
起動時に取得する:
const metadata = webSocket.deserializeAttachment();
console.log(metadata.userId); // "123"
永続状態の保存先:
// ❌ DON'T: In-memory state lost on hibernation
this.userId = "123";
// ✅ DO: Use storage API
await this.state.storage.put("userId", "123");
コスト削減
ハイバネーションを使用しない場合:
- 同時 WebSocket 接続 1000 件 × 10ms CPU/秒 = 10 CPU-sec/秒
- コスト:約 0.50 ドル/日
ハイバネーションを使用する場合:
- メッセージの処理時のみ CPU を使用します(アイドル時間の 99% は一時停止)
- コスト:約 0.01 ドル/日(50 倍削減!)
Worker と Durable Objects の基本
単独で利用できる自己完結型のセクションです
Worker のエクスポートパターン
Worker は fetch ハンドラーをエクスポートする必要があります:
export default {
fetch(request: Request, env: Env, ctx: ExecutionContext): Response | Promise<Response> {
// Handle request
return new Response("Hello");
}
};
Durable Objects のクラス構造
MCP サーバーの場合、DO は McpAgent を継承します:
export class MyMCP extends McpAgent<Env> {
constructor(state: DurableObjectState, env: Env) {
super(state, env);
}
// Your methods here
}
バインディング設定
環境バインディングにより、Worker はリソースにアクセスできます:
{
"kv_namespaces": [{ "binding": "MY_KV", "id": "..." }],
"durable_objects": {
"bindings": [{ "name": "MY_DO", "class_name": "MyDO" }]
},
"r2_buckets": [{ "binding": "MY_BUCKET", "bucket_name": "..." }]
}
コード内でのアクセス:
env.MY_KV.get("key");
env.MY_DO.idFromName("session-123").getStub(env);
env.MY_BUCKET.get("file.txt");
デプロイとテスト
ローカル開発
# Start dev server (uses Miniflare for local DOs)
npm run dev
# Start dev server with remote Durable Objects (more accurate)
npx wrangler dev --remote
アクセス先:http://localhost:8788/sse
MCP Inspector でテストする
npx @modelcontextprotocol/inspector@latest
http://localhost:5173を開きます- MCP サーバーの URL を入力します
- 「Connect」をクリックします
- 「List Tools」を使って、利用可能なツールを確認します
- パラメーターを指定して、ツール呼び出しをテストします
Cloudflare にデプロイする
# First time: Login
npx wrangler login
# Deploy
npx wrangler deploy
# Check deployment
npx wrangler tail
サーバーの公開先:
https://my-mcp-server.YOUR_ACCOUNT.workers.dev/sse
Claude Desktop に接続する
~/.config/claude/claude_desktop_config.json(Linux/Mac):
{
"mcpServers": {
"my-mcp": {
"url": "https://my-mcp-server.your-account.workers.dev/sse"
}
}
}
%APPDATA%/Claude/claude_desktop_config.json(Windows)
OAuth を使用する場合:
{
"mcpServers": {
"my-mcp": {
"url": "https://my-mcp-oauth.your-account.workers.dev/sse",
"auth": {
"type": "oauth",
"authorizationUrl": "https://my-mcp-oauth.your-account.workers.dev/authorize",
"tokenUrl": "https://my-mcp-oauth.your-account.workers.dev/token"
}
}
}
}
設定を変更した後は、Claude Desktop を再起動してください。
よく使われるパターン
API プロキシ MCP サーバー
用途:外部 API を MCP ツールでラップする
パターン:
this.server.tool(
"search_wikipedia",
"Search Wikipedia for a topic",
{ query: z.string() },
async ({ query }) => {
const response = await fetch(
`https://en.wikipedia.org/api/rest_v1/page/summary/${encodeURIComponent(query)}`
);
const data = await response.json();
return {
content: [{
type: "text",
text: data.extract
}]
};
}
);
データベース連携ツール
用途:D1、KV、または外部データベースをクエリする
パターン:
this.server.tool(
"get_user",
"Get user details from database",
{ userId: z.string() },
async ({ userId }) => {
// Query Durable Objects storage
const user = await this.state.storage.get<User>(`user:${userId}`);
// Or query D1 database
const result = await env.DB.prepare(
"SELECT * FROM users WHERE id = ?"
).bind(userId).first();
return {
content: [{
type: "text",
text: JSON.stringify(user || result, null, 2)
}]
};
}
);
複数ツールの連携
用途:別のツールを呼び出すツール
パターン:
// Store result from first tool
await this.state.storage.put("last_search", result);
// Second tool reads it
const lastSearch = await this.state.storage.get("last_search");
キャッシュ戦略
用途:コストの高い API 呼び出しをキャッシュする
パターン:
this.server.tool(
"get_weather",
"Get weather (cached 5 minutes)",
{ city: z.string() },
async ({ city }) => {
const cacheKey = `weather:${city}`;
const cached = await this.state.storage.get<CachedWeather>(cacheKey);
// Check cache freshness
if (cached && Date.now() - cached.timestamp < 5 * 60 * 1000) {
return {
content: [{ type: "text", text: cached.data }]
};
}
// Fetch fresh data
const weather = await fetchWeatherAPI(city);
// Cache it
await this.state.storage.put(cacheKey, {
data: weather,
timestamp: Date.now()
});
return {
content: [{ type: "text", text: weather }]
};
}
);
Durable Objects によるレート制限
用途:不正利用を防ぎ、上流のレート制限を遵守する
パターン:
async rateLimit(key: string, maxRequests: number, windowMs: number): Promise<boolean> {
const now = Date.now();
const requests = await this.state.storage.get<number[]>(`ratelimit:${key}`) || [];
// Remove old requests outside window
const recentRequests = requests.filter(ts => now - ts < windowMs);
if (recentRequests.length >= maxRequests) {
return false; // Rate limited
}
// Add this request
recentRequests.push(now);
await this.state.storage.put(`ratelimit:${key}`, recentRequests);
return true; // Allowed
}
// Use in tool
if (!await this.rateLimit(userId, 10, 60 * 1000)) {
return {
content: [{ type: "text", text: "Rate limit exceeded (10 requests/minute)" }],
isError: true
};
}
既知のエラー 15 件(解決策付き)
1. McpAgent クラスがエクスポートされていない
エラー:TypeError: Cannot read properties of undefined (reading 'serve')
原因:McpAgent クラスのエクスポートを忘れています
解決策:
export class MyMCP extends McpAgent { ... } // ✅ Must export
export default { fetch() { ... } }
2. トランスポートの不一致
エラー:Connection failed: Unexpected response format
原因:クライアントは /sse を想定していますが、サーバーは /mcp のみを提供しています
解決策:両方のトランスポートを提供してください(「トランスポート方式」セクションを参照)
3. OAuth リダイレクト URI の不一致
エラー:OAuth error: redirect_uri does not match
原因:クライアントは localhost で設定されていますが、workers.dev にデプロイされています
解決策:デプロイ後に claude_desktop_config.json を更新してください
4. WebSocket ハイバネーションによる状態の消失
エラー:「state not found」と表示され、再接続後にツール呼び出しが失敗します
原因:ハイバネーション時にメモリ内の状態がクリアされます
解決策:インスタンスのプロパティではなく、this.state.storage を使用してください
5. Durable Objects のバインディングがない
エラー:Error: Cannot read properties of undefined (reading 'idFromName')
原因:wrangler.jsonc で DO バインディングを設定し忘れています
解決策:バインディングを追加してください(「ステートフル MCP サーバー」セクションを参照)
6. マイグレーションが定義されていない
エラー:Error: Durable Object class MyMCP has no migration defined
原因:DO の初回デプロイにはマイグレーションが必要です
解決策:
{
"migrations": [
{ "tag": "v1", "new_classes": ["MyMCP"] }
]
}
7. リモート MCP での CORS エラー
エラー:Access to fetch at '...' blocked by CORS policy
原因:MCP サーバーが CORS ヘッダーを返していません
解決策:OAuthProvider を使用する(CORS を処理します)か、ヘッダーを手動で追加してください
8. クライアント設定形式のエラー
エラー:Claude Desktop がサーバーを認識しません
原因:claude_desktop_config.json の JSON 形式が正しくありません
解決策:正しい形式については、「Claude Desktop に接続する」セクションを参照してください
9. serializeAttachment() が使用されていない
エラー: ハイバネーションから復帰した際に WebSocket メタデータが失われる
原因: serializeAttachment() を使用していない
解決策: WebSocket ハイバネーションのセクションを参照してください
10. OAuth 同意画面が無効になっている
セキュリティリスク: ユーザーに権限が表示されません
原因: 本番環境で allowConsentScreen: false に設定されている
解決策: 本番環境では必ず allowConsentScreen: true に設定してください
11. JWT 署名キーが見つからない
エラー: Error: JWT_SIGNING_KEY environment variable not set
原因: OAuth Provider には署名キーが必要です
解決策:
openssl rand -base64 32
# Add to wrangler.jsonc vars
12. 環境変数が設定されていない
エラー: env.MY_VAR is undefined
原因: 変数が .dev.vars にはあるものの、wrangler.jsonc には設定されていない
解決策: wrangler.jsonc の "vars" セクションに追加してください
13. ツールスキーマの検証エラー
エラー: ZodError: Invalid input type
原因: クライアントは文字列を送信していますが、スキーマでは数値が想定されています
解決策: Zod の変換機能を使用してください:
z.string().transform(val => parseInt(val, 10))
14. 複数のトランスポートエンドポイントが競合している
エラー: /mcp を追加した後、/sse が 404 を返す
原因: パスの照合が正しくありません
解決策: startsWith() または完全一致を使用してください
15. Miniflare の制限によるローカルテストの問題
エラー: ローカル開発環境で OAuth フローが失敗する
原因: Miniflare はすべての DO 機能をサポートしていません
解決策: すべての DO 機能を利用するには、npx wrangler dev --remote を使用してください
設定リファレンス
wrangler.jsonc の完全な例(全機能)
{
"name": "my-mcp-server",
"main": "src/index.ts",
"compatibility_date": "2025-01-01",
"compatibility_flags": ["nodejs_compat"],
"account_id": "YOUR_ACCOUNT_ID",
"vars": {
"ENVIRONMENT": "production",
"GITHUB_CLIENT_ID": "optional-pre-configured-id"
},
"kv_namespaces": [
{
"binding": "OAUTH_KV",
"id": "YOUR_KV_ID",
"preview_id": "YOUR_PREVIEW_KV_ID"
}
],
"durable_objects": {
"bindings": [
{
"name": "MY_MCP",
"class_name": "MyMCP",
"script_name": "my-mcp-server"
}
]
},
"migrations": [
{ "tag": "v1", "new_classes": ["MyMCP"] }
],
"node_compat": true
}
package.json の完全な例
templates/package.json を参照してください
claude_desktop_config.json の完全な例
templates/claude_desktop_config.json を参照してください
追加リソース
公式ドキュメント
- Cloudflare Agents: https://developers.cloudflare.com/agents/
- MCP 仕様: https://modelcontextprotocol.io/
- workers-oauth-provider: https://github.com/cloudflare/workers-oauth-provider
- Durable Objects: https://developers.cloudflare.com/durable-objects/
公式サンプル
- Cloudflare AI デモ: https://github.com/cloudflare/ai/tree/main/demos
- 13 の MCP サーバー: https://blog.cloudflare.com/thirteen-new-mcp-servers-from-cloudflare/
ツール
- MCP Inspector: https://github.com/modelcontextprotocol/inspector
- Wrangler CLI: https://developers.cloudflare.com/workers/wrangler/
このスキルを使用しない場合
次の場合はこのスキルを使用しないでください:
- Python の MCP サーバーを構築する場合(代わりに
fastmcpスキルを使用してください) - ローカル専用の MCP サーバーを構築する場合(代わりに
typescript-mcpスキルを使用してください) - Cloudflare 以外のホスティング(AWS Lambda、GCP など)が必要な場合
- Claude.ai のウェブインターフェースのスキルを扱う場合(MCP とは異なります)
このスキルを使用する対象:TypeScript + Cloudflare Workers + リモート MCP
バージョン情報
- @modelcontextprotocol/sdk: 1.21.0
- @cloudflare/workers-oauth-provider: 0.0.13
- agents(Cloudflare Agents SDK): 0.2.20
- 最終検証日: 2025-11-04
本番環境でのテスト済み:Cloudflare の公式 MCP サーバー(mcp-server-cloudflare、workers-mcp)に基づいています
トークン効率
このスキルを使用しない場合:
- 分散したドキュメントの調査:約10kトークン
- 15件のエラーのデバッグ:約30kトークン
- 合計:約40kトークン
このスキルを使用する場合:
- スキルを読む:約4kトークン
- テンプレートをコピー:約1kトークン
- 合計:約5kトークン
削減率:約87%(40k → 5k トークン)
防止できるエラー:15件(防止率100%)
質問がある場合は、以下を確認してください:
references/authentication.md- 認証方式の比較references/transport.md- SSE と HTTP の技術的な詳細references/oauth-providers.md- GitHub、Google、Azure の設定references/common-issues.md- エラーの詳細なトラブルシューティングreferences/official-examples.md- Cloudflare のサンプルへの厳選リンク