Skip to main content
Glama
SJMakin

even-better-playwright-mcp

by SJMakin
README.md
# even-better-playwright-mcp

The **best of all worlds** Playwright MCP server - combining intelligent DOM compression, code execution, visual labels, and advanced DevTools capabilities.

## Features

- ๐ŸŽญ **Full Playwright API** - Execute any Playwright code via the `execute` tool
- ๐Ÿ—๏ธ **90%+ DOM Compression** - SimHash-based list folding and wrapper removal
- ๐Ÿ“ **Ref-Based Elements** - Stable `[ref=e1]` identifiers with aria-ref selectors
- ๐Ÿ” **Enhanced Search & Diff** - Search snapshots with regex, track changes with diff mode
- ๐ŸŽฏ **Visual Labels** - Vimium-style overlays for screenshot-based interaction
- ๐Ÿ”ง **Advanced DevTools** - Debugger, live editor, styles inspection, React source finding
- ๐ŸŒ **Network Capture** - Request/response interception with analytics filtering
- โฑ๏ธ **Smart Page Load** - Intelligent wait that filters analytics and stuck requests
- ๐Ÿ“ **Browser Console Logs** - Persistent per-page logging with search and filtering
- ๐Ÿงน **Clean HTML** - Get LLM-friendly HTML with search and diff capabilities
- ๐Ÿ”’ **Sandboxed Execution** - Safe VM with scoped file system and module allowlist

## Installation

```bash
npm install -g even-better-playwright-mcp
```

Or use directly with npx:
```bash
npx even-better-playwright-mcp
```

## Configuration

Add to your MCP client settings (e.g., Claude Desktop's `claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["even-better-playwright-mcp"]
    }
  }
}
```

### CLI Options

```
Usage: even-better-playwright-mcp [options]

Options:
  --browser <browser>       Browser to use: chromium, firefox, webkit (default: chromium)
  --headless               Run browser in headless mode (default: false)
  --cdp-endpoint <url>     Connect to existing browser via CDP endpoint
  --user-data-dir <path>   Use persistent browser profile directory
  -h, --help               Show help message
```

### Examples

```bash
# Basic usage (launches Chromium in headed mode)
even-better-playwright-mcp

# Use Firefox in headless mode
even-better-playwright-mcp --browser firefox --headless

# Connect to existing Chrome instance
even-better-playwright-mcp --cdp-endpoint ws://localhost:9222

# Use persistent profile
even-better-playwright-mcp --user-data-dir ./browser-profile
```

## Tools

### 1. `snapshot` - Get Page Structure

Get compressed accessibility snapshot with ref IDs for element targeting.

```
Returns: DOM tree with [ref=e1], [ref=e2] etc.
Use refs with execute tool: await $('e1').click()
Call again after navigation (refs become stale).
```

**Options:**
- `compress` (boolean, default: true) - Enable smart compression (~90% token reduction)
- `search` (string | RegExp) - Search pattern to filter results with 5 lines of context
- `showDiff` (boolean, default: false) - Show changes since last snapshot

**Example output:**
```
### Page Info
- URL: https://example.com
- Title: Example Domain

### Accessibility Snapshot
- document [ref=e1]
  - heading "Example Domain" [level=1] [ref=e2]
  - paragraph [ref=e3]: This domain is for use in illustrative examples...
  - link "More information..." [ref=e4]
```

### 2. `browser_execute` - Run Playwright Code

Execute any Playwright code with full API access. This is the main tool for browser automation.

**Scope variables:**
- `page` - Current Playwright page
- `context` - Browser context
- `state` - Persistent object across calls
- `$('e5')` - Shorthand for `page.locator('aria-ref=e5')`
- `accessibilitySnapshot()` - Get current page snapshot
- `waitForPageLoad()` - Smart page load detection (filters analytics/ads)
- `getLatestLogs()` - Get browser console logs with search/filtering
- `clearAllLogs()` - Clear all stored console logs
- `getCleanHTML()` - Get cleaned HTML with search and diff
- `getLocatorStringForElement()` - Generate selector string from element

**Common patterns:**
```javascript
// Navigate
await page.goto('https://example.com')

// Click by ref (from snapshot)
await $('e5').click()

