Web サイトが AI Agent と直接対話する:WebMCP を試してみた
WebMCP は、Web サイトが自らの機能を AI Agent に直接公開するための新しい Web プラットフォーム API です。Google と Microsoft が主導し、現在は W3C Web Machine Learning Community Group のドラフト段階にあります。コア API は document.modelContext.registerTool() で、サイト側が呼び出し可能な JavaScript 関数を登録すると、Agent はスキーマに従ってそれを直接呼び出せます。「スクリーンショットを撮って UI を認識し、ボタンを推測して押す」という一連の手順が不要になります。
以前 Agent Ready 化を進めたとき、この項目は意図的に見送りました。Chrome がまだ Early Preview で、仕様も変わり続けていて、静的サイトにとって費用対効果が合わなかったからです。ここ数日で公式ドキュメント、いくつかのインタビュー、コミュニティの polyfill を一通り読み、小さな demo も書いて実際に動かしてみたので、その学習メモとしてまとめます。
2026-08 追記:WebMCP は現在 Chrome 149 および Edge でのオリジントライアル(Origin Trial)に進み、エントリーポイントは document.modelContext に変更され、ChatGPT デスクトップ版の Site tools にも対応しました。詳細は文末の 2026-08 更新後記 をご覧ください。

Demo は kuro-roasters-webmcp という別 repo に置いてあります。ここでは WebMCP のおおまかな紹介と、開発者がつまずきそうなポイント、そして私が予想する今後の展開などを記録しておきます。
なぜ WebMCP が必要なのか
現時点で AI Agent が Web ページを操作する方法は二つあります。
一つはバックエンド API または MCP server です。安定していて制御しやすい反面、サイト側がそれを公開していることが前提になります。 多くのサイトにはそれがなく、あったとしても OAuth、API key、rate limit といった面倒を処理しなければなりません。
もう一つは、いま最も一般的な Browser Agent(Claude Computer Use や OpenAI Operator など)で、モデルに画面を見せ、UI を認識させ、どのボタンを押すか決めさせる方式です。サイト側の協力は不要ですが、毎ステップでスクリーンショットや DOM 全体を context に詰め込むため、遅くて高コストで、サイトが class 名を一つ変えただけで壊れます。
WebMCP は第三の道を切り開きます。サイト自身が、できることを Agent が理解できる構造で明示するというものです。モデルに画面から推測させるのではなく、サイトが名前、自然言語による説明、input schema を持つ JavaScript 関数の一式を宣言し、Agent はスキーマに従って呼び出すだけです。Scalekit の explainer にかなり具体的な比較があります。「Drugstore という支店を追加して、リップクリームを一つ追加する」というタスクで、従来の Browser Agent は 30〜60 秒かかるのに対し、WebMCP の tool call なら約 5 秒で終わります。違いは速さだけではありません。一方は十数枚のスクリーンショットが必要で、もう一方は function call 二回で済むのです。
WebMCP は現在、W3C Web Machine Learning Community Group で incubation 中の Draft Community Group Report です(執筆時点のドラフトは 2026-04-23 版で、まだ更新が続いています)。W3C Standard ではなく、Standards Track にも乗っていないことが明記されており、Google と Microsoft が推進しています。Chrome 146 Canary から Early Preview Program が始まりました。他のブラウザにはまだネイティブ対応がありませんが、Mozilla と Apple のエンジニアも working group に参加しており、完全に関与していないわけではありません。
WebMCP はどう使う?
コア API の入口は一つだけ、document.modelContext.registerTool() です。tool の登録は次のようになります:
const context = document.modelContext;
const registrationController = new AbortController();
if (typeof context?.registerTool === 'function') {
await context.registerTool({
name: 'search_products',
title: '商品を検索',
description: '商品を検索する。キーワードと上限価格によるフィルタに対応。',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: '検索キーワード' },
maxPrice: { type: 'number', description: '上限価格' }
},
additionalProperties: false
},
annotations: { readOnlyHint: true },
async execute(input, { signal }) {
signal.throwIfAborted();
const res = await fetch('/api/search?' + new URLSearchParams(input));
return res.json();
}
}, { signal: registrationController.signal });
}
// ページやコンポーネントの破棄 hook から呼び出す
const unregisterTool = () => registrationController.abort();いくつか特に触れておきたい点があります。description はモデルがこの tool を呼ぶかどうかを判断する主な根拠なので、自然言語で書き、どの場面で使うかを明確にすると信頼性が上がります。 inputSchema は JSON Schema そのもので、enum、required、minimum といった一般的な属性はすべて対応しています。 annotations.readOnlyHint: true は、この tool が状態を変更しないことを示すヒントです。呼び出し側はリスク判断に使えますが、確認の要否はブラウザや Agent host のセキュリティポリシーに委ねられます。 execute は構造化された input を受け取り、第二引数の signal で実行のキャンセルを受け取ります。戻り値には通常の JavaScript オブジェクトをそのまま返せます。ブラウザ側でシリアライズされるため、MCP スタイルの { content: [...] } wrapper は不要です。
初期ドラフトにあった ModelContextClient と client.requestUserInteraction() は、現行ドラフトからいったん削除されています。状態を変更したりセンシティブな処理を行う tool は readOnlyHint: false を正しく指定し、呼び出しの審査とユーザー確認をブラウザや Agent host に任せます。ページ内の Gemini function calling シミュレーターやシナリオボタンはブラウザ Agent の安全審査を通らないため、アプリケーション側で window.confirm() などの確認を追加する必要があります。
仕様にはさらに「declarative API」も計画されていて、既存の <form> に toolname / tooldescription / toolautosubmit の三つの属性を付けるだけで自動的に tool に変換できるというものです。本体仕様のこの章はまだ書き終わっていませんが、working group は GitHub issue #22 と declarative-example repo で進めています。いま手を動かすなら imperative の方を選ぶのが現実的です。
ネイティブ API のないブラウザでは @mcp-b/global polyfill が使えます。インストール後に import '@mcp-b/global' と書けば、必要な場合に document.modelContext が補われます。注意点として、polyfill が補うのは API の表面だけで、一般的なブラウザにはそれを呼び出す Agent が内蔵されていません。実際のブラウザ WebMCP を試すには、ChatGPT デスクトップ版の Site tools または Chrome の WebMCP テスト機能を使います。自分で LLM を繋いで駆動させるなら、どのブラウザでも動きます。demo repo の Gemini サンプルはまさにその方式で動いています。
WebMCP がもたらすメリット
三つの立場からそれぞれ見てみます。
サイト開発者にとって最大の魅力は、Agent 向けに API を作り直さなくていいことです。ページにもともとある JavaScript 関数を registerTool で包むだけで Agent から使えるようになり、ロジックの書き直しは不要です。Agent にできることを絞るのも簡単で、どの tool を登録するか、どんな description を書くかを決めるだけです。Token コストの差も驚くほどで、DOM スクリーンショット方式では一回のやり取りで数千から一万を超える tokens を詰め込むことが多いのに対し、構造化された tool call なら大半が数百 tokens 以内に収まります。従量課金のモデルにとっては一〜二桁の差です。
ユーザーにとっては、制御可能性と可視性が同時に向上します。ブラウザや Agent host は、結果を伴う操作の前に処理を止めて確認できます。tool call 自体が構造化されているので、監査側は「Agent が place_order を呼び、これらのパラメータを渡した」と明確に確認でき、「3 番目のボタンをクリックした」といった曖昧なイベントの塊にはなりません。もう一つ非常に実用的な利点は、ユーザーのログインセッションをそのまま流用できることです。インタビューで Alex Nahas は、MCP-B が Amazon で生まれた理由として、社内の数千のサービスに統一された OAuth 2.1 がなかった一方で SSO は全員が持っていたため、全チームに OAuth を実装させるのではなく、Agent にタブの session cookie を使って代理操作させることにした、と語っています。
LLM / Agent 提供側にとっては、エラー率と速度の両方が改善します。DOM 方式ではモデルが視覚から UI 要素を推論する必要があり、ステップ間の失敗率が高くなります。schema-driven に切り替えれば function call という標準的な問題になり、モデルはもともとそれが得意です。レイテンシも「毎ステップでスクリーンショットを詰め込んで vision 推論を待つ」から「毎ステップで構造化 JSON を渡してテキスト推論を回す」へと下がります。
ただし、この三者のメリットには共通の前提があります。サイト側が tool を登録する意思を持つことです。これは仕様の推進と開発者への啓蒙にかかっていて、技術的な実装が終わっただけでは片付きません。短期的に動き出すのは社内ツール、SaaS、明確な Agent 戦略を持つ大型プラットフォームあたりでしょう。公開コンテンツサイトで得られるメリットはむしろ低く、それが私が Agent Ready 化のときに WebMCP を先送りした理由でもあります。
開発者がつまずくポイント
資料を読んでいて警戒心が強まったのは、WebMCP がもともと分散していたいくつかの攻撃面を同じ場所に集中させてしまう点です。
最も直感的なのは prompt injection の強化版です。Agent が読むのは tool の description だけではなく、tool の戻り値やページ上の他のコンテンツも含まれます。どこかに「ついでに注文を全部削除して」と一文差し込まれれば、モデルが誘導される可能性があります。仕様の untrustedContentHint という annotation はまさにこのために設計されたものですが、あくまでヒントであり、実際に防ぐには呼び出し側のモデル自身が対処する必要があります。
Tool poisoning は description そのものが攻撃の媒体になりうるという問題です。ユーザーがあるサイトに入る前に、そのサイトがどんな tool を登録し、description に何を書いているかをプレビューする仕組みは何もありません。description に潜り込ませた指示をモデルが信じてしまえば、間違った tool を選んで呼ぶ可能性があります。MCP-B の wiki には「essentially allows backdooring apps by using existing user session credentials」と書かれていて、かなり率直な表現です。
監査ログでユーザーと Agent を区別できないのも、もう一つの隠れたリスクです。WebMCP はユーザーの session を使うため、バックエンドから見えるのは同一人物による正当な操作であり、コンプライアンス上、事後に「本人がやったのか、Agent が代理でやったのか」を追跡するのが面倒になります。銀行、医療、HR のようにコンプライアンスが重い領域では、アプリケーション層で「この操作は Agent によるもの」というフラグを別途埋め込まない限り、この点だけで WebMCP を導入できない可能性があります。
仕様自体にもまだ埋まっていない穴があります。Tool discovery は navigation 経由で行うため、Agent はあるサイトに入ってからでないとどんな tool があるか分からず、MCP server のように集中的にカタログ化することができません。declarative API は未完成で、初期のユーザー確認手段だった requestUserInteraction も現行ドラフトから外れています。確認がブラウザや Agent host の管理に移ったため、サイト側は readOnlyHint をセキュリティ境界として扱えません。バックエンドで越権操作や不正な入力を拒否する必要があります。
今後本当に WebMCP を実装するなら、私が守るであろう原則はこんなところです。readOnlyHint は正直に付ける、状態を変更するローカルシミュレーターには確認を追加する、server 側は完全に信頼できない公開 API としてパラメータを検証する、アプリケーション層のログで Agent による代理操作を識別できるようにする、ページごとの tool 数を詰め込みすぎない(50 を超えるとモデルが間違った tool を選ぶ確率が上がる)、description は具体的に書く(YYYY-MM-DD のようなフォーマット制約も含めて)。そして仕様とは無関係だけれど非常に重要なことが一つ。Agent に与える権限はユーザー本人より一段小さくする。モデルが悪意ある prompt に誘導されたときに、大きな事故を起こさせないためです。
今後の展開の可能性
ここからは現時点の仕様のギャップとコミュニティの議論に基づいた私の推測なので、参考程度に読んでください。 ただ、これらが本当に動き出したら、二、三年後の Web エコシステムは今とはかなり違うものになると思っています。
ブラウザ対応は予想どおり先に動きました。Chrome 149 と Edge はオリジントライアルに進み、ChatGPT デスクトップ版も Site tools から現在のページにある WebMCP tool を呼び出せます。Firefox と Safari は W3C working group にエンジニアが参加しているものの、公開された対応時期はなく、Chromium 以外は引き続き様子見です。
Declarative API の成熟は導入の敷居を大きく下げるはずです。今の imperative 方式では JS を一式書く必要があり、大量の単純なフォーム(お問い合わせ、ニュースレター登録、サイト内検索)に対しては大げさすぎます。<form toolname="..."> のような宣言的インターフェースが整えば、Agent 対応は aria-label を付けるのと同じくらいの小さな作業になり、EC と SaaS のオンボーディングフローが最初に動き出す可能性が高いでしょう。
クロスオリジンでの tool 共有は v1 では明確に除外されています(同一オリジンでの tool 登録のみ許可)が、将来の計画には挙げられています。利用シーンは明確で、「台北で評価が最も高いレストラン五軒を探して一気に予約する」といったタスクでは Agent が複数のサイトをまたいで調整する必要があり、一つのタブだけでは実現できません。ユーザーデータを保護しつつ cross-origin invocation を許可する方法は未解決の設計課題で、類推するなら postMessage と明示的なユーザー確認を組み合わせたハイブリッドになるかもしれません。
Tool discoverability も未解決の課題で、エコシステムへの影響は仕様本体より大きいかもしれません。現在 Agent はあるサイトに navigate してからでないとどんな tool があるか分からず、MCP server catalog のような集中インデックスは存在しません。コミュニティでは agenticweb.md のような machine-readable な発見規約を推す動きがあり、「robots.txt と同じ場所に置き、この domain が提供する tool の構造化された一覧を書く」という考え方です。この方向が固まれば、「SEO」という言葉の意味の半分くらいは書き換わることになるでしょう。
PWA とバックグラウンド実行はやや遠いものの、かなり興味深い可能性です。PWA manifest でどの tool が「UI を開かずに実行できる」かを宣言できれば、Agent は可視のタブがない状況でもそれを呼び出せるようになり、「毎週金曜の午後に買い物リストをチェックして、セール品があればカートに入れておいて」といったバックグラウンドの代理タスクが実現します。これは WebMCP が「ユーザーに付き添って現在のタブを操作する」から「ユーザーの代わりにバックグラウンドでタスクを回す」へと広がる、一つの可能な道筋です。
これらの方向性が合わさって指しているのは同じことです。Web 全体が「人が見るためのページ」から「人と Agent が共有するインタラクション面」へ変わりつつあるということです。短期的に動くのはやはり社内ツール、SaaS、主要な EC あたりでしょうが、Firefox と Safari も追随し、クロスオリジンと discovery にも合意ができれば、二年後の Web エコシステムは今とはかなり違うものになります。
WebMCP を触ってみたい人へ
今回の Demo は kuro-roasters-webmcp という repo に置いてあり、オンライン版は https://kuro.tw/kuro-roasters-webmcp/ を開けばすぐ遊べます。WebMCP の利用フローの雰囲気を掴んでもらえると思います。
Demo のシナリオは架空のコーヒー豆ショップで、五つの WebMCP tool(検索、商品を見る、カートに追加、カートを見る、注文を送信)を登録しています。ChatGPT デスクトップ版や Chrome では実際の WebMCP 呼び出しを試せます。通常のブラウザでもシナリオボタンと Gemini function calling シミュレーターは動きますが、後者の二つはページ内のローカルシミュレーションであり、ブラウザ Agent が WebMCP を呼び出したわけではありません。技術的な詳細(TOOL_DEFS の集中管理、polyfill の挙動、agent loop と Gemini の繋ぎ方)はそちらの README に書いてあるので、この記事では深入りしません。
ChatGPT デスクトップ版でテストする
執筆時点で Site tools を再現性のある形で試すには、ChatGPT デスクトップ版の内蔵ブラウザを ChatGPT Work の会話から使います。通常のチャットに URL を貼る方法、外部の Chrome、単体の Codex App では同じ経路を通りません。Site tools 公式ドキュメントによると、現在 WebMCP が有効なのは GPT-5.6 Sol と Terra で、Luna はまだ対象外です。
ChatGPT デスクトップ版を最新版に更新し、
Settings → Browser → Permissions → Enable site toolsを有効にします。ChatGPT Work の会話を作り、GPT-5.6 Sol または Terra を選びます。
Cmd + Shift + Bで内蔵ブラウザを開き、https://kuro.tw/kuro-roasters-webmcp/ に移動します。ページ上部に
document.modelContext 已註冊 5 個 toolと表示されることを確認します。同じ Work の会話で検索を試します。
text現在のブラウザページが提供する Site tools を使い、 価格が 500 台湾ドル以下の浅煎りコーヒー豆を検索して、 名前と価格を一覧にしてください。通常の画面操作は使わないでください。続けて、ページの状態を変更する操作を試します。
text現在のページの Site tools を使い、検索結果で最も安い コーヒー豆を 2 袋カートに追加してください。その後 view_cart を使って カートの内容を報告してください。注文は確定しないでください。
成功すると、ページの絞り込み条件やカートが変化し、ChatGPT に tool 呼び出しと安全性審査が表示されます。対象の UI が段階的リリース(rollout)済みのアカウントでは、アドレスバーにも Site tools が現れ、Available site tools と Recently used を確認できます。
入口がまったく見つからない場合は、会話の種類、モデル、内蔵ブラウザ、権限設定を確認してください。Enterprise と Edu workspace は現在対象外です。条件がすべて正しければ、そのアカウントにはまだ段階的リリースが届いていない可能性があります。
ChatGPT デスクトップ版で実際に試したところ、Vue / Pinia 固有の落とし穴も見つかりました。TOOL_DEFS が Pinia store から返されると、Vue は inputSchema や annotations まで含めて深い reactive Proxy に変換します。WebMCP は tool 登録時にこれらのデータを実行環境の間でコピーしますが、Proxy は structured clone できません。その結果、ページには An object could not be cloned.、ChatGPT には No WebMCP tools are available in this document. と表示されます。
修正は一行で済みました。Vue の markRaw() で TOOL_DEFS を包み、tool 定義を通常の JavaScript オブジェクトのままにします。schema 自体には問題がなく、reactive Proxy が structured clone の境界にぶつかっていました。
2026-08 追記:早期プレビューから Site tools 登場まで
この記事を公開してから 4 か月(2026 年 8 月)、WebMCP の仕様とエコシステムの進展は予想以上に早く動いています。本文の例は現行 API に合わせて更新済みなので、ここでは変更の経緯を残しておきます。
まずコア API の変更です。仕様上のエントリーポイントは navigator.modelContext から document.modelContext へと移行し(旧名称は Chrome 150 から非推奨扱い)、ドキュメントごとに独立したコンテキストを持つ形になりました。ブラウザ対応も初期の実験用フラグから、Chrome 149 や Edge でのオリジントライアル(Origin Trial)へと進んでいます。
同時に、初期ドラフトにあった ModelContextClient やユーザー確認の仕組みは一旦仕様から外れ、標準の AbortSignal でツールの登録と実行のライフサイクルを管理する方式に改められました。途中で登録を解除しても、実行中の処理は中断されません。また、ツールの実行関数は通常の JavaScript オブジェクトを直接返せるようになり、ブラウザ側で自動的にシリアライズされるため、MCP 形式の構造で包み直す必要もなくなりました。
さらに大きな転換点は、AI エージェント側の動きです。本文では Gemini in Chrome が最初の組み込み入口になるのではないかと推測していましたが、2026 年 8 月末に OpenAI が ChatGPT デスクトップ版の内蔵ブラウザで「Site tools」を先行リリースしました。ChatGPT Work や Codex が、開いているページで登録された WebMCP ツールを直接検出し、既存のログイン状態や画面データを共有しながら呼び出せるようになっています。
OpenAI はこれに合わせて Chrome、Shopify、Cloudflare、Vercel などと共同で WebMCP 挑戦企画(WebMCP Challenge)を開催し、開発者によるツールの提供を促そうとしています。
これにより、WebMCP が直面する課題の構図が変わりました。かつては「サイト側がツールを用意しても使ってくれる AI がいない」という鶏と卵の問題が最大の壁でしたが、主要な AI エージェントが先に登場したことで、現在の本当のボトルネックは「WebMCP ツールを実際に提供しているサイトがまだ極端に少ないこと」へと移っています。
もし手元に操作手順が多く状態管理の重いフロントエンドアプリや管理画面があるなら、オリジントライアルや ChatGPT デスクトップ版を使って連携を試してみる絶好のタイミングです。ただし重要なデータの変更を伴う操作では、バックエンド側での権限と入力検証を厳格に保ち、安全性をすべて AI 側の事前審査任せにしないよう注意してください。
参考資料
- WebMCP 仕様ドラフト (W3C WebML CG)
- WebMCP GitHub Repo
- Chrome 公式 blog:WebMCP Origin Trial
- Chrome 公式 blog:WebMCP is available for early preview
- Chrome 公式 blog:When to use WebMCP and MCP
- OpenAI 公式ドキュメント:Site tools
- OpenAI 公式ドキュメント:ChatGPT 内蔵ブラウザ
- Scalekit:WebMCP explained
- Arcade による Alex Nahas インタビュー
- MCP-B Wiki:Known Security Issues With WebMCP
@mcp-b/globalnpm ページ- Gemini function calling 公式ドキュメント
- awesome-webmcp