Back to Directory/Testing & Quality

io.github.devinwang/cloak-browser-mcp

Playwright-compatible MCP server on CloakBrowser stealth Chromium: 86 tools, humanized input.

Testing & QualityTypeScriptv0.2.0

cloak-browser-mcp

A Model Context Protocol (MCP) server backed by CloakHQ/CloakBrowser — a source-patched Chromium that passes Cloudflare Turnstile, reCAPTCHA v3, FingerprintJS, BrowserScan, and 30+ other bot detection services without runtime JS injection.

Drop-in replacement for @playwright/mcp with 86 tools: every Playwright MCP tool except browser_annotate (see Not implemented), plus a Cloak-exclusive stealth/profile/audit layer.

Works with Claude Code, Cursor, VS Code, Codex, Gemini CLI, Windsurf, or any MCP client.


Table of contents


Why CloakBrowser over vanilla Playwright?

@playwright/mcpcloak-browser-mcp
ChromiumStockSource-patched (58 C++ patches)
navigator.webdrivertrue (leaks)absent
Cloudflare TurnstileFailsAuto-pass
reCAPTCHA v3 score~0.1~0.9
Humanized mouse / keyboardNoneBézier curves, typo correction
Persistent profilesManualFirst-class CLI flag + management tools
GeoIP-aware emulationNoneAuto timezone/locale from proxy exit IP
Stealth audit / detection probeNoneBuilt-in cloak_stealth_audit + cloak_detection_test

When you don't need stealth, @playwright/mcp is faster and lighter — use that. When the site has any bot detection (Cloudflare, DataDome, PerimeterX, FingerprintJS) — use this.


Quick start

1. Install once

The wrapper installs from npm; the CloakBrowser Chromium binary (~200 MB) downloads on first use into ~/.cloakbrowser/.

Requires Node.js ^20.19.0 || >=22.12.0 (the minimum CloakBrowser itself needs).

The binary comes in two tiers. Without a key you get the free binary. Set CLOAKBROWSER_LICENSE_KEY in the MCP server's environment to use a CloakBrowser Pro license; CLOAKBROWSER_RELEASE_CHANNEL (stable or preview) and CLOAKBROWSER_VERSION are read by the CloakBrowser library too. See cloakbrowser.dev for what each tier includes. cloak_binary_info reports the active tier.

npm install -g @devinwangd/cloak-browser-mcp

Or run on demand without installing:

npx @devinwangd/cloak-browser-mcp --caps all

After install, the binary on PATH is cloak-browser-mcp (unscoped) — that's what you reference in MCP client configs below.

2. Wire into your MCP client

Claude Code (~/.claude.json or project .mcp.json)
{
  "mcpServers": {
    "cloak-browser": {
      "command": "cloak-browser-mcp",
      "args": ["--caps", "all"]
    }
  }
}
Cursor / VS Code (.cursor/mcp.json or .vscode/mcp.json)
{
  "servers": {
    "cloak-browser": {
      "command": "cloak-browser-mcp",
      "args": ["--caps", "all"]
    }
  }
}
Persistent profile + proxy + humanized inputs
{
  "mcpServers": {
    "cloak-browser": {
      "command": "cloak-browser-mcp",
      "args": [
        "--caps", "all",
        "--profile-dir", "/Users/me/.cloak-browser-mcp/profiles/work",
        "--proxy", "http://user:pass@proxy.example.com:8080",
        "--timezone", "Europe/London",
        "--locale", "en-GB",
        "--geoip",
        "--humanize",
        "--viewport", "1920x1080",
        "--allowed-domains", "*.example.com,*.cloudflare.com"
      ]
    }
  }
}

3. Use it

In Claude Code:

"Open example.com, click the search box, search for 'hello', take a screenshot."

The agent will call browser_navigate → browser_snapshot → browser_click → browser_type → browser_take_screenshot.


Capabilities (--caps)

