Puppeteer Swarm MCP
MCP server for browser automation with tab pool support using Puppeteer.
Features
- Explicit Browser Control: Launch and close browser on demand via
launch/closetools - Tab Pool: Manage multiple browser tabs concurrently
- Auto-release: Automatically release tabs after idle timeout (default: 5 minutes)
- Auto-recovery: Automatically recover crashed tabs
- Configurable: Set tab count and headless mode via CLI arguments
Installation
Option 1: Install from npm
npm install -g puppeteer-swarm-mcp
Or run directly using npx:
npx puppeteer-swarm-mcp
Option 2: Install from source
git clone https://github.com/greatSumini/puppeteer-swarm-mcp.git
cd puppeteer-swarm-mcp
npm install
npm run build
Usage
# Default: 5 tabs, headless=false
puppeteer-swarm-mcp
# Custom tab count
puppeteer-swarm-mcp --tabs=10
# Headless mode
puppeteer-swarm-mcp --headless
# Combined options
puppeteer-swarm-mcp --tabs=10 --headless
Environment Variables
TAB_COUNT=10 HEADLESS=true puppeteer-swarm-mcp
MCP Client Integration
Puppeteer Swarm MCP can be integrated with various AI coding assistants and IDEs that support the Model Context Protocol (MCP).
Requirements
- Node.js >= v18.0.0
- An MCP-compatible client (Claude Code, Cursor, VS Code, Windsurf, etc.)
Install in Claude Code
Run this command:
claude mcp add puppeteer-swarm -- npx -y puppeteer-swarm-mcp --tabs=5 --headless
Or with custom options:
claude mcp add puppeteer-swarm -- npx -y puppeteer-swarm-mcp --tabs=10
Install in Cursor
Go to: Settings -> Cursor Settings -> MCP -> Add new global MCP server
Add the following configuration to your ~/.cursor/mcp.json file:
{
"mcpServers": {
"puppeteer-swarm": {
"command": "npx",
"args": ["-y", "puppeteer-swarm-mcp", "--tabs=5", "--headless"]
}
}
}
Install in Claude Desktop
Add the following to your Claude Desktop configuration file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"puppeteer-swarm": {
"command": "npx",
"args": ["-y", "puppeteer-swarm-mcp", "--tabs=5", "--headless"]
}
}
}
Install in VS Code
Add this to your VS Code MCP config file. See VS Code MCP docs for more info.
"mcp": {
"servers": {
"puppeteer-swarm": {
"type": "stdio",
"command": "npx",
"args": ["-y", "puppeteer-swarm-mcp", "--tabs=5", "--headless"]
}
}
}
Install in Windsurf
Add this to your Windsurf MCP config file:
{
"mcpServers": {
"puppeteer-swarm": {
"command": "npx",
"args": ["-y", "puppeteer-swarm-mcp", "--tabs=5", "--headless"]
}
}
}
Install in Cline
- Open Cline
- Click the hamburger menu icon (☰) to enter the MCP Servers section
- Choose Remote Servers tab
- Click the Edit Configuration button
- Add puppeteer-swarm to
mcpServers:
{
"mcpServers": {
"puppeteer-swarm": {
"command": "npx",
"args": ["-y", "puppeteer-swarm-mcp", "--tabs=5", "--headless"]
}
}
}
Install in Zed
Add this to your Zed settings.json:
{
"context_servers": {
"puppeteer-swarm": {
"source": "custom",
"command": "npx",
"args": ["-y", "puppeteer-swarm-mcp", "--tabs=5", "--headless"]
}
}
}
Available Tools
launch
Initialize the browser and tab pool. Must be called before using any other browser tools.
Parameters: None
Returns:
{
"message": "브라우저가 성공적으로 시작되었습니다.",
"config": {
"tabCount": 5,
"headless": false,
"idleTimeout": 300000
}
}
close
Close the browser and all tabs.
Parameters: None
Returns:
{
"message": "브라우저가 종료되었습니다."
}
get_pool_status
Get the current status of the tab pool. Can be called before launch to check initialization status.
Parameters: None
Returns (after launch):
{
"initialized": true,
"total": 5,
"idle": 3,
"busy": 2
}
Returns (before launch):
{
"initialized": false,
"message": "브라우저가 초기화되지 않았습니다. 먼저 'launch' 도구를 호출하세요."
}
navigate
Allocate an idle tab and navigate to a URL.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Yes | URL to navigate to |
waitUntil | string | No | Wait condition (load, domcontentloaded, networkidle0, networkidle2) |
Returns:
{
"tabId": "tab-1",
"url": "https://example.com",
"title": "Example Domain"
}
get_content
Extract HTML or text content from a page.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
tabId | string | Yes | Target tab ID |
type | string | No | Extract format (html, text). Default: text |
Returns:
{
"content": "..."
}
screenshot
Capture a page screenshot.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
tabId | string | Yes | Target tab ID |
fullPage | boolean | No | Capture full page. Default: false |
Returns: Image content (base64 PNG)
click
Click an element by CSS selector.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
tabId | string | Yes | Target tab ID |
selector | string | Yes | CSS selector |
Returns:
{
"success": true
}
type
Type text into an input field.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
tabId | string | Yes | Target tab ID |
selector | string | Yes | CSS selector |
text | string | Yes | Text to type |
Returns:
{
"success": true
}
evaluate
Execute JavaScript in the page context.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
tabId | string | Yes | Target tab ID |
script | string | Yes | JavaScript code to execute |
Returns:
{
"result": "..."
}
wait_for_selector
Wait for an element to appear in the DOM.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
tabId | string | Yes | Target tab ID |
selector | string | Yes | CSS selector |
timeout | number | No | Timeout in ms. Default: 30000 |
Returns:
{
"success": true
}
release_tab
Release a tab back to idle state.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
tabId | string | Yes | Tab ID to release |
Returns:
{
"success": true
}
Workflow Example
1. launch()
-> Initialize browser and tab pool
2. navigate({ url: "https://example.com" })
-> Returns { tabId: "tab-1", ... }
3. get_content({ tabId: "tab-1", type: "text" })
-> Returns page content
4. click({ tabId: "tab-1", selector: "button.submit" })
-> Click a button
5. release_tab({ tabId: "tab-1" })
-> Release the tab for reuse
6. close()
-> Close browser when done (optional)
Note: The browser does not start automatically. You must call
launchbefore using any browser tools.
Logging
Logs are stored in the logs/ directory:
- File Pattern:
mcp-puppeteer-YYYY-MM-DD.log - Daily rotation, max 20MB per file
- 14 days retention with auto-compression
License
MIT License - see the LICENSE file for details.
Author
Choi Sumin - GitHub
