← All articles

Playwright MCP: Complete Setup Guide & Browser Automation

July 6, 2026·28 min read·MCPForge

Playwright MCP: Complete Setup Guide & Browser Automation

Playwright MCP is the bridge between AI agents and real browsers. Instead of describing what a webpage looks like and hoping an AI can act on it, Playwright MCP gives Claude, Cursor, Codex, and Copilot direct, structured control over Chromium, Firefox, and WebKit — navigation, clicks, form fills, screenshots, and full DOM inspection, all through standard MCP tool calls.

This guide covers everything: installation for every major AI client, how the accessibility snapshot system works, headless vs. headed mode, persistent and isolated sessions, security hardening, Docker deployment, and common production pitfalls. If you've ever wanted to give an AI agent a browser, this is how you do it properly.


What Playwright MCP Actually Is

Microsoft's @playwright/mcp package is an MCP server that exposes Playwright browser automation as a set of typed tools. When an AI client connects to it, the agent gains tools like:

  • browser_navigate — load a URL
  • browser_click — click an element by description or selector
  • browser_type — fill a text field
  • browser_snapshot — capture the accessibility tree
  • browser_screenshot — take a visual screenshot
  • browser_wait_for — wait for conditions
  • browser_evaluate — execute JavaScript in page context

Under the hood, every tool call maps to Playwright API calls. The MCP server handles JSON-RPC transport (stdio or SSE), manages browser lifecycle, and returns structured results the AI can reason about.

This is architecturally different from asking an AI to write Playwright scripts and run them yourself. The AI is the operator — it decides what to click, reads the result, and iterates. This enables genuine agentic web workflows: research, testing, form automation, monitoring, and more.

Unlike traditional automation frameworks, where you define every step upfront, Playwright MCP lets the agent adapt in real time — handling popups, redirects, and unexpected UI states without you writing fallback logic. The browser becomes a live environment that the AI navigates dynamically, not a script it executes blindly. That shift is what makes it genuinely useful for complex, multi-step tasks that break under rigid automation.

It also means the AI carries full context across steps — it knows what it clicked, what loaded, and what failed — so it can recover from errors the same way a human would. For developers, this removes an entire category of brittle glue code that traditional automation constantly requires.

┌─────────────────────────────────────────────────────────┐
│                    AI Client (Claude / Cursor)          │
│                                                         │
│  "Fill out the signup form at example.com"              │
└───────────────────────┬─────────────────────────────────┘
                        │ MCP Tool Calls (JSON-RPC / stdio)
┌───────────────────────▼─────────────────────────────────┐
│               Playwright MCP Server                     │
│         (@playwright/mcp — Node.js process)             │
│                                                         │
│  Tool Registry: navigate, click, type, snapshot, ...    │
└───────────────────────┬─────────────────────────────────┘
                        │ Playwright API
┌───────────────────────▼─────────────────────────────────┐
│            Browser Engine (Chromium / Firefox)          │
│                                                         │
│  ┌─────────────────────────────────────────────────┐    │
│  │  Browser Context (isolated or persistent)       │    │
│  │  ┌───────────────────────────────────────────┐  │    │
│  │  │  Page / Tab                               │  │    │
│  │  └───────────────────────────────────────────┘  │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘

Prerequisites

Before installing, make sure you have:

  • Node.js 18+ — Playwright MCP is a Node.js package
  • npm or npx — for running the server
  • Playwright browser binaries — installed separately (npx playwright install)
  • An MCP-compatible AI client (Claude Desktop, Cursor, VS Code Copilot, or OpenAI Codex environment)

Check your Node version:

bash
node --version  # Should be 18.x or higher

Install Playwright browser binaries (Chromium by default):

bash
npx playwright install chromium
# Or install all browsers:
npx playwright install

This is the most commonly missed step. If browsers aren't installed, Playwright MCP fails with a cryptic "executable not found" error.


Installation

Playwright MCP is distributed as an npm package. You don't need a global install — npx handles it:

bash
# Run directly (no global install needed)
npx @playwright/mcp@latest

# Or install globally if you prefer
npm install -g @playwright/mcp

For projects where you want to pin a version:

bash
npm install --save-dev @playwright/mcp

Verify it runs:

bash
npx @playwright/mcp --help

You should see a list of available flags including --browser, --headed, --port, and --config.


Want to analyze your API security?

Import your OpenAPI spec and generate a Security Report automatically.

Configuration File

Before diving into client-specific setup, understand the config format. Playwright MCP accepts a JSON config file:

json
{
  "browser": "chromium",
  "headless": true,
  "viewport": {
    "width": 1280,
    "height": 720
  },
  "userDataDir": "/path/to/profile",
  "allowedOrigins": ["https://example.com", "https://staging.example.com"],
  "blockedOrigins": ["https://ads.example.com"],
  "timeout": 30000,
  "locale": "en-US",
  "timezoneId": "America/New_York",
  "ignoreHTTPSErrors": false
}

Pass it with:

bash
npx @playwright/mcp --config ./playwright-mcp.config.json

Key config options explained:

OptionDefaultPurpose
browserchromiumBrowser engine: chromium, firefox, webkit
headlesstrueRun without visible window
userDataDir(temp dir)Persistent profile directory
allowedOrigins(all)Whitelist URLs the agent can visit
blockedOrigins(none)Blacklist URLs
timeout30000Default navigation timeout in ms
ignoreHTTPSErrorsfalseAllow invalid certs (dev only)
viewport1280×720Browser window dimensions

Setting Up with Claude Desktop

Claude Desktop reads MCP server configurations from a JSON file:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json

Add Playwright MCP:

json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": [
        "@playwright/mcp@latest",
        "--browser", "chromium",
        "--headless"
      ]
    }
  }
}

For headed mode (useful for debugging):

json
{
  "mcpServers": {
    "playwright-headed": {
      "command": "npx",
      "args": [
        "@playwright/mcp@latest",
        "--browser", "chromium",
        "--headed"
      ]
    }
  }
}

With a config file:

json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": [
        "@playwright/mcp@latest",
        "--config", "/Users/yourname/.config/playwright-mcp.json"
      ]
    }
  }
}

After editing, restart Claude Desktop completely. You'll know it's working when Claude responds to "take a screenshot of google.com" by actually doing it.

Important: The MCP server process is spawned by Claude Desktop on demand and communicates over stdio. There's no separate server process to manage.


Setting Up with Cursor

Cursor supports MCP servers through its settings. Open Settings → MCP (or edit .cursor/mcp.json in your project root for project-scoped config):

Global config (~/.cursor/mcp.json):

json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest"],
      "env": {
        "PLAYWRIGHT_BROWSERS_PATH": "/home/user/.cache/ms-playwright"
      }
    }
  }
}

Project-scoped (.cursor/mcp.json at project root — useful for team projects):

json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": [
        "@playwright/mcp@latest",
        "--config", "./.playwright-mcp.json"
      ]
    }
  }
}

With Cursor, Playwright MCP is most useful in Agent mode. You can instruct it to:

  • Test your local dev server at localhost:3000
  • Scrape reference data from documentation sites
  • Verify that a UI change actually renders correctly
  • Run through a checkout flow on a staging environment

Cursor's AI can directly see tool results and iterate — asking for a snapshot, identifying a broken element, fixing the code, and verifying the fix all in one session.


Setting Up with OpenAI Codex

OpenAI Codex (the API-based coding agent) can use MCP servers when deployed in environments that support MCP. If you're using Codex through an orchestration framework that supports MCP (like LangChain with MCP adapters, or direct API usage with tool calling):

python
import subprocess
import json

# Launch Playwright MCP as a subprocess
server_process = subprocess.Popen(
    ["npx", "@playwright/mcp@latest", "--headless"],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
)

# JSON-RPC over stdio
def call_mcp_tool(process, tool_name: str, params: dict) -> dict:
    request = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/call",
        "params": {
            "name": tool_name,
            "arguments": params
        }
    }
    message = json.dumps(request) + "\n"
    process.stdin.write(message.encode())
    process.stdin.flush()
    
    response_line = process.stdout.readline()
    return json.loads(response_line)

# Navigate to a page
result = call_mcp_tool(server_process, "browser_navigate", {
    "url": "https://example.com"
})

For production Codex-based agents, use an MCP client library rather than raw subprocess communication.


Setting Up with GitHub Copilot (VS Code)

VS Code with GitHub Copilot Chat supports MCP servers in Agent mode. Configure via .vscode/mcp.json:

json
{
  "servers": {
    "playwright": {
      "type": "stdio",
      "command": "npx",
      "args": ["@playwright/mcp@latest", "--headless"]
    }
  }
}

Or in VS Code's settings.json:

