一项由谷歌和微软支持的新提案可能正在塑造我们使用网络的未来。 我个人很喜欢它。 它被称为 WebMCP,但别把它和普通的 MCP 服务器搞混了。
WebMCP 实际上是一个浏览器 API。 它允许前端开发者将网站的功能作为工具暴露给 AI 代理。 这实质上让每个网站都变成一个迷你的 MCP 服务器。
虽然你可能已经看到一些网站开始推出自己的 MCP 服务器,但 WebMCP 有点不同。 它的目标是帮助代理为你使用网站,而不仅仅是访问你的 API 并在聊天中显示结果。 它将完全基于前端。
如果这个区别听起来有点令人困惑,让我们直接看一个演示,并讨论我为什么喜欢它。
WebMCP 演示:简单却强大
首先我得承认,这个演示看起来并不会太令人兴奋。 但这正是 WebMCP 的重点所在。 它将一件已经可能实现的事情,变得更好。 所以请耐心看下去。
我这里有正在测试此提案的 Chrome Canary 版本,以及一个设置了 WebMCP 工具的网站。 你可以看到右边我有一个扩展程序,能够与这些 WebMCP 工具交互。 但想象一下,在未来,这可能就是你浏览器内置的普通 AI,无论是 Gemini、Chad Atlas,还是 Arc 现在变成的任何东西。
当我在这个网站上发送一个用户提示,比如“我想预订一张从伦敦到纽约的双人往返机票,日期是特定的”,然后点击发送。 它会直接带我到搜索结果页面。 所以,它为我使用了这个网站。
哇,很神奇,对吧? 是的,正如我所说的,这个演示看起来非常基础。 但 WebMCP 的关键在于它如何使用那个网站。
WebMCP 的工作原理
目前 AI 使用网站的方法倾向于使用像 Playwright、HTML 解析,甚至是截取网站截图并尝试像人类一样使用它。 但所有这些方法效率都很低,尤其是在令牌消耗方面,而且仍然容易出错。 这正是 WebMCP 要解决的问题。
WebMCP 让网站开发者暴露特定的 MCP 工具,这些工具与客户端的 JavaScript 交互。 所以,当 AI 选择使用这些 WebMCP 工具之一时,所发生的一切仅仅是在你的网站上运行一个你(开发者)已经设置好的 JavaScript 函数。
graph TD
A[用户提示: "预订航班"] --> B{AI 代理};
B --> C{发现 WebMCP 工具: `searchFlights`};
C --> D[使用输入参数调用工具];
D --> E[在网站上执行 `execute` 函数];
E --> F[客户端 JavaScript 更新 React 状态];
F --> G[导航到搜索结果页面];
在这个演示航班页面的例子中,我有一个可用的 WebMCP 工具,名为 searchFlights。
你可以看到它接受一些输入参数,如 origin、destination 和 tripType,这些参数与我们这边的表单一一对应。
关键在于,AI 现在知道它可以使用这个 MCP 工具。 所以当我们发送这样的提示时,它不会通过 Playwright 或 HTML 解析来填写表单。 事实上,它根本不需要知道网站长什么样,也不需要知道 HTML 结构。 它只知道它有那个 WebMCP 工具,并用那些输入参数调用它。
然后,开发者已经设定了当接收到这些输入参数并运行一个 JavaScript 函数时会发生什么。 在这种情况下,它只是更新了 React 的状态,从而导致导航到搜索航班页面。
命令式 API:代码中的优雅
让我们看看这个的前端代码,它非常简单,希望能让一切变得更清晰。
首先,我们需要为给定页面注册可用的 WebMCP 工具。
我们可以通过使用 window.navigator.mmodelcontext 来实现。
这是如果该提案通过后需要内置到浏览器中的 API。
它目前在 Chrome Canary 中,所以我们可以测试一下。
// 注册页面可用的 WebMCP 工具
if (window.navigator.mmodelcontext) {
const modelContext = window.navigator.mmodelcontext;
modelContext.registerTool(searchFlightsTool);
}
一旦我们有了 modelContext API,我们就可以使用 registerTool 函数来注册我们的工具。
在这种情况下,我注册了我们之前看到的 searchFlights 工具。
一个实际的工具定义是一个非常简单的对象。
我们有一个名称(name)和一个描述(description),这样 AI 就知道何时使用这个工具。
如果我们需要接收任何参数,我们还有一个输入模式(inputSchema)。
// 工具定义示例
const searchFlightsTool = {
name: "search_flights",
description: "搜索航班",
inputSchema: {
type: "object",
properties: {
origin: { type: "string", description: "出发城市" },
destination: { type: "string", description: "到达城市" },
// ... 其他参数
},
},
execute: handleSearchFlights, // 将要执行的函数
};
工具定义中最重要的部分是 execute 函数。
这是当此 MCP 工具被使用时将在你的网站上运行的客户端 JavaScript。
它可以是你想要的任何东西。
在我的例子中,我正在使用 searchFlights 函数。
我们不必太担心这个实现细节。
但基本上我所做的就是接收 AI 为这些输入参数填写的值,并用这些参数分派一个名为 searchFlights 的事件。
// 在 React 代码中监听事件
useEffect(() => {
const handleSearch = (event) => {
const { origin, destination } = event.detail;
// 使用参数更新搜索参数并导航
setSearchParams({ from: origin, to: destination });
};
window.addEventListener('searchFlights', handleSearch);
return () => {
window.removeEventListener('searchFlights', handleSearch);
};
}, [setSearchParams]);
在我的 React 代码中,我所做的只是为那个 searchFlights 事件添加一个事件监听器。
当事件发生时,我运行 handleSearchFlights 函数。
在这里,我们基本上可以做任何在 React 中能做的事情。
在我的例子中,我接收参数并将它们设置为搜索参数,从而引发导航。
真的就这么简单。 这就是我非常喜欢这种方法的原因,它不仅令牌效率极高,而且还允许我作为开发者来定义网站的交互,AI 可以遵循我的护栏。
这是一个非常巧妙的解决方案,可以同时为人类和 AI 助手构建网站。 而不是当前的方法:为人类构建一个网站,然后为 AI 构建一个 MCP 服务器。 如果 AI 需要使用网站,好吧,你最好希望它能自己搞定。
从页面传递信息
值得注意的是,这些 WebMCP 工具不仅可用于在你的页面上触发事件,如导航或填写表单。 当你需要传递页面上的信息时,它们也非常有用。
假设我,作为人类,现在进来并开始调整一些过滤器,比如我想要价格低于 $500 并且出发时间在中午之前。 这个页面上仍然有很多航班。 所以,我希望 AI 帮助我选择最好的一个。 我可以问:“你推荐这个页面上的哪个航班?”
[!TIP] 当前的方法会使用 Playwright 或 HTML 解析来获取整个页面,并尝试将信息转化为结构化数据。但使用 WebMCP,我们不再需要这样做。
相反,我作为开发者,只需设置一个名为 listFlights 的 WebMCP 工具。
这个工具可以访问当前的 React 状态。
所以,它可以访问这里显示给用户的所有信息,但是是以漂亮的 JSON 格式。
这样,如果我向 AI 提出这个提示,你可以看到它调用了那个工具。 它获取了当前页面上显示的所有航班,并在这里为我推荐了 56 号航班。 我可以在页面上找到那个航班。
这个过程使用的令牌少得多,而且会准确得多。
声明式 API:无需 JavaScript
最后我想展示的是如何在没有 JavaScript 的情况下利用 WebMCP。 到目前为止,我们一直在使用命令式 API,即我作为开发者编写 JavaScript 来处理工具调用并注册特定工具。 还有第二种方法,称为声明式 API。
这种方法要简单得多,因为它适用于填写 HTML 表单的简单用例。 你可以看到我有一个非常简单的预订表单。 我可以简单地要求我的 AI 为我预订一张桌子,并提供一些填写表单所需的信息,它就会为我填写那个表单。
这是因为它有权访问一个名为 bookTable 的 WebMCP 工具。
但重要的是,我没有编写任何 JavaScript来访问这个 WebMCP 工具。
<form
id="booking-form"
tool-name="book_table"
tool-description="为餐厅预订一张桌子">
<label for="name">姓名:</label>
<input
type="text"
id="name"
name="name"
tool-param-description="预订所用的全名">
<label for="phone">电话:</label>
<input
type="tel"
id="phone"
name="phone"
tool-param-description="联系电话号码">
<!-- ... 其他表单输入 ... -->
<button type="submit">预订</button>
</form>
WebMCP 的声明式 API 的工作方式是,你只需在你的 HTML 表单上添加 tool-name 和 tool-description 属性。
然后浏览器会尝试将该表单转换为一个 WebMCP 工具,试图理解每个输入应该对应于 MCP 工具的哪个参数。
在一些输入中,我们还使用了 tool-param-description 属性,给 AI 更多关于如何填写该信息的上下文。
但对于其余部分,浏览器会获取输入、输入类型、输入名称,并用它们来创建 MCP 工具。
我们可以在检查器中看到,它正确地识别出输入参数是 name、phone、date、time、guest、seating 和 request。
所有这些都是通过简单的 HTML 表单逻辑完成的,而我没有编写一行 JavaScript。
结论与展望
这差不多就是目前 WebMCP 提案的全部内容了。 正如我所说,我对此非常看好。 我喜欢它弥合了 Web 应用和 AI 代理之间差距的方式,并消除了代理在尝试使用网站时的任何猜测。 它确保了任何交互都由网站的开发者明确定义。
此外,我还没有完全被 AI 取代。 我喜欢有一个工具能帮助 AI 代理与我协同工作,而不是取代我。 我不喜欢在 ChatGPT 的界面中预订我的航班或餐厅,我更喜欢自己去实际的网站。 如果我愿意,我可以让 AI 在那个页面上帮助我。
这是一个更好的系统,可以将人类保留在循环中,并允许网站开发者定义体验的走向。
[!WARNING] 安全问题 值得记住的是,这目前只是一个提案,所以它可能需要一些时间才会出现在浏览器中。 还有一些他们需要处理的限制,比如经典的安全问题。某些网站上可能存在恶意的工具和描述。 所以,它被授予多少用户信息访问权限,以及浏览器 AI 对整个浏览器有多大的控制权,都是需要解决的问题。如果其中一个恶意工具失控,它能造成多大的损害?
希望他们能找到答案,因为我对这个提案非常乐观。