// Fill input
await $('e12').fill('search query')

// Get text
const text = await $('e3').textContent()

// Wait for network (smart detection, filters analytics/ads)
const result = await waitForPageLoad({ timeout: 30000 })
// => { success: true, waitTimeMs: 1234, pendingRequests: [] }

// Screenshot
await page.screenshot({ path: 'screenshot.png' })
```

**Advanced - DevTools access:**
```javascript
// Get CDP session for debugging
const cdp = await getCDPSession({ page })
const dbg = createDebugger({ cdp })

// Set breakpoint
await dbg.setBreakpoint({ file: 'app.js', line: 42 })

// Inspect styles
const styles = await getStylesForLocator({ locator: $('e5') })

// Find React component source
const source = await getReactSource({ locator: $('e5') })
// => { fileName: 'Button.tsx', lineNumber: 42 }
```

**Browser Console Logs:**
```javascript
// Get latest 50 console logs from current page
const logs = await getLatestLogs({ count: 50 })

// Search logs with regex
const errorLogs = await getLatestLogs({ search: /error|warning/i })

// Get logs from all pages
const allLogs = await getLatestLogs()

// Clear all stored logs
clearAllLogs()
```

**HTML Utilities:**
```javascript
// Get cleaned HTML from page or element
const html = await getCleanHTML({
  locator: page,  // or $('e5') for specific element
  maxContentLen: 500
})

// Search within HTML
const forms = await getCleanHTML({
  locator: page,
  search: 'form'
})

// Track HTML changes
const diff = await getCleanHTML({
  locator: page,
  showDiffSinceLastCall: true
})

// Generate readable selector for element
const button = $('e5')
const selector = await getLocatorStringForElement(button)
// => "page.getByRole('button', { name: 'Submit' })"
```

**Safe modules via require():**
`path`, `url`, `crypto`, `buffer`, `util`, `assert`, `os`, `fs` (sandboxed)

### 3. `screenshot` - Capture Page Image

Capture screenshots with optional visual ref labels.

**Options:**
- `ref` (string) - Screenshot specific element by ref
- `fullPage` (boolean) - Capture entire scrollable area
- `withLabels` (boolean) - Show Vimium-style ref labels

**Label colors by role:**
| Color | Role |
|-------|------|
| Yellow | links |
| Orange | buttons |
| Coral | text inputs |
| Pink | checkboxes, radios |
| Blue | images, videos |

### 4. `browser_search_snapshot` - Search Content

Search the last captured snapshot using regex patterns.

**Options:**
- `pattern` (string) - Regex pattern to search for
- `ignoreCase` (boolean, default: false) - Case-insensitive matching
- `lineLimit` (number, default: 100) - Maximum lines to return

**Example:**
```
Pattern: "button|link"
Result:
- link "Contact Us" [ref=e15]
- button "Submit" [ref=e23]
- link "Privacy Policy" [ref=e31]
```

### 5. `browser_network_requests` - Capture Network Traffic

Get captured network requests with automatic filtering of analytics and ads.

**Options:**
- `includeStatic` (boolean, default: false) - Include images, CSS, fonts
- `limit` (number, default: 50) - Max requests to return (most recent)
- `clear` (boolean, default: false) - Clear captured requests after returning

**Features:**
- Automatically starts capturing on first call
- Filters analytics/tracking domains (Google Analytics, Facebook Pixel, etc.)
- Captures request/response bodies (up to 50KB)
- Shows status codes, timing, and response previews

**Example:**
```
Network Requests (127 total, showing last 50):

POST https://api.example.com/login [200] (245ms)
  POST: {"email":"user@example.com","password":"***"}
  RESPONSE: {"token":"eyJ...","user":{"id":123,"name":"John"}}

GET https://api.example.com/profile [200] (89ms)
  RESPONSE: {"id":123,"name":"John","email":"user@example.com"}