json
{
  "mcp": {
    "servers": {
      "playwright": {
        "type": "stdio",
        "command": "npx",
        "args": ["@playwright/mcp@latest"]
      }
    }
  }
}

In VS Code Copilot's chat panel, switch to Agent mode and Playwright tools become available. This is particularly powerful for test-driven workflows: write a failing test, ask Copilot to fix the implementation, then verify with a browser screenshot — all in the editor.


Accessibility Snapshots: The Right Way for AI to See Pages

This is the most important concept in Playwright MCP that most tutorials gloss over.

When an AI agent needs to understand a webpage, it has two options:

  1. Screenshot — Take an image, pass it to a vision model
  2. Accessibility Snapshot — Get the structured accessibility tree as text

Playwright MCP defaults to accessibility snapshots, and this is deliberate. Here's why it matters:

Screenshot Approach:
  Page → PNG image → Vision model → "I see a button labeled Submit"
  ✗ Uses vision tokens (expensive)
  ✗ Resolution-dependent
  ✗ Misses aria-labels, roles, interactive states
  ✗ Can't identify element selectors

Accessibility Snapshot:
  Page → Accessibility Tree → Structured text → Direct element reference
  ✓ Token-efficient
  ✓ Resolution-independent
  ✓ Exposes roles, labels, states, relationships
  ✓ AI can reference elements by stable identifiers

A snapshot looks like this (what the AI actually receives):

browser_snapshot result:
- document [role=document]
  - navigation [role=navigation]
    - link "Home" [href=/]
    - link "Products" [href=/products]
    - link "Sign In" [href=/signin]
  - main [role=main]
    - heading "Welcome to Example" [level=1]
    - paragraph "Your trusted platform for..."
    - button "Get Started" [focused=false, disabled=false]
    - form [role=form, label="Contact"]
      - textbox "Email address" [required=true, value=""]
      - textbox "Message" [required=true, value=""]
      - button "Send" [type=submit]

The AI can now say: "click the 'Get Started' button" or "type into the 'Email address' textbox" — and Playwright MCP translates that into a precise selector match without needing coordinates.

Take a snapshot via the tool:

browser_snapshot → returns accessibility tree
browser_screenshot → returns base64 PNG (use when visual verification matters)

For most automation tasks, browser_snapshot should be your primary tool. Use browser_screenshot only when you need to visually verify rendering, catch CSS bugs, or deal with canvas-based UIs that don't have meaningful accessibility trees.


Headless vs. Headed Mode

ModeFlagUse CaseLimitation
Headless--headless (default)CI/CD, production automation, background tasksCan't load extensions, some anti-bot systems detect it
Headed--headedDebugging, development, extension testingRequires display server, not suitable for servers without GUI
Headless with virtual displayXvfb + --headedCI on Linux with display emulationMore complex setup

For headless on a Linux server without a display:

bash
# Default headless - just works
npx @playwright/mcp --headless

# Headed with Xvfb (for extension testing in CI)
Xvfb :99 -screen 0 1280x720x24 &
export DISPLAY=:99
npx @playwright/mcp --headed

In production: always run headless unless you have a specific reason not to. Headed mode uses more memory (the GPU process, compositor, etc.) and requires OS-level display infrastructure.


Persistent Sessions

By default, Playwright MCP creates a fresh browser context for each server start — no cookies, no storage, no history. This is the isolated session mode.

Persistent sessions maintain state across sessions using a userDataDir:

json
{
  "browser": "chromium",
  "headless": true,
  "userDataDir": "/home/user/.playwright-mcp-profile"
}

Or via CLI:

bash
npx @playwright/mcp --user-data-dir /home/user/.playwright-mcp-profile

What gets persisted:

  • Cookies and session tokens
  • localStorage and sessionStorage values
  • IndexedDB data
  • Browser preferences
  • Service worker registrations

Production workflow for authenticated sessions:

bash
# Step 1: Run headed to log in manually
npx @playwright/mcp --headed --user-data-dir ./auth-profile
# Use Claude/Cursor to navigate to your app and log in
# Close the session when done

# Step 2: Future sessions automatically use saved auth
npx @playwright/mcp --headless --user-data-dir ./auth-profile
# Agent is already logged in

Security note: treat userDataDir like a password file. It contains session tokens. If your userDataDir is compromised, an attacker has access to every site the session is authenticated with. Store it outside your project directory, restrict file permissions to 700, and never commit it to version control.


