Navigator MCP
# Navigator MCP β the pathfinding browser MCP
**High-performance browser automation for LLM agents.**
One Model Context Protocol server β the *Navigator*
- π§ **Token-efficient perception** β ref-based accessibility snapshots with
change-caching (an unchanged page costs ~40 tokens, not 4,000)
- π₯· **Advanced stealth** β coherent fingerprint profiles, runtime patches
(WebGL/canvas/navigator/chrome), human-like mouse paths & typing jitter
- π§© **Captcha handling** β detection for 8+ providers, auto-solve via
2Captcha/CapSolver, manual handoff with a visible browser
- π‘ **Traffic intelligence** β network capture/blocking, hidden API
discovery, console & dialog observability
- π **Isolated sessions** β per-session fingerprint/proxy/cookies, auth
persistence across restarts, up to 64 parallel sessions
- π **Zero gating** β no licenses, no tiers, no telemetry, no phone-home.
Every capability is always unlocked; usage stats stay on your disk
> The VAPT security suite (OOB callbacks, passive scanning, WAF detection,
> raw HTTP, XSS probing) that shipped in v1.x has been **extracted to
> `reference/`** β proven, tested code parked for a dedicated **Security
> MCP** companion server. See `reference/README.md`.
```
51 tools Β· stdio + Streamable HTTP Β· Python 3.10+ Β· Playwright Chromium
```
---
## Why Navigator outperforms the field
| Capability | Playwright MCP | Browserbase | Stagehand | **Navigator** |
|---|:---:|:---:|:---:|:---:|
| Ref-based AX snapshots | β
| β
| β | β
|
| **Snapshot change-caching** (unchanged page β 1-liner) | β | β | β | β
|
| Auto-snapshot after actions (no extra round-trip) | partial | β | β | β
|
| Shadow-DOM traversal | β | β | partial | β
|
| Batch form filling (one call, N fields) | β | β | β | β
|
| Advanced stealth (fingerprint + runtime + humanized input) | β | partial | β | β
|
| Captcha detect + auto-solve + manual handoff | β | β | β | β
|
| Network capture / blocking / API discovery | partial | partial | β | β
|
| Console & dialog capture (JS-error observability) | partial | β | β | β
|
| Isolated sessions with auth persistence | partial | β
| partial | β
|
| Optional navigation lockdown (domain allowlist) | β | β | β | β
|
| "Pro" features behind a paywall | metered | β
| partial | **never** |
| Local-first, zero telemetry | β
| β | β
| β
|
Numbers that matter for autonomous agents: on a typical multi-step task
(login β navigate β extract), change-caching + auto-snapshots + batch fill
cut **token usage by ~50β70%** and **round-trips by ~40%** vs a
snapshot-per-step loop.
---
## Quickstart
### Local (Claude Desktop / Cursor / VS Code / any MCP client)
```bash
pip install -e .
playwright install chromium
```
`claude_desktop_config.json` (see `examples/`):
```json
{
"mcpServers": {
"navigator": {
"command": "navigator-mcp",
"env": { "NAVIGATOR_STEALTH": "true" }
}
}
}
```
That's it. The first `browser_navigate` lazily starts a stealthed Chromium.
### Remote access (your own server, optional API keys)
```bash
NAVIGATOR_API_KEYS=sk-my-laptop,sk-my-desktop \
navigator-mcp --transport http --host 0.0.0.0 --port 8765
```
Clients connect to `http://your-host:8765/mcp` with header
`X-API-Key: sk-my-laptop`. Unauthenticated requests get `401`;
`GET /health` is open for monitoring.
### Docker
```bash
docker compose up # HTTP on :8765
docker compose --profile vnc up # + headful VNC on :5901
docker run -i --rm --init navigator-mcp # stdio for local clients
```
---
## The tool surface (51 tools)
**Perceive** β `browser_snapshot` (ref tree, change-cached, `deep=true` for
frames) Β· `browser_find` (regex search, actionable-first) Β·
`browser_extract_text/html/links/forms/tables/meta` (paginated) Β·
`browser_read_console` Β· `browser_read_dialogs`
**Act** β `browser_click` Β· `browser_click_text` Β· `browser_fill` Β·
`browser_fill_form` (batch) Β· `browser_select_option` Β· `browser_hover` Β·
`browser_press_key` Β· `browser_drag` Β· `browser_upload_file` Β·
`browser_scroll` Β· `browser_wait_for`
**Navigate** β `browser_navigate` Β· `browser_navigate_back/forward` Β·
`browser_reload` Β· `browser_get_url`
**Organize** β `browser_tab_list/new/select/close` Β·
`browser_session_list/new/close/save_auth` (isolated contexts, persistent
auth profiles, per-session proxy/fingerprint/HAR recording)
**See** β `browser_screenshot` (native image content: viewport / full page /
element) Β· `browser_save_pdf`
**Inspect traffic** β `browser_network_capture_start/stop/list/get` Β·
`browser_network_block/unblock` Β· `browser_discover_apis` (find the JSON
endpoints behind any page) Β· `browser_set_dialog_mode` Β·
`browser_dialog_respond`
**Compute** β `browser_evaluate` (arbitrary JS, arg passing)
**Captchas** β `browser_captcha_detect` Β· `browser_captcha_solve`
(needs a provider key) Β· `browser_captcha_manual_wait`
**System** β `navigator_status` Β· `usage_report` (local stats)
### The core loop in practice
```
You: Fill the login form on staging.acme.io and screenshot the dashboard.
Model: browser_navigate("https://staging.acme.io/login")
β snapshot included automatically:
- textbox "Email" [ref=e4]
- textbox "Password" [ref=e5]
- button "Sign in" [ref=e9]
browser_fill_form([{ref: "e4", value: "bot@acme.io"},
{ref: "e5", value: "β’β’β’β’"}])
browser_click(ref="e9")
β new snapshot included (page changed)
browser_screenshot(area="viewport")
```
Three tool calls, zero redundant snapshots, refs stable across steps.
---
## Stealth: what's actually patched
Per **session** (contexts never share fingerprints):
| Layer | Mechanism |
|---|---|
| Network | UA / `sec-ch-ua` / `sec-ch-ua-platform` / `accept-language` headers coherent with the chosen profile |
| Navigator | `webdriver` removed, `platform`, `languages`, `hardwareConcurrency`, `deviceMemory`, `plugins`/`mimeTypes` (5 realistic Chrome plugins), `maxTouchPoints` |
| `window.chrome` | `runtime` (ports + listeners), `app`, `loadTimes`, `csi` |
| WebGL | `UNMASKED_VENDOR/RENDERER` return profile-matched GPU strings |
| Canvas / Audio | session-stable deterministic noise (fingerprint distinct per session, consistent within it) |
| Input | BΓ©zier mouse paths with overshoot+correction, typing jitter with occasional typo-and-fix, burst scrolling |
| Permissions | `Notification.permission`/`permissions.query` consistency |
Six bundled profiles (Win/Mac/Linux Γ Chrome/Safari) β or bring a patched
browser via `NAVIGATOR_CDP_ENDPOINT=ws://β¦` and Navigator drives it (Camoufox,
rebrowser-patches, your own build).
> For maximum anti-bot resilience run headful: `NAVIGATOR_HEADLESS=false`
> (locally) or the `vnc` compose profile (container). Headless Chrome has
> residual fingerprints no JS patch fully erases.
## Captcha flow
1. `browser_captcha_detect` β type + evidence + sitekeys
2. `browser_captcha_solve` β reCAPTCHA v2 / hCaptcha / Turnstile token
solved by your 2Captcha or CapSolver key and injected; image captchas
solved from an element screenshot; auto re-check
3. Manual fallback: headful browser + `browser_captcha_manual_wait` while a
human solves it over VNC
---
## No licensing β everything unlocked
There is no license server, no key format, no tier table, no phone-home,
and nothing to configure. All 51 tools β stealth, captcha auto-solve,
unlimited sessions (resource-capped at 64 by default, raise via
`NAVIGATOR_MAX_SESSIONS`), the HTTP transport β are always available.
The only "metering" is a local stats file (`~/.navigator/usage.json`) that
powers the `usage_report` tool: per-tool counters, per-day breakdown,
and totals. **No URLs, no page content, nothing leaves your machine.**
Turn it off with `NAVIGATOR_STATS=false` if even that is unwanted.
When you expose the HTTP transport beyond localhost, set `NAVIGATOR_API_KEYS`
to require bearer keys β that's plain access control for your own endpoint,
not a billing feature.
---
## Configuration reference
Everything is environment-driven (see `.env.example` for the full list):
| Variable | Default | Purpose |
|---|---|---|
| `NAVIGATOR_HEADLESS` | `true` | headless mode (set false for captchas/anti-bot) |
| `NAVIGATOR_STEALTH` | `true` | fingerprint + runtime patches |
| `NAVIGATOR_HUMANIZE` | `true` | human-like input synthesis |
| `NAVIGATOR_AUTO_SNAPSHOT` | `true` | include snapshots in action results |
| `NAVIGATOR_MAX_SESSIONS` | `64` | resource cap on parallel sessions |
| `NAVIGATOR_CDP_ENDPOINT` | β | drive an external (patched) browser |
| `NAVIGATOR_PROXY_SERVER` | β | default proxy for all sessions |
| `NAVIGATOR_ALLOWED_DOMAINS` | β | optional navigation lockdown (allowlist) |
| `NAVIGATOR_API_KEYS` | β | HTTP auth keys (comma-separated) |
| `NAVIGATOR_STATS` | `true` | local usage counters for usage_report |
| `TWOCAPTCHA_API_KEY` / `CAPSOLVER_API_KEY` | β | captcha provider keys |
## Architecture
```
navigator_mcp/
βββ server.py FastMCP assembly Β· instructions Β· stats middleware
βββ __main__.py CLI: stdio / http
βββ config.py env-driven settings
βββ metering.py purely local usage counters
βββ runtime.py singleton wiring Β· navigation lockdown Β· session cap
βββ core/
β βββ browser.py sessions Β· tabs Β· per-page event wiring
β βββ scope.py optional domain-allowlist lockdown
βββ perception/
β βββ snapshot.py ref-based AX collector (shadow DOM, frames) + renderer
β βββ extraction.py text/html/links/forms/tables/meta
βββ stealth/
β βββ fingerprints.py coherent profile bundles
β βββ init_scripts.py per-session runtime patches (JS)
β βββ humanize.py BΓ©zier mouse Β· typing jitter Β· burst scroll
βββ captcha/
β βββ detector.py 8+ captcha families, sitekey discovery
β βββ providers.py 2Captcha + CapSolver async clients
βββ network/
βββ interceptor.py capture filters Β· API discovery
```
## Development
```bash
pip install -e ".[dev]"
playwright install chromium # for browser-marked tests + the E2E script
./scripts/run_checks.sh # one command: lint + pytest + real-browser E2E + HTTP smoke
./scripts/run_checks.sh --fast # lint + pytest only (no browser, no server)
```
`pytest` runs 28 tests (browser-marked ones auto-skip without a chromium
binary). The two E2E scripts can also be run individually:
`python scripts/e2e_browser.py` (9-check live browser loop) and
`python scripts/http_smoke.py` (boots the HTTP server, checks the API-key
gate and the MCP initialize handshake).
## Roadmap
- Firefox/WebKit session engines Β· cookie-jar import/export
- Remote browser grid (connect a fleet via CDP endpoints)
- Playwright-element-handle-compatible script recording
- Headful farm orchestration on top of the VNC profile
TDQS
Scored across 51 tools
Tools are organized around clearly separate actions and resources (navigation, clicks, fills, extractions, tabs, sessions, network, captchas), so an agent can usually pick the right one. A few pairs like browser_click vs browser_click_text or browser_snapshot vs browser_find overlap in intent, but the descriptions frame them as ref-based vs fallback/filtered alternatives.
The vast majority follow a predictable browser_<verb>_<noun> snake_case pattern, with clear groups like browser_extract_*, browser_network_*, browser_tab_*, and browser_session_*. Exceptions such as navigator_status and usage_report break the prefix pattern, and dialog/network verbs are not perfectly parallel, but the system is still easy to navigate.
Fifty-one tools is well past the 25+ threshold and creates a heavy surface for an agent to evaluate, even for a browser-automation domain. The set could be consolidated (e.g., extraction variants, captcha helpers, network controls) without losing core capability, so the count feels too high rather than well-scoped.
The server covers the full browser lifecycle: session/tab management, navigation, interaction, extraction, network capture/blocking, dialogs, console, screenshots, PDF, and captcha handling. There are no obvious dead ends, and browser_evaluate provides an escape hatch for anything not explicitly exposed.