はじめに
第1回でWebMCPの「なぜ」を、第2回で「何を」を解説してきました。2つのAPI(Declarative / Imperative)の設計思想、Tool Contractの構成要素、human-in-the-loopの仕組みは理解できたはずです。
第3回の今回は、いよいよ「どうやるか」です。
Chrome Canaryのセットアップから、サイトの「ツール棚卸し」、Declarative APIとImperative APIによる実装、Model Context Tool Inspectorを使ったテスト・デバッグまで、一気通貫で進めます。本記事を読みながら手を動かせば、自分のサイトにWebMCPツールを実装し、AIエージェントから呼び出せる状態にできます。
なお、本記事のコード例と手順は2026年3月時点のChrome 146 Canaryの実装に基づいています。WebMCPはまだ標準化の途上にあり、API名・属性名・フラグ名が変更される可能性があります。実装時にはChrome Developersの公式ドキュメントで最新情報を確認してください。
Step 0:開発環境の準備
WebMCPを動かすには、対応ブラウザとデバッグツールの準備が必要です。
Chrome Canary(またはBeta)のインストール
WebMCPは現時点ではChrome 146以降でのみ利用可能です。選択肢は2つあります。
Chrome Canary — 最新のフラグを最初に利用できる。ただし不安定な場合がある。google.com/chrome/canary/ からダウンロード。
Chrome Beta — Canaryより安定性が高く、WebMCPフラグも利用可能。多くの開発者にとってはこちらが安全な選択肢。google.com/chrome/beta/ からダウンロード。
インストール後、バージョンを確認します。Chromeメニューから「ヘルプ」→「Google Chromeについて」を開き、バージョンが146以上であることを確認してください(詳細なビルド番号はアップデートにより変わるため、メジャーバージョンで判断します)。
フラグの有効化
- アドレスバーに
chrome://flagsと入力 - 検索欄に「WebMCP for testing」と入力
- 該当するフラグを「Enabled」に変更
- (一部のビルドでは「Experimental Web Platform Features」の有効化も必要です)
- 画面下部の「Relaunch」ボタンでChromeを再起動
有効化の確認
再起動後、任意のHTTPSサイト(localhostでも可)を開き、DevTools(F12)のコンソールで以下を入力します。
'modelContext' in navigator
true が返れば、WebMCPが正しく有効化されています。
Model Context Tool Inspectorのインストール
GoogleChromeLabs/webmcp-toolsリポジトリで公開されているModel Context Tool Inspectorは、WebMCP開発に不可欠なデバッグツールです。Chrome Web Storeからインストールできます。
この拡張機能は、DevToolsに専用パネルを追加し、以下の機能を提供します。
- ページ上に登録されているすべてのWebMCPツールの一覧表示
- 各ツールの入力スキーマの可視化
- テストパラメータを入力して手動でツールを実行
- Gemini APIキーを設定すれば、自然言語によるツール呼び出しテストも可能
AIエージェントから自サイトがどう見えているかを確認するための「鏡」と考えてください。
Step 1:サイトの「ツール棚卸し」— 何をAIに公開すべきか
コードを書く前に、まず自サイトのどの機能をWebMCPツールとして公開するかを棚卸しします。
棚卸しの判断フレームワーク
すべての機能をいきなり公開する必要はありません。Mcpfy.aiが提唱する3フェーズのロールアウト戦略が参考になります。
Phase 1:読み取り専用ツール(低リスク)
まずはデータを変更しないツールから始めます。失敗してもデータが壊れないため、安全に実験できます。
- 商品検索、フライト検索、店舗検索
- 在庫確認、価格照会、営業時間の取得
- カテゴリ一覧、フィルタリング
これらのツールにはreadOnlyHint: trueを設定します。
Phase 2:書き込みツール(中リスク)
Phase 1が安定したら、状態を変更するツールを追加します。
- お問い合わせフォームの送信
- カートへの商品追加
- 予約の仮登録
- ニュースレター登録
これらにはrequestUserInteraction()による確認フローを組み込みます。
Phase 3:トランザクションツール(高リスク)
最後に、課金や不可逆な操作を伴うツールを追加します。
- 購入の確定
- 予約の最終確定
- アカウント情報の変更
これらは必ずrequestUserInteraction()でユーザーの明示的な承認を取得します。
具体例:クライアントサイト(不動産会社)で棚卸し
| 機能 | Phase | API | 理由 | |
|---|---|---|---|---|
| 物件検索 | 1 | Declarative | 既存の検索フォームに属性追加のみ | |
| 物件詳細の取得 | 1 | Imperative | フォームなし、JS経由でデータ取得 | |
| お気に入り登録 | 2 | Imperative | ログイン状態に依存、状態変更あり | |
| 内覧予約フォーム | 2 | Declarative | 既存フォームあり、書き込み操作 | |
| 契約申し込み | 3 | Imperative | 高リスク、複数ステップ、確認必須 |
Step 2:Declarative APIで既存フォームをWebMCP対応にする
Phase 1の読み取り専用ツールから着手します。既存のHTMLフォームに属性を追加するだけの、最も低コストな実装です。
注: Declarative APIで使用する属性名(toolname、tooldescription、toolautosubmit、toolparamdescription)は、現時点ではW3Cドラフト仕様およびChrome Canaryの実験的実装に基づく名称です。正式標準化の過程で変更される可能性があります。詳しくは第2回のDeclarative APIセクションを参照してください。
物件検索フォームの実装
<form action="/search" method="GET" toolname="searchProperties" tooldescription="エリア、価格帯、間取りなどの条件で不動産物件を検索する" toolautosubmit="true">
<label for="area">エリア</label>
<select name="area" id="area" toolparamdescription="検索対象の地域(例:渋谷区、港区、世田谷区)">
<option value="">すべて</option>
<option value="shibuya">渋谷区</option>
<option value="minato">港区</option>
<option value="setagaya">世田谷区</option>
</select>
<label for="min_price">価格下限(万円)</label>
<input type="number" name="min_price" id="min_price" toolparamdescription="物件価格の下限(万円単位。例:3000)" />
<label for="max_price">価格上限(万円)</label>
<input type="number" name="max_price" id="max_price" toolparamdescription="物件価格の上限(万円単位。例:8000)" />
<label for="layout">間取り</label>
<select name="layout" id="layout" toolparamdescription="希望する間取り(例:1LDK、2LDK、3LDK)">
<option value="">指定なし</option>
<option value="1LDK">1LDK</option>
<option value="2LDK">2LDK</option>
<option value="3LDK">3LDK</option>
</select>
<button type="submit">検索する</button>
</form>
ポイントは3つです。
toolautosubmit="true"を設定。検索は読み取り専用の操作なので、エージェントがフォームを埋めたら自動で送信して構いません。ユーザーにわざわざ送信ボタンを押させる必要はありません。
tooldescriptionは具体的に書く。「物件を検索する」ではなく「エリア、価格帯、間取りなどの条件で不動産物件を検索する」と、どんなパラメータで何ができるかを明示します。第2回で解説したとおり、descriptionの品質がツールの発見可能性を左右します。
toolparamdescriptionで各フィールドを説明。「価格下限」だけでは単位がわかりません。「物件価格の下限(万円単位。例:3000)」のように、単位と入力例を含めます。
内覧予約フォームの実装(書き込み操作)
Phase 2の書き込み操作では、toolautosubmitを設定しません。
<form action="/booking" method="POST" toolname="bookPropertyViewing" tooldescription="不動産物件の内覧予約を行う。物件ID、希望日時、連絡先を指定する">
<label for="property_id">物件ID</label>
<input type="text" name="property_id" id="property_id" required toolparamdescription="内覧したい物件の一意な識別子(例:PROP-2026-001)" />
<label for="name">お名前</label>
<input type="text" name="name" id="name" required toolparamdescription="予約者のフルネーム" />
<label for="email">メールアドレス</label>
<input type="email" name="email" id="email" required toolparamdescription="予約確認メールの送信先アドレス" />
<label for="date">希望日</label>
<input type="date" name="date" id="date" required toolparamdescription="内覧希望日(YYYY-MM-DD形式)" />
<button type="submit">内覧を予約する</button>
</form>
toolautosubmitがないため、AIエージェントはフォームの各フィールドを埋めたところで止まります。画面には入力済みのフォームが表示され、ユーザーが内容を確認した上で「内覧を予約する」ボタンを自分でクリックします。予約という行為の最終判断を人間に委ねるhuman-in-the-loopの実装です。
Step 3:Imperative APIで複雑なワークフローをツール化する
フォームでは表現できない操作——たとえば物件詳細の取得や、ログイン状態に依存する機能——はImperative APIで実装します。
物件詳細の取得ツール(読み取り専用)
if ('modelContext' in navigator) {
navigator.modelContext.registerTool({
name: 'getPropertyDetails',
description: '物件IDを指定して、物件の詳細情報(価格、間取り、面積、最寄り駅、築年数など)を取得する',
inputSchema: {
type: 'object',
properties: {
property_id: {
type: 'string',
description: '物件の一意な識別子(例:PROP-2026-001)'
}
},
required: ['property_id']
},
annotations: {
readOnlyHint: true
},
async execute(input) {
const response = await fetch(`/api/properties/${input.property_id}`);
if (!response.ok) {
throw new Error(`物件 ${input.property_id} が見つかりませんでした`);
}
const property = await response.json();
return {
id: property.id,
name: property.name,
price: property.price,
layout: property.layout,
area: property.area_sqm,
station: property.nearest_station,
built_year: property.built_year,
description: property.description
};
}
});
}
読み取り専用の操作なのでreadOnlyHint: trueを設定。readOnlyHintはエージェントやブラウザがツールの安全性を判断するためのヒントです(確認フローの省略が仕様上保証されるわけではありません。詳しくは第2回のhuman-in-the-loopセクションを参照)。
お気に入り登録ツール(書き込み操作・ログイン依存)
ログイン状態に応じてツールを出し入れする例です。
if ('modelContext' in navigator) {
// ログイン状態のチェック
function registerAuthenticatedTools() {
const user = getCurrentUser(); // 自サイトの認証API
if (!user) return;
navigator.modelContext.registerTool({
name: 'addToFavorites',
description: 'ログイン中のユーザーのお気に入りリストに物件を追加する',
inputSchema: {
type: 'object',
properties: {
property_id: {
type: 'string',
description: '追加する物件のID'
}
},
required: ['property_id']
},
async execute({ property_id }, agent) {
// ユーザーに確認を求める
const confirmed = await agent.requestUserInteraction(async () => {
return confirm(`物件 ${property_id} をお気に入りに追加しますか?`);
});
if (!confirmed) {
return { success: false, reason: 'ユーザーがキャンセルしました' };
}
const response = await fetch('/api/favorites', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ property_id })
});
const result = await response.json();
return { success: true, totalFavorites: result.total };
}
});
}
// ログインイベントで登録、ログアウトイベントで解除
document.addEventListener('user:login', registerAuthenticatedTools);
document.addEventListener('user:logout', () => {
navigator.modelContext.unregisterTool('addToFavorites');
});
// ページロード時にすでにログイン済みならツールを登録
if (getCurrentUser()) {
registerAuthenticatedTools();
}
}
このパターンのポイントは3つです。
状態に応じたツールの出し入れ。ログインしていないユーザーの画面には「お気に入り登録」ツールが存在しません。エージェントはログイン中の場合のみこのツールを発見し、利用できます。
requestUserInteraction()による確認。お気に入り追加はデータを変更する操作なので、実行前にユーザーの確認を取得します。
unregisterTool()によるツール削除。ログアウト時にツールを明示的に削除します。削除しないと、認証が切れた状態でエージェントがツールを呼び出し、APIエラーが発生します。
Step 4:テストとデバッグ
実装したツールが正しく動作するかを、Model Context Tool Inspectorで確認します。
テストワークフロー
1. DevToolsを開く(F12またはCtrl+Shift+I)
2. Model Context Tool Inspectorパネルを選択。ページ上に登録されているすべてのツールが一覧表示されます。ツール名、description、inputSchemaが確認できます。
3. ツールが表示されない場合のチェックリスト
chrome://flagsでWebMCPフラグが有効化されているか- Chromeのバージョンが146以上か
- ページがHTTPS(またはlocalhost)で配信されているか
- Declarative APIの場合:
toolnameとtooldescriptionの両方が<form>に付与されているか - Imperative APIの場合:
'modelContext' in navigatorがtrueを返すか
4. テストパラメータを入力して手動実行。Inspectorでツールをクリックし、テストパラメータを入力して「Execute」を押します。
たとえば物件検索ツールなら:
area: "shibuya"
min_price: 3000
max_price: 8000
layout: "2LDK"
実行結果がJSON形式で返ってくれば成功です。これがAIエージェントが受け取るレスポンスそのものです。
5. 自然言語によるテスト。Model Context Tool Inspectorは、Gemini APIキーを設定することで、自然言語によるツール呼び出しテストにも対応しています。「渋谷区で3000万円以上8000万円以下の2LDKの物件を探して」と入力し、エージェントが正しいツールを正しいパラメータで呼び出すかを確認できます。
よくある問題と対処法
ツールは表示されるがExecuteでエラーになる。execute関数内のfetchリクエストが失敗している可能性があります。DevToolsのNetworkタブでAPIリクエストを確認してください。CORSエラーの場合は、APIサーバー側の設定を見直します。
Declarative APIのフォームがツールとして認識されない。toolnameだけでなくtooldescriptionも必須です。どちらか一方が欠けているとツールとして登録されません。
SPAでページ遷移後にツールが消える。WebMCPのツールはページのライフタイムに紐づいています。SPAでクライアントサイドルーティングを行っている場合、遷移先で改めてツールを登録する必要があります。React SPAの場合、useEffectフック内で登録処理を行い、クリーンアップ関数でunregisterTool()を呼ぶのが定石です。
Step 5:本番公開前のチェックリスト
実装とテストが完了したら、以下の項目を確認してから公開に進みます。
機能チェック
- すべてのツールがModel Context Tool Inspectorに表示される
- 各ツールのdescriptionが「何ができるか」を具体的に説明している
- inputSchemaのrequired(必須パラメータ)が適切に設定されている
- 読み取り専用ツールに
readOnlyHint: trueが設定されている - 書き込みツールに
requestUserInteraction()が組み込まれている - エラー時に意味のあるエラーメッセージが返される
セキュリティチェック
- ページがHTTPS(セキュアコンテキスト)で配信されている
- サーバーサイドでの入力バリデーションが実装されている(JSONスキーマの型チェックだけに頼らない)
- 管理者向け機能がWebMCPツールとして公開されていない
- 個人情報(PII)がツールのレスポンスに不用意に含まれていない
- CSP(Content Security Policy)がWebMCPの動作を阻害していないか確認
互換性チェック
- WebMCP非対応ブラウザでも通常のWebサイトとして問題なく動作する
'modelContext' in navigatorのチェックにより、非対応環境でエラーが発生しない- Declarative APIのフォームは、WebMCPなしでも通常のHTMLフォームとして送信できる
監視の準備
- ツール呼び出しのログ記録を実装している(どのツールが、どのパラメータで、何回呼ばれたか)
- ツールの成功率/失敗率を追跡する仕組みがある
現時点での注意事項
ここまでの手順で、自サイトにWebMCPツールを実装しAIエージェントから呼び出せる状態にできます。ただし、2026年3月時点での制約をあらためて確認しておきましょう。
本番サイトへの導入は慎重に。WebMCPはDevTrial(開発者向け試験)段階です。APIの仕様変更が予告なく行われる可能性があります。ステージング環境での実験と、社内向けのプロトタイプにとどめておくのが現時点の推奨です。
ツールディスカバリーは未解決。現在、AIエージェントがサイトのWebMCPツールを発見するには、まずそのページに遷移する必要があります。ページを訪問する前にツールの存在を知る仕組み(.well-known/webmcpのようなマニフェスト)は、将来のバージョンで検討されています。
フレームワーク連携が急速に整備中。MCP-B(@mcp-b/globalポリフィル)によるChrome非対応ブラウザでの実験、webmcp-rails gemによるRuby on Rails統合、@mcp-b/react-webmcpパッケージによるReact統合など、エコシステムが急速に立ち上がっています。自社のフレームワークに合わせた選択肢を確認しておくとよいでしょう。
まとめ — 「今日できること」を今日やる
WebMCPの実装は、特にDeclarative APIについては驚くほどシンプルです。既存のHTMLフォームにtoolnameとtooldescriptionの2つの属性を追加する——これだけでそのフォームはAIエージェントから構造化されたツールとして利用可能になります。
段階的アプローチが鍵です。まずPhase 1として読み取り専用ツール(検索フォーム、詳細取得)から始め、Phase 2で書き込みツール(問い合わせ、予約)、Phase 3でトランザクションツール(購入確定)へと拡張していく。
正式リリースを待つ必要はありません。Chrome Canaryで実験し、Model Context Tool Inspectorでデバッグし、自社サイトのTool Contract設計を磨いておく。この準備が、Chrome安定版での正式ロールアウト時に先行者優位をもたらします。
次回の第4回では、WebMCPがSEO/GEOに与えるインパクトを論じます。構造化データ(Schema.org)との併用戦略、llms.txtとの役割分担、そしてトランザクショナルインテント検索における「アクション可能なサイト」のアドバンテージを解説します。
参考情報
Google Chrome Developers「WebMCP is available for early preview」(2026年2月10日)
GoogleChromeLabs「webmcp-tools(Model Context Tool Inspector / Demos / Evals)」
beaufortfrancois「Model Context Tool Inspector(Chrome拡張のソースコード)」
W3C Web Machine Learning Community Group「WebMCP Specification」(2026年2月12日)
Ivan Turkovic「How to Make Your Website Agent-Ready With WebMCP」(2026年2月23日)
Salam Experts「Enable WebMCP in Chrome 146: Step-by-Step Guide」(2026年3月)
Codely「What is WebMCP and how to use it」(2026年2月)
GitHub「MCP-B — WebMCPブラウザ実装・ポリフィル・SDK」
GitHub「awesome-webmcp」
DEV Community「Chrome's WebMCP Early Preview」(2026年2月11日)
Google「WebMCP Travel Demo(公式デモ)」
この記事は「WebMCP:Webサイトがアクションを話す時代」シリーズの第3回です。
AI技術のビジネス活用やWebサイトのAIエージェント対応について、具体的なご相談はunTypeまでお気軽にお問い合わせください。
この記事をシェアする