ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Puppeteer 中的 WebMCP 类:通过 page.webmcp 发现与调用页面暴露的 Agent 工具

Puppeteer 中的 WebMCP 类:通过 page.webmcp 发现与调用页面暴露的 Agent 工具 Puppeteer 中的 WebMCP 类通过 page.webmcp 发现与调用页面暴露的 Agent 工具【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteerWebMCP 是 Puppeteer 中一处尚处于实验阶段的 API 面它让 Node.js 侧的脚本能够发现当前页面中注册的工具tools并监听工具的注册、移除与调用事件。读完本文你将掌握page.webmcp的接入前提、WebMCP类的四个核心事件与tools()方法的使用方式以及与之配套的WebMCPTool、WebMCPToolCall等类型的字段语义并能在真实页面中驱动一次完整的工具调用。本文以 WebMCP 类 API 文档 为主体展开结合 Puppeteer 仓库中 CDP 层实现 与 测试用例 进行源码级印证。WebMCP 类概览页面工具与自动化端的桥梁WebMCP类是 Puppeteer 对 WebMCPWeb Model Context Protocol能力在页面侧的封装。按照 API 索引 的定位它provides an API for the WebMCP API——即让自动化代码访问页面定义的 WebMCP 工具。从 类签名文档 可以看到它的完整声明export declare class WebMCP extends EventEmitter{ toolsadded: WebMCPToolsAddedEvent; toolsremoved: WebMCPToolsRemovedEvent; toolinvoked: WebMCPToolCall; toolresponded: WebMCPToolCallResult; }它继承自 EventEmitter并把四类事件类型参数化到泛型中。在实际源码里对应的类定义位于 packages/puppeteer-core/src/cdp/WebMCP.ts#L255-L264内部持有CDPSession、FrameManager以及用于缓存工具、追踪进行中调用的几个Map字段export class WebMCP extends EventEmitter{ toolsadded: WebMCPToolsAddedEvent; toolsremoved: WebMCPToolsRemovedEvent; toolinvoked: WebMCPToolCall; toolresponded: WebMCPToolCallResult; } { #client: CDPSession; #frameManager: FrameManager; #tools new Mapstring, Mapstring, WebMCPTool(); #pendingCalls new Mapstring, WebMCPToolCall(); #subscriptions new DisposableStack(); // ... }从源码结构看WebMCP 是典型的 CDP 驱动实现initialize()时向浏览器发送WebMCP.enable命令WebMCP.ts#L371-L375随后把WebMCP.toolsAdded、WebMCP.toolsRemoved、WebMCP.toolInvoked、WebMCP.toolResponded四条 CDP 事件通过 DisposableStack 订阅并翻译成上面的四个 EventEmitter 事件。访问入口page.webmcp 与其环境前提WebMCP实例不需要也不能由第三方代码直接构造——文档的 Remarks 明确说明The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend theWebMCPclass.在 API 文档中它属于公开类型public但用experimental标注见 WebMCP.ts 源码注释构造器仅供 Puppeteer 内部使用。应用侧统一通过Page上的webmcp属性访问。这一抽象 getter 定义在 Page.ts#L1004-L1010/** * Experimental API for WebMCP. * Requires Chrome 151 with the --enable-featuresWebMCP flag enabled. * experimental */ abstract get webmcp(): WebMCP;对应的 page.webmcp 属性文档 也给出了两个关键限制这两点是实际运行前必须满足的前提浏览器版本需要 Chrome 151 及以上的版本启动参数必须以--enable-featuresWebMCP启动 Chromium。测试代码正是这样配置的。在 webmcp.test.ts#L20-L24 中整个测试套件通过setupSeparateTestBrowserHooks为浏览器注入args: [--enable-featuresWebMCP]describe(Page.webmcp, function () { const state setupSeparateTestBrowserHooks({ args: [--enable-featuresWebMCP], acceptInsecureCerts: true, });因此在你的代码里启动浏览器时需要类似写法import puppeteer from puppeteer; const browser await puppeteer.launch({ headless: true, args: [--enable-featuresWebMCP], }); const page await browser.newPage();如果使用了 Puppeteer 的connect连接远端浏览器同样需要确保远端 Chrome 版本 ≥ 151 且以该特性开关启动。由于目前是实验特性后续版本中 API 形态可能变化建议在使用时固定 Puppeteer 版本。枚举页面工具tools() 方法WebMCP目前对外暴露的唯一方法就是tools()。其签名与返回类型见 WebMCP.tools() 方法文档class WebMCP { tools(): WebMCPTool[]; }它返回页面上全部已注册的 WebMCP 工具数组每个元素是一个 WebMCPTool 实例。底层实现是对内部两级MapframeId → 工具名 → 工具做扁平化WebMCP.ts#L404-L411。原文档给出了最典型的用法——页面加载完成后枚举工具并打印其名称与描述示例await page.goto(https://www.example.com); const tools page.webmcp.tools(); for (const tool of tools) { console.log(Tool found: ${tool.name} - ${tool.description}); }在 测试用例 中可以看到tools()返回结果的完整断言当页面分别通过命令式注册调用document.modelContext.registerTool与声明式声明往 DOM 中追加带toolname/tooldescription属性的form两种方式暴露工具后page.webmcp.tools()会返回两条工具记录其name、description、inputSchema、annotations、frame、formElement、location等字段会被逐一校验。需要留意的生命周期语义结合测试可以发现两个与工具集合管理直接相关的边界行为整页导航会清空工具toolsremoved事件在 frame 上下文销毁时被触发源码见 onContextDisposed测试 should remove tools on frame navigation 验证了 reload 后tools()长度回到 0同文档导航hash 跳转不会清空工具上下文未被销毁工具集合保持不变测试用例 L363-L387。事件体系toolsadded / toolsremoved / toolinvoked / toolrespondedWebMCP 是一套事件驱动模型四项事件分别对应工具上架、工具下架、工具被调用、调用有结果四个阶段。原文档通过类签名声明了这四个事件测试用例则逐个验证了它们的触发时机与载荷。事件载荷类型触发时机对应文档toolsaddedWebMCPToolsAddedEvent{tools: WebMCPTool[]}页面注册了新的工具源码toolsremovedWebMCPToolsRemovedEvent{tools: WebMCPTool[]}页面移除工具或所在 frame 被销毁源码toolinvokedWebMCPToolCall页面侧发起一次工具调用源码toolrespondedWebMCPToolCallResult工具调用完成、失败或被取消源码监听方式与 EventEmitter 完全一致例如在 toolinvoked 事件测试 中所示const tools page.webmcp.tools(); page.webmcp.on(toolsadded, event { console.log(added, event.tools.map(t t.name)); }); page.webmcp.on(toolsremoved, event { console.log(removed, event.tools.map(t t.name)); }); page.webmcp.on(toolinvoked, call { console.log(invoked, call.tool.name, call.input); }); page.webmcp.on(toolresponded, response { console.log(responded, response.id, response.status, response.output); });注意同一把事件也会穿透到具体工具上WebMCPTool本身也继承EventEmitter{toolinvoked: WebMCPToolCall}声明见 docs/api/puppeteer.webmcptool.md因此既可以page.webmcp.on(toolinvoked, ...)全局监听也可以tool.once(toolinvoked, ...)针对某个工具监听测试中两种方式都被使用见 test L419-L425。WebMCPTool单个工具的对象化表示tools()返回的每个 WebMCPTool 是一个 EventEmitter 子类把页面暴露的工具元数据完整地对象化。其公开属性如下属性类型说明namestring工具名称descriptionstring工具描述inputSchema可选object工具输入参数对应的 JSON Schemaannotations可选Protocol.WebMCP.Annotation工具的可选标注如只读提示、不可信内容提示frameFrame该工具被定义所在的 framelocation可选ConsoleMessageLocation定义工具的源码位置若可用formElement只读PromiseElementHandleHTMLFormElement \| undefined工具若通过form声明式注册则对应其表单元素句柄rawStackTraceProtocol.Runtime.StackTrace内部字段原始调用栈对应实现见 WebMCP.ts#L26-L132。其中location是从工具注册时的stackTrace首帧解析而来L75-L82所以命令式注册的工具通常能拿到定义位置而声明式纯 HTML注册的工具该项为空——测试断言也印证了这一差异。formElement属于懒加载属性只有当工具经由表单注册携带 backendNodeId时才有值否则返回undefined有值时它会把 backend node 采纳为主世界中的 ElementHandle实现见 L88-L103。发起调用execute() 与工具调用结果虽然页面侧的工具通常由页面自己的逻辑或页面内的 agent来触发WebMCPTool也提供了从自动化侧主动调用工具的方法。签名见 WebMCPTool.execute() 方法文档class WebMCPTool { execute( input?: object, options?: WebMCPToolExecuteOptions, ): PromiseWebMCPToolCallResult; }input调用参数对象需与工具的inputSchema匹配options可传{signal: AbortSignal}类型定义见 WebMCPToolExecuteOptions用于取消仍在执行的调用。其内部流程WebMCP.ts#L108-L131分两步先经invokeTool()发送 CDP 命令WebMCP.invokeTool携带frameId、toolName与input见 L380-L389拿到invocationId随后挂起等待toolresponded事件中与invocationId匹配的结果若传入的AbortSignal被触发则回退到WebMCP.cancelInvocationCDP 命令请求取消。返回的 WebMCPToolCallResult 字段如下字段类型说明idstring调用标识与WebMCPToolCall.id对应call可选WebMCPToolCall本次调用对应的调用对象若在 pending 表中可找到statusProtocol.WebMCP.InvocationStatus调用状态output可选any结果输出仅当status为Completed时存在errorText可选string错误文本exception可选Protocol.Runtime.RemoteObject若工具内 JS 抛异常则为对应的异常远程对象用 execute() 驱动一次完整调用结合 should invoke tool 测试完整流程如下// 页面内提前注册工具命令式 WebMCP 工具 await page.evaluate(async () { await document.modelContext?.registerTool({ name: test-tool-1, description: A test tool 1, inputSchema: { type: object, properties: {text: {type: string, description: Some text}}, required: [text], }, execute: (params: {text: string}) { return hello ${params.text}; }, }); }); // 等待工具被发现 await new Promise(resolve { page.webmcp.once(toolsadded, resolve); }); // 自动化侧直接调用 const [tool] page.webmcp.tools(); const response await tool!.execute({text: world}); console.log(response.status); // Completed console.log(response.output); // hello worldstatus 的三种状态从测试中可以归纳出status的取值语义它们与工具本身的执行结果一一对应Completed工具成功返回output携带结果测试 L462-L512Error工具内部抛出了 JS 异常此时exception.description含错误信息errorText为空字符串或输入参数解析失败如传入非法 JSON此时errorText为Failed to parse input arguments参见 L514-L602Canceled调用通过 AbortSignal 被取消L653-L767。取消既可以在调用中途执行controller.abort()在调用已经开始后才触发也可以在调用前就把 signal 置为已中止——两种情况下结果状态都是Canceledconst controller new AbortController(); const executePromise tool!.execute({text: world}, {signal: controller.signal}); // …一段时间后决定取消 controller.abort(); const response await executePromise; // status Canceled从事件到调用的完整协作视图把上面各节串起来一次 WebMCP 交互的生命周期是页面脚本调用document.modelContext.registerTool(...)或向 DOM 追加带toolname的form注册工具浏览器发出WebMCP.toolsAddedPuppeteer 包装成toolsadded事件并更新内部工具表之后page.webmcp.tools()可枚举到该工具页面或自动化侧调用tool.execute()发起调用toolinvoked事件先于结果到达携带 WebMCPToolCall含id、tool、input工具执行完成/出错/被取消后toolresponded事件携带 WebMCPToolCallResult 到达其id与对应的WebMCPToolCall.id一致若用户导航离开或重新加载页面frame 上下文销毁触发toolsremoved并清空待处理调用表源码见 onContextDisposed。在 webmcp.test.ts 中should fire toolinvoked events、should fire toolresponded event with success / with exception / with errorText、should invoke tool、should cancel tool execution等一系列用例完整覆盖了上述链路是理解该实验特性最直观的可运行参考。小结page.webmcp为 Puppeteer 提供了一块访问页面声明的 WebMCP 工具的实验性入口。核心使用要点可归纳为环境Chrome 151且启动时携带--enable-featuresWebMCP发现page.webmcp.tools()枚举当前页面全部工具得到 WebMCPTool 数组订阅监听toolsadded/toolsremoved跟踪工具上/下架监听toolinvoked/toolresponded跟踪调用过程执行与取消tool.execute(input, {signal})从自动化侧主动调用结果含Completed/Error/Canceled三种状态。由于该特性仍处于实验阶段构造器内部化、API 标注experimental使用时请以 docs/api/puppeteer.webmcp.md 及 Page.webmcp 属性文档 为基准并及时跟进新版本 Puppeteer 的 CHANGELOG 以应对可能的接口调整。【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表