Isolated Sessions

For security-sensitive workflows or parallel automation, isolated sessions are preferable:

json
{
  "browser": "chromium",
  "headless": true
  // No userDataDir — new ephemeral context every time
}

Isolated sessions are ideal for:

  • Processing untrusted URLs (web scraping from arbitrary sources)
  • Test automation where clean state is required
  • Multi-tenant systems where sessions must not bleed between users
  • Any workflow where you don't want credentials cached

For parallel isolated sessions, run multiple server instances on different ports (if using SSE transport) or as separate stdio processes:

bash
# Instance 1 - SSE on port 8931
npx @playwright/mcp --port 8931 --headless &

# Instance 2 - SSE on port 8932  
npx @playwright/mcp --port 8932 --headless &

Browser Extensions

Playwright MCP supports loading Chrome extensions into Chromium. This requires:

  1. Headed mode OR persistent context
  2. Extension path pointing to unpacked extension directory
json
{
  "browser": "chromium",
  "headless": false,
  "userDataDir": "./extension-profile",
  "extensionPaths": ["/path/to/unpacked/extension"]
}

Or via CLI:

bash
npx @playwright/mcp \
  --headed \
  --user-data-dir ./ext-profile \
  --extension-path /path/to/extension

Common use cases for extensions:

  • Password managers — maintain authenticated state through extension-based auth
  • Ad blockers — cleaner pages for content extraction
  • Custom network interceptors — for testing specific network conditions
  • Internal tooling extensions — automating enterprise SaaS with companion extensions

Firefox/WebKit limitation: Extensions only work in Chromium. If you need Firefox or WebKit, you can't use browser extensions.


Docker Deployment

Running Playwright MCP in Docker is the cleanest approach for production — isolated OS, pinned dependencies, no conflicts with system Playwright installations.

Dockerfile:

dockerfile
FROM mcr.microsoft.com/playwright:v1.49.0-noble

# Set working directory
WORKDIR /app

# Install Playwright MCP
RUN npm install @playwright/mcp@latest

# Copy config
COPY playwright-mcp.config.json ./

# Expose port for SSE transport (optional)
EXPOSE 8931

# Run the MCP server
CMD ["node", "node_modules/.bin/playwright-mcp", \
     "--config", "./playwright-mcp.config.json", \
     "--port", "8931"]

playwright-mcp.config.json:

json
{
  "browser": "chromium",
  "headless": true,
  "allowedOrigins": ["https://your-target-site.com"],
  "timeout": 30000,
  "viewport": {
    "width": 1280,
    "height": 720
  }
}

docker-compose.yml:

yaml
version: '3.8'

services:
  playwright-mcp:
    build: .
    ports:
      - "8931:8931"
    volumes:
      - playwright-sessions:/app/sessions
    environment:
      - NODE_ENV=production
    restart: unless-stopped
    # Security: limit capabilities
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    # Memory limit (browsers are hungry)
    mem_limit: 2g

volumes:
  playwright-sessions:

Build and run:

bash
docker build -t playwright-mcp .
docker-compose up -d

The Microsoft Playwright Docker image (mcr.microsoft.com/playwright) includes all browser binaries and system dependencies pre-installed. This avoids the painful apt-get install libgbm-dev libxshmfence-dev... dependency dance.

Docker networking note: When Playwright MCP runs in Docker and needs to access a local dev server on your host machine, use host.docker.internal instead of localhost in your URLs.


Security Hardening

Playwright MCP gives an AI agent a real browser. A real browser can visit any URL, execute JavaScript, access local resources, and interact with any authenticated service. This power requires deliberate security controls.

Origin Allowlisting

The single most important security control — restrict which URLs the agent can visit:

json
{
  "allowedOrigins": [
    "https://app.yourcompany.com",
    "https://staging.yourcompany.com",
    "http://localhost:3000"
  ]
}

With allowedOrigins set, attempts to navigate to URLs outside the whitelist fail immediately. This prevents prompt injection attacks where a malicious page tries to redirect the agent to an attacker-controlled site.

Blocking Dangerous Origins

json
{
  "blockedOrigins": [
    "https://webhook.site",
    "https://requestbin.com"
  ]
}

Never Expose MCP Over Public Networks

MCP servers using SSE transport listen on a port. Never expose this port directly to the internet without authentication. If you need remote access:

