Playwright MCP Server
A production-ready Model Context Protocol (MCP) server that provides browser automation capabilities using Playwright. Built with the mcp-use framework for enhanced developer experience with built-in Inspector UI and comprehensive error handling.
Overview
This MCP server exposes 6 powerful browser automation tools that allow AI assistants like Claude to interact with web pages, extract information, and perform automated testing. All operations are performed in a managed Chromium browser instance with robust error handling and timeout management.
Key Features:
- 🎭 Playwright Integration - Full async Playwright API support
- 🔍 Built-in Inspector UI - Test tools interactively at
http://localhost:8000/inspector - 📡 Auto-discovery - OpenMCP metadata endpoint at
/openmcp.json - 🛡️ Robust Error Handling - Clear, actionable error messages with suggestions
- 🔄 Crash Recovery - Automatic browser restart on failures
- ⚙️ Highly Configurable - All timeouts and settings via environment variables
- 🐛 Debug Mode - Enhanced logging and
/docsendpoint
Features
6 Browser Automation Tools
- navigate - Navigate to URLs with configurable wait conditions
- click_element - Click elements by CSS selector
- fill_input - Fill form inputs with text
- extract_text - Extract text content from elements
- screenshot - Take viewport or full-page screenshots
- get_page_info - Get current page URL, title, and viewport size
All tools return standardized responses with either success data or detailed error information.
Installation
Prerequisites
- Python 3.13 or higher
- pip (Python package manager)
Setup
- Clone or download this repository
cd "C:\Users\David Jr\playwright-mcp-server"
- Create a virtual environment
python -m venv venv
- Activate the virtual environment
Windows:
venv\Scripts\activate
macOS/Linux:
source venv/bin/activate
- Install dependencies
pip install -r requirements.txt
- Install Playwright browsers
playwright install chromium
- Configure environment variables
# Windows
copy .env.example .env
# macOS/Linux
cp .env.example .env
Edit .env to customize settings (optional - defaults work out of the box).
Quick Start
Running the Server
python src/server.py
You should see output like:
============================================================
🚀 Playwright Automation Server v1.0.0
============================================================
📊 Inspector UI: http://localhost:8000/inspector
📄 API Docs: http://localhost:8000/docs
📋 OpenMCP: http://localhost:8000/openmcp.json
🔌 MCP Endpoint: http://localhost:8000/mcp
💡 Open http://localhost:8000/inspector in your browser
to test all 6 browser automation tools interactively
Press CTRL+C to stop the server
============================================================
Accessing the Inspector UI
What to do:
- Copy the Inspector URL:
http://localhost:8000/inspector - Paste it into your web browser (Chrome, Firefox, Edge, Safari, etc.)
- The Inspector UI will open where you can test all tools
Note: If you see 0.0.0.0 in any URL, replace it with localhost in your browser.
The Inspector UI allows you to:
- See all available tools and their parameters
- Test tools interactively with a web form
- View real-time responses and errors
- Explore the OpenMCP metadata
How to use the Inspector:
- You'll see a list of 6 tools (navigate, click_element, fill_input, etc.)
- Click on a tool to see its description and parameters
- Fill in the parameters (example: url = "https://example.com")
- Click "Execute" to run the tool
- View the results in the response panel
Testing with the Manual Test Script
python tests/manual_test.py
This runs a complete integration test suite covering all tools.
Usage Examples
Tool 1: Navigate
Navigate to a URL and wait for page load:
await navigate("https://example.com")
# Returns:
# {
# "success": True,
# "url": "https://example.com/",
# "title": "Example Domain"
# }
Navigate with custom wait condition:
await navigate("https://example.com", wait_until="networkidle")
Wait conditions:
"load"- Wait for the load event (default)"domcontentloaded"- Wait for DOMContentLoaded event"networkidle"- Wait until network is idle (no requests for 500ms)
Tool 2: Click Element
Click an element by CSS selector:
await click_element("button.submit")
# Returns:
# {
# "success": True,
# "selector": "button.submit",
# "element_text": "Submit Form"
# }
Tool 3: Fill Input
Fill a form input with text:
await fill_input("input[name='email']", "user@example.com")
# Returns:
# {
# "success": True,
# "selector": "input[name='email']",
# "text_length": 16
# }
Tool 4: Extract Text
Extract text content from an element:
await extract_text("h1")
# Returns:
# {
# "success": True,
# "selector": "h1",
# "text": "Example Domain",
# "text_length": 14
# }
Tool 5: Screenshot
Take a viewport screenshot:
await screenshot("./screenshots/homepage.png")
# Returns:
# {
# "success": True,
# "path": "C:\\Users\\David Jr\\playwright-mcp-server\\screenshots\\homepage.png",
# "file_size": 52341,
# "full_page": False,
# "viewport": {"width": 1920, "height": 1080}
# }
Take a full-page screenshot:
await screenshot("./screenshots/full.png", full_page=True)
Supported formats: .png, .jpg, .jpeg
Tool 6: Get Page Info
Get current page information:
await get_page_info()
# Returns:
# {
# "success": True,
# "url": "https://example.com/",
# "title": "Example Domain",
# "viewport": {"width": 1920, "height": 1080}
# }
Configuration Reference
All configuration is done via environment variables in the .env file:
Server Configuration
| Variable | Description | Default |
|---|---|---|
DEBUG | Enable debug mode with enhanced logging | true |
HOST | Server host address | 0.0.0.0 |
PORT | Server port | 8000 |
Browser Configuration
| Variable | Description | Default |
|---|---|---|
HEADLESS | Run browser in headless mode | true |
BROWSER_TIMEOUT | Browser launch timeout (ms) | 30000 |
VIEWPORT_WIDTH | Browser viewport width | 1920 |
VIEWPORT_HEIGHT | Browser viewport height | 1080 |
Operation Timeouts
| Variable | Description | Default |
|---|---|---|
NAVIGATION_TIMEOUT | Page navigation timeout (ms) | 30000 |
ELEMENT_TIMEOUT | Element interaction timeout (ms) | 10000 |
SCREENSHOT_TIMEOUT | Screenshot capture timeout (ms) | 5000 |
Screenshot Configuration
| Variable | Description | Default |
|---|---|---|
SCREENSHOT_DIR | Directory for screenshots | ./screenshots |
Error Handling
All tools return standardized error responses with actionable suggestions:
{
"success": False,
"error": "Element 'button.submit' not found or not clickable within 10000ms",
"error_type": "ElementNotFound",
"suggestion": "Check if selector is correct and element is visible",
"selector": "button.submit"
}
Error Types
- ValidationError - Invalid inputs (bad URL, empty parameters, wrong types)
- ElementNotFound - Selector not found or element not visible/clickable
- TimeoutError - Operation exceeded timeout
- NetworkError - DNS failures, connection refused, SSL errors
- FileSystemError - File write permission errors
- InvalidElementState - Element is disabled or read-only
- UnknownError - Unexpected errors with details
Common Issues and Solutions
Browser fails to launch
Error: Failed to launch browser
Solution:
- Ensure Playwright browsers are installed:
playwright install chromium - Check that you have sufficient permissions
- Try running with
HEADLESS=falsein.envto see browser window
Element not found
Error: Element not found with given selector
Solution:
- Verify the CSS selector is correct
- Check if element is inside an iframe (not currently supported)
- Increase
ELEMENT_TIMEOUTif page loads slowly - Use browser dev tools to test your selector
Navigation timeout
Error: Navigation timed out after 30000ms
Solution:
- Increase
NAVIGATION_TIMEOUTin.env - Check your internet connection
- Verify the URL is accessible
- Try using
wait_until="domcontentloaded"instead of"load"
Screenshot permission denied
Error: Permission denied
Solution:
- Check write permissions for the target directory
- Ensure parent directories exist (created automatically by the tool)
- Verify you have disk space available
Development
Project Structure
playwright-mcp-server/
├── src/
│ ├── __init__.py
│ ├── server.py # Main MCP server with 6 tools
│ └── browser_manager.py # Singleton browser lifecycle management
├── tests/
│ ├── __init__.py
│ ├── test_server.py # Unit tests
│ └── manual_test.py # Integration test script
├── .env.example # Environment template
├── .gitignore # Git ignore rules
├── requirements.txt # Python dependencies
├── README.md # This file
└── pyproject.toml # Project metadata
Running Tests
Unit tests (requires pytest):
pytest tests/test_server.py -v
Integration tests:
python tests/manual_test.py
Code Quality
This project follows best practices:
- ✅ Type hints on all functions
- ✅ Comprehensive docstrings
- ✅ Async/await throughout
- ✅ Singleton pattern for browser management
- ✅ Standardized error responses
- ✅ Configuration via environment variables
- ✅ Graceful shutdown handling
Architecture
BrowserManager (Singleton):
- Manages browser lifecycle
- Lazy initialization (browser starts on first use)
- Async lock prevents race conditions
- Automatic crash recovery
- Graceful cleanup on shutdown
MCP Server:
- Built with
mcp-useframework - 6 tools decorated with
@server.tool() - Streamable HTTP transport for Inspector UI
- Signal handlers for graceful shutdown
- Comprehensive error parsing
Integration with Claude Desktop
To use this server with Claude Desktop, add to your Claude config:
Windows: %APPDATA%\Claude\claude_desktop_config.json
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"playwright": {
"command": "python",
"args": [
"C:\\Users\\David Jr\\playwright-mcp-server\\src\\server.py"
],
"env": {
"PYTHONPATH": "C:\\Users\\David Jr\\playwright-mcp-server\\src"
}
}
}
}
Note: For production use with Claude Desktop, modify server.py to use transport="stdio" instead of transport="streamable-http".
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
License
MIT License - feel free to use this in your own projects.
Support
For issues and questions:
- Check the Troubleshooting section above
- Review the test files for usage examples
- Open an issue on GitHub
Acknowledgments
Built with:
- Playwright - Browser automation framework
- mcp-use - Enhanced MCP server framework
- Model Context Protocol - Protocol specification
📚 Citation
@software{mcp_use2025, author = {Zullo, Pietro and Contributors}, title = {MCP-Use: Complete MCP Ecosystem for Python and TypeScript}, year = {2025}, publisher = {GitHub}, url = {https://github.com/mcp-use/mcp-use}
}
Version: 1.0.0 Author: Built with Claude Code Last Updated: 2026-01-30