Playwright MCP Server

Playwright MCP Server

Enables browser automation through the MCP protocol, allowing AI agents to control a real browser using accessibility snapshots and natural language commands.

Category
Visit Server

README

Playwright MCP Server — POC with 100+ Test Cases

VentureDive QA Engineering Prepared by: Raheel Imran Date: May 2026


Overview

This Proof of Concept (POC) demonstrates the Playwright MCP Server (@playwright/mcp) used as the browser automation engine for a complete test suite. It includes:

  • A fully functional demo web application — TaskMaster Pro
  • 166 Playwright test cases across 8 feature areas using reusable MCP-style commands
  • A cmd fixture that maps directly to @playwright/mcp tool names
  • A live MCP server demo that connects via @modelcontextprotocol/sdk and drives the browser using real MCP protocol — no external API calls
  • MCP server configuration for Claude Desktop and Claude Code
  • An interactive HTML test report

Architecture

┌──────────────────────────────────────────────────────────────┐
│                   Playwright MCP POC                         │
│                                                              │
│  ┌───────────────────┐   MCP Protocol    ┌────────────────┐  │
│  │  MCP Client       │◄─────────────────►│ @playwright/mcp│  │
│  │  (run-demo.ts)    │   stdio transport │  Server        │  │
│  └───────────────────┘                   └───────┬────────┘  │
│                                                  │           │
│                                         Playwright Browser   │
│                                                  │           │
│                                         ┌────────▼─────────┐ │
│                                         │ TaskMaster Pro   │ │
│                                         │ localhost:3000   │ │
│                                         └──────────────────┘ │
│                                                              │
│  Playwright Test Runner (166 tests)                          │
│  └── tests/fixtures/browser-commands.ts  ← reusable cmd      │
│      ├── auth.spec.ts          (25 tests)                    │
│      ├── navigation.spec.ts    (20 tests)                    │
│      ├── dashboard.spec.ts     (12 tests)                    │
│      ├── tasks.spec.ts         (45 tests)                    │
│      ├── categories.spec.ts    (14 tests)                    │
│      ├── profile.spec.ts       (17 tests)                    │
│      ├── settings.spec.ts      (17 tests)                    │
│      └── ui-components.spec.ts (16 tests)                    │
└──────────────────────────────────────────────────────────────┘

Quick Start

1. Install dependencies

npm install
npx playwright install chromium

2. Start the demo app

npm run dev
# → http://localhost:3000

3. Run all tests and generate HTML report

npm test
npm run test:report    # opens playwright-report/index.html

4. Run the MCP server demo (browser driven via MCP protocol)

npm run demo
# Starts @playwright/mcp server, connects as MCP client, runs 10 scenarios

5. Interactive test runner

npm run test:ui

npm Scripts

Script Description
npm run dev Start the TaskMaster Pro demo app on port 3000
npm test Run all 100+ tests (Chromium + Firefox)
npm run test:ui Open Playwright interactive UI mode
npm run test:report Open generated HTML report
npm run test:headed Run tests in headed browser
npm run test:debug Run tests with Playwright debugger
npm run demo Run the MCP server demo (real MCP protocol)
npm run mcp:start Start @playwright/mcp standalone server

Reusable Browser Commands

All tests import from tests/fixtures/browser-commands.ts instead of @playwright/test directly. Command names match @playwright/mcp tool names exactly, making the test code portable to any MCP client.

import { test, expect } from './fixtures/browser-commands';

test('example', async ({ cmd }) => {
  await cmd.browser_navigate('/login.html');
  await cmd.browser_type('email-input', 'testuser@test.com');
  await cmd.browser_type('password-input', 'Test@123');
  await cmd.browser_click('login-btn');
  await cmd.browser_expect_url(/dashboard/);
  await cmd.browser_take_screenshot('login-success.png');
});

Full command reference

