Skip to main content
Glama
README.md
# 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

B3.2/5.0

Scored across 51 tools

Disambiguation4/5

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.

Naming Consistency4/5

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.

Tool Count2/5

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.

Completeness5/5

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.

Maintenance

ActivityMaintained
ResponsivenessNo issues