```

## Workflow

### Basic Automation

1. **Get page structure**
   ```
   Use: snapshot tool
   โ†’ See all interactive elements with refs
   ```

2. **Interact with elements**
   ```
   Use: execute tool
   Code: await $('e5').click()
   ```

3. **After navigation, refresh refs**
   ```
   Use: snapshot tool again
   โ†’ Refs are stale after navigation
   ```

### Visual Automation

1. **Take labeled screenshot**
   ```
   Use: screenshot tool with withLabels: true
   โ†’ See visual labels overlaid on elements
   ```

2. **Identify element from image**
   ```
   Label shows: "e5" on a button
   ```

3. **Click using ref**
   ```
   Use: execute tool
   Code: await $('e5').click()
   ```

## Architecture

```
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                     even-better-playwright-mcp                  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  CORE                                                           โ”‚
โ”‚  โ”œโ”€โ”€ aria-ref selector system ([ref=e1], [ref=e2], etc.)       โ”‚
โ”‚  โ”œโ”€โ”€ page._snapshotForAI() for accessibility snapshots         โ”‚
โ”‚  โ””โ”€โ”€ Standard Playwright browser automation                     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  ENHANCED SNAPSHOT                                              โ”‚
โ”‚  โ”œโ”€โ”€ SimHash-based list folding (compress 48 items โ†’ 2 lines)  โ”‚
โ”‚  โ”œโ”€โ”€ Useless wrapper removal                                    โ”‚
โ”‚  โ”œโ”€โ”€ Regex-powered content search with context                  โ”‚
โ”‚  โ””โ”€โ”€ Diff tracking (compare snapshots over time)                โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  CODE EXECUTION                                                 โ”‚
โ”‚  โ”œโ”€โ”€ browser_execute tool (run Playwright code in VM sandbox)  โ”‚
โ”‚  โ”œโ”€โ”€ Sandboxed require (safe module allowlist)                  โ”‚
โ”‚  โ”œโ”€โ”€ Scoped file system (cwd, /tmp only)                       โ”‚
โ”‚  โ””โ”€โ”€ Console log capture and forwarding                         โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  PERSISTENT LOGGING                                             โ”‚
โ”‚  โ”œโ”€โ”€ Per-page browser console capture (5000 log limit)         โ”‚
โ”‚  โ”œโ”€โ”€ Logs persist across executions and reconnections          โ”‚
โ”‚  โ”œโ”€โ”€ Search logs with regex and context                         โ”‚
โ”‚  โ””โ”€โ”€ Auto-clear on navigation                                   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  NETWORK & PAGE UTILITIES                                       โ”‚
โ”‚  โ”œโ”€โ”€ Network capture with analytics filtering                   โ”‚
โ”‚  โ”œโ”€โ”€ Smart page load (filters stuck/analytics requests)        โ”‚
โ”‚  โ”œโ”€โ”€ Clean HTML extraction with search/diff                     โ”‚
โ”‚  โ””โ”€โ”€ Selector string generation from elements                   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  ADVANCED DEVTOOLS                                              โ”‚
โ”‚  โ”œโ”€โ”€ Debugger class (breakpoints, step, inspect variables)     โ”‚
โ”‚  โ”œโ”€โ”€ Editor class (live code editing without reload)           โ”‚
โ”‚  โ”œโ”€โ”€ Styles inspection (CSS like DevTools panel)               โ”‚
โ”‚  โ””โ”€โ”€ React source finding (component file/line locations)      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  VISUAL OVERLAYS                                                โ”‚
โ”‚  โ”œโ”€โ”€ Vimium-style labels on interactive elements               โ”‚
โ”‚  โ”œโ”€โ”€ Color-coded by role (links=yellow, buttons=orange, etc.)  โ”‚
โ”‚  โ””โ”€โ”€ Screenshot with visible ref labels                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
```

## Ref System

All projects use the same ref system built into Playwright:

- **Snapshots** generate refs like `[ref=e1]`
- **Selectors** use `page.locator('aria-ref=e1')`
- **Shorthand** `$('e1')` in execute tool

**Important:** Refs become stale after navigation. Always call `snapshot` again after `page.goto()` or clicking links that navigate.

## Compression Algorithm

The snapshot compression achieves ~90% token reduction:

```
Original DOM (5000+ lines)
    โ†“ removeUselessWrappers()
    โ†“ truncateText(50 chars)
    โ†“ detectSimilarPatterns(SimHash)
    โ†“ foldLists()
