BroSDK MCP 使用教程

browsersdk
browsersdk
Lv.0
本文面向需要通过 AI Agent、MCP Inspector 或自研 MCP 客户端操作 BroSDK 浏览器环境的开发者。目标是从一个已经启动的 BroSDK 环境出发,完成连接、 页面观察、点击输入、结果确认、截图和会话清理。 本文使用当前公开的单环境 MCP endpoint: ```text http://127.0.0.1:{sdkPort}/sdk/v1/mcp/env/{envId} ``` ## 1. BroSDK MCP 是什么 BroSDK MCP 把一个正在运行的指纹浏览器环境暴露为 MCP Streamable HTTP 服务。每个 endpoint 只操作路径中指定的 `envId`,不会跨环境选择页面。 主要能力分成两层: 1. 页面自动化层:通过 BroSDK 已有 CDP 连接完成页面发现、AX snapshot、 原生鼠标键盘输入、截图、PDF、上传和下载。 2. 浏览器 UI/Profile 层:通过可选的 BroSDK MCP Bridge 扩展完成窗口、标签 排序、标签组、书签、历史和统一浏览器状态管理。 扩展不是基础页面操作的前置条件。未安装扩展时,Agent 仍可以导航、观察、 点击、输入、滚动、拖动、截图和打印 PDF。 ## 2. 使用前准备 连接 MCP 前应满足以下条件: - BroSDK 已完成初始化,并启动本地 HTTP 服务。 - 目标 `envId` 的浏览器已经启动且 CDP 已就绪。 - MCP 客户端运行在用户本机,并能访问 `127.0.0.1:{sdkPort}`。 - 如需窗口、书签、历史或标签组能力,启动环境时已经加载 Bridge 扩展。 本文示例使用: ```powershell $SdkPort = 65535 $EnvId = "2063816419455275008" $McpUrl = "http://127.0.0.1:$SdkPort/sdk/v1/mcp/env/$EnvId" ``` 请将端口和环境 ID 替换为当前 BroSDK 实例的实际值。 ### 2.1 健康检查 先确认 endpoint 存在: ```powershell Invoke-RestMethod "$McpUrl/health" ``` 正常结果类似: ```json { "ok": true, "server": "brosdk-mcp", "envId": "2063816419455275008", "transport": "streamable-http", "sessionTtlMs": 43200000, "toolCount": 18 } ``` `toolCount` 可能因构建开关而变化,应以当前响应和 `tools/list` 为准。 ## 3. 使用 MCP Inspector 或 Agent 客户端连接 在支持 Streamable HTTP 的 MCP 客户端中新增 server: ```text Transport: Streamable HTTP URL: http://127.0.0.1:{sdkPort}/sdk/v1/mcp/env/{envId} ``` 不同 MCP 客户端的配置文件格式并不统一。等价的概念配置如下: ```json { "mcpServers": { "brosdk-current-env": { "transport": "streamable-http", "url": "http://127.0.0.1:65535/sdk/v1/mcp/env/2063816419455275008" } } } ``` 连接成功后应先检查: 1. `tools/list` 能列出 `tabs`、`snapshot`、`act` 等公开工具。 2. 调用 `tabs` 的 `list` action 能返回至少一个 `page`。 3. 调用 `snapshot` 能返回 AX tree,而不是 `BROWSER_NOT_READY`。 不要把下面的地址配置给 MCP 客户端: ```text http://mcp.brosdk.internal ``` 它是 Bridge 扩展在浏览器内部访问的专用主机,不是 Agent 的 MCP endpoint。 普通页面或错误的扩展上下文直接访问它可能得到 `403 Forbidden`。 ## 4. 直接调用 Streamable HTTP 一般 MCP 客户端会自动管理 session。自研客户端需要严格执行初始化握手。 ### 4.1 Initialize ```powershell $BaseHeaders = @{ Accept = "application/json, text/event-stream" "Content-Type" = "application/json" } $InitializeBody = @{ jsonrpc = "2.0" id = 1 method = "initialize" params = @{ protocolVersion = "2025-06-18" capabilities = @{} clientInfo = @{ name = "brosdk-tutorial" version = "1.0.0" } } } | ConvertTo-Json -Depth 10 -Compress $Initialize = Invoke-WebRequest ` -Method Post ` -Uri $McpUrl ` -Headers $BaseHeaders ` -Body $InitializeBody $SessionId = [string]$Initialize.Headers["Mcp-Session-Id"] $ProtocolVersion = [string]$Initialize.Headers["Mcp-Protocol-Version"] ``` 后续请求必须同时携带服务端返回的两个 header: ```powershell $SessionHeaders = @{ Accept = "application/json, text/event-stream" "Content-Type" = "application/json" "Mcp-Session-Id" = $SessionId "Mcp-Protocol-Version" = $ProtocolVersion } ``` 不要在新的 `initialize` 请求中复用旧 `Mcp-Session-Id`。 ### 4.2 发送 initialized notification ```powershell $InitializedBody = @{ jsonrpc = "2.0" method = "notifications/initialized" params = @{} } | ConvertTo-Json -Depth 5 -Compress Invoke-WebRequest ` -Method Post ` -Uri $McpUrl ` -Headers $SessionHeaders ` -Body $InitializedBody ``` 该 notification 成功时返回 HTTP `202`,响应体为空。 ### 4.3 封装 JSON-RPC 调用 ```powershell function Invoke-BroSdkMcp { param( [int]$Id, [string]$Method, [hashtable]$Params = @{} ) $Body = @{ jsonrpc = "2.0" id = $Id method = $Method params = $Params } | ConvertTo-Json -Depth 30 -Compress Invoke-RestMethod ` -Method Post ` -Uri $McpUrl ` -Headers $SessionHeaders ` -Body $Body } $Tools = Invoke-BroSdkMcp 2 "tools/list" $Tools.result.tools | Select-Object name, description ``` 调用 tool 时,tool 名放在 `params.name`,输入放在 `params.arguments`: ```powershell $Tabs = Invoke-BroSdkMcp 3 "tools/call" @{ name = "tabs" arguments = @{ action = "list" } } $Tabs.result.structuredContent.pages ``` ## 5. 第一个完整自动化任务 下面以“打开页面、查找按钮、点击并验证结果”为例。 ### 5.1 获取 page ```json { "name": "tabs", "arguments": { "action": "list" } } ``` 返回的 `page` 是 BroSDK 公共页面句柄,例如: ```json { "action": "list", "pages": [ { "page": 7, "url": "https://example.test/", "title": "Example", "active": true, "stateSource": "cdp", "stateFresh": false } ], "count": 1 } ``` 后续只使用 `page: 7`,不要向 Agent 暴露或保存 CDP `targetId`、Chrome `tabId` 或内部 CDP session ID。 ### 5.2 获取 snapshot ```json { "name": "snapshot", "arguments": { "page": 7 } } ``` `snapshot` 默认使用 CDP Accessibility Tree,并给可操作节点分配稳定 `ref`: ```text [ref=e12] button "Submit" [ref=e13] textbox "Email" ``` 只有 AX tree 无法提供目标元素时,才按需启用只读 DOM fallback: ```json { "name": "snapshot", "arguments": { "page": 7, "domFallback": true } } ``` ### 5.3 输入和点击 填写输入框: ```json { "name": "act", "arguments": { "page": 7, "kind": "fill", "ref": "e13", "value": "user@example.com" } } ``` 点击按钮: ```json { "name": "act", "arguments": { "page": 7, "kind": "click", "ref": "e12" } } ``` 鼠标和键盘动作使用原生 CDP 输入。`inputMode: "cdp"` 只能证明输入已分发, 不能单独证明业务操作成功。 ### 5.4 验证结果 优先检查 `act` 返回的 `autoDiff`。如果页面异步更新,再等待明确条件: ```json { "name": "wait", "arguments": { "page": 7, "for": "text", "value": "Saved", "timeout": 10000 } } ``` 也可以用 `grep` 做低成本检查: ```json { "name": "grep", "arguments": { "page": 7, "pattern": "Saved", "over": "content", "limit": 20 } } ``` 页面导航、刷新或 document 被替换后,应丢弃旧 ref 并重新 `snapshot`。 ## 6. 推荐的 Agent 工作流 稳定的页面任务应遵循“观察、动作、验证”循环: ```text tabs(list/current) -> snapshot(page) -> act(page, ref/kind) -> 检查 autoDiff -> 必要时 wait/grep/diff -> 页面大改或导航后重新 snapshot ``` 选择观察工具时从轻到重: | 目的 | 首选 tool | |------|-----------| | 查找少量文字或控件 | `grep` | | 获取可操作控件和 ref | `snapshot` | | 提取正文 | `read` | | 理解 Canvas、图表、视觉布局 | `screenshot` | | 归档打印页面 | `pdf` | | 读取 AX/正文都没有的小段页面状态 | `evaluate` | 不要在每个动作后固定等待若干秒。优先使用 `autoDiff`、文本、selector、URL、 下载完成或新 page 等可验证条件。 ## 7. 常用 tools 当前默认公开工具可按用途分组: | 类别 | Tools | 用途 | |------|-------|------| | 浏览器空间 | `browser_state`, `tabs`, `tab_groups`, `windows` | 页面、窗口和标签组管理 | | Profile 数据 | `bookmarks`, `history` | 书签和历史记录 | | 页面观察 | `snapshot`, `diff`, `read`, `grep`, `screenshot`, `pdf` | 结构、文本和视觉状态 | | 页面动作 | `navigate`, `act`, `wait`, `evaluate` | 导航、输入和条件等待 | | 文件 | `upload`, `download` | 文件输入和浏览器下载 | `dialogs` 当前默认构建未公开。诊断、legacy tools 和 `cdp.send` 也不属于默认 Agent tool surface,除非宿主显式启用对应环境开关。 ### 7.1 `act` 常用 kind | kind | 主要参数 | 用途 | |------|----------|------| | `click` / `double_click` | `ref` | 单击、双击语义元素 | | `click_at` | `x`, `y` | 点击截图推导出的 viewport 坐标 | | `fill` | `ref`, `value` 或 `fields` | 清空并填写一个或多个字段 | | `type` / `type_at` | `text`,可选 `clear` | 向焦点或坐标输入文本 | | `press` | `key` | Enter、Tab、Escape 或组合键 | | `hover` / `hover_at` | `ref` 或 `x`, `y` | 悬停菜单和提示区域 | | `check` / `uncheck` | `ref` | 设置 checkbox/switch 状态 | | `select` | `ref`, `value` | 选择原生 select option | | `scroll` | 可选 `ref`, `direction`, `amount` | 滚动页面或命中的容器 | | `drag` | `ref`, `targetRef` | 从语义源元素拖到目标元素 | | `drag_at` | 起止坐标,可选 `waypoints` | 滑块、轨迹和视觉拖动 | 复杂拖动应先通过 snapshot 或 screenshot 确定目标。`drag_at` 的坐标属于当前 viewport CSS 坐标,页面滚动或缩放后必须重新观察。 ## 8. Bridge 扩展:何时需要 ### 8.1 无扩展可以完成 - `tabs`: `list`、`current`、`new`、`close`。 - 所有页面级导航、snapshot、文本读取和搜索。 - `act` 的点击、输入、滚动、双击和拖动。 - screenshot、PDF、upload、download、wait 和 evaluate。 ### 8.2 当前需要扩展 - `browser_state`。 - `tabs`: `focus`、`move`、`pin`、`unpin`。 - `windows` 和 `tab_groups`。 - `bookmarks`。 - `history` 的 `recent`、`search`、`delete_url`、`delete_range`。 `history action="open"` 直接使用传入 URL 创建页面,不依赖历史查询能力。 扩展不可用时,依赖扩展的 tool 会返回 `BRIDGE_NOT_READY`。这不是 MCP session 失效;Agent 可继续使用页面级 CDP tools。 ## 8. Page、ref 与 session 这三个身份不要混用: | 身份 | 作用域 | 失效条件 | |------|--------|----------| | `envId` | BroSDK 浏览器环境 | 环境被删除 | | `page` | 同一 env 的页面 | 页面关闭 | | `ref` | 同一 env/page/document 的元素 | 导航、document 替换或元素结构失效 | | `Mcp-Session-Id` | 一次 MCP 客户端连接 | DELETE、TTL 过期或服务重启 | 同一页面在不同 MCP session 中使用相同公共 `page`。同一 document 的稳定 AX 节点也应产生相同 `ref`。底层 CDP attach session、`diff` 基线和 artifact 列表 仍按 MCP session 隔离,避免多个 Agent 相互推进观察状态。 MCP session 默认 TTL 为 12 小时。客户端断线重连通常应重新 initialize,不要 假定旧 session 永远可复用。 任务结束后主动释放 session: ```powershell Invoke-WebRequest ` -Method Delete ` -Uri $McpUrl ` -Headers $SessionHeaders ``` ## 9. Screenshot 与坐标动作 截图调用示例: ```json { "name": "screenshot", "arguments": { "page": 7, "format": "png", "fullPage": false, "size": { "width": 1280, "height": 900 } } } ``` 返回结果除了 artifact,还包含 viewport、pageSize、scroll、remaining 和图片到 CSS viewport 的坐标变换: ```text viewportX = imageX * coordinateScaleX + coordinateOffsetX viewportY = imageY * coordinateScaleY + coordinateOffsetY ``` 全页截图中的目标可能不在当前 viewport。不能直接把全页图片坐标传给 `click_at`;应先滚动到目标区域,再获取当前 viewport 截图或 snapshot。 ## 10. Artifact、PDF 与下载文件 `screenshot` 和 `pdf` 返回 MCP artifact 元数据,而不是承诺一个永久磁盘路径。 artifact: - 只属于创建它的 MCP session。 - 默认 30 分钟过期。 - 可以通过 `resources/read` 读取。 - 也可以使用带 session header 的 HTTP 分块接口读取。 HTTP 分块读取格式: ```text GET /sdk/v1/mcp/env/{envId}/artifacts/{artifactId}?offset=0&limit=1048576 Mcp-Session-Id: ... Mcp-Protocol-Version: ... ``` `download` 与 artifact 不同。它等待浏览器下载完成,并在成功结果中返回实际 本地 `path`、安全 `filename`、`bytes` 和 `state="completed"`。调用方应使用 返回的路径,不猜测系统 Downloads 目录。 ## 11. Prompts 与 Resources ### 11.1 Prompt 服务公开一个可选 prompt: ```text browser-automation ``` 调用示例: ```json { "jsonrpc": "2.0", "id": 20, "method": "prompts/get", "params": { "name": "browser-automation", "arguments": { "task": "打开订单页并读取待处理订单数量" } } } ``` 它提供推荐的观察、动作、验证和安全规则。Agent 不依赖该 prompt 也能使用 tools。 ### 11.2 Resources `resources/list` 默认包含: ```text browser://state ``` 它是 `browser_state action="get"` 的 resource 形式,因此仍需要 Bridge 扩展。 当前 session 创建的 screenshot/PDF 等 artifact 也会出现在 resources 中。 服务当前不实现 Resource Templates。客户端调用 `resources/templates/list` 得到 JSON-RPC `-32601 method not found` 是预期行为,不应把它判定为 MCP 连接失败。 ## 12. 常见错误与处理 | 错误或现象 | 原因 | 处理方式 | |------------|------|----------| | `/extension/health` 返回 403 | 把扩展内部接口当作 MCP endpoint | 改用 `127.0.0.1:{sdkPort}/sdk/v1/mcp/env/{envId}` | | `Mcp-Session-Id is required` | initialize 后请求没有携带 session header | 保存 initialize 响应 header,并在后续请求中携带 | | `Mcp-Protocol-Version is required` | session 请求缺少协商后的版本 | 使用 initialize 响应中的版本,不要自行猜测 | | `BROWSER_NOT_READY` | 环境未运行或 CDP 尚未就绪 | 检查环境状态,等待启动完成后有限重试 | | `BRIDGE_NOT_READY` | 扩展未安装、未连接、状态过期或实例不匹配 | 使用 CDP 可降级能力,或检查扩展是否随当前 env 启动 | | `PAGE_NOT_FOUND` / `NO_ACTIVE_PAGE` | page 已关闭或尚未发现 | 重新调用 `tabs list` | | `REF_NOT_FOUND` / stale ref | 页面导航或 document/元素已变化 | 重新 snapshot 后最多重试一次 | | `REF_FORBIDDEN` | ref 来自其它浏览器环境 | 在目标 env/page 重新观察 | | `TIMEOUT` | 等待条件未在期限内成立 | 先 snapshot/grep 当前状态,不要立即重复动作 | | `resources/templates/list -32601` | 服务没有 Resource Templates | 使用 `resources/list`;忽略 Inspector 中该模板入口 | 同一个动作连续失败两次且页面状态没有变化时,应停止盲目重试,重新观察或向 用户报告阻塞原因。
0 条回复
暂无回复,快来抢沙发吧~
发表回复

登录后可参与讨论