mcpField
B
Bruster

Bruster

ローカル
aliilyas.github.ioその他0今日更新

Bruster について

Brusterは、Node.jsを必要とせずネイティブWebViewを使うRust製ブラウザー自動化サーバーです。対応デスクトップ環境でのページ操作、検査、スクリーンショットを必要とするエージェント、スクリプト、テストハーネス向けです。

主な機能

  1. 01ページの移動と検査
  2. 02クリック、フォーム入力、ドラッグ、アップロード
  3. 03画像コンテンツとしてのスクリーンショット取得
  4. 04ネットワークとコンソールの検査
  5. 05タブと永続プロファイルの管理
  6. 06ネイティブWebViewエンジンの利用

活用シーン

  1. 01ブラウザーセッションでのフォーム入力の自動化
  2. 02エージェントのワークフロー向けスクリーンショット取得
  3. 03ページ構造とネットワーク活動の検査
  4. 04MCPまたはJSON行経由のブラウザーテスト

MCP 対応

`--mcp`を指定すると、Brusterはstdio経由でネイティブメソッドをすべてMCPツールとして公開します。スクリーンショットは画像コンテンツ、ページイベントは通知として返します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

インストール方法は未掲載です

このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。

リポジトリ
パッケージ
mcpbbruster-0.3.2.mcpb

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

README(原文)English

プロジェクトの README より

この README の日本語訳はまだありません。以下は英語の原文です。日本語の紹介はページ上部をご覧ください。

bruster

bruster

Native webview browser driven by an agent over JSON lines on stdio.

WKWebView · WebKitGTK · WebView2. A small Rust executable using native browser runtimes. No Node required.

CI Release Docker Hub: ilyastmn/bruster MIT License macOS Linux Windows Website

Demo · Install · Docker · Quickstart · MCP · Protocol · API · Performance · Test Lab


bruster uses native browser engines, installed separately where required. Its Rust controller reads and writes JSON lines on stdin and stdout; rendering also uses browser helper processes. This design is good for agents, scripts, and test harnesses. The --mcp option exposes every method as a tool.

Why bruster?

  • Native webviews, no Node.js required. bruster uses WKWebView on macOS, WebKitGTK on Linux, and WebView2 on Windows through wry. WebView2 is Chromium-based; browser runtimes are installed separately where required.
  • Small controller. One small release executable, with a separately installed native browser runtime. The complete runtime footprint includes its libraries and helper processes.
  • Agent support. MCP support with --mcp. Screenshots return as image content, and page events return as notifications.
  • Cross-platform. Prebuilt for macOS (arm64, x86_64), Linux (x86_64, arm64), and Windows (x86_64).
  • Practical API. Navigate, snapshot, click, fill forms, drag, upload, take screenshots, inspect the network and console, manage tabs, and keep a session with --profile.
  • Deterministic and safe. Each call is one line-based JSON request and response. beforeunload is disarmed, and dialogs never block.
  • Fast. A persistent HTTP cache and profiles make repeat visits faster. The first tab loads about:blank while the agent starts.

ヒント

Live benchmarks compare Bruster with the latest stable Playwright, Puppeteer, and agent-browser after every merge to main: startup, navigation, extraction, screenshots, total process memory, and installed runtime files. See benchmark setup and methodology.

Demo

Bruster navigating a local page, inspecting controls, filling a form, and returning a screenshot through MCP

30-second video · Try the same workflow · Benchmark chart and source data

These are actual WebKitGTK screenshots from a scripted MCP client. Each step is held for five seconds for readability; the presentation is not a speed test or a recording of an LLM session.

Install

One-liner (recommended)
curl -fsSL https://raw.githubusercontent.com/aliilyas/bruster/main/install.sh | sh

The script installs the correct build for your OS and CPU into ~/.local/bin.

Prebuilt releases

Download archives for all platforms from the Releases page.

MCP bundle

For clients that support MCP bundles, download bruster-0.3.2.mcpb. It contains the native executables for all five supported OS/CPU combinations. Linux still requires WebKitGTK 4.1 and a display or Xvfb; Windows requires WebView2. The official MCP Registry name is io.github.aliilyas/bruster; server.json pins the bundle and its SHA-256 hash.

From source
cargo build --release

メモ

