使用 WebMCP 向 AI 智能体开放你网站的操作能力
WebMCP 说明如何用 document.modelContext 注册站点工具、设置注释,并在已登录浏览器会话中安全执行操作。
WebMCP 颠倒了 Model Context Protocol 的方向。不再是智能体向外连接到你托管的服务器,而是你的页面通过 JavaScript 用 document.modelContext.registerTool() 注册自己的工具,已经打开该页面的智能体直接调用这些声明好的操作,而不必点击你的界面、猜测你的表单字段。
如果你曾经为编程智能体接入过 MCP 服务器,服务端模型你应该很熟悉:一个进程、一种传输方式、一份工具列表、一个负责连接的客户端。浏览器场景才是别扭的那个。智能体的流量落在一个已渲染的页面上,还带着已登录的会话,而在此之前唯一的出路就是”操控”(actuation):读取 DOM、推断按钮的用途、祈祷结账步骤不会在点击中途重新渲染。
本文讲的是真正拥有一个线上应用的人所关心的机制:一次正确的工具注册长什么样,三个 annotation 提示到底改变了智能体的哪些行为,站点工具今天能在哪里运行,以及工具在用户已登录会话中执行所带来的安全后果。
核心要点
- 工具通过
document.modelContext.registerTool()注册,必须提供 name、description 和inputSchema;navigator.modelContext是更早的命名空间,如今仍会出现在过时的代码片段里。 - 三个 annotation 提示会改变智能体的行为:
readOnlyHint、consequentialHint和untrustedContentHint。 - 注册的工具在活动页面中以用户已登录的会话身份执行,因此你暴露的每一项能力,智能体都能以该用户的权限行使。
- ChatGPT 内置浏览器不支持声明式 HTML 表单 API,也不会发现 iframe 内的工具,所以请在顶层文档上以命令式方式注册。
- WebMCP 不是一条发现渠道:Chrome 将工具可发现性列为尚未解决的限制,因为在智能体加载页面之前,没有任何机制会对外宣告一个站点有哪些工具。
这次反转:WebMCP 到底不一样在哪?
服务端 MCP 服务器是智能体主动向外连接的对象,配置一次即可,与是否打开了某个页面无关。WebMCP 反其道而行。OpenAI 的站点工具文档把分界线划在”工具住在哪里”。MCP 让 AI 应用指向一个服务器,本地或远程,它位于页面之外,浏览器开不开都能工作。而一个 WebMCP 站点把自身能力交付为一组现成的工具,智能体一到即可发现,用户什么都不用安装。
回报是精确性。Chrome 的 WebMCP 文档从”由谁来决定一个控件的含义”这个角度说明了差别:有了工具,站点直接把话说明白,智能体不再需要推断任何东西。操控方式给它的是一串步骤,每一步都要做一次判断。一个针对你所编写的 schema 调用 search_orders({ status: "open" }) 的智能体,不可能点错筛选下拉框,也不会因为你重命名了一个 CSS 类而崩掉。
如何用 document.modelContext.registerTool() 注册工具?
工具注册接收一个包含 name、description 和 inputSchema 的对象;Chrome 的命令式 API 参考把这三项视为必填字段,而 annotations 和 execute 函数承载具体行为。调用前请先做特性检测,就像 OpenAI 自己的示例那样,因为大多数浏览器尚不提供该 API。
async function registerAgentTools() {
if (typeof document.modelContext?.registerTool !== "function") return;
await document.modelContext.registerTool({
name: "list_orders",
description:
"List the signed-in customer's orders, newest first, optionally filtered by fulfilment status. Returns order number, placed date, status and total.",
inputSchema: {
type: "object",
properties: {
status: {
type: "string",
enum: ["open", "shipped", "delivered", "cancelled"],
description: "Fulfilment status to filter by. Omit for all orders.",
},
limit: {
type: "integer",
minimum: 1,
maximum: 20,
description: "Maximum orders to return. Defaults to 10.",
},
},
required: [],
additionalProperties: false,
},
annotations: { readOnlyHint: true },
// Same function the orders table calls. The API still checks the session.
execute: async ({ status, limit = 10 }) => fetchOrders({ status, limit }),
});
}
description 是模型在判断这个工具是否契合当前请求时唯一会读的内容,因此它的分量不亚于背后的代码。写清楚返回结构、写清楚筛选条件,也写清楚这个工具不覆盖什么。
注意这里的 execute 做了什么:它做的是委托。工具调用的是 UI 所调用的同一个取数函数,其背后的服务器施加的仍是它一直施加的那套授权。OpenAI 的指引是让开发者复用既有的认证与授权,而不是另起一条并行路径,工程上的理由很直白:通向同一能力的两条代码路径必然会走偏,而其中没有 UI 挡在前面的那条,正是没人会注意到它已经走偏的那条。
三个 annotation 提示改变了什么?
Annotations 是元数据,用来在智能体调用工具之前告诉它该如何对待这个工具。Chrome 记录了三个,Chrome 的工具安全指南则从各自所标示的风险角度重新解释了它们。
| 提示 | 何时设置 | 对智能体的影响 |
|---|---|---|
readOnlyHint | 工具只读取、不改变任何东西 | 让智能体判断是否根本不需要确认 |
consequentialHint | 操作会落到现实世界且无法撤回:支付、转账、预订 | 告知智能体或浏览器先获取用户确认 |
untrustedContentHint | 输出包含用户生成内容或外部数据 | 将载荷标记为不可信,使智能体更谨慎地处理 |
逐个工具、有意识地设置它们。一个没有 consequentialHint 的 cancel_subscription 工具,智能体可能不作停顿就触发;一个没有 untrustedContentHint 的评论抓取工具,则会把一整段陌生人撰写的文本毫无标记地递给模型。
WebMCP 今天能在哪里运行?
OpenAI 的站点工具页面说明了 ChatGPT 会在何处认可已注册的工具:在保持更新的 ChatGPT 桌面应用内置浏览器中,ChatGPT Work 与 Codex 可以发现并调用页面所提供的任何工具。模型同样有要求,GPT-5.6 Sol 与 GPT-5.6 Terra 受支持,而 GPT-5.6 Luna 上 WebMCP 被禁用。Enterprise 与 Edu 工作区不在范围内,而该功能是否会出现,仍取决于灰度进度以及打开的页面注册了什么。地址栏中的一个箭头会列出页面提供的工具,整个功能也可以在 Browser permissions 下关闭。
Chrome 的实现仍处于预览阶段。Chrome 记录的 WebMCP 位于 chrome://flags/#enable-webmcp-testing 标志之后,供本地开发使用,设为 Enabled 并重启浏览器即可,此外还有一个自 Chrome 149 起可加入的 origin trial。它在稳定版中并非默认开启,而且两家厂商的支持声明都在变动,因此在据此发布之前请先查阅原始页面。
ChatGPT 浏览器不支持什么
OpenAI 的文档明确表示内置浏览器只覆盖了 WebMCP 的一部分,并点名了两处缺口。通过 HTML 表单属性定义的工具不会成为站点工具,而在 iframe 内注册的工具不会被发现,同源 iframe 也不例外。实际操作上的建议很简短:以命令式方式、在顶层文档上注册,不要依赖任何花哨的东西。
那条 iframe 限制是 ChatGPT 的,不是标准的。Chrome 把两套 API 都置于 tools Permissions Policy 之后,其初始值为 self。在该默认值下,顶层文档与同源 frame 可以注册工具,跨域 iframe 则不行。位于另一来源的嵌入式组件若要注册工具,需要该 frame 被授予 tools 策略、工具传入列出授权来源的 exposedTo,并且调用方在 getTools() 中传入 fromOrigins。Chrome 还将 WebMCP 限制在 origin-isolated 文档内,因此使用了 document.domain 的页面完全拿不到该 API。
你的工具以登录用户的身份运行
已注册的工具在活动页面内、以用户已登录的会话身份执行,这意味着你暴露的每一项能力,都是智能体可以用该用户权限行使的能力。界定范围时要问的不是”自动化什么会比较方便”,而是”什么样的操作你能接受在没有点击的情况下被调用”。
Chrome 的安全指南在解释这一点为何重要时异常直白。模型把指令和数据当作一串连续的 token 接收,二者之间没有界线。在一个概率性的系统内部,安全无法被保证。提示注入已经在运行最强模型的智能体系统上反复奏效,而网络上此类攻击的数量还在持续攀升。OpenAI 对工具本身的说法也大体相同:在其站点工具文档中,一个网站的工具定义及其返回的结果都被视为不可信内容。
由此引出三项具体控制。工具可见性默认是关闭的,因为在你于 exposedTo 中点名其来源之前,其他站点和跨域 iframe 看不到你的工具;对会暴露用户数据的只读工具,要施加与写入工具同等的谨慎。Chrome 还指出一条你并未主动开放的访问路径:扩展可以从 content script 查询并执行你的工具,而一个持有你站点 host_permission 的扩展,本来就已经能在该页面上运行自己的 JavaScript。另外,把文本控制得短一些。Chrome 建议工具描述 500 字符、每个参数描述 150 字符、工具名与参数名 30 字符、每个工具输出 1.5K,并说明这四项都是建议值,可能随生态反馈而变化,日后也可能被正式规范化。围绕同意管理的工作仍在推进,其中包括规范草案中用于在执行中途向用户提问的 requestUserInteraction(),该方法尚未发布。
WebMCP 不是一项 SEO 手段
注册站点工具改变的是智能体到达你页面之后能做什么,它完全无助于让智能体到达。Chrome 自己的限制清单就把工具可发现性列为待解问题:客户端或浏览器只有访问了某个站点,才会知道它有可调用的工具。没有爬取、没有索引、没有已注册工具的信息流。结合这一机制来看,结论很直接——尽管这是我们的解读而非厂商声明:WebMCP 是一个转化路径层面的能力,而不是排名或引用的杠杆,把工具描述当成 meta description 文案来写,是搞错了它的读者是谁。
挑一个用户已经会在你站点上完成的操作,先以只读方式注册它,然后把真正的功夫花在 description 和 schema 上。智能体究竟能不能读懂你的应用,分水岭就在这里,而这部分,任何浏览器的灰度推进都不会替你解决。
常见问题
当用户离开页面时,我该如何注销一个 WebMCP 工具?
并不存在 unregisterTool 方法。在 document.modelContext.registerTool 的 options 对象中传入一个 AbortSignal,然后在该工具不再适用时中止对应的 controller,例如组件卸载或 SPA 路由切换时。Chrome 的最佳实践用页面状态来表述这件事:工具有用时注册它,不再有用时注销它。把 abort 绑定到你的页面切换上,是实现这一点的务实做法,也能避免过期工具滞留,或与同名工具的新一次注册发生冲突。智能体通过 document.modelContext 上的 toolchange 事件感知这一变化。
声明式与命令式 WebMCP API 有什么区别?
声明式 API 把一个已有的 HTML 表单变成工具:在 form 元素上添加 toolname 与 tooldescription 属性,并在各个字段上添加 toolparamdescription,浏览器会据此从表单推导出结构化表示。移除其中任一属性都会注销该工具。命令式 API,即 document.modelContext.registerTool,更适合动态工具和复杂逻辑。ChatGPT 内置浏览器仅支持命令式路径。
注册 WebMCP 工具是否有 React 或 Angular 的支持?
两者都有,且都处于实验阶段。Chrome Labs 在 use-webmcp-tool 包中维护了 useWebMCP hook,它在挂载时注册工具、卸载时注销,要求 React 18 或更高版本,并在 API 缺失时降级为空操作。Angular 从其 core 包中导出 provideExperimentalWebMcpTools,将工具生命周期绑定到注入器,推荐放置在路由或应用级 providers 中。
浏览器会依据我的 inputSchema 校验智能体传入的参数吗?
不要假设它会。把到达 execute 的输入视为未经校验,在据其行动之前先在代码中检查。Chrome 的 WebMCP 指南要求开发者校验各项约束并返回描述性错误,以便智能体重试;Angular 则明确表示它不会根据你声明的 JSON schema 检查智能体提供的参数。在此之上,服务端授权校验依然必须执行。