MCPからWebMCPへ:WebブラウザとAIエージェントを直接つなぐ次世代プロトコルの仕組み

はじめに
Cloudflare Blog: thttps://blog.cloudflare.com/webmcp/
Cloudflare Docs: https://developers.cloudflare.com/browser-run/features/webmcp/
AIエージェントが一般のWebサイトを操作する場合、サイト側にエージェント向けのAPIや操作インターフェースがなければ、ページの内容を読み取り、DOM要素や画面上の位置を手がかりに、クリック・入力・ページ遷移を試行する必要があります。
特にスクリーンショットを解析してマウス操作を行う方式では、画面レイアウトの変化や表示状態の影響を受けやすく、操作を一つずつ確認するため、効率や安定性に課題があります。
WebMCPは、これとは異なるアプローチを取ります。サイト側があらかじめsearch_flights()やbookTicket()のような型付きパラメータを持つ関数(ツール)をAIエージェント向けに公開しておくことで、エージェントは画面を解析せずにツールを直接呼び出せるようになります。
今回は、MCP / WebMCP / Cloudflare WebMCPの比較を行いつつ、Cloudflare Workers と D1 を使って、AIエージェント向けにFAQ検索ツールを公開するミニマムなサイトを実際に構築し、CloudflareのWebMCPの仕組みを検証してみました。
※CloudflareのWebMCPは2026年8月段階でDeveloper Previewの機能になります。
WebMCPとは
Cloudflare公式ドキュメントでは、次のように説明されています。
"a browser API that lets websites expose structured tools for AI agents to discover and execute directly"(Webサイトで、AIエージェントが発見・実行できる構造化ツールを公開するためのブラウザAPI)
Cloudflare Doc: https://developers.cloudflare.com/browser-run/features/webmcp/
WebMCPは、Chromeで実験的に実装が進められている、AIエージェント向けのブラウザAPIです。
ただ、WebMCPの仕様はまだ流動的で、これからも変更が入る可能性が高いため継続的な情報の収集が必要です。
MCP / WebMCP / Cloudflare WebMCPの動作比較



