ライチョウのイラスト

Web アプリケーションをツール化する WebMCP

WebMCP は Web 開発者が Web アプリケーションの機能をツールとして公開できるようにする JavaScript インターフェイスです。これにより AI エージェントが Web アプリケーションの機能を直接呼び出して操作できるようになります。

WebMCP は Web 開発者が Web アプリケーションの機能をツールとして公開できるようにする JavaScript インターフェイスです。これは AI エージェントや支援技術から呼び出せる自然言語による説明と構造化スキーマを備えた JavaScript 関数です。WebMCP を使用する Web アプリケーションは MCP サーバーとみなすことができます。これにより従来の AI エージェントがウェブページのスクリーンショットを解析して情報を取得するのではなく、Web アプリケーションが提供するツールを直接呼び出して操作できるようになるため、より正確で効率的なインタラクションが可能になります。

WebMCP を実装する

WebMCP を実装するための JavaScript API を利用するためには Chrome 146 以降が必要です。Chrome Canary のような最新の Chrome ビルドを使用してください。さらに chrome://flags#webmcp-for-testing フラグを有効にする必要があります。

MCP ツールをテストするためには Chrome 拡張機能として提供されている Model Context Tool Inspector をインストールします。この拡張機能は Web ページに登録された MCP ツールを一覧表示し、ツールの入力スキーマに基づいて引数を指定して手動でツールを呼び出すことができます。

WebMCP では開発者が WebMCP API のメソッドを使用して MCP ツールをブラウザに登録します。AI エージェントがツールを呼び出せるようにするために、自然言語の説明と JSON スキーマを提供します。Web アプリケーションに接続された AI エージェントがツールの呼び出しを要求すると、ツールに登録した JavaScript コールバック関数が呼び出されエージェントに結果が返されます。シンプルなアプリケーションではページ内のスクリプトで処理を完結できますが、より複雑なアプリケーションでは計算負荷の高い処理を Web Worker にオフロードして非同期で結果を返すことも可能です。

MCP ツールをブラウザに登録する方法は命令的な方法と宣言的な方法の 2 種類があります。

命令的な方法

命令的な方法では window.navigator.modelContext オブジェクトの provideContext メソッドを使用します。

window.navigator.modelContext.provideContext({
  tools: [
    {
      name: "add-todo",
      description: "Add a new todo item to the list",
      inputSchema: {
        type: "object",
        properties: {
          text: { type: "string", description: "The text of the todo item" },
        },
        required: ["text"],
      },
      execute: async ({ text }) => {
        console.log(`Adding todo: ${text}`);
        addTask(text);
        return { content: [{ type: "text", text: `Added todo: ${text}` }] };
      },
    },
  ],
});

上記の例では add-todo という名前の MCP ツールを登録しています。このツールは text プロパティを持つオブジェクトを引数として受け取り、execute コールバック関数内で新しいタスクを追加する処理を実行します。ツール名は一意である必要があります。Model Context Tool Inspector を使用して登録されたツールを確認できます。

Gemini API キーを登録し、「映画館に行く予定を追加」といったプロンプトを入力すると、AI エージェントが add-todo ツールを呼び出してタスクを追加する様子を確認できます。AI エージェントを介さずに直接ツールを呼び出すことも可能です。

provideContext メソッドは複数回呼び出すことができ、新しく呼び出すたびに既存のツールはクリアされます。この挙動は UI が頻繁に更新されるシングルページアプリケーションに適しています。既存のツールを保持しつつ新しいツールを追加・削除したい場合には registerToolunregisterTool メソッドを使用します。

// ツールの登録
window.navigator.modelContext.registerTool({
  name: "add-todo",
  description: "Add a new todo item to the list",
  inputSchema: {
    type: "object",
    properties: {
      text: { type: "string", description: "The text of the todo item" },
    },
    required: ["text"],
  },
  execute: async ({ text }) => {
    console.log(`Adding todo: ${text}`);
    addTask(text);
    return { content: [{ type: "text", text: `Added todo: ${text}` }] };
  },
});
 
// ツールの登録解除
window.navigator.modelContext.unregisterTool("add-todo");

宣言的な方法

宣言的な方法は HTML 属性を追加することでフォームを自動で WebMCP ツールとして登録する方法です。<form> 要素に toolnametooldescription 属性を追加します。フォーム内の各入力要素はツールの引数として自動的にマッピングされ、入力要素の name 属性が引数名として使用されます。required 属性が指定されている入力要素は必須引数としてマークされるように、フォームのバリデーション属性も自動的にスキーマに反映されます。

