🔗 Companion project:
@vernikr/browser-agent-mcp— the MCP server that exposes this daemon to LLM agents (Claude Code, Cursor, Freebuff…). The two projects are developed together and speak the HTTP contract indocs/api.md.
Real headful Chrome on Xvfb with a hardware-level X11 mouse. One localhost daemon gives any project, script, or AI agent on a Linux box a genuine desktop browser: steered over real XTEST input events on randomized Bézier paths, with zero-leak CDP (no Runtime.enable), Cloudflare Turnstile auto-solve, and RAM discipline for tiny VPSes (auto-hibernates when idle — browser-agent doctor reports what it actually costs).
Why not Playwright/CDP directly: mainstream automation stacks call Runtime.enable / Debugger.enable on connect — the primary headless-detection vector. This daemon's CDP client refuses those methods by construction and reads the DOM via DOM.getOuterHTML; all mouse/keyboard input goes through the X server, so clicks are isTrusted: true hardware events.
curl -LsSf https://astral.sh/uv/install.sh | sh # if uv is missing
uv tool install browser-agent-server
sudo browser-agent setup --with-chrome # apt deps + google-chrome-stable + systemd unit
sudo browser-agent doctor # self-checkNo systemd (container, WSL, a supervisor of your own)? The same install works —
--no-unit skips the unit file and you run the daemon yourself:
uv tool install browser-agent-server
sudo browser-agent setup --no-apt --no-unit # chrome only; deps already in the image
browser-agent doctor # self-check
browser-agent serve & # foreground/background under your supervisorUse it three ways:
browser-agent fetch "https://example.com" --text # CLI
curl -s 127.0.0.1:8765/status # HTTP API (any language)Driving a live session over SSH needs no bridge — every action the daemon implements is a subcommand:
browser-agent goto "https://example.com" # navigate the session
browser-agent screenshot /tmp/page.png # capture the X11 window
browser-agent html # read the page back
browser-agent move 640 360 && browser-agent click 640 360
browser-agent type "hello" --submit # then press Return
browser-agent key Page_Down
browser-agent scroll --clicks 5 --direction downfrom browser_agent import BrowserClient # Python SDK
client = BrowserClient()
page = client.fetch("https://example.com")
print(page["title"], len(page["text"]))Point the MCP bridge at this daemon — details and ready-made agent configs live in the companion repo:
pnpm dlx @vernikr/browser-agent-mcp init --client claude-codedocs/deployment.md— provisioning, systemd, memory limits, WARP, VNC loginsdocs/api.md— HTTP contract (v1)docs/architecture.md— how and why it worksdocs/security.md— trust boundaries (loopback-only, no auth)docs/troubleshooting.md— symptom → cause → action
Install one-liner: uv tool install browser-agent-server && sudo browser-agent setup --with-chrome && browser-agent doctor
No-systemd host (container/WSL): uv tool install browser-agent-server && sudo browser-agent setup --no-apt --no-unit && browser-agent serve &
Self-check: browser-agent doctor --json (exit 0 = host ready; every failed check carries a fix command you can run).
Companion MCP for agent hosts: vernikr/browser-agent-mcp.
SSH-only agent, no bridge: the CLI drives the whole session — goto, move, click, type, key, scroll, screenshot, html, stop. Every one is a subcommand, so nothing needs the MCP layer to be installed.
Linux/X11 only (Xvfb, XTEST). Works great on a 1 vCPU / 1 GB RAM VPS. macOS/Windows workstations should run the MCP bridge and talk to a Linux host running this daemon.
MIT — see LICENSE.