※2026年8月時点。MCPは2026-07-28、WebMCPはW3C Community Groupのドラフト(2026-08-26)、CloudflareのWebMCP は developer preview。
MCP / WebMCP / Cloudflare WebMCPでの簡単な比較は以下になります。
| No | 項目 | MCP | WebMCP | CloudflareのWebMCP |
|---|---|---|---|---|
| 1 | Toolの提供元 | MCP Server | WebサイトのJavaScript | 既存のMCP Server ※Site MCP Server packの場合 |
| 2 | AIがToolを知る方法 | MCP Clientが tools/list でTool一覧を取得 | WebサイトJSが registerTool() でブラウザ(ModelContext)に登録 | bridge.js が /mcp へ tools/list を送信して取得し、registerTool() でブラウザ(ModelContext)に登録 |
| 3 | AIがToolを利用する場所 | AI Agent(MCP Client側) | ブラウザのAI Agent(WebMCP対応) | ブラウザのAI Agent(WebMCP対応) |
| 4 | Toolの実行場所 | MCP Server | WebサイトのJavaScript | ブラウザ内の bridge.js がToolハンドラを実行し、実処理をMCP Server(/mcp)へ tools/call で委譲 |
| 5 | 外部システムへのアクセス | MCP Serverから実行 | WebサイトのJavaScriptから実行 | MCP Serverから実行 ※Site MCP Server packの場合 |
| 6 | 通信/API | MCPプロトコル (JSON-RPC 2.0 *1) | WebMCP API *2 (ブラウザ内API) | WebMCP API(document.modelContext)⇄ bridge.js / bridge.js ⇄ 同一オリジンの/mcp:MCP(JSON-RPC 2.0) |
| 7 | MCPサーバの有無 | 必要 | 不要 | Site MCP Server packでは既存のMCP Serverを利用 |
| 8 | Cloudflareの関与 | なし | なし | EdgeでHTMLに bridge.js の<script>タグを挿入し、bridge scriptもEdgeから配信 |
| 9 | 特徴 | 汎用的なMCP Server連携方式 | WebサイトJavaScriptがブラウザのModelContextへToolを登録できる | 既存MCP ServerのToolをWebMCP ToolとしてブラウザAI Agentから利用可能 ※Site MCP Server packの場合 |
*1 JSON-RPC 2.0
→ プログラム同士がJSON形式で「この処理を実行して」と依頼・応答するための通信ルール
MCPでは tools/list や tools/call などのやり取りに使われます。
*2 WebMCP API
→ Webサイトの機能を、ブラウザ内のAI AgentからToolとして利用できるようにするブラウザAPI
registerTool() などを使って、WebサイトのToolをブラウザのModelContextに登録し、AI Agentから利用可能にします。
CloudflareのWebMCP対応
| No | 機能名 | 内容 |
|---|---|---|
| 1 | Browser Run | Chrome BetaのLab session上で、WebMCP対応サイトのツールを検証・実行できます。 Browser Runでは、次の検証用APIが利用できます。 -navigator.modelContextTesting.listTools() -navigator.modelContextTesting.executeTool() これはWebサイトにツールを追加する機能ではなく、WebMCP対応サイトをテストするための機能です。 |
| 2 | Agents SDKの WebMCPアダプタ | Cloudflare Agents SDKには、実験的な agents/experimental/webmcp アダプタが用意されています。 registerWebMcp() を使用すると、MCPサーバーへ接続して tools/list からツールを取得し、それらをブラウザの navigator.modelContext にWebMCPツールとして登録できます。 ブラウザ上でツールが実行されると、その呼び出しはMCP経由でサーバー側へ中継されます。これにより、ページ内JavaScriptで直接登録したWebMCPツールと、MCPサーバー側で実装したツールを、同じページ上のツールとしてAIから利用できるようになります。 agents/experimental/webmcpについて: https://github.com/cloudflare/agents/blob/main/experimental/webmcp.md |
| 3 | Cloudflare Dashboard連携 | Dashboardの「Agent Readiness > WebMCP」を有効にすると、CloudflareがHTMLRewriterを使ってbridge scriptをHTMLへ自動注入します。 既存のMCPエンドポイントがある場合、そのツールをWebMCPとしてブラウザに公開できます。 |
検証する内容
| 1 | FAQデータを格納するD1を構築する |
| 2 | Cloudflare Agents SDKのcreateMcpHandlerを使い、FAQをキーワード検索するsearch_faqツールを持つMCPサーバーをCloudflare Workersで実装する |
| 3 | CloudflareにWorkersをデプロイしてMCPサーバーが正しく動作することを確認する |
| 4 | デプロイ後にCloudflareの画面からWebMCPを有効化する |
| 5 | ブラウザ側からツールを検出・実行する |