Linux requirements. WebKitGTK 4.1 is necessary at run time. Install it with one of these commands: apt install libwebkit2gtk-4.1-0, apk add webkit2gtk-4.1, or dnf install webkit2gtk4.1. If the system has no desktop session, bruster starts again under xvfb-run -a when DISPLAY is not set.

Docker Hub

The published ilyastmn/bruster image bundles Bruster, WebKitGTK, Xvfb, fonts, and HTTPS certificates for linux/amd64 and linux/arm64. Docker automatically selects the matching architecture.

docker pull ilyastmn/bruster:latest
docker run --rm -i ilyastmn/bruster:latest

latest tracks tested main builds; sha-<full-git-commit> selects a particular source revision. Docker CI publishes the exact tested images and updates the multi-platform tags only after both architecture checks pass. Available tags are listed on Docker Hub.

The default command serves MCP on stdin/stdout. Keep -i and omit -t for MCP clients; no port mapping or host display is needed. For example:

{ "mcpServers": { "bruster": { "command": "docker", "args": ["run", "--rm", "-i", "ilyastmn/bruster:latest"] } } }

To pass additional options, include --mcp again, for example docker run --rm -i ilyastmn/bruster:latest --mcp --viewport 1920x1080. The image runs as a non-root user, uses software rendering, and disables WebKit's nested sandbox because Docker's default seccomp profile blocks its user namespaces. It needs no --privileged or extra capabilities. Tini forwards shutdown signals and reaps browser helper processes. Diagnostics remain on stderr.

For Glama, submit the Dockerfile in the listing's Admin → Docker builds configuration, using this repository as the build context, then run its evaluation. The default command answers initialize and tools/list without credentials.

The Dockerfile uses a multi-stage build of the locked Rust source; the compiler and development packages stay in the build stage. Both base images are pinned to multi-platform SHA-256 digests. Refresh those digests when updating the base images, then rerun both architecture checks.

To build the current checkout and test it on a Linux Docker host (Python standard library only):

docker build -t bruster:local .
python3 tests/docker.py --image bruster:local --https

This checks MCP discovery, navigation, form interactions, JavaScript, screenshots, tabs, HTTPS certificates, and shutdown via MCP, stdin EOF, and SIGTERM. Containers run with a 512 MiB memory limit, all capabilities dropped, and no new privileges; the report includes image size, initialization time, and memory use.

Quickstart

Run bruster in its native protocol mode:

bruster

Then send JSON objects, one per line:

{"id":1,"method":"navigate","params":{"url":"https://example.com"}}
{"id":2,"method":"snapshot"}
{"id":3,"method":"click","params":{"ref":"e2"}}
{"id":4,"method":"close"}

You receive the results and events on 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

With --mcp, bruster uses the Model Context Protocol on stdio. Every native method becomes a tool. Screenshots return as image content, and page events return as notifications.

Common MCP client configs
// 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 uses mcp.servers in opencode.jsonc. See the client-specific MCP setup guide for complete configurations.

// VS Code (.vscode/mcp.json)
{ "servers": { "bruster": { "type": "stdio", "command": "bruster", "args": ["--mcp", "--quiet"] } } }

--mcp keeps the windows off-screen. Add --visible to see the browser. --hidden is not true headless mode: on Linux, WebKitGTK still requires an X11/Wayland display or Xvfb. When no display is set, Bruster automatically tries xvfb-run; install Xvfb if it is unavailable.

On Linux, hidden/MCP mode skips the desktop session bus to avoid waiting for unavailable desktop portals. Set BRUSTER_USE_SESSION_BUS=1 if you need desktop session integration in hidden mode. --visible uses the normal session bus.

Run

bruster [--mcp] [--hidden|--visible] [--quiet] [options]
flageffect
--mcpuse the Model Context Protocol on stdio instead of the native protocol. This option also sets --hidden
--hidden / --visiblemove the windows off-screen / show the windows
--quietsend stderr to /dev/null. This mutes GL, ALSA, and GTK noise
--viewport WxHinitial window size, default 1280x800
--user-agent UAreplace the user agent
--profile DIRkeep cookies and storage between runs
--proxy URLhttp://host:port or socks5://host:port
--init-script FILEJavaScript that runs in every page before its own scripts
--darkpersist dark color-scheme for this profile (or the default state); use light to reset
--insecureignore TLS errors (Linux only)
--no-imagesdo not load images. Pages load about 30% faster (Linux only)
Window and color controls

Native commands and MCP tools minimize and maximize target the specified tab (or the current tab), return "minimized" or "maximized", and persist the requested window mode. Each mode replaces the previous one. minimize hides the native window (rather than iconifying it); maximize restores visibility and maximizes. In hidden/MCP mode both commands are accepted and saved, but windows stay off-screen for rendering.

dark and light persist a color preference independently of window mode and apply it to all existing tabs, new tabs, and subsequent navigations. The portable page-level fallback sets the root CSS color-scheme (including native controls and default page colors); it does not emulate prefers-color-scheme media queries or recolor a site's explicit colors. Custom --init-script scripts still run.

Preferences are stored outside WebView data. With --profile PATH, metadata is a sibling of the canonical profile directory, named PATH.bruster-window.json. Without a profile, the file is:

  • Linux: $XDG_STATE_HOME/bruster/window.json, falling back to $HOME/.local/state/bruster/window.json.
  • macOS: $HOME/Library/Application Support/bruster/window.json.
  • Windows: %LOCALAPPDATA%/bruster/window.json.

Settings are profile-wide; the last successful command wins. Missing or malformed metadata uses defaults, and legacy window-only state files are still accepted. Persistence failures return protocol errors. OS window-manager changes are not saved. close shuts down the server and all tabs; close_tab or closing a window through the OS closes only that tab. Closing stdin also shuts down the server.

Linux uses software rendering. Hidden views skip off-screen GTK painting while remaining mapped for layout, animation, and native screenshots. Set BRUSTER_PAINT_HIDDEN=1 to enable those window paints. Hidden mode also defaults WEBKIT_DISABLE_DMABUF_RENDERER=1 to avoid an unnecessary graphics transport probe; an explicitly supplied value (including 0) takes precedence.

Automatic Xvfb launches disable GLX. BRUSTER_XVFB_ARGS overrides the server arguments (default: -screen 0 1280x1024x24 -nolisten tcp -extension GLX). Set BRUSTER_NO_XVFB=1 to prevent automatic Xvfb startup.

Tests

The Test Lab provides individual HTML/CSS/JavaScript fixtures with executable assertions. Cargo builds Bruster and runs 52 focused fixtures through both native JSONL and MCP (Python 3.10+ required; prefix with xvfb-run -a on headless Linux):

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

See test-lab setup and coverage for the complete core suite (full_test_lab), individual case filters, stress cases, pinned framework bundles, and reports. The Python runner also accepts an existing executable:

python3 scripts/test_lab.py run --binary target/release/bruster --case 'ref-*' --transport both

tests/run_all.sh [--rounds N] [--no-e2e] [--no-lab] runs the full test cycle: build, unit, smoke, edge, focused test-lab groups, a leftover-process check, MCP launch, and end-to-end tests including the published lab. --no-e2e keeps the cycle local; --no-lab omits both lab runs. On Linux, run the script under xvfb-run -a. CI runs the complete core lab on every platform and publishes release archives on v* tags.

The Linux desktop-portal startup regression requires D-Bus, python3-dbus, and python3-gi:

cargo build --release --locked
xvfb-run -a /usr/bin/python3 tests/startup_portal.py target/release/bruster

Protocol

One JSON object per line, in both directions. Elements are addressed by {"selector": "css"} or by {"ref": "eN"} from the last snapshot/find. With format: "text", a snapshot returns one line per element:

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

メモ

Same-origin hrefs lose the origin in the text format. Alert and prompt dialogs never block. bruster answers them as the current dialog setting specifies, and reports them as dialog events. beforeunload handlers are disarmed.

Calls routed through the page runtime (eval, url, title, snapshot, interactions and other DOM tools) have an outer request_timeout in milliseconds, defaulting to at least 30000 ms (or the requested timeout/time plus 5000 ms, whichever is longer). This deadline includes time spent waiting for navigation. Set it explicitly for unusually long operations. A timeout stops waiting for the reply; it does not interrupt JavaScript already running in the page. In particular, an infinite loop can make a web process unresponsive and may require restarting bruster. Late replies are discarded. Navigation uses its own timeout; native operations such as screenshots do not use request_timeout. MCP represents null results as the text null.

API

methodparamsresult
navigateurl, until? (load default, dom, idle), timeout? ms (default 30000){tab, url} on load/DOM/idle, or a failure on timeout, DNS/error, or download (Linux)
reload back forwardnone{url}, or null if there is nowhere to go
url titlenonestring
evalexpressionJSON value. Promises are awaited. Compiled as a script
snapshotselector?, max? (1000), boxes?, format? (native default json, MCP default text){url,title,elements[],truncated?} or text lines
findtext? or regex? + snapshot paramsfiltered snapshot
screenshotpath?, full?, clip? {x,y,width,height}{path,bytes} or {png_base64}. Full pages are capped at 16000 px
recttarget{x,y,width,height} viewport-relative
clicktarget or x,y; force?, timeout?null
hovertargetnull
filltarget, valuenull
fill_formfields: [{selector|ref, value}]null (checkboxes bool, selects string/array)
typetarget, text, delay?, submit?null
presstarget?, key (Enter, Control+a)null
selecttarget, valueselected values
checktarget, checked?bool
dragfrom target, to targetnull
uploadtarget, paths[]file names set on the input
scrolltarget or x,y deltas{x,y} current position
resizewidth, height (1 to 16000){width,height}
text htmltargetstring
attrtarget, namestring or null
countselectornumber
wait_forselector/ref + state? (visible, attached, hidden), text, textGone, url, idle, time ms; timeout? msnull
networkclear?fetch/XHR entries with index, method and status where available, plus resource timing entries
network_requestindexone entry with req_headers, res_headers, and body (first 16 KB)
consoleclear?[{level,text,ms}] console output and uncaught errors
dialogaccept?, text?, clear?dialogs seen. Sets the answer for the next dialogs
cookiesnonelist
set_cookiename, value, domain?, path? (/)null
new_taburl?, timeout? ms (default 30000){tab}, or {tab,url} after load; does not switch the current tab
tabsnone[{tab,url,current}]
switch_tabtabnull
close_tab(uses tab)null; closing the last tab is rejected (use close)
closenoneexits

Events

ready, navigating, load, tab_opened, tab_closed, dialog (type, message, accept), tls_error (Linux), load_failed, and download (Linux).

Limits

  • Input uses synthetic DOM events (isTrusted is false). You do not get :hover styles, native <select> popups, or OS-level shortcuts.
  • Network and console logs are patched in the page and reset on navigation. Network entries for fetch/XHR include status and an index; other resources use performance timings and may lack status or method. The document request is not included. Logs contain no request bodies. Use --proxy for real interception.
  • Cross-origin iframes are out of reach. Same-origin iframes and open shadow roots work.
  • Use HTTP(S) URLs for navigation. data: and file: URLs are unsupported; serve local pages over localhost instead.
  • bruster does not intercept native file choosers. Use upload instead of a click on a file input.
  • Without --profile, cookies and storage last for one session.
  • Full-page screenshots are capped at 16000 px. On macOS, very tall pages can be cut when they are higher than the screen.
  • WebKitGTK screenshots capture page content without non-overlay scrollbars, so their width can be narrower than the window viewport.
  • On Windows (WebView2), screenshot has no clip. --quiet does nothing. The Linux-only flags have no effect.
  • With --hidden, WebKit timer throttling can make setTimeout-driven pages slow. macOS WKWebView suspends animation frames in off-screen windows; use --visible for animation-driven workflows.

Development

  • bin/bruster runs the development build from this checkout.
  • tests/run_all.sh runs the build, unit tests, smoke tests, edge tests, test-lab groups, the MCP launch check, and end-to-end tests.
  • CI (.github/workflows/ci.yml) builds all platforms, runs the tests, and publishes release archives on v* tags.
  • Benchmarks: scripts/bench_compare.py compares five configurations; scripts/bench_footprint.py inventories runtime files and scripts/bench_report.py validates and publishes results. See setup and methodology.
  • Test Lab: tests/test_lab.rs integrates the shared fixtures into Cargo; scripts/test_lab.py builds, serves, and runs them. See case authoring and verification.
  • Website: site/ contains the GitHub Pages source. See local preview and publishing.

License

MIT License

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。