Command MCP Tool Description
cmd.browser_navigate(url) browser_navigate Navigate to URL
cmd.browser_navigate_back() browser_navigate_back Go back in history
cmd.browser_click(testId) browser_click Click element by data-testid
cmd.browser_type(testId, text) browser_type Fill input field
cmd.browser_clear_and_type(testId, text) browser_type Clear then fill
cmd.browser_select_option(testId, value) browser_select_option Select dropdown option
cmd.browser_check(testId) browser_click Check a checkbox
cmd.browser_uncheck(testId) browser_click Uncheck a checkbox
cmd.browser_take_screenshot(filename?) browser_take_screenshot Capture screenshot
cmd.browser_get_url() — Get current URL
cmd.browser_get_text(testId) — Get element text
cmd.browser_get_value(testId) — Get input value
cmd.browser_is_visible(testId) browser_snapshot Returns boolean
cmd.browser_is_checked(testId) browser_snapshot Returns boolean
cmd.browser_count(testId) browser_snapshot Count elements
cmd.browser_wait_for(testId, state?) browser_wait_for Wait for element
cmd.browser_wait_for_url(pattern) — Wait for URL
cmd.browser_set_storage(key, value) — (fixture-only) Set localStorage via page.evaluate
cmd.browser_evaluate(fn) — (fixture-only) Run JS via page.evaluate
cmd.browser_expect_url(pattern) — Assert current URL
cmd.browser_expect_visible(testId) — Assert visible
cmd.browser_expect_hidden(testId) — Assert hidden
cmd.browser_expect_text(testId, text) — Assert text content
cmd.browser_expect_count(testId, n) — Assert element count
cmd.browser_expect_value(testId, val) — Assert input value
cmd.browser_expect_checked(testId) — Assert checkbox state
cmd.browser_expect_disabled(testId) — Assert disabled
cmd.browser_expect_attr(testId, attr, val) — Assert attribute

Demo App — TaskMaster Pro

A fully self-contained web app using localStorage for all data persistence.

Page URL Features
Login /login.html Form validation, password toggle, remember-me
Register /register.html Password strength, validation
Dashboard /dashboard.html Stats, recent tasks, quick-add
Tasks /tasks.html CRUD, filter, search, sort, bulk actions
Categories /tasks.html#categories Create, edit, delete categories
Profile /profile.html Edit name, avatar, change password
Settings /settings.html Theme, notifications, language, export
404 /404.html Error page

Default test credentials:

Email Password Role
testuser@test.com Test@123 Test User
admin@test.com Admin@123 Admin User

Pre-seeded data: 5 tasks (3 active, 2 completed) and 4 categories.

MCP Tools provided by @playwright/mcp

See the full categorized reference in MCP Server Setup → Available MCP tools below. Key tools used in this demo app:

Tool Description
browser_navigate Navigate to a URL
browser_snapshot Get accessibility tree — returns ARIA refs for click/type targets
browser_click Click an element by ARIA ref
browser_type Type text into a focused field
browser_fill_form Fill multiple form fields in one call
browser_select_option Select a dropdown value
browser_take_screenshot Capture the current page as an image
browser_localstorage_set Write a localStorage key (used for fast auth seeding)
browser_evaluate Evaluate JavaScript on the page
browser_wait_for Wait for an element or condition
browser_network_requests Inspect captured network traffic
browser_route Mock API responses for isolated testing
browser_tabs List, open, close, or switch tabs
browser_close Close the browser

MCP Server Setup

@playwright/mcp exposes browser automation as MCP tools so any MCP-compatible client (Claude Code, Claude Desktop, VS Code, Cursor, Windsurf) can drive a real browser with no screenshots or vision models — just accessibility snapshots.

Claude Code (project-level)

A .mcp.json file is included at the project root. Claude Code picks it up automatically when you open this directory:

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

Or install it manually via the CLI:

claude mcp add playwright npx @playwright/mcp@latest

Claude Desktop

Add the following to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

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

VS Code

One-liner via the VS Code CLI:

code --add-mcp '{"name":"playwright","command":"npx","args":["@playwright/mcp@latest"]}'

Or use the included .vscode/mcp.json — VS Code with the Copilot extension picks it up automatically:

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

Cursor / Windsurf

Add the same block under mcpServers in their respective settings files.

Configuration options

Append flags to the args array to customise the server:

