Private stealth browser-automation MCP server. Forked from chrome-devtools-mcp; default-on stealth posture for driving bot-managed sites. Coexists with upstream chrome-devtools-mcp on the same machine.
Not published to npm ("private": true in package.json). Local install only.
When on:
- The chrome-devtools-frontend
Universeis not initialised. The Universe forcesRuntime.enable+Debugger.enableon every page, which is the largest CDP-side fingerprint and is what theconsole.groupEndProxy-trap family of detectors looks for. - Page
console/pageerror/Runtime.exceptionThrownlisteners are not subscribed (those implicitly enableRuntime). - Patchright-shape DOM polyfills are injected on every navigation in every page:
chrome.runtime/chrome.loadTimes()/chrome.csi()stubs.Notification.permission↔navigator.permissions.query({name:'notifications'})coherence.Function.prototype.toStringProxy preserving[native code]for the polyfilled functions.
- WebGL remains untouched so Chrome reports the renderer it actually uses.
- Mouse, hover, fill, type, key-press, and drag go through humanisers:
- Cubic-bezier mouse paths with 8–24
mouseMovedevents, 8–30ms non-uniform gap. - 40–180ms mouse-down/up dwell.
- Lognormal keystroke flight (mean ~110ms, p10 55ms, p90 220ms), 50–150ms dwell, 350–600ms thinking pauses every 8–25 chars.
fillandfill_formfocus, clear, and type text per key; select elements retain native selection behavior.- Drag transitions use an 80–280ms randomized dwell.
- Cubic-bezier mouse paths with 8–24
- Geolocation defaults to no override (instead of
{lat:0,lon:0}Null Island). - The in-page tools state global is
window[Symbol.for('dtmcp')]instead ofwindow.__dtmcp.
Trade-off: list_console_messages and get_console_message return empty under stealth, and the ConsoleFormatter falls back to its non-Universe-detailed mode. Pass --no-stealth to restore upstream behaviour.
--enable-automationstripped from default args (zerosnavigator.webdriver).--disable-blink-features=AutomationControlledadded.- Hardcoded
--screen-info=3840x2160removed. - Default user-data-dir is
~/.cache/ghostframe-mcp/..., distinct from upstream's~/.cache/chrome-devtools-mcp/...so cookies, Cloudflare reputation, and the profile lock don't collide. pipe: trueis kept (over the detectable--remote-debugging-port).
Added: set_blocked_urls (CDP Network.setBlockedURLs). Rules persist across page navigations until cleared or the page closes.
Schema additions on existing tools:
evaluate_scriptand slimevaluateacceptworld: 'isolated' | 'main'. Default isisolatedfor stealth, except whenargs(element UIDs) are passed, in which case it falls back tomain(element handles can only be evaluated in the realm that created them).emulateacceptsuserAgentMetadata(JSON-encoded UA Client-Hints),locale, andtimezone, and routes UA/locale/timezone overrides through raw CDPEmulation.setUserAgentOverride+setLocaleOverride+setTimezoneOverride+Network.setExtraHTTPHeaderssonavigator.userAgent,Sec-CH-UA-*, andAccept-Languagestay coherent.
Removed: lighthouse_audit, take_memory_snapshot, load_memory_snapshot, get_memory_snapshot_details, performance_start_trace, performance_stop_trace, performance_analyze_insight. The lighthouse npm dep, the chrome-devtools-frontend heap-snapshot worker bundle, and the trace-processing/ module are also gone. Use upstream chrome-devtools-mcp for these.
--usage-statisticsdefaults tofalse. Sending stealth-config telemetry to Google's Clearcut endpoint contradicts the fork posture.--proxy-serveraccepts authenticated proxies — see Proxy.- File access defaults to MCP workspace roots plus the system temporary directory.
--allow-unrestricted-pathsrestores the legacy unrestricted behavior. - Package marked private; npm name is
ghostframe-mcp; bin entries areghostframe-mcp(server) andghostframe(CLI). Names are distinct from upstreamchrome-devtools-mcp/chrome-devtoolsso a global install never shadows upstream.
git clone <fork-url> ~/Documents/ghostframe-mcp
cd ~/Documents/ghostframe-mcp
npm install
npm run buildRegister with Claude Code (user-scoped):
claude mcp add -s user ghostframe -- \
node /absolute/path/to/ghostframe-mcp/build/src/bin/ghostframe-mcp.jsOr as JSON in your MCP client config:
{
"mcpServers": {
"ghostframe": {
"command": "node",
"args": [
"/absolute/path/to/ghostframe-mcp/build/src/bin/ghostframe-mcp.js"
]
}
}
}After pulling new commits, run npm run build. The MCP config does not change.
Requirements: Node.js v20.19+, Chrome stable (or another channel via --channel).
Dependabot checks npm and GitHub Actions dependencies weekly. Puppeteer, Chrome DevTools frontend, the MCP SDK, yargs, debug, and core-js are grouped separately so higher-risk upgrades are tested independently.
The fork's npm name, bin entries, and default user-data-dir are all distinct from upstream so both packages can be installed and registered with the same MCP client at once. Add both servers to your client config:
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": ["-y", "chrome-devtools-mcp@latest"]
},
"ghostframe": {
"command": "node",
"args": [
"/absolute/path/to/ghostframe-mcp/build/src/bin/ghostframe-mcp.js"
]
}
}
}Pick which to invoke per task:
ghostframe— sites with bot management (Cloudflare, DataDome, AXS-style ticketing), anything wherenavigator.webdriver=truewould block, work that benefits from clean per-session state.chrome-devtools(upstream) — Lighthouse audits, performance tracing, heap snapshots, accessibility audits, trusted local pages.
Proxies are off by default. Without --proxy-server, Chrome uses the machine's normal network route and public IP.
Pass an unauthenticated proxy with --proxy-server:
--proxy-server=203.0.113.7:8888
--proxy-server=http://203.0.113.7:8888
--proxy-server=socks5://proxy.example.com:1080
HTTP proxy authentication uses GHOSTFRAME_PROXY_USERNAME and GHOSTFRAME_PROXY_PASSWORD. Both variables are required together. Chrome does not support authenticated SOCKS proxies.
{
"mcpServers": {
"ghostframe-proxied": {
"command": "node",
"args": [
"/absolute/path/to/ghostframe-mcp/build/src/bin/ghostframe-mcp.js",
"--proxy-server=203.0.113.7:8888"
],
"env": {
"GHOSTFRAME_PROXY_USERNAME": "user",
"GHOSTFRAME_PROXY_PASSWORD": "pass"
}
}
}
}The common IP:PORT:USER:PASS format remains available as an explicit compatibility mode:
ghostframe start \
--allow-legacy-proxy-credentials \
--proxy-server=203.0.113.7:8888:user:passLegacy embedded credentials are rejected by default because process arguments can be inspected by other local processes. The Ghostframe CLI removes them from daemon arguments and transfers them through the daemon environment before starting the MCP server.
Reads and writes are limited to workspace roots supplied by the MCP client and the system temporary directory. Existing paths and the nearest existing parent of new outputs are resolved canonically, so symlinks cannot escape an allowed root. If the client supplies no roots, only the temporary directory is allowed.
Use --allow-unrestricted-paths only for compatibility with clients that cannot advertise roots and must access other local paths.
- Input automation (9 tools)
- Navigation automation (6 tools)
- Emulation (2 tools)
- Network (3 tools)
- Debugging (5 tools)
- Extensions (5 tools)
Full schemas: docs/tool-reference.md. Slim mode (3 tools): docs/slim-tool-reference.md.
-
--autoConnect/--auto-connectIf specified, automatically connects to a browser (Chrome 144+) running locally from the user data directory identified by the channel param (default channel is stable). Requires the remote debugging server to be started in the Chrome instance via chrome://inspect/#remote-debugging.- Type: boolean
- Default:
false
-
--browserUrl/--browser-url,-uConnect to a running, debuggable Chrome instance (e.g.http://127.0.0.1:9222). See README "Connecting to a running Chrome instance".- Type: string
-
--wsEndpoint/--ws-endpoint,-wWebSocket endpoint to connect to a running Chrome instance (e.g.,ws://127.0.0.1:9222/devtools/browser/{ID}). Alternative to --browserUrl.- Type: string
-
--wsHeaders/--ws-headersCustom headers for WebSocket connection in JSON format (e.g., '{"Authorization":"Bearer token"}'). Only works with --wsEndpoint.- Type: string
-
--headlessWhether to run in headless (no UI) mode.- Type: boolean
- Default:
false
-
--executablePath/--executable-path,-ePath to custom Chrome executable.- Type: string
-
--isolatedIf specified, creates a temporary user-data-dir that is automatically cleaned up after the browser is closed. Defaults to false.- Type: boolean
-
--userDataDir/--user-data-dirPath to the user data directory for Chrome. Default is $HOME/.cache/ghostframe-mcp/chrome-profile$CHANNEL_SUFFIX_IF_NON_STABLE.- Type: string
-
--channelSpecify a different Chrome channel that should be used. The default is the stable channel version.- Type: string
- Choices:
canary,dev,beta,stable
-
--logFile/--log-filePath to a file to write debug logs to. Set the env variableDEBUGto*to enable verbose logs. Useful for submitting bug reports.- Type: string
-
--viewportInitial viewport size for the Chrome instances started by the server. For example,1280x720. In headless mode, max size is 3840x2160px.- Type: string
-
--proxyServer/--proxy-serverProxy server for Chrome. Use GHOSTFRAME_PROXY_USERNAME and GHOSTFRAME_PROXY_PASSWORD for HTTP proxy authentication. SOCKS proxies must be unauthenticated.- Type: string
-
--allowLegacyProxyCredentials/--allow-legacy-proxy-credentialsAllow credentials embedded in --proxy-server. This may expose secrets through process listings and is disabled by default.- Type: boolean
- Default:
false
-
--allowUnrestrictedPaths/--allow-unrestricted-pathsAllow file access outside client workspace roots and the system temporary directory. Disabled by default.- Type: boolean
- Default:
false
-
--acceptInsecureCerts/--accept-insecure-certsIf enabled, ignores errors relative to self-signed and expired certificates. Use with caution.- Type: boolean
-
--experimentalVision/--experimental-visionWhether to enable coordinate-based tools such as click_at(x,y). Usually requires a computer-use model able to produce accurate coordinates by looking at screenshots.- Type: boolean
-
--experimentalScreencast/--experimental-screencastExposes experimental screencast tools (requires ffmpeg). Install ffmpeg from https://www.ffmpeg.org/download.html and ensure it is on the MCP server PATH.- Type: boolean
-
--experimentalFfmpegPath/--experimental-ffmpeg-pathPath to ffmpeg executable for screencast recording.- Type: string
-
--experimentalWebmcp/--experimental-webmcpSet to true to enable debugging WebMCP tools. Requires Chrome 149+ with the following flags:--enable-features=WebMCPTesting,DevToolsWebMCPSupport- Type: boolean
-
--chromeArg/--chrome-argAdditional arguments for Chrome. Only applies when Chrome is launched by ghostframe-mcp.- Type: array
-
--ignoreDefaultChromeArg/--ignore-default-chrome-argExplicitly disable default arguments for Chrome. Only applies when Chrome is launched by ghostframe-mcp.- Type: array
-
--categoryEmulation/--category-emulationSet to false to exclude tools related to emulation.- Type: boolean
- Default:
true
-
--categoryNetwork/--category-networkSet to false to exclude tools related to network.- Type: boolean
- Default:
true
-
--categoryExtensions/--category-extensionsSet to true to include extension tools. This requires a browser launched through the pipe connection.- Type: boolean
- Default:
false
-
--stealthStealth posture (default: true). Skips initialization of the chrome-devtools-frontend Universe (which forces Runtime.enable + Debugger.enable on every page and is the single largest CDP fingerprint) and the page console / pageerror / Runtime.exceptionThrown listeners that implicitly enable Runtime. Trade-off: list_console_messages and get_console_message return empty results, and the ConsoleFormatter degrades to its non-DevTools-detailed mode. Set to false to restore the upstream chrome-devtools-mcp behavior.- Type: boolean
- Default:
true
-
--usageStatistics/--usage-statisticsSend usage statistics to Google Clearcut. Off by default in this stealth fork (sending stealth-config telemetry to Google contradicts the fork posture). Set to true to opt back in. Also disabled ifCHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICSorCIenv variables are set.- Type: boolean
- Default:
false
-
--slimExposes a "slim" set of 3 tools covering navigation, script execution and screenshots only. Useful for basic browser tasks.- Type: boolean
-
--redactNetworkHeaders/--redact-network-headersIf true, redacts some of the network headers considered senstive before returning to the client.- Type: boolean
- Default:
false
Pass options via the args array in the MCP JSON config. Run node build/src/bin/ghostframe-mcp.js --help to print the full list.
Same as upstream — useful when you want manual and agent-driven sessions to share state, or when the agent runs inside a sandbox. Two paths:
--auto-connect(Chrome 144+) — connect to a Chrome instance you started yourself. In Chrome, navigate tochrome://inspect/#remote-debuggingto enable remote debugging, then start the MCP server with--auto-connect.--browser-url=http://127.0.0.1:9222— connect to a Chrome started with--remote-debugging-port=9222. Chrome requires a non-default--user-data-dirwhen--remote-debugging-portis set.
When connecting to a running Chrome, the fork does not control its launch flags. Existing pages keep their existing document state; MCP-created pages receive the stealth init script before their first navigation. The Universe gate, console-listener gate, and humanizers still apply because they live in the context and tool layers.
docs/detection-signals.md— six-layer detection map (CDP / launch / DOM / fingerprint / behavioral / network) with citations.docs/stealth-configuration.md— flag posture, Universe gate trade-off, isolated-world routing, persona bundling, polyfill list.docs/design-principles.md,docs/cli.md,docs/troubleshooting.md— adapted from upstream for stealth scope.skills/stealth-launch/— pre-flight checklist before driving a stealth-protected site.skills/detection-testing/— sweep workflow forbot.sannysoft.com,arh.antoinevastel.com,creepjs,pixelscan.skills/diagnose-bot-block/— six-layer walk for "blocked but detectors pass".skills/borrow-stealth-feature/— port workflow for borrowing primitives fromvibheksoni/stealth-browser-mcpandnodriver.skills/humanized-input/— humanisation distributions and persona-coherence callouts.skills/ghostframe/,skills/ghostframe-cli/,skills/troubleshooting/— adapted from upstream.
This fork exposes browser content to MCP clients. Don't share sensitive or personal information you wouldn't share with an MCP-connected agent. Intended for personal use against sites you own or have authorisation to test.