グラレコ
はじめに
WebMCP は、Web ページが自分の機能を「ツール」としてブラウザに登録し、ブラウザ上で動く AI エージェントがそれを直接呼び出せるようにする API の提案です。W3C の Web Machine Learning Community Group で策定が進んでいて、最新のドラフトは 2026年8月12日付の Draft Community Group Report として公開されています。編集者は Microsoft の Brandon Walderman さん、Google の Khushal Sagar さんと Dominic Farolino さんの3名です。
Chrome では 2026年5月から Origin Trial が始まっていて、Chrome 149 以降で実際のユーザーに対して有効化できます。ローカルで試すだけなら chrome://flags/#enable-webmcp-testing を有効にすれば動きます。
⚠️ 本記事は 2026年8月14日時点の情報です。 WebMCP は API の置き場所がこの半年で2回変わっています。検索で出てくる日本語記事の多くは
navigator.modelContext時代に書かれたもので、そのままでは動きません。この点は後半の「引っ越し」の節でまとめます。
🕸️ 何が問題だったのか:エージェントは今、画面を「読んで」いる
いま普及している Web 操作系の AI エージェントは、ほぼ例外なく人間向けの画面を解析して動いています。スクリーンショットを撮って視覚的に読む、あるいは DOM を丸ごと取り込んでボタンらしき要素を探す、というやり方です。
この方式には、実運用で効いてくる弱点が3つあります。
1つ目は、コストです。1ページ分の DOM やスクリーンショットは、それ自体が数千トークンから数万トークンになります。「検索して、絞り込んで、カートに入れる」だけで画面を何度も読み直すことになり、トークン消費が積み上がります。
2つ目は、壊れやすさです。サイト側がボタンの class 名を変えただけで、エージェントの手順が動かなくなります。サイト側には「壊した」自覚すらありません。
3つ目は、意図の推測が混ざることです。エージェントは画面から「たぶんこのボタンが購入だろう」と推測します。推測が外れたときに何が起きるかは、購入ボタンで想像してみると分かりやすいと思います。
WebMCP は、この構図をひっくり返します。サイト側が「うちにはこういう操作があります」と機械可読な形で宣言し、エージェントはそれを呼ぶだけになります。
まず、従来型のエージェントがやっていることを図にします。
エージェントは人間向けの HTML を受け取り、そこから操作対象を推測しています。点線が示すとおり、サイト側が class 名を変えるだけでこのループは壊れます。
同じ処理を WebMCP でやると、こうなります。
2つの図で決定的に違うのは、エージェントが何を受け取るかです。前者は人間向けの HTML を受け取って解釈しますが、後者は名前・説明・JSON Schema という契約を受け取ります。契約があるので推測が要りません。
表にすると差がはっきりします。
| 観点 | スクレイピング/DOM操作型 | WebMCP型 |
|---|---|---|
| エージェントが読むもの | スクリーンショット・DOM全体 | ツール定義(名前・説明・入力スキーマ) |
| トークン消費 | ページ規模に比例して増える | ツール定義の分だけ |
| UI変更への耐性 | class名・レイアウト変更で壊れる | ツール名と入力スキーマが契約になる |
| 操作の確実性 | 「たぶんこのボタン」の推測が入る | サイトが定義した関数を直接実行 |
| サイト側の関与 | なし(勝手に読まれる) | 何を公開するか自分で決める |
| 認証済み操作 | セッションの扱いが曖昧 | 訪問者のセッションでそのまま動く |
最後の行が地味に大きいところです。ログイン済みのページでツールが動くので、「注文履歴を見る」のような認証が要る操作も、追加の API キー発行なしに成立します。この点は便利さと危うさが表裏一体なので、セキュリティの節で改めて扱います。
🔌 MCP と WebMCP は何が違うのか
名前が似ているので混同しやすいのですが、WebMCP は MCP(Model Context Protocol)のブラウザ版であって、置き換えではありません。Explainer の非ゴールにも「バックエンドの MCP を置き換えるものではない」と明記されています。
住み分けはこうなります。
この図で押さえておきたいのは、WebMCP はユーザーが開いているタブの中で完結するという点です。サーバーに常駐する MCP サーバーとは動く場所が違います。
| MCP(サーバーサイド) | WebMCP(ブラウザ) | |
|---|---|---|
| 動く場所 | サーバー / ローカルプロセス | 開いているタブの中 |
| 想定する呼び出し元 | IDE、チャットアプリ、エージェント基盤 | ブラウザ内のエージェント |
| 認証 | APIキー、OAuth などを別途設計 | 訪問者の既存セッションをそのまま利用 |
| ユーザーの可視性 | 基本的に見えない | 画面上で操作が進むので見える |
| 主なユースケース | バックエンド連携、社内データ接続 | ユーザーが今見ているサイトの操作 |
一方で、両者は思想を共有しています。ツールの定義の仕方(名前・説明・入力スキーマ)も、返り値の考え方(content 配列を持つ結果オブジェクト)も MCP を踏襲しているため、MCP でツールを書いたことがある人なら初見でも読めるはずです。Cloudflare の実装は、この共通性を使って「サイトの MCP サーバーのツールを、そのままページ上の WebMCP ツールに変換する」ということをやっています(後述します)。
🧩 API の全体像:document.modelContext
WebMCP の入口は document.modelContext の1つだけです。仕様上は ModelContext というインターフェースで、EventTarget を継承しています。セキュアコンテキスト(HTTPS または localhost)でのみ露出します。
主なメソッドは2つです。
| メソッド | 戻り値 | 役割 |
|---|---|---|
registerTool(tool, options) |
Promise<undefined> |
ツールを1つ登録する |
getTools(options) |
Promise<RegisteredTool[]> |
登録済みツールを一覧する |
加えて toolchange イベントが飛びます。ツールが登録・解除されたときに発火するので、エージェント側やページ内の別コンポーネントが追随できます。
まずは最小のコードです。Explainer に載っている ToDo アプリの例をそのまま引用します。
await document.modelContext.registerTool({
name: "add-todo",
description: "Add a new item to the user's active todo list",
inputSchema: {
type: "object",
properties: {
text: { type: "string", description: "The text content of the todo item" }
},
required: ["text"]
},
async execute({ text }) {
// 既存のクライアントサイド処理をそのまま呼ぶ
await addTodoItemToCollection(text);
return {
content: [{ type: "text", text: `Added todo item: "${text}" successfully.` }]
};
}
});
ポイントは4つあります。
-
nameはツールの識別子です。1〜128文字で、使えるのは英数字と_-.だけです -
descriptionはエージェントが「このツールを使うべきか」を判断する材料になります。ここが雑だと呼ばれません -
inputSchemaは JSON Schema です。requiredを書いておくと、引数が足りないままの呼び出しを防げます -
executeの中身は既存の関数をそのまま呼ぶだけで構いません。addTodoItemToCollection()はもともとページにあった関数です
最後の点が、WebMCP のいちばん現実的な魅力だと思います。新しいバックエンドを立てる必要がありません。ボタンの onClick から呼んでいる関数に、もう1つ呼び出し口を生やすだけです。
登録から実行までの流れを整理すると、こうなります。
この図で見てほしいのは、実行がページの中で起きていることです。UI が実際に更新されるので、ユーザーは何が行われたかを目で確認できます。裏で API が叩かれて結果だけ返ってくるのとは、体験としてかなり違います。
ModelContextTool に渡せるメンバーを一覧にしておきます。
| メンバー | 必須 | 型 | 説明 |
|---|---|---|---|
name |
○ | string | 1〜128文字。英数字・_・-・.
|
title |
string | 人間向けの表示名 | |
description |
○ | string | エージェントの選択判断に使われる |
inputSchema |
object | JSON Schema | |
execute |
○ | function | 実処理。同期・非同期どちらも可 |
annotations |
object |
readOnlyHint / untrustedContentHint(既定は false) |
🪜 最小から本番へ:3段階で書き足す
実際にサイトへ組み込むときは、いきなり全部書くより段階的に足していくほうが楽です。
段階1:引数なしの読み取り専用ツール
まず、状態を返すだけのツールから始めます。Explainer の Gerrit(コードレビュー)の例が分かりやすいです。
await document.modelContext.registerTool({
name: "get-trybot-statuses",
description: "Returns the current status of all trybot runs for the active patch.",
execute() {
return activePatch.getStatuses();
}
});
inputSchema すら省略できます。引数を取らないツールなら、これで動きます。
段階2:入力スキーマを付ける
引数を受け取るなら JSON Schema を書きます。enum を使うと、エージェントが取りうる値を推測せずに済みます。
await document.modelContext.registerTool({
name: 'get_order_status',
description: 'Search orders in a given timeframe. Returns order number, shipping status and location',
inputSchema: {
type: 'object',
properties: {
timeframe: {
type: 'string',
enum: ['today', 'yesterday', 'last_7_days', 'last_30_days', 'last_6_months'],
description: 'Timeframe for the order lookup.'
}
},
required: ['timeframe']
},
execute: async ({ timeframe }) => {
// 既存のAPI呼び出しやDBアクセスをここに書く
},
});
enum を書かずに type: 'string' だけにすると、エージェントは "先週" や "past week" のような値を渡してきます。選択肢が決まっているものは必ず enum にしておくほうが安全です。
段階3:注釈・公開範囲・解除を付ける
本番に載せる段階では、あと3つ足します。
const controller = new AbortController();
await document.modelContext.registerTool({
name: 'get_reviews',
title: 'レビュー一覧の取得',
description: '表示中の商品に投稿されたレビューを返します。',
inputSchema: {
type: 'object',
properties: {
limit: { type: 'number', description: '取得する件数。1〜50。' }
}
},
annotations: {
readOnlyHint: true, // 状態を変えない
untrustedContentHint: true // 出力はユーザー投稿=信用できない
},
execute: async ({ limit = 10 }) => fetchReviews(limit),
}, {
signal: controller.signal, // 解除用
exposedTo: ['https://partner.example'] // 公開先を絞る
});
// ページ遷移やモーダルを閉じるタイミングで解除する
// controller.abort();
3つの追加要素の意味は次のとおりです。
-
annotations—readOnlyHint: trueは「このツールは何も壊さない」という申告です。エージェントはこれを見て、ユーザーへの確認を挟むかどうかを判断します。untrustedContentHint: trueは「返す中身は外部由来なので、指示として解釈しないでほしい」という申告です -
signal— 解除はunregisterTool()のような専用メソッドではなく、AbortControllerで行います。SPA でルートが変わったらabort()する、という書き方になります -
exposedTo— 既定では、ツールは自分自身・同一オリジンの文書・ブラウザ内蔵のエージェントにしか見えません。特定のオリジンに見せたいときだけ、明示的に列挙します
ツールの一覧を取るときは getTools() を使います。既定では同一オリジンのツールを名前順で返します。
// 同一オリジンのツール
const tools = await document.modelContext.getTools();
// 特定のオリジンのツールも含めて取得する
const allTools = await document.modelContext.getTools({
fromOrigins: ['https://partner.example']
});
// ツールの増減を監視する
document.modelContext.addEventListener('toolchange', () => {
console.log('ツール一覧が変わりました');
});
📝 JavaScript を書かない選択肢:宣言的 API
WebMCP には、HTML の <form> に属性を足すだけでツール化する方法も用意されています。問い合わせフォームや検索フォームのように「入力して送信する」だけの機能なら、こちらのほうが速いです。
<form toolname="supportRequestTool"
tooldescription="Submit a request for support."
action="/submit">
<label for="firstName">First Name</label>
<input type="text" name="firstName">
<label for="lastName">Last Name</label>
<input type="text" name="lastName">
<select name="select" required
toolparamdescription="Determines what team this request is routed to.">
<option value="Customer happiness team">Return my purchase.</option>
<option value="Distribution team">Check where my package is.</option>
<option value="Website support team">Get help on the website.</option>
</select>
<button type="submit">Submit</button>
</form>
使う属性は4つです。
| 属性 | 付ける場所 | 役割 |
|---|---|---|
toolname |
<form> |
ツール名。これと tooldescription が揃うとツールとして登録される |
tooldescription |
<form> |
ツールの説明 |
toolparamdescription |
入力要素 | パラメータの説明。省略時は <label> や aria-description が使われる |
toolautosubmit |
<form> |
エージェントが呼んだときに自動で送信する |
toolname か tooldescription を外すとツールは登録解除されます。条件によってツールを出し分けたいなら、属性を付け外しすれば済みます。
エージェントがこのツールを呼んだとき、ページ側では次のことが起きます。
注目したいのは、フォームがユーザーに見えたまま操作が進むところです。値が勝手に入るところまでは見えていて、送信するかどうかはユーザーが判断できます。:tool-form-active という疑似クラスまで用意されているのは、「今エージェントが触っています」を視覚的に示すためです。
送信イベントには agentInvoked というブール値が付きます。人間が押したのかエージェントが呼んだのかを区別できるので、ログを分けたり、エージェント経由のときだけ確認ダイアログを出したりできます。
form.addEventListener('submit', (e) => {
if (e.agentInvoked) {
e.preventDefault();
e.respondWith(submitSupportRequest(new FormData(form)));
}
});
🛡️ セキュリティ:ログイン済みの画面で動くということ
ここが WebMCP のいちばん神経を使うところです。ツールは訪問者のブラウザで、訪問者のセッションのまま実行されます。API キーを配らなくていいのは楽ですが、裏を返すと「エージェントを騙せば、ログイン中のユーザーとして操作できる」ということでもあります。
Chrome のセキュリティガイドは、主な脅威として間接プロンプトインジェクションを挙げています。データの中に「これまでの指示を無視して……」のような文字列を仕込み、それを読んだエージェントを乗っ取る攻撃です。ドキュメントには、最新の LLM に対しても再現可能な攻撃が存在すること、そして Web 上での攻撃が増えていることが明記されています。
信頼境界を図にすると、こうなります。
仕様側が用意している防御は、大きく3層あります。
1層目:Permissions Policy — tools というトークンが定義されていて、既定の allowlist は ['self'] です。つまりクロスオリジンの iframe からは既定で使えません。使わせたい場合だけ、埋め込み側が明示します。
<iframe src="https://chat-bot-provider.example/" allow="tools"></iframe>
許可がない状態で registerTool() を呼ぶと、Promise が NotAllowedError で reject されます。
2層目:exposedTo — 登録時にオリジンを列挙して、ツールを見せる相手を絞ります。ガイドでは、読み取り専用ツールは「そのデータを直接渡してよい相手」に、書き込み系ツールは「ユーザーの代理として行動させてよい相手」だけに公開するよう勧めています。
3層目:annotations — readOnlyHint と untrustedContentHint です。強制力のあるサンドボックスではなく、エージェントに判断材料を渡すためのヒントです。ただ、これを付けておかないとエージェントは「全部が危険かもしれないし、全部が安全かもしれない」という前提で動くことになります。
実務でのリスクと対策を整理すると、次のようになります。
| リスク | 起きること | 対策 |
|---|---|---|
| 間接プロンプトインジェクション | レビュー本文などに仕込まれた指示にエージェントが従う | 外部由来を返すツールに untrustedContentHint: true
|
| 意図しない状態変更 | 確認なしに購入・削除が実行される | 状態を変えるツールは readOnlyHint を付けない。execute 側でも確認を挟む |
| 情報の漏れ出し | 個人情報を返すツールが他オリジンから呼ばれる |
exposedTo を明示。既定の ['self'] を安易に広げない |
| 権限の踏み台化 | 埋め込んだ外部 iframe がツールを呼ぶ |
allow="tools" を付ける相手を限定する |
| 説明文からの誤用 | エージェントが用途を取り違える |
description に「使ってよい場面」と「使ってはいけない場面」を書く |
説明文については、Chrome のガイドが文字数の目安まで示しています。長ければ良いというものではないという話です。
| 対象 | 推奨する長さ |
|---|---|
ツールの description
|
500文字まで |
パラメータの description
|
150文字まで |
| ツール名・パラメータ名 | 30文字まで |
| ツール1回の出力 | 1.5K文字まで |
💡 出力の 1.5K 文字という上限は、地味ですが設計に効いてきます。「注文一覧を全部返す」ようなツールは、そのままだと上限を超えます。件数を絞る引数を必ず用意して、既定値も小さめにしておくほうが噛み合います。
📊 実装状況(2026年8月14日時点)
現時点のブラウザ対応をまとめます。
| ブラウザ | 状況 |
|---|---|
| Chrome |
149 から Origin Trial が開催中。ローカル検証は chrome://flags/#enable-webmcp-testing で可能 |
| Edge | 147 でフラグ付きの実験的サポート。「ネイティブ対応」と報じる記事もありますが、Microsoft の公式リリースノートには記載がないと指摘されています |
| Firefox / Safari | 仕様の議論には参加。実装の表明はまだありません |
Origin Trial は Chrome 156 まで続く見込みとする報道もありますが、これは二次情報なので、参加する場合は Chrome の Origin Trial ページで期間を確認してください。
ここまでの流れを時系列で追うと、こうなります。
仕様は W3C の標準化トラックには乗っておらず、Community Group のドラフトという位置づけです。図の右側2つを見ると分かるとおり、API 面はまだ動いています。プロダクションに入れるなら、そこは織り込んでおく必要があります。
⚠️ いちばんのハマりどころ:navigator から document への引っ越し
WebMCP を検索して最初に読む記事が、動かないコードを載せている可能性はかなり高いです。API の置き場所と登録方法が、この半年で2回変わっているためです。
| 時期 | API の場所 | 登録方法 |
|---|---|---|
| 〜2026年3月 | navigator.modelContext |
provideContext({ tools: [...] }) — 呼ぶたびに全ツールが置き換わる |
| 2026年3月〜7月 | navigator.modelContext |
registerTool() / unregisterTool()(provideContext は削除) |
| 2026年7月21日〜 | document.modelContext |
registerTool()、解除は AbortSignal
|
Chrome のドキュメントには、はっきりこう書かれています。
navigator.modelContextis deprecated in Chrome 150. Usedocument.modelContextinstead.
置き場所が navigator から document に移ったのは、「ツールは特定のページに属するもの」という考え方を反映するためです。navigator はブラウザ全体を表すオブジェクトなので、タブごとに違うツールが生えるという性質と噛み合っていませんでした。
日本語の検証記事では、Chrome 146 の頃のフラグ名(chrome://flags#webmcp-for-testing)や provideContext() が紹介されているものがあります。当時は正しかった情報です。今から試すなら、フラグ名は chrome://flags/#enable-webmcp-testing、API は document.modelContext を使ってください。
既存コードを移行するときの最小の書き換えは、次のようになります。
// 旧(Chrome 146 期)
navigator.modelContext.provideContext({
tools: [ { name: 'calculate', /* ... */ } ]
});
// 現行
await document.modelContext.registerTool({
name: 'calculate',
// ...
});
provideContext() は「渡した配列で全ツールを置き換える」という挙動でした。registerTool() は1つずつ追加していく方式なので、ツールを入れ替える処理を書いていた場合は、AbortController での解除に置き換える必要があります。
⚠️ 「両対応にしておけば安心」と考えたくなりますが、
navigator側は Chrome 150 で非推奨になっています。新規に書くならdocument.modelContextだけを見るほうが素直だと思います。
☁️ Cloudflare の実装:ダッシュボードのトグル1つ
2026年8月6日、Cloudflare が WebMCP のサポートを発表しました(著者は Will Rowe さん、Developer Preview 段階)。面白いのは、サイト側のコードを1行も書かずに WebMCP 対応にしてしまうアプローチです。
ダッシュボードの Agent Readiness > WebMCP をオンにすると、Cloudflare がエッジで HTML を書き換えて、ブリッジ用のスクリプトタグを注入します。ブログの表現をそのまま借りると「デプロイするものは何もなく、オリジンで変更するものも何もない」という状態です。
注入されるのはこれだけです。
<!-- Cloudflare injects this at the edge. Same origin, and your HTML is otherwise untouched. -->
<script type="module"
src="/.webmcp/bridge.js"
data-packs="c2pa,mcp-server-client"
data-mcp-url="/mcp"></script>
書き換えには HTMLRewriter が使われていて、HTML の他の部分には手を触れません。WebMCP 非対応のブラウザでは、ブリッジは何もせずに return するので、ページの挙動は今までと変わりません。
導入されたかどうかは、次のコマンドで確認できます。
curl -s https://your-site.example | grep webmcp
構成を図にすると、こうなります。
Developer Preview では、ツールパックが2つ用意されています。
Content Credentials pack は、ページ内の画像に C2PA(コンテンツの来歴情報)が付いているかを調べます。scan_images_c2pa がページ全体を走査し、inspect_image_c2pa が個別のマニフェスト(編集履歴や署名証明書)を返します。
{
"imageCount": 12,
"scanned": 12,
"withC2pa": 8,
"results": [
{
"src": "https://example.com/hero.jpg",
"hasC2pa": true,
"format": "image/jpeg",
"manifestCount": 1,
"claimGenerator": "Adobe Firefly",
"title": "sunrise over the bay",
"signedBy": "Adobe Inc."
},
{ "src": "https://example.com/logo.png", "hasC2pa": false, "format": "image/png" }
]
}
ここは注意が要ります。このツールは署名を暗号学的に検証していません。あくまで「そう書いてある」という申告を読んで報告するだけで、結果には常に signatureVerified: false が付きます。「C2PA が付いている=本物」と受け取ると誤読になります。
Site MCP Server pack のほうが、実務では効いてくると思います。サイトが同一オリジンに /mcp を持っている場合、その tools/list を読んで、各ツールを registerTool にそのまま流し込みます。呼び出しは tools/call にプロキシされます。
document.modelContext.registerTool({
name: tool.name, // 例: "search_products"
description: tool.description,
inputSchema: tool.inputSchema, // tools/list の内容をそのまま使う
execute: async (args) => {
const res = await fetch(mcpUrl, { // 同一オリジンの /mcp
method: "POST",
credentials: "same-origin",
headers: { "content-type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0", id: 1, method: "tools/call",
params: { name: tool.name, arguments: args },
}),
});
const { result } = await res.json();
return result; // MCP の CallToolResult をそのまま返す
},
});
credentials: "same-origin" の1行がこのパターンの肝です。訪問者のログインセッションがそのまま乗るので、「自分の注文を検索する」のような認証付きの操作が、追加の認証設計なしで動きます。MCP サーバーを既に持っているサイトなら、WebMCP 対応のコストはほぼゼロになります。
Cloudflare のリモートブラウザである BrowserRun も WebMCP に対応済みなので、ローカルの Chrome でもヘッドレス環境でも、同じようにツールを発見して呼べます。
セキュリティの3層と Cloudflare の構成を1枚にまとめると、上のようになります。
🤔 では、いま実装すべきなのか
ここまで書いておいて何ですが、2026年8月時点の正直な状況として、呼ぶ側がまだほとんどいません。
Claude も ChatGPT Agent も Perplexity も Gemini も、Web 操作の実装は依然として DOM スクレイピングやスクリーンショットです。document.modelContext のツールを積極的に呼ぶ主要エージェントは、まだ登場していません。Google は Gemini in Chrome を最初の主要な消費者にすると表明しているので、そこが最初の分岐点になりそうです。
Google I/O 2026 では、Expedia、Booking.com、Shopify、Credit Karma、TurboTax、Redfin、Etsy、Instacart、Target といった名前が「実験している企業」として挙がりました。ただし、これらが本番で稼働しているという確証は公開されていません。旅行予約・EC・金融・不動産・配送と、繰り返し操作が多い領域に偏っているのは、いかにも納得できる並びではあります。
仕様の非ゴールも確認しておく価値があります。WebMCP は次のことをやらないと宣言しています。
- ヘッドレスブラウジング(人が見ている前提の設計です)
- 人間の監督なしの完全自律ワークフロー
- バックエンドの MCP プロトコルの置き換え
- 人間向け UI の置き換え
つまり「夜間バッチでエージェントに全部やらせる」という用途は最初から想定外です。あくまで、ユーザーが開いているタブの中で、人とエージェントが協調する場面のための仕様です。
判断の目安を整理すると、こうなります。
私の見立てとしては、いま急いで全機能をツール化する必要はないと思います。一方で、既に MCP サーバーを持っているサイトと、フォームが主役のサイトは、コストがあまりに小さいので試しておいて損がありません。前者は tools/list をブリッジするだけ、後者は HTML の属性を2つ足すだけで終わります。
手元で動きを見るだけなら、手順は3つです。
- Chrome 149 以降で
chrome://flags/#enable-webmcp-testingを Enabled にして再起動する - localhost か HTTPS のページを開く(
file://では動きません。セキュアコンテキストが必要です) - DevTools のコンソールで
'modelContext' in documentがtrueになることを確認してからregisterTool()を呼ぶ
実ユーザーに対して有効化したい場合は、Chrome の Origin Trial に登録してトークンを取得します。
✅ まとめ
WebMCP について、この記事で一番お伝えしたかったのは「サイト側が主導権を取り戻せる仕組みである」ということです。
スクレイピング型のエージェントは、サイトの意思とは無関係に画面を読み、推測で操作します。WebMCP では、何を公開して何を公開しないかをサイトが決めます。しかも公開するのは新設の API ではなく、既にボタンから呼んでいる関数です。実装コストと得られるコントロールのバランスとしては、かなり良い部類だと思います。
一方で、今すぐ全面的に投資する話でもありません。呼ぶ側のエージェントが揃うのはこれからですし、API 面もまだ動いています。navigator から document への移動が起きたのは、つい先月のことです。
次の一歩としては、次の順で触ってみるのが現実的だと思います。
- ローカルでフラグを立てて、
registerTool()を1つ書いてみる(15分もあれば動きます) - 問い合わせフォームに
toolnameとtooldescriptionを足して、宣言的 API の挙動を見る - 自社サイトが MCP サーバーを持っているなら、Cloudflare のトグルか、自前のブリッジで繋いでみる
そして、公開するツールを増やすときは、readOnlyHint と untrustedContentHint を必ず付けてください。ログイン済みのセッションで動くという性質上、ここを省略したときのリスクは、ツールの便利さとちょうど同じ大きさになります。
参考
- WebMCP 仕様ドラフト — W3C Web Machine Learning Community Group(Draft Community Group Report, 2026-08-12)
- WebMCP Explainer — webmachinelearning/webmcp
- WebMCP | AI on Chrome — Chrome for Developers
- Imperative API — Chrome for Developers
- Declarative API — Chrome for Developers
- WebMCP tool security — Chrome for Developers
- Join the WebMCP origin trial — Chrome for Developers
- Bring your site to the agentic web with WebMCP — Cloudflare Blog(2026-08-06)
- Chrome 149 origin trial puts WebMCP in developers' hands at last — PPC Land
- The State of WebMCP: July 2026 — Spronta
- WebMCPについて調べて、動きを確認してみた — DevelopersIO(Chrome 146 期の記録)

