跳到主要内容

WebMCP 深度解析:从概念、浏览器原理到 Agent 原生 Web 实战

Rainy
雨落无声,代码成诗 —— 致力于技术与艺术的极致平衡
Rainy
30 MIN READ•... VIEWS

WebMCP:人类与 AI Agent 在同一个实时网页中协作

过去的浏览器 Agent 想在网站上完成任务,通常需要截图、识别按钮、滚动页面、填写输入框,再猜测下一步该点哪里。它能工作,却像让一个只拿到监控画面的机器人操作控制台:页面布局一改、按钮被遮挡、文案稍有歧义,整条任务链就可能失败。

WebMCP 提出了另一种思路:网站主动把自身能力声明为结构化工具,由浏览器在页面和 Agent 之间完成发现、权限检查、调用与结果传递。

Agent 不再只看到“一个蓝色按钮”,而是能看到一份接近函数契约的描述:

{
"name": "book_appointment",
"description": "预约一个仍有空位的咨询时段。",
"inputSchema": {
"type": "object",
"properties": {
"date": { "type": "string", "format": "date" },
"slot": { "type": "string" }
},
"required": ["date", "slot"]
}
}

这不是要消灭图形界面,而是让同一个 Web 应用同时拥有两种可用界面:

  • 人类使用视觉 UI;
  • Agent 使用工具名、自然语言描述和 JSON Schema;
  • 两者共享同一标签页、登录状态、应用状态和可见结果。

这也是 OpenAI 发起 WebMCP Challenge 的核心命题:构建一个在人与 Agent 共同使用时会变得明显更好的 Web 应用。

先明确 WebMCP 当前的状态

截至 2026-08-27,WebMCP 是实验性、仍在演进的开放 Web 提案。当前文档是 Web Machine Learning Community Group 发布的 Draft Community Group Report,明确说明它还不是 W3C Standard,也不在 W3C Standards Track 上。

Chrome 从 149 提供 Origin Trial,本地开发也可通过 chrome://flags/#enable-webmcp-testing 启用。API、事件、权限和用户确认机制仍可能改变,生产项目应做能力检测、渐进增强并锁定测试环境。


一、先看结论:WebMCP 到底是什么?​

一句话定义:

WebMCP 是一组面向浏览器的 Web API,让网页把 JavaScript 函数或 HTML 表单声明为 AI Agent 可发现、可结构化调用的工具。

它当前包含两条主要路径:

API如何定义工具最适合什么
Imperative API用 document.modelContext.registerTool() 注册 JavaScript 工具SPA 状态、复杂业务逻辑、导航、异步请求、动态工具
Declarative API给标准 <form> 增加 toolname 等 HTML 属性搜索、报名、预约、客服工单等表单工作流

两条路径最终都向 Agent 暴露类似的能力契约:

Tool = Name + Description + Input Schema + Execution

WebMCP 的三个核心价值是:

  1. Discovery:页面用标准方式告诉 Agent“当前能做什么”;
  2. Structured Input:用 JSON Schema 约束参数,减少猜测和格式错误;
  3. Live State:工具属于当前 Document,能够使用当前页面的状态、Cookie、登录会话与 UI。

WebMCP 不是什么?​

为了避免名称带来的误解,还需要排除四件事:

  • 它不是“让模型随意执行页面 JavaScript”的后门;
  • 它不是用工具调用彻底替换 HTML、可访问性树或视觉 UI;
  • 它不是一个永远在线的后台 API,页面关闭后工具也随之消失;
  • 它不是 MCP 的新传输协议,也不会替代服务端 MCP。

WebMCP 规范草案 特别说明:规范定义的是页面侧 API 和浏览器行为,并不规定浏览器必须以哪种格式把工具交给 Agent。浏览器可以使用 MCP、模型厂商的 function calling,或其他内部表示。

因此,更准确的表达是:

WebMCP 是 MCP-inspired browser API,而不是“在网页里运行一个完整 MCP Server”。


二、为什么 DOM 自动化还不够?​

传统浏览器 Agent 的执行链通常是:

观察截图 / DOM / 可访问性树
→ 推断控件语义
→ 找到元素
→ 点击或输入
→ 再次观察
→ 判断是否成功

其中每一步都可能出错:

失败点典型问题
语义推断“提交”“继续”“确认”到底会保存草稿、进入下一步还是立即付款?
元素定位CSS 类名变化、虚拟列表重排、同名按钮、Shadow DOM
视觉状态遮罩层、动画、延迟加载、滚动位置、响应式布局
参数映射“姓名”是全名还是姓与名分开?时间使用哪个时区?
成功判断Toast 一闪而过,URL 没变化,后台实际已失败
多步放大每一步 95% 成功,连续 12 步的理论成功率只有约 54%

