Skip to content

LowOrbitLab/spectra-mcp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spectra MCP

An MCP server that exposes invisible_playwright — an anti-detect Firefox with patched fingerprint surfaces — to LLMs.

Your assistant can launch a fingerprint-randomized browser, navigate, click, type, read the DOM, and take screenshots through it, using the standard Playwright surface, but with a patched Firefox engine under the hood.

The patched Firefox binary is a one-time ~100 MB download (python -m invisible_playwright fetch, or the fetch_binary tool).


How it works

  • invisible_playwright is a drop-in Playwright replacement that patches Firefox at the C++ level (navigator, GPU/WebGL, canvas, fonts, audio, WebRTC, timezone, network) and humanizes mouse motion in the driver.
  • An MCP server is a resident process, which is exactly what a stateful browser needs. This server keeps long-lived sessions in-process; each session owns an InvisiblePlaywright instance plus one or more pages. Tools operate on the session's active page unless told otherwise.
LLM ──MCP/stdio──► server ──► InvisiblePlaywright ──► patched Firefox
                       ▲                (async API)
              sessions held in-process

Install

pip install -e .                       # or: pip install spectra-mcp
python -m invisible_playwright fetch   # one-time ~100 MB, SHA256-verified

Requires Python 3.11+. Supported platforms: Windows x86_64, Linux x86_64/arm64, macOS arm64/x86_64.

On macOS the app is ad-hoc signed (not notarized): if Gatekeeper complains, clear the quarantine flag once with xattr -dr com.apple.quarantine on the cached Firefox.app.


Configure your MCP client

opencode (opencode.json)

{
  "mcp": {
    "spectra-mcp": {
      "type": "local",
      "command": ["spectra-mcp"],
      "enabled": true
    }
  }
}

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "spectra-mcp": {
      "command": "spectra-mcp"
    }
  }
}

Cursor (~/.cursor/mcp.json)

{
  "mcpServers": {
    "spectra-mcp": {
      "command": "spectra-mcp"
    }
  }
}

If the console script isn't on PATH, use the module form instead:

{ "command": "python", "args": ["-m", "spectra_mcp"] }

Quick start (for the LLM)

  1. fetch_binary (once) — download the patched Firefox if binary_status says ready: false.
  2. start_session → returns session_id, seed, and the initial page_id. Pass a proxy_server for residential/socks proxies.
  3. goto a URL, then query_elements / get_text / screenshot to understand the page.
  4. click / fill / press_key to act. Mouse motion is humanized.
  5. close_session when done (or just let the server shut down — the lifespan cleans up all Firefox processes).

Log the seed to replay an identical fingerprint later (start_session with the same seed).


Tool reference

Tool exposure is selected at server startup with SPECTRA_MCP_TOOL_PROFILE:

Profile Tools Approx. tool tokens Intended use
setup 2 ~230 Binary status/download only.
core 28 ~4,165 Default. Setup plus normal browsing, reading, forms, tabs, screenshots and evaluate.
full 55 ~7,942 Every advanced mouse, keyboard, dialog, cookie/storage and frame tool.

Token estimates use the o200k_base tokenizer and an OpenAI-style function-tool payload. Exact numbers vary by MCP client and whether output schemas are included.

core includes session lifecycle, page switching/popups, goto/reload, click/fill/type_text/press_key, scrolling/hover/selects, text/HTML/ attribute/element reads, visibility, screenshots, waits and evaluate.

SPECTRA_MCP_TOOL_PROFILE=core spectra-mcp
SPECTRA_MCP_TOOL_PROFILE=full spectra-mcp

PowerShell equivalent:

$env:SPECTRA_MCP_TOOL_PROFILE = "full"
spectra-mcp

The server must be restarted after changing profiles. The reference below lists the complete full profile; disabled functions remain available internally for tests but are not advertised to the model.

Setup / binary

Tool Description
binary_status Is the patched Firefox cached? Does not download.
fetch_binary Download + SHA256-verify the binary (~100 MB, one-time). force=True to re-download.

Session lifecycle

Tool Description
start_session Launch a browser with a fresh/seeded fingerprint. Returns session_id, seed, page_id.
close_session Close a session and free its Firefox process.
list_sessions Active session ids.
session_info Session metadata, pages, active page id, URL and title.

Pages

Tool Description
new_page Open a new tab; becomes the active page.
close_page Close a page (active by default).
switch_page Change the active page.

Navigation

goto, go_forward, reload

Interaction (humanized)

click, fill, type_text, press_key, keyboard_press, select_option, hover, focus, check, uncheck, scroll

Reading

get_text, get_html, get_attribute, query_elements, is_visible

query_elements returns a structured snapshot (tag, id, name, type, role, href, text, value, placeholder, visible, bounding rect) so the LLM can decide what to click without scraping raw HTML.

Screenshot

screenshot → returns image content directly to the LLM. Defaults to JPEG (quality=85) to keep payloads small; image_format="png" for lossless. full_page=True captures the whole scrollable page.

Waiting

wait_for_selector, wait_for_timeout