Compressed (<500 lines)
```

**Example:**
```
Before:
- listitem [ref=e234]: Product 1 - Description...
- listitem [ref=e235]: Product 2 - Description...
- listitem [ref=e236]: Product 3 - Description...
... (48 items)

After:
- listitem [ref=e234]: Product 1 - Description...
- listitem (... and 47 more similar) [refs: e235, e236, ...]
```

## Error Handling

The execute tool provides contextual hints:

- **Stale ref**: "Page may have navigated. Refs are stale after navigation. Call snapshot tool to get fresh refs."
- **Timeout**: "Operation timed out. Try increasing timeout or check if element exists/is visible."
- **Hidden element**: "Element may be hidden or covered by another element. Try scrolling or closing overlays."
- **Connection lost**: "Browser connection lost. The browser may have been closed - try again to relaunch."

## Programmatic Usage

The server can be used as a library with full programmatic control:

```typescript
import { createServerInstance, BrowserManager } from 'even-better-playwright-mcp';

// Create server instance with custom config
const { server, browserManager, cleanup } = createServerInstance({
  browser: 'chromium',
  headless: true,
  isolated: true,  // Force ephemeral context
  launchOptions: {
    slowMo: 50,
    args: ['--disable-blink-features=AutomationControlled']
  },
  contextOptions: {
    viewport: { width: 1920, height: 1080 },
    userAgent: 'Custom User Agent'
  }
});

// Connect your transport
await server.connect(transport);

// Cleanup when done
await cleanup();
```

### BrowserConfig Options

- `browser` - Browser type: 'chromium', 'firefox', 'webkit'
- `headless` - Run in headless mode
- `cdpEndpoint` - Connect to existing browser via CDP
- `userDataDir` - Persistent browser profile directory
- `isolated` - Force ephemeral context (overrides userDataDir)
- `launchOptions` - Pass-through to Playwright's browser.launch()
- `contextOptions` - Pass-through to browser.newContext()

### Multi-Session Support

Each `BrowserManager` instance has isolated state:
- Independent browser/context/page
- Separate network capture
- Isolated console logs
- Per-instance persistent state

```typescript
// Create multiple isolated sessions
const session1 = createServerInstance({ browser: 'chromium' });
const session2 = createServerInstance({ browser: 'firefox' });

// Each has its own browser and state
await session1.browserManager.getPage();
await session2.browserManager.getPage();
```

## Development

### Building from Source

```bash
git clone https://github.com/your-repo/even-better-playwright-mcp
cd even-better-playwright-mcp
npm install
npm run build
```

### Running Tests

The project includes comprehensive end-to-end tests:

```bash
# Build first
npm run build

# Run e2e tests
npm run test:e2e

