关于 Bruster
Bruster 是基于 Rust 的浏览器自动化 MCP 服务,通过 JSON 行驱动原生 WebView,无需 Node.js。它适用于需要跨支持平台进行网页交互、检查和截图的 Agent、脚本与测试工具。
主要功能
- 01导航并检查网页
- 02点击、填写表单、拖动和上传
- 03以图像内容返回截图
- 04检查网络与控制台活动
- 05管理标签页和持久配置文件
- 06使用原生 WebView 引擎
适用场景
- 01自动填写浏览器会话中的表单
- 02为 Agent 工作流截取网页画面
- 03检查页面结构和网络活动
- 04通过 MCP 或 JSON 行运行浏览器测试
MCP 相关
使用 `--mcp` 时,Bruster 会通过 stdio 将所有原生方法公开为 MCP 工具。截图以图像内容返回,页面事件则以通知发送。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
bruster
由 Agent 通过 stdio 上的 JSON 行驱动的原生 WebView 浏览器。
WKWebView · WebKitGTK · WebView2。使用原生浏览器运行时的小型 Rust 可执行文件。无需 Node。
bruster 使用原生浏览器引擎,需要时需单独安装。
其 Rust 控制器通过 stdin 和 stdout 读写 JSON 行;渲染过程
也会使用浏览器辅助进程。这种设计适用于 Agent、脚本和测试工具。--mcp 选项会将每个方法公开为工具。
为什么选择 bruster?
- 原生 WebView,无需 Node.js。 bruster 通过 wry 在 macOS 上使用 WKWebView,在 Linux 上使用 WebKitGTK,在 Windows 上使用 WebView2。WebView2 基于 Chromium;需要时需单独安装浏览器运行时。
- 小型控制器。 一个小型发布版可执行文件,以及单独安装的原生浏览器运行时。完整运行时占用包括其库和辅助进程。
- 支持 Agent。 使用
--mcp提供 MCP 支持。截图以图像内容形式返回,页面事件以通知形式返回。 - 跨平台。 提供适用于 macOS(arm64、x86_64)、Linux(x86_64、arm64)和 Windows(x86_64)的预构建版本。
- 实用的 API。 可导航、获取快照、点击、填写表单、拖动、上传、截图、检查网络和控制台、管理标签页,并使用
--profile保留会话。 - 确定且安全。 每次调用都对应一行 JSON 请求和响应。
beforeunload会被禁用,且对话框不会阻塞操作。 - 速度快。 持久化 HTTP 缓存和配置文件可加快重复访问。Agent 启动时,第一个标签页会加载
about:blank。
提示
实时基准测试会在每次合并到
main后,将 Bruster 与最新稳定版 Playwright、Puppeteer 和 agent-browser 进行比较,测试启动、导航、内容提取、截图、进程总内存和已安装的运行时文件。请参阅基准测试设置与方法。
演示