nginx
# Nginx reverse proxy with basic auth
server {
    listen 443 ssl;
    server_name mcp.internal.yourcompany.com;
    
    location / {
        auth_basic "MCP Server";
        auth_basic_user_file /etc/nginx/.htpasswd;
        proxy_pass http://localhost:8931;
        proxy_set_header Connection '';
        proxy_http_version 1.1;
        proxy_buffering off;
    }
}

For production deployments at scale, see running MCP in production for patterns around authentication, monitoring, and zero-downtime operations.

JavaScript Execution Caution

The browser_evaluate tool can execute arbitrary JavaScript in the page context. In agentic workflows, be aware that a compromised or malicious page could craft content designed to trick the AI into executing harmful JS. Mitigations:

  • Use allowedOrigins to restrict which pages the agent visits
  • Don't give agents access to browser_evaluate unless the workflow genuinely requires it
  • Log all browser_evaluate calls in production

Credential Hygiene

bash
# Lock down persistent profile directory
chmod 700 /path/to/userDataDir

# Never store userDataDir inside your project repo
echo ".playwright-profile/" >> .gitignore

# Use environment variables for profile paths
npx @playwright/mcp --user-data-dir $PLAYWRIGHT_PROFILE_PATH

Real Automation Workflows

Workflow 1: Automated Form Testing

A QA agent verifies a signup form on every deploy:

Agent instruction: "Navigate to https://staging.app.com/signup. 
Fill in the name field with 'Test User', 
email with 'test@example.com', 
password with 'SecurePass123!'. 
Click the signup button and verify the success message appears."

Playwright MCP tool sequence:

  1. browser_navigatehttps://staging.app.com/signup
  2. browser_snapshot → identify form fields
  3. browser_type → fill each field
  4. browser_click → submit button
  5. browser_snapshot → verify success state
  6. browser_screenshot → capture evidence

Workflow 2: Competitive Research Agent

python
# Agent task: "Collect pricing from competitor sites"
# Playwright MCP handles the browser interactions

instructions = """
Visit https://competitor-a.com/pricing
Extract all plan names and prices from the pricing table
Then visit https://competitor-b.com/pricing  
Extract the same data
Return a comparison as JSON
"""

With allowedOrigins set to only the competitor domains, this stays scoped.

Workflow 3: CI/CD Visual Regression

In a GitHub Actions workflow:

yaml
name: Visual Regression Tests
on: [push]

jobs:
  visual-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
      
      - name: Install Playwright browsers
        run: npx playwright install chromium
      
      - name: Start dev server
        run: npm run dev &
        
      - name: Run AI visual test agent
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          node scripts/visual-test-agent.js
javascript
// scripts/visual-test-agent.js
import Anthropic from '@anthropic-ai/sdk';
import { spawn } from 'child_process';

// Launch Playwright MCP
const mcpServer = spawn('npx', ['@playwright/mcp@latest', '--headless']);

// Use Claude to drive visual tests via MCP
const client = new Anthropic();

const result = await client.messages.create({
  model: 'claude-opus-4-5',
  max_tokens: 4096,
  messages: [{
    role: 'user',
    content: `Visit http://localhost:3000 and verify:
    1. The hero section heading is visible
    2. Navigation links are all present
    3. Take a screenshot as evidence
    Report PASS or FAIL with details.`
  }]
  // MCP integration wired via SDK's MCP client support
});

Testing Strategies

Playwright MCP complements, not replaces, traditional Playwright test scripts. Here's how to think about when to use each:

ScenarioUse Playwright MCPUse Raw Playwright
Exploratory testing / QA checks
One-off automation tasks
Stable regression test suite
Performance benchmarking
CI/CD deterministic tests
Dynamic UI investigation
Generating test scripts from interaction

A powerful workflow: use Playwright MCP to explore a UI and generate Playwright test code, then commit that code to your test suite. The AI handles discovery; the generated script handles repeatability.

Ask Claude: "Explore the signup flow at localhost:3000 and generate a Playwright test script that covers the happy path and the validation error case for an invalid email."


Performance Considerations

Memory: Each Chromium instance uses ~150–400MB RAM. Firefox uses slightly less. For high-volume automation, consider:

json
{
  "browser": "chromium",
  "headless": true,
  "args": [
    "--disable-dev-shm-usage",
    "--disable-gpu",
    "--no-sandbox"
  ]
}

Concurrency: Playwright MCP handles one task at a time per server instance. For parallel workloads, spawn multiple instances. A load balancer or orchestration layer routes requests.

