mcpField
K
kimi-webbridge

kimi-webbridge

github.com/mxyhi生产力507205 次安装1 周前更新
代码仓库

关于 kimi-webbridge

kimi-webbridge 是供 Agent 使用的技能,通过本地守护进程操作用户浏览器,包括使用用户登录会话的页面。它提供网页交互与检查工具,并包含将网站调研整理为可复用 CLI 工具或脚本的流程。

主要功能

  1. 01导航并管理浏览器标签页
  2. 02通过无障碍快照读取页面
  3. 03点击元素并填写字段
  4. 04截取页面并保存为 PDF
  5. 05检查网络请求与响应
  6. 06创建网站 CLI 的工作流程

适用场景

  1. 01跨网页调研信息
  2. 02在现有浏览器会话中填写表单
  3. 03探索网站时检查页面请求
  4. 04根据网站调研构建可复用 CLI

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mxyhi/ok-skills --skill kimi-webbridge

安装后在 Claude Code 中输入/kimi-webbridge确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
operations.md
references/cli-creator/
companion-skill-template.md
go-layout.md
login-handling.md
site-exploration.md
workflow.md

详细介绍

Kimi 浏览器扩展(原名 Kimi WebBridge)

通过本地守护进程 http://127.0.0.1:10086 控制用户的真实浏览器(及其登录会话)(这是默认地址;地址不同时,请参阅工具调用失败时)。

当用户要求为某个网站构建可复用的 CLI 工具或脚本(而非执行一次性任务)时,请遵循 references/cli-creator/workflow.md。其中的阶段说明了何时阅读以下各项:

  • references/cli-creator/site-exploration.md——查找每项功能如何获取数据的协议
  • references/cli-creator/login-handling.md——网站需要登录时
  • references/cli-creator/go-layout.md——CLI 使用 Go 编写时
  • references/cli-creator/companion-skill-template.md——用于指导 Agent 如何使用 CLI 的技能模板

工具

工具参数返回值说明
navigateurl、newTab(bool)、group_title{success, url, tabId}首次调用会打开一个标签页——请参阅标签页。group_title 用于设置标签组的可见名称
find_taburl、active(bool){success, url, tabId, borrowed}重新选择本次会话打开的标签页;active:true 会借用用户正在查看的标签页——请参阅标签页
snapshot可选的 ref;format:"aria" 可选择返回文本,并可指定 max_chars(1–60000)或 cursor 以继续默认 {url, title, tree};ARIA {url, title, tree_text}无障碍树(文本)——用于读取页面内容和定位元素
clickselector(@e 引用或 CSS){success, tag, text}合成的 el.click()
fillselector、value{success, tag, mode}适用于 <input>/<textarea> 以及 [contenteditable](ProseMirror/Lexical/Slate)。mode 为 "value" 或 "contenteditable"
evaluatecode(要使用 await,请将其包装在 async IIFE 中——顶层 await 会导致 SyntaxError){type, value}
cdpmethod、params原始 CDP 响应原始 chrome.debugger 直通接口——对于 JS,evaluate 是什么,cdp 对 CDP 就是什么。适用于上述工具无法处理情况的底层逃生通道。Page.bringToFront 是最后手段:当标签页的焦点模拟关闭时,调用它会开启焦点模拟,而不是激活标签页(标签页会渲染并接收真实输入,但不会切换到该标签页);只有在模拟已开启后调用,才会激活标签页;并且绝不会将 Chrome 切换到用户正在使用的其他应用之上。Target.activateTarget 会被拒绝
screenshotformat(png|jpeg)、quality(0-100)、可选的 selector(@e/CSS)、可选的 path{format, path, sizeBytes, mimeType}返回文件路径,而非 base64——请参阅屏幕截图
networkcmd(start|stop|list|detail)、filter(URL 子字符串,用于 list)、requestId(用于 detail)list:{count, requests:[{requestId, url, method, status, mimeType, completed}]};detail:该请求及 requestHeaders、requestBody、body(响应)按标签页捕获,从调用 start 时开始。请在调用 stop 前调用 detail——停止捕获会释放响应正文,此后 detail 会返回 bodyError 而非 body
uploadselector、files(string[]){success, fileCount}
save_as_pdfpaper_format、landscape、scale、print_background、可选的 path{path, sizeBytes, mimeType, pageTitle}将当前页面渲染为 PDF,并返回文件路径——请参阅将当前页面另存为 PDF
list_tabs—{success, tabs:[{tabId, url, title, active, groupTitle}]}查看当前会话中的标签页
list_browser_tabs—{success, tabs:[{tabId, windowId, url, title, active}]}查看此 WebBridge 连接在所有窗口中可见的全部标签页;不会附加或聚焦任何标签页
attach_tabtabId{success, tabId, url, title, borrowed}将指定的现有标签页附加到本次会话,而不聚焦它;借用的标签页在调用 close_session 后仍会保持打开
close_tab—{success, closed: bool}关闭会话中的当前标签页
close_session—{success, closed: int}关闭本次会话打开的标签页;借用的标签页保持打开。closed 为关闭的标签页数量。何时调用,请参阅会话
标签页和当前标签页

单标签页工具(snapshot、click、fill、screenshot、save_as_pdf)会在当前标签页上执行操作——即你最近通过 navigate 打开、通过 find_tab 选中或通过 attach_tab 附加的标签页。

  • 打开页面:如果需要让多个页面并存(用于比较、交叉引用),请使用 newTab:true;如果要将当前标签页转到新 URL,则省略该参数。
  • 返回较早打开的标签页:调用 find_tab,重新将你在本次会话中较早打开的标签页设为当前标签页。传入标签页的 URL——可从 list_tabs 或较早的 navigate 结果中获取。匹配依据是主机名:kimi.com 也能找到 www.kimi.com 标签页,且会忽略路径。默认情况下,find_tab 只搜索本会话自己的标签页,不会访问用户的其他标签页或窗口。
  • 操作用户已经打开的页面:调用 list_browser_tabs,根据 URL/标题和 tabId 选择标签页,然后用该 ID 调用 attach_tab。此方法也适用于其他窗口中的标签页,且不会改变用户当前的前台标签页。附加的标签页是借用的,在调用 close_session 后仍会保持打开。对于用户当前正在查看的特定标签页,使用 find_tab 并设置 active:true 仍然有效。
  • 如果 find_tab 报错 "no tab matching … in this session",说明该页面未在本会话中打开——请改用 navigate 并设置 newTab:true。
curl -s -X POST http://127.0.0.1:10086/command \
  -d '{"action":"find_tab","args":{"url":"https://www.kimi.com","active":true},"session":"k26-research"}'
调用格式

每条命令都包含一个顶层 session,用于指定当前任务——请参阅下文的 会话。后续章节中的示例仅为简洁起见省略了它;实际调用时请务必包含。每条回复都是一个信封:成功时为 {"ok":true,"data":…}(上方的返回值列描述了 data),失败时为 {"ok":false,"error":{"code","message"}}。命令格式取决于用户的操作系统。

macOS / Linux——可以使用内联 JSON:

curl -s -X POST http://127.0.0.1:10086/command \
  -H 'Content-Type: application/json' \
  -d '{"action":"navigate","args":{"url":"https://example.com","newTab":true,"group_title":"My task"},"session":"my-task"}'

如果内联调用失败——例如 bash 返回 shell 引号/语法错误,或守护进程返回 HTTP 400——不要原样重试同一条命令。请将请求作为文件正文重新发送:

  1. 使用你自己的文件写入工具,将 JSON 正文写入一个唯一命名的临时文件——不要使用 shell echo/heredoc,因为它们会以同样的方式破坏 JSON。每个请求都使用一个新文件名(例如 /tmp/webbridge-req-<random>.json)。
  2. POST 该文件:
