跳到主要内容

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 APIdocument.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、exposedTofromOrigins 等条件决定工具是否可见、是否可调用。跨 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.modelContextprovideContext()。当前规范与 Chrome 文档使用 document.modelContextregisterTool()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、控件类型、requiredoptionlabeltoolparamdescription 生成 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>

页面还可以监听 toolactivatedtoolcancel,并用 :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_diagnosticsexport_current_viewexplain_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、状态、预计送达时间
隐私不返回完整地址与支付信息
失败码UNAUTHENTICATEDRATE_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;
  • 正确设置 readOnlyHintuntrustedContentHint
  • 服务端执行认证、对象级授权、幂等、限流和审计;
  • 测试工具描述、输入和输出中的提示注入;
  • 敏感数据不会因过度参数化而被 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)
版权所有。
系统正常