ultimate-playwright-mcp

ultimate-playwright-mcp

Multi-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.

Category
Visit Server

README

Ultimate Playwright MCP

npm version npm downloads license CI

Multi-agent Playwright MCP server with tab isolation via targetId. Allows multiple Claude instances (or other MCP clients) to share a single Chrome browser while maintaining isolated tab groups.

Why Ultimate Playwright?

The official @playwright/mcp gives you browser control for a single agent. But what if you have multiple agents sharing one browser?

Ultimate Playwright MCP solves this with tab group isolation:

  • šŸ”€ Multi-agent tab groups — Each agent creates a groupId and only sees its own tabs
  • šŸŖ Shared cookies & sessions — All agents share the same BrowserContext (log in once, everyone's authenticated)
  • šŸŽØ Visual Chrome tab groups — Companion extension organizes tabs into color-coded Chrome tab groups
  • šŸ’¾ Persistent registry — Tab groups survive MCP server restarts (~/.ultimate-playwright-mcp/tab-groups.json)
  • šŸ”Œ Connect to existing Chrome — Uses CDP to attach to your running Chrome (keeps your profile, extensions, bookmarks)

Comparison

Feature ultimate-playwright-mcp @playwright/mcp browser-use-mcp
Multi-agent tab isolation āœ… Tab groups with groupId āŒ Single session āŒ Single session
Shared cookies across agents āœ… Same BrowserContext N/A N/A
Connect to existing Chrome āœ… CDP āŒ Launches new browser āŒ Launches new browser
Visual tab groups in Chrome āœ… Extension āŒ āŒ
Persistent tab registry āœ… Survives restarts āŒ āŒ
Accessibility tree snapshots āœ… Element refs (e1, e2…) āœ… āŒ Screenshot-based
Open source āœ… MIT āœ… Apache-2.0 āœ… MIT

Features

  • āœ… Tab Isolation - Each agent gets its own tabs via unique targetId
  • āœ… Shared Cookies - All agents share the same BrowserContext (cookies, sessions, localStorage)
  • āœ… Parallel Execution - Multiple agents can operate simultaneously without interference
  • āœ… CDP Connection - Connects to existing Chrome via Chrome DevTools Protocol
  • āœ… Native Page Checkpoints - Capture structured artifacts and generate reports per targetId
  • āœ… Battle-Tested - Extracted from OpenClaw (MIT licensed)

Installation

npm install -g ultimate-playwright-mcp

Or run directly with npx:

npx ultimate-playwright-mcp --cdp-endpoint http://localhost:9222

Quick Start

1. Launch Chrome with Remote Debugging

# macOS
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
  --remote-debugging-port=9222 \
  --user-data-dir=/tmp/chrome-debug

# Linux
google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug

# Windows
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" ^
  --remote-debugging-port=9222 ^
  --user-data-dir=C:\\temp\\chrome-debug

2. Configure Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "ultimate-playwright": {
      "command": "npx",
      "args": [
        "ultimate-playwright-mcp",
        "--cdp-endpoint",
        "http://localhost:9222"
      ]
    }
  }
}

3. Restart Claude Desktop

Claude will now have access to browser control tools with tab isolation.

Usage Example

User: Open two tabs and navigate them independently

Claude: I'll create two tabs with separate targetIds:

1. browser_tabs({ action: "new" })
   → **targetId: ABC123...**

2. browser_tabs({ action: "new" })
   → **targetId: XYZ789...**

3. browser_navigate({ targetId: "ABC123...", url: "https://github.com" })
4. browser_navigate({ targetId: "XYZ789...", url: "https://google.com" })

Both tabs are now navigated independently!

Available Tools

Tool Description Key Parameters
browser_tab_group Create/list/delete tab groups for isolation action, name, color, groupId
browser_tabs List, create, close, or select tabs action, groupId, targetId, index
browser_navigate Navigate to a URL url, targetId
browser_snapshot Capture accessibility tree with refs targetId
browser_click Click an element ref, targetId
browser_type Type text into an element ref, text, targetId
browser_hover Hover over an element ref, targetId
browser_press_key Press a keyboard key key, targetId
browser_fill_form Fill multiple form fields fields, targetId
browser_wait_for Wait for conditions text, selector, url, loadState, targetId
browser_checkpoint Capture a structured checkpoint for a tab name, targetId, collectors
browser_checkpoint_report Generate reports from stored checkpoints format, resultsDir

Checkpoints

Use browser_checkpoint when you want a persisted capture of the current page for later review or report generation.

  • Checkpoints are scoped to the resolved targetId, so they work with this server's tab isolation model.
  • Artifacts and manifests are written under ~/.ultimate-playwright-mcp/checkpoints by default.
  • Generated reports are written under ~/.ultimate-playwright-mcp/checkpoints/report.

Example:

1. browser_checkpoint({ targetId: "ABC123", name: "after-login" })
2. browser_checkpoint_report({ format: "html" })

Tab Groups (Multi-User Isolation)

When multiple users or agents share one browser instance, tab groups keep everyone's tabs isolated. Each session creates its own group, and all tab operations are scoped to that group.

User: Research product pricing

Claude: I'll create a tab group first, then open tabs within it.