curl -s -X POST http://127.0.0.1:10086/command -H 'Content-Type: application/json' --data-binary @/tmp/webbridge-req-<random>.json
  1. 请求返回后立即删除临时文件。

Windows(PowerShell / cmd)——shell 会破坏命令参数或管道中内联传递的非 ASCII 字符(如中文);这些字符到达守护进程时会变成 ?,且无法恢复。所有请求都必须作为文件正文发送:

  1. 使用你自己的文件写入工具,将 JSON 正文写入一个唯一命名的临时文件——不要使用 shell echo/heredoc,因为它们同样会破坏非 ASCII 字符。每个请求都使用带随机后缀的独立文件名(例如 webbridge-req-<random>.json),以免并发请求共用同一个文件并相互覆盖。
  2. 使用 curl.exe POST 该文件——始终使用 curl.exe,不要使用裸 curl,因为 Windows PowerShell 会将其别名映射到 Invoke-WebRequest:
curl.exe -s -X POST http://127.0.0.1:10086/command -H "Content-Type: application/json" --data-binary "@$env:TEMP\webbridge-req-<random>.json"
  1. 请求返回后立即删除临时文件——不要将请求正文留在磁盘上。

会话

一个任务 = 一个会话 = 一个标签页组。 session 会将任务打开的所有标签页收集到一个标签页组中,让用户能在一个组中看到“Agent 当前正在做什么”。将其作为请求正文的顶层字段传入(不要放在 args 内)。

  • 在任务开始时选定一个会话名称,将其用于每条命令,任务中途绝不切换——即使跨不同网站也一样。 按网站切换会话名称是标签页组分散的头号原因。
  • 会话名称应体现任务,而非网站(camping-research、phone-compare)。只有真正无关的并行任务才使用多个会话。
  • group_title 是供用户阅读的组标签——请用用户的语言填写,并在任务中的第一个 navigate 时设置。
  • 创建组时(任务中的第一个 navigate),告知用户一次:此任务的页面会收集在名为「标题」的组中,并且用户提出要求时你会关闭它们。
# First tab: set session + a human label (in the user's language)
curl -s -X POST http://127.0.0.1:10086/command \
  -d '{"action":"navigate","args":{"url":"https://www.kimi.com","newTab":true,"group_title":"K2.6 feature research"},"session":"k26-research"}'
# Another site, same task → same session → joins the same group automatically
curl -s -X POST http://127.0.0.1:10086/command \
  -d '{"action":"navigate","args":{"url":"https://www.moonshot.cn","newTab":true},"session":"k26-research"}'

关闭操作始终由用户发起:只有在用户明确提出要求(“关闭那些标签页”“清空标签页”)时,才调用 close_session。一次调用即可清除整个组。

截图

守护进程会将图像写入磁盘,并返回 {format, path, sizeBytes, mimeType}——不会返回 base64,因为模型无法读取原始图像字节。获取 .path 后,使用 Read 工具打开它,才能实际查看图像。

# Default: PNG of the visible viewport, daemon picks a temp path
curl ... -d '{"action":"screenshot","args":{}}'
# Options (each independent): JPEG quality, element-only via @e/CSS selector, custom output path
curl ... -d '{"action":"screenshot","args":{"format":"jpeg","quality":60}}'
curl ... -d '{"action":"screenshot","args":{"selector":"@e123"}}'

调用方提供的 path 会原样使用(创建父目录,覆盖现有文件)——请使用唯一名称以避免覆盖其他文件。save_as_pdf 遵循相同规则。

优先使用 snapshot,而非 CSS/JS 选择器

snapshot 会返回带有 @e 引用的交互元素,这些引用绑定到观察到的 DOM 节点。将引用作为不透明字符串复制到 click/fill 中。重新读取页面会保留相同节点的引用;节点被移除或文档/连接发生变化时,则需要重新执行 snapshot。引用不会自动选择名称相同的替代元素。

