本文へスキップ
Edition · Tokyo

Cloudflare WorkersでRemote MCPを安全に運用する設計ガイド

Cloudflare Workers上のRemote MCPを、現行createMcpHandler、OAuth、権限、レート制限、監査ログ、停止条件まで含めて段階的に設計します。

codeagent.jp編集部 情報確認 約8分
Tags
情報確認
参考リンク
7件
更新性
定期更新
読了目安
約8分
更新管理

仕様・料金・提供範囲が変わりやすいテーマは、公開日・更新日・情報確認日を分けて管理します。 導入前には必ず記事末尾の一次情報と公式ドキュメントで最新状況を確認してください。

Cloudflare WorkersでRemote MCPを安全に運用する設計ガイド の16:9共有用サマリー画像。 Remote MCPはデプロイ手順より、認証・権限・観測・停止条件を先に設計する 1. 実装境界: 新規はステートレスなcreateMcpHandlerを使う、旧McpAgentは移行期間だけ別経路に残す、SDK版はAgentsの要求版に合わせて固定する 2. 防御層: OAuthのログインとツール権限を分ける、利用者とツール単位でレートを制御する、Originと入力、同意画面を検証する 3. 運用境界: 構造化ログに主体、ツール、結果を残す、トークンと機密引数・結果は記録しない、認可逸脱や漏えい時は即時停止する 結論: 新規サーバーはcreateMcpHandlerを基準にし、公開前に書き込み権限と撤退手順を検証する
Cloudflare WorkersでRemote MCPを安全に運用する設計ガイド 資料 26-YR9G 2026.08.13 設計・ワークフロー
共有用画像を開く シェア 約8分 / mcp / cloudflare-workers

結論

Cloudflare WorkersでRemote MCPを作るなら、2026年8月13日時点の新規実装は**ステートレスな createMcpHandler()**を基準にします。ただし、ハンドラーを置いて公開URLを得るだけでは運用可能とはいえません。OAuthによる本人確認、ツール単位の権限、利用者単位のレート制限、機密値を除外した構造化ログ、異常時の停止条件を一つのリリースゲートとして設計します。

この記事は公式仕様とCloudflare公式Docsを基にした設計ガイドです。特定のWorkersアカウントへ実際にデプロイし、すべてのプラン・SDK組み合わせで動作確認した結果ではありません。パッケージ版、利用可能な機能、上限、料金は、実装時点の公式Docsと自分のアカウントで再確認してください。

この記事の対象読者

  • ローカルMCPをチームや顧客向けのRemote MCPへ移したい開発者
  • Cloudflare WorkersとAgents SDKで新規MCPサーバーを作る人
  • OAuthを入れたが、ツール権限・レート制限・監査ログまで設計できていない人
  • 本番投入の可否と、問題発生時に止める条件を明文化したい運用担当者

トランスポート自体をまだ決めていない場合は、stdioとStreamable HTTPの選び方から確認してください。

現行の実装方式を選ぶ

CloudflareのRemote MCPガイドは、2026年7月時点で次の境界を示しています。

方式状態新規実装での判断
createMcpHandler()ステートレス、現行MCP向け第一候補
createLegacyMcpHandler()WorkerTransport経路向け移行期間だけ使う
McpAgent非推奨・機能固定新規では使わない
Raw SDK transport実装者が輸送層を所有独自要件が明確な場合だけ

公式のMCP handler APIでは、createMcpHandler はリクエストごとに新しいMCPサーバーを生成するファクトリーを受け取ります。依存版は記事の固定値をコピーせず、インストールしている agents が要求するMCPパッケージの正確な版へ合わせます。

src/index.tsの最小構造
import { McpServer } from '@modelcontextprotocol/server';
import { createMcpHandler } from 'agents/mcp/server';
function createServer() {
const server = new McpServer({ name: 'team-tools', version: '1.0.0' });
// registerToolで、最初は読み取り専用ツールだけを登録する
return server;
}
const handler = createMcpHandler(createServer, {
// modern専用endpoint。旧クライアントは期限付きの別経路へ分離する
legacy: 'reject',
// 実際の許可OriginとCORSも環境ごとに明示する
});
export default {
fetch(request, env, ctx) {
return handler(request, env, ctx);
},
} satisfies ExportedHandler;

このコードは構造を示す骨組みです。legacy: 'reject' はmodern専用endpointの境界を明示します。既定の legacy: 'stateless' で互換性を残す場合は、対象クライアント、廃止日、legacy成功率を別に記録してください。認証、権限判定、環境型、例外処理を省略しているため、そのまま本番へ出してはいけません。

公開レベルを判断する表