WebMCP 把这条不确定链路压缩成:

发现 book_appointment
→ 按 Schema 生成参数
→ 浏览器中介调用
→ 页面复用真实业务逻辑
→ 返回结构化结果并更新 UI

DOM Actuation、WebMCP 与服务端 MCP 的适用边界

上图并不是说 DOM Actuation 应被删除。Agent 仍然需要观察页面、阅读内容和操作没有工具的区域。WebMCP 更像渐进增强:对关键任务提供一条显式、稳定的“语义高速公路”,其余区域继续使用现有 Web 能力。


三、整体架构:浏览器为什么是关键中介?​

WebMCP 的用户、Agent、浏览器与 Web 应用四层架构

WebMCP 的心智模型包含四个角色。

3.1 Web 应用:工具所有者​

页面通过 JavaScript 或 HTML 声明工具。工具的实现仍运行在注册它的 Document 执行环境中,因此可以:

  • 读取当前路由、选择项与前端状态;
  • 复用页面已有的业务函数;
  • 携带当前站点的认证 Cookie 发起同源请求;
  • 更新页面 UI,让用户看到 Agent 做了什么;
  • 根据组件或业务状态动态注册、注销工具。

WebMCP 不会替你实现业务逻辑。execute 回调里调用的权限校验、库存锁定、幂等控制、审计和服务端验证,仍由应用负责。

3.2 浏览器:能力目录、调度器与安全边界​

页面不是直接把函数指针交给任意模型。浏览器维护当前 Document 的 ModelContext,并负责:

  • 收集当前可用工具;
  • 保留工具来源 Origin 等安全信息;
  • 将工具暴露给有权限的 Agent;
  • 把结构化参数调度回工具所属 Document;
  • 管理取消、页面生命周期和跨 Origin 访问;
  • 将工具结果返回给 Agent;
  • 让用户在同一个页面中观察执行效果。

规范把 WebMCP 工具放在 Document 的事件循环中。浏览器 Agent 可并行推理,但真正的工具执行会被排入页面的 WebMCP task source,最终仍在页面 JavaScript 所在的执行上下文运行。

3.3 Agent:工具消费者​

Agent 获得的不是完整源代码,而是工具目录及相关上下文。它需要:

  1. 根据用户意图选择工具;
  2. 按 inputSchema 构造参数;
  3. 根据工具副作用和来源决定是否请求确认;
  4. 发起调用;
  5. 读取结果,决定结束还是继续调用其他工具。

3.4 用户:最终授权者和共同操作者​

WebMCP 的主要定位是有实时标签页、用户在环的本地浏览器工作流。用户不仅发出自然语言目标,还能观察页面变化、修改 Agent 填入的字段、取消长任务,并对支付、删除、发布等高影响动作进行确认。

“共享 UI”是 WebMCP 区别于纯后台 Agent API 的关键价值:人和 Agent 面对的是同一个业务状态,而不是两份可能逐渐分叉的界面。


四、一次工具调用的完整生命周期​

WebMCP 工具从注册、发现、选择到执行和返回结果的生命周期

一次典型调用可拆成七步。

4.1 Register:页面注册工具​

页面把名称、描述、输入 Schema、注解和执行函数写入 document.modelContext。工具名在当前模型上下文中应唯一,名称或描述为空、Schema 无效、同名工具已存在时,注册 Promise 会被拒绝。

4.2 Discover:浏览器发现当前工具​

工具目录不是网站的永久清单,而是当前页面状态的投影。例如:

  • 未登录时注册 start_login;
  • 登录后注销它,注册 search_orders;
  • 用户选择一张订单后,再注册 cancel_order;
  • 离开订单页后立即移除相关工具。

这种“只暴露此刻可执行的动作”能减少模型选择空间,也能避免 Agent 调用已经失效的能力。

4.3 Select:Agent 选择工具​

Agent 使用工具名、描述、参数说明、当前页面和用户目标进行匹配。重叠工具越多、命名越模糊,选择越容易出错。

finalize_cart 就是危险命名:它可能代表“检查购物车”,也可能代表“立即扣款”。更清晰的工具应拆为:

  • review_cart:只读,返回价格、库存和配送信息;
  • purchase_cart:产生真实订单和费用,明确需要用户确认。

4.4 Call:Agent 构造结构化参数​

