Skip to main content
Glama
README.md
# MCP Chromium ARM64 Server

<p align="center">
  <img src="https://img.shields.io/badge/MCP%20Protocol-1.0%20Compatible-blue?style=for-the-badge" alt="MCP Compatible">
  <img src="https://img.shields.io/badge/Platform-ARM64%20Cross--Platform-green?style=for-the-badge" alt="Platform Support">
  <img src="https://img.shields.io/badge/Chrome%20DevTools%20Protocol-Native-red?style=for-the-badge" alt="CDP">
  <img src="https://img.shields.io/badge/Version-1.4.0%20Direct%20CDP-purple?style=for-the-badge" alt="Version">
</p>

<p align="center">
  <strong>Cross-platform ARM64 browser automation via Chrome DevTools Protocol</strong><br>
  <em>Native Chromium control with 27 MCP tools for Linux, macOS, and Windows ARM64</em>
</p>

## ๐Ÿš€ Two Implementation Approaches Available

### ๐Ÿ“ฆ Version Comparison

| Feature | **Direct CDP (v1.4.0)** โญ **RECOMMENDED** | **Puppeteer-based (v1.2.0)** |
|---------|---------------------------------------------|------------------------------|
| **Dependencies** | Only `ws` + MCP SDK (89 packages) | Puppeteer + MCP SDK (163 packages) |
| **Memory Usage** | Lower (native chromium) | Higher (Node.js wrapper overhead) |
| **Startup Time** | Faster (direct WebSocket) | Slower (puppeteer initialization) |
| **Browser Control** | Native Chrome DevTools Protocol | Puppeteer abstraction layer |
| **ARM64 Optimization** | Full native ARM64 | Depends on Puppeteer ARM64 support |
| **Debugging** | Raw CDP messages visible | Abstracted by Puppeteer |
| **Maintenance** | Chrome protocol changes only | Puppeteer + Chrome protocol changes |
| **Performance** | Best (direct communication) | Good (wrapped communication) |

### ๐ŸŽฏ When to Use Which Version

**Use Direct CDP (v1.4.0) if:**
- โœ… You want maximum performance and minimum dependencies
- โœ… You need native ARM64 optimization
- โœ… You want direct Chrome DevTools Protocol control
- โœ… You're building production automation systems
- โœ… You want the latest features and fastest updates

**Use Puppeteer-based (v1.2.0) if:**
- โœ… You're migrating from existing Puppeteer code
- โœ… You prefer the Puppeteer API abstraction
- โœ… You need specific Puppeteer features not yet implemented in direct CDP
- โœ… You want to minimize changes to existing workflows

### ๐Ÿ”„ Switching Between Versions

```bash
# Switch to Direct CDP (recommended)
git checkout direct-chromium
npm install  # Only 89 packages

# Switch back to Puppeteer version
git checkout main  
npm install  # 163 packages
```

---

## ๐Ÿ“š Documentation & Specialized Guides

This repository includes multiple documentation approaches for different audiences:

### ๐ŸŽฏ **For Developers & DevOps Engineers**
**[๐Ÿ“– TECHNICAL README](README-TECHNICAL.md)** - Comprehensive technical documentation including:
- Architecture diagrams and API reference
- Performance benchmarks and optimization guides
- CI/CD integration examples and E2E testing workflows
- Advanced debugging and customization options

### ๐Ÿ“ **For Makers & Entrepreneurs** 
**[๐Ÿ“– RASPBERRY PI README](README-RASPBERRY-PI.md)** - Budget-focused guide featuring:
- Complete $480 AI development setup
- No-code SaaS development workflows
- Real-world startup use cases and ROI analysis
- Global accessibility and maker movement focus

### โšก **Quick Links**
- **Developers**: Jump to [Technical Documentation โ†’](README-TECHNICAL.md)
- **Makers**: Jump to [Raspberry Pi Guide โ†’](README-RASPBERRY-PI.md)
- **Everyone**: Continue reading for universal setup and usage

---

## โœจ Core Features

**๐Ÿค– Native ARM64 Browser Automation** 
- Direct Chrome DevTools Protocol implementation
- 27 comprehensive MCP tools for complete browser control
- Optimized for Raspberry Pi and Apple Silicon architectures
- No dependency on broken x86_64 Puppeteer binaries

**โšก High Performance Architecture**
- Only 2 dependencies (ws + MCP SDK) vs 163 packages in Puppeteer
- Lower memory usage and faster startup times
- Direct WebSocket communication with Chrome
- Comprehensive logging and audit capabilities