扱うもの認証権限レート制限リリース判断
公開情報の低コスト検索条件次第読み取り専用必須小規模ベータから
個人・顧客データの参照必須利用者・テナント分離必須認可テスト後のみ
外部サービスへの書き込み必須ツール別スコープ厳しめ人間確認を加える
削除・公開・購入・課金必須最小権限+再確認必須初期公開から除外を推奨
管理者操作必須管理者専用、既定非表示必須独立経路を検討

最初の公開範囲は「利用価値」ではなく「失敗時の損失」で決めます。読み取り専用で十分な価値を確認してから、書き込みツールを一つずつ追加します。AIエージェントの秘密情報保護も、環境変数とログの境界を決める際に使えます。

OAuthはログインとツール権限を分ける

CloudflareのAuthorization解説は、認証と認可を別の問題として扱っています。ログインに成功しただけでは、すべてのMCPツールを実行できる根拠になりません。

設計は次の順序で行います。

  1. 誰がログインできるかを決める
  2. read:documentswrite:issuesのようにツールへ対応するスコープを定義する
  3. 同意画面に、クライアント名、要求スコープ、対象リソースを表示する
  4. ツール登録時またはツール実行時にスコープを強制する
  5. テナントID・ユーザーIDを、クライアントからの任意入力ではなく検証済み認証コンテキストから得る
  6. トークン失効、ユーザー無効化、権限変更が反映されることを試す

CloudflareのWorkers OAuth Provider Libraryを使う選択肢には、Cloudflare Access、第三者OAuth、既存の認証サービス、独自フローがあります。どれを選んでも、同意とツール権限の最終責任はアプリケーション側に残ります。

第三者OAuthへプロキシする場合は、CloudflareのMCPセキュリティガイドが示すように、上流へ転送する前に自前の同意画面とCSRF対策が必要です。保存済み同意を攻撃者のクライアントに誤用される「confused deputy」を防ぐため、state、安全なCookie、リダイレクトURI、発行者を結び付けて検証します。

レート制限は過負荷防止として使う

Workers Rate Limiting bindingは、Worker内の任意の位置で利用者やリソース別の制限をかけられます。MCPでは、検証済みの主体IDとツール名を組み合わせたキーが扱いやすい設計です。

概念例: 主体とツールで分ける
const key = `${verifiedTenantId}:${verifiedUserId}:${toolName}`;
const { success } = await env.MCP_RATE_LIMITER.limit({ key });
if (!success) {
return new Response('rate limit exceeded', { status: 429 });
}

ただし、これは概念例です。verifiedTenantIdverifiedUserIdtoolName は信頼できる認証コンテキストと検証済みMCPメタデータから作り、外部入力をそのまま信用しません。

また、Cloudflare公式Docsは、このAPIのカウンターがCloudflareロケーション単位で、許容的・結果整合的であり、正確な会計システム向けではないと明記しています。そのため役割を分けます。

  • Rate Limiting binding: バースト、誤ループ、上流API過負荷の緩和
  • 永続的なクォータ管理: 課金、厳密な日次上限、契約上限
  • 観測: 429件数、主体別・ツール別拒否率、上流エラー率

IPアドレスだけをキーにすると、モバイル回線やプロキシを共有する正当な利用者をまとめて止める可能性があります。可能なら検証済みユーザーID、テナントID、クライアントIDを使います。

Workers Logsを監査可能な形にする

Workers Logsの公式Docsでは、Wrangler設定でobservabilityを有効にし、JSONの構造化ログを使うことが推奨されています。ただし「ログを有効化した」だけでは監査ログになりません。

推奨するイベント項目は次の通りです。

項目注意
request_idランダムな相関ID応答にも返すなら形式を固定
actor_idハッシュ化または不透明IDメールアドレスを直接入れない
tenant_id不透明IDテナント越境の調査に使う
client_idOAuthクライアントID生トークンは入れない
scopes許可済みスコープ名権限判断の証跡にする
tool_name呼び出したツール引数全文とは分離する
decisionallow / deny拒否理由を定型化する
statussuccess / error / cancelledHTTPコードも別項目にする
duration_ms処理時間上流遅延の検知に使う
release_idデプロイ版ロールバック判断に使う

記録しないものも明文化します。

  • OAuthアクセストークン、更新トークン、Cookie、APIキー
  • authInfo.tokenauthInfo.extra.props
  • ツール引数・結果の全文
  • 個人情報や顧客文書の本文
  • 例外オブジェクト内に混入した秘密値

サンプリングを使う場合でも、拒否、認可エラー、書き込み操作、重大エラーを追跡できる設計にします。保存期間、閲覧権限、削除手順も監査要件に含めてください。

段階的な実装手順

1. ローカルで読み取り専用ツールを作る

createMcpHandler と対応MCPパッケージの版を公式Docsで固定し、外部副作用のないツールを一つだけ登録します。不正入力、タイムアウト、キャンセルもテストします。