CapToolsUse when
(always)navigation, interaction, page stateStandard browsing
networkrequest inspection, route mocking, offline simulationDebugging APIs, testing failure modes
storagecookies, localStorage, sessionStorage, storage state export/importAuth state persistence, session replay
visionpixel-coordinate mouseBypassing accessibility tree for canvas / SVG apps
pdfbrowser_pdf_saveSnapshotting pages as PDF
testingverify_* + generate_locatorCodegen for Playwright tests
devtoolshighlight, tracing, video, resumeDebugging agent decisions
configget_config, close, run_code_unsafeIntrospection + (with --enable-unsafe-eval) arbitrary JS
humanizecloak_humanize_setTuning humanized input parameters

--caps all enables everything (except run_code_unsafe, which additionally requires --enable-unsafe-eval).


CloakBrowser-exclusive tools (always on)

ToolPurpose
cloak_set_fingerprintOverride canvas seed, GPU vendor/renderer, screen size, hardware concurrency, device memory, UA brand, platform, storage quota
cloak_set_timezoneLive timezone via CDP (no relaunch)
cloak_set_localeOverride navigator.language and Accept-Language
cloak_set_geolocationSet coords, or auto-resolve from proxy exit IP
cloak_set_proxySwitch proxy mid-session
cloak_detection_testLoad a known probe (CreepJS, FingerprintJS, BrowserScan, SannySoft, Cloudflare Turnstile) and dump results
cloak_stealth_auditProgrammatic check: navigator.webdriver, plugin count, WebGL vendor, languages, UA, chrome.runtime, canvas hash, $cdc_* CDP signals
cloak_request_signal_inspectCapture per-request TLS / header signals for a single URL
cloak_persistent_profile_create / list / deleteManage ~/.cloak-browser-mcp/profiles/
cloak_binary_info / cloak_binary_updateInspect / refresh the CloakBrowser Chromium binary

CLI flags

FlagValueDefaultNotes
--caps <csv>all or any subset(none)Enables capability-gated tools
--profile-dir <path>Absolute path(ephemeral)Persistent user-data dir
--headless / --headed(boolean)headed (visible)Pass --headless for batch/CI runs.
--proxy <url>http(s)/socks5 with inline authnone
--timezone <tz>IANA tzsysteme.g. America/New_York
--locale <bcp47>BCP-47systeme.g. en-US
--user-agent <ua>string(cloak default)
--viewport <WxH>e.g. 1920x10801280×720
--geoipbooleanoffAuto resolve geolocation from proxy IP
--humanizebooleanoffEnable Bézier mouse + typo-correcting keyboard
--fingerprint-seed <int>intrandomDeterministic canvas/WebGL noise
--allowed-domains <csv>host patterns(open)Whitelist for browser_navigate
--blocked-domains <csv>host patterns(none)Blocklist for browser_navigate
--enable-unsafe-evalbooleanoffRequired for browser_run_code_unsafe
--upload-allow-dir <path>path(none)Restrict file-upload source paths
--download-dir <path>path(cwd)Where downloaded files land
--max-pages <n>int20Concurrent tab cap
--self-testbooleanoffPrint the tool list and exit

Tool inventory

Tools are grouped by capability. The "always-on" sections are exposed regardless of --caps; capability-gated sections require the matching --caps entry.

Always-on