またオプショナルな属性として、フォームの各入力要素に toolparamtitletoolparamdescription 属性を指定して引数のタイトルと説明を追加できます。toolparamtitle 属性が設定されていない場合は name 属性の値がタイトルとして使用されます。toolparamdescription 属性が設定されていない場合は <label> 要素の内容もしくは aria-description 属性の値が説明として使用されます。

<form
  toolname="add-todo-item"
  tooldescription="Add a new todo item to the list"
>
  <input
    name="text"
    type="text"
    toolparamtitle="Todo Text"
    toolparamdescription="The text of the todo item"
    required
  />
  <button type="submit">Add Todo</button>
</form>

このフォームは以下のように WebMCP ツールとして登録されます。

[
  {
    "name": "add-todo-item",
    "description": "Add a new todo item to the list",
    "inputSchema": {
      "type": "object",
      "properties": {
        "text": {
          "type": "string",
          "title": "Todo Text",
          "description": "The text of the todo item"
        }
      },
      "required": ["text"]
    }
  }
]

AI エージェントがツールを呼び出すと、ブラウザは関連するフォームにフォーカスし、そのフィールドに入力内容を反映します。デフォルトではフォームは送信されず、ユーザーが手動で送信する必要があります。toolautosubmit 属性が設定されている場合、フォームは自動的に送信されます。

toolautosubmit 属性を使用しツールが呼び出された時にフォームが自動でサブミットされている場合、SubmitEventagentInvoked プロパティが true に設定されます。これにより開発者はフォームが AI エージェントによって送信されたかどうかを判別できます。さらに SubmitEvent には respondWith メソッドが追加されており、AI エージェントにフォームの結果を返すために使用できます。

document.querySelector("form").addEventListener("submit", (e) => {
  e.preventDefault();
  const formData = new FormData(e.target);
  const text = formData.get("text").trim();
 
  addTask(text);
  taskInput.value = "";
 
  if (e.agentInvoked) {
    e.respondWith(Promise.resolve(`Added todo: ${text}`));
  }
  return;
});

ツール関連のイベント

AI エージェントがツールを呼び出したときには toolactivated イベントが、ツールの実行がキャンセルされた(ユーザーがツールの使用を拒否した or フォームの reset ボタンが押された)ときには toolcancel イベントが発生します。

window.addEventListener("toolactivated", ({ toolName }) => {
  console.log(`the tool "${toolName}" execution was activated.`);
});
 
window.addEventListener("toolcancel", ({ toolName }) => {
  console.log(`the tool "${toolName}" execution was cancelled.`);
});

ツールが呼び出された場合の CSS 疑似クラス

AI エージェントがツールを呼び出したとき、以下の CSS 疑似クラスを使用してビジュアルフィードバックを提供できます。

  • :tool-form-active: ツールが呼び出されたときに、対応する toolname 属性を持つフォーム要素に適用されます。
  • :tool-submit-active: ツールが呼び出されたときにフォームの送信ボタンに適用されます。
form:tool-form-active {
  border: 2px solid red;
  background-color: pink;
}
 
button:tool-submit-active {
  background-color: green;
}

参考

記事の理解度チェック

以下の問題に答えて、記事の理解を深めましょう。

WebMCP で MCP ツールをブラウザに登録する命令的な方法として正しいものはどれか?

  • window.navigator.modelContext.createTool() メソッドを使用する

    もう一度考えてみましょう

  • window.navigator.modelContext.provideContext() メソッドを使用する

    正解!

    命令的な方法では window.navigator.modelContext オブジェクトの provideContext メソッドを使用して MCP ツールを登録します。

  • document.registerMCPTool() メソッドを使用する

    もう一度考えてみましょう

  • window.navigator.addTool() メソッドを使用する

    もう一度考えてみましょう

フォームの要素に toolparamdescription 属性が設定されていない場合、引数の説明として使用されるものはどれか?

  • <label> 要素の内容もしくは aria-description 属性の値

    正解!

    toolparamdescription 属性が設定されていない場合は <label> 要素の内容もしくは aria-description 属性の値が説明として使用されます。

  • name 属性の値

    もう一度考えてみましょう

    name 属性の値は toolparamtitle が設定されていない場合のタイトルとして使用されます。説明ではありません。

  • placeholder 属性の値

    もう一度考えてみましょう

  • title 属性の値

    もう一度考えてみましょう

toolautosubmit 属性を使用してフォームが AI エージェントによって自動送信された場合、SubmitEvent のどのプロパティが true に設定されるか?

  • agentInvoked

    正解!

    toolautosubmit 属性を使用しツールが呼び出された時にフォームが自動でサブミットされている場合、SubmitEvent の agentInvoked プロパティが true に設定されます。

  • autoSubmitted

    もう一度考えてみましょう

  • isTrusted

    もう一度考えてみましょう

  • toolActivated

    もう一度考えてみましょう