@vernikr/browser-agent-mcp
v1.0.4
Published
MCP server that gives LLM agents a real headful Chrome (X11 mouse, Cloudflare Turnstile auto-solve) via the browser-agent-server daemon. Companion: github.com/vernikr/browser-agent
Maintainers
Readme
@vernikr/browser-agent-mcp
🔗 Companion project:
vernikr/browser-agent(PyPIbrowser-agent-server) — the real-Chrome-on-Xvfb daemon this MCP server talks to over its HTTP API. The two projects are developed together; the contract isdocs/api.md.
MCP server that gives LLM agents a real desktop browser. Your agent gets four tools — browser_status, browser_fetch, browser_action, browser_agent — backed by headful Chrome on Xvfb with a hardware-level X11 mouse (Bézier curves, isTrusted: true clicks), Cloudflare Turnstile auto-solve and zero-leak CDP. The heavy lifting happens on a Linux host running browser-agent-server; this bridge is a thin, well-behaved MCP citizen in front of it.
Quickstart
# 0. Have a daemon reachable: install browser-agent-server on a Linux host (see the companion repo),
# then open a route to it (default: SSH local forward to 127.0.0.1:8766)
pnpm dlx @vernikr/browser-agent-mcp tunnel start --ssh user@host
# 1. Point your agent at the bridge — writes the MCP config for you
pnpm dlx @vernikr/browser-agent-mcp init --client claude-code # also: claude-desktop | cursor | freebuff | gemini-cli
# 2. Verify end-to-end
pnpm dlx @vernikr/browser-agent-mcp doctorpnpm not available? Every command also works as npx -y @vernikr/browser-agent-mcp …. init --runner npx writes configs as npx -y @vernikr/browser-agent-mcp@latest — the quickest route to fresh releases (see below).
The MCP config written by init (manual form):
{
"mcpServers": {
"browser-agent": {
"command": "pnpm",
"args": ["dlx", "@vernikr/browser-agent-mcp"],
"env": { "BROWSER_AGENT_URL": "http://127.0.0.1:8766" }
}
}
}Getting bridge updates
| Config | Fresh release arrives | Why |
|---|---|---|
| pnpm dlx @vernikr/browser-agent-mcp (also @latest) | ≤ 24 h | pnpm caches the resolved dlx environment for (dlxCacheMaxAge, default 1440 min) — even for @latest |
| npx -y @vernikr/browser-agent-mcp@latest | ≈ 5 min | npx always resolves the latest dist-tag over the network; the only cache is the registry packument's Cache-Control: public, max-age=300 |
| pinned, e.g. …@1.0.2 | never (by design) | reproducible |
So: want prompt auto-updates (recommended for MCP clients, which restart the bridge on launch) → use the npx runner: pnpm dlx @vernikr/browser-agent-mcp init --client <you> --runner npx, or hand-write the config above with @latest. Sticking to a pnpm-only toolbox? pnpm dlx still updates — within a day; to force now: pnpm --config.dlx-cache-max-age=0 dlx @vernikr/browser-agent-mcp@latest doctor.
Tools
| Tool | What it does | Notes |
|---|---|---|
| browser_status | Daemon/X11/Chrome/mouse/WARP status | read-only; call before a fetch wave |
| browser_fetch | Open URL in real Chrome, Turnstile auto-solve, return text/HTML/cookies | save_text_to / save_html_to keep megabytes out of context; include_screenshot returns MCP image content |
| browser_action | Single-step driving: goto/move/click/type/key/scroll/screenshot/stop | hardware X11 events (no CDP input); return_screenshot saves a round trip |
| browser_agent | Vision-guided computer use: URL + goal → it clicks/types to the answer | slow & costly on small hosts — only for pages plain fetch can't handle |
Errors come back structured: browser-agent-mcp error (<kind>): <message> + a hint: line (network_error, rate_limit, auth_or_bot_wall, timeout, server_error), so agents can branch without parsing prose.
Configuration (env)
| Var | Default | Meaning |
|---|---|---|
| BROWSER_AGENT_URL | http://127.0.0.1:8766 | where the daemon's HTTP API is reachable (tunnel/VPN/localhost) |
| BROWSER_AGENT_TIMEOUT_MS | 180000 | per-attempt timeout; cold start after hibernation takes seconds — keep ≥60s |
| BROWSER_AGENT_ATTEMPTS | 3 | retries on transient failures (network/408/429/5xx) with backoff + Retry-After |
| BROWSER_AGENT_LOG_FILE | $XDG_STATE_HOME/browser-agent-mcp/logs/mcp-browser-agent.jsonl | rotating-friendly jsonl with secret redaction |
| MCP_LOG_LEVEL | info | debug for HTTP-level traces |
CLI
browser-agent-mcp # MCP server on stdio (what agents run)
browser-agent-mcp --http [--port 8767] # Streamable HTTP at 127.0.0.1:8767/mcp
browser-agent-mcp --selfcheck [--offline]
browser-agent-mcp doctor [--json] [--url …]
browser-agent-mcp init --client <agent> [--user] [--runner pnpm|npx] [--print]
browser-agent-mcp tunnel {start|ensure|check|stop|vnc} --ssh user@host--selfcheck needs no network with --offline (in-process handshake); without it, also probes the daemon and checks api_version compatibility.
For AI agents
- Install one-liner:
pnpm dlx @vernikr/browser-agent-mcp init --client <your-host>then… doctor. - Daemon side (the thing
BROWSER_AGENT_URLpoints at):browser-agent-serveron PyPI — install & provisioning guide in the companion repo. - Before a fetch wave:
browser_status. If a fetch returnsblocked: true, retry once withuse_proxy: true; a persistent login wall is a human item, not a retry loop.
Docs
docs/mcp-clients.md— ready-made configs per agent hostdocs/troubleshooting.md— tunnel, cold start, 429/403 playbook- HTTP contract:
browser-agent/docs/api.md
License
MIT — see LICENSE.
