Skip to main content
Glama
jamesmurdza

Daytona Playwright MCP Server

by jamesmurdza
README.md
# Daytona Playwright MCP Server

An MCP (Model Context Protocol) server that lets you control a stealth patchright+Chrome browser running inside a [Daytona](https://daytona.io) cloud sandbox. Use it with Claude Code, Claude Desktop, or any MCP-compatible client to browse the web, take screenshots, fill forms, and more.

https://github.com/user-attachments/assets/23b13e1f-4ed3-4204-ad0d-b2fdb1f77d0d

## Features

- **Stealth Chrome**: Real Chrome (not headless, via [patchright](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright)'s stealth patches) rendered into a virtual display
- **Live VNC view**: The signed preview URL returned by `browser_start` streams the sandbox desktop, so you can watch what Claude is doing
- **Cloud Sandbox**: Browser runs securely in a Daytona sandbox, isolated from your local machine
- **Rich Tool Set**: Navigate, click, type, scroll, take screenshots, extract content, manage tabs
- **Screenshot Support**: Returns screenshots as images that Claude can see and analyze
- **Multiple Transports**: Works with stdio (default), SSE, or HTTP

## Quick Start

### 1. Install the Package

```bash
pipx install git+https://github.com/jamesmurdza/playwright-daytona-mcp-server.git
```

### 2. Get a Daytona API Key

1. Sign up at [daytona.io](https://daytona.io)
2. Go to your dashboard and generate an API key

### 3. Configure Claude Code / Claude Desktop

Add to your MCP settings:

```json
{
  "mcpServers": {
    "daytona-playwright": {
      "command": "daytona-playwright-mcp",
      "env": {
        "DAYTONA_API_KEY": "your-api-key-here"
      }
    }
  }
}
```

## Usage

Once configured, you can ask Claude to browse the web:

```
"Start a browser and go to https://news.ycombinator.com"

"Take a screenshot of the page"

"Click on the first article link"

"Search for 'AI news' on Google and show me the results"

"Fill out the contact form on example.com with test data"
```

### Workflow

1. **Start the browser**: Claude will call `browser_start` to create a Daytona sandbox and launch Chrome
2. **Navigate and interact**: Use navigation, clicking, typing, and other tools
3. **Take screenshots**: See what's on the page with `browser_screenshot`
4. **Clean up**: Call `browser_stop` when done to delete the sandbox

## Available Tools

### Browser Lifecycle
| Tool | Description |
|------|-------------|
| `browser_start` | Start a new browser session in a Daytona sandbox |
| `browser_stop` | Stop the browser and clean up the sandbox |
| `browser_status` | Check if the browser is running |

### Navigation
| Tool | Description |
|------|-------------|
| `browser_navigate` | Navigate to a URL |
| `browser_back` | Go back in history |
| `browser_forward` | Go forward in history |
| `browser_refresh` | Refresh the current page |

### Interaction
| Tool | Description |
|------|-------------|
| `browser_click` | Click on an element (CSS, XPath, or text selector) |
| `browser_type` | Type text into an input field |
| `browser_press` | Press keyboard keys (Enter, Tab, etc.) |
| `browser_hover` | Hover over an element |
| `browser_select` | Select from a dropdown |
| `browser_scroll` | Scroll the page or an element |

### Content Extraction
| Tool | Description |
|------|-------------|
| `browser_screenshot` | Take a screenshot (full page or element) |
| `browser_get_text` | Get text content from the page |
| `browser_get_html` | Get HTML content |
| `browser_get_attribute` | Get an element's attribute |
| `browser_evaluate` | Run JavaScript and get results |

### Waiting
| Tool | Description |
|------|-------------|
| `browser_wait_for_selector` | Wait for an element to appear/disappear |
| `browser_wait_for_navigation` | Wait for navigation to complete |

### Tab Management
| Tool | Description |
|------|-------------|
| `browser_new_tab` | Open a new tab |
| `browser_list_tabs` | List all open tabs |
| `browser_switch_tab` | Switch to a different tab |
| `browser_close_tab` | Close a tab |

### File Operations
| Tool | Description |
|------|-------------|
| `browser_upload_file` | Upload a file to a file input |

## Running with Different Transports

### Stdio (Default - for Claude Code/Desktop)

```bash
daytona-playwright-mcp
```

### HTTP Transport (for remote connections)

```bash
daytona-playwright-mcp --transport http --host 0.0.0.0 --port 8765
```

Then connect via: `http://localhost:8765/mcp`

### SSE Transport (legacy)

```bash
daytona-playwright-mcp --transport sse --host 0.0.0.0 --port 8765
```

## Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `DAYTONA_API_KEY` | Your Daytona API key (required) | - |
| `DAYTONA_API_URL` | Daytona API server URL | `https://app.daytona.io/api` |

## Development

### Run from Source

```bash
# Clone the repository
git clone https://github.com/jamesmurdza/playwright-daytona-mcp-server.git
cd playwright-daytona-mcp-server

# Install dependencies
uv sync

# Run the server
uv run daytona-playwright-mcp
```

### Configure MCP for Development

When developing locally, use this MCP configuration:

```json
{
  "mcpServers": {
    "daytona-playwright": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/playwright-daytona-mcp-server", "daytona-playwright-mcp"],
      "env": {
        "DAYTONA_API_KEY": "your-api-key-here"
      }
    }
  }
}
```

### Run Tests

```bash
uv run pytest
```

## How It Works

1. When you call `browser_start`, the server:
   - Builds a minimal Daytona sandbox image declaratively (xfce + VNC stack for `computer_use`, plus patchright with the Chrome channel)
   - Starts `computer_use` so the sandbox desktop is streamed on port 6080 (the returned "Live view" URL)
   - Launches Chrome via patchright into `DISPLAY=:0` with CDP bound on `0.0.0.0:9222` — no TCP proxy needed, since patchright's stealth patches are applied at launch time
   - Connects to Chrome over a signed CDP WebSocket through Daytona's secure preview URL

2. All browser commands are executed through the async Playwright API connected to the remote browser

3. Screenshots are captured as PNG images and returned via MCP's image content type

4. When you call `browser_stop`, the sandbox is deleted and all resources are freed

## Credits

- Based on the [Daytona browser-in-sandbox pattern](https://gist.github.com/synacktraa/29e05d51363b40d55e4d163aea8feaae) by synacktraa
- Uses [Patchright](https://github.com/AnyBrowser/patchright) for Playwright CDP connectivity
- Built with [FastMCP](https://github.com/jlowin/fastmcp) for the MCP server
- Powered by [Daytona](https://daytona.io) cloud sandboxes

TDQS

A3.6/5.0

Scored across 26 tools

Disambiguation5/5

Each tool has a clearly distinct purpose with no ambiguity. For example, browser_click is for clicking, browser_type is for typing, browser_screenshot is for capturing images, and browser_wait_for_selector is for waiting on element states. The descriptions reinforce these distinctions, making misselection unlikely.

Naming Consistency5/5

All tools follow a consistent 'browser_verb' or 'browser_verb_noun' naming pattern (e.g., browser_back, browser_click, browser_screenshot). This uniformity makes the tool set predictable and easy to navigate, with no deviations in style or convention.

Tool Count3/5

With 26 tools, the count feels heavy for a browser automation server, though not extreme. While it covers many operations, some tools could potentially be consolidated (e.g., browser_back and browser_forward are simple navigations), making the set borderline in scope.

Completeness5/5

The tool set provides complete coverage for browser automation, including session management (start, stop, status), navigation, interaction (click, type, hover), inspection (get_html, get_text), and utilities (screenshot, download). There are no obvious gaps, and agents can handle typical workflows without dead ends.

Maintenance

ActivityInactive
ResponsivenessNo issues