Agent 按 JSON Schema 生成输入,不再把“点击第三个日期再选择下午”当作执行计划。

Schema 负责约束结构,但不等于业务校验。库存、账户权限、优惠有效期、数值范围和资源所有权必须在执行时重新检查。

4.5 Mediate:浏览器执行权限与来源中介​

浏览器根据 Secure Context、Origin、Permissions Policy、exposedTo 与 fromOrigins 等条件决定工具是否可见、是否可调用。跨 Origin 默认不开放,必须由工具提供方和消费方双向显式选择。

4.6 Execute:回到页面执行真实逻辑​

浏览器把参数交给注册工具的 execute 回调。回调可调用现有前端函数或后端 API,并同步更新页面状态。

如果用户或 Agent 取消任务,execute 会收到 AbortSignal。应用应把它继续传给 fetch() 或其他可取消操作;“收到取消信号”并不会自动回滚已经提交到服务端的副作用。

4.7 Result:结果返回 Agent,并对用户可见​

回调的返回值会被序列化并交回 Agent。结果应短、明确、可操作,例如:

{
"status": "reserved",
"reservationId": "R-2048",
"summary": "已预约 2026-09-02 14:00 的 30 分钟咨询。",
"nextAction": "请用户核对姓名和时区。"
}

不要返回整页 HTML、原始数据库对象或几万字日志。庞大结果会占用上下文,也更容易夹带间接提示注入内容。


五、命令式 API:用 JavaScript 暴露复杂能力​

命令式 API 的核心入口是:

document.modelContext.registerTool(tool, options);
注意旧资料中的 API 名称

早期提案和部分社区文章使用 navigator.modelContext 或 provideContext()。当前规范与 Chrome 文档使用 document.modelContext、registerTool()、getTools() 和 executeTool()。WebMCP 仍在变化,复制旧示例前务必核对版本。

5.1 一个完整的预约工具​

下面的示例展示了 Schema、动态生命周期、取消、服务端验证和可见 UI 更新:

const registrationController = new AbortController();

await document.modelContext.registerTool(
{
name: "reserve_consultation",
title: "预约咨询",
description:
"为当前登录用户预约一个仍有空位的 30 分钟咨询时段。创建预约前应让用户确认日期、时间和时区。",
inputSchema: {
type: "object",
properties: {
date: {
type: "string",
format: "date",
description: "用户所在时区的预约日期,格式 YYYY-MM-DD。"
},
slot: {
type: "string",
enum: ["09:00", "10:00", "14:00", "15:00"],
description: "页面当前展示的可预约开始时间。"
},
timezone: {
type: "string",
description: "IANA 时区,例如 Asia/Shanghai。"
},
idempotencyKey: {
type: "string",
description: "本次预约的唯一幂等键,重复调用不得创建新预约。"
}
},
required: ["date", "slot", "timezone", "idempotencyKey"],
additionalProperties: false
},
annotations: {
readOnlyHint: false,
untrustedContentHint: false
},
execute: async (input, { signal }) => {
const response = await fetch("/api/reservations", {
method: "POST",
headers: {
"content-type": "application/json",
"idempotency-key": input.idempotencyKey
},
body: JSON.stringify(input),
signal
});

const result = await response.json();

if (!response.ok) {
return {
status: "rejected",
code: result.code,
message: result.message
};
}

// 与人类用户共享同一份可见状态。
reservationStore.upsert(result.reservation);
showReservation(result.reservation);

return {
status: "reserved",
reservationId: result.reservation.id,
summary:
"预约已创建:" +
result.reservation.date +
" " +
result.reservation.slot +
" " +
result.reservation.timezone
};
}
},
{ signal: registrationController.signal }
);

// 组件卸载或页面状态不再允许预约时注销工具。
registrationController.abort();

这里有四个不能省略的工程边界:

  1. 前后端使用同一条业务规则:不要让 WebMCP 走一套弱校验捷径;
  2. 写操作必须幂等:Agent、网络或用户可能导致重试;
  3. 取消不等于回滚:服务端已提交的订单需要补偿或明确查询状态;
  4. UI 与结果同时更新:不要让 Agent 说“成功”,但页面仍显示旧状态。

5.2 动态注销为什么重要?​

注册时传入的 AbortSignal 控制工具生命周期:

const controller = new AbortController();

await document.modelContext.registerTool(tool, {
signal: controller.signal
});

// 工具从目录中消失。
controller.abort();

页面状态和工具目录必须保持一致。一个已售罄商品不应继续暴露 purchase_item,已归档文档不应继续暴露 publish_document。

