xspace-browser-mcp-bridge
v5.0.2
Published
MCP bridge that connects AI agents (Cursor, Claude Code, VS Code Copilot, etc.) to the xspace-browser browser extension. Auto-spawns a shared daemon to support multiple simultaneous clients.
Maintainers
Readme
xspace-browser-mcp-bridge
MCP server that connects AI agents (Cursor, Claude Code, VS Code Copilot, etc.) to the xspace-browser browser extension. Each agent runs a thin stdio bridge that auto-spawns a single shared daemon, so multiple agents — and multiple browsers — can be driven at once.
How it works
Cursor ──stdio──▶ bridge ──┐
Claude Code ──stdio──▶ bridge ──┼─WS /bridge─▶ daemon ─WS /extension─▶ xspace-browser extension(s)
VS Code ──stdio──▶ bridge ──┘- Each AI agent launches its own
xspace-browser-mcp-bridgeprocess over stdio. - The first bridge to start auto-spawns a shared daemon on
localhost:9223; later bridges connect to the same daemon. The daemon self-terminates when idle. - The daemon exposes WebSocket endpoints:
/extension— the xspace-browser Chrome extension(s) connect here/bridge— stdio bridge instances connect here/cli— thexspace-browser-clitool connects here/health— HTTP health check
Quick start
1. Configure your AI agent
The bridge speaks MCP over stdio and is launched on demand by the agent — there is nothing to start manually.
Cursor (.cursor/mcp.json or ~/.cursor/mcp.json):
{
"mcpServers": {
"xspace-browser": {
"command": "npx",
"args": ["-y", "xspace-browser-mcp-bridge"]
}
}
}Claude Code:
claude mcp add xspace-browser -- npx -y xspace-browser-mcp-bridgeVS Code Copilot (.vscode/mcp.json):
{
"servers": {
"xspace-browser": {
"command": "npx",
"args": ["-y", "xspace-browser-mcp-bridge"]
}
}
}2. Connect the xspace-browser extension
- Open Chrome → xspace-browser extension → Options page → MCP WebSocket Bridge.
- Set a Name for this browser (defaults to a random name; pick something
memorable like
workorpersonal). - Set the WebSocket URL to
ws://localhost:9223/extensionand click Connect.
Your AI agents can now control the browser through xspace-browser.
Multiple browsers
More than one browser profile can connect to the same daemon simultaneously, each under a distinct Name. Names must be unique — a second connection trying to use a name already in use is rejected (the extension shows a "name already in use" notice).
When two or more browsers are connected, the daemon will not guess which one to drive. The agent must pick a target for its session using two meta-tools:
list_browsers— lists the connected browsers and which (if any) is selected.select_browser— selects a browser by name for the current agent session; subsequent tool calls route to it.
If a tool is called while multiple browsers are connected and none is selected, the
call returns an error listing the available names and asking you to call
select_browser first. The selection is per agent session, so different agents can
drive different browsers at the same time. If the selected browser disconnects, the
next call errors and asks you to re-select (it never silently falls back to another
browser). With exactly one browser connected, selection is unnecessary and calls
route to it automatically.
Options
The daemon's bind options can be passed through the bridge:
npx xspace-browser-mcp-bridge [--port <port>] [--host <host>] [--profile <profile>]| Option | Default | Description |
| --------------------- | ----------- | ----------------------------------------------------------- |
| --port <port> | 9223 | Daemon port |
| --host <host> | 127.0.0.1 | Bind address (0.0.0.0 to allow remote/Docker connections) |
| --profile <profile> | full | Session capability profile (see below) |
| --help, -h | | Show help message |
| --version, -v | | Show version |
Security: token + session capability profiles
Local token. The daemon requires a per-machine token on /bridge and /cli
connections — reaching the port is not enough to drive the browser. The token
lives in ~/.xspace-browser/bridge-token (created on first use, mode 0600);
the bridge and CLI read the same file, so same-user clients need zero
configuration. Foreign processes without the token get 401. The
/extension endpoint is protected by the origin allowlist instead (browser
WebSockets cannot set headers).
Capability profiles. Every /bridge / /cli session declares a profile;
the daemon enforces it at the protocol layer — a denied call never reaches the
extension:
| Profile | Allowed | Rejected |
| ---------------- | ------------------------------------------------------------------ | ---------------------------------------------------- |
| probe-readonly | perception (search/screenshot/get_xxx/wait_for) + tab navigation | all interaction tools, evaluate_script, mutations |
| test-execute | full interaction on session tabs | set_proxy, downloads, tab (un)grouping |
| full (default) | everything | — |
Tab isolation. Under non-full profiles a session may only target tabs it
created itself (create_new_tab); calls with a foreign tabId — or
active-tab tools that cannot be scoped — are rejected with a hint.
Named sessions (CLI). The CLI opens one connection per invocation, so multi-step flows under non-full profiles must name a session to share its tab set across calls:
xspace-browser-cli create_new_tab --url https://a.com --profile probe-readonly --session probe1
xspace-browser-cli search_elements --tabId <id> --query "button*" --profile probe-readonly --session probe1Env fallbacks: XSPACE_BROWSER_PROFILE, XSPACE_BROWSER_SESSION.
You can also run the daemon directly with xspace-browser-mcp-daemon [--port <port>] [--host <host>].
xspace-browser CLI
Command-line tool for controlling the browser directly from the terminal. It
connects to the daemon's /cli WebSocket endpoint (auto-spawning the daemon if
needed).
Usage
xspace-browser-cli <tool_name> [--param value ...]
xspace-browser-cli --list # List all tools
xspace-browser-cli --help <tool_name> # Show tool parameters
xspace-browser-cli --json '{"name":"...","arguments":{...}}' # Raw JSONExamples
xspace-browser-cli get_all_tabs
xspace-browser-cli create_new_tab --url https://example.com
xspace-browser-cli search_elements --tabId 123 --query "button*"
xspace-browser-cli click --tabId 123 --uid btn-42
xspace-browser-cli capture_screenshotEnvironment Variables
| Variable | Default | Description |
| -------------------------------- | ------------------------- | -------------------------- |
| XSPACE_BROWSER_WS_URL | ws://localhost:9223/cli | Daemon WebSocket URL |
| XSPACE_BROWSER_CONNECT_TIMEOUT | 60000 | Max ms to wait for daemon |
Compatibility
Bridge 5.x with an older (pre-test-layer) extension: the connection itself
still works — /extension is not token-gated — but the M1–M4 test-capability
tools (console/network evidence, wait_for, evaluate_script,
get_element_locators, audit_accessibility, cookies/storage, CDP trace
export, sanitized action recording, etc.) require a matching 5.x extension
build. Calling them against an older extension fails with "unknown tool".
Upgrade the extension from the store (or load the matching build unpacked) to
use the test-capability layer.
When the extension connects to /extension it now performs a register
handshake (sending its name and a stable instance id) so the daemon can support
multiple named browsers. This is a breaking protocol change:
- Bridge
4.xrequires an xspace-browser extension build that supports named connections. An older extension that does not send the register handshake is closed by the daemon after a short timeout and cannot connect. - Publish this bridge version together with the matching extension release, and keep the major versions in step. If you upgrade only one side, connections will fail.
Requirements
- Node.js >= 18
- xspace-browser Chrome extension installed (not needed for Docker image), version with named-connection support
License
MIT