Startup time: Browser cold start takes 1–3 seconds. For latency-sensitive workflows, keep the MCP server running rather than spawning it per request.

Snapshot vs. screenshot performance:

  • browser_snapshot → typically 50–200ms
  • browser_screenshot → 200–500ms (image encoding overhead)

Use snapshots by default. Reserve screenshots for moments when visual evidence is genuinely required.

Timeouts: The default navigation timeout is 30 seconds. For slow target sites, increase it. For fast internal apps, reduce it to fail faster:

json
{
  "timeout": 10000
}

Troubleshooting Common Problems

"Browser executable not found"

Cause: Playwright browser binaries not installed.
Fix:

bash
npx playwright install chromium
# Or if you installed @playwright/mcp globally:
playwright install chromium

MCP Server Doesn't Appear in Claude/Cursor

Cause: JSON syntax error in config file, wrong file path, or client not restarted.
Fix:

bash
# Validate JSON syntax
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json | python3 -m json.tool
# Fix any errors, then fully quit and restart Claude Desktop

Cause: Target page is slow or network is unreliable.
Fix: Increase timeout in config:

json
{ "timeout": 60000 }

Or investigate if the URL is actually reachable from the MCP server's network context.

Agent Can't Find Elements

Cause: Page uses iframes, shadow DOM, or canvas — these aren't fully represented in the accessibility tree.
Fix: Use browser_screenshot to visually inspect the page. For iframes, the MCP server may need explicit frame switching support depending on version. Check the official changelog for frame handling updates.

"Access denied" or "Origin not allowed"