Flag Effect
--headless Run browser without a visible window (default: headed)
--browser <browser> Browser to use: chrome, firefox, webkit, msedge (default: Chromium)
--isolated Keep browser profile in memory; do not persist to disk
--port <n> Expose the server over HTTP/SSE instead of stdio
--host <host> Host to bind to (default: localhost; use 0.0.0.0 for all interfaces)
--vision Use screenshots instead of accessibility snapshots (requires vision model)
--caps <caps> Comma-separated capability subset: tabs,pdf,history,wait,files,install
--device <device> Emulate a device, e.g. "iPhone 15"
--viewport-size <size> Set viewport, e.g. "1280, 720"
--user-agent <ua> Override the browser user-agent string
--storage-state <path> Load saved auth state (cookies/localStorage) from a JSON file
--save-trace Save a Playwright Trace of the session to --output-dir
--output-dir <path> Directory for screenshots, PDFs, and traces
--proxy-server <proxy> Route traffic through a proxy, e.g. http://myproxy:3128
--no-sandbox Disable the browser sandbox (useful in some CI environments)
--extension Connect to an existing browser tab instead of launching a new browser
--config <path> Load advanced settings from a JSON config file

Example — headless Firefox in isolated mode:

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest", "--headless", "--browser=firefox", "--isolated"]
    }
  }
}

Standalone server (HTTP transport)

For headless/CI environments where stdio is not suitable:

npx @playwright/mcp@latest --port 8931

Then point your MCP client at http://localhost:8931/mcp using the url form:

{
  "mcpServers": {
    "playwright": {
      "url": "http://localhost:8931/mcp"
    }
  }
}

Available MCP tools

Navigation

Tool Description
browser_navigate Navigate to a URL
browser_navigate_back / browser_navigate_forward Browser history navigation
browser_reload Reload the current page

Interaction

Tool Description
browser_click Click an element by ARIA ref
browser_check / browser_uncheck Check or uncheck a checkbox
browser_type Type text into a focused field
browser_press_sequentially Type text one character at a time (for masked fields)
browser_fill_form Fill multiple form fields by their labels in one call
browser_select_option Select a dropdown value
browser_hover Hover over an element
browser_drag / browser_drop Drag-and-drop between elements
browser_press_key / browser_keydown / browser_keyup Keyboard key events
browser_handle_dialog Accept or dismiss browser dialogs
browser_file_upload Upload a file to a file input
browser_mouse_click_xy / browser_mouse_move_xy / browser_mouse_drag_xy Pixel-precise mouse control
browser_mouse_down / browser_mouse_up / browser_mouse_wheel Low-level mouse events

Inspection & Assertions

Tool Description
browser_snapshot Get the page accessibility tree — primary way to read elements and obtain ARIA refs
browser_take_screenshot Capture the current page as an image
browser_annotate Capture a screenshot with annotated highlights
browser_highlight / browser_hide_highlight Visually highlight an element on the page
browser_generate_locator Generate a Playwright locator for a given element
browser_verify_element_visible Assert an element is visible
browser_verify_text_visible Assert specific text is visible on the page
browser_verify_list_visible Assert a list of items is visible
browser_verify_value Assert an element's value
browser_wait_for Wait for an element or network condition

Storage

Tool Description
browser_evaluate Evaluate a JavaScript expression on the page
browser_localstorage_get / browser_localstorage_set / browser_localstorage_list Read/write localStorage
browser_localstorage_clear / browser_localstorage_delete Remove localStorage items
browser_sessionstorage_get / browser_sessionstorage_set / browser_sessionstorage_list sessionStorage CRUD
browser_sessionstorage_clear / browser_sessionstorage_delete Remove sessionStorage items
browser_cookie_get / browser_cookie_set / browser_cookie_list Read/write cookies
browser_cookie_clear / browser_cookie_delete Remove cookies
browser_storage_state Export current cookies and storage to a file
browser_set_storage_state Import previously saved storage state

Network

Tool Description
browser_network_requests List all captured network requests
browser_network_request Get details for a single network request
browser_network_clear Clear the captured request log
browser_network_state_set Simulate online/offline/throttled network conditions
browser_route Mock requests matching a URL pattern with a custom response
browser_route_list List active route mocks
browser_unroute Remove a route mock