2. 認証なしの公開を前提にしない

将来個人データや書き込みを扱うなら、最初からOAuthの主体IDとスコープをツール層へ渡せる構造にします。認証なしの試験エンドポイントは、公開情報・低コスト・読み取り専用に限定し、期間と呼び出し上限を決めます。

3. ツール単位の権限テストを書く

少なくとも、未認証、期限切れトークン、正しい利用者でスコープ不足、別テナント、管理者、失効後を試します。ツール一覧から見せない方式と、実行時に拒否する方式のどちらでも、サーバー側の強制を省略しません。

4. レート制限と上流保護を入れる

主体×ツールの制限、全体の緊急上限、上流APIタイムアウト、同時実行上限を分けます。429と上流エラーをダッシュボードで追えるようにします。

5. 構造化ログとアラートを入れる

秘密値除外テストを行い、認可拒否急増、5xx、429、レイテンシ、書き込み件数を観測します。エージェントのサンドボックス運用と同様に、許可境界と証跡を実行環境の外側にも持たせます。

6. 限定利用者でステージングする

本番データを使わず、テスト用テナントと最小スコープで接続します。旧クライアントが必要ならmodernとlegacyを別経路・別メトリクスにします。

7. 停止訓練をしてから公開する

対象ツールの無効化、ルート停止、直前版へのロールバック、OAuthクライアント失効、上流資格情報のローテーションを実際に手順化します。

即時停止する条件

次のいずれかを検知したら、新規リリースを止め、影響するツールまたはMCPルートを無効化します。

  • ログや応答にトークン、秘密値、顧客データが出た
  • 未認証またはスコープ不足でツールを実行できた
  • 別テナントのデータを参照・変更できた
  • 同意していない書き込み、削除、公開、課金が行われた
  • 429、5xx、上流タイムアウトが定めた閾値を超えた
  • 主体、ツール、結果、リリース版をログから追えない
  • OAuth発行者、リダイレクトURI、CSRF検証に不整合がある
  • ロールバックまたは資格情報失効の手順が機能しない

閾値の数値は利用量、上流APIの契約、SLOによって変わるため、この記事では一律値を断定しません。平常時のベースラインを計測し、絶対値と増加率の両方で決めます。

公開前チェックリスト

  • 新規実装が createMcpHandler と対応SDK版を使っている
  • legacy経路が必要なら期限・対象・監視を分離した
  • Origin、CORS、許可メソッドを明示した
  • ログインとツール権限を別々に検証した
  • 同意画面にクライアント、スコープ、対象を表示した
  • 主体×ツールのレート制限と全体上限を設けた
  • 厳密な課金・クォータをRate Limiting bindingへ任せていない
  • 構造化ログからトークンと機密本文を除外した
  • 未認証、スコープ不足、テナント越境、失効をテストした
  • ツール停止、ルート停止、ロールバックを実行できる

よくある質問

認証なしのRemote MCPを公開してもよいですか?

公開情報を返す低コストの読み取り専用ツールに限定し、悪用時の上限と停止手順を持つ場合は選択肢になります。個人データ、社内情報、書き込み、課金を扱うツールは、OAuthとツール単位の権限を先に実装してください。

CloudflareのRate Limiting bindingだけで厳密な利用量課金をできますか?

できません。公式Docsではロケーション単位で、許容的かつ結果整合的な仕組みであり、正確な会計用途には使わないよう説明されています。過負荷防止に使い、課金や厳密なクォータは別の整合性を持つ仕組みで管理します。

Workers Logsを有効にすれば監査ログは完成ですか?

ログ保存基盤が使えるだけで、監査項目や機密値の除外はアプリ側の設計です。主体の不透明ID(opaque ID)、クライアントID、スコープ、ツール名、結果、所要時間を構造化し、raw token、秘密値、機密引数・結果は残さないでください。

まとめ

Cloudflare WorkersはRemote MCPの公開基盤を用意できますが、本番品質はURLを発行した後の設計で決まります。新規サーバーはステートレスな createMcpHandler を基準にし、OAuthのログインとツール権限を分離します。Rate Limiting bindingは過負荷防止に使い、厳密な会計とは分けます。Workers Logsには監査に必要な最小項目だけを構造化して残します。

そして、認可逸脱、秘密値漏えい、テナント越境、追跡不能が起きた時に止められなければ、まだ公開可能な設計ではありません。読み取り専用の限定公開から始め、停止訓練を通過した機能だけを段階的に広げてください。

一次情報

Primary sources

一次情報・参考リンク

About the author
codeagent.jp編集部

Claude Code / Codex / MCP を個人開発サイト運用と公開MCPサーバー開発で試し、一次情報・検証ログ・失敗例をもとに整理します。

関連して読む