Cloudflareで認証付きリモートMCPサーバー
はじめに
AI 駆動で開発することも多くなってきた昨今、皆さんも各種 MCP サーバー(Serena だとか Playwright MCP だとか Context7 だとか)を使っていることと思います。
認証周りが整理されてきたり、MCP-UI(最近だと OpenAI も Apps SDK の発表の中での MCP UI も話題に)なんてものが出てきたりしていてスタンダードにしようという動きは加速していますね。
とはいえ、まだまだ自分で MCP サーバーを作ったことのない人もいるのではないでしょうか?
かくいう自分も作ったことがあるのはローカルの MCP サーバーくらい...。
なので、もう一歩踏み込んだことに取り組みたいなと思い認証付きのリモート MCP サーバーを Cloudflare Workers 上に構築してみました!
Cloudflare の雛形に大感謝しながらの構築だったので、
個人として大したことはしていないですが日本語のリソースの一部として認証付きのリモート MCP サーバーを作ってみたい!という方の参考になれば幸いです!
MCP-UI 関連
技術スタックの簡単な説明
- フレームワーク: Hono(ただし、今回の記事上はあまり書いていない)
- ランタイム/ホスティング: Cloudflare Workers
- その他: Bindings で KV/DO など連携
- 実装ベース: Cloudflare の公式デモ「remote-mcp-cf-access」
- 認証: Cloudflare Access for SaaS(OIDC)で MCP サーバーを保護
- 集約/配布: MCP Server Portals(複数サーバーを一つの入口に集約し、Access ポリシーで制御)
重要な事前準備
- Cloudflare アカウント: 言わずもがな必要ですね
- カスタムドメイン: Access でポリシーを適用するなどのために必要です
- Cloudflare 上でも購入と登録は可能
- ポータルのために必要(認証のみであればなくても大丈夫です)
使用した雛形
workers-oauth-providerが適切にハンドリングしてくれるので実装者としてすることはほぼありません。
参考資料
これも本当に優しいチュートリアルです。公式ドキュメントも充実しているのが素晴らしい。
改めて今回の目的と要件
目的は「認証つきのリモート MCP サーバー」を Cloudflare の公式デモをベースに構築し、Access for SaaS(OIDC)で保護したうえで MCP Server Portals に接続すること。
VSCode や inspector などで開いて認証が正しく動作する、ツールが確認できることがゴールです 👑
要件(最小)
- エンドポイント:
/mcp(標準トランスポートではなくなったSSE の/sseルートは削除) - ツール: R2 に置いているオブジェクトのリストを取得できるツール(実際は CRUD)
- 認証: Cloudflare Access for SaaS(OIDC)でログインを要求
- MCP Server Portals に登録し、ポータル URL(例:
https://<subdomain>.<domain>/mcp)でクライアントから接続
実装フロー(ダイジェスト)
公式のドキュメントが充実しているので詳細な手順は割愛しますが、ざっくり以下の流れで実装しました。
変更点は別途解説します。
- Cloudflareの公式デモから雛形を作成(remote-mcp-cf-access)
- デモ内のSSEルート(
/sse)を削除し、HTTP の/mcpのみを残す - KV(
OAUTH_KV)を作成し、wrangler.jsoncにバインディングを設定 - MCPサーバーとしての機能を実装(R2連携の簡単なツールを追加)
- Access for SaaSアプリ(OIDC)を作成し、Client ID/Secretなどの取得
- WorkercのSecretsに上記値を格納(
ACCESS_CLIENT_IDなど)し、デプロイ - Zero Trust > AI controlsでMCP サーバーを登録し、MCP Server Portalを作成・紐付け
- PortalのURL(例:
https://<subdomain>.<domain>/mcp)経由でクライアントから接続
構築
では、ここから構築を始めていきます。
ざっくりと以下のポイントで解説します。
- 実装のポイントを解説
- Cloudflare 周りの設定
実装のポイントを解説
作成したプロジェクトの全体感は以下の通り。
MCPのツールなどをディレクトリに分けて整理した都合、雛形から少し変わっています。
src
├── index.ts // 雛形のsrc/index.ts
├── auth // 認証関連
│ ├── index.ts
│ ├── workers-oauth-utils.ts
│ └── access-handler.ts
└── mcp // MCP関連
└── tools
├── index.ts
└── list_objects.ts
実際は MCP のディレクトリにほかのツールやリソースの実装もしています。
気になっていたので MCP-UI なども試してみましたが、今回は割愛します。
一応上記構成のサンプルプロジェクトは以下にあるので、こちらを使用していただいても大丈夫です!
雛形からの主な変更点としてエントリーポイントの修正くらいです。
エントリーポイントは以下の通り。
/sseルートを削除し、/mcpのみを残しています。
import OAuthProvider from '@cloudflare/workers-oauth-provider';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { McpAgent } from 'agents/mcp';
import { registerTools } from './mcp/tools';
import { handleAccessRequest } from './auth/access-handler';
import type { Props } from './auth/workers-oauth-utils';
export class MyMCP extends McpAgent<Env, Record<string, never>, Props> {
declare env: Env;
declare props?: Props;
server = new McpServer({
name: 'my-mcp-server',
version: '1.0.0',
});
async init() {
registerTools(this.server, this.env);
}
}
async function handleMcpRequest(req: Request, env: Env, ctx: ExecutionContext) {
const { pathname } = new URL(req.url);
if (pathname === '/mcp') {
return MyMCP.serve('/mcp').fetch(req, env, ctx);
}
return new Response('Not found', { status: 404 });
}
export default new OAuthProvider({
apiHandler: { fetch: handleMcpRequest as any },
apiRoute: ['/mcp'],
authorizeEndpoint: '/authorize',
clientRegistrationEndpoint: '/register',
defaultHandler: { fetch: handleAccessRequest as any },
tokenEndpoint: '/token',
});
Cloudflare 周りの設定
設定と言いつつも構築-デプロイ-Access までのフローはすでに以下の記事にまとまっているので参考にして下さい 👀
この記事では上記では触れられていない > AIコントロール(MCP サーバーポータル・MCP サーバー)周りの設定を説明します!
MCP サーバーの追加
AIコントロールのMCPサーバータブ
Zero Trust ホーム > Access > > AIコントロール にアクセスし、MCP サーバーを追加します!
サーバー名は任意ですが、HTTP URL には Workers の URL を指定してください。
- Workers ドメインの場合:
https://<your-workers-subdomain>.workers.dev/mcp - カスタムドメインの場合:
https://sub.yourdomain.com/mcp
MCPサーバーの基本情報入力画面
MCP サーバーにもポリシーの設定がありますがこちらはなくても大丈夫です!
(SaaS アプリケーションのポリシーで制御するため)
設定の完了後、再度 MCP サーバーの編集画面を開くと基本情報の下に認証のテスト UI が表示されます。
こちらで認証が正しく動作するか確認しましょう。
MCPサーバーの認証テストUI
MCP サーバーポータルの追加
MCPサーバーポータルタブの画面
では、次にZero Trust ホーム > Access > > AIコントロール > MCPサーバーポータル タブに移動し、ポータルを追加します。
ポータルの追加にはカスタムドメインが必要なので注意してください。
MCPサーバーポータルの基本情報
また、最低1つのMCPとポリシーを設定する必要があります。
MCPサーバーポータルのサーバー追加エリア・Accessポリシー設定エリア
ここまでの設定が完了したらポータルのURLにアクセスしてみましょう。
検証にはCloudflareのプレイグラウンドを使うと便利です。
プレイグラウンドのMCPサーバーURLにポータルのURLを設定し接続。
設定が適切であれば以下のような画面が表示されます。
MCPサーバーポータルの画面
この画面の後、各MCPサーバーの認証が完了するとMCPサーバー内のツールなどが利用可能になります!
個人的に詰まったところ
- ポリシーの設定ミス: MCPサーバー・ポータル両方のポリシーを適切に設定する必要があります
- ポータルに繋ぐすべてのMCPサーバーに対してポリシーを設定する必要があります
(CloudflareのMCPなど)パブリックなMCPサーバーをポータルに登録したい時があるので、自動でポリシーを適用できると嬉しいな...なんて。
以下はMCPサーバーにサブドメインを設定するオプションの手順です。
興味のある方は参考にしてみてください!
(オプション)MCPサーバーにサブドメインを設定する
ここからはオプショナルな設定ですが、設定しておくと単体の MCP サーバーとしてもアクセスが簡単になるのでおすすめです!
Cloudflare で管理しているドメインがあればやることは単純で 3 つだけです!
例としてsub.yourdomain.comを使う場合の設定を見ていきましょう。
Workers ルートの設定
リクエストをもとにワーカーを実行するために Workers ルートを設定します。
例えば以下のような設定をすることでsub.yourdomain.com/mcpへのリクエストによって MCP サーバーを実行できます。
Workersルートの設定
参考記事からの変更点
コールバック URL をhttps://sub.yourdomain.com/callbackを設定してください。
DNS レコードの追加
Workers ルートを設定してもレコードが存在しないとアクセスできないので、DNS レコードに以下の設定をします。
DNSレコードの追加
まとめ
若干詰まるところがありつつも、公式の雛形のおかげで
- とりあえずのミニマムなMCPサーバーの構築
- Cloudflare Access for SaaS(OIDC)での認証保護
- MCP Server Portalsでの集約
まで一通りスムーズに実装できました!
Cloudflareの雛形もドキュメントも充実していて本当にありがたい限りですね!
今回の記事が皆さんが自分専用・会社専用のMCPサーバーを構築する際の参考になれば幸いです!
余談
先日行われたHono Conf 2025でAditya Mathur氏がhono/mcpを使用しての認証デモをしていたので、アップデートされたら試してみたいなと思っています👀
Discussion