Tabs

Tool Description
browser_tabs List, create (new), close, or switch to a tab by index

Console

Tool Description
browser_console_messages Get browser console output
browser_console_clear Clear the console message log

Recording & Tracing

Tool Description
browser_start_tracing / browser_stop_tracing Record a Playwright Trace
browser_start_video / browser_stop_video / browser_video_chapter Record session video
browser_pdf_save Save the current page as a PDF

Misc

Tool Description
browser_resize Resize the browser window
browser_get_config Get the current server configuration
browser_run_code_unsafe Execute an arbitrary Playwright script (RCE-equivalent; trusted clients only)
browser_close Close the browser

How accessibility snapshots work: Instead of returning a screenshot, browser_snapshot returns a structured text tree of all visible elements with their roles, labels, and unique [ref=…] identifiers. LLMs reference these ids when calling browser_click or browser_type — no vision model required.

Verify the server is working

# Start the demo app first
npm run dev

# Then run the MCP demo (connects via stdio and runs 10 browser scenarios)
npm run demo

MCP Demo (demo/)

demo/run-demo.ts connects to @playwright/mcp via real MCP stdio protocol using @modelcontextprotocol/sdk. It runs 10 browser scenarios with no external API dependencies.

npm run demo
╔══════════════════════════════════════════════════════════╗
║  Playwright MCP Server — Direct MCP Protocol Demo       ║
╚══════════════════════════════════════════════════════════╝

Target: http://localhost:3000
Transport: stdio (@playwright/mcp subprocess)

Connecting to @playwright/mcp server…
Connected.

Available MCP tools (14):
  • browser_navigate
  • browser_snapshot
  • browser_click
  …

S01  ✓ PASS  Login page loads via MCP browser_navigate
S02  ✓ PASS  Fill login form using browser_type
S03  ✓ PASS  Capture login page screenshot
…

Test Coverage

Area Tests TC Range
Authentication 25 TC001–TC025
Navigation 20 TC026–TC045
Dashboard 12 TC046–TC057
Task Management 45 TC058–TC102
Categories 14 TC103–TC116
Profile 17 TC117–TC133
Settings 17 TC134–TC150
UI Components 16 TC151–TC166
Total 166

Project Structure

.
├── demo-app/
│   ├── server.js                  Express static file server (port 3000)
│   └── public/
│       ├── index.html             Entry point (redirect)
│       ├── login.html
│       ├── register.html
│       ├── dashboard.html
│       ├── tasks.html             Tasks + Categories
│       ├── profile.html
│       ├── settings.html
│       ├── 404.html
│       ├── css/styles.css
│       └── js/utils.js            Shared helpers + seed data
├── tests/
│   ├── fixtures/
│   │   └── browser-commands.ts    Reusable MCP-style command fixture
│   ├── helpers/
│   │   └── auth.helper.ts         Fast localStorage-based auth setup
│   ├── auth.spec.ts               TC001–TC025
│   ├── navigation.spec.ts         TC026–TC045
│   ├── dashboard.spec.ts          TC046–TC057
│   ├── tasks.spec.ts              TC058–TC102
│   ├── categories.spec.ts         TC103–TC116
│   ├── profile.spec.ts            TC117–TC133
│   ├── settings.spec.ts           TC134–TC150
│   └── ui-components.spec.ts      TC151–TC166
├── demo/
│   ├── scenarios.ts               10 MCP test scenario definitions
│   └── run-demo.ts                MCP client demo (real MCP protocol)
├── playwright-report/             Generated HTML report (after npm test)
├── playwright.config.ts
├── package.json
└── tsconfig.json

Key Design Decisions

Decision Rationale
data-testid attributes on all elements Tests don't break when CSS or text changes
Reusable browser-commands.ts fixture Command names match @playwright/mcp tools — tests are portable
loginViaStorage() helper Sets session via localStorage.setItem directly — 10× faster than UI login
Sequential workers (workers: 1) Prevents localStorage conflicts between parallel tests
retries: 1 locally, retries: 2 on CI Handles transient timing issues without masking real failures
No external API dependencies MCP demo uses @playwright/mcp directly via stdio protocol

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
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

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