MCP server

twin-browser-mcp exposes the execution engine as 31 native tools over stdio to any MCP client — Cursor, Claude Desktop, Claude Code, Cline, or your own. One API key, nothing to install or clone: the client launches the server via npx. Every target-bearing tool is authenticated with your key, scoped to your tenant, metered, and audited.

1 · Get a key

The hosted server needs a single Twin Browser API key from Keys & Secrets.

Create a keybash
# 1. Create an API key at https://twin-browser.com/dashboard/keys
#    (starts with ab_live_…). That's the only thing the hosted server needs.

# 2. Optional — smoke-test the server yourself before wiring it into a client:
TWIN_API_KEY=ab_live_… npx -y twin-browser-mcp
#    → "transport: customer (web API at https://twin-browser.com …)"

2 · Register the server

Pick the config for your client — the shape is the same everywhere.

Cursorjson
// .cursor/mcp.json  (project) or ~/.cursor/mcp.json (global)
// HOSTED setup — one variable, nothing to install. Every tool routes through the web API.
{
  "mcpServers": {
    "twin-browser": {
      "command": "npx",
      "args": ["-y", "twin-browser-mcp"],
      "env": {
        "TWIN_API_KEY": "ab_live_…"
      }
    }
  }
}
Claude Desktopjson
// claude_desktop_config.json → mcpServers
// HOSTED setup — one variable. WEB_BASE_URL defaults to https://twin-browser.com.
{
  "mcpServers": {
    "twin-browser": {
      "command": "npx",
      "args": ["-y", "twin-browser-mcp"],
      "env": {
        "TWIN_API_KEY": "ab_live_…"
      }
    }
  }
}
Claude Code / Clinebash
# Claude Code CLI — register the server in one line. Cline uses the same shape.
# HOSTED setup — one variable, nothing to install. (Operators running their own
# engine add EXEC_URL + EXEC_SHARED_SECRET instead.)
claude mcp add twin-browser \
  --env TWIN_API_KEY=ab_live_… \
  -- npx -y twin-browser-mcp

Environment & modes

Hosted-only mode (recommended): set ONLY TWIN_API_KEYWEB_BASE_URL defaults to https://twin-browser.com — and every tool routes through the hosted web API under your key. The startup log names the resolved mode: look for [twin-browser-mcp] transport: customer in your MCP client's logs; if it says operator, stale EXEC_URL/EXEC_SHARED_SECRET env is set.