Cause: allowedOrigins is set and the URL doesn't match.
Fix: Add the origin to the allowlist in your config. Remember that origins include protocol + domain + port (e.g., http://localhost:3000 is different from http://localhost).

High Memory Usage

Cause: Browser context not being properly closed between tasks, or too many tabs open.
Fix: Configure the agent to explicitly close tabs after tasks. In Docker, set mem_limit. Add --disable-dev-shm-usage to Chromium args if running in containers with limited /dev/shm.

Extension Not Loading

Cause: Running in headless mode (default) or using Firefox/WebKit.
Fix: Switch to Chromium in headed mode with a persistent userDataDir.


Verifying Your Playwright MCP Server

Before trusting any MCP server in a production workflow, verify it exposes the tools it claims to, behaves correctly under error conditions, and doesn't have configuration issues.

MCPForge's verification tool lets you point at an MCP server and automatically enumerate its tools, test basic connectivity, and flag common misconfigurations. For Playwright MCP specifically, this confirms your tool list matches what you configured and that snapshot/screenshot tools respond correctly.

If you've built a custom wrapper around Playwright MCP — adding auth middleware, custom tools, or domain-specific behaviors — listing it in the MCPForge verified directory helps other teams discover and trust it.


Recent Protocol and Ecosystem Updates

As of late 2024 and into 2025, several important changes affect Playwright MCP deployments:

MCP 1.0 Specification stabilization: The core JSON-RPC protocol, tool discovery handshake, and capability negotiation patterns are now stable. If you're running Playwright MCP built against pre-1.0 MCP drafts, upgrade — there are breaking changes in error codes and capability advertisement.

Playwright 1.49+ changes: Recent Playwright versions improved accessibility tree fidelity for ARIA patterns and fixed edge cases in shadow DOM traversal. If your snapshots were missing elements, upgrading Playwright (and reinstalling browser binaries with npx playwright install) often fixes it.

@playwright/mcp SSE transport: The server-sent events transport mode is now production-stable, enabling remote connections without stdio. This makes centralized deployment (one MCP server, multiple AI clients) viable.

Vision mode improvements: The package now supports explicit --vision mode where the AI works primarily from screenshots rather than accessibility trees. This is useful for canvas-heavy apps (maps, design tools, games) but uses significantly more tokens.


Production Checklist

Before deploying Playwright MCP in any production or team environment:

  • Playwright browser binaries installed and version-pinned
  • allowedOrigins configured to restrict navigable URLs
  • headless: true unless headed is explicitly required
  • userDataDir set to a secure, non-repo path with chmod 700
  • MCP server not exposed on public ports without authentication
  • Docker image uses Microsoft's official Playwright base image
  • Memory limits set on container (mem_limit: 2g minimum)
  • Timeouts configured for your target environment's latency
  • ignoreHTTPSErrors: false (never true in production)
  • Server logs captured and monitored
  • MCP server config validated through MCPForge Verify
  • Tested with browser_snapshot before browser_screenshot for efficiency
  • .playwright-profile/ in .gitignore

Key Takeaways

Playwright MCP makes browser automation a first-class capability for AI agents — but it's not magic. The tools are only as reliable as your configuration, your allowed origins, and your understanding of how accessibility snapshots work.

Start with isolated sessions and allowedOrigins. Add persistent sessions only when your workflow genuinely needs stored auth. Run in Docker for any production deployment. And prefer browser_snapshot over browser_screenshot until you have a reason to reach for the visual approach.

The accessibility-first design isn't an arbitrary choice — it's what makes AI-driven browser automation reliable at scale. An agent that reads the accessibility tree will be more consistent than one that interprets screenshots, because the tree doesn't vary with viewport size, font rendering, or OS theme.

For teams running multiple MCP servers across different workflows, the patterns in running MCP in production cover the orchestration, monitoring, and zero-downtime deployment concerns that come with serious adoption.

Frequently Asked Questions

What is Playwright MCP and how is it different from regular Playwright?

Playwright MCP is a Model Context Protocol server that wraps Microsoft's Playwright browser automation library. Instead of writing Playwright scripts yourself, AI agents like Claude or Cursor can control browsers directly through MCP tool calls. Regular Playwright requires you to write code; Playwright MCP lets an AI write and execute that code on your behalf, with structured tool discovery and safety controls.

Does Playwright MCP work with headless browsers?

Yes. By default, Playwright MCP runs in headless mode, meaning the browser runs without a visible window. You can enable headed mode by passing the --headed flag or setting 'headless: false' in your configuration. Headed mode is useful for debugging visual issues or workflows that depend on browser extensions.

Can I use Playwright MCP with Claude Desktop?

Yes. Add Playwright MCP to Claude Desktop's configuration file (claude_desktop_config.json) under the mcpServers key. Use the npx @playwright/mcp command. Once configured and Claude Desktop is restarted, Claude can take screenshots, click elements, fill forms, and navigate URLs directly from the chat interface.

What is an accessibility snapshot in Playwright MCP?

An accessibility snapshot is a structured, text-based representation of the browser's current DOM, derived from the Accessibility Tree rather than a screenshot. It tells the AI which elements are interactive, their roles, labels, and text content — enabling more reliable and token-efficient interactions compared to image-based vision approaches.

Is Playwright MCP safe to run in production?

It can be, but requires deliberate configuration. You should restrict allowed origins, disable unnecessary capabilities, use isolated browser sessions per task, and never expose the MCP server publicly without authentication. For production use, always run in an isolated Docker container with limited network access.

How do I handle authentication with Playwright MCP persistent sessions?

Playwright MCP supports persistent browser contexts that store cookies, localStorage, and session data between runs. You specify a userDataDir path in your config. On first run, the AI (or you manually) can log in, and subsequent sessions reuse those credentials. For production, store the userDataDir securely and treat it like a credential file.

Can Playwright MCP run multiple browser sessions simultaneously?

Yes, but each MCP server instance manages one browser context at a time. To run parallel sessions, you spin up multiple Playwright MCP server instances, each with its own configuration and optionally separate userDataDir paths. Orchestration tools or your AI agent framework handles routing requests to the correct instance.

What browsers does Playwright MCP support?

Playwright MCP supports Chromium, Firefox, and WebKit — the same browsers as the underlying Playwright library. You configure the target browser via the --browser flag or the 'browser' key in your JSON config. Chromium is the default and most commonly used for automation tasks.

How do I debug Playwright MCP when tools aren't working?

Start by enabling headed mode so you can see what the browser is doing. Check the MCP server logs for JSON-RPC errors. Use the browser_snapshot tool to inspect the current page state. Verify Playwright browsers are installed with 'npx playwright install'. If using Claude or Cursor, confirm the MCP server entry is syntactically valid JSON.

Does Playwright MCP support browser extensions?

Yes, with limitations. Browser extensions require a persistent browser context and must be loaded via the --extension-path flag. Only Chromium supports extensions in Playwright. Extensions are useful for scenarios like maintaining logged-in states, ad blocking during scraping, or testing extension-dependent UI.

Check your MCP security posture

Generate a Security Score, detect risky tools, and review permissions before exposing APIs to AI agents.