wait_for_selector returns reached=true when the requested state is reached; element_present reports whether an element handle still exists (it is normally false after successful hidden / detached waits).

Advanced

evaluate — run arbitrary JavaScript in the page and return its value. Powerful; use sparingly.

Coordinate mouse

mouse_drag, mouse_move, mouse_click

mouse_drag is intended for sliders, canvas handles and similar coordinate-based controls. With the current firefox-15 patched binary, hold-drag requires a session started with humanize=False.

Focused keyboard

keyboard_down, keyboard_up, keyboard_type

Use keyboard_down / keyboard_up for modifier-key combinations. Always release keys that were explicitly held.

Dialogs and popups

set_dialog_handler, get_dialogs, wait_for_page

Dialogs are handled automatically according to the session policy so they cannot freeze an in-flight action. Popups are adopted into the session without changing the active page.

Cookies and storage state

get_cookies, add_cookies, clear_cookies, save_storage_state

Storage state contains cookies and localStorage. Treat saved files as secrets and resume them with start_session(storage_state_path=...). Files are written via a private temporary file and atomically replaced; on Unix the final mode is 0600.

Frames

list_frames, frame_click, frame_fill, frame_type, frame_get_text, frame_wait_for_selector, frame_query_elements, frame_evaluate, frame_get_html, frame_get_attribute

list_frames returns a unique selector for each top-level iframe. Chain selectors with >>> to address nested iframes.


start_session parameters

Param Default Notes
seed random Reproducible fingerprint when set.
headless true Windows/macOS self-cloak the window.
proxy_server "" socks5://host:1080, http://..., etc. DNS routes via proxy.
proxy_username / proxy_password "" Proxy auth.
timezone "" IANA zone; empty = auto from egress IP.
locale "auto" auto = from egress country, or e.g. en-US.
humanize true Bezier mouse paths + human timing.
profile_dir "" Persistent profile path (enables persistent context).
prep_recaptcha false Pre-seed reCAPTCHA cookies (non-persistent only).
storage_state_path "" JSON file created by save_storage_state; cannot be combined with profile_dir.

Runtime safeguards

The resident server applies hard limits so a single tool call cannot exhaust the browser host or the stdio/MCP channel. Defaults can be changed with environment variables:

  • SPECTRA_MCP_MAX_SESSIONS=8
  • SPECTRA_MCP_MAX_PAGES_PER_SESSION=32
  • SPECTRA_MCP_MAX_TEXT_CHARS=200000
  • SPECTRA_MCP_MAX_ELEMENT_RESULTS=500
  • SPECTRA_MCP_MAX_TIMEOUT_MS=300000
  • SPECTRA_MCP_MAX_DELAY_MS=10000
  • SPECTRA_MCP_MAX_CLICK_COUNT=10
  • SPECTRA_MCP_MAX_MOUSE_STEPS=1000
  • SPECTRA_MCP_MAX_SCREENSHOT_BYTES=10485760
  • SPECTRA_MCP_MAX_SCREENSHOT_PIXELS=50000000
  • SPECTRA_MCP_MAX_EVALUATE_RESULT_BYTES=1048576

Set SPECTRA_MCP_DATA_ROOT to restrict profile_dir, storage-state input, and storage-state output to one filesystem tree. When it is unset, arbitrary local paths remain available for trusted local MCP use.

timeout_ms=0 keeps Playwright's conventional “no timeout” meaning. Negative timeouts and positive values above the configured maximum are rejected. fetch_binary(force=true) is rejected while sessions are active or cleaning up; binary launch/download/cache mutation is serialized with a cross-process lock.


Notes & caveats

  • IP matters. The browser fingerprint is handled; ~90% of captchas that remain are from known/blocked proxy IPs. Use clean residential IPs.
  • First start_session needs network to resolve geo/timezone (and to download the binary if you skipped fetch_binary).
  • Humanized clicks are slower than vanilla Playwright — raise timeout_ms if needed.
  • Coordinate hold-drag requires humanize=False on the current patched Firefox build.
  • File chooser, browser download events, selector drag-and-drop and back navigation are intentionally not exposed because firefox-15 does not support them reliably. Use evaluate-based workflows when appropriate.
  • evaluate runs arbitrary JS — only enable for trusted use.
  • All logging goes to stderr so it never corrupts the stdio JSON-RPC stream.
  • Calls against a single session must be sequential (the natural LLM pattern: the model waits for each tool result before sending the next). Concurrent calls to one session are not supported.

Development checks

The regression suite uses only Python's standard library:

python -m unittest discover -s tests -v
python -m compileall -q src tests

Real-browser integration checks are opt-in because they launch the patched Firefox and may require network access for session geo initialization:

SPECTRA_MCP_RUN_INTEGRATION=1 python -m unittest tests.test_integration -v

License

MIT. The patched Firefox binary is MPL-2.0 (Firefox upstream). This wrapper does not redistribute the binary; it downloads it on demand from the upstream releases.

About

MCP server exposing invisible_playwright anti-detect Firefox to LLMs

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages