跳到主要内容

WebMCP — 跨源、权限策略与事件

本章讲三件相互咬合的事:谁被允许用这套 API(权限策略)、一个文档的工具能被谁看见(exposedTo 跨源授权)、以及工具变化/被观察时发生什么(toolchange 事件 + observation 快照)。

1. 第一道门:tools 权限策略

WebMCP 这套 API 整个被一个权限受控特性(policy-controlled feature) tools 守着,其默认允许列表是 'self'(index.bs:613-617)。

含义:

  • 顶层文档和它的同源 iframe 默认能用。
  • 跨源 iframe 默认不能用,除非显式委派。

委派方式是标准的 Permissions Policy 写法(README.md:318-322):

<iframe src="https://chat-bot-provider.example/" allow="tools"></iframe>

权限被关时(无论因 allow 没给还是 Permissions-Policy: tools=() 头),registerTool() 返回的 promise 会 reject 一个 NotAllowedError(README.md:324)。这正是 §01 登记算法第 3 步的落点(index.bs:351-352)。

2. 默认可见范围:工具默认只给自己人

一个文档登记的工具,默认只暴露给三类对象(README.md:328):它自己、同一棵树里的同源文档、以及浏览器内置 agent。要让别的源看到,得用 exposedTo

这套「谁能看见」的判定由一个小算法 tool is visible to an origin 精确定义(index.bs:237-249):

// index.bs:237-247(逻辑复述,# 示意)
# 给定:工具属主源、exposed origins 列表、目标源
1. 属主源 与 目标源 同源 → 可见(返回 true)
2. 遍历 exposed origins:有任一与目标源同源 → 可见
3. 否则 → 不可见

一句话:默认同源可见;额外可见的源必须显式列进 exposedTo

3. 跨源授权:exposedTo

要把工具分享给指定的可信源(典型场景:页面里嵌了一个第三方 agent 的 iframe),登记时传 exposedTo(README.md:326-342):

// README.md:331-336
await document.modelContext.registerTool({
name: "share-location",
description: "Returns the user's office location.",
execute() { return { office: "Building 4" }; }
}, { exposedTo: ["https://trusted-partner.example"] });

登记算法对 exposedTo 的每个源做两道校验(§01 第 10 步,index.bs:415-425):URL 解析必须成功,且源必须 potentially trustworthy(安全源);任一不满足就 reject SecurityError。通过的源被存进该工具定义的 exposed origins(index.bs:180-181)。

被授权且持有 tools 权限的文档将能(README.md:338-342):收到 toolchange 事件、发现并运行这些工具。

这服务于 README 强调的**「作者自带的 agent」(author-provided agent)**场景——不止浏览器内置 agent,页面里或 iframe 里嵌的 agent 也能协作(README.md:309-316)。

4. 变更通知:toolchange 事件

工具增删时,怎么让关心它的文档知道?靠 notify documents of a tool change 算法(index.bs:186-235):

// index.bs:192-206(逻辑复述,# 示意)
# 给定:工具属主文档、exposed origins
1. 找到属主所在 traversable 的所有后代 navigable
2. 对每个目标文档:
- 不允许用 tools 特性 → 跳过
- 若「工具对该源可见」(用 §2 算法判断):
在 webmcp task source 上排任务,
向该文档的 ModelContext fire 一个 toolchange 事件

注意它遍历整棵树的后代文档并逐一用可见性算法过滤——这就是 exposedTo 让别的源「收到 toolchange」的实现机制。toolchangeModelContext 上唯一的标准事件,对应 ontoolchange handler(index.bs:597-611)。

5. 一个反直觉的时序坑

登记和通知都跑在 in parallel 上,且 toolchange 走的是专门的 webmcp task source(index.bs:619-632)。规范专门举例警告时序不可依赖(index.bs:208-233):

// index.bs:213-232(节选)
document.modelContext.ontoolchange = e => console.log('Parent toolchange');
iframe.contentDocument.modelContext.ontoolchange = e => console.log('Child toolchange');
const p = document.modelContext.registerTool({ name:"tool_name", description:"d", execute: async()=>{} });
p.then(() => console.log('Register promise resolved'));
setTimeout(() => console.log('Post-register task'));

规范保证(index.bs:229-231):

  • Parent toolchange 总在 Child toolchange 之前。
  • Register promise resolved 总在两者之后。
  • Post-register task(setTimeout,走 timer task source)可能落在三者之前、之间、之后任意位置。

重点:toolchange 事件与 registerTool 的 promise resolve 不在同一任务源,跨任务源的相对顺序不可依赖。写代码别假设 setTimeouttoolchange 谁先谁后。

6. 浏览器 agent 怎么「看」工具:observation

上面讲的是页面内 JS agent——它直接用 ModelContext API 就能看见工具。但浏览器内置 agent 不在页面里跑 JS(index.bs:646-647)。它靠拿一份 observation(观察快照)

observation 是一个实现自定义的数据结构,至少含一个 tool map:键是各文档的 unique ID,值是该文档的工具定义列表(index.bs:648-651)。它通常还包含截图、部分可访问性树等(index.bs:653-656683-685)。

生成它的算法是 perform an observation(index.bs:660-701):遍历 traversable 的所有后代文档,把每个文档的 tool map 收进 observation,再加任何实现觉得有用的东西(截图等),最后用任意它接受的格式喂给浏览器 agent。

两个关键设计点:

  • 不规定暴露格式。 规范明说:尽管名字带 MCP,但它不规定工具以什么格式给到浏览器 agent——可以是 MCP、专有 function-calling、或任何方式(index.bs:691-694)。WebMCP 标准化的是「页面如何登记」,不是「浏览器如何转述给模型」。
  • 建议带上安全信息。 规范用 Advisement 提醒实现:要把工具的来源 origin 等安全信息一并传给浏览器 agent,让模型知道「场上有哪些方」、能更安全地执行用户意图(index.bs:696-699)。

何时拍快照是实现自定义的,但通常保留在「用户正与浏览器 agent 交互且网页在视野中」时(index.bs:706-710)。

7. 边界与局限

  • 同源边界违规一节还是 TODO。 「agent 把一个源的状态带到另一个源」的风险,规范里只有一个红色 TODO 占位(index.bs:1065-1069)。
  • getTools()/executeTool() 未定。 文档如何对 JS 暴露发现/调用接口,README 标 TODO(README.md:344-345)。

8. 代码地图

主题文件符号 / 锚点
tools 权限特性index.bs:613-617tools(policy-controlled feature)
iframe 委派README.md:318-324allow="tools"
可见性判定index.bs:237-249tool is visible to an origin
exposedTo 用法README.md:326-342exposedTo
exposedTo 校验index.bs:415-425registerTool 第 10 步
变更通知index.bs:186-235notify documents of a tool change
任务源时序index.bs:208-233619-632webmcp task sourcenotify-task-ordering
观察快照index.bs:634-701observationperform an observation