若要读取限定长度的文本,请调用 snapshot 并设置 format:"aria",还可选择设置 max_chars(默认值为 60000)。这会限制 tree_text,但不限制元数据。如果 truncated:true,请将 next_cursor 作为 cursor(不带 ref)传回,以继续读取同一已保存的观察结果;continued:true 表示后续文本块。拼接 tree_text 时不要添加额外分隔符:文本块可能会拆分较长的行,且预算按 UTF-16 代码单元计算,不会拆分代理对(若下一个字符需要 2 个代码单元,则预算设为 1 会报错)。游标会在五分钟后、缓存被清除后、导航后或连接重置后过期;遇到游标过期错误时,请重新执行 snapshot。同一文档中的内容编辑不会刷新已保存的文本。缓存最多保存八个 snapshot/八百万个代码单元;超过四百万个代码单元的观察结果会明确失败,因此请缩小读取范围。或者,使用带有特定 query 的 find 在完整的主文档无障碍树中搜索,然后使用选定匹配项的 ref 调用 snapshot 读取其子树。搜索结果包含祖先路径,可用于区分名称相同的匹配项。范围和预算不会重新分配已有引用;此搜索不包含 iframe 内容。

仅在以下情况下回退到 evaluate(JS):

  • 目标在 snapshot 中没有 @e 引用
  • 需要获取 snapshot 中没有的属性(例如 href)
  • 需要派发复杂事件序列或滚动

Evaluate 提示

  • 始终使用精简的 JSON.stringify(data)——不要添加 null, 2 格式化。缩进和换行可能会让响应膨胀数倍,导致传输过程中被截断。
  • evaluate 调用共享页面的 JS 环境——在两次调用中重复声明相同的 const/let 会引发 SyntaxError。请使用 IIFE 创建独立作用域:(() => { const x = ...; return x; })()。

文本输入 — 使用 fill

fill(选择器 = CSS 或 @e 引用,以及要填入的值)适用于 <input>/<textarea>(返回 mode: "value"),也适用于 [contenteditable] 富文本编辑器——ProseMirror、TipTap、Lexical、Slate、Quill 等(返回 mode: "contenteditable"),并会触发相应的输入事件,让页面作出响应。

fill 会先清除再插入:替换现有内容。要追加内容,请通过 evaluate 读取当前值,拼接后再用结果调用 fill。

表单提交/特殊按键

没有单独的“按 Enter”工具。要提交表单,请直接点击提交按钮(对 @e 引用或选择器调用 click)。要以编程方式分派按键事件(例如按 Escape 关闭模态框):

{"action":"evaluate","args":{"code":"document.activeElement.dispatchEvent(new KeyboardEvent('keydown',{key:'Escape',bubbles:true}))"}}

将当前页面保存为 PDF

save_as_pdf 会将当前页面渲染为 PDF 并返回文件路径。所有参数均为可选:

  • paper_format:letter(默认)| a4 | legal | a3 | tabloid
  • landscape:false(默认)
  • scale:1.0(默认),范围为 [0.1, 2.0]
  • print_background:true(默认)——保留背景颜色
  • path:调用方提供的输出路径;如果未指定,守护进程会在操作系统临时目录下选择默认路径,并以页面标题作为文件名

path 的语义与 screenshot 一致:按原样写入,自动创建父目录,覆盖已有文件。

解码后的 PDF 上限为 100 MB。超过此大小时,守护进程会拒绝处理;请降低 scale 或拆分页内容。