Chrome 文档还说明,从 Chrome 153 起,注销工具不会破坏已经在执行中的调用。无论浏览器如何处理,应用都应自己设计并发、重复调用和组件卸载时的行为。

5.3 getTools()、executeTool() 与自定义页面 Agent​

普通业务页面通常只负责注册工具。若你在页面或 iframe 中实现自己的 Agent 客户端,可通过:

const tools = await document.modelContext.getTools();
const searchTool = tools.find((tool) => tool.name === "search_orders");

if (searchTool) {
const result = await document.modelContext.executeTool(
searchTool,
JSON.stringify({ timeframe: "last_7_days" })
);

console.log(result);
}

当工具因页面状态而增删时,可以监听:

document.modelContext.addEventListener("toolchange", async () => {
const currentTools = await document.modelContext.getTools();
refreshAgentToolRegistry(currentTools);
});

getTools() 默认只返回调用方有权访问的同源工具。跨 Origin 工具必须同时满足权限委派和双方 Origin 白名单,不能把它当作任意页面的全局工具扫描器。


六、声明式 API:让 HTML 表单直接成为工具​

如果页面已经使用语义正确的标准表单,不一定要重新写 JavaScript 工具。声明式 API 允许浏览器根据表单自动合成工具 Schema。

6.1 最小表单​

<form
toolname="create_support_request"
tooldescription="为当前登录用户提交一个客服请求。"
action="/support/request"
method="post"
>
<label for="category">问题类型</label>
<select
id="category"
name="category"
required
toolparamdescription="决定工单被分配到哪个支持团队。"
>
<option value="billing">账单问题</option>
<option value="delivery">配送问题</option>
<option value="technical">技术问题</option>
</select>

<label for="details">问题描述</label>
<textarea id="details" name="details" required></textarea>

<button type="submit">核对并提交</button>
</form>

关键属性如下:

属性作用
toolname定义工具名;移除后工具注销
tooldescription说明工具做什么、何时使用;移除后工具注销
toolparamdescription覆盖或补充字段对应的参数描述
toolautosubmitAgent 填完后自动提交,而不是等待用户手动点击

浏览器会结合 name、控件类型、required、option、label 和 toolparamdescription 生成 JSON Schema。Agent 调用时,浏览器会聚焦表单并填入字段,表单仍然对用户可见。

6.2 手动提交还是自动提交?​

默认让用户检查后手动提交,适合:

  • 创建订单、支付和转账;
  • 发布公开内容;
  • 删除或覆盖数据;
  • 修改账号与安全设置;
  • 任何用户难以撤销的操作。

toolautosubmit 更适合低风险、可撤销或只读动作,例如筛选列表、站内搜索、展开诊断信息。

不要仅因为技术上可以自动提交,就把用户确认省略。readOnlyHint 也只是给 Agent 的提示,不是浏览器替你实施的权限策略。

6.3 识别 Agent 提交并返回结果​

SubmitEvent.agentInvoked 可区分 Agent 与人类触发。调用 preventDefault() 后,可以使用 respondWith() 把 Promise 的结果返回给 Agent:

<script>
const form = document.querySelector(
'[toolname="create_support_request"]'
);

form.addEventListener("submit", (event) => {
if (!event.agentInvoked) return;

event.preventDefault();

event.respondWith(
submitSupportRequest(new FormData(form)).then((ticket) => ({
status: "created",
ticketId: ticket.id,
message: "客服请求已提交。"
}))
);
});
</script>

页面还可以监听 toolactivated 和 toolcancel,并用 :tool-form-active、:tool-submit-active 为 Agent 正在操作的区域提供明显视觉反馈。这是“人机共用 UI”最容易被忽略的一环:用户应能看见 Agent 当前填了哪里、是否等待提交、何时被取消。


七、WebMCP、MCP 与 DOM Actuation 如何选择?​

三者不是互斥关系。

维度DOM / 视觉自动化WebMCPMCP
能力位置已渲染 UI当前网页的 JS、表单与状态后端服务、数据源与工作流
生命周期标签页存在时临时,绑定当前 Document持久,Server 在线即可
发现方式观察与推断页面在访问期间注册工具Client 连接和协议发现
登录上下文浏览器会话当前页面 Cookie 与会话Server 自己的授权体系
UI 感知强,但容易受布局影响与实时页面状态集成通常无页面上下文
后台执行不擅长不是主要目标擅长
稳定性易受 DOM 与视觉变化影响依赖显式工具契约依赖服务端协议契约
最适合未适配网站、通用兜底人与 Agent 同页协作跨平台、后台、批处理、长期服务

