mcpField
C
cloudflare-mcp-server

cloudflare-mcp-server

github.com/jackspace開発1636 回インストール12 週間前に更新
リポジトリ

cloudflare-mcp-server について

cloudflare-mcp-serverは、TypeScriptでCloudflare Workers向けのリモートMCPサーバーを構築・デプロイする開発者向けスキルです。ツール定義、認証、セッション状態、トランスポート、デプロイテストをテンプレートやエラー対策とともに扱います。

主な機能

  1. 01McpAgentとツール定義のパターン
  2. 02SSEとStreamable HTTPのトランスポート
  3. 03JWTとOAuthの認証パターン
  4. 04Durable Objectsによるセッション状態管理
  5. 05WebSocketハイバネーション設定
  6. 06ローカルテストとWorkersのデプロイ手順

活用シーン

  1. 01テンプレートからリモートMCPサーバーを作成
  2. 02サーバーへのOAuthやトークン検証の追加
  3. 03永続的なセッション状態を持つMCPサーバーの構築
  4. 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 件以上回避するとき

次の内容を学べます:

  1. McpAgent クラスのパターンとツール定義
  2. OAuth 統合(4 種類すべての認証パターン)
  3. セッションごとの状態管理に使う Durable Objects
  4. WebSocket ハイバネーション API
  5. デュアルトランスポートの設定(SSE + HTTP)
  6. 完全なデプロイワークフロー

クイックスタート(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
  1. http://localhost:5173 を開きます
  2. MCP サーバーの URL を入力します
  3. 「Connect」をクリックします
  4. 「List Tools」を使って、利用可能なツールを確認します
  5. パラメーターを指定して、ツール呼び出しをテストします
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 を参照してください


追加リソース

公式ドキュメント
公式サンプル
ツール

このスキルを使用しない場合

次の場合はこのスキルを使用しないでください:

  • 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 のサンプルへの厳選リンク

コメント