已知限制

  • 严格检查 event.isTrusted 的网站(例如某些银行门户、验证码)会忽略 click / fill,因为这些操作会触发 DOM 层级的合成事件(isTrusted=false)。遇到这种情况,请告知用户该页面需要手动操作。(通过协议层的 cdp 逃生舱可以实现可信输入,但这属于高级用法:你的标签页在后台运行,只有在启用焦点模拟时,真实输入才会发送到后台标签页——输入前发送 Emulation.setFocusEmulationEnabled {"enabled":true},在该标签页操作完成后发送 {"enabled":false}。如果输入仍未生效,最后的办法是使用 Page.bringToFront;请参阅 cdp 行。)
  • iframe 内的内容:snapshot、fill、click 和 evaluate 只能访问顶层文档——嵌入的文档(预览窗格、沙盒预览、嵌入式应用)属于独立页面,其节点不会出现在树中。当快照在树之后列出 frames(frames: [{frame:"#f1", url, size, …}],按面积从大到小排列)时,请使用列表中的句柄,通过 read_page {"frame":"#f1"} 读取其中一个框架。框架读取结果会回显 frame;如果没有回显,说明扩展比此技能版本旧,并返回了顶层页面——请参阅下文的版本不匹配。预览框架通常会在页面本身加载数秒后才出现——使用 wait {"frame":"any"},即可在占据屏幕大部分区域的框架可读时立即返回,而不必重新获取快照。PDF 预览通过查看器自身的文档读取,因此无需滚动即可获取所有页面。目前仍不支持对框架内的元素执行操作——有时直接导航到框架的 URL 可行,但经过身份验证的预览流通常无法单独加载。

如果工具调用失败(守护进程或扩展尚未就绪)

如果工具调用无法连接到守护进程(连接被拒绝),或者回复不是上面的 ok 信封(有其他程序正在响应该端口),请自行运行 start,不要询问用户。任何时候运行都安全:如果守护进程已启动,则不会执行任何操作。 二进制文件不在 PATH 中:~/.kimi-webbridge/bin/kimi-webbridge(Windows:%USERPROFILE%\.kimi-webbridge\bin\kimi-webbridge.exe)。

守护进程的监听地址始终会显示在 start 的输出中,或者显示在 kimi-webbridge status 中(运行时显示 port,未运行时显示 addr)。如果地址不是 127.0.0.1:10086,本任务中的每次调用都使用该地址。配置文件只用于更改守护进程地址,不用于查找地址。然后重试工具调用。

如果回复为 ok:false,且代码为 extension_not_connected,说明守护进程正常,但浏览器端未连接——运行 start 不会改变这一点。消息会说明用户需要做什么;请用用户的语言转告他们,并在用户确认后继续。

start 失败并显示 "did not come up … held by another program" → 另一个程序占用了该端口。更改守护进程地址:将 {"addr":"127.0.0.1:<port>"}(选择一个空闲端口)写入错误中指定的配置文件,然后再次运行 start,接着请用户将扩展指向新端口一次(Kimi 侧边栏 → Settings → Local agent remote control → Connection address → ws://127.0.0.1:<port>/ws;扩展会记住该设置)。

如果仍然失败,说明二进制文件缺失(command not found 表示未安装 kimi-webbridge),或者浏览器扩展无法连接——请引导用户访问帮助页面,不要深入排查:

切勿自动运行 stop / restart / upgrade / uninstall——这些命令会终止正在运行的守护进程。当 status 显示 version_mismatch、update_available 或 skill_mismatch,或者 kimi-webbridge 命令输出 ==> … Run: <command> 行(同样的提示也会输出到 stderr)时,请告知用户,并原样提供他们需要运行的命令——即 command 字段中的内容,或 Run: 后的内容;这就是这些提示的用途。当用户询问 kimi-webbridge 本身(安装、启动/停止/升级、“是否正在运行”、status 的含义、更改端口)时,请先阅读 references/operations.md。

版本不匹配

如果工具返回的错误中包含 "Please update the Kimi Browser Extension",说明用户的浏览器扩展版本低于此技能所需的版本。不要尝试自行协调版本——只需用用户的语言告知他们更新扩展并重试:

评论

支持 Markdown