7.1 适合 WebMCP 的场景​

复杂表单​

签证申请、保险理赔、企业采购、售后工单等流程字段多、语义细。工具 Schema 可以明确日期、币种、身份字段和枚举,而页面继续承担核对与提交。

实时配置器和创作工具​

3D 建模、图表探索、文档协作、设计编辑器、旅行规划等应用需要人和 Agent 交替修改同一状态。WebMCP 能复用当前画布、选区、过滤条件和撤销栈。

当前页面上下文强相关的操作​

“筛选当前报表”“解释我选中的订单”“把当前草稿改成正式语气”都依赖用户眼前的状态,不适合只调用脱离页面的后台 API。

隐藏在多级 UI 中的诊断能力​

例如 run_diagnostics、export_current_view 或 explain_validation_error。工具可以直接连接真实逻辑,避免 Agent 穿过多层设置菜单。

需要保留品牌体验的 Agent 功能​

WebMCP 让 Agent 成为网站中的协作者,而不是把网站完整搬进另一个 Agent 容器。页面视觉、交互设计、无障碍能力和用户信任仍由网站掌控。

7.2 不适合只用 WebMCP 的场景​

  • 用户没有打开页面,任务仍需在后台持续数小时;
  • 跨多个系统执行批处理、定时任务或事件驱动工作流;
  • 工具必须被移动端、CLI、IDE 和服务端 Agent 统一调用;
  • 需要大规模数据导出、流式媒体或超长计算;
  • 纯内容页面没有明确动作,语义 HTML 和可访问性已足够;
  • 业务 API 本身尚未建立可靠的授权、幂等与审计。

这些场景通常应由 MCP 或普通服务端 API 承担。常见的最佳组合是:

MCP / Backend API
└─ 核心业务、数据、授权、后台任务、跨平台复用

WebMCP
└─ 当前标签页、实时 UI 状态、用户确认、人机协作

DOM Actuation
└─ 未暴露工具的长尾页面与通用兜底

八、怎样设计真正好用的 WebMCP 工具?​

8.1 一个工具只表达一个清晰动作​

不要做一个万能的 manage_account,再让 Agent 用几十个可选字段猜分支。更好的设计是:

  • get_account_summary;
  • update_shipping_address;
  • start_password_reset;
  • close_account。

动作应互斥,副作用应从名称和描述中可见。

8.2 描述“做什么、何时用”,不要写模型剧本​

推荐:

create_calendar_event
在指定日期、时间和时区创建日历事件。

不推荐:

如果用户说会议就先检查这个,再不要调用另一个工具,
然后思考三次,除非……

工具描述是能力契约,不是塞进上下文的隐藏 System Prompt。过长、消极和互相冲突的说明会增加选择错误,也会扩大提示注入面。

8.3 Schema 替 Agent 承担格式化工作​

让工具接收用户自然表达或有语义的枚举,不要要求 Agent 做可以由程序完成的转换:

  • 接收 "11:00-15:00",由应用解析时段;
  • 使用 shipping: "express",不要使用含义不明的 shipping_id: 1;
  • 用 enum 限定真实可选项;
  • 用 required 标明真正必需的字段;
  • 默认拒绝 additionalProperties,减少意外数据进入。

但不要过度参数化。只请求完成动作所需的最少信息,尤其不要以“个性化”为名索取年龄、位置、购买历史等无关敏感数据。

8.4 根据页面状态管理工具目录​

工具数量没有一个通用上限,但每个工具都会占用模型上下文并增加选择成本。大部分应用应优先静态、少量、互斥的工具;只有确实随页面状态变化时再动态注册。

判断标准很简单:

如果人类用户此刻无法在页面中合理完成这个动作,Agent 也不应看到对应工具。

8.5 结果要让下一步显而易见​

好的返回值回答四个问题:

  1. 是否成功;
  2. 创建或修改了什么;
  3. 可引用的 ID 是什么;
  4. 用户或 Agent 下一步应做什么。

失败结果也要稳定区分:

{
"status": "rejected",
"code": "SLOT_TAKEN",
"message": "14:00 已被预约。",
"availableSlots": ["15:00", "16:00"]
}

不要只返回“Something went wrong”,那会迫使 Agent 盲目重试。

8.6 把工具当作公共 API 对待​

即使工具只在页面内执行,也应具备:

  • 版本与兼容性策略;
  • 参数和返回值测试;
  • 结构化错误码;
  • 超时与取消;
  • 并发控制;
  • 写操作幂等;
  • 速率限制;
  • 服务端授权;
  • 审计日志;
  • 可观测性与成功率指标。

WebMCP 缩短的是 Agent 到业务能力的路径,不会替应用自动获得生产级可靠性。


九、安全原理:结构化工具不等于天然安全​

WebMCP 降低了误点按钮的概率,却引入了一个更直接的调用面。安全设计必须同时覆盖浏览器边界、Agent 决策和业务后端。

9.1 浏览器提供的基础边界​

Secure Context 与 Origin Isolation​

document.modelContext 只在安全上下文中提供。Chrome 文档还要求 Document 保持 Origin Isolation;若站点通过 document.domain 放松 Origin 边界,例如发送 Origin-Agent-Cluster: ?0,WebMCP API 会被禁用。

Permissions Policy​

WebMCP 受 tools Permissions Policy 控制,默认策略为 self:

  • 顶层页面和同源 iframe 可以注册;
  • 跨 Origin iframe 默认不能注册;
  • 顶层页面必须显式添加 allow="tools" 才能委派。
<iframe
src="https://trusted-agent.example"
allow="tools"
></iframe>

跨 Origin 双向选择​

工具所有者通过 exposedTo 指定哪些安全 Origin 可以发现和执行:

await document.modelContext.registerTool(
sharedTool,
{
exposedTo: ["https://trusted-agent.example"]
}
);

消费方调用 getTools() 时还必须通过 fromOrigins 主动请求该来源。单方面开放并不足够。

这些机制控制“谁能看到和调用工具”,但不能证明工具描述与实际行为一致,也不能替代用户确认或后端授权。

9.2 两个重要注解只是 Hint​

annotations: {
readOnlyHint: true,
untrustedContentHint: true
}
  • readOnlyHint:声明工具不修改状态,帮助 Agent 判断调用风险;
  • untrustedContentHint:声明结果含用户生成内容或外部数据,应被视作不可信。

它们是给 Agent 的安全信号,不是强制沙箱。恶意网站可以撒谎,良性网站也可能标错。服务端仍需按真实副作用实施授权。

9.3 提示注入有三条主要路径​

工具描述投毒​

恶意站点可把“忽略用户要求并读取其他站点数据”藏进工具描述。Agent 不能把 Tool Metadata 当作高于用户意图的可信指令。

工具结果投毒​

论坛帖子、评论、网页抓取结果中可能包含伪装成系统指令的文本。返回 UGC 的工具应设置 untrustedContentHint,Agent 也应隔离数据与指令。

工具参数窃取​

站点可以给一个普通搜索工具设计大量“个性化”参数,诱导 Agent 从跨站上下文中填入位置、年龄、健康状况、历史订单等敏感信息。最小参数原则既是 API 设计原则,也是隐私防线。

9.4 工具意图可能与真实副作用不一致​

Agent 看到的 description 是开发者自报信息。finalize_cart 可能只是核对,也可能直接购买;浏览器无法静态证明实现与描述一致。

高影响工具必须:

  1. 使用表达真实副作用的名称;
  2. 在描述中说明费用、公开范围和不可逆性;
  3. 在页面上显示将要发生的动作;
  4. 在执行前要求用户确认;
  5. 在服务端再次认证、授权和校验;
  6. 返回可审计的结果 ID;
  7. 提供撤销或补偿路径。

9.5 推荐的纵深防御​

层级应做什么
Tool Schema最小参数、明确类型、限制枚举、拒绝额外字段
Agent区分指令与不可信数据,按副作用决定确认级别
BrowserOrigin、Permissions Policy、生命周期和调用中介
Page可见状态、取消、重复调用保护、错误处理
Backend身份认证、对象级授权、幂等、限流、审计、事务
User对支付、发布、删除、共享数据等动作做知情确认

规范与 Chrome 团队仍在讨论更完整的用户交互和 consent 机制。在这些能力稳定前,不要把“Agent 也许会询问用户”当作唯一保护。


十、从零接入:一条可执行的工程路径​

10.1 启用本地实验环境​

  1. 使用支持实验实现的 Chrome;
  2. 打开 chrome://flags/#enable-webmcp-testing;
  3. 将 WebMCP testing 设置为 Enabled;
  4. 重启浏览器;
  5. 对公开环境,根据官方说明加入 Chrome 149 起的 Origin Trial。

代码必须做能力检测:

function supportsWebMCP(): boolean {
return "modelContext" in document;
}

if (!supportsWebMCP()) {
// 保留原有 UI,WebMCP 只是渐进增强。
console.info("WebMCP is not available in this browser.");
}