Operator mode: running your own engine, set EXEC_URL (default http://localhost:7070) and EXEC_SHARED_SECRET instead of a key and the server talks to your fleet directly. The web-backed tools — search_library, dispatch, deep_search, etl/etl_query, the monitor tools, and the streamed-run branch of submit_verification — still need WEB_BASE_URL + TWIN_API_KEY.

3 · The tools

Lead with dispatch, run_goal, compile_skill and run_skill — the rest cover async jobs, observation, extraction, search, crawl, ETL, monitors, sessions, CAPTCHA, and recording.

Core — run, compile, replay, dispatch

  • run_goalExecute a goal on a target URL you provide — observe, plan, and act until a success condition is met. Optional proxy, video recording, and on-screen annotation. A sign-in run parks by default on a 2FA/approval wall it can’t auto-resolve, returning { status:"paused", sessionId } (resume with submit_verification); pass hitl:false to opt out.
  • compile_skillDiscover a goal once with the planner, then minimize it into a reusable, deterministic skill.
  • run_skillBlind-replay a compiled skill with no LLM in the loop — the cheap, deterministic path.
  • dispatchThe cheap path: fuzzy-match a goal to an existing compiled skill via the semantic cache — a hit replays deterministically (~5× cheaper), a miss compiles and caches it for next time (needs WEB_BASE_URL + TWIN_API_KEY).
  • list_skillsList the compiled skills available for replay.
  • list_catalogThe runnable-skill catalog: each compiled skill plus its run contract — the params to pass, the secrets it fills, and your auth readiness on the host (mode + ready + missing). Plan a run before spending a credit.
  • search_librarySemantically search the cross-tenant shared skill library by intent and host (needs WEB_BASE_URL + TWIN_API_KEY).

Async jobs

  • submit_runSubmit a goal as an async background job; returns a job id immediately. Like run_goal, a sign-in job parks by default on a 2FA/approval wall — get_job then reports status:"paused" with a sessionId.
  • get_jobPoll an async job by id for status, success, steps and result.
  • cancel_jobCancel a running async job by id (full credit refund).

Observation & data

  • observe_pageSerialize a page into token-efficient indexed DOM state without taking any action.
  • screenshotCapture a single screenshot of an authorized URL as PNG or JPEG — full page or one CSS selector. No action, no LLM cost.
  • extractRead an authorized page and return structured JSON matching the fields or JSON schema you request.
  • searchWeb search returning ranked results; set fetchContent to also fetch and clean the top results.
  • deep_searchAsync deep search — search, then scrape the top results (platform-aware) for cleaned content; returns a job id (needs WEB_BASE_URL + TWIN_API_KEY).
  • map_siteDiscover a site’s URLs fast from sitemap.xml + robots.txt + a shallow link scan. No page content.
  • submit_crawlCrawl a whole site asynchronously (BFS), bounded by page/depth limits and path globs; returns a job id. Optional per-page structured extraction.
  • etlRun the ETL pipeline: extract → transform → chunk → embed → load into the queryable content store (needs WEB_BASE_URL + TWIN_API_KEY).
  • etl_querySemantic search over content ingested with etl; returns the top-k matching chunks (needs WEB_BASE_URL + TWIN_API_KEY).

Monitors

  • create_monitorWatch a page on a schedule and push an HMAC-signed webhook when the watched value changes (needs WEB_BASE_URL + TWIN_API_KEY).
  • list_monitorsList this tenant’s monitors.
  • delete_monitorDelete a monitor by id.
  • get_monitor_historyGet a monitor’s recent check history — changed/unchanged/error plus value excerpts.

Sessions, credentials & HITL

  • connect_accountGet a one-time link that lets a HUMAN sign into a site by hand, so Twin Browser captures the session and later runs are already logged in. Use it when a run returns code:"credential_missing", or when a site hard-challenges automated logins from datacenter IPs and simply cannot be signed into by an agent. Never ask the user to paste a password — send this link. Re-run the task afterwards and it restores the session (sessionRestored:true).
  • list_connectionsCheck whether the user finished a connect link you sent them (pending | active | connected | failed | expired) before re-running the task.
  • list_accountsList the stored logins you already have as { label, host, emailPreview } — masked, never a credential. Pass a returned label as account on run_goal/run_skill and that login plus its own saved session are applied automatically. Nothing back for a host? Use connect_account to have the user sign in once.
  • control_runDrive a PAUSED run's browser directly — click, type, press a key, scroll, or navigate. Coordinates are 0..1 fractions of the viewport, read off a screenshot. The run continues by itself once the page no longer looks blocked; there is no "done" call. For a login a human must do, prefer connect_account; for a code, submit_verification.
  • submit_verificationResume a run waiting on a 2FA/approval wall. Two paths: a PARKED run (from run_goal/submit_run) → pass its { sessionId, code } (resumes the engine session directly); a LIVE streamed run → pass its { token, code } (needs WEB_BASE_URL + TWIN_API_KEY). Codes: sms/email, TOTP, or phone approval; or cancel.
  • solve_captchaHand a live/paused session’s CAPTCHA to the solver and continue.

Recording

  • record_runRun a goal and capture a video recording of the session.
  • record_jobSubmit an async job that records its run to video.

Capture a session from your own browser

For sites whose sign-in is hard to automate remotely — popup-based “Continue with Google”, hardware-attested logins — sign in on your OWN browser (where OAuth just works) and hand the session to Twin Browser. Your password never leaves your browser; only the resulting session cookies are sent, encrypted at rest.

  1. Download the extension folder from the repo (extension/) and open chrome://extensions.
  2. Turn on Developer mode, click Load unpacked, select the folder.
  3. Sign into the site normally (e.g. linkedin.com → Continue with Google).
  4. Click the Twin Browser icon, paste your ab_live_… key, add an optional account label, and Send this session.

From then on a run restores it (sessionRestored: true). Manage or forget connected sessions under Keys & secrets → Sessions. Works in any Chromium browser (Chrome, Edge, Brave, Arc). Under the hood it POSTs to /api/v1/sessions/import.

Enterprise / managed browsers: force-install by policy instead — a signed package with a stable ID and auto-update is hosted at /extension/twin-browser-extension.crx (update manifest /extension/updates.xml). No Chrome Web Store needed. See extension/SELF_HOSTING.md for the ExtensionInstallForcelist policy JSON.

Use it

Example promptstext
# Once connected, ask your agent in natural language, e.g.:
#   "Compile a skill that logs into app.acme.com and exports invoices,
#    then replay it." → compile_skill → run_skill (no LLM on replay)
#   "Search the library for 'export invoices as CSV' on app.acme.com"
#    → search_library
# Every target-bearing call is authenticated with your key and acts on the
# url you pass — scoped to your tenant, metered, and written to the audit log.

Replays run with no LLM: run_skill replays a compiled skill deterministically, and compile_skill discovers a path once and minimizes it for reuse — so repeated tasks avoid the per-run model cost entirely.