Skip to main content
Version: 25.3.0

WebMCP

caution

WebMCP 是一个实验性的 API,可能会发生变化。目前它仅在 Chrome 150 及以上版本中支持,并且需要启用特定的标志。

🌐 WebMCP is an experimental API and is subject to change. It is currently only supported in Chrome 150+ and requires specific flag to be enabled.

WebMCP 是一个实验性的 API,允许网页注册工具,这些工具可以被浏览器或外部代理(如大型语言模型)发现和调用。Puppeteer 提供了一个实验性 API 来与支持 WebMCP 的页面进行交互。

先决条件

🌐 Prerequisites

要在 Puppeteer 中使用 WebMCP,你需要:

🌐 To use WebMCP with Puppeteer, you need:

  1. Chrome 150+:浏览器必须支持 WebMCP CDP 域。
  2. 启用标志:你必须使用以下标志启动浏览器:
    • --enable-features=WebMCP

启用 WebMCP

🌐 Enabling WebMCP

在 Puppeteer 中,WebMCP 支持可通过 page.webmcp 属性获取。如果浏览器支持它,当你导航到页面时,它会自动初始化。

🌐 In Puppeteer, WebMCP support is available through the page.webmcp property. It is automatically initialized when you navigate to a page if the browser supports it.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
args: ['--enable-features=WebMCP'],
});
const page = await browser.newPage();

// page.webmcp is now available
console.log(page.webmcp);

发现工具

🌐 Discovering tools

你可以使用 page.webmcp.tools() 获取页面上注册的所有工具的列表。你还可以监听 toolsaddedtoolsremoved 事件,以响应注册工具的变化。

🌐 You can get a list of all tools registered on the page using page.webmcp.tools(). You can also listen for toolsadded and toolsremoved events to react to changes in the registered tools.

// Get currently registered tools
const tools = page.webmcp.tools();
for (const tool of tools) {
console.log(`Tool found: ${tool.name} - ${tool.description}`);
}

// Listen for new tools
page.webmcp.on('toolsadded', event => {
for (const tool of event.tools) {
console.log(`New tool added: ${tool.name}`);
}
});

// Listen for removed tools
page.webmcp.on('toolsremoved', event => {
for (const tool of event.tools) {
console.log(`Tool removed: ${tool.name}`);
}
});

执行工具

🌐 Executing tools

你可以使用 WebMCPTool 对象上的 execute 方法执行已发现的工具。此方法返回一个在工具结果解析时完成的 promise。

🌐 You can execute a discovered tool using the execute method on the WebMCPTool object. This method returns a promise that resolves with the tool's result.

const tools = page.webmcp.tools();
const tool = tools.find(t => t.name === 'calculate_sum');

if (tool) {
const result = await tool.execute({a: 5, b: 10});
if (result.status === 'Completed') {
console.log('Result:', result.output);
} else {
console.error('Error:', result.errorText);
}
}

处理工具调用

🌐 Handling tool invocations

你可以观察到工具何时被页面或浏览器调用以及它何时响应。

🌐 You can observe when a tool is invoked by the page or the browser and when it responds.

page.webmcp.on('toolinvoked', call => {
console.log(`Tool ${call.tool.name} was invoked with input:`, call.input);
});

page.webmcp.on('toolresponded', response => {
console.log(
`Tool ${response.call?.tool.name} responded with status: ${response.status}`,
);
if (response.status === 'Completed') {
console.log('Output:', response.output);
} else {
console.log('Error:', response.errorText);
}
});

在页面中注册工具

🌐 Registering tools in the page

工具可以通过 JavaScript 以命令式方式注册到页面中,也可以通过 HTML 表单以声明式方式注册。

🌐 Tools can be registered in the page either imperatively via JavaScript or declaratively via HTML forms.

强制注册

🌐 Imperative registration

await page.evaluate(() => {
document.modelContext.registerTool({
name: 'calculate_sum',
description: 'Calculates the sum of two numbers',
inputSchema: {
type: 'object',
properties: {
a: {type: 'number'},
b: {type: 'number'},
},
required: ['a', 'b'],
},
execute: ({a, b}) => {
return a + b;
},
});
});

声明式注册

🌐 Declarative registration

WebMCP 还支持发现被定义为具有特定属性的 HTML 表单的工具。

🌐 WebMCP also supports discovering tools defined as HTML forms with specific attributes.

await page.setContent(`
<form
toolname="search_products"
tooldescription="在目录中搜索产品"
>
<input name="query" type="text" />
<button type="submit">Search</button>
</form>
`);

当通过表单注册工具时,你可以使用 tool.formElement 访问相应的 ElementHandle

🌐 When a tool is registered via a form, you can access the corresponding ElementHandle using tool.formElement.

const tools = page.webmcp.tools();
const searchTool = tools.find(t => t.name === 'search_products');
const formHandle = await searchTool.formElement;