TypeScript 项目可以使用 Chrome 文档推荐的 webmcp-types 类型包,但仍应把运行时能力检测作为真实边界。

10.2 先选择一个高价值、低风险任务​

第一版不要暴露整个产品。优先选择:

  • 任务步骤多、Agent 容易点错;
  • 结果可见;
  • 失败可恢复;
  • 副作用低;
  • 业务逻辑已有可靠 API;
  • 成功标准容易测量。

例如先做 filter_orders,再做 prepare_refund,最后才考虑 submit_refund。

10.3 建立工具契约​

在写代码前完成一张契约表:

项目示例
用户目标查找最近 30 天未送达订单
工具名find_undelivered_orders
使用条件用户已登录且位于订单页
参数timeframe、可选 carrier
副作用无
数据来源当前账户订单 API
返回订单 ID、状态、预计送达时间
隐私不返回完整地址与支付信息
失败码UNAUTHENTICATED、RATE_LIMITED
成功指标正确选工具、正确参数、结果与 UI 一致

10.4 复用业务逻辑,而不是复制一份​

推荐:

async function findUndeliveredOrders(input, signal) {
// UI 和 WebMCP 共用这一层。
return orderService.search({
...input,
status: "undelivered",
signal
});
}

不推荐让 execute 直接拼接未经验证的 URL、操作 DOM 私有细节或绕过 UI 所使用的权限层。两条实现路径迟早会产生校验差异。

10.5 建立三类测试​

确定性测试​

  • Schema 是否有效;
  • 合法参数是否得到预期结果;
  • 非法枚举是否被拒绝;
  • 未登录、越权、限流如何响应;
  • 重复幂等键是否只产生一次副作用;
  • AbortSignal 是否传递到耗时操作;
  • 工具何时注册和注销;
  • 页面状态是否与返回值一致。

Agent Evals​

生成式 Agent 的结果具有概率性,需要测试:

  • 用户表达目标后是否选择正确工具;
  • 相似工具并存时是否混淆;
  • 是否生成正确参数;
  • 缺少必要信息时是否向用户询问;
  • 高风险动作是否先确认;
  • 工具失败后是否使用返回信息恢复;
  • 不该调用工具时是否保持不调用;
  • 多工具任务能否完成完整用户旅程。

不要只测一句“标准提示词”。应覆盖口语、歧义、输入缺失、恶意页面内容和重复调用。

端到端人工验证​

在浅色/深色、移动/桌面、不同语言和不同登录状态下,检查:

  • Agent 填写区域是否可见;
  • 用户能否修改和取消;
  • 错误信息是否同时对人和 Agent 清楚;
  • 页面导航后旧工具是否消失;
  • 重新进入页面后状态能否正确恢复。

10.6 调试工具​

Chrome 官方推荐使用 Model Context Tool Inspector Extension 查看注册工具、Schema、手动执行与结果。Chrome 149 DevTools 的 Application 面板也加入了实验性 WebMCP 调试能力。

调试时至少记录:

页面状态
→ 当前工具目录
→ Agent 选择
→ 输入参数
→ 用户确认
→ 执行耗时
→ 结果 / 错误码
→ UI 最终状态

只有“最终任务失败”一条日志,无法区分是工具发现、模型选择、参数、浏览器权限还是业务逻辑出了问题。


十一、WebMCP Challenge 带来的产品启示​

OpenAI WebMCP Challenge 将重点放在“人与 Agent 一起使用时,产品是否明显变得更好”,而不是“给现有按钮批量包一层工具”。

官方给出的启发方向包括:

  • 人与 Agent 共同创建和修改 3D 模型;
  • 在共享文档中协作写作、评论和回应;
  • 根据主题生成并继续调整填字游戏;
  • 把旅行笔记变成行程,再通过评论共同塑形;
  • 在浏览器内使用 DuckDB-Wasm 查询、组合数据并生成可视化。

这些例子有一个共同点:

WebMCP 最有价值的地方不是替人点得更快,而是让人负责目标、审美和判断,让 Agent 负责结构化操作与繁琐转换,并让双方始终共享可见状态。

按当前活动页,挑战于 2026-08-25 12:00 PT 开放,提交截止为 2026-09-03 13:00 PT,计划于 9 月 23 日公布结果。可在原生支持 WebMCP 的 ChatGPT 内置浏览器中测试,也可使用开启实验 Flag 或参加 Origin Trial 的 Chrome。活动信息可能调整,提交前应以官方页面和 Devpost 规则为准。


十二、常见误区​

误区 1:有了 WebMCP,就不需要无障碍和语义 HTML​

错。人类、搜索引擎、辅助技术和没有 WebMCP 的 Agent 仍需要语义 Web。声明式 API 本身也依赖 label、表单控件和有效 HTML。

误区 2:把所有后端 API 都注册成页面工具​

错。工具应围绕当前用户旅程和页面状态组织,而不是机械复制 OpenAPI。过多工具会消耗上下文并增加选择冲突。

误区 3:readOnlyHint: true 就代表安全​

错。只读工具也可能泄露私人订单、联系人或浏览历史;Hint 不是强制权限。

误区 4:JSON Schema 会替服务端完成验证​

错。Schema 帮助 Agent 构造结构,并可能被实现用于基础校验;真正的身份、授权、业务约束必须由服务端执行。

误区 5:工具调用成功,任务就完成了​

错。返回成功、服务端状态和页面可见状态必须一致。Agent 还需要把结果准确解释给用户。

误区 6:WebMCP 会取代 MCP​

错。MCP 适合跨平台、持久、后台能力;WebMCP 适合当前标签页中的实时人机协作。成熟产品很可能同时使用两者。


十三、上线检查清单​

产品​

  • 工具解决的是高价值用户任务,而不是只展示技术;
  • 人类与 Agent 使用同一份页面状态;
  • Agent 的操作对用户可见、可理解;
  • 高影响动作有明确确认与恢复路径。

工具设计​

  • 工具名准确表达副作用;
  • 工具之间职责单一且不重叠;
  • Schema 只收集必要参数;
  • 工具随页面状态正确注册和注销;
  • 返回值短、结构化、包含稳定错误码。

安全​

  • 使用安全上下文和正确的 Origin Isolation;
  • 检查 tools Permissions Policy;
  • exposedTo 只包含可信安全 Origin;
  • 正确设置 readOnlyHint 与 untrustedContentHint;
  • 服务端执行认证、对象级授权、幂等、限流和审计;
  • 测试工具描述、输入和输出中的提示注入;
  • 敏感数据不会因过度参数化而被 Agent 带入。

可靠性​

  • 能力检测失败时原有 UI 仍完整可用;
  • 取消信号能传递到耗时操作;
  • 页面跳转和组件卸载不会留下失效工具;
  • 重试不会创建重复订单或重复提交;
  • 确定性测试、Agent Evals 和人工 E2E 都已覆盖。

十四、未来会往哪里演进?​

当前规范仍有多项开放问题:

  • 多模态输入输出与二进制媒体;
  • 流式工具参数和流式结果;
  • 输出 Schema 与原生输入/输出校验;
  • 长任务进度;
  • 跨文档导航后的工具结果;
  • 用户确认与 requestUserInteraction();
  • Service Worker 中的后台发现与调用;
  • 多工具组合成更高层 Skill。

这意味着现在最稳妥的投资不是绑定某个实验性细节,而是先把应用能力整理成:

  1. 清晰的动作边界;
  2. 可验证的结构化输入;
  3. 可审计的结构化结果;
  4. 与 UI 共享的状态模型;
  5. 可靠的授权、幂等和回滚机制。

即使 API 形态继续变化,这些工程资产仍然有价值。


总结​

WebMCP 真正解决的不是“Agent 不会点击”,而是:

今天的网站只把意图画给人看,却没有把意图明确告诉 Agent。

它通过页面注册、浏览器中介、结构化 Schema 和当前 Document 状态,把脆弱的视觉操作转化为明确的能力调用,同时保留用户可见、可参与的 Web UI。

判断一个功能是否适合 WebMCP,可以问四个问题:

  1. 它是否依赖当前标签页、登录会话或实时 UI 状态?
  2. 它是否因为多步点击或字段语义而经常让 Agent 失败?
  3. 用户是否需要看到、修改或确认 Agent 的操作?
  4. 页面是否已有可靠、可复用的业务逻辑?

如果大多回答“是”,WebMCP 很可能是合适的增强层;如果任务需要脱离页面长期运行、跨平台复用或大规模后台处理,应优先考虑 MCP 或服务端 API。

最终形态不会是“Agent 取代网页”,而更可能是:

语义 HTML 服务所有用户
+
WebMCP 服务实时人机协作
+
MCP / API 服务跨平台后台能力

这三层共同构成 Agent 原生 Web。


官方资料​

Logo
RainLib

探索技术、设计与分布式系统的边界。构建面向未来的开发者工具。

留言与建议

© 2026 RainLib. 为未来构建。(Built for the Future)
版权所有。
系统正常