谷歌最近发布了一个名为 Web MCP 的概念,它非常有趣。
我想快速解释它是什么,为什么它很酷,以及你今天如何开始使用它。
核心问题:代理程序的确定性行为
Web MCP 的核心是解决一个关键问题:
让 AI 代理程序在每个网站上都能有确定性的行为。
想象一下,你是一个电商网站的所有者。
你的目标是让任何 AI 代理程序都能使用你的网站。
在未来,数以百万计的代理程序将在网络上为人类执行实际操作。
要在没有 Web MCP 的情况下实现这一点,你今天有两种选择。
现有方案的局限
第一种选择是,你构建自己的 MCP 服务器。
然后希望代理程序会加载你的 MCP。
但这基本不可能发生。
因为你的网站不会是每个代理程序每天都会使用的网站。
让代理程序一直加载你的 MCP 也没有意义。
所以这种方法对普通网站通常行不通。
第二种选择是,你依赖代理程序拥有非常好的浏览器使用能力。
越来越多的代理程序已经具备了这些能力。
它们可以打开浏览器并执行某些任务。
但这些浏览器使用能力的问题在于,它们通常是非确定性的。
这些代理程序提取的是庞大的原始 HTML。
然后进行一些清理,再输入给大语言模型。
有时它们会截取屏幕截图,并标注出界面元素。
试图通过这个翻译层来解析 HTML 或截图,以理解代理程序需要执行的核心操作。
我们知道,大多数网站的构建并不完美。
它们是为人类消费而设计的,而不是为代理程序。
因此,大量的噪音会被发送到大语言模型,导致非确定性行为。
这意味着代理程序在使用你的网站完成任务时很可能会失败。
在一个 AI 代理程序将成为许多网络内容或操作的主要消费者的时代。
如果你的网站更容易让代理程序完成任务,那么代理程序就会更多地使用它。
也会有更多的人愿意采用它。
这就是为什么 Web MCP 这个概念如此有趣。
Web MCP 的工作原理
它的工作方式是,你仍然构建 MCP,但你在你的代码或 HTML 中声明它。
这样,操作浏览器的代理程序就不需要自己做翻译层了。
它们只需查看你为每个页面注册的操作和 MCP 工具。
比如,在你的电商网站例子中:
- 主页:你可以注册像
搜索产品、获取分类和筛选这样的操作。 - 产品详情页:可以有像
添加到购物车或获取相似产品这样的操作。
代理程序可以像调用普通的 MCP 工具一样执行这些操作。
但这些 MCP 工具是在它们登陆某个特定页面时才动态加载的。
所以你仍然能享受到代理程序可以采取的高度确定性操作的好处。
Web MCP 的两种实现方式
Web MCP 提供了两种设置方式。
1. 声明式方法 (Declarative)
这意味着你可以添加特定的 HTML 属性。
让我们看一个 Chrome 团队的演示示例。
这是一个简单的 HTML 预订页面。
<form>
<input name="date" type="date">
<input name="time" type="time">
<input name="guests" type="number">
<button type="submit">预订</button>
</form>
在这个 HTML 中,对于像 form 这样的元素,你可以开始添加 tool-name 和 tool-description 属性。
对于每个代理程序能够自定义的 input,你还可以添加 tool-param-description。
- <form>
+ <form tool-name="bookTable" tool-description="预订一张桌子">
- <input name="date" type="date">
+ <input name="date" type="date" tool-param-description="预订日期">
- <input name="time" type="time">
+ <input name="time" type="time" tool-param-description="预订时间">
- <input name="guests" type="number">
+ <input name="guests" type="number" tool-param-description="客人数量">
<button type="submit">预订</button>
</form>
设置好这些属性后,当代理程序用最新版的 Chrome 访问页面时:
它们将看到一个名为 bookTable 的工具。
这个工具的描述和输入模式是根据你添加的属性自动转换的。
任何支持 Web MCP 格式的代理程序都会自动装备上这个可以调用的 MCP 工具。
当代理程序调用这个工具后,它会自动将内容填充到表单中。
调用后,你还可以在网站上看到一些特殊的 UI 元素弹出,比如“请检查并确认”的浮动提示。
这也是 Web MCP 升级的一部分。
它支持一些特殊的 CSS 类,当代理程序填写某些表单元素或即将提交表单时触发。
这就是让你的静态网站为代理程序做好准备的简单方法。
2. 命令式方法 (Imperative)
如果你正在构建一个实际的应用程序,你更可能采用这种命令式模式。
它允许你通过 JavaScript 注册工具,或在某个 React 组件渲染时绑定特定的 MCP 工具。
新版 Chrome 浏览器支持 navigator.registerTool 来加载 MCP。
这是另一个来自 Chrome 的演示。
如果你有一个预订机票的 React 应用。
当用户在搜索页面时,可能会暴露一个用于 searchFlights 的 MCP 工具。
如果代理程序发送请求,它就能填写表单并执行操作,将用户重定向到搜索结果页面。
真正酷的是,当你导航到不同页面时,暴露的 MCP 工具会随之改变。
- 搜索结果页:会有像
setFilter、searchFlights、resetFilter和listFlights这样的相关工具。
这是我使用 Web MCP 后看到的最酷的部分。
每个网页都有一份特殊的、上下文加载的暴露 MCP 工具列表。
你使用新的 navigator.register 和 unregister 函数。
剩下的就和你构建普通 MCP 工具一样了。
你需要为名称、描述、输入模式、输出模式和函数定义工具模式。
然后,你可以为每个组件开始注册和注销工具。
每当相关的 UI 组件出现时,MCP 工具也会相应地加载。
从 MCP 到上下文 MCP 的演变
Web MCP 引入的上下文 MCP 方法,我认为非常棒。
回顾一下工具的演变过程:
graph TD;
A[传统 MCP] --> B{问题:上下文过载};
B --> C[技能(Skills)概念];
C --> D{问题:无严格模式保证};
A --> E[Web MCP (上下文 MCP)];
C --> E;
E --> F[未来:理想的上下文工具];
- 传统 MCP:很棒,它允许代理程序扩展其能力,并保证传递正确的模式。但问题是,无论是否相关,它都会占用大量的上下文,不适合长尾场景。
- 技能 (Skills):最近很多人转向这个概念。好处是它不占用太多令牌,只在上下文中加载标题和描述。但问题是它没有严格的模式保证。
- Web MCP (上下文 MCP):它创造了一个非常有趣的模式。根据代理程序所在的上下文(即网页),加载不同的 MCP 工具。
我坚信这是未来。
理想情况下,我们应该始终追求这种上下文 MCP 设置。
根据代理程序正在执行的任务,加载相关的 MCP 工具。
如何开始使用 Web MCP
[!TIP] 入门指南
- 安装 Chrome Beta 版本。
- 转到
chrome://flags,搜索Web MCP并启用该标志。- 安装名为 Model Context Tool Inspector 的 Chrome 扩展程序。
示例 1:改造静态联系表单(声明式)
假设我有一个静态的“联系我们”页面。
目前,Web MCP 工具中没有为该页面注册任何工具。
这个页面就是一个单一的 HTML 文件。
首先,我们向 form 元素添加 tool-name 和 tool-description 属性。
<form
id="contact-form"
tool-name="submitContactForm"
tool-description="提交联系表单"
>
<!-- ... form inputs ... -->
</form>
然后,为每个代理程序需要填写的输入添加 tool-param-description。
<input
type="text"
id="name"
name="name"
required
tool-param-description="你的名字"
/>
<input
type="email"
id="email"
name="email"
required
tool-param-description="你的电子邮件地址"
/>
仅仅这样做,如果我回到这个页面并刷新,你会看到这个 Web MCP 工具已经被代理程序识别。
为了形成一个完整的闭环,我们还需要确保将正确的工具响应返回给代理程序。
我们可以为表单提交操作自定义事件监听器。
const form = document.getElementById('contact-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());
// 检查事件是否由代理程序触发
if (event.detail && event.detail.agent) {
try {
// 假设这里有一些验证逻辑
if (!data.name || !data.email) {
throw new Error("姓名和邮箱是必填项。");
}
// 向代理程序返回成功响应
event.detail.resolve({ success: true, message: "表单已成功提交!" });
} catch (error) {
// 向代理程序返回错误响应
event.detail.resolve({ success: false, message: error.message });
}
}
});
现在,当代理程序填写表单后,它会收到一个明确的成功或失败的响应。
示例 2:为 React 应用实现 Web MCP(命令式)
假设我有一个看板应用,我们想为它添加 Web MCP 支持。
project/
├── components/
│ └── KanbanBoard.jsx
├── lib/
│ └── web-mcp.ts
└── pages/
└── index.js
我们将使用 navigator.registerTool 和 navigator.unregisterTool 将 MCP 工具绑定到 React 组件。
-
创建
web-mcp.ts文件:我们在这里声明所有工具的注册和注销逻辑。 -
定义 MCP 工具:为
listColumns、addCard、moveCard、deleteCard等定义函数,并将每个函数包装在 MCP 工具模式下。
// lib/web-mcp.ts
export const addCardTool = {
name: "addCard",
description: "向特定列添加新卡片",
inputSchema: {
type: "object",
properties: {
columnId: { type: "string", description: "要添加卡片的列的 ID" },
title: { type: "string", description: "卡片的标题" },
},
required: ["columnId", "title"],
},
func: async ({ columnId, title }) => {
// ... 添加卡片的逻辑 ...
return { success: true, cardId: "new-card-id" };
},
};
export function registerTools() {
if (navigator.registerTool) {
navigator.registerTool(addCardTool);
// ... 注册其他工具 ...
}
}
export function unregisterTools() {
if (navigator.unregisterTool) {
navigator.unregisterTool("addCard");
// ... 注销其他工具 ...
}
}
- 在 UI 组件中连接:在我们的
KanbanBoardReact 组件中,我们使用useEffect来管理工具的生命周期。
// components/KanbanBoard.jsx
import { useEffect } from 'react';
import { registerTools, unregisterTools } from '../lib/web-mcp';
function KanbanBoard() {
useEffect(() => {
// 组件挂载时注册工具
registerTools();
// 组件卸载时注销工具
return () => {
unregisterTools();
};
}, []);
return (
// ... 看板 UI ...
);
}
现在,当我刷新页面并打开这个 Web 应用时,所有的 Web MCP 工具都出现了。
我可以让代理程序帮我规划任务。
例如:“帮我计划一个三人晚餐的所有任务,每个列是一个任务类别。”
你可以看到它实时地创建不同的列,并为每个任务类别自主地添加任务。
我突然之间就把任何通用代理程序变成了一个非常熟悉我正在构建的 Web 应用的专家。
它将绝对不会犯任何错误。
因为所有的操作都是通过 MCP 工具以确定性的方式执行的。
总结
这就是对 Web MCP 的一个总结。
它通过允许网站声明自己的交互能力,为 AI 代理程序提供了一种可靠、确定性的方式来操作网络。
这无疑是朝着更智能、更无缝的人机协作迈出的重要一步。