Agent 帮用户订票、填售后单,却在自定义日期控件、多层菜单里点错、重试、烧 token——根因往往不是模型「不够聪明」,而是页面只对人类可读,没有给机器一份可调用的接口。Chrome 里的 WebMCP 要解决的就是这件事:让站点主动声明「我能做什么」,而不是让 Agent 从 DOM 里猜。
状态说明(2026-08):WebMCP 仍是 Web Machine Learning CG Draft(非 Standards Track)。Chrome 本地 flag 约自 M146;Origin Trial 为 M149–M156(blink-dev Intent to Experiment);Intent 估计 Shipping M157,Stable 默认开启尚未官宣。API 可能继续变;以 Chrome 文档 为准。
先分清三个「MCP」
名字撞车很常见,先对齐:
| 名称 | 干什么 | 典型入口 |
|---|---|---|
| WebMCP | 网页把客户端能力暴露给浏览器内 Agent | document.modelContext.registerTool / HTML toolname |
| MCP(Model Context Protocol) | Agent 连后端/外部系统的通用协议 | JSON-RPC + stdio / HTTP / SSE 等 |
| Chrome DevTools MCP / DevTools for agents | 编码 Agent 操控、调试浏览器 | chrome-devtools-mcp 等 |
官方写得很直白:WebMCP 不是 MCP 的扩展,也不替代 MCP。更贴切的说法是:MCP-inspired 的浏览器 API——共享「工具发现 + 结构化调用」的哲学,但省略服务端那套 Resources / Prompts,也没有 HTTP/SSE/stdio 传输。工具绑定在当前打开的标签页上,用户离开页面,Agent 就不能再碰。
实用分工:
- MCP Server:核心业务、跨端数据、后台任务(随时可调用)。
- WebMCP:用户正在看的站点 UI、当前 session / cookie / 表单(只在访问时可用)。
为什么需要它
没有 WebMCP 时,浏览器 Agent 的路径大致是:扫可访问性树 / DOM → 猜哪个按钮 → 模拟点击 → 再猜下一步。每一步都可解释失败。
有了 WebMCP,站点可以注册例如 checkout、filter_results、submit_application:带 JSON Schema 的输入输出,执行走你自己的前端逻辑,UI 仍在用户眼前更新。官方把它定位为 progressive enhancement:没 Agent 的浏览器照常用人机界面;有 Agent 时任务更准、更省步数。
在 Chrome 里怎么开
本地实验
- 使用具备 WebMCP 的 Chrome(flag 路径约需 ≥ 146.0.7672.0)。
- 打开
chrome://flags/#enable-webmcp-testing→ Enabled → 重启。 - 要在 DevTools 里调试工具列表与调用历史,再开
#devtools-webmcp-support。 - 面向真实源、不想让用户开 flag:参加 WebMCP Origin Trial(文档写自 Chrome 149;Intent 窗口 149–156),用
<meta http-equiv="origin-trial">或Origin-Trial响应头挂 token。
环境约束(踩坑点)
- 需要 secure context(HTTPS / localhost)与 origin-isolated 文档。若启用了会破坏源隔离的配置(例如与
document.domain/Origin-Agent-Cluster: ?0相关),WebMCP API 会被关掉。 - Permissions Policy 功能名是
tools,默认self:同站可用,跨源 iframe 默认不能注册;需要时在 iframe 上写allow="tools"。 - 工具执行依赖可见 browsing context——没有「无界面后台偷偷调网页工具」这条路径。
Imperative API:用 JS 注册工具
入口是 document.modelContext(旧的 navigator.modelContext 已走弃用路径,新代码别再用)。最小模式:
const modelContext = document.modelContext;
if (!modelContext || typeof modelContext.registerTool !== "function") {
// 浏览器不支持或未开 flag:走无人机增强的普通 UI
return;
}
await modelContext.registerTool({
name: "get_order_status",
description:
"Search orders in a given timeframe. Returns order number, shipping status and location.",
inputSchema: {
type: "object",
properties: {
timeframe: {
type: "string",
enum: ["today", "yesterday", "last_7_days", "last_30_days"],
description: "Timeframe for the order lookup.",
},
},
required: ["timeframe"],
},
annotations: {
readOnlyHint: true,
untrustedContentHint: false,
},
execute: async ({ timeframe }) => {
const status = await fetchOrderStatus(timeframe);
// 返回清晰、可被模型消费的文本;过长易撞上 Agent 护栏
return status;
},
});
要点:
- name / description / inputSchema / execute 是注册核心。
- 用
AbortSignal注销(没有单独的unregisterTool):SPA 换路由时在离开页面 abort。 annotations.readOnlyHint:只读工具,方便 Agent 决定要不要二次确认。annotations.untrustedContentHint:返回 UGC / 外部数据时标上,降低间接 prompt injection 风险。
跨源共享时双闸:注册侧 exposedTo: ['https://trusted.example'],发现侧 getTools({ fromOrigins: ['https://partner.org'] })。只暴露给你愿意代用户行动的源。
框架侧已有实验封装:React 的 usewebmcp、Angular 也对 Signal Forms 做了 WebMCP 对接——仍属实验,跟 Chrome 版本一起看。
Declarative API:给表单贴注解
表单本来就是「结构化输入」。声明式 API 让浏览器把 <form> 合成工具:
<form
toolname="createSupportRequest"
tooldescription="Submits a request for customer support."
action="/submit"
>
<label for="firstName">First Name</label>
<input type="text" name="firstName" id="firstName" />
<label for="topic">Topic</label>
<select
name="topic"
required
toolparamdescription="Determines what team this request is routed to."
>
<option value="returns">Return my purchase.</option>
<option value="shipping">Check where my package is.</option>
</select>
<button type="submit">Submit</button>
</form>
行为差异:
- 没有
toolautosubmit:Agent 填完字段后,通常还要用户点提交——适合付款、发帖等敏感动作。 - 有
toolautosubmit:调用时可触发提交/导航。 - 提交事件上有
agentInvoked;需要把结果回给模型时,先preventDefault(),再respondWith(promise)。 - 样式钩子:
:tool-form-active、:tool-submit-active,让用户看见「Agent 正在操作这块」。
去掉 toolname 或 tooldescription 即注销该声明式工具。
怎么验:Inspector 与 DevTools
- Model Context Tool Inspector 扩展:看已注册工具、手搓参数调用、用自然语言试 Agent(文档默认示例模型为
gemini-3-flash-preview)。 - DevTools → Application → WebMCP(Chrome 149+,需开调试 flag):Available Tools / Invoked Tools、schema 校验、手动 Run。
- 若用 Chrome DevTools for agents 自动化联调,需额外打开 WebMCP 相关 category(如
--category-experimental-webmcp),与「站点实现 WebMCP」是两条线。
官方 demo 可对照:WebMCP zaMaker、Travel(React)、Le Petit Bistro(声明式),源码在 GoogleChromeLabs/webmcp-tools。
工具设计:少而准
抄官方 best practices 里最容易落地的几条:
- 一个工具一件事;重叠工具会让模型选错。
- 名称用动词表结果:
create-eventvsstart-event-creation-process(后者只是导航到表单)。 - 描述用正向能力,少写「不要用于某某」。
- Schema 宽松、代码里严格校验;错误信息写清楚,方便模型改参重试。
- 字符预算(安全文档建议量级):描述约 500、参数描述约 150、名称约 30、单次输出约 1.5K——具体 Agent 会有差异。
安全:默认别给跨源、别信模型护栏
WebMCP 把能力交给 Agent,等价于多了一条「可编程操作面」。至少做到:
- 跨源默认不暴露;
exposedTo白名单要短。 - 写操作要用户可见、可取消;敏感流优先声明式 + 人手确认。
- 返回不可信内容时打
untrustedContentHint。 - 假定 LLM 护栏挡不住间接 prompt injection——业务侧校验、鉴权、审计不能省。
什么时候还不该上
- 需要无 UI / 纯后台的长期自动化 → 业务仍应走后端 MCP 或正规 API。
- 工具要被未打开你网站的 Agent 随时调用 → WebMCP 发现不了。
- 浏览器未开 flag / 未进 Origin Trial → 只能当增强,不能当唯一路径。
最小落地清单
- 开
#enable-webmcp-testing(或 Origin Trial)。 - Feature detect 后注册 1~3 个高价值工具(搜索、填表、查状态)。
- 用 Inspector / Application → WebMCP 手测 schema 与错误返回。
- 敏感工具强制用户确认;只读工具标
readOnlyHint。 - 后端能力继续放 MCP Server;页面上下文交互再叠 WebMCP。
一句话:WebMCP 让「当前打开的网页」成为浏览器 Agent 的可靠工具源;MCP 负责随时可达的业务后端。 两者一起用,而不是互相取代。
参考
- WebMCP 概览
- Imperative API / Declarative API
- WebMCP 与 MCP 对比
- Best practices / Tool security
- Debug WebMCP in DevTools
- WebMCP Draft Spec
- 本仓库调研 memo:
docs/research/webmcp-chrome-research-memo.md