Navigation
ToolRequiredOptionalNotes
browser_navigateurlwaitUntil, timeoutMsSubject to --allowed-domains / --blocked-domains. Returns a fresh [eN] snapshot.
browser_navigate_back——History back in the active tab.
browser_tabsaction (list/new/switch/close)index, id, urlManage tabs by id (t1,…) or 0-based index.
Interaction
ToolRequiredOptionalNotes
browser_clicktargetelement, doubleClick, button, modifierstarget is a eN ref or a Playwright selector.
browser_typetarget, textelement, submit, slowlyslowly:true triggers per-character typing; combine with --humanize.
browser_hovertargetelement
browser_dragstartTarget, endTargetstartElement, endElement
browser_droptargetpaths, dataFile paths via setInputFiles; arbitrary MIME data via synthetic DataTransfer.
browser_select_optiontarget, valueselement
browser_press_keykey—Page-level key press (e.g. Control+A, ArrowDown).
browser_handle_dialogacceptpromptTextResponds to the most recently captured dialog.
browser_file_uploadpaths—Paths constrained by --upload-allow-dir if set.
browser_fill_formfields—Each field has target + value (+ optional kind).
browser_scroll—target, direction, amountElement-scoped or page-level.
Page state
ToolRequiredOptionalNotes
browser_snapshot——Accessibility tree with [eN] refs for interactable nodes.
browser_findtext or regexfilenameSearches the snapshot instead of returning all of it. Each match is shown under its path from the root with a few lines of context, up to 20 matches. regex is case-sensitive unless written as /pattern/i.
browser_emulate_media—colorScheme, reducedMotion, forcedColors, contrast, mediaOmitted parameters are left unchanged; null clears an override back to the system setting.
browser_take_screenshot—element, target, type, fullPage, quality, saveAsImage is returned inline; optionally saved to disk.
browser_console_messages—level, limitBuffered console + pageerror.
browser_wait_for—timeMs, text, textGone, selector, state, timeoutMs
browser_resizewidth, height—
browser_evaluatefunctionelement, targetFunction source must be an arrow or function expression.
CloakBrowser-exclusive
ToolRequiredOptionalNotes
cloak_set_fingerprint—seed, gpuVendor, gpuRenderer, screenWidth, screenHeight, hardwareConcurrency, deviceMemoryGB, uaBrand, uaBrandVersion, platform, storageQuotaMBSome flags only take effect on next launch — call browser_close then any tool to relaunch.
cloak_set_timezonetimezone—Live via CDP.
cloak_set_localelocale—Sets navigator.language + Accept-Language header.
cloak_set_geolocation—latitude, longitude, accuracy, fromProxyIpfromProxyIp calls ipapi.co/json/ via current proxy.
cloak_set_proxyproxy—Recreates the context.
cloak_detection_test—suite, customUrlSuites: creepjs, fingerprintjs, browserscan, sannysoft, cloudflare-turnstile.
cloak_stealth_audit——Programmatic audit.
cloak_request_signal_inspecturl—Returns TLS details, response status, request headers, response headers.
cloak_persistent_profile_createname—Creates ~/.cloak-browser-mcp/profiles/<name>.
cloak_persistent_profile_list——
cloak_persistent_profile_deletename, confirm=true—
cloak_binary_info——
cloak_binary_update——

Capability-gated

--caps network — browser_network_requests, browser_network_request, browser_route, browser_route_list, browser_unroute, browser_network_state_set.

--caps storage — browser_cookie_set/get/list/delete/clear, browser_localstorage_*, browser_sessionstorage_*, browser_storage_state, browser_set_storage_state.

--caps vision — browser_mouse_click_xy, browser_mouse_move_xy, browser_mouse_drag_xy, browser_mouse_down, browser_mouse_up, browser_mouse_wheel.

--caps pdf — browser_pdf_save.

--caps testing — browser_verify_element_visible, browser_verify_text_visible, browser_verify_list_visible, browser_verify_value, browser_generate_locator.

--caps devtools — browser_highlight, browser_hide_highlight, browser_start_tracing, browser_stop_tracing, browser_start_video, browser_stop_video, browser_video_chapter, browser_resume, browser_video_show_actions, browser_video_hide_actions, browser_start_recording, browser_stop_recording.

--caps config — browser_get_config, browser_close, browser_run_code_unsafe (also needs --enable-unsafe-eval).

--caps humanize — cloak_humanize_set.

Not implemented

browser_annotate from Playwright MCP is not provided. It opens Playwright's dashboard window and waits for a person to draw on the page, and Playwright runs that as an internal process that this server does not launch.


Target syntax for interaction tools

The target argument accepts:

  • eN ref from a prior browser_snapshot — e.g. e7. Most reliable.
  • CSS selector — e.g. button.primary.
  • xpath=… — e.g. xpath=//button[contains(., "Submit")].
  • text=… — e.g. text=Sign in.
  • role=…[name="…"] — e.g. role=button[name="Submit"].

After any navigation or significant DOM mutation, call browser_snapshot again to refresh refs.


Example flows

1. Take a screenshot of a Cloudflare-protected page

You: Open https://example-cloudflare-protected.com, wait for the page to settle, take a full-page screenshot.

Agent calls:
  browser_navigate(url="https://...")
  browser_wait_for(textGone="Checking your browser")
  browser_take_screenshot(fullPage=true)

Vanilla @playwright/mcp fails the Turnstile check; cloak-browser-mcp passes it automatically because the stealth patches are below the JS layer.

2. Sign into a SaaS dashboard, persist auth, reopen later

Phase 1 — initial sign-in with a fresh profile:

// .mcp.json
{
  "mcpServers": {
    "cloak": {
      "command": "cloak-browser-mcp",
      "args": [
        "--caps", "all",
        "--profile-dir", "/Users/me/.cloak-browser-mcp/profiles/saas-prod",
        "--humanize"
      ]
    }
  }
}
You: Open https://saas.example.com, sign in as me@example.com / <password>, then confirm I'm on the dashboard.

Phase 2 — reopen later, all cookies still present:

You: Open https://saas.example.com — you should already be signed in from yesterday's session.

3. Probe how stealth is doing

You: Run a stealth audit and then load the SannySoft bot detection test.

Agent:
  cloak_stealth_audit()
  cloak_detection_test(suite="sannysoft")

You'll see all green if stealth is intact.

4. Switch geolocation/timezone mid-session via proxy

You: Switch to a UK proxy, align my timezone/locale/geo to match, then load a country-specific landing page.

Agent:
  cloak_set_proxy(proxy="http://uk-proxy.example.com:8080")
  cloak_set_timezone(timezone="Europe/London")
  cloak_set_locale(locale="en-GB")
  cloak_set_geolocation(fromProxyIp=true)
  browser_navigate(url="https://example.com/uk")

5. Mock an API response while testing a frontend

You: While loading example.com, return a fake 500 to /api/orders so I can verify the error state.

Agent:
  browser_route(pattern="**/api/orders", status=500, body='{"error":"simulated"}', contentType="application/json")
  browser_navigate(url="https://example.com")
  browser_take_screenshot()
  browser_unroute(pattern="**/api/orders")

6. Export storage state, replay in a fresh session

Agent:
  browser_storage_state(filename="/tmp/saas-state.json")
  # …later, in a new ephemeral session…
  browser_set_storage_state(filename="/tmp/saas-state.json")
  browser_navigate(url="https://saas.example.com")

7. Run a Playwright trace for human review

You: Trace this whole flow so I can replay it in Playwright Trace Viewer.

Agent:
  browser_start_tracing(filename="/tmp/trace.zip", screenshots=true, snapshots=true)
  # …agent runs the flow…
  browser_stop_tracing()