**๐Ÿ› ๏ธ Enterprise-Ready Development**
- Full debugging suite with console/network monitoring  
- Accessibility, SEO, and performance audits built-in
- CI/CD integration examples and E2E testing workflows
- Cross-platform compatibility (Linux ARM64, macOS Apple Silicon)

**๐Ÿ’ฐ Affordable Innovation Platform**
- Complete AI development setup for under $500
- Same capabilities as $50K+ enterprise workstations  
- Global accessibility for makers and startups worldwide
- No recurring cloud costs - own your infrastructure

---

## ๐Ÿš€ Universal Quick Start

### Prerequisites
```bash
# Install system dependencies
sudo apt update
sudo apt install chromium-browser nodejs npm python3

# Verify Chromium works
chromium-browser --version
```

### Installation
```bash
git clone https://github.com/nfodor/mcp-chromium-arm64
cd mcp-chromium-arm64
npm install
chmod +x *.py *.sh
```

### Quick Test (One-Liner)
```bash
# Verify it works immediately after install:
python3 -c "import sys; sys.path.append('.'); import arm64_browser; print('[OK] ARM64 Browser Works!' if 'error' not in arm64_browser.navigate('https://example.com').lower() else '[FAIL] Failed')"
```
**Expected Result:** `[OK] ARM64 Browser Works!`

### Test & Demo
```bash
# Quick demo with immediate visible results (30 seconds)
python3 instant_demo.py

# Or comprehensive demo showing all capabilities (2-3 minutes)
./run_demo.sh
```

### Test the Setup
```bash
# Test MCP server directly
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node index.js

# Test Python wrapper
python3 simple_browser.py
```

---

## ๐Ÿ› ๏ธ Developer Guide & Debugging

### ๐Ÿ”ง Available MCP Tools (29 total)

#### Core Browser Control
- `navigate` - Navigate to URLs with full page loading
- `screenshot` - Capture PNG screenshots (full page or viewport)
- `click` - Click elements by CSS selector with precise positioning
- `fill` - Fill input fields with text or values
- `hover` - Hover over elements for dropdown/tooltip interactions
- `select` - Select dropdown options by value
- `evaluate` - Execute JavaScript and return results
- `get_content` - Extract page HTML or plain text content

#### Advanced Functionality  
- `get_console_logs` - Retrieve browser console output
- `get_console_errors` - Get console error messages only
- `get_network_logs` - Monitor all network requests/responses
- `get_network_errors` - Track failed network requests (4xx/5xx)
- `wipe_logs` - Clear all stored logs from memory
- `get_selected_element` - Get info about currently focused element

#### Session & Authentication
- `set_cookies` - Import cookies (e.g. exported after logging in elsewhere) to authenticate without scripting the login form
- `get_cookies` - Export the current session's cookies as JSON (round-trips with `set_cookies`)

#### Mobile Device Emulation
- `emulate_device` - Emulate mobile devices with 17 presets or custom viewport/UA/DPR/touch, with landscape support
  - **iPhones**: `iphone-16`, `iphone-16-pro`, `iphone-16-pro-max`, `iphone-16e`, `iphone-15`, `iphone-15-pro-max`, `iphone-se`
  - **Pixels**: `pixel-9`, `pixel-9-pro`, `pixel-9-pro-xl`, `pixel-9-pro-fold`
  - **Samsung**: `galaxy-s24`, `galaxy-s24-ultra`, `galaxy-z-fold-5`
  - **Tablets**: `ipad-air-m2`, `ipad-pro-13`, `galaxy-tab-s9`
- `reset_emulation` - Reset device emulation back to desktop mode

#### Screencast Recording
- `start_screencast` - Start recording browser activity via CDP screencast (configurable format, quality, resolution, frame skip)
- `stop_screencast` - Stop recording and encode to **MP4**, **GIF**, or **WebM** via ffmpeg (auto-detects FPS from frame timestamps)
- `screencast_status` - Check recording status, frame count, and elapsed duration

#### Audit & Analysis Tools
- `run_accessibility_audit` - Check alt text, labels, headings, contrast
- `run_performance_audit` - Measure load times, memory usage, resources
- `run_seo_audit` - Validate title, meta description, H1 tags, canonical
- `run_best_practices_audit` - Check HTTPS, deprecated HTML, viewport
- `run_nextjs_audit` - Next.js specific optimization checks
- `run_debugger_mode` - Comprehensive debugging information
- `run_audit_mode` - Run all audits together with summary
- `close_browser` - Clean shutdown of chromium process

### ๐Ÿ” Authenticated Review (login-required sites)

To review pages behind a login (e.g. `x.com`) you don't have to script the login form, captcha, or 2FA. Log in once in your normal browser, export the cookies, inject them, then navigate.

