Getting started
browxai is an MCP server that gives an AI agent a curated browser-control surface. It runs over stdio and is driven by any MCP client.
Install
Section titled “Install”You need Node 22 or newer (node --version tells you). browxai drives the
Google Chrome you already have installed, so a machine with Chrome needs no
browser download.
npm install -g browxaibrowxai doctorbrowxai doctor checks the environment and prints one line per area, with a tick
or a cross and the next step under anything that fails. browxai doctor --verbose
prints every check. On a machine with no Google Chrome it fails until you add a browser:
install Chrome, or fetch the bundled Chromium (about 150 MB).
npx playwright-core@1.64.1 install chromiumA bare Linux image also lacks the system libraries Chromium needs. Add
--with-deps to that command to install them (it needs root).
Firefox and WebKit sessions use their own Playwright builds
(npx playwright-core@1.64.1 install firefox webkit).
A global install puts the browxai binary on your PATH, so an MCP client can
launch it by name (command: "browxai"). The binary is the MCP server on the
stdio transport. Run by hand in a terminal it just waits for a client, so use
browxai doctor to check the machine instead: it reports the Node version, the
browser, the workspace and your configuration.
On Linux and macOS, npm install -g can fail with EACCES when npm’s global
prefix sits in a root-owned directory. Don’t reach for sudo. Either skip the
global install and use npx -y browxai as the client’s command (how to wire it into a
client), or give npm a prefix in your home directory:
npm config set prefix ~/.npm-globalThen add ~/.npm-global/bin to your PATH and run the install again.
browxai launches the Google Chrome already installed on the machine, on one
default profile per workspace (<workspace>/profile), so logins carry over
between sessions. It looks for Google Chrome at its default install path on each
OS, so a distro Chromium package is not picked up. When there is no Chrome it
falls back to Playwright’s bundled Chromium. browxai doctor fails only when
neither browser is present.
Wire it into an MCP client
Section titled “Wire it into an MCP client”The quickest way is one command, run in your project:
browxai init .It writes a .mcp.json in that directory, finds the MCP clients on your machine
(Claude Code, Cursor, Codex and Claude Desktop) and prints the exact command or
snippet for each one. It also adds browxai to the user-level config of each of
Cursor, Codex and Claude Desktop it finds, for example ~/.cursor/mcp.json. It
prints the change first. A file that exists is merged, and the old copy is kept
as <config>.browxai-bak. Pass --no-write-user-config to leave those files
alone, or --no-write to print everything and write nothing. An older
--write-user-config still works and does nothing extra. A file init will not edit
(not plain JSON, or one that already has a browxai entry) is left as it is. A read
or write error on a config makes init exit with code 1, after it tried every client. At the end it opens a
headless private session on a blank page, takes a snapshot and closes it, then
prints ok: first snapshot in N ms. If that fails, init says what to fix and
exits with code 1. Add --no-smoke to skip that check.
To do it by hand instead, add browxai to your client’s MCP server config. In Claude Code, one command does it:
claude mcp add browxai -- browxaiRestart the client after any config change, then check that browxai shows as
connected (in Claude Code, run /mcp).
Every client below runs the same command, browxai. Without a global install,
use npx -y browxai instead (claude mcp add browxai -- npx -y browxai).
Add this to ~/.codex/config.toml, or to .codex/config.toml in a project.
Or run codex mcp add browxai -- browxai.
[mcp_servers.browxai]command = "browxai"startup_timeout_sec = 30tool_timeout_sec = 120The longer startup timeout helps when the client launches browxai through
npx -y, which can take a while on first run. Options go in an env table:
env = { BROWX_HEADLESS = "1" }.
Cursor
Section titled “Cursor”Add this to ~/.cursor/mcp.json for all projects, or .cursor/mcp.json for one:
{ "mcpServers": { "browxai": { "command": "browxai" } }}Other clients
Section titled “Other clients”Each client keeps its list of servers under its own key in its own file.
- Claude Desktop: key
mcpServers. macOS~/Library/Application Support/Claude/claude_desktop_config.json, Windows%APPDATA%\Claude\claude_desktop_config.json. - VS Code: key
servers, in.vscode/mcp.json. - Windsurf: key
mcpServers, in~/.codeium/windsurf/mcp_config.json. - Zed: key
context_servers, insettings.json. Its entry has a different shape, so copy it from Zed’s MCP docs.
For the three JSON clients, the entry is "browxai": { "command": "browxai" }
under that key, as in the Cursor example.
By default the server launches a managed Chrome on the workspace’s default
profile, headed, with the default capability set (read, navigation,
action, human). That is the installed Google Chrome, or the bundled
Chromium with a logged warning when Chrome is absent. Every capability outside
that set is opt-in.
A headed browser needs a display. On a machine without one, such as a Linux
server or a container, the first session fails to open until you set
BROWX_HEADLESS=1 in the server’s environment. In a JSON config that is an
env entry next to command: "env": { "BROWX_HEADLESS": "1" }. With
Claude Code, add --env BROWX_HEADLESS=1 to claude mcp add.
Common environment variables
Section titled “Common environment variables”| Variable | Purpose |
|---|---|
BROWX_WORKSPACE | Where all transient state lives (default ~/.browxai/). Never cwd. |
BROWX_HEADLESS | 1 or true launches headless. |
BROWX_CAPABILITIES | The full comma-separated capability set. It replaces the default, so keep read,navigation,action,human and add eval, network-body, clipboard, or file-io to opt into gated tools. |
BROWX_ENGINE | Default engine, chromium unless set. Also --engine <kind>. The values are in the FAQ. |
BROWX_ATTACH_CDP | Loopback CDP endpoint to attach to an existing Chrome (BYOB). Needs byob-attach in BROWX_CAPABILITIES too: read,navigation,action,human,byob-attach. |
See the tool reference for the full configuration surface, and note that capabilities are resolved once at server start: changing them means restarting the server.
A first flow
Section titled “A first flow”A typical agent loop:
navigateto a URL.snapshotto get the accessibility tree plus DOM-walk; every node has a stable[ref=eN].findto describe the target in natural language; get ranked candidates with astabilityflag, anactionableverdict, and a visible-rectbbox.click/fill/ … to act byref; each returns a structuredActionResultdescribing what navigated, what structure changed, and a console/network slice.
For verification use text_search, inspect, and the read tools; for
flaky or transient UI use wait_for, sample, and act_and_sample.
Try it with a prompt such as “open https://example.com, snapshot it and tell me
what the page says”. The agent calls navigate and snapshot. The paragraph text
comes back on its row, and the heading and link come back as refs it can click. A Chrome window opens on a machine
with a display. Headless runs show no window.
When something does not work
Section titled “When something does not work”Run browxai doctor. For an error string, see Troubleshooting.
Where to go next
Section titled “Where to go next”- Tool reference is every tool, its inputs and outputs, example calls, the configuration and session model, and the stability policy.
- Agent guidance is the reach-for-this-not-that map: the footguns agents hit and the curated tool that avoids each one.
- Configuration and Recipes cover config layers and copy-adaptable flows.
- Security and threat model is the capability model, what browxai defends against, and what it explicitly does not.