π§ TabPilot
Drive the real Chrome you are already logged into β on macOS, Windows, and Headless Ubuntu 24/7.
Most browser MCP servers launch a fresh, blank browser instance. That works for scraping static pages, but fails completely on tasks that matter:
- π« Cloudflare & Bot Shields immediately flag fresh automation browsers.
- π« Corporate SSO, Okta, & 2FA make authenticating from scratch painful or impossible.
- π« Read-only tab viewers can only look at DOM text, not click or fill forms.
TabPilot bridges this gap. It attaches directly to your existing, logged-in Google Chrome. Your AI agents (Claude, Cursor, Antigravity, Cline) can read pages with up to 99% token savings, click elements with authentic mouse events (isTrusted: true), defeat React state caching traps, solve multi-row survey grids, and capture background screenshots without stealing window focus.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β YOUR WORKSPACE TABPILOT MCP ENGINE REAL BROWSER β
β β
β ββββββββββββββββββββββββ ββββββββββββββββββββββββ ββββββββββββββββ β
β β AI Agents β β TabPilot MCP Server β β Real Chrome β β
β β - Claude Desktop β stdio / β - Token Budget Slicerβ CDP β - Active SSO β β
β β - Cursor IDE β βββββββ> β - Native Form Settersβββββ> β - Cookies β β
β β - Antigravity/Gemini β SSH β - Matrix Grid Driver β<ββββ β - 2FA Saved β β
β β - Cline / Windsurf β β - Dual CDP/AppleScr. β β - Real Fingerβ β
β ββββββββββββββββββββββββ ββββββββββββββββββββββββ ββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β‘ Quick Start
1. Test your environment in one command
Run tabpilot doctor via uvx (no installation required):
uvx tabpilot-mcp doctor
(Or install via pip: pip install tabpilot-mcp)
2. Configure your MCP Client
Add to claude_desktop_config.json or .cursor/mcp.json:
{
"mcpServers": {
"tabpilot": {
"command": "uvx",
"args": ["tabpilot-mcp"]
}
}
}
3. Launch Chrome with Remote Debugging
Quit Chrome completely, then start it pointing to your persistent automation profile:
# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port=9222 --user-data-dir="$HOME/tabpilot-chrome"
# Linux
google-chrome --remote-debugging-port=9222 --user-data-dir="$HOME/tabpilot-chrome"
# Windows
taskkill /F /IM chrome.exe
"C:\Program Files\Google\Chrome\Application\chrome.exe" ^
--remote-debugging-port=9222 --user-data-dir="%USERPROFILE%\tabpilot-chrome"
[!IMPORTANT] π macOS Zero-Config Fallback:
On macOS, if you do not launch Chrome with debugging flags, TabPilot automatically falls back to AppleScript to drive the Chrome you already have open.
Prerequisite: In Google Chrome, go to View β Developer β check "Allow JavaScript from Apple Events".
π° How TabPilot Saves 90%+ Tokens
Naive browser automation dumps document.body.innerText or raw HTML, wasting 15,000β45,000 tokens on navigation bars, cookies banners, and tracking scripts.
TabPilot provides Progressive Token Slicing:
Raw Page Dump (eval_js body) ββββββββββββββββββββββββββββββββββββββ 18,000+ tokens
read_tab() (Link-Density) ββββββββββββββββββββββββββββββββββββββ ~1,200 tokens (93% saved)
read_tab(selector) ββββββββββββββββββββββββββββββββββββββ ~350 tokens (98% saved)
query_dom(selector) β ~18 tokens (99.9% saved)
| Method | Tokens | Savings | Best For |
|---|---|---|---|
query_dom(selector) | ~15β30 | 99.9% | Checking button states (disabled), inputs, badges, or alerts |
read_tab(selector) | ~300β600 | 98.0% | Reading isolated articles, ticket cards, or form sections |
read_tab() (Link-Density) | ~1,200β1,800 | 93.0% | Full-page reads with nav, ads, headers, and footers stripped |
β Naive eval_js innerText | 15,000β35,000 | 0% | Context budget incinerator |
π‘ Enforced Character Budget: Reads default to
--max-chars 20000. If truncated, TabPilot alerts the model with exact cut sizes, prompting it to narrow down withselectorinstead of hallucinating.
π₯ Driving Forms That Fight Back
Modern Single-Page Applications (React, Vue, Svelte) defeat standard automation scripts. TabPilot solves the 3 most infamous SPA traps:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TRAP 1: React Synthetic Cache β
β Standard `.value = 'x'` is ignored by React's internal tracker. β
β β
TabPilot calls native property setters + fires both `input` and `change`. β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β TRAP 2: Multi-Row Survey Grid Batching β
β Clicking 25 matrix rows in one JS tick causes React to commit only the last row. β
β β
`fill_matrix` clicks row-by-row across microtasks with delays, then confirms. β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β TRAP 3: Virtual Portals (React-Select, Headless UI) β
β No `<select>` exists; options render only after clicking the trigger. β
β β
`select_option_ui` clicks trigger, awaits portal mount, and selects option. β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βοΈ Comparison
| Capability | Read-Only Tab Readers | Headless Bots (Puppeteer/Playwright) | π§ TabPilot |
|---|---|---|---|
| Uses Existing Sessions & Cookies | β | β Fresh empty profile | β Real Chrome (No re-login) |
| Bypasses Cloudflare & Bot Shields | β Human | β Bot fingerprint | β Human browser fingerprint |
| Form Driving & Clicking | β Read-only | β | β Full Bidirectional Driving |
| React Synthetic Event Fix | β | β οΈ Often missed | β Native prototype setters |
| Survey Matrix Handler | β | β Batched drops | β
fill_matrix task scheduling |
| Token-Optimized Extraction | β οΈ Basic text | β Raw DOM / costly vision | β
query_dom (18 tokens) |
| Background Tab Screenshots | β Must be active | β | β Off-screen CDP captures |
| Headless Ubuntu 24/7 Daemon | β macOS only | β οΈ Complex Docker | β Native systemd stack |
| External Dependencies | Minimal | β Heavy Node/Playwright binaries | β Zero dependencies beyond MCP |
π§ 24/7 Headless Ubuntu Server Stack
TabPilot is engineered to run permanently on cloud VPS servers (AWS, Hetzner, DigitalOcean) with zero exposed ports:
[ Laptop / Client ] ββ( Encrypted SSH Pipe )ββ> [ Remote Ubuntu Server ]
β
βΌ
[ TabPilot MCP Server ]
β (CDP 127.0.0.1:9222)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Managed Systemd User Stack (Restart=always, Linger Enabled) β
β tabpilot-xvfb.service ββ> tabpilot-wm.service ββ> tabpilot-chrome.service
β (Virtual Framebuffer) (Openbox Window Mgr) (Real Chrome + SSO) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- One-Command Setup:
bash deploy/ubuntu/install.shconfigures Xvfb, Openbox, Chrome, and systemd services withRestart=always. - Font Protection (Anti-Tofu): Headless servers often render Vietnamese and CJK characters as empty square boxes.
install.shinstalls Noto and Liberation fonts;doctorvalidates text rendering. - Cgroup Memory Caps: Prevent Chrome from exhausting host RAM:
tabpilot install-stack --memory-high 4G - Zero Remote Attack Surface: Chrome CDP stays locked to
127.0.0.1. Remote MCP connections run securely through SSH pipes (ssh you@server "tabpilot serve").
π§° Tools & Resources Reference
TabPilot exposes 19 tools and 2 live resources:
π‘οΈ CAPTCHA Detection & Solving
detect_captcha(url_pattern, tab_id): Structured, zero-side-effect detection of CAPTCHAs (Cloudflare Turnstile/Interstitial, reCAPTCHA v2/Enterprise, hCaptcha, image grids, text captchas, and slider puzzles) with confidence scores, candidate IDs, and available strategies.solve_captcha(tab_id, url_pattern, operation, candidate_id, solve_id, observation_id, action_id, action, strategy, agent_vision, timeout_ms, max_attempts, max_rounds, expected, activate_on_fail): Multi-step stateful solver supporting automated checkbox solvers, passive wait, and interactive Agent Vision observation-action loops (select_tile,drag,type_answer,verify) with postcondition access verification and token freshness checks.
π Reading & DOM Inspection
query_dom(selector, attrs, limit, visible_only): Atomic element inspection (~18 tokens). Checks disabled, checked, values.read_tab(selector, mode, max_chars, url_pattern): Link-density markdown extraction with token caps.list_tabs(url_pattern): Lists open tabs with IDs, titles, and URLs (regex filterable).eval_js(expression, timeout_ms): Runs arbitrary JS in tab context; automatically awaits Promises in CDP.
π§ Navigation & Tabs
open_tab(url, activate, wait_for_load): Opens a URL in a new tab, awaiting page completion.close_tab(url_pattern, tab_id): Closes tab and polls until process confirms destruction.navigate(url, wait_for_load): Points tab to a new URL and awaits document load.activate_tab(url_pattern, tab_id): Brings target tab to foreground focus.
π±οΈ Interaction & Complex Forms
click(selector, text, nth): Scrolls element into view and emits trusted mouse event (isTrusted: true).fill(selector, value, clear, press_enter): Sets form inputs via native prototype setters to trigger React/Vue.select_option(selector, values, by): Selects options in native<select>or Select2 dropdowns.select_option_ui(control_selector, option_text): Clicks trigger, waits for popup portal, and selects item.wait_for(selector, state, text, timeout_ms): Polls until condition holds (visible,hidden,text,enabled).
π Matrix Surveys & Evidence
scan_matrix(selector): Discovers multi-row grid questions and flags unanswered rows.fill_matrix(column_index, rows, delay_ms): Answers matrix rows sequentially with task delays.screenshot(full_page, selector, label): Offscreen capture of any tab (local path or inline base64).browser_status(): Reports active backend, capabilities, CDP endpoint, and open tab count.
π¦ Live MCP Resources
tab://activeβ Markdown stream of the currently focused tab.tab://{tab_id}β Markdown stream of any specific tab by ID.
π οΈ CLI Reference
tabpilot doctor # Run diagnostic suite (Chrome, CDP, fonts, permissions)
tabpilot tabs # List open browser tabs in terminal
tabpilot serve # Start MCP server on stdio
# Linux Managed Stack Commands
tabpilot install-stack # Install systemd user services
tabpilot up / tabpilot down # Start or stop the headless stack
tabpilot status # Check systemd stack status
tabpilot logs chrome -f # Follow live Chrome logs
π§ͺ Testing
git clone https://github.com/hunglp97/tabpilot-mcp.git
cd tabpilot-mcp
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
# Unit tests (Zero browser needed)
pytest -v
# Live integration tests (against Chrome on port 9222)
pytest -v -m live
π License
Distributed under the MIT License. See LICENSE for details.
Built with β€οΈ for AI Engineers, QA Automators, and Power Users who demand real browser agency.
Star β TabPilot on GitHub if it saved your agents from bot shields and token burn!