browser-relay
Provides isolated browser automation for Google Chrome, managing separate Chrome instances per session to allow parallel agents to work independently without sharing tabs, cookies, or login state.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@browser-relayOpen https://example.com in a new isolated browser session called task-1"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
English | 简体中文
browser-relay — Multi-Session Browser-Isolated MCP
One MCP endpoint, N isolated browsers.
An MCP multiplexer: to your IDE / MCP host (ZCode, Claude Desktop, Codex CLI, dsh, …) it looks like a single, ordinary Playwright MCP server, but internally it routes every call tagged with a session_id to a dedicated @playwright/mcp child process for that id — so every session / subagent gets a fully isolated Chrome of its own (separate profile, separate tabs, cookies invisible to each other).
IDE (registers one MCP entry: browser-relay, stdio)
└─ relay.mjs
├─ session_id "task-1" → child playwright-mcp --isolated → Chrome #1
├─ session_id "task-2" → child playwright-mcp --isolated → Chrome #2
└─ ... (concurrency cap, idle reaping, crash auto-restart, full teardown on exit)Within one relay process, different ids are isolated from each other. Different host sessions each spawn their own relay process, so even colliding ids are naturally isolated (process-level backstop).
Why
When multiple subagents / tasks run in parallel and share one playwright MCP, they share one browser: tabs stomp on each other, login state leaks between agents, one agent closes the page another agent is reading. browser-relay gives every session a browser of its own, while the host only registers a single MCP entry.
Related MCP server: chrome-devtools-mcp-mux
Prerequisites
Node.js ≥ 18.
Install the original (upstream) playwright MCP server — all real browser automation is done by it:
npm install -g @playwright/mcpReady a browser.
@playwright/mcpdrives the locally installed Google Chrome by default:npx playwright install chromeNo Chrome, or prefer the bundled Chromium? Run
npx playwright install chromium, then pass--child-arg --browser --child-arg chromiumto the relay (forwarded to every child process).A global install is not mandatory: when the relay cannot find a global
@playwright/mcp, it falls back tonpx -y @playwright/mcp@0.0.82(downloaded on first run; version is pinned — a global install is recommended to follow upstream updates). You can also point theRELAY_MCP_PATHenvironment variable or the--mcp-pathoption directly at the upstreamcli.js.
Install & Run
git clone https://github.com/CarrotHu-secret-workstation/mcp-browser-relay.git
cd mcp-browser-relay
npm install
node relay.mjs --help # show options
node relay.mjs # start (stdio, foreground)Or skip the clone and run straight from GitHub with npx:
npx github:CarrotHu-secret-workstation/mcp-browser-relay --helpRunning node relay.mjs on its own just waits on stdio — that is normal; that is how an MCP server gets launched by its host. To see it in action, register it with your MCP host as described below.
Hooking It into an MCP Host
Ground rules:
Register only this one entry per session; if you previously had a direct
@playwright/mcpentry, disable it so you don't end up with two sets of near-identical tools.MCP connections are established when a session starts — newly opened sessions only.
commandis alwaysnode(or the absolute path to node on your machine);argspoints at the repo'srelay.mjs.
ZCode (~/.zcode/cli/config.json; field names may vary by version):
{
"mcpServers": {
"browser-relay": {
"command": "node",
"args": ["/path/to/mcp-browser-relay/relay.mjs"]
},
"playwright": { "enabled": false }
}
}Claude Desktop / other JSON-configured hosts:
{
"mcpServers": {
"browser-relay": {
"command": "node",
"args": ["/path/to/mcp-browser-relay/relay.mjs"]
}
}
}Codex CLI (~/.codex/config.toml):
[mcp_servers.browser-relay]
command = "node"
args = ["/path/to/mcp-browser-relay/relay.mjs"]
startup_timeout_sec = 60dsh (profile overlay patch, e.g. ~/.dsh/profiles/<profile>/cordis.patch.yml):
- insert:
- id: mcp-browser-relay
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: browser-relay
transport: stdio
command: node
args:
- /path/to/mcp-browser-relay/relay.mjsVerify with whatever your host offers (codex mcp list, dsh --profile web --dump-config, …). Once connected you will see the full upstream tool set (25 browser_* tools as of 0.0.82) plus the relay's own relay_status.
Rolling back / disabling: delete or enabled: false the entry above and restore your direct playwright entry.
Usage
Tool names are identical to @playwright/mcp; every tool takes one extra required parameter session_id:
browser_navigate { session_id: "task-1", url: "https://example.com" }session_idrules:[A-Za-z0-9_-]{1,64}. Missing or invalid → immediate error asking you to fix it.Different id = a completely different Chrome. Multiple agents sharing one id = sharing one browser (shared login state) — that is a feature.
relay_status { }lists active sessions (id / pid / idle time / concurrency cap); passsession_idto inspect a single one.
Assigning ids from the orchestrator (key discipline)
The session_id is assigned by the main session: when spawning a subagent, put the id in its prompt. Template:
For browser work, use only the
mcp__browser-relay__*tools and passsession_id: "task-3"on EVERY call (that browser is yours alone). Do not use any other session_id.
Naming suggestion:
<task>-<n>(e.g.audit-1,crawl-2); the orchestrator guarantees uniqueness.To keep login state across relay restarts, start the relay with
--profile-root <dir>: each id's profile persists at<dir>/<session_id>(the default--isolatedis an in-memory profile, wiped when the browser is reaped).
relay.mjs Options
Option | Default | Description |
| auto | Cap on concurrent child browsers. Default: computed at every relay start as |
| 1800000 | Reap an id's browser after this much idle time (0 = never) |
| off | Headless child browsers (default headed, so you can eyeball the multiple Chromes) |
| none | Enable a persistent per-id profile (default |
| auto | Path to the upstream |
| none | Extra argument forwarded to every child playwright-mcp (repeatable) |
The RELAY_MCP_PATH environment variable is equivalent to --mcp-path.
Known Limitations
Identity is "discipline + schema validation" grade: any caller can claim someone else's id. The orchestrator's id assignment discipline is the single source of isolation; colliding ids share a browser (exploitable on purpose).
Upstream capabilities follow
@playwright/mcpupgrades automatically (the tool list is aggregated from the child at startup).The concurrency cap takes effect per relay process: each host session spawns its own relay, which sizes itself from remaining memory at its own start (earlier sessions get a bigger quota, later ones shrink — natural first-come-first-served). The value stays fixed for the lifetime of the process. 400 MiB is a coarse per-browser budget (including all its child processes and pages); tune it to your machine.
Developed and verified on Windows; the macOS/Linux code paths (POSIX signals, process-tree kill, npx fallback) are in place but untested — issues and PRs welcome.
Acknowledgements
Every bit of browser capability in this project stands on the shoulders of the following projects — our respect and thanks:
@playwright/mcp (Apache-2.0, Microsoft) — the real upstream Playwright MCP server. The relay is just a session pool + forwarder: launching every Chrome, the whole
browser_*tool set, snapshots / screenshots / clicks / typing — all done by it.Playwright (Apache-2.0, Microsoft) — the foundation under all of the above: the cross-browser automation engine.
Model Context Protocol and the official TypeScript SDK @modelcontextprotocol/sdk (MIT, © Anthropic, PBC and community contributors) — the MCP protocol and SDK that make "one host, one stdio, bidirectional forwarding" possible.
Inspired by a real pain point: the browser turf war between parallel agents. This repo is a thin layer of glue — upstream upgrades (new tools, new capabilities) are picked up with zero code changes. Without the projects above, this repository would not exist.
License
This project's code is released under the MIT license.
Third-party licenses and copyright notices: see THIRD_PARTY_NOTICES.md —
@playwright/mcp and playwright are Apache-2.0; @modelcontextprotocol/sdk is MIT.
This repository does not copy or modify their source code; they are used at runtime as npm dependencies. The notices file exists for compliance and as a tribute.
This server cannot be deployed
Maintenance
Related MCP Connectors
A paid remote MCP for AI agent browser MCP session, built to return verdicts, receipts, usage logs,
MCP server for Superserve sandboxes: create, exec, and manage Firecracker microVMs
Hosted MCP memory and agent control plane for durable conversations, jobs, and operations.
Agent-native collaboration network: orchestrate a team of long-running agents from any MCP client.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA multi-agent orchestrator that enables multiple AI agents to share a single Chrome browser instance with tab isolation and shared state. It preserves local browser data like cookies and logins while allowing concurrent agent sessions through the official Playwright MCP.10-
- AlicenseAqualityDmaintenanceEnables multiple MCP clients to share a single Chrome instance while maintaining isolated tab sessions for each client. It acts as a multiplexer between clients and the chrome-devtools-mcp server, preventing tab conflicts across different sessions like Claude Code windows.297 npm5Apache 2.0
- AlicenseAqualityCmaintenanceMulti-agent Playwright MCP server with tab isolation via targetId, enabling multiple agents to share a single Chrome browser while maintaining isolated tab groups and shared sessions.142 npm3MIT
- AlicenseAqualityDmaintenanceAn MCP server that runs concurrent, session-isolated Playwright browser contexts, so many agents can each drive their own browser at the same time without colliding.2312 npm4MIT