# Run all tests
npm test
```

**Test Coverage**: 15 tests covering all MCP tools against Hacker News
- Tool discovery and validation
- Browser automation (navigate, click, fill forms)
- Accessibility snapshots with ref system
- Screenshot capture
- Network request monitoring
- Persistent state management
- Error and timeout handling
- Full end-to-end workflows

See `test/README.md` for detailed test documentation.

### Project Structure

```
even-better-playwright-mcp/
โ”œโ”€โ”€ bin/
โ”‚   โ””โ”€โ”€ cli.ts                  # CLI entry point with arg parsing
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ index.ts                # MCP server factory (createServerInstance)
โ”‚   โ”œโ”€โ”€ browser.ts              # BrowserManager class (refactored!)
โ”‚   โ”œโ”€โ”€ vm-context.ts           # VM sandbox setup
โ”‚   โ”œโ”€โ”€ tools/
โ”‚   โ”‚   โ”œโ”€โ”€ snapshot.ts         # Snapshot tool (compressed + search + diff)
โ”‚   โ”‚   โ”œโ”€โ”€ execute.ts          # Execute tool (main)
โ”‚   โ”‚   โ”œโ”€โ”€ screenshot.ts       # Screenshot tool (with labels)
โ”‚   โ”‚   โ”œโ”€โ”€ search.ts           # Search tool
โ”‚   โ”‚   โ””โ”€โ”€ network.ts          # Network capture tool
โ”‚   โ”œโ”€โ”€ utils/
โ”‚   โ”‚   โ”œโ”€โ”€ smart-outline.ts    # DOM compression
โ”‚   โ”‚   โ”œโ”€โ”€ list-detector.ts    # Pattern detection
โ”‚   โ”‚   โ”œโ”€โ”€ dom-simhash.ts      # SimHash implementation
โ”‚   โ”‚   โ”œโ”€โ”€ scoped-fs.ts        # Sandboxed file system
โ”‚   โ”‚   โ”œโ”€โ”€ search.ts           # Regex search
โ”‚   โ”‚   โ”œโ”€โ”€ browser-logs.ts     # Persistent console logging
โ”‚   โ”‚   โ”œโ”€โ”€ clean-html.ts       # HTML cleaning with search/diff
โ”‚   โ”‚   โ”œโ”€โ”€ locator-string.ts   # Selector generation
โ”‚   โ”‚   โ”œโ”€โ”€ wait-for-page-load.ts  # Smart page load detection
โ”‚   โ”‚   โ”œโ”€โ”€ network-capture.ts  # Network request capture
โ”‚   โ”‚   โ””โ”€โ”€ console-capture.ts  # Console log capture
โ”‚   โ”œโ”€โ”€ devtools/
โ”‚   โ”‚   โ”œโ”€โ”€ cdp-session.ts      # CDP connection
โ”‚   โ”‚   โ”œโ”€โ”€ debugger.ts         # Debugger class
โ”‚   โ”‚   โ”œโ”€โ”€ editor.ts           # Live editor
โ”‚   โ”‚   โ”œโ”€โ”€ styles.ts           # CSS inspection
โ”‚   โ”‚   โ””โ”€โ”€ react-source.ts     # React locations
โ”‚   โ””โ”€โ”€ visual/
โ”‚       โ””โ”€โ”€ aria-labels.ts      # Vimium-style overlays
โ”œโ”€โ”€ test/
โ”‚   โ”œโ”€โ”€ e2e.test.js            # Comprehensive E2E test suite
โ”‚   โ””โ”€โ”€ README.md              # Test documentation
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ tsconfig.json
โ””โ”€โ”€ README.md
```

### Recent Refactoring (v0.1.0)

The codebase was refactored from global module-level state to a clean, testable architecture:

**Before**: Global functions and singletons
```typescript
import { getPage, getContext } from './browser.js';
const page = await getPage(); // Global state
```

**After**: Dependency injection with BrowserManager
```typescript
const browserManager = new BrowserManager(config);
const page = await browserManager.getPage(); // Instance state
```

**Benefits**:
- โœ… Multi-session support (multiple isolated browsers)
- โœ… Better testability (no global state)
- โœ… Library-friendly API (clean exports)
- โœ… Full Playwright configuration control
- โœ… Flexible browser lifecycle management

All tool handlers now use factory functions with dependency injection:
```typescript
const handleSnapshot = createSnapshotHandler(browserManager);
const handleExecute = createExecuteHandler(browserManager);
```

## Acknowledgments

This project combines the best ideas from:
- [better-playwright-mcp](https://github.com/) - Intelligent DOM compression
- [playwriter](https://github.com/) - Code execution and DevTools
- [playwright-mcp](https://github.com/microsoft/playwright-mcp) - Microsoft's official MCP

## License

MIT

TDQS

A4.3/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a distinct and non-overlapping purpose: browser_execute runs code, browser_network_requests captures network data, browser_search_snapshot searches snapshots, screenshot captures images, and snapshot retrieves accessibility data. There is no ambiguity in their functions.

Naming Consistency5/5

All tool names follow a consistent snake_case pattern with a 'browser_' prefix for three tools and simple nouns for the others, creating a clear and predictable naming scheme. The structure is uniform and easy to understand.

Tool Count5/5

With 5 tools, the server is well-scoped for browser automation, covering execution, network monitoring, snapshot searching, screenshot capture, and accessibility snapshot retrieval. Each tool serves a unique and essential function without redundancy.

Completeness4/5

The tool set provides comprehensive coverage for browser automation tasks, including interaction, monitoring, and inspection. A minor gap exists in lacking a dedicated tool for browser context/page management (e.g., opening/closing pages), but this is mitigated by instructions within browser_execute.

Maintenance

ActivityInactive
ResponsivenessNo issues