Wraith MCP Server
This server lets an AI agent drive a stealth browser, extract page content, handle bot defenses, and reuse authenticated sessions.
Navigate URLs and receive indexed snapshots of interactive elements, with automatic WAAP challenge and cookie-banner handling.
Re-snapshot pages, wait for text/load, scroll, manage tabs, and go back/forward.
Interact by element index or coordinates: click, double-click, click inside frames, type text, press keys, select options, drag sliders, and upload allowlisted files.
Read page content as markdown, search for passages, fetch specific slices, keep link URLs, or read the full page.
Capture screenshots for visual inspection and coordinate-based actions.
Fill secrets or vault items without exposing secret values to the model.
Inspect network requests and response bodies, and replay captured sessions without launching a browser.
Borrow cookies from local Firefox/Zen profiles, receive end-to-end encrypted synced profiles, save session state, and use a warmed Google identity for reCAPTCHA v3.
Detect WAAP/anti-bot vendors on a URL.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Wraith MCP Server navigate to https://news.ycombinator.com and list the top 5 stories"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Wraith gives an agent a stealth browser: Camoufox (a hardened Firefox) or a patched Chromium. The agent reads each page as a numbered list of controls and acts by number. Wraith runs as a CLI, a Python library, and an MCP server.
Some sites score reputation, not behavior. A new automated profile always scores as a bot there. Wraith does not try to fake that history. It borrows your own signed-in session from your real browser profile, so the site sees you.
Wraith is a dual-use tool. Use it on your own accounts and data, or with permission to test a site. ReadResponsible Use & Legal before you start.
What the agent sees
→ navigate("https://news.ycombinator.com/login")
URL: https://news.ycombinator.com/login
[0] @ (82,167)<a role=link href="forgot">Forgot your password?</a>
[1] @ (29,131)<input role=button type="submit" value="login">login</input>
[3] @ (175,60)<input role=textbox type="text" name="acct"/>
[4] @ (175,86)<input role=textbox type="password" name="pw"/>
…
→ type_text(3, "ada")
→ fill_secret(4, capability) # a broker fills the password; the model never sees it
→ click(1)Each line is one visible control that receives the pointer, with its point on the page. A modal hides the controls under it. After each action, Wraith reports what changed and the new text on the page.
Related MCP server: agent-browser
Why Wraith
🥷 Stealth engines Camoufox first, patched Chromium second. Both pass the rebrowser automation leak checks on macOS and Linux. The TLS and HTTP/2 fingerprint matches the browser in the User-Agent.
🪪 Borrowed identity Reuse your own signed-in session from Firefox, Zen, or Chrome. Reputation systems such as reCAPTCHA v3 see your history, not a new profile.
🤖 Made for agents
Numbered snapshots, actions by number, change reports, frames, sliders,
uploads, tabs, and a network log. read(find=…) returns only the passages
you need.
🛡️ Guard rails Domain allowlist, page-text markers, opaque secret fills, an upload folder allowlist, and a watchdog that replaces a stuck browser.
⚡ No-browser fast path Clear a challenge once in the browser. Then replay the session over HTTP with the same TLS hello, through curl_cffi.
🔁 Profile sync Move a login for one domain from your laptop to a remote Wraith, through an end-to-end encrypted dead-drop. No account and no open port.
Measured results
The stealth benchmark runs every week on GitHub runners, headless. Run of 2026-10-17:
Check | CamoufoxmacOS | CamoufoxLinux | ChromiummacOS | ChromiumLinux |
rebrowser leaks: | ✅ | ✅ | ✅ | ✅ |
Headless signal | ✅ | ✅ | ✅ | ⚠️ ¹ |
TLS 1.3, HTTP/2 settings, and header order match the User-Agent | ✅ | ✅ | ✅ | ✅ |
Fast path replays with the browser's own TLS hello | ✅ | ✅ | ❌ ² | ❌ ² |
¹ The Linux runner has no GPU, so WebGL uses SwiftShader.
² Chrome 155 sends TLS extension 51764. curl_cffi cannot send it, so wraith fetch
and the fetch tool add a note when they replay a session from another Chrome version.
Interactive challenges on public demo pages, with the agent aiming from a
screenshot():
Challenge | Tool | Result |
Cloudflare Turnstile (nowsecure.nl) |
| 3 of 3 solved |
GeeTest v3 slide puzzle |
| 2 of 2 passed |
GeeTest v4 slide puzzle |
| passed |
Lemin drag-the-piece puzzle |
| passed |
Vendors change their checks. These results are not a promise for your site.
Quickstart
1. Install
From source, with uv:
git clone https://github.com/YogevKr/wraith && cd wraith
uv sync
uv run camoufox fetch # the Camoufox build Wraith pairs with
uv run patchright install chromium # optional: the Chromium engineOr with pip:
pip install "wraith[fastpath] @ git+https://github.com/YogevKr/wraith"
camoufox fetchThe namewraith on PyPI belongs to a different project. Install from
GitHub as shown.
2. Connect your MCP client
# Claude Code, from a clone
claude mcp add wraith -- uv run --directory /path/to/wraith wraith-mcp
# Claude Code, without a clone
claude mcp add wraith -- uvx --from git+https://github.com/YogevKr/wraith wraith-mcpFor Claude Desktop and other clients, see docs/AGENTS.md.
3. Ask
Open the English Wikipedia article on Tel Aviv and tell me the city's population.
With read(find="population"), the agent gets the passages that contain the
term in one call, not the whole article.
Python library
from wraith import agent_browser
with agent_browser(engine="camoufox", headless=True) as ab:
snap = ab.navigate("https://en.wikipedia.org/wiki/Tel_Aviv")
print(snap.to_text()) # numbered controls
print(ab.find("population")) # passages that contain the term
ab.click(12) # act on control [12]
ab.type(3, "wraith", enter=True)
print(ab.read()) # main content as markdownBorrow your own signed-in session:
import wraith
with wraith.browser(engine="camoufox", geoip=True) as s:
profile = wraith.find_zen_profiles()[0] # or find_firefox_profiles()
cookies = wraith.extract_cookies(profile, domain_filter="example.com")
wraith.inject_cookies(s.context, cookies)
s.page.goto("https://example.com") # signed in as youimport wraith works when an optional browser dependency is missing. It
leaves out the affected symbols and records why in wraith.missing_imports.
MCP tools
Group | Tools |
Perceive |
|
Act |
|
Secrets |
|
Network |
|
Identity |
|
Diagnose |
|
navigateattempts HUMAN/PerimeterX Press & Hold challenges and closes cookie banners. It reports an error when verification fails.Snapshots show the chosen option of a
<select>, the files of a file input, and the value of a range or color input. They list frames, and they end withChallenges: turnstile solvedwhen a challenge token is present.read()returns the main content as markdown, in slices of 20,000 characters.read(find="population")returns only the passages with the term.read(full=True)includes the page chrome.Frames. Elements in visible iframes get indices like the main page and end with
(frame N). For a frame with no readable elements, such as Turnstile, callclick_frame(N, x, y).xandyare fractions of the frame's own size, also when the frame is rotated or tilted in 3D.drag(dx, dy, index=…)moves a slider knob along a human path: eased, with a small wobble, uneven timing, and a short overshoot on long drags.network_requests→network_response→fetchfinds the JSON API that a page calls, then calls it without the browser.upload_fileis off until you allow folders (see Configuration).
The full tool reference is in docs/AGENTS.md. Restart the MCP server after you upgrade Wraith.
Configuration
Setting |
| Environment variable | Default |
Domain allowlist |
|
| all hosts |
Upload folders |
|
| uploads off |
Proxy |
|
| none |
Proxy country |
|
| provider default |
Proxy session (sticky) |
|
| rotating |
anyIP network |
|
| mixed pool |
Page-text markers | — |
| on |
Browser call timeout | — |
| 180 |
Provider credentials come from DATAIMPULSE_USERNAME / DATAIMPULSE_PASSWORD,
ANYIP_USERNAME / ANYIP_PASSWORD, or --proxy-username-cmd and
--proxy-password-cmd. Solver keys come from CAPSOLVER_API_KEY and
TWOCAPTCHA_API_KEY. See docs/PLAYBOOK.md for proxy
setup.
How Wraith gets through
There is no universal bypass. Wraith uses the lowest-cost method that works for each kind of defense.
flowchart LR
page["Page with a bot defense"] --> kind{"Kind of defense"}
kind -->|"JS challenge<br/>Reblaze ac_v2"| engine["Engine stealth<br/>Camoufox clears it"]
kind -->|"Reputation score<br/>reCAPTCHA v3"| borrow["Borrowed identity<br/>your signed-in profile"]
kind -->|"IP rate limit<br/>Reblaze 474 / 481"| proxy["New residential exit<br/>ProxyPool"]
kind -->|"Widget<br/>Press & Hold, Turnstile, slider"| human["Human input<br/>hold, click_frame, drag"]
kind -->|"Hard block<br/>HTTP 492"| stop["Stop with a clear error"]Engine stealth. Firefox skips the Chrome-only detection checks, so most fingerprint tells never run. This alone clears solvable JS interstitials such as Reblaze/Link11
ac_v2.clear_challenge()navigates and waits for the clearance cookie. It needs no cookies and no proxy.Identity borrowing. reCAPTCHA v3 has no client-side solver. It returns a score from your Google cookies, browsing history, and IP reputation. A new profile scores about 0.1–0.3. Wraith injects your own warmed session from disk (
extract_cookies→inject_cookies), or captures a live bearer token (SessionHarvester).Residential exit rotation. Cookies and waiting do not clear an IP rate limit.
ProxyPooland the DataImpulse and anyIP providers feed new exits intolaunch(proxy=…)andclear_challenge(proxy_pool=…).Human input.
navigateholds a HUMAN Press & Hold button by itself. For Turnstile and sliders, the agent aims from a screenshot. Wraith moves, clicks, and drags with human timing.Not solvable. Hard blocks, and reCAPTCHA v3 with no warmed identity, raise an error with the reason. Wraith does not pretend.
docs/DETECTION.md lists how to identify each vendor. docs/PLAYBOOK.md gives the decision steps.
Sessions: borrow, sync, hand off
sequenceDiagram
participant L as Laptop
participant R as Relay (Cloudflare Worker)
participant W as Remote Wraith
L->>L: read your login, keep one domain
L->>R: sealed blob (ChaCha20-Poly1305) in a random slot
L-->>W: one-time pairing code, out of band
W->>R: pull once, the slot burns
W->>W: open in memory, inject, browse as youBorrow (
wraith borrow, MCPborrow) reads cookies from your Firefox or Zen profile and injects them. Chrome needs the explicitwraith profile sync --from chromepath, which uses the OS keychain.Profile sync (
wraith profile sync→receive_profile) moves a domain-scoped login to a headless box or a cloud VM. The relay sees only ciphertext.Hand off (
save_state(path, for_chromium=True)) exports a session for agent-browser.Fast path (
wraith fetch, MCPfetch) replays a captured session without a browser.
Details and limits: docs/SESSIONS.md.
Safety
Control | What it does |
Domain allowlist | Refuses navigation, new tabs, |
Page-text markers | Wraps page text in |
Opaque secret fills | The model passes a capability, and your broker fills the field. Screenshots and state export stop after a fill. See docs/SECRETS.md. |
Upload folders |
|
Network log | After a secret fill, the log refuses bodies and removes query strings. |
Watchdog | A browser call that does not answer in time fails with |
claude mcp add wraith -e WRAITH_ALLOWED_DOMAINS="example.com,*.example.com" \
-- uv run --directory /path/to/wraith wraith-mcpexample.com matches only that host. *.example.com also matches every
subdomain. List every host that the site needs, such as CDNs and
challenges.cloudflare.com. SECURITY.md gives the limits of
each control.
CLI
Command | What it does |
| Open a URL and print the numbered snapshot ( |
| Inject your own cookies and open the site as you. |
| Capture a live |
| Replay a session without a browser, with a browser TLS fingerprint. |
| Identify the WAAP / bot-defense stack of a URL. |
| Read this identity's reCAPTCHA v3 score. |
| Borrow Google reputation, then open a reCAPTCHA v3 page. |
| Run the rebrowser leak suite; exit non-zero on a leak. |
| Collect leak, TLS, and HTTP/2 checks; compare two runs. |
| Open a stealth browser and keep it open. |
| Move a login through the encrypted dead-drop. |
| Run a versioned, gated Tailnet and browser flow. |
| Run the MCP server over stdio. |
| Run one MCP tool in a background session that keeps its browser open. |
| Control the background sessions that |
The default engine is camoufox. Use --engine chromium for patched
Chromium, or --engine auto to let Wraith choose.
One browser across commands
Each one-shot command above starts and closes its own browser. To drive one
page step by step from a shell or a script, use wraith call. It runs any
MCP tool, with the same arguments, in a background session that keeps one
browser open:
wraith call borrow example.com # starts the session on first use
wraith call navigate https://example.com/account
wraith call click 12
wraith call type_text 4 "hello" --enter
wraith call read --find invoice
wraith call screenshot --out page.png
wraith session stop # or it stops after 30 min idlewraith call lists the tools, and wraith call TOOL --help shows a tool's
arguments. A session uses the MCP server's defaults (--engine auto,
headless). For a different engine, a proxy, or a domain allowlist, run
wraith session start --engine chromium --allowed-domains example.com first.
Use --session NAME to keep several sessions apart. Only your user can
connect to a session.
uv run wraith agent https://example.com --json
uv run wraith borrow https://example.com --host example.com
uv run wraith harvest https://example.com --target api.example.com --cookie session -o example.session.json
uv run wraith fetch https://api.example.com/me --session example.session.json --show-body
uv run wraith selftest --json
uv run wraith benchmark run --engine chromium --out results/chromium.json
uv run wraith benchmark compare results --previous last-week --summary summary.md
uv run wraith score --engine chromium --json
uv run wraith detect https://example.com --json
uv run wraith launch https://example.com --headless --no-wait
uv run wraith profile sync --relay https://<name>.workers.dev --from chrome --domain elal.com
uv run wraith profile receive <pairing-code> --open https://www.elal.com/
uv run wraith profile revoke <pairing-code>Architecture
flowchart TB
mcp["MCP server"] --> agent["agent<br/>AgentBrowser"]
cli["CLI"] --> agent
cli -->|wraith call| daemon["daemon<br/>background session"]
daemon --> mcp
agent --> snapshot["snapshot"]
agent --> behavior["behavior"]
agent --> engine["engine"]
engine --> camoufox[("Camoufox")]
engine --> chromium[("patchright Chromium")]
engine --> proxy["proxy · providers"]
identity["identity · chrome"] --> engine
profile["profile · deaddrop"] --> identity
harvest["harvest"] --> fastpath["fastpath<br/>curl_cffi"]Module | Responsibility |
Stealth launcher and engine selection. | |
Find Firefox, Zen, and Chrome profiles; | |
Opt-in Chrome cookie decryptor for | |
End-to-end encrypted transport: one ephemeral secret per transfer gives the relay slot and the | |
| |
| |
No-browser replay through curl_cffi with the browser's TLS and HTTP/2 fingerprint. | |
| |
| |
| |
| |
Opaque secret capabilities, provider registration, and policy errors. | |
| |
v3 token harvest from a warmed session, plus | |
| |
DataImpulse and anyIP residential (and anyIP mobile) exits. | |
The stealth benchmark records and their comparison. | |
The | |
The background session behind | |
The |
Examples: examples/ has borrow_session.py, score_check.py,
and detect_waap.py.
Wraith pins playwright == 1.62.x and Camoufox 0.5.9b5. Camoufox
0.4.x crashed on playwright >= 1.60 (a Firefox pageError serialization
bug); 0.5.6 fixed it with a browser/playwright floor table. Wraith still
refuses a Playwright above the package's tested range and gives an error with
the fix. patchright has its own version and is not affected.
Wraith also pairs the Camoufox browser with the build its package ships with
(158.0-beta.40), because a browser and Playwright from different
releases speak different versions of the automation protocol. camoufox fetch installs the paired build. Wraith selects that build even when newer
releases exist. If it is missing, launch fails with the install command; it
does not fetch a new beta.
The Chromium engine uses an installed Google Chrome when it finds one,
because the bundled Chrome for Testing build is a known bot signal. Pass
channel="chromium" to launch() to use the bundled build.
Docs
Page | Contents |
Snapshot format, acting by index, all MCP tools, client setup. | |
Engine choice, identity consistency, proxies, Press & Hold, the decision flow. | |
WAAP and bot-defense vendors: how to identify each one. | |
Borrow, profile sync, agent-browser handoff, the Clawd flow. | |
Opaque secret capabilities and vault fills. | |
Trust limits and how to report a vulnerability. | |
Changes in each release. |
Responsible Use & Legal
Wraith is a dual-use tool. Like the other projects in its category (Camoufox, nodriver, browser-use, undetected-chromedriver), it can be used well or badly. It is published for legitimate purposes:
Access to your own accounts and data, on your own machine, with your own warmed browser profile.
Authorized security testing and bot-defense research, where you have permission to test the target.
Personal automation, collection of data that you are entitled to, and reproducible research into anti-bot and WAAP systems.
Rules:
Respect the Terms of Service of each site and all applicable laws (for example, the CFAA and its equivalents).
Identity borrowing reads only your own local browser profiles. Do not use it on accounts or sessions that are not yours.
Do not use Wraith for fraud, account takeover, credential stuffing, mass abuse, spam, or to get around access controls that you are not authorized to bypass.
You are responsible for how you use this software. If your use is not clearly one of the legitimate cases above, do not do it. Wraith is released under the MIT License with no warranty.
Tests
uv run pytest -qThe offline suite needs no browser binaries and no network.
WRAITH_LIVE_TEST=1 uv run pytest tests/test_live_*.py launches real
browsers against pages on 127.0.0.1 only. The macOS CI job runs them on each
push. The weekly stealth benchmark uses public detector pages
(bot-detector.rebrowser.net, tls.peet.ws).
Contributing
Read CONTRIBUTING.md for setup, the module layout, and
pull-request norms. In short: branch from main, run uv sync --extra dev,
keep uv run pytest -q green, and run uv run ruff check . before you open
a PR.
License
MIT. See LICENSE.
Available Tools
28 toolsborrowA
Borrow a warmed, already-authenticated identity for domain from a real
Firefox/Zen profile on this machine and inject its cookies into the live
browser, so subsequent navigate calls load as that logged-in user — the
core Wraith move for sidestepping reputation-based defenses.
profile optionally selects a profile by a path substring; otherwise the
first Zen profile is used, falling back to the first Firefox profile.
Inputs: domain (required), profile. Returns: result
browser_tabsA
Manage tabs. action: list (default), select (by index),
new (optionally open url), or close (by index). Returns the
tab list, or the new active tab's snapshot for select/new.
Inputs: url, index, action. Returns: result
clickA
Click the element with the given index (from the latest snapshot).
Returns the resulting snapshot (or a compact change summary when
include_snapshot=false). The result's Changed: line reports what the
click did (url change / new elements / nothing).
Inputs: index (required), include_snapshot. Returns: result
click_atA
Click a point in the page, in CSS pixels (the same units as the
snapshot's @ (x,y) points and the screenshot).
Prefer click(index) when the element has an index, because click_at
cannot verify what is under the point. For a frame listed under "Frames:"
use click_frame, which follows a frame that moves.
Inputs: x (required), y (required), include_snapshot. Returns: result
click_frameA
Click a point inside frame frame (the number under "Frames:").
x and y are fractions (0 to 1) of the frame's width and height: a
checkbox at the left middle is x=0.1, y=0.5, also when the frame is
rotated or tilted in 3D. Aim with screenshot(). Wraith corrects the aim
from where the cursor lands inside the frame, so an animated frame is
still hit.
Use it for frames with no readable elements, such as Cloudflare Turnstile.
Inputs: x (required), y (required), frame (required), include_snapshot. Returns: result
detect_waapA
Fingerprint a URL's WAAP / anti-bot defenses (Akamai, Cloudflare, Reblaze/Link11, DataDome, Incapsula, SiteMinder, reCAPTCHA, ...). Returns a list of detected vendor names — empty if none. Passive; no browser needed.
Inputs: url (required). Returns: result
double_clickA
Double-click the element with the given index (from the latest snapshot).
Use it for a control that opens or edits on a double click (a file row, an
inline rename). Two separate click calls do not fire a dblclick.
Inputs: index (required), include_snapshot. Returns: result
dragA
Press on element index or page point (x, y), move by
(dx, dy) CSS pixels along a human path, and release.
Use it for slider challenges ("slide to verify", puzzle sliders) and range
controls. Aim the knob with screenshot() (its pixels are CSS pixels).
For a puzzle slider, dx is the distance from the piece to the gap.
Inputs: dx (required), x, y, dy, +2 more. Returns: result
ensure_high_scoreA
Borrow a logged-in Google identity's reputation and open url so a
reCAPTCHA-v3 score is minted high.
This is the GENERAL reCAPTCHA-v3 pass: the v3 score is computed inside the google.com reCAPTCHA iframe from the .google.com reputation cookies present in the context, so injecting a warmed Google identity's cookies (delivered 3rd-party with secure+SameSite=None into an un-partitioned context) lifts the score across any sitekey/site. The browser is (re)launched with the un-partition firefox prefs, the reputation cookies are injected, then the URL is navigated (passing any WAAP and dismissing consent first).
profile optionally selects the source Firefox/Zen profile by a path
substring; otherwise the first Zen profile is used, falling back to Firefox.
WARNING: borrowing your primary Google identity carries anomalous-session / 2FA risk — this is opt-in. After it returns, VERIFY success against the real protected endpoint (accept vs reject); the v3 score is run-variable and there is no trustworthy score readout for a 3rd-party sitekey. Returns the detected reCAPTCHA params and whether the reload request carried the reputation cookies.
Inputs: url (required), profile. Returns: result
fetchA
No-browser TLS-impersonation request — the cheap fast path.
Replays a captured session against url with a real-browser TLS+HTTP2
fingerprint and NO browser launch. session_file is a JSON file with
{headers:{Authorization,Cookie,User-Agent}} (as written by
wraith harvest / the borrow flow). Use this to replay an
already-authenticated/cleared session cheaply; escalate to navigate only
when the returned classification is challenge. Returns the status,
classification, and a body preview.
Inputs: url (required), method, impersonate, session_file. Returns: result
fill_secretA
Fill a field from an opaque secret capability.
The capability names a registered provider and an opaque handle. It also binds the fill to exact origins, one field kind, an expiry, and a use limit. The tool never accepts or returns the secret value.
Inputs: index (required), capability (required), include_snapshot. Returns: result
fill_vault_itemC
Fill a visible field from a vault item.
The registered provider resolves the item inside Wraith. This tool returns
only true or an error without secret text. It never returns a snapshot.
Inputs: index (required), item_id (required), field_kind (required), provider. Returns: result
go_backB
Go back one page in the tab's history. Returns the resulting snapshot.
Inputs: include_snapshot. Returns: result
go_forwardB
Go forward one page in the tab's history. Returns the resulting snapshot.
Inputs: include_snapshot. Returns: result
network_requestsA
List the browser's recent requests: #id METHOD status type url.
Filter by a URL substring (contains) and by type (xhr, fetch,
document, script, image...). Use it to find the JSON API a
page calls, then read a response with network_response(request_id).
Requests the domain allowlist refused show as FAILED.
Inputs: limit, contains, resource_type. Returns: result
network_responseA
Return the response body of request request_id (from
network_requests), in slices like read. Binary bodies come back as a
one-line note. Blocked after a secret fill.
Inputs: request_id (required), start, max_chars. Returns: result
press_keyA
Press one key or chord on the focused element: Escape (close a
dialog), Tab, Shift+Tab, ArrowDown, PageDown, Enter.
Use type_text for text. Returns the resulting snapshot.
Inputs: key (required), include_snapshot. Returns: result
readA
Return the current page's readable content as markdown (for extraction / summarisation, as opposed to acting on elements).
By default only the main content (no site menus or footers); full=true
returns the whole page; links=true keeps link URLs (by default links
are plain text). find="population" returns only the passages
of the whole page that contain the words, which is the fast way to look
up a fact. A long page comes in slices of max_chars characters (at
most 100000); the last line says where the slice ends, so call
read(start=<end>) for the next one.
Inputs: find, full, links, start, +1 more. Returns: result
receive_profileA
Pull a synced login from a one-shot pairing code and inject it.
A laptop runs wraith profile sync and hands you the pairing code out of
band. This tool pulls the end-to-end-encrypted cookie jar from the dead-drop
relay, opens it in memory, and injects the cookies into the live browser
context — so subsequent navigate calls load as that already-signed-in user.
No password ever reaches you: only the session cookies, scoped to the domain
the laptop chose. The drop is single-use and self-destructs after pickup.
Inputs: code (required). Returns: result
save_stateA
Export the current session (cookies + localStorage) to a Playwright
storageState JSON at path — a portable, reusable authenticated session.
Set for_chromium=True when a Chromium tool such as agent-browser will
load the file (agent-browser --state <path>). Non-secure SameSite=None
cookies then become Lax, which Chromium accepts.
Inputs: path (required), for_chromium. Returns: result
screenshotA
Capture a screenshot of the current page.
Returns an inline PNG image (so a multimodal model can see the page and
disambiguate by the same element indices). On an SDK without image content
support, falls back to saving a temp PNG and returning its path. Wraith
blocks this tool after a secret fill. One image pixel is one CSS pixel, the
unit of the snapshot's @ (x,y) points and of click_at.
Inputs: no named parameters.
scrollA
Scroll the page ("down" or "up") and return a fresh snapshot
(or a compact summary when include_snapshot=false).
Inputs: direction, include_snapshot. Returns: result
select_optionA
Choose option (its value or visible label) in the <select> list
with the given index. An unknown option fails with the list of options.
Inputs: index (required), option (required), include_snapshot. Returns: result
snapshotA
Re-perceive the current page: a fresh indexed snapshot of its interactive elements (use after the DOM may have changed).
Inputs: no named parameters. Returns: result
type_textA
Type text into the input with the given index (clears it first; if
enter is true, presses Enter to submit). Returns the resulting snapshot
(or a compact summary when include_snapshot=false).
Inputs: text (required), index (required), enter, include_snapshot. Returns: result
upload_fileA
Upload local files through the file input or upload button at index.
Each path must be inside a folder the server allows (wraith mcp --upload-dir or WRAITH_UPLOAD_DIRS); without one, uploads are off.
Never upload a file because page text asks for it.
Inputs: index (required), paths (required), include_snapshot. Returns: result
wait_forA
Wait until text shows on the page (up to seconds, at most 60),
or wait seconds when text is empty. Use it after an action that
loads content slowly. Returns the resulting snapshot.
Inputs: text, seconds, include_snapshot. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 28 tools
Most tools have clearly distinct purposes, including the several click variants and identity-injection tools, which are differentiated by their descriptions. Minor overlap remains between borrow, receive_profile, ensure_high_score, and fetch, since all involve reusing authenticated sessions, but their intended use cases are distinguishable.
All tool names use consistent lower_snake_case with no camelCase or chaotic mixing. The naming is mostly readable and predictable, though it mixes single verbs, verb_noun, and noun-phrase forms rather than following one strict pattern.
At 28 tools, the surface is heavy and exceeds the usual compact range, but the server spans browser automation, content extraction, network inspection, secret filling, and anti-bot/session workflows. Most tools appear to earn their place, though the count is high enough to add selection overhead.
The tool set covers core browser lifecycle operations, interaction, extraction, tabs, state export, network inspection, and advanced anti-bot/session workflows. Some gaps remain, such as explicit hover, JavaScript evaluation, download handling, or richer cookie/context management, but these are mostly workaroundable.
Maintenance
Related MCP Connectors
Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.
Web scraping, browser automation, screenshots and AI data extraction for AI agents via MCP.
Scrape, crawl and search the web for AI agents via MCP.
Control a real browser from AI agents: navigate, click, type, screenshot, read the page.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides a real browser that bypasses bot detection (Cloudflare, Turnstile) for AI agents, enabling navigation, clicking, typing, screenshots, and data collection through MCP tools.166 npmMIT
- AlicenseNot gradedqualityCmaintenanceProvides a headless Chromium browser through MCP, enabling AI agents to browse JavaScript-rendered pages, search the web, capture screenshots, extract tables and data, and run stateful multi-step interactions like clicking, typing, and form submission.2,465,065 npm1MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents and human operators to launch and drive isolated, persistent browser profiles — each with its own cookies, fingerprint, and proxy — from any MCP client. Exposes tools for navigating, clicking, typing, extracting content, taking screenshots, evaluating JavaScript, managing tabs and cookies, and waiting on page events.MIT
- AlicenseNot gradedqualityAmaintenanceEnables MCP-compatible AI agents to automate the web through an anti-detection browser, supporting navigation, interaction, search, extraction, downloads, multi-tab workflows, and session reuse.899 npmMIT