You: open /tmp/trace.zip in Playwright Trace Viewer (https://trace.playwright.dev)

Security model

Read this before deploying on any machine that has production credentials.

TL;DR

AssetTrust boundary
cloak-browser-mcp source (this repo)MIT, public, audit by reading.
cloakbrowser npm packageTrust the CloakHQ maintainers + npm registry.
CloakBrowser Chromium binaryDownloaded on first use from cloakbrowser.dev. SHA-256 verified by upstream wrapper. The binary is closed-source by license.
Your env vars / Keychain / shell historyThe MCP server inherits your process env. Do not run with prod credentials in scope unless you trust the supply chain.

Threats this package introduces

1. Supply-chain compromise

Three packages are pulled at install/run time: @modelcontextprotocol/sdk, playwright-core, and cloakbrowser + its downloaded Chromium binary. If CloakHQ's npm publish token or cloakbrowser.dev is compromised, an attacker could push a malicious binary that runs under your user account.

Mitigations:

  • Pin a known-good cloakbrowser version.
  • Set CLOAKBROWSER_BINARY_PATH to an audited binary.
  • Leave CLOAKBROWSER_SKIP_CHECKSUM at default (false).
  • Audit ~/.cloakbrowser/ and any --profile-dir you use.
2. Agent-driven browser navigation

By default browser_navigate accepts any URL. An LLM agent can be prompt-injected into navigating somewhere malicious.

Mitigations:

  • --allowed-domains <csv> (supports *.example.com).
  • --blocked-domains <csv> (checked first).
  • Use a dedicated ephemeral --profile-dir, not your real browser profile.
  • --max-pages <n> caps tab explosion.
3. Arbitrary JS execution
  • browser_evaluate — runs JS in the page sandbox. Cannot read your local filesystem. Always available.
  • browser_run_code_unsafe — runs JS in this Node.js server process. Can do anything Node can. Double-opt-in: needs --caps config AND --enable-unsafe-eval.

Mitigation: never combine --enable-unsafe-eval with a machine that has prod credentials in env vars.

4. File system reach

browser_file_upload and browser_drop can attach any file you have read access to. Use --upload-allow-dir <path> to restrict.

Write-side: browser_take_screenshot --saveAs, browser_pdf_save, browser_storage_state, browser_start_tracing write files at agent-chosen paths. If you don't want this, omit --caps pdf / storage / devtools.

5. Persistent profile leakage

A --profile-dir accumulates cookies/localStorage/IndexedDB. If synced to cloud storage, every site you've signed into via the agent becomes accessible to anyone with that sync token. Default path ~/.cloak-browser-mcp/profiles/<name> lives outside common cloud-sync roots.

6. Prompt-injection-driven exfil

A malicious page can prompt-inject the agent into navigating elsewhere with stolen state, or POST DOM secrets out. This is an LLM problem, not an MCP problem.

  • Use a separate session per task — browser_close between unrelated jobs.
  • Prefer ephemeral over persistent profiles for sensitive flows.
  • Review agent tool calls when the task touches anything authenticated.
7. Network egress
CallDestinationWhen
CloakBrowser binary downloadcloakbrowser.dev (override via CLOAKBROWSER_DOWNLOAD_URL)First use after install
Browser trafficWhatever the agent navigates toAlways
cloak_set_geolocation --fromProxyIpipapi.co/json/Only when explicitly invoked

The wrapper does not phone home and does not collect telemetry.

Recommended deployment profiles

"Tight" (sensitive machine — has prod credentials):

--caps network,storage,pdf
--profile-dir /Users/me/.cloak-browser-mcp/profiles/scoped
--allowed-domains *.target.com
--upload-allow-dir /tmp/cloak-uploads
--max-pages 5

No --enable-unsafe-eval. No vision cap (xy clicks bypass allow-listing).

"Open" (research / personal browsing):

--caps all
--humanize
--max-pages 20

"Untrusted" (you don't fully trust the upstream binary yet) — run inside a Docker container or a fresh macOS user account with no Keychain access and no .env files mounted.

Reporting vulnerabilities

If you find a security issue in cloak-browser-mcp (not in the upstream cloakbrowser package or its binary): open a private security advisory at https://github.com/devinwang/cloak-browser-mcp/security/advisories/new.

For issues in upstream CloakBrowser: https://github.com/CloakHQ/CloakBrowser/security/advisories/new.


Changelog

[0.2.0] - 2026-10-21

  • Upgraded cloakbrowser from 0.3.x to 0.6.3. The new releases add Pro licensing, release channels, and signed download verification. Nothing the server used was removed. No new MCP tools; the tool count stays at 80.
  • Fix: library log lines could corrupt the stdio stream. cloakbrowser reports some events (for example auto-encoding of special characters in proxy credentials) with console.info, which Node writes to stdout, where an MCP client expects only JSON-RPC. console.log, console.info and console.debug are now routed to stderr while the server runs.
  • Node requirement is now ^20.19.0 || >=22.12.0 (was declared as >=18). CloakBrowser 0.3.30 already required Node 20 or newer, and 0.6.x needs 20.19 or newer. CI no longer tests Node 18.
  • Six tools added for parity with Playwright MCP 0.0.83 (80 → 86):
    • browser_find — search the snapshot for text or a regex.
    • browser_emulate_media — color scheme, reduced motion, forced colors, contrast, media type. null clears an override.
    • browser_video_show_actions / browser_video_hide_actions (devtools) — annotate actions on the page while recording or screencasting.
    • browser_start_recording / browser_stop_recording (devtools) — record what the user does in the browser and return it as Playwright code.
  • browser_annotate is not provided: it launches Playwright's internal dashboard process and needs someone to draw on the page.
  • playwright-core minimum raised to ^1.61.0, the first release with page.screencast.showActions(); the resolved version moves from 1.60.0 to 1.64.1.
  • Input schemas now advertise nullable parameters as { oneOf: [<type>, null] } (the converter used to drop the null), which browser_emulate_media needs.
  • Added mcpName to package.json and a server.json for the official MCP Registry, including the optional CLOAKBROWSER_LICENSE_KEY variable.

[0.1.4] - 2026-08-23

  • Fix: browser_evaluate without target always failed. The function was passed to Playwright as a string expression, so the function object came back instead of its result, which serialized to undefined and failed MCP result validation. It is now invoked, and a function that legitimately returns undefined reports the string "undefined".

[0.1.3] - 2026-08-23

  • Fix: a failed browser launch could not be retried. A rejected launch promise was cached and re-awaited forever, so one transient error forced a process restart. It is now cleared on failure.
  • Clearer errors. A stale CloakBrowser process holding the profile directory used to surface as "No active page". There is now a NO_BROWSER error (BrowserNotLaunchedError) that carries the underlying launch error and the command to find stale processes, and a TAB_NOT_FOUND error for an unknown tab id. NoActivePageError no longer tells the caller to run the call that is itself failing.

[0.1.2] - 2026-08-03

  • No behaviour change. Release-pipeline only: publishes via npm trusted publishing (OIDC) instead of an NPM_TOKEN secret. A long-lived token expires silently, and npm answers an unauthorized publish with 404 Not Found - PUT — which reads like a missing package rather than an auth failure. OIDC has nothing to expire.
  • Dropped registry-url from actions/setup-node: it writes an .npmrc containing _authToken=${NODE_AUTH_TOKEN} and, with no token supplied, exports NODE_AUTH_TOKEN as the literal placeholder XXXXX-XXXXX-XXXXX-XXXXX, so npm authenticates with a bogus token instead of falling through to OIDC.
  • The release job pins npm to the 11.x line before publishing — OIDC needs >= 11.5.1 and Node 22 still bundles 10.x. Provenance is automatic under trusted publishing, so the explicit --provenance flag is gone; attestation coverage is unchanged.

[0.1.1] - 2026-05-24

  • BREAKING (UX): default is now headed (visible browser) instead of headless. An interactive MCP server should let the user watch the agent work. Pass --headless explicitly for batch/CI usage. Smithery default flipped to match.

[0.1.0] - 2026-05-24

  • Initial release. ~62 MCP tools backed by CloakHQ/CloakBrowser, covering full Playwright-MCP parity plus a Cloak-exclusive stealth/profile/audit/binary-management layer.
  • CLI: --caps, --profile-dir, --headless/--headed, --proxy, --timezone, --locale, --user-agent, --viewport, --geoip, --humanize, --fingerprint-seed, --allowed-domains, --blocked-domains, --enable-unsafe-eval, --upload-allow-dir, --download-dir, --max-pages, --self-test.
  • Smithery YAML for one-click integration.
  • MIT-licensed wrapper; upstream CloakBrowser Chromium binary remains proprietary-free-redistribute-prohibited.

License


Acknowledgments

Installation

Source-derived launch command. Check the maintainer’s required arguments and credentials before running:

bash
npx -y @devinwangd/cloak-browser-mcp

Set up in your AI client

Merge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.

json
{
  "mcpServers": {
    "io-github-devinwang-cloak-browser-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "@devinwangd/cloak-browser-mcp"
      ]
    }
  }
}

Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.

Claude Desktop setup reference

Package

@devinwangd/cloak-browser-mcpnpm

Compatible MCP Clients

io.github.devinwang/cloak-browser-mcp works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.

  • Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.
  • Cursor~/.cursor/mcp.jsonRestart Cursor for changes to take effect.
  • VS Code.vscode/mcp.jsonReload VS Code window for changes to take effect.
  • Windsurf~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect.
  • Claude Code.mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.

Learn More