Skip to content

ColorSource/invisible_playwright_mcp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

invisible_playwright_mcp

An MCP server that exposes invisible_playwright — a patched stealth Firefox that beats reCAPTCHA v3, FingerprintPro, CreepJS, and the rest — to any MCP client (Claude Code, Claude Desktop, Cursor, Cherry Studio, …).

Tool surface mirrors Microsoft's @playwright/mcp: same names, same (element, target) ref pattern, drop-in for any agent already using it. Adds multi-session support so one agent can drive several independent fingerprints in parallel.

What you get

  • 34 MCP tools covering navigation, interaction, snapshot/screenshot, content extraction, cookies, downloads, tabs, dialogs, network/console inspection, coordinate-based mouse, and session management.
  • Stealth by default. Every session gets a unique coherent fingerprint sampled from real Firefox telemetry; .toString() is clean because the patches are in Gecko C++, not in injected JS.
  • Persistent login. Pass profile_dir to browser_context_create to keep cookies/history/localStorage across sessions — re-opening with the same path restores everything.
  • Multi-session. browser_context_create spawns isolated browsers with their own seed/proxy/locale; pass context_id to any tool to target a specific one.
  • Full fingerprint pinning. pin dict lets you override any seed-derived value (gpu.renderer, screen.width, hardware.concurrency, audio/canvas/font knobs, …); extra_prefs accepts any raw Firefox preference.
  • Snapshot-driven refs. browser_snapshot tags interactable elements with [ref=eN] and returns a markdown outline. Pass that ref to browser_click/browser_type/etc. — no XPath, no fragile selectors.

Install

Requirements: Python 3.11+, Windows x86_64 or Linux x86_64 (macOS not supported — upstream invisible_playwright constraint).

pip install git+https://github.com/ColorSource/invisible_playwright_mcp.git

That's it. The patched invisible_playwright package is pulled in as a dependency. The ~100 MB Firefox binary is downloaded lazily on the first browser_context_create (or first auto-created default session), SHA256-verified, and cached at %LOCALAPPDATA%\invisible-playwright\Cache\ (Windows) or ~/.cache/invisible-playwright/ (Linux). Pre-fetch it if you want to avoid the wait on first call:

python -m invisible_playwright fetch

Register with your MCP client

Claude Code (CLI)

Add to ~/.claude.json (or %USERPROFILE%\.claude.json on Windows) under mcpServers:

{
  "mcpServers": {
    "invisible_playwright": {
      "command": "python",
      "args": ["-m", "invisible_playwright_mcp"]
    }
  }
}

Or run once:

claude mcp add invisible_playwright -- python -m invisible_playwright_mcp

Claude Desktop

Drop examples/claude_desktop_config.json into your Claude Desktop config (%APPDATA%\Claude\claude_desktop_config.json on Windows, ~/Library/Application Support/Claude/claude_desktop_config.json on macOS). Restart the app.

Cursor / Cherry Studio / other MCP clients

Same pattern — command python, args ["-m", "invisible_playwright_mcp"], transport stdio.

Tool catalog

Group Tool Purpose
Session browser_context_create Start a new isolated stealth browser — seed, proxy_*, locale, timezone, headless, humanize, profile_dir, full pin dict, extra_prefs
browser_context_list Show all live sessions
browser_context_close Close a session (preserves profile_dir on disk if used)
Navigation browser_navigate / _back / _forward / browser_reload URL nav + history
browser_wait_for Wait for text to appear / disappear / fixed time
Snapshot browser_snapshot Markdown tree of interactable elements with [ref=eN]
browser_take_screenshot PNG/JPEG of page or single element
browser_evaluate Run JS on page or element
Content browser_get_text Visible text of page or element
browser_get_html Raw HTML (inner or outer)
Interaction browser_click / browser_hover / browser_type Standard actions, target by ref or selector
browser_drag Drag-drop between two refs
browser_press_key Keyboard press
browser_select_option <select> value(s)
browser_fill_form Multi-field form fill
browser_file_upload Upload files to <input type=file>
Cookies browser_get_cookies / _set_cookies / _clear_cookies Round-trip login state between sessions
Downloads browser_downloads_list List files auto-captured to per-session temp dir
Tabs/Dialogs browser_tabs list/new/close/select
browser_handle_dialog Arm a one-shot alert/confirm/prompt handler
Observability browser_network_requests / browser_network_request List + drill into HTTP traffic
browser_console_messages Drain captured console logs
Window/Mouse browser_resize Viewport size
browser_mouse_click_xy / _move_xy / _drag_xy Coordinate-level mouse

Every interaction/capture tool accepts an optional context_id parameter (default "default"). The default context is created lazily on first use.

Note: PDF export (page.pdf()) is Chromium-only in Playwright — Firefox does not support it, so we don't expose a PDF tool. Use browser_take_screenshot(full_page=true) for a visual capture.

Quick example (agent workflow)

1. browser_navigate(url="https://abrahamjuliot.github.io/creepjs/")
2. browser_wait_for(time=5)                 # let the page finish profiling
3. browser_snapshot()                       # find the "Lies" element ref
   → "- div \"0 lies\" [ref=e12]"
4. browser_take_screenshot(full_page=true)  # confirm visually

Persistent login

browser_context_create(
  context_id="github",
  profile_dir="C:/profiles/github_account_a",
  seed=42
)
browser_navigate(url="https://github.com/login", context_id="github")
# ... user logs in once ...
browser_context_close(context_id="github")

# Next session: same login still there
browser_context_create(context_id="github", profile_dir="C:/profiles/github_account_a", seed=42)
browser_navigate(url="https://github.com/dashboard", context_id="github")  # logged in

Multi-account parallelism

browser_context_create(context_id="acct_a", seed=1, proxy_server="socks5://gate:1080", proxy_username="u1", proxy_password="p1")
browser_context_create(context_id="acct_b", seed=2, proxy_server="socks5://gate:1080", proxy_username="u2", proxy_password="p2")
browser_navigate(url="...", context_id="acct_a")
browser_navigate(url="...", context_id="acct_b")

Verifying the stealth works through MCP

The whole point is that no Gecko-level guarantee leaks when you wrap it. To sanity-check end-to-end:

browser_navigate(url="https://bot.sannysoft.com")
browser_take_screenshot(full_page=true)
# every row should be green
browser_navigate(url="https://fingerprint.com/products/bot-detection/")
browser_evaluate(function="() => document.body.innerText")
# 'bot detected: not detected'

Architecture

MCP client (Claude Code, Cursor, …)
        │  stdio JSON-RPC
        ▼
FastMCP server (server.py)
        │
        ▼
BrowserContextManager        ← context_id → SessionState
        │
        ▼
invisible_playwright.async_api.InvisiblePlaywright
        │
        ▼
patched Firefox 150 (C++ level fingerprint spoofing)

Ref resolution: browser_snapshot tags interactable DOM elements with data-mcp-ref="eN" via JS injection, stores page.locator('[data-mcp-ref="eN"]') keyed by ref. Interaction tools' target parameter accepts either a ref ("e3") or any Playwright selector. Refs are cleared on every snapshot and on navigation.

License

MIT. Bundles no Firefox binary — invisible_playwright fetch retrieves it from the upstream release.

About

MCP server exposing invisible_playwright (patched stealth Firefox) to AI agents. 28 tools mirroring @playwright/mcp surface, with multi-session support.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages