trackmcp
Back to directory
nfodor

mcp-chromium-arm64

View on GitHub

๐Ÿš€ ARM64 Browser Automation for Claude Code - SaaS testing on 80 Raspberry Pi budget. The first solution that works where Playwright/Puppeteer fail on ARM64. Autonomous testing without human debugging.

2 stars PythonWeb & Internet Tools Updated Oct 15, 2025
ai-testingarm64browser-automationbudget-aiclaude-codemcpnodejsraspberry-pisaas-testingstartup-tools

Documentation

MCP Chromium ARM64 Server

Cross-platform ARM64 browser automation via Chrome DevTools Protocol

Native Chromium control with 27 MCP tools for Linux, macOS, and Windows ARM64

๐Ÿš€ Two Implementation Approaches Available

๐Ÿ“ฆ Version Comparison

FeatureDirect CDP (v1.4.0) โญ RECOMMENDEDPuppeteer-based (v1.2.0)
DependenciesOnly `ws` + MCP SDK (89 packages)Puppeteer + MCP SDK (163 packages)
Memory UsageLower (native chromium)Higher (Node.js wrapper overhead)
Startup TimeFaster (direct WebSocket)Slower (puppeteer initialization)
Browser ControlNative Chrome DevTools ProtocolPuppeteer abstraction layer
ARM64 OptimizationFull native ARM64Depends on Puppeteer ARM64 support
DebuggingRaw CDP messages visibleAbstracted by Puppeteer
MaintenanceChrome protocol changes onlyPuppeteer + Chrome protocol changes
PerformanceBest (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** - 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** - 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

โœจ 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 (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 / 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

ErrorCauseSolution
`CDP command timeout`WebSocket connection lostRestart browser, check port availability
`WebSocket not ready`Chrome not fully startedIncrease startup delay, check chrome process
`Element not found`CSS selector invalidVerify selector with `evaluate` tool
`ECONNREFUSED`Debugging port blockedCheck firewall, kill existing chrome processes
`Navigation timeout`Page loading issuesCheck 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

PlatformStatusChrome PathInstallation MethodNotes
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 GoogleWould 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

PlatformStartup TimeMemory UsageNotes
Linux ARM64 (Pi 4)~3-4s~150MBOptimized, well-tested
macOS Apple Silicon~2-3s~200MBFaster CPU, more memory
Windows ARM64UnknownUnknownWould 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:

code
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:

code
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)
  • 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.*


๐Ÿ—๏ธ 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

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


โญ Star this repo if it helps democratize AI development!

Every star helps more developers discover accessible AI solutions


Built with โค๏ธ for the global developer community

Frequently asked questions

What is mcp-chromium-arm64?

mcp-chromium-arm64 is ๐Ÿš€ ARM64 Browser Automation for Claude Code - SaaS testing on 80 Raspberry Pi budget. The first solution that works where Playwright/Puppeteer fail on ARM64. Autonomous testing without human debugging.

How do I install mcp-chromium-arm64?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is mcp-chromium-arm64 open source?

Yes โ€” it is hosted on GitHub at https://github.com/nfodor/mcp-chromium-arm64 and has 2 stars.

Related MCP tools

co-browserbrowser-use-mcp-server

Browse the web, directly from Cursor etc. Built for the Model Context Protocol to enhance AI capabilities. Python-based implementation.

760 Python
browserbrowser-usecursor+3
OTA-Tech-AIweb-agent-protocol

๐ŸŒWeb Agent Protocol (WAP) - Record and replay user interactions in the browser with MCP support Python-based implementation.

479 Python
ai-agentsai-toolsbrowser-automation+11
zilliztechclaude-context

Code search MCP for Claude Code. Make entire codebase the context for any coding agent. TypeScript-based implementation. Trusted by 4100+ developers.

4,153 TypeScript
agentagentic-ragai-coding+17
zhayujiechatgpt-on-wechat

ๅŸบไบŽๅคงๆจกๅž‹ๆญๅปบ็š„่Šๅคฉๆœบๅ™จไบบ๏ผŒๅŒๆ—ถๆ”ฏๆŒ ๅพฎไฟกๅ…ฌไผ—ๅทใ€ไผไธšๅพฎไฟกๅบ”็”จใ€้ฃžไนฆใ€้’‰้’‰ ็ญ‰ๆŽฅๅ…ฅ๏ผŒๅฏ้€‰ๆ‹ฉChatGPT/Claude/DeepSeek/ๆ–‡ๅฟƒไธ€่จ€/่ฎฏ้ฃžๆ˜Ÿ็ซ/้€šไน‰ๅƒ้—ฎ/ Gemini/GLM-4/Kimi/LinkAI๏ผŒ่ƒฝๅค„็†ๆ–‡ๆœฌใ€่ฏญ้Ÿณๅ’Œๅ›พ็‰‡๏ผŒ่ฎฟ้—ฎๆ“ไฝœ็ณป็ปŸๅ’Œไบ’่”็ฝ‘๏ผŒๆ”ฏๆŒๅŸบไบŽ่‡ชๆœ‰็Ÿฅ่ฏ†ๅบ“่ฟ›่กŒๅฎšๅˆถไผไธšๆ™บ่ƒฝๅฎขๆœใ€‚

39,573 Python
aiai-agentchatgpt+17
assafelovicgpt-researcher

An LLM agent that conducts deep research (local and web) on any given topic and generates a long report with citations. Built for the Model Context Protocol to

24,026 Python
agentaiautomation+8
jlowinfastmcp

๐Ÿš€ The fast, Pythonic way to build MCP servers and clients Trusted by 19900+ developers. Trusted by 19900+ developers. Trusted by 19900+ developers.

19,927 Python
agentsfastmcpllms+6

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP