| name | browser-mcp-control |
| description | Control Chrome browser tabs via MCP for AI-assisted web automation using the Browser MCP server and extension |
| triggers | ["navigate to a website using browser mcp","take a screenshot of the current page","click an element in the browser","get page content snapshot","interact with browser extension","automate browser actions through mcp","fill out web form using browser","extract data from web page"] |
Browser MCP Control
Skill by ara.so — MCP Skills collection.
What Browser MCP Does
Browser MCP is a Model Context Protocol server that bridges AI assistants to your local Chrome browser through a Chrome extension. Unlike headless automation tools, it operates on your existing browser profile, preserving login sessions and cookies, reducing CAPTCHA triggers and bot detection.
The architecture uses:
- MCP Server (stdio) that AI clients spawn as subprocess
- WebSocket bridge (port 9009) for extension communication
- Chrome Extension that executes commands in active tabs
- Optional Redis for session persistence
Installation
1. Install the MCP Server
git clone https://github.com/BrowserMCP/mcp.git
cd mcp
npm install
npm run build
2. Configure Your MCP Client
Add to your MCP settings (Cursor, Claude Desktop, VS Code, etc.):
Cursor/Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"browsermcp": {
"command": "node",
"args": ["/absolute/path/to/mcp/dist/index.js"]
}
}
}
VS Code (.vscode/settings.json):
{
"mcp.servers": {
"browsermcp": {
"command": "node",
"args": ["/absolute/path/to/mcp/dist/index.js"]
}
}
}
3. Install Chrome Extension
Install the Browser MCP extension from browsermcp.io or the Chrome Web Store.
4. Connect Extension
- Restart your AI client to spawn the MCP server
- Open Chrome and click the Browser MCP extension icon
- Click Connect on the active tab
- Extension connects via WebSocket to localhost:9009
Configuration
Create .env in the project root:
WS_PORT=9009
LOG_LEVEL=info
REDIS_ENABLED=false
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0
REDIS_KEY_PREFIX=browsermcp:
REDIS_SESSION_TTL_SECONDS=86400
Core Tools
Navigation Tools
browser_navigate
Navigate to a URL:
{
"tool": "browser_navigate",
"arguments": {
"url": "https://github.com/trending",
"waitUntil": "networkidle"
}
}
Parameters:
url (required): Target URL
waitUntil (optional): load, domcontentloaded, networkidle
browser_go_back / browser_go_forward
{
"tool": "browser_go_back"
}
{
"tool": "browser_go_forward"
}
browser_wait
Wait for page state or timeout:
{
"tool": "browser_wait",
"arguments": {
"seconds": 3
}
}
Interaction Tools
browser_click
Click an element by selector or coordinates:
{
"tool": "browser_click",
"arguments": {
"selector": "button.submit-btn"
}
}
{
"tool": "browser_click",
"arguments": {
"x": 250,
"y": 400
}
}
Parameters:
selector (optional): CSS selector
x, y (optional): Pixel coordinates
button (optional): left, right, middle
clickCount (optional): Single/double/triple click
browser_type
Type text into an input:
{
"tool": "browser_type",
"arguments": {
"selector": "input[name='email']",
"text": "user@example.com",
"pressEnter": false
}
}
Parameters:
selector (required): CSS selector for input
text (required): Text to type
pressEnter (optional): Submit after typing
browser_select_option
Select dropdown option:
{
"tool": "browser_select_option",
"arguments": {
"selector": "select#country",
"value": "USA"
}
}
browser_hover
Hover over element:
{
"tool": "browser_hover",
"arguments": {
"selector": ".tooltip-trigger"
}
}
browser_press_key
Press keyboard keys:
{
"tool": "browser_press_key",
"arguments": {
"key": "Enter"
}
}
Common keys: Enter, Escape, Tab, Backspace, ArrowDown, ArrowUp
Inspection Tools
browser_snapshot
Get ARIA accessibility tree as YAML:
{
"tool": "browser_snapshot"
}
Returns structured page content for AI analysis:
- role: navigation
name: Main navigation
- role: link
name: Home
- role: link
name: About
- role: main
- role: heading
name: Welcome
level: 1
- role: article
- role: heading
name: Getting Started
level: 2
browser_screenshot
Capture page screenshot:
{
"tool": "browser_screenshot",
"arguments": {
"quality": 90,
"fullPage": false
}
}
Parameters:
quality (optional): JPEG quality 0-100
fullPage (optional): Capture entire scrollable page
Returns base64-encoded image.
browser_get_console_logs
Retrieve browser console messages:
{
"tool": "browser_get_console_logs"
}
Returns array of log entries with type, message, timestamp.
Common Patterns
Login Flow
await useTool("browser_navigate", {
url: "https://app.example.com/login"
});
await useTool("browser_type", {
selector: "input[name='username']",
text: process.env.USERNAME
});
await useTool("browser_type", {
selector: "input[name='password']",
text: process.env.PASSWORD
});
await useTool("browser_click", {
selector: "button[type='submit']"
});
await useTool("browser_wait", {
seconds: 2
});
Form Automation
await useTool("browser_navigate", {
url: "https://example.com/contact"
});
await useTool("browser_type", {
selector: "#name",
text: "John Doe"
});
await useTool("browser_type", {
selector: "#email",
text: "john@example.com"
});
await useTool("browser_select_option", {
selector: "#topic",
value: "sales"
});
await useTool("browser_type", {
selector: "textarea#message",
text: "I'd like to discuss..."
});
await useTool("browser_click", {
selector: "button.submit"
});
Data Extraction
await useTool("browser_navigate", {
url: "https://news.ycombinator.com"
});
const snapshot = await useTool("browser_snapshot");
const screenshot = await useTool("browser_screenshot", {
fullPage: true
});
Multi-Step Workflow
await useTool("browser_navigate", {
url: "https://github.com/search"
});
await useTool("browser_type", {
selector: "input[name='q']",
text: "mcp server",
pressEnter: true
});
await useTool("browser_wait", { seconds: 2 });
await useTool("browser_click", {
selector: "button[data-filter='repositories']"
});
await useTool("browser_wait", { seconds: 1 });
const content = await useTool("browser_snapshot");
await useTool("browser_click", {
selector: ".repo-list-item:first-child a"
});
const repoSnapshot = await useTool("browser_snapshot");
Error Handling
Connection Errors
try {
await useTool("browser_navigate", {
url: "https://example.com"
});
} catch (error) {
if (error.message.includes("No connection")) {
console.error("Chrome extension not connected. Open extension popup and click Connect.");
}
}
Timeout Handling
await useTool("browser_navigate", {
url: "https://slow-site.com",
waitUntil: "networkidle"
});
await useTool("browser_wait", {
seconds: 5
});
Element Not Found
await useTool("browser_wait", { seconds: 2 });
await useTool("browser_click", {
selector: ".dynamic-content button"
});
const snapshot = await useTool("browser_snapshot");
Development & Testing
Run in Development Mode
npm run dev
Type Checking
npm run typecheck
Run Tests
npm test
npm run test:watch
Use MCP Inspector
Debug tools interactively:
npm run build
npm run inspector
Enable Debug Logging
LOG_LEVEL=debug node dist/index.js
Troubleshooting
Extension Not Connecting
Symptom: Tools fail with "No connection to browser extension"
Solutions:
- Click Browser MCP extension icon in Chrome
- Click Connect on the active tab
- Verify WebSocket port 9009 is not blocked
- Check extension is enabled in
chrome://extensions
Port Already in Use
Symptom: Error: listen EADDRINUSE: address already in use :::9009
Solutions:
lsof -i :9009
kill -9 <PID>
WS_PORT=9010 node dist/index.js
Update MCP config with new port.
Tools Timeout
Symptom: Operations timeout after 30 seconds
Solutions:
- Ensure browser tab is active and visible
- Check network connection for slow pages
- Use
browser_wait before interactions
- Verify extension is connected (green indicator)
No Tools Available
Symptom: AI client doesn't show browser tools
Solutions:
- Verify absolute path in MCP config
- Restart AI client after config changes
- Check
npm run build completed successfully
- Confirm Node.js 18+ installed
Redis Connection Failures
Symptom: Redis errors in logs (when enabled)
Solutions:
redis-cli ping
REDIS_ENABLED=false
Server continues without persistence if Redis unavailable.
Architecture Notes
- Stdio Transport: Server communicates with AI client via stdin/stdout
- Stderr Logging: All diagnostics go to stderr to preserve MCP protocol
- Single Connection: Only one extension WebSocket connection active at a time
- Session Preservation: Uses existing Chrome profile, maintaining cookies and login state
- Type Safety: End-to-end TypeScript with Zod schema validation
Security Considerations
- Server runs locally on localhost only
- No data sent to remote servers
- Extension requires explicit user connection per tab
- Use environment variables for credentials, never hardcode
- Redis passwords should be set if exposing port
Use Cases
- Web Scraping: Extract data while authenticated
- Form Automation: Fill multi-page forms
- Testing: Verify UI workflows with real browser
- Research: Navigate sites requiring JavaScript
- Data Collection: Gather information from protected content
- Monitoring: Check site status and capture evidence