事前準備:Cloudflareにログイン、D1作成、Workers作成
まず、Cloudflareにログインします。
$ npx wrangler login
$ npx wrangler whoami
事前準備:DNS設定
Workersを適用するFQDNをCloudflareのDNSに登録しておきます。
※Workerが全リクエストを処理する構成では、到達可能なオリジンサーバーは不要。
今回は以下の名前で登録しています。
webmcp-faq-demo.xxx.xxx
実装:Workersの雛形作成
Workersの雛形を作成して、型定義を生成します。
$ npm create cloudflare@latest -- webmcp-faq-demo
...
├ What would you like to start with?
│ category Hello World example
│
├ Which template would you like to use?
│ type Worker only
│
├ Which language do you want to use?
│ lang TypeScript
...
├ Do you want to use git for version control?
│ yes git
...
├ Do you want to deploy your application?
│ no deploy via `npm run deploy`
...
$ cd webmcp-faq-demo
$ npx wrangler types
実装:D1作成 + サンプルデータ登録
D1を作成します。
$ npx wrangler d1 create webmcp-faq-demo
Successfully created DB 'webmcp-faq-demo' in region APAC
Created your new D1 database.
To access your new D1 Database in your Worker, add the following snippet to your configuration file:
{
"d1_databases": [
{
"binding": "webmcp_faq_demo",
"database_name": "webmcp-faq-demo",
"database_id": "xxxxxx"
}
]
}
Would you like Wrangler to add it on your behalf? … yes
What binding name would you like to use? … webmcp_faq_demo
For local dev, do you want to connect to the remote resource instead of a local resource? … no
D1にサンプルのデータを入れるsqlを以下に配置します。
$ mkdir migrations
$ vi migrations/0001_create_faqs.sql
-- FAQデモ用テーブル。内容はすべてサンプル
CREATE TABLE IF NOT EXISTS faqs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
category TEXT NOT NULL,
question TEXT NOT NULL,
answer TEXT NOT NULL
);
INSERT INTO faqs (category, question, answer) VALUES
('CDN', 'CDNを導入するとどんなメリットがありますか?', 'エッジキャッシュにより配信元サーバーの負荷を減らし、表示速度と可用性を改善できます(デモ用サンプル回答です)。'),
('セキュリティ', 'WAFとDDoS対策の違いは何ですか?', 'WAFはアプリケーション層の攻撃を防ぎ、DDoS対策は大量トラフィックによる可用性低下を防ぎます(デモ用サンプル回答です)。'),
('運用', '導入までにどれくらい期間がかかりますか?', '構成や既存環境により異なります。まずは現状構成のヒアリングから始めます(デモ用サンプル回答です)。'),
('料金', '料金体系はどうなっていますか?', '通信量や機能構成により異なるため、個別見積りとなります(デモ用サンプル回答です)。'),
('サポート', '導入後のサポート体制はありますか?', '運用監視から設定変更まで、フルアウトソーシングからミニマムサポートまで選択可能です(デモ用サンプル回答です)。');
D1にサンプルデータを入れます。
$ npx wrangler d1 migrations apply webmcp-faq-demo --remote
Resource location: remote
Migrations to be applied:
┌──────────────────────┐
│ name │
├──────────────────────┤
│ 0001_create_faqs.sql │
└──────────────────────┘
About to apply 1 migration(s)
Your database may not be available to serve requests during the migration, continue? … yes
Executing on remote database webmcp-faq-demo (xxxxx):
To execute on your local development database, remove the --remote flag from your wrangler command.
Executed 3 commands in 1.10ms
以下のコマンドを実行してD1にデータが入っているか確認します。
$ npx wrangler d1 execute webmcp-faq-demo --remote --command "SELECT * FROM faqs"
実装:Workersコード作成
今回、編集/追加を行うファイルは以下となります。
- src`wrangler.jsonc`を以下の様に編集します。
| - index.ts
| - mcp.ts
| - page.html
- wrangler.jsonc
database_idは、D1作成時に自動で入力される値をそのまま使用すればOKです。
routesの部分はWorkersを適用するドメインとFQDNを指定して下さい。
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "webmcp-faq-demo",
"main": "src/index.ts",
"compatibility_date": "2026-08-25",
"upload_source_maps": true,
"compatibility_flags": [
"nodejs_compat"
],
"d1_databases": [
{
"binding": "DB",
"database_name": "webmcp-faq-demo",
"database_id": "xxxxxx-xxxxxx-xxxxx"
}
],
"routes": [
{
"zone_name": "xxx.xxx",
"pattern": "webmcp-faq-demo.xxx.xxx/*"
}
]
}`src/mcp.ts`を編集して、D1を検索するsearch_faqツールを定義します。
import { McpServer } from "@modelcontextprotocol/server";
import { z } from "zod";
export interface Env {
DB: D1Database;
}
export function createFaqServer(env: Env) {
const server = new McpServer({ name: "webmcp-faq-demo", version: "1.0.0" });
server.registerTool(
"search_faq",
{
description:
"サイト内のFAQをキーワードで検索する。質問文の一部が一致するFAQを最大5件まで返す。",
inputSchema: {
query: z.string().min(1).describe("検索したいキーワード(例: 'CDN', '料金')"),
},
},
async ({ query }: { query: string }) => {
const { results } = await env.DB.prepare(
`SELECT category, question, answer FROM faqs
WHERE question LIKE ?1 OR answer LIKE ?1 OR category LIKE ?1
LIMIT 5`,
)
.bind(`%${query}%`)
.all<{ category: string; question: string; answer: string }>();
if (!results || results.length === 0) {
return {
content: [
{
type: "text" as const,
text: `「${query}」に一致するFAQは見つかりませんでした。`,
},
],
};
}
const text = results
.map(
(r, i) =>
`${i + 1}. [${r.category}] Q. ${r.question}n A. ${r.answer}`,
)
.join("n");
return {
content: [{ type: "text" as const, text }],
};
},
);
return server;
}`src/index.ts`を編集して、WorkerのfetchハンドラでMCPサーバーをルーティングします。
import { createMcpHandler } from "agents/mcp/server";
import { createFaqServer, type Env } from "./mcp";
import PAGE_HTML from "./page.html";
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
// AIエージェント(WebMCPブリッジ/MCPクライアント)向けのMCPサーバーエンドポイント
if (url.pathname === "/mcp") {
return createMcpHandler(() => createFaqServer(env), {
allowedOriginHostnames: [url.hostname],
})(request, env, ctx);
}
// 人間向けUIが叩く簡易なREST API
if (url.pathname === "/api/faq") {
const query = url.searchParams.get("query") ?? "";
const { results } = await env.DB.prepare(
`SELECT category, question, answer FROM faqs
WHERE question LIKE ?1 OR answer LIKE ?1 OR category LIKE ?1
LIMIT 5`,
)
.bind(`%${query}%`)
.all();
return Response.json({ results: results ?? [] });
}
if (url.pathname === "/") {
return new Response(PAGE_HTML, {
headers: { "content-type": "text/html; charset=utf-8" },
});
}
return new Response("Not Found", { status: 404 });
},
} satisfies ExportedHandler<Env>;`src/page.html`を編集して、GUIを作成します
オプションとしてGUIからD1に接続して検索できるようにしてますが、こちらは確認用なので必須ではありません。
※以下のコードはサンプルデータが完全に信頼できる検証用実装になります。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>WebMCP FAQデモ (Workers + D1)</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 640px; margin: 40px auto; padding: 0 16px; }
h1 { font-size: 1.4rem; }
#results { margin-top: 16px; }
.faq { border: 1px solid #ddd; border-radius: 8px; padding: 12px; margin-bottom: 8px; }
.faq .q { font-weight: bold; }
code { background: #f4f4f4; padding: 2px 6px; border-radius: 4px; }
</style>
</head>
<body>
<h1>WebMCP FAQデモ (Cloudflare Workers + D1)</h1>
<p>
このページはWebMCPの検証用デモです。
</p>
<form id="search-form">
<input type="text" id="q" placeholder="例: CDN, 料金, サポート" />
<button type="submit">検索(人間向けUI)</button>
</form>
<div id="results"></div>
<script>
document.getElementById('search-form').addEventListener('submit', async (e) => {
e.preventDefault();
const q = document.getElementById('q').value;
const res = await fetch('/api/faq?query=' + encodeURIComponent(q));
const data = await res.json();
const el = document.getElementById('results');
el.innerHTML = data.results.length
? data.results.map(r => `<div class="faq"><div class="q">[${r.category}] ${r.question}</div><div>${r.answer}</div></div>`).join('')
: '<p>該当するFAQが見つかりませんでした。</p>';
});
</script>
</body>
</html>
必要なライブラリをダウンロードします。
$ npm install --save-exact agents@0.22.0 @modelcontextprotocol/server@2.0.0 zod@4.5.4
動作確認
Cloudflareにdeployします。
$ npx wrangler deployWorkersを適用したFQDN宛に、コマンドラインからMCPのJSON-RPCエンドポイントに直接リクエストを送って動作を確認します。
ツール一覧の取得(tools/list)
$ curl -s https://webmcp-faq-demo.xxx.xxx/mcpsearch_faqツールが、型付きの入力スキーマ(queryは必須の文字列)とともに公開されていることが確認できます。
-H "Content-Type: application/json"
-H "Accept: application/json, text/event-stream"
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
...
event: message
data: {"result":{"tools":[{"name":"search_faq","description":"サイト内のFAQをキーワードで検索する。質問文の一部が一致するFAQを最大5件まで返す。","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"query":{"type":"string","minLength":1,"description":"検索したいキーワード(例: 'CDN', '料金')"}},"required":["query"]}}]},"jsonrpc":"2.0","id":1}
ツールの実行(tools/call)
`料金`について聞いてみると、以下の様な回答が返ってきます。
$ curl -s -X POST https://webmcp-faq-demo.xxx.xxx/mcp
-H "Content-Type: application/json"
-H "Accept: application/json, text/event-stream"
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_faq","arguments":{"query":"料金"}}}'
...
event: message
data: {"result":{"content":[{"type":"text","text":"1. [料金] Q. 料金体系はどうなっていますか?n A. 通信量や機能構成により異なるため、個別見積りとなります(デモ用サンプル回答です)。"}]},"jsonrpc":"2.0","id":2}
FAQにない内容を聞いてみると、以下の様な回答が返ってきます。
$ curl -s -X POST https://webmcp-faq-demo.durasite-cc.net/mcp
-H "Content-Type: application/json"
-H "Accept: application/json, text/event-stream"
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_faq","arguments":{"query":"明日の天気"}}}'
...
event: message
data: {"result":{"content":[{"type":"text","text":"「明日の天気」に一致するFAQは見つかりませんでした。"}]},"jsonrpc":"2.0","id":2}
D1に格納したFAQデータに対して、キーワードに応じた検索結果、あるいは0件時のメッセージが正しく返ることを確認できました。
Cloudflare WebMCPの有効化とブラウザからの検証手順
ダッシュボードでWebMCPを有効化する
Cloudflareダッシュボードの「Agent Readiness > WebMCP」で、「サイトMCPサーバー」を有効化します。

これにより、Cloudflareのエッジ側でHTMLレスポンスに以下のようなブリッジスクリプトが自動的に挿入されます。コード変更は不要です。
※<head>...</head>部分に挿入されます
※Workersのdev用のURLでは挿入されませんでした
<script type="module" src="https://webmcp-faq-demo.xxx.xxx/.webmcp/bridge.js" data-packs="mcp-server-client"></script>
Browser Runのlab sessionでブラウザから検証する
Cloudflare Browser Runの実験用ブラウザプール(lab session)を使って試してみます。
以下のコマンドを実行するとブラウザが起動します。
$ npx wrangler browser create --lab --keepAlive 300
...
[WARNING]`wrangler browser create` is an open beta command. Please report any issues to https://github.com/cloudflare/workers-sdk/issues/new/choose
Session created: xxxx-xxxxx-xxxxx-xxxx
Opening DevTools...
URL入力部分に今回のFQDN(webmcp-faq-demo.xxx.xxx)を入力します。

開いたライブビューで、DevToolsのConsoleで以下を実行すると、WebMCPが動作していることが確認できます。
> await navigator.modelContextTesting.listTools();
> await navigator.modelContextTesting.executeTool(
"search_faq",
JSON.stringify({ query: "CDN" }),
);


ChatGPTのデスクトップアプリのブラウザから確認
ChatGPT Doc: https://learn.chatgpt.com/docs/changelog#codex-2026-08-25-browser
実際に内蔵ブラウザからサイトにアクセスさせて確認してみたところ、以下のように表示されてることが確認できました。

ChatGPTアプリから実際に問い合わせてみたところ、以下のようにWebMCPの内容の回答が返ってきました。

Agent Readinessでの計測
Acceliaコラム: https://www.accelia.net/column/cloudflaretips/9236/
今回のWebMCPの設定追加前
↓

今回のWebMCPの設定追加後
↓

まとめ
WebMCPを利用すると、AIエージェントはWebページの見た目やDOMの解析だけに頼らず、サイトが公開したツールを直接呼び出せます。今回の例では、search_faqがD1を検索し、FAQの内容を返します。
一方で、WebMCPはまだ実験段階であり、対応ブラウザやAPI仕様は今後変更される可能性があります。CloudflareのWebMCPも、2026年8月時点ではDeveloper Previewです。本番導入時は、認証・権限管理・ユーザー確認などを十分に検討する必要があります。
また、CloudflareのAgent Readinessが示すように、今後はAIエージェントによる利用を前提としたサイト設計が重要になると考えられます。AIエージェントから見つけてもらいやすい構造、内容を正しく読み取れるページ設計、そして今回のWebMCPのようなツール公開が、これからのWebサイトに求められる要素になりそうです。
そしてCloudflareなら、
- ●パフォーマンスの向上
- ●サイトの信頼性の向上
- ●運用コストの最適化
を、一つのプラットフォーム上で進められます。Cloudflareの導入や運用を検討する際は、アプリケーションの更新頻度と利用者ごとのデータ分離を踏まえ、自社に合ったキャッシュ設計から検討してみてください。
サービスにご興味をお持ちの方は
お気軽にお問い合わせください。
Webからお問い合わせ
お問い合わせお電話からお問い合わせ
平日09:30 〜 18:00