30 秒视频 · 试用相同的工作流 · 基准测试图表和源数据
这些是由脚本化 MCP 客户端获取的真实 WebKitGTK 截图。为便于阅读,每一步都会停留 五秒;这段演示不是速度测试,也不是 LLM 会话的录制。
安装
一键安装(推荐)
curl -fsSL https://raw.githubusercontent.com/aliilyas/bruster/main/install.sh | sh
该脚本会根据你的操作系统和 CPU 安装相应的构建版本到 ~/.local/bin。
预编译版本
从 Releases 页面下载适用于所有平台的压缩包。
MCP bundle
对于支持 MCP bundle 的客户端,请下载
bruster-0.3.2.mcpb。
其中包含适用于全部五种受支持操作系统/CPU 组合的原生可执行文件。
Linux 仍需要 WebKitGTK 4.1 和显示服务器或 Xvfb;Windows 需要 WebView2。
官方 MCP Registry 名称为 io.github.aliilyas/bruster;server.json
固定了 bundle 及其 SHA-256 哈希值。
从源代码安装
cargo build --release
说明
Linux 要求。 运行时必须安装 WebKitGTK 4.1。使用以下任一命令安装:
apt install libwebkit2gtk-4.1-0、apk add webkit2gtk-4.1或dnf install webkit2gtk4.1。如果系统没有桌面会话,且未设置DISPLAY,bruster 会通过xvfb-run -a重新启动。
Docker Hub
已发布的 ilyastmn/bruster 镜像
为 linux/amd64 和 linux/arm64 捆绑了 Bruster、WebKitGTK、Xvfb、字体和 HTTPS 证书。Docker 会自动选择匹配的架构。
docker pull ilyastmn/bruster:latest
docker run --rm -i ilyastmn/bruster:latest
latest 对应经过测试的 main 构建版本;sha-<full-git-commit> 用于选择特定的
源代码修订版本。Docker CI 会发布经过测试的确切镜像,并且只有在两种架构的检查都通过后才会更新多平台标签。可用标签列于
Docker Hub。
默认命令通过 stdin/stdout 提供 MCP 服务。对于 MCP 客户端,请保留 -i 并省略 -t;无需映射端口或使用主机显示服务器。例如:
{ "mcpServers": { "bruster": { "command": "docker", "args": ["run", "--rm", "-i", "ilyastmn/bruster:latest"] } } }
要传入其他选项,请再次包含 --mcp,例如
docker run --rm -i ilyastmn/bruster:latest --mcp --viewport 1920x1080。
镜像以非 root 用户运行,使用软件渲染,并停用 WebKit 的嵌套沙箱,因为 Docker 的默认 seccomp 配置文件会阻止其用户命名空间。
无需使用 --privileged 或额外能力。Tini 会转发关闭信号并回收浏览器辅助进程。诊断信息仍会输出到 stderr。
对于 Glama,请在该条目的
Admin → Docker builds 配置中提交 Dockerfile,并使用此仓库作为构建上下文,然后运行其评估。
默认命令无需凭据即可响应 initialize 和 tools/list。
Dockerfile 使用锁定的 Rust 源代码进行多阶段构建; 编译器和开发软件包仅留在构建阶段。两个基础镜像都固定为多平台 SHA-256 摘要。更新基础镜像时,请刷新这些摘要,然后重新运行两种架构的检查。
要构建当前检出版本并在 Linux Docker 主机上测试(仅使用 Python 标准库):
docker build -t bruster:local .
python3 tests/docker.py --image bruster:local --https
此检查会通过 MCP 验证服务发现、导航、表单交互、JavaScript、截图、标签页、 HTTPS 证书,以及通过 MCP、stdin EOF 和 SIGTERM 进行关闭。容器以 512 MiB 内存限制运行,丢弃所有能力且不授予新权限; 报告包含镜像大小、初始化时间和内存使用量。
快速入门
以原生协议模式运行 bruster:
bruster
然后每行发送一个 JSON 对象:
{"id":1,"method":"navigate","params":{"url":"https://example.com"}}
{"id":2,"method":"snapshot"}
{"id":3,"method":"click","params":{"ref":"e2"}}
{"id":4,"method":"close"}
结果和事件会通过 stdout 返回:
{"event":"load","tab":1,"url":"https://example.com/"}
{"id":1,"result":{"url":"https://example.com/"}}
{"id":2,"result":{"url":"https://example.com/","title":"Example Domain","elements":[...]}}
{"id":3,"result":null}
MCP
使用 --mcp 时,bruster 会通过标准输入/输出使用 Model Context Protocol。每个原生方法都会变成一个工具。屏幕截图会作为图像内容返回,页面事件则会作为通知返回。
常见 MCP 客户端配置
// Claude Desktop (claude_desktop_config.json), Cursor (.cursor/mcp.json)
{ "mcpServers": { "bruster": { "command": "bruster", "args": ["--mcp", "--quiet"] } } }
claude mcp add bruster -- bruster --mcp --quiet # Claude Code
codex mcp add bruster -- bruster --mcp --quiet # Codex CLI
opencode mcp add bruster -- bruster --mcp --quiet # OpenCode
OpenCode V2 在 opencode.jsonc 中使用 mcp.servers。完整配置请参阅
客户端专用 MCP 设置指南。
// VS Code (.vscode/mcp.json)
{ "servers": { "bruster": { "type": "stdio", "command": "bruster", "args": ["--mcp", "--quiet"] } } }
--mcp 会让窗口保持在屏幕外。添加 --visible 可查看浏览器。
--hidden 并非真正的无头模式:在 Linux 上,WebKitGTK 仍需要 X11/Wayland 显示环境或 Xvfb。如果未设置显示环境,Bruster 会自动尝试使用
xvfb-run;如果该程序不可用,请安装 Xvfb。
在 Linux 上,隐藏/MCP 模式会跳过桌面会话总线,以避免等待不可用的桌面门户。如果隐藏模式需要桌面会话集成,请设置 BRUSTER_USE_SESSION_BUS=1。--visible 会使用常规会话总线。
运行
bruster [--mcp] [--hidden|--visible] [--quiet] [options]
| 标志 | 效果 |
|---|---|
--mcp | 通过标准输入/输出使用 Model Context Protocol,而非原生协议。此选项也会设置 --hidden |
--hidden / --visible | 将窗口移至屏幕外 / 显示窗口 |
--quiet | 将 stderr 发送到 /dev/null。这会屏蔽 GL、ALSA 和 GTK 噪声 |
--viewport WxH | 初始窗口大小,默认为 1280x800 |
--user-agent UA | 替换 user agent |
--profile DIR | 在多次运行之间保留 Cookie 和存储数据 |
--proxy URL | http://host:port 或 socks5://host:port |
--init-script FILE | 在每个页面自身的脚本运行前执行的 JavaScript |
--dark | 为此配置文件(或默认状态)持续启用深色配色方案;使用 light 重置 |
--insecure | 忽略 TLS 错误(仅限 Linux) |
--no-images | 不加载图像。页面加载速度约提升 30%(仅限 Linux) |
窗口和颜色控制
原生命令和 MCP 工具 minimize 与 maximize 会针对指定的 tab
(或当前标签页)执行操作,返回 "minimized" 或 "maximized",并持久化所请求的窗口模式。每种模式都会取代之前的模式。minimize 会隐藏原生窗口(而非将其最小化到图标);maximize 会恢复窗口的可见性并将其最大化。在隐藏/MCP 模式下,这两条命令都会被接受并保存,但窗口仍会处于屏幕外以供渲染。
dark 和 light 会独立于窗口模式持久化颜色偏好,并将其应用于所有现有标签页、新标签页和后续导航。便携式页面级回退方案会设置根 CSS color-scheme(包括原生控件和默认页面颜色);它不会模拟 prefers-color-scheme 媒体查询,也不会重新着色网站明确指定的颜色。自定义 --init-script 脚本仍会运行。
偏好设置存储在 WebView 数据之外。使用 --profile PATH 时,元数据位于规范配置目录的同级目录中,文件名为 PATH.bruster-window.json。未指定配置文件时,文件位于:
- Linux:
$XDG_STATE_HOME/bruster/window.json,若未设置,则使用$HOME/.local/state/bruster/window.json。 - macOS:
$HOME/Library/Application Support/bruster/window.json。 - Windows:
%LOCALAPPDATA%/bruster/window.json。
设置适用于整个配置文件;最后一条成功执行的命令生效。缺失或格式错误的元数据会使用默认值,旧版仅包含窗口状态的文件仍可接受。持久化失败会返回协议错误。操作系统窗口管理器所做的更改不会被保存。close 会关闭服务和所有标签页;close_tab 或通过操作系统关闭窗口时,只会关闭对应标签页。关闭标准输入也会关闭服务。
Linux 使用软件渲染。隐藏视图会跳过屏幕外的 GTK 绘制,但仍保持映射状态,以支持布局、动画和原生截图。设置 BRUSTER_PAINT_HIDDEN=1 可启用这些窗口绘制。隐藏模式还会默认设置 WEBKIT_DISABLE_DMABUF_RENDERER=1,以避免不必要的图形传输探测;显式提供的值(包括 0)优先级更高。
自动启动的 Xvfb 会禁用 GLX。BRUSTER_XVFB_ARGS 可覆盖服务端参数(默认值:-screen 0 1280x1024x24 -nolisten tcp -extension GLX)。设置 BRUSTER_NO_XVFB=1 可阻止自动启动 Xvfb。
测试
Test Lab 提供包含可执行断言的独立
HTML/CSS/JavaScript 测试用例。Cargo 会构建 Bruster,并通过原生 JSONL 和 MCP
运行 52 个针对性测试用例(需要 Python 3.10+;在无头 Linux 上请在前面加上
xvfb-run -a):
cargo test --release --test test_lab
# Opt-in check against the published site, including real React/Vue/Svelte apps.
cargo test --release --test test_lab -- --ignored --exact published_test_lab
请参阅测试实验室设置和覆盖范围,了解完整核心测试套件
(full_test_lab)、单个测试用例筛选、压力测试用例、固定版本的框架包和报告。Python 运行器也接受现有的可执行文件:
python3 scripts/test_lab.py run --binary target/release/bruster --case 'ref-*' --transport both
tests/run_all.sh [--rounds N] [--no-e2e] [--no-lab] 会运行完整测试周期:
构建、单元测试、冒烟测试、边界测试、针对性的测试实验室分组、遗留进程检查、MCP
启动,以及包含已发布测试实验室在内的端到端测试。--no-e2e 会将测试周期限制在本地;--no-lab 会跳过两次测试实验室运行。在 Linux 上,请在 xvfb-run -a 下运行脚本。CI 会在所有平台上运行完整核心测试实验室,并在 v* 标签上发布发行归档。
Linux 桌面门户启动回归测试需要 D-Bus、python3-dbus 和
python3-gi:
cargo build --release --locked
xvfb-run -a /usr/bin/python3 tests/startup_portal.py target/release/bruster
协议
两个方向均为每行一个 JSON 对象。元素可通过 {"selector": "css"} 或来自上一次 snapshot/find 的 {"ref": "eN"} 进行寻址。使用 format: "text" 时,快照会为每个元素返回一行:
https://example.com/
Example Domain
e1 heading "Example Domain"
e2 text "This domain is for use in..."
e3 link "Learn more" href=https://iana.org/help/example-domains
e4 checkbox "Remember me" checked=false
说明
在文本格式中,同源 href 会省略源站。警告和提示对话框永远不会阻塞。bruster 会按照当前的
dialog设置响应,并将其报告为dialog事件。beforeunload处理程序会被停用。
通过页面运行时路由的调用(eval、url、title、snapshot、交互操作和其他 DOM 工具)具有以毫秒为单位的外层 request_timeout,默认至少为 30000 毫秒(或所请求的 timeout/time 加 5000 毫秒,两者取较长者)。此期限包含等待导航所花的时间。对于耗时异常长的操作,请显式设置此值。超时会停止等待回复,但不会中断已在页面中运行的 JavaScript。尤其是,无限循环可能导致 Web 进程无响应,可能需要重启 bruster。超时后才到达的回复会被丢弃。导航使用自己的 timeout;截图等原生操作不使用 request_timeout。MCP 会将 null 结果表示为文本 null。
API
| 方法 | 参数 | 结果 |
|---|---|---|
navigate | url、until?(默认为 load,可选 dom、idle)、timeout? 毫秒(默认 30000) | 在 load/DOM/idle 时返回 {tab, url};超时、DNS/错误或下载(Linux)时返回失败 |
reload back forward | 无 | {url};无可前往的页面时返回 null |
url title | 无 | 字符串 |
eval | expression | JSON 值。会等待 Promise 完成。作为脚本编译 |
snapshot | selector?、max?(1000)、boxes?、format?(原生默认 json,MCP 默认 text) | {url,title,elements[],truncated?} 或文本行 |
find | text? 或 regex? + 快照参数 | 经过筛选的快照 |
screenshot | path?、full?、clip? {x,y,width,height} | {path,bytes} 或 {png_base64}。整页高度上限为 16000 px |
rect | 目标 | 相对于视口的 {x,y,width,height} |
click | 目标或 x,y;force?、timeout? | null |
hover | 目标 | null |
fill | 目标、value | null |
fill_form | fields: [{selector|ref, value}] | null(复选框为布尔值,选择框为字符串/数组) |
type | 目标、text、delay?、submit? | null |
press | 目标?、key(Enter、Control+a) | null |
select | 目标、value | 已选值 |
check | 目标、checked? | 布尔值 |
drag | from 目标、to 目标 | null |
upload | 目标、paths[] | 设置到输入框中的文件名 |
scroll | 目标或 x,y 增量 | 当前 {x,y} 位置 |
resize | width、height(1 到 16000) | {width,height} |
text html | 目标 | 字符串 |
attr | 目标、name | 字符串或 null |
count | selector | 数字 |
wait_for | selector/ref + state?(visible、attached、hidden)、text、textGone、url、idle、time 毫秒;timeout? 毫秒 | null |
network | clear? | fetch/XHR 条目(含索引、方法和可用状态),以及资源计时条目 |
network_request | index | 单个条目,含 req_headers、res_headers 和 body(前 16 KB) |
console | clear? | [{level,text,ms}] 控制台输出及未捕获错误 |
dialog | accept?、text?、clear? | 已出现的对话框。设置对下一个对话框的响应 |
cookies | 无 | 列表 |
set_cookie | name、value、domain?、path?(/) | null |
new_tab | url?、timeout? 毫秒(默认 30000) | {tab};加载后返回 {tab,url};不会切换当前标签页 |
tabs | 无 | [{tab,url,current}] |
switch_tab | tab | null |
close_tab | (使用 tab) | null;拒绝关闭最后一个标签页(请使用 close) |
close | 无 | 退出 |
事件
ready、navigating、load、tab_opened、tab_closed、dialog(type、message、accept)、tls_error(Linux)、load_failed 和 download(Linux)。
限制
- 输入使用合成 DOM 事件(
isTrusted为 false)。无法获得:hover样式、原生<select>弹出菜单或操作系统级快捷键。 - 网络和控制台日志会在页面中进行拦截,并在导航时重置。fetch/XHR 的网络条目包含状态和索引;其他资源使用性能计时信息,可能没有状态或方法。日志不包含文档请求,也不包含请求正文。要进行真实拦截,请使用
--proxy。 - 无法访问跨域 iframe。同源 iframe 和开放的 shadow root 可以正常使用。
- 导航时请使用 HTTP(S) URL。不支持
data:和file:URL;请改为通过 localhost 提供本地页面。 - bruster 不会拦截原生文件选择器。请使用
upload,不要点击文件输入框。 - 未指定
--profile时,Cookie 和存储数据仅在单次会话中保留。 - 全页面截图的上限为 16000 px。在 macOS 上,页面过高、超过屏幕高度时,截图可能会被截断。
- WebKitGTK 截图会捕获页面内容,但不包含非覆盖式滚动条,因此宽度可能小于窗口视口。
- 在 Windows(WebView2)上,
screenshot不支持clip。--quiet不起作用。仅限 Linux 的标志均无效果。 - 使用
--hidden时,WebKit 计时器节流可能导致由setTimeout驱动的页面变慢。macOS WKWebView 会暂停屏幕外窗口中的动画帧;对于由动画驱动的工作流,请使用--visible。
开发
bin/bruster会运行此代码检出目录中的开发构建。tests/run_all.sh会运行构建、单元测试、冒烟测试、边缘测试、测试实验室组、MCP 启动检查和端到端测试。- CI(
.github/workflows/ci.yml)会构建所有平台、运行测试,并在v*标签上发布发行归档。 - 基准测试:
scripts/bench_compare.py用于比较五种配置;scripts/bench_footprint.py用于盘点运行时文件;scripts/bench_report.py用于验证并发布结果。请参阅设置和方法。 - 测试实验室:
tests/test_lab.rs将共享测试夹具集成到 Cargo 中;scripts/test_lab.py负责构建、提供并运行这些测试夹具。请参阅用例编写和验证。 - 网站:
site/包含 GitHub Pages 的源文件。请参阅本地预览和发布。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。