MCP
Browsergator
Multi-agent Chrome MCP gateway. One browser, many AI agents. Replaces 20 duplicate chrome-devtools-mcp processes with a single coordinated gateway using per-tab FIFO queues, leases, and audit logging.
Implementation
// Browsergator — multi-agent Chrome MCP gateway
// One browser, many agents. No conflicts.
// Before: each agent spawns its own chrome-devtools-mcp
// Codex → chrome-devtools-mcp → Chrome (page conflicts!)
// Claude → chrome-devtools-mcp → Chrome (duplicate sessions!)
// Gemini → chrome-devtools-mcp → Chrome (20 processes!)
// After: all agents share one Browsergator gateway
// Codex ─┐
// Claude ─┼─ Browsergator ─ one CDP connection ─ Chrome
// Gemini ─┘
// 1. Start Chrome with CDP enabled
// chrome --remote-debugging-port=9222
// 2. Start Browsergator
// npx browsergator-mcp
// 3. Connect agents via Streamable HTTP
// MCP endpoint: http://127.0.0.1:8788/mcp
// Auth: Bearer <token>
// Available MCP tools:
interface BrowsergatorTools {
list_tabs(): Tab[];
open_tab(url: string): Tab;
close_tab(pageId: string): void;
navigate(pageId: string, url: string): void;
snapshot(pageId: string): string; // DOM snapshot
screenshot(pageId: string): string; // base64 PNG
claim_tab(pageId: string, leaseOwnerId: string): Lease;
release_tab(pageId: string, leaseOwnerId: string): void;
run_atomic(pageId: string, steps: Step[]): Result[];
}
// Key concepts:
// - pageId: explicit Chrome target ID (no guessing)
// - leaseOwnerId: agent claims exclusive tab access
// - FIFO queue: mutations serialized per tab
// - Protected tabs: lease-holders block other writers
// - Reads bypass queue: snapshots/screenshots never block
// Claude Code config (.mcp.json):
const mcpConfig = {
"mcpServers": {
"browser-gateway": {
"type": "streamable-http",
"url": "http://127.0.0.1:8788/mcp",
"headers": {
"Authorization": "Bearer <your-token>"
}
}
}
};Usage
Start Chrome with --remote-debugging-port=9222, run npx browsergator-mcp, configure agents to connect to http://127.0.0.1:8788/mcp with Bearer token auth.
Examples
Input:
Output:
list_tabs()Output:
Array of open Chrome tabs with pageId, title, urlInput:
Output:
claim_tab(pageId, "claude-agent-1")Output:
Lease granting exclusive write access to the tabInput:
Output:
run_atomic(pageId, [{navigate: url}, {snapshot: {}}])Output:
Navigate + snapshot in single atomic operation