Playwright MCP Wrapper - Reliable Browser Automation in Containers

If you've ever tried to run browser automation inside Docker containers or DevContainers, you know the pain. Browsers don't run well in containers, MCP servers crash frequently, and connecting containerized environments to host browsers is a nightmare.
That's why I built playwright-mcp-wrapper.
The Problem
When developing inside Docker containers, you face three major challenges:
- You can't run browsers directly in containers - Browsers need display servers, GPU access, and system libraries that containers don't provide reliably
- MCP servers running on host need connection management - Your containerized development environment needs to connect to MCP servers on the host machine
- Frequent server crashes - Playwright MCP servers are unstable and crash often, breaking your automation workflows
The typical solution? Run MCP servers on your host machine and connect to them from containers. But this creates a new problem: who manages the servers? How do you keep them running? How do you handle multiple browsers?
The Solution: playwright-mcp-wrapper
This wrapper tool solves all three problems:
1. Persistent Process Management with PM2
Instead of manually starting/stopping MCP servers, the wrapper uses PM2 to:
- Auto-start all browser servers with a single command
- Auto-recover when servers crash
- Monitor server health
- Provide centralized logs
npm start # Start all browser servers
npm stop # Stop all servers
npm test # Test all endpoints
2. Multi-Browser Support with Dedicated Ports
The wrapper manages 6 different browser types, each on its own dedicated port:
- Chrome (8931) - Default Chrome browser
- Brave (8932) - Privacy-focused browsing
- Firefox (8933) - Mozilla's browser engine
- Chromium (8934) - Open-source base
- WebKit (8935) - Safari's engine
- Comet (8936) - Custom browser profile
Plus two additional persistent browser profiles on ports 8941-8942.
3. Seamless Container Integration
The real magic happens when connecting from containers. Here's how it works:
Local development:
{
"mcpServers": {
"playwright-chrome": {
"url": "http://localhost:8931/sse"
}
}
}
Inside Docker/DevContainer:
{
"mcpServers": {
"playwright-chrome": {
"url": "http://host.docker.internal:8931/sse"
}
}
}
That's it. The host.docker.internal
hostname automatically resolves to your host machine from inside the container.
How It Works
The project uses an ecosystem.config.js
file that defines PM2 apps for each browser:
module.exports = {
apps: [
{
name: "mcp-chrome",
script: "npx",
args: "-y @executeautomation/playwright-mcp-server ./chrome.json",
cwd: "./browser-configs",
autorestart: true,
watch: false
},
// ... more browsers
]
};
Each browser has its own JSON config file specifying the port and browser type:
{
"port": 8931,
"browserName": "chrome"
}
Real-World Usage
I built this because I develop exclusively inside DevContainers, and running browser automation was a constant headache. Now:
- Start servers once on host machine with
npm start
- Configure Claude Code/AI tools inside DevContainer to use
host.docker.internal
URLs - Automation just works - servers auto-recover if they crash
- Test across browsers easily by switching ports
Installation
git clone https://github.com/ssv445/playwright-mcp-wrapper.git
cd playwright-mcp-wrapper
npm install -g pm2 playwright
npm install
npm start
Visit any browser's SSE endpoint to verify it's running:
curl http://localhost:8931/sse
Use it To Feel it
If you develop in containers and need browser automation, give playwright-mcp-wrapper a try.
The days of fighting with browser processes are over.