1. **Log in** to the site in your regular browser.
2. **Export the cookies** with [Cookie-Editor](https://cookie-editor.com/) (Chrome / Firefox / Edge / Safari / Opera): open it on the logged-in tab โ†’ **Export โ†’ JSON**. An extension export is required for `httpOnly` cookies (e.g. x.com's `auth_token`), which `document.cookie` cannot read.
3. **Inject and review** via the MCP:

```bash
# 1) import the exported cookies (replace the [...] with the Cookie-Editor JSON array)
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"set_cookies","arguments":{"url":"https://x.com","cookies":[]}}}' | node index.js

# 2) navigate to the page you want โ€” now authenticated
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"navigate","arguments":{"url":"https://x.com/home"}}}' | node index.js
```

The session stays authenticated for the life of the browser process. Use `get_cookies` to export it back out for reuse.

**Alternative โ€” raw Cookie header.** Instead of the JSON array you can paste a raw `Cookie:` header string via `cookieHeader` (requires `url`, since a header carries no domain):

```bash
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"set_cookies","arguments":{"url":"https://x.com","cookieHeader":"auth_token=abc123; ct0=def456"}}}' | node index.js
```

**Persist across restarts.** By default the profile is ephemeral, so the session is lost when the browser process exits. Set `CHROMIUM_USER_DATA_DIR` to a writable path and cookies/logins survive restarts โ€” log in (or inject cookies) once and reuse:

```bash
export CHROMIUM_USER_DATA_DIR="$HOME/.mcp-chromium-arm64/profile"
```

> **Format:** `set_cookies` accepts the [Cookie-Editor](https://cookie-editor.com/) / EditThisCookie JSON export directly โ€” it normalizes `sameSite` (`no_restriction` โ†’ `None`), accepts `expirationDate`, and honors session cookies. Pass a top-level `url` for any cookie that omits a domain, or use `cookieHeader` for a raw header string. `cookies[]` and `cookieHeader` can be combined.
>
> **Security:** cookies are session secrets and pass through as tool arguments, so they appear in logs/transcripts. Treat an exported `auth_token` like a password โ€” log out / rotate when done. A persistent `CHROMIUM_USER_DATA_DIR` stores the live session on disk, so protect that directory too.

### ๐Ÿ› Debugging & Development

#### Direct MCP Testing
```bash
# Test individual tools directly
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"navigate","arguments":{"url":"https://example.com"}}}' | node index.js

echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"evaluate","arguments":{"script":"document.title"}}}' | node index.js

echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"screenshot","arguments":{"name":"debug.png"}}}' | node index.js
```

#### Screencast Recording
```bash
# Start recording, interact with the page, then stop and encode
# 1. Start screencast
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"start_screencast","arguments":{"format":"jpeg","quality":80,"maxWidth":1280,"maxHeight":720}}}' | node index.js

# 2. Perform actions (navigate, click, fill, etc.)
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"navigate","arguments":{"url":"https://example.com"}}}' | node index.js

# 3. Check recording progress
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"screencast_status","arguments":{}}}' | node index.js

# 4. Stop and encode to MP4
echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"stop_screencast","arguments":{"output":"mp4","name":"my-demo"}}}' | node index.js
# Output: /tmp/my-demo.mp4

# Encode as GIF instead (2-pass palette for quality)
echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"stop_screencast","arguments":{"output":"gif","name":"bug-repro"}}}' | node index.js
# Output: /tmp/bug-repro.gif

# Or WebM (VP9)
echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"stop_screencast","arguments":{"output":"webm"}}}' | node index.js
```

> **Requires**: `ffmpeg` installed on the system. FPS is auto-detected from CDP frame timestamps. GIF output is capped at 15fps for reasonable file sizes.

#### Mobile Device Emulation
```bash
# Emulate iPhone 16 Pro
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"emulate_device","arguments":{"device":"iphone-16-pro"}}}' | node index.js

# Emulate in landscape mode
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"emulate_device","arguments":{"device":"ipad-pro-13","landscape":true}}}' | node index.js

# Custom viewport with DPR
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"emulate_device","arguments":{"width":390,"height":844,"deviceScaleFactor":3,"mobile":true}}}' | node index.js

# Reset back to desktop
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"reset_emulation","arguments":{}}}' | node index.js
```

#### Network & Console Monitoring
```bash
# Navigate to a page, then check console logs
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_console_logs","arguments":{}}}' | node index.js

# Get only errors
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_console_errors","arguments":{}}}' | node index.js

# Check network activity (all requests with status codes)
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_network_logs","arguments":{}}}' | node index.js

# Check for failed requests (4xx/5xx)
echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"get_network_errors","arguments":{}}}' | node index.js

# Clear all logs when done
echo '{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"wipe_logs","arguments":{}}}' | node index.js
```

#### Audits
```bash
# Run all audits at once (accessibility + performance + SEO + best practices + Next.js)
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"run_audit_mode","arguments":{}}}' | node index.js

# Or run individual audits
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"run_accessibility_audit","arguments":{}}}' | node index.js
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"run_performance_audit","arguments":{}}}' | node index.js
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"run_seo_audit","arguments":{}}}' | node index.js

# Get full debug info (URL, viewport, memory, timing)
echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"run_debugger_mode","arguments":{}}}' | node index.js
```

#### Element Inspection
```bash
# Get info about the currently focused element
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_selected_element","arguments":{}}}' | node index.js
# Returns: tagName, id, className, textContent, value, and a CSS selector
```

#### Chrome DevTools Protocol Debugging
```bash
# Manual CDP connection test
node -e "
const { WebSocket } = require('ws');
const { spawn } = require('child_process');

const chrome = spawn('/usr/bin/chromium-browser', [
  '--headless', '--remote-debugging-port=9227'
]);

setTimeout(() => {
  fetch('http://localhost:9227/json')
    .then(r => r.json())
    .then(tabs => {
      console.log('Available tabs:', tabs.length);
      const ws = new WebSocket(tabs[0].webSocketDebuggerUrl);
      ws.on('open', () => {
        console.log('CDP WebSocket connected!');
        ws.send(JSON.stringify({id: 1, method: 'Runtime.evaluate', params: {expression: '2+2'}}));
      });
      ws.on('message', (data) => {
        console.log('CDP Response:', JSON.parse(data));
        chrome.kill();
        process.exit(0);
      });
    });
}, 2000);
"
```

#### Performance Monitoring
```bash
# Monitor system resources during operation
htop &
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"navigate","arguments":{"url":"https://httpbin.org/delay/5"}}}' | time node index.js

# Check memory usage
ps aux | grep chromium
free -h
```

#### Network Debugging
```bash
# Check if debugging port is accessible
curl -s http://localhost:9222/json | jq '.[] | {id, title, type}'

# Monitor WebSocket traffic (install websocat)
websocat ws://localhost:9222/devtools/page/[TAB_ID] --text -v
```

### ๐Ÿ” Common Debugging Scenarios

#### 1. WebSocket Connection Issues
```bash
# Symptoms: "CDP command timeout" errors
# Check if chrome debugging port is running
lsof -i :9222

# Test manual connection
node -e "
const { WebSocket } = require('ws');
const ws = new WebSocket('ws://localhost:9222/devtools/browser');
ws.on('open', () => console.log('โœ“ WebSocket OK'));
ws.on('error', (e) => console.log('โœ— WebSocket Error:', e.message));
setTimeout(() => process.exit(0), 2000);
"
```

#### 2. Chrome Process Issues  
```bash
# Symptoms: Browser won't start or hangs
# Kill any stuck processes
pkill -f chromium-browser
pkill -f remote-debugging-port

# Test chrome startup manually
timeout 10s /usr/bin/chromium-browser --headless --remote-debugging-port=9223 --no-sandbox

# Check chrome logs
journalctl --user -u chromium --since "1 hour ago"
```

#### 3. Element Selection Problems
```bash
# Debug CSS selectors interactively
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"evaluate","arguments":{"script":"document.querySelectorAll(\"button\").length"}}}' | node index.js

# Get element information
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"evaluate","arguments":{"script":"document.querySelector(\"#mybutton\") ? \"found\" : \"not found\""}}}' | node index.js
```

#### 4. Memory and Performance Issues
```bash
# Monitor memory during operation
watch -n 1 'ps aux | grep -E "(chromium|node)" | grep -v grep'

# Chrome memory debugging
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"evaluate","arguments":{"script":"JSON.stringify(performance.memory)"}}}' | node index.js
```

### ๐ŸŽฏ Advanced Debugging Features

#### Enable Verbose Logging
```bash
# Set environment variables for detailed output
export DEBUG=puppeteer:*
export NODE_ENV=development

# Run with detailed Chrome logs
/usr/bin/chromium-browser --headless --enable-logging --log-level=0 --remote-debugging-port=9222
```

#### CDP Message Tracing
```bash
# Create debug version with message logging
cp index.js debug-index.js

# Add to sendCDPCommand method:
# console.log('โ†’ CDP:', JSON.stringify(command));
# console.log('โ† CDP:', JSON.stringify(response));

node debug-index.js
```

#### Integration with Browser DevTools
```bash
# Connect regular Chrome DevTools to the headless instance
# 1. Start the MCP server
# 2. Open regular Chrome/Chromium
# 3. Navigate to: chrome://inspect
# 4. Click "Configure..." and add localhost:9222
# 5. Click "inspect" on the page you want to debug
```

### ๐Ÿ“Š Performance Benchmarks

#### Startup Time Comparison
```bash
# Direct CDP (v1.3.0)
time echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"evaluate","arguments":{"script":"Date.now()"}}}' | node index.js

# Puppeteer version (v1.2.0)  
git checkout main
time echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"evaluate","arguments":{"script":"Date.now()"}}}' | node index.js
```

#### Memory Usage Monitoring
```bash
# Before operation
free -h && ps aux | grep -E "(chromium|node)" | grep -v grep

# During operation (run in another terminal)
watch -n 1 'echo "=== $(date) ===" && free -h && echo && ps aux | grep -E "(chromium|node)" | grep -v grep'
```

### ๐Ÿšจ Error Codes & Solutions

| Error | Cause | Solution |
|-------|-------|----------|
| `CDP command timeout` | WebSocket connection lost | Restart browser, check port availability |
| `WebSocket not ready` | Chrome not fully started | Increase startup delay, check chrome process |
| `Element not found` | CSS selector invalid | Verify selector with `evaluate` tool |
| `ECONNREFUSED` | Debugging port blocked | Check firewall, kill existing chrome processes |
| `Navigation timeout` | Page loading issues | Check network, increase timeout, try simpler page |

### ๐Ÿ”ง Customization & Extension

#### Adding New MCP Tools
```javascript
// In index.js, add to tools array:
{
  name: 'my_custom_tool',
  description: 'My custom functionality',
  inputSchema: {
    type: 'object',
    properties: {
      param: { type: 'string', description: 'Parameter description' }
    },
    required: ['param']
  }
}

// Add to switch statement in CallToolRequestSchema handler:
case 'my_custom_tool':
  return await this.myCustomTool(args.param);

// Implement the method:
async myCustomTool(param) {
  await this.ensureChromium();
  const result = await this.sendCDPCommand('Page.navigate', { url: param });
  return { content: [{ type: 'text', text: `Custom result: ${result}` }] };
}
```

#### Environment Variables
```bash
# Set browser window size (default: 1280,720)
export CHROMIUM_WINDOW_SIZE=1920,1080

# Cap full-page screenshot height in px (default: 32768)
export CHROMIUM_MAX_SCREENSHOT_HEIGHT=32768

# Persistent profile: keep cookies / logins across restarts (default: ephemeral when unset)
export CHROMIUM_USER_DATA_DIR="$HOME/.mcp-chromium-arm64/profile"

# Use a specific Chromium-family binary (Chrome, Edge, Brave, Opera, Vivaldi, Chromium).
# Overrides auto-detection; point it at any Chromium-based browser.
export CHROMIUM_PATH="/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"

# Launch a visible (headful) window instead of headless โ€” e.g. to log into a site
# by hand once into a persistent profile (default: headless when unset)
export CHROMIUM_HEADLESS=false

# Cap Chrome's on-disk HTTP cache in bytes (default: 104857600 = 100MB).
# Bounds profile/cache growth, especially with a persistent CHROMIUM_USER_DATA_DIR.
export CHROMIUM_DISK_CACHE_SIZE=104857600
```

**Disk hygiene:** in the default (ephemeral) mode the server launches Chrome with its **own temp profile dir and deletes it on close** โ€” and sweeps any leftovers from crashed/killed prior runs on startup โ€” so it can't accumulate orphaned profile/cache directories. The disk cache is capped (`CHROMIUM_DISK_CACHE_SIZE`) in both ephemeral and persistent modes. A persistent `CHROMIUM_USER_DATA_DIR` is intentionally kept (that's the point of it), so it's the one path you manage yourself.

**Browser support:** auto-detects any Chromium-family browser โ€” Chrome, Chromium, Microsoft Edge, Brave, Opera, Vivaldi (Firefox/Safari are not supported; the server speaks Chrome DevTools Protocol). Set `CHROMIUM_PATH` to force a specific binary.

**Headful login (no cookie-export extension needed):** set `CHROMIUM_USER_DATA_DIR` + `CHROMIUM_HEADLESS=false`, log into a site (X, LinkedIn, โ€ฆ) by hand once in the visible window, then drop `CHROMIUM_HEADLESS` โ€” the persistent profile keeps you logged in for subsequent headless runs. This also beats headless bot-detection since you sign in as a normal user.

#### Chrome Launch Options
```javascript
// Modify in startChromium() method:
const customArgs = [
  '--headless',
  '--no-sandbox',
  '--disable-extensions',
  '--disable-plugins',
  '--disable-background-timer-throttling',
  '--disable-backgrounding-occluded-windows',
  '--disable-renderer-backgrounding',
  '--remote-debugging-port=9222',
  '--window-size=1920,1080',        // Custom viewport
  '--user-agent=CustomUA/1.0',      // Custom user agent
  '--disable-web-security',         // For CORS testing
  '--allow-running-insecure-content' // For mixed content
];
```

---

## ๐ŸŒ Cross-Platform ARM64 Compatibility

### **Platform Support Matrix**

| Platform | Status | Chrome Path | Installation Method | Notes |
|----------|--------|-------------|---------------------|--------|
| **Linux ARM64** โœ… | **Fully Supported** | `/usr/bin/chromium-browser` | `apt install chromium-browser` | Tested on Raspberry Pi OS |
| **macOS Apple Silicon** โš ๏ธ | **Requires Modifications** | `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome` | Download from Google or `brew install chromium` | Need path and flag updates |
| **Windows ARM64** โ“ | **Untested** | `C:\Program Files\Google\Chrome\Application\chrome.exe` | Download from Google | Would need Windows-specific changes |

### **macOS Apple Silicon Setup**

#### **Prerequisites**
```bash
# Install Homebrew if not already installed
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install Node.js and Chromium
brew install node chromium --no-quarantine
```

#### **Required Code Changes**
Currently, the server is optimized for Linux ARM64. For macOS compatibility, modify `index.js`:

```javascript
// Detect platform and set appropriate chrome path
function getChromePath() {
  const platform = process.platform;
  
  switch(platform) {
    case 'linux':
      return '/usr/bin/chromium-browser';
    case 'darwin': // macOS
      // Try multiple possible paths
      const macPaths = [
        '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
        '/Applications/Chromium.app/Contents/MacOS/Chromium',
        '/opt/homebrew/bin/chromium'
      ];
      
      for (const path of macPaths) {
        if (require('fs').existsSync(path)) {
          return path;
        }
      }
      throw new Error('Chrome/Chromium not found on macOS');
    case 'win32':
      return 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe';
    default:
      throw new Error(`Unsupported platform: ${platform}`);
  }
}

// Update startChromium method
async startChromium() {
  const chromePath = getChromePath();
  const platform = process.platform;
  
  // Platform-specific arguments
  const baseArgs = [
    '--headless',
    '--disable-extensions',
    '--disable-plugins',
    `--remote-debugging-port=${debuggingPort}`,
    '--no-first-run',
    '--disable-gpu',
    '--window-size=1280,720'
  ];
  
  // Add Linux-specific sandbox flags
  if (platform === 'linux') {
    baseArgs.push('--no-sandbox', '--disable-setuid-sandbox');
  }
  
  // Add macOS-specific flags if needed
  if (platform === 'darwin') {
    baseArgs.push('--disable-dev-shm-usage');
  }
  
  chromiumProcess = spawn(chromePath, baseArgs);
  // ... rest of method
}
```

### **macOS-Specific Issues & Solutions**

#### **1. "Chromium is damaged" Error**
```bash
# Remove quarantine flag if downloading manually
sudo xattr -r -d com.apple.quarantine /Applications/Chromium.app

# Or install via Homebrew with no-quarantine flag
brew install chromium --no-quarantine
```

#### **2. Chrome vs Chromium Choice**
```bash
# Option 1: Use Google Chrome (recommended)
# Download from: https://www.google.com/chrome/
# Path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

# Option 2: Use Chromium via Homebrew
brew install chromium --no-quarantine
# Path: /opt/homebrew/bin/chromium
```

#### **3. Permission Issues**
```bash
# Ensure Chrome has required permissions
# System Preferences > Security & Privacy > Privacy tab
# Grant Camera, Microphone access if needed for specific use cases
```

### **Testing Cross-Platform Compatibility**

#### **Quick Platform Detection Test**
```bash
node -e "
console.log('Platform:', process.platform);
console.log('Architecture:', process.arch);
const fs = require('fs');

const paths = {
  linux: '/usr/bin/chromium-browser',
  darwin: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
  win32: 'C:\\\\Program Files\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe'
};

const chromePath = paths[process.platform];
console.log('Expected Chrome path:', chromePath);
console.log('Chrome exists:', fs.existsSync(chromePath));
"
```

#### **Cross-Platform MCP Test**
```bash
# Test basic functionality across platforms
echo '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"evaluate\",\"arguments\":{\"script\":\"navigator.platform\"}}}' | node index.js

# Should return the current platform
```

### **Windows ARM64 Considerations** 
While untested, Windows ARM64 support would need:

```javascript
// Windows-specific chrome path detection
case 'win32':
  const winPaths = [
    'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
    'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
    process.env.LOCALAPPDATA + '\\Google\\Chrome\\Application\\chrome.exe'
  ];
  // Similar path checking logic...
```

### **Performance Differences**

| Platform | Startup Time | Memory Usage | Notes |
|----------|--------------|--------------|--------|
| **Linux ARM64 (Pi 4)** | ~3-4s | ~150MB | Optimized, well-tested |
| **macOS Apple Silicon** | ~2-3s | ~200MB | Faster CPU, more memory |
| **Windows ARM64** | Unknown | Unknown | Would depend on hardware |

### **Contribution Needed**

**We welcome contributions for full cross-platform support!**

- **macOS testers**: Test the proposed changes on Apple Silicon
- **Windows ARM64**: Test on Surface Pro X or similar devices  
- **Performance optimization**: Platform-specific optimizations
- **Installation scripts**: Automated setup for each platform

---

##  Claude CLI Integration

### Prerequisites
```bash
# Install Claude Code CLI if you haven't already
npm install -g @anthropic-ai/claude-code
```

### Add to Claude CLI
```bash
# From the project directory after cloning
claude mcp add chromium-arm64 "$(pwd)/mcp-wrapper.sh" --scope user
```

### Verify Connection
```bash
claude mcp list
# Should show: chromium-arm64: /path/to/mcp-wrapper.sh - โœ“ Connected
```

### โš ๏ธ Important: Restart Claude After Adding
**You MUST start a new Claude session after adding the MCP server:**
```bash
# Exit current session if in one
exit
# Start fresh session
claude
```

### Using in Claude CLI

**Ask Claude to use the chromium-arm64 tools:**
```
List available MCP servers and use chromium-arm64 to navigate to https://example.com

Take a screenshot using the chromium-arm64 tool

Use chromium-arm64 to click the button with selector #submit

Fill the email field using chromium-arm64 with test@example.com

Record a screencast of the login flow and save it as a GIF

Emulate an iPhone 16 Pro and take a screenshot of the homepage

Run a full audit on https://example.com using chromium-arm64
```

**Be explicit to avoid Playwright/Puppeteer:**
-  "Use chromium-arm64 to navigate..."
-  "Using the chromium-arm64 tool, take a screenshot"
-  "Open a browser" (might try broken Playwright)
-  "Take a screenshot" (might try broken Puppeteer)

###  Success Example

When working correctly, you'll see:
```
You: Use chromium-arm64 to navigate to https://httpbin.org/json and show me what you see

Claude: I'll navigate to https://httpbin.org/json using the chromium-arm64 tool.

[Uses chromium-arm64.navigate tool]

The page displays a JSON object with a slideshow structure containing:
- Author: "Yours Truly"
- Date: "date of publication"
- Title: "Sample Slide Show"
...
```

##  Usage Examples

### Python API
```python
import simple_browser

# Navigate to any website
result = simple_browser.browser_navigate("https://example.com")
print(result)  # "Successfully navigated to https://example.com"

# Take a screenshot
screenshot = simple_browser.browser_screenshot("homepage.png")
print(screenshot)  # "Screenshot saved to /tmp/homepage.png"

# Execute JavaScript
title = simple_browser.browser_evaluate("document.title")
print(title)  # Website title

# Extract page content
content = simple_browser.browser_get_content("text")
print(content[:100])  # First 100 chars of page text
```

### MCP Tools (via Claude Code)
Once configured, use these tools directly in Claude Code:
- `navigate` - Go to URLs
- `screenshot` - Capture page images
- `click` / `fill` / `hover` / `select` - Interact with page elements
- `evaluate` - Execute JavaScript
- `get_content` - Extract page HTML/text
- `emulate_device` / `reset_emulation` - Mobile device emulation with 17 presets
- `start_screencast` / `stop_screencast` - Record browser activity to MP4/GIF/WebM
- `get_console_logs` / `get_network_logs` - Monitor console and network
- `run_audit_mode` - Run all audits (a11y, performance, SEO, best practices)
- `close_browser` - Clean shutdown

## ๐ŸŽฏ Key Use Cases

### ๐Ÿงช **For Testing & QA Teams**
- End-to-end SaaS testing with autonomous AI agents
- Visual regression detection and cross-device compatibility
- 24/7 continuous validation on budget hardware

### ๐Ÿš€ **For Startups & Makers** 
- Complete $480 AI development setup (see [Raspberry Pi Guide](README-RASPBERRY-PI.md))
- No-code SaaS development with AI-powered testing
- Competitive analysis and market research automation

### ๐Ÿ› ๏ธ **For DevOps & Developers**
- CI/CD integration with comprehensive audit tools
- Performance benchmarking and accessibility testing
- Advanced debugging with console/network monitoring

*๐Ÿ“– Full examples and detailed guides available in the [specialized documentation](#-documentation--specialized-guides).*

---

## ๐Ÿ—๏ธ Architecture

```mermaid
graph TB
    A[Claude Code] --> B[MCP Protocol]
    B --> C[ARM64 Browser Server]
    C --> D[System Chromium]
    D --> E[Web Pages]
    
    F[Python Tools] --> C
    G[Direct CLI] --> C
```

## ๐Ÿ”ง Troubleshooting & Advanced Usage

For detailed troubleshooting guides, debugging tools, and advanced configuration:

### ๐Ÿ“– Quick References
- **Common Issues**: See [Technical Documentation โ†’](README-TECHNICAL.md#-common-debugging-scenarios)  
- **Performance Tuning**: See [Technical Documentation โ†’](README-TECHNICAL.md#-performance-benchmarks)
- **Cross-Platform Setup**: See [Technical Documentation โ†’](README-TECHNICAL.md#-cross-platform-arm64-compatibility)
- **Complete Hardware Setup**: See [Raspberry Pi Guide โ†’](README-RASPBERRY-PI.md#-complete-startup-ai-setup---under-500)

### Quick Fixes
```bash
# Test MCP server directly
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node index.js

# Verify browser installation
chromium-browser --version

# Check Claude MCP integration
claude mcp list
```

---

## ๐Ÿค Contributing

We welcome contributions to democratize AI access for developers worldwide.

### Areas for Contribution:
- ๐Ÿ“ฑ Mobile browser support (Android/iOS testing)
- ๐Ÿ”ง Additional MCP tools and integrations  
- โšก Performance optimizations for smaller devices
- ๐Ÿ“š Tutorial content and use-case examples

### Development Setup:
```bash
git clone https://github.com/nfodor/mcp-chromium-arm64
cd mcp-chromium-arm64
npm install
# Ready to use - no development server needed!
```

---

## ๐Ÿ“œ License

MIT License - feel free to use in commercial projects!

---

## ๐Ÿ™ Acknowledgments

- **๐Ÿค– Anthropic** for Claude Code and MCP protocol
- **๐Ÿ“ Raspberry Pi Foundation** for democratizing computing
- **๐ŸŒ Chromium Project** for ARM64 browser support
- **๐Ÿ‘ฅ Open Source Community** for making this possible

---

## ๐Ÿ“ž Support & Community

- **๐Ÿ› Issues**: [GitHub Issues](https://github.com/nfodor/mcp-chromium-arm64/issues)
- **๐Ÿ’ฌ Discussions**: [GitHub Discussions](https://github.com/nfodor/mcp-chromium-arm64/discussions)  
- **๐Ÿ“ง Email**: github@fodor.app
- **๐Ÿ“ Repository**: [github.com/nfodor/mcp-chromium-arm64](https://github.com/nfodor/mcp-chromium-arm64)

---

<p align="center">
  <strong>โญ Star this repo if it helps democratize AI development!</strong><br>
  <em>Every star helps more developers discover accessible AI solutions</em>
</p>

---

<p align="center">
  <sub>Built with โค๏ธ for the global developer community</sub>
</p>

TDQS

B3.2/5.0

Scored across 22 tools

Disambiguation4/5

Most tools have distinct purposes, such as click, fill, navigate, and screenshot, with clear boundaries. However, some overlap exists between the various audit tools (e.g., run_accessibility_audit, run_best_practices_audit, run_performance_audit, run_seo_audit, run_nextjs_audit, run_audit_mode), which could cause confusion as their specific scopes might not be immediately clear from the names alone, though descriptions help differentiate them.

Naming Consistency5/5

The tool names follow a highly consistent snake_case pattern with clear verb_noun structures, such as click, close_browser, evaluate, fill, get_console_errors, navigate, run_accessibility_audit, and screenshot. There are no deviations in naming conventions, making the set predictable and easy to understand.

Tool Count3/5

With 22 tools, the count is borderline high for a browser automation and auditing server, as it might feel heavy and potentially overwhelming. While it covers many aspects, some tools could be consolidated (e.g., multiple audit tools), suggesting a slight over-scoping that could impact usability.

Completeness5/5

The tool set provides comprehensive coverage for browser automation and auditing, including navigation, interaction (click, fill, select), content retrieval (get_content, get_console_logs), debugging (run_debugger_mode, get_network_errors), audits (performance, SEO, accessibility), and maintenance (close_browser, wipe_logs). There are no obvious gaps, and agents can handle full workflows from setup to analysis.

Maintenance

ActivityStale
ResponsivenessNo issues