ljchang/playwright-mcp-server
If you are the rightful owner of playwright-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
The Playwright MCP Server is a Model Context Protocol server designed to facilitate browser automation for web application testing, documentation generation, and accessibility checks.
Playwright MCP Server
A Model Context Protocol (MCP) server that provides Playwright browser automation tools for testing web applications, capturing screenshots, generating documentation, and running accessibility checks.
Features
Core Tools
- screenshot - Capture full page or element screenshots
- test_login - Test login flows with credentials
- fill_form - Fill and submit forms automatically
- check_element - Verify element existence and content
- navigate_and_wait - Navigate to URLs with custom wait conditions
- click_and_wait - Click elements and wait for results
- extract_text - Extract text content from page elements
- run_accessibility_check - Run WCAG accessibility audits
- generate_pdf - Convert webpages to PDF documents
- monitor_network - Monitor and capture network requests
Session Management Tools
- start_session - Start a persistent browser session that stays open
- end_session - Close a specific browser session
- list_sessions - List all active browser sessions
- get_session_state - Get current state of a browser session
- get_page_context - Get detailed page context including forms, buttons, and links
- get_screenshot_history - Get screenshot history for a session
Multi-Participant Test Scenarios (NEW!)
- create_test_scenario - Create named test scenarios to group related sessions
- list_test_scenarios - View all active test scenarios
- get_test_scenario - Get detailed scenario information and session list
- update_scenario_state - Track test phases and custom state data
- end_test_scenario - Clean up scenario and close all associated sessions
- Enhanced sessions - Sessions can have roles (admin/participant) and labels
Debugging & Console Tools
- console - Interactive JavaScript console - execute commands in page context
- console_history - Get console command history for the session
- inspect_object - Deep inspect any JavaScript object or variable
- execute_script - Execute JavaScript code in the page
- get_debug_info - Get console logs, errors, and network activity
- get_dom_snapshot - Get structured DOM representation
- set_breakpoint - Set debugging breakpoints in JavaScript code
All tools now support both one-off operations and persistent sessions!
Installation
Prerequisites
- Node.js 18+
- npm or yarn
- Docker (optional, for containerized deployment)
Local Setup
- Clone the repository:
git clone https://github.com/yourusername/playwright-mcp-server.git
cd playwright-mcp-server
- Install dependencies:
npm install
- Install Playwright browsers:
npx playwright install chromium
- Create environment file:
cp .env.example .env
- Edit
.env
with your configuration:
TEST_USER=testuser@example.com
TEST_PASS=testpassword123
HEADLESS=true
APP_BASE_URL=http://localhost:3000
Usage
Using with Claude Code (Recommended)
Claude Code automatically manages the MCP server lifecycle - no need to manually start the server!
Quick Setup (Global Installation)
- First, ensure you have the server installed:
git clone https://github.com/ljchang/playwright-mcp-server.git
cd playwright-mcp-server
npm install
npx playwright install chromium
- Add the server to Claude Code globally (available in all sessions):
claude mcp add playwright-mcp "node" "/absolute/path/to/playwright-mcp-server/src/index.js" --scope user
- Verify the server is connected:
claude mcp list
That's it! The server will automatically start when Claude Code needs it.
Usage Examples in Claude Code
One-off Operations
-
Headless mode (default - fast, no UI):
"Use playwright to screenshot https://example.com"
-
Visible mode (see the browser in action):
"Use playwright to screenshot https://example.com with headless=false"
Persistent Browser Sessions
Keep a browser open for multiple operations - perfect for debugging and interactive testing:
-
Start a session with debugging and screenshots:
"Start a playwright session with debugMode=true and recordScreenshots=true"
Response will include a sessionId like:
session-1234567890-abc123
-
Use the session for multiple operations:
"Use playwright session-1234567890-abc123 to click the login button" "Use playwright session-1234567890-abc123 to fill the form with test data" "Use playwright session-1234567890-abc123 to take a screenshot"
-
Interactive JavaScript console:
"Use playwright console for session-1234567890-abc123 to execute: document.title" "Use playwright to inspect window.localStorage in session-1234567890-abc123" "Use playwright to check console logs for session-1234567890-abc123"
-
Debug and inspect:
"Get debug info for playwright session-1234567890-abc123" "Get DOM snapshot for #app in session-1234567890-abc123" "Get page context for session-1234567890-abc123"
-
List active sessions:
"List all playwright sessions"
-
End a session when done:
"End playwright session-1234567890-abc123"
The browser window stays open between commands, maintaining state, cookies, and login sessions!
Optional: Add Environment Variables
To add credentials or customize behavior:
claude mcp add playwright-mcp "node" "/path/to/playwright-mcp-server/src/index.js" \
--scope user \
-e TEST_USER=your_email@example.com \
-e TEST_PASS=your_password \
-e HEADLESS=false \
-e SLOW_MO=500
Using with Claude Desktop
Add the server to your Claude Desktop configuration (~/Library/Application Support/Claude/claude_desktop_config.json
on macOS):
{
"mcpServers": {
"playwright": {
"command": "node",
"args": ["/path/to/playwright-mcp-server/src/index.js"],
"env": {
"TEST_USER": "testuser@example.com",
"TEST_PASS": "testpassword123",
"HEADLESS": "true"
}
}
}
}
Manual Server Mode
For development or testing without Claude:
Standard Mode
npm start
Development Mode (with auto-reload)
npm run dev
Docker Mode
docker-compose up
Tool Examples
All tools now support:
headless
parameter (default:true
) - Set tofalse
to see the browser in actionsessionId
parameter (optional) - Use an existing browser session for the operation
Take a Screenshot
{
"tool": "screenshot",
"arguments": {
"url": "https://example.com",
"fullPage": true,
"filename": "homepage.png",
"headless": false // Optional: see the browser window
}
}
Test Login Flow
{
"tool": "test_login",
"arguments": {
"url": "https://app.example.com/login",
"usernameSelector": "#email",
"passwordSelector": "#password",
"submitSelector": "button[type='submit']",
"headless": false // Optional: watch the login process
}
}
Fill a Form
{
"tool": "fill_form",
"arguments": {
"url": "https://example.com/contact",
"formData": {
"#name": "John Doe",
"#email": "john@example.com",
"#message": "Test message"
},
"submitSelector": "#submit-button"
}
}
Check Element Content
{
"tool": "check_element",
"arguments": {
"url": "https://example.com",
"selector": "h1",
"expectedText": "Welcome"
}
}
Extract Text Content
{
"tool": "extract_text",
"arguments": {
"url": "https://example.com/blog",
"selectors": ["h1", ".article-title", ".author"],
"extractAll": true
}
}
Run Accessibility Check
{
"tool": "run_accessibility_check",
"arguments": {
"url": "https://example.com",
"standard": "WCAG2AA"
}
}
Generate PDF
{
"tool": "generate_pdf",
"arguments": {
"url": "https://example.com/report",
"filename": "report.pdf",
"format": "A4",
"landscape": false
}
}
Monitor Network Requests
{
"tool": "monitor_network",
"arguments": {
"url": "https://example.com",
"captureTypes": ["xhr", "fetch"],
"filterPattern": "api.*"
}
}
Session Management
Start a Persistent Session with Debugging
{
"tool": "start_session",
"arguments": {
"headless": false, // Default false for sessions
"url": "https://example.com", // Optional initial URL
"debugMode": true, // Capture console logs, errors, network
"recordScreenshots": true // Auto-capture screenshots after each action
}
}
// Returns: sessionId to use with other tools
Use Session with Other Tools
{
"tool": "screenshot",
"arguments": {
"url": "https://example.com/page2",
"sessionId": "session-1234567890-abc123" // Use existing session
}
}
List Active Sessions
{
"tool": "list_sessions",
"arguments": {}
}
End a Session
{
"tool": "end_session",
"arguments": {
"sessionId": "session-1234567890-abc123"
}
}
Debugging Tools
Interactive JavaScript Console
{
"tool": "console",
"arguments": {
"sessionId": "session-1234567890-abc123",
"command": "document.querySelector('#app').innerText",
"mode": "eval" // Options: eval, inspect, watch
}
}
Deep Object Inspection
{
"tool": "inspect_object",
"arguments": {
"sessionId": "session-1234567890-abc123",
"expression": "window.localStorage",
"depth": 3
}
}
Get Debug Information
{
"tool": "get_debug_info",
"arguments": {
"sessionId": "session-1234567890-abc123",
"includeConsole": true,
"includeErrors": true,
"includeNetwork": true
}
}
Get DOM Snapshot
{
"tool": "get_dom_snapshot",
"arguments": {
"sessionId": "session-1234567890-abc123",
"selector": "#app",
"includeStyles": true
}
}
Get Page Context (Forms, Buttons, Links)
{
"tool": "get_page_context",
"arguments": {
"sessionId": "session-1234567890-abc123"
}
}
// Returns all interactive elements on the page
Multi-Participant Test Scenarios (NEW!)
Coordinate multiple browser sessions for testing experiments with multiple participants, different user roles, and complex interactions.
Create a Test Scenario
{
"tool": "create_test_scenario",
"arguments": {
"name": "Collaborative Task Test",
"description": "Testing 2 participants in a collaborative task",
"experimentName": "collab_study_v2",
"testParameters": {
"condition": "synchronous",
"difficulty": "medium"
},
"tags": ["collaboration", "multi-user"]
}
}
// Returns: scenarioId to group related sessions
Start Sessions with Roles and Labels
// Admin session
{
"tool": "start_session",
"arguments": {
"scenarioId": "scenario-123", // Link to scenario
"role": "admin", // Role: admin, participant, observer
"label": "Admin1", // Friendly label
"headless": false,
"url": "https://experiment.com/admin"
}
}
// Participant sessions
{
"tool": "start_session",
"arguments": {
"scenarioId": "scenario-123",
"role": "participant",
"label": "P1",
"headless": false,
"url": "https://experiment.com/join"
}
}
List Sessions by Scenario or Role
{
"tool": "list_sessions",
"arguments": {
"scenarioId": "scenario-123", // Optional: filter by scenario
"role": "participant" // Optional: filter by role
}
}
List All Test Scenarios
{
"tool": "list_test_scenarios",
"arguments": {} // Optional: { "tag": "collaboration" } to filter
}
Get Scenario Details
{
"tool": "get_test_scenario",
"arguments": {
"scenarioId": "scenario-123"
}
}
// Returns scenario metadata, all sessions, and event history
Update Scenario State
{
"tool": "update_scenario_state",
"arguments": {
"scenarioId": "scenario-123",
"phase": "running", // created, running, completed, failed
"customData": {
"participantsReady": true,
"tasksCompleted": 0
}
}
}
End Scenario and Clean Up All Sessions
{
"tool": "end_test_scenario",
"arguments": {
"scenarioId": "scenario-123"
}
}
// Closes all browser sessions associated with the scenario
Complete Multi-Participant Example
Testing multiple participants joining an experiment:
// 1. Create scenario
const scenario = create_test_scenario({
name: "Two-Player Game Test",
experimentName: "multiplayer_game_v1"
});
// 2. Start admin and create experiment
const admin = start_session({
scenarioId: scenario.id,
role: "admin",
label: "Admin"
});
// 3. Start participant 1
const p1 = start_session({
scenarioId: scenario.id,
role: "participant",
label: "P1"
});
// 4. Start participant 2 with delay
await new Promise(r => setTimeout(r, 3000));
const p2 = start_session({
scenarioId: scenario.id,
role: "participant",
label: "P2"
});
// 5. Verify all connected
check_element({
sessionId: admin.id,
selector: "#participant-count",
expectedText: "2"
});
// 6. Clean up everything
end_test_scenario({ scenarioId: scenario.id });
Use Cases
- Multiple Participants: Test experiments requiring 2+ simultaneous users
- Role-Based Testing: Different views for admin vs participants
- Parameter Changes: Verify changes propagate to all participants
- Dropout Recovery: Test handling of participant disconnections
- Synchronization: Ensure all participants see consistent state
Docker Deployment
Build and Run with Docker Compose
# Build the image
docker-compose build
# Run the server
docker-compose up
# Run with test app (optional)
docker-compose --profile with-test-app up
Docker Environment Variables
Configure via docker-compose.yml
or .env
:
NODE_ENV
- Environment (development/production)HEADLESS
- Run browser in headless modeTEST_USER
- Default test usernameTEST_PASS
- Default test passwordMCP_AUTH_TOKEN
- Authentication token for MCP
Environment Configuration
Core Settings
Variable | Description | Default |
---|---|---|
HEADLESS | Run browser in headless mode | true |
TEST_USER | Default username for login tests | - |
TEST_PASS | Default password for login tests | - |
MCP_AUTH_TOKEN | MCP authentication token | - |
Application URLs
Variable | Description | Example |
---|---|---|
APP_BASE_URL | Local development URL | http://localhost:3000 |
APP_STAGING_URL | Staging environment URL | https://staging.example.com |
APP_PRODUCTION_URL | Production environment URL | https://example.com |
Browser Settings
Variable | Description | Default |
---|---|---|
BROWSER_TIMEOUT | Browser operation timeout (ms) | 30000 |
NAVIGATION_TIMEOUT | Page navigation timeout (ms) | 30000 |
SLOW_MO | Delay between actions (ms) | 0 |
Screenshot Settings
Variable | Description | Default |
---|---|---|
SCREENSHOTS_DIR | Directory to save screenshots | ~/.playwright-mcp/screenshots/ |
SCREENSHOT_QUALITY | JPEG quality (1-100) | 80 |
SCREENSHOT_TYPE | Image format (png/jpeg) | png |
Screenshots are saved to ~/.playwright-mcp/screenshots/
by default (in your home directory).
You can override this by setting the SCREENSHOTS_DIR
environment variable.
File Structure
playwright-mcp-server/
āāā src/
ā āāā index.js # Main MCP server implementation
āāā docker/
ā āāā Dockerfile # Docker container configuration
āāā tests/ # Test files
āāā docker-compose.yml # Docker Compose configuration
āāā package.json # Node.js dependencies
āāā .env.example # Environment template
āāā .gitignore # Git ignore rules
āāā run-dev.sh # Development mode script
āāā README.md # Documentation
Note: Screenshots are saved to ~/.playwright-mcp/screenshots/
in your home directory by default.
Development
Running Tests
npm test
Adding New Tools
- Add tool definition in
tools/list
handler - Implement tool logic in
tools/call
switch statement - Update README with usage example
Debugging
Set HEADLESS=false
in .env
to see browser actions:
HEADLESS=false
SLOW_MO=500 # Add 500ms delay between actions
Security Considerations
- Never commit
.env
files with real credentials - Use environment-specific credentials
- Rotate
MCP_AUTH_TOKEN
regularly - Run in containers for isolation
- Limit network access in production
Troubleshooting
Browser Installation Issues
# Reinstall Playwright browsers
npx playwright install --with-deps chromium
Permission Errors in Docker
# Run with proper permissions
docker-compose run --user root playwright-mcp npm install
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
License
MIT License - See LICENSE file for details
Support
For issues and questions:
- Open an issue on GitHub
- Check existing issues for solutions
- Review environment configuration
Acknowledgments
- Built with Playwright for browser automation
- Implements Model Context Protocol (MCP) specification
- Uses official Playwright Docker images for containerization