1. browser_tab_group({ action: "create", name: "pricing-research", color: "blue" })
   → **groupId: g_a1b2c3d4e5f6**

2. browser_tabs({ action: "new", groupId: "g_a1b2c3d4e5f6", url: "https://example.com/pricing" })
   → **targetId: ABC123...**

3. browser_tabs({ action: "list", groupId: "g_a1b2c3d4e5f6" })
   → Only shows tabs in this group (not other users' tabs)

Meanwhile, another user on the same server:

1. browser_tab_group({ action: "create", name: "docs-review", color: "green" })
   → **groupId: g_x9y8z7w6v5u4**

2. browser_tabs({ action: "new", groupId: "g_x9y8z7w6v5u4", url: "https://docs.example.com" })
   → **targetId: XYZ789...**

Both users share the same cookies/sessions but only see their own tabs!

Tab Group Lifecycle

  1. Create a group at the start of your session
  2. Open tabs within the group using groupId
  3. Work with tabs using targetId as before
  4. Delete the group when done (optionally closes all tabs)

Group state is persisted to ~/.ultimate-playwright-mcp/tab-groups.json so it survives MCP server restarts.

Architecture

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│        Single Chrome Process                │
│    (--remote-debugging-port=9222)           │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”   │
│  │     Single BrowserContext            │   │
│  │  (shared cookies, storage)           │   │
│  │                                      │   │
│  │  Group: alice (blue)                 │   │
│  │  ā”Œā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”                    │   │
│  │  │ Tab │ │ Tab │                    │   │
│  │  │  A  │ │  B  │                    │   │
│  │  ā””ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”˜                    │   │
│  │                                      │   │
│  │  Group: bob (green)                  │   │
│  │  ā”Œā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”            │   │
│  │  │ Tab │ │ Tab │ │ Tab │            │   │
│  │  │  C  │ │  D  │ │  E  │            │   │
│  │  ā””ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”˜            │   │
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜   │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
                   ↑
           CDP Connection
                   ↓
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│    ultimate-playwright-mcp (MCP Server)     │
│    - Tab routing via targetId               │
│    - Tab groups via groupId                 │
│    - Shared ownership registry (JSON file)  │
│    - Stdio transport                        │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
         ↓           ↓           ↓
   ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
   │ Alice   │ │  Bob    │ │ Charlie │
   │ (Claude)│ │ (Claude)│ │ (Cursor)│
   ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

MCP Configuration

Cursor / Windsurf / Generic MCP Client

{
  "mcpServers": {
    "ultimate-playwright": {
      "command": "npx",
      "args": ["ultimate-playwright-mcp", "--cdp-endpoint", "http://localhost:9222"]
    }
  }
}

With Environment Variable

{
  "mcpServers": {
    "ultimate-playwright": {
      "command": "npx",
      "args": ["ultimate-playwright-mcp"],
      "env": {
        "CDP_ENDPOINT": "http://localhost:9222"
      }
    }
  }
}

CLI Options

ultimate-playwright-mcp [options]

Options:
  --cdp-endpoint <url>  CDP endpoint URL (e.g., http://localhost:9222)
                        Can also use CDP_ENDPOINT env var.
                        If omitted, daemon-managed Chrome is started lazily on first tool call.
  --agent-id <id>       Optional agent ID for logging/debugging
                        Can also use AGENT_ID env var
  --keep-alive          Auto-restart daemon-managed Chrome if it exits
                        Use --no-keep-alive for testing workflows where you want Chrome to stay down after kill
                        Default: disabled (no auto-restart)
                        Can also use KEEP_ALIVE env var (set to "false" to disable)
  --checkpoint-output-dir <path>
                        Root directory for checkpoint manifests, artifacts, and reports
                        Can also use CHECKPOINT_OUTPUT_DIR env var
  -V, --version         Output version number
  -h, --help            Display help

Multi-Agent Setup

Running Multiple Claude Code Instances

Each instance connects to the same MCP server and gets isolated tabs:

Terminal 1:

claude-code --mcp-config ./mcp-config.json
# Agent A creates tabs with targetIds starting from ABC...

Terminal 2:

claude-code --mcp-config ./mcp-config.json
# Agent B creates tabs with targetIds starting from XYZ...

Both agents share cookies and sessions but operate on different tabs!

Persistent Chrome Setup (macOS)

For a Chrome instance that auto-starts with debug port:

Create ~/Library/LaunchAgents/com.user.chrome-debug.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.user.chrome-debug</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Applications/Google Chrome.app/Contents/MacOS/Google Chrome</string>
        <string>--remote-debugging-port=9222</string>
        <string>--user-data-dir=/Users/YOUR_USERNAME/chrome-debug-profile</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>

Load with:

launchctl load ~/Library/LaunchAgents/com.user.chrome-debug.plist

Development

# Install dependencies
npm install

# Build
npm run build

# Type check
npm run type-check

# Lint
npm run lint

# Watch mode
npm run watch

License

MIT

Attribution

This project extracts browser control code from OpenClaw (MIT licensed), which provides battle-tested tab isolation and Playwright integration.

Key extracted components:

  • CDP session management (pw-session.ts)
  • Browser operations (pw-tools-*.ts)
  • Role-based element refs (pw-role-snapshot.ts)

Links

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured