MCP Servers

A collection of Model Context Protocol servers, templates, tools and more.

C
Chrome Devtools MCP Stealth

Private stealth fork of ChromeDevTools/chrome-devtools-mcp

Created 5/1/2026
Updated about 9 hours ago
Repository documentation and setup instructions

ghostframe-mcp

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.

Differences from upstream

Stealth mode (--stealth, default true)

When on:

  • The chrome-devtools-frontend Universe is not initialised. The Universe forces Runtime.enable + Debugger.enable on every page, which is the largest CDP-side fingerprint and is what the console.groupEnd Proxy-trap family of detectors looks for.
  • Page console / pageerror / Runtime.exceptionThrown listeners are not subscribed (those implicitly enable Runtime).
  • Patchright-shape DOM polyfills are injected on every navigation in every page:
    • chrome.runtime / chrome.loadTimes() / chrome.csi() stubs.
    • Notification.permissionnavigator.permissions.query({name:'notifications'}) coherence.
    • WebGL UNMASKED_VENDOR_WEBGL / UNMASKED_RENDERER_WEBGL spoof (Intel Inc. / Intel Iris OpenGL Engine instead of Google Inc. (Google) / SwiftShader).
    • Function.prototype.toString Proxy preserving [native code] for the polyfilled functions.
  • Mouse, hover, type, key-press, and drag go through humanisers:
    • Cubic-bezier mouse paths with 8–24 mouseMoved events, 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.
  • 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 of window.__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.

Chrome launch flags

  • --enable-automation stripped from default args (zeros navigator.webdriver).
  • --disable-blink-features=AutomationControlled added.
  • Hardcoded --screen-info=3840x2160 removed.
  • 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: true is kept (over the detectable --remote-debugging-port).

Tool changes

Added: set_blocked_urls (CDP Network.setBlockedURLs).

Schema additions on existing tools:

  • evaluate_script and slim evaluate accept world: 'isolated' | 'main'. Default is isolated for stealth, except when args (element UIDs) are passed, in which case it falls back to main (element handles can only be evaluated in the realm that created them).
  • emulate accepts userAgentMetadata (JSON-encoded UA Client-Hints), locale, and timezone, and routes UA/locale/timezone overrides through raw CDP Emulation.setUserAgentOverride + setLocaleOverride + setTimezoneOverride + Network.setExtraHTTPHeaders so navigator.userAgent, Sec-CH-UA-*, and Accept-Language stay 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.

Other

  • --usage-statistics defaults to false. Sending stealth-config telemetry to Google's Clearcut endpoint contradicts the fork posture.
  • --proxy-server accepts authenticated proxies — see Proxy.
  • Package marked private; npm name is ghostframe-mcp; bin entries are ghostframe-mcp (server) and ghostframe (CLI). Names are distinct from upstream chrome-devtools-mcp / chrome-devtools so a global install never shadows upstream.

Setup

git clone <fork-url> ~/Documents/ghostframe-mcp
cd ~/Documents/ghostframe-mcp
npm install
npm run build

Register with Claude Code (user-scoped):

claude mcp add -s user ghostframe -- \
  node /absolute/path/to/ghostframe-mcp/build/src/bin/ghostframe-mcp.js

Or 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).

Side-by-side with upstream

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 where navigator.webdriver=true would block, work that benefits from clean per-session state.
  • chrome-devtools (upstream) — Lighthouse audits, performance tracing, heap snapshots, accessibility audits, trusted local pages.

Proxy

Proxies are off by default. Pass one with --proxy-server:

--proxy-server=203.0.113.7:8888                         no auth
--proxy-server=203.0.113.7:8888:user:pass               with basic auth (proxy-list format)
--proxy-server=http://203.0.113.7:8888                  no auth, explicit scheme
--proxy-server=http://user:pass@203.0.113.7:8888        URL form with embedded auth
--proxy-server=socks5://proxy.example.com:1080           SOCKS5
--proxy-server=socks5://user:pass@proxy.example.com:1080 SOCKS5 with auth

Authenticated proxies use Puppeteer's page.authenticate() to answer the 407 challenge — Chrome strips inline user:pass@ from --proxy-server for security, so credentials are applied at the page-event layer rather than on the command line. Authentication is registered for every existing and future page in the browser.

To bake a proxy into the global MCP config, register a separate variant alongside the default:

claude mcp add -s user ghostframe-proxied -- \
  node /absolute/path/to/ghostframe-mcp/build/src/bin/ghostframe-mcp.js \
  --proxy-server=203.0.113.7:8888:user:pass

Then you have both ghostframe (no proxy) and ghostframe-proxied registered, and pick which to invoke per task. Credential rotation requires re-running claude mcp add; consider this trade-off before baking creds into the config.

Tools

Full schemas: docs/tool-reference.md. Slim mode (3 tools): docs/slim-tool-reference.md.

Configuration

  • --autoConnect/ --auto-connect If 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, -u Connect 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, -w WebSocket 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-headers Custom headers for WebSocket connection in JSON format (e.g., '{"Authorization":"Bearer token"}'). Only works with --wsEndpoint.

    • Type: string
  • --headless Whether to run in headless (no UI) mode.

    • Type: boolean
    • Default: false
  • --executablePath/ --executable-path, -e Path to custom Chrome executable.

    • Type: string
  • --isolated If 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-dir Path to the user data directory for Chrome. Default is $HOME/.cache/ghostframe-mcp/chrome-profile$CHANNEL_SUFFIX_IF_NON_STABLE.

    • Type: string
  • --channel Specify a different Chrome channel that should be used. The default is the stable channel version.

    • Type: string
    • Choices: canary, dev, beta, stable
  • --logFile/ --log-file Path to a file to write debug logs to. Set the env variable DEBUG to * to enable verbose logs. Useful for submitting bug reports.

    • Type: string
  • --viewport Initial viewport size for the Chrome instances started by the server. For example, 1280x720. In headless mode, max size is 3840x2160px.

    • Type: string
  • --proxyServer/ --proxy-server Proxy server for Chrome to route all browser traffic through. Accepts: host:port (no auth), host:port:user:pass (with basic auth — common proxy-list format), http://host:port, http://user:pass@host:port, socks5://host:port, or socks5://user:pass@host:port. Authenticated proxies use Puppeteer's page.authenticate() to answer the 407 challenge — Chrome strips inline credentials from --proxy-server for security, so credentials are applied at the page-event layer, not on the command line.

    • Type: string
  • --acceptInsecureCerts/ --accept-insecure-certs If enabled, ignores errors relative to self-signed and expired certificates. Use with caution.

    • Type: boolean
  • --experimentalVision/ --experimental-vision Whether 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-screencast Exposes 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-path Path to ffmpeg executable for screencast recording.

    • Type: string
  • --experimentalWebmcp/ --experimental-webmcp Set to true to enable debugging WebMCP tools. Requires Chrome 149+ with the following flags: --enable-features=WebMCPTesting,DevToolsWebMCPSupport

    • Type: boolean
  • --chromeArg/ --chrome-arg Additional arguments for Chrome. Only applies when Chrome is launched by ghostframe-mcp.

    • Type: array
  • --ignoreDefaultChromeArg/ --ignore-default-chrome-arg Explicitly disable default arguments for Chrome. Only applies when Chrome is launched by ghostframe-mcp.

    • Type: array
  • --categoryEmulation/ --category-emulation Set to false to exclude tools related to emulation.

    • Type: boolean
    • Default: true
  • --categoryPerformance/ --category-performance Set to false to exclude tools related to performance.

    • Type: boolean
    • Default: true
  • --categoryNetwork/ --category-network Set to false to exclude tools related to network.

    • Type: boolean
    • Default: true
  • --categoryExtensions/ --category-extensions Set to true to include tools related to extensions. Note: This feature is currently only supported with a pipe connection. autoConnect, browserUrl, and wsEndpoint are not supported with this feature until 149 will be released.

    • Type: boolean
    • Default: false
  • --stealth Stealth 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-statistics Send 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 if CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS or CI env variables are set.

    • Type: boolean
    • Default: false
  • --slim Exposes a "slim" set of 3 tools covering navigation, script execution and screenshots only. Useful for basic browser tasks.

    • Type: boolean
  • --redactNetworkHeaders/ --redact-network-headers If 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.

Connecting to a running Chrome instance

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 to chrome://inspect/#remote-debugging to 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-dir when --remote-debugging-port is set.

When connecting to a running Chrome, the fork does not launch its own browser, and the launch-time stealth flags (--enable-automation strip, polyfill injection, etc.) do not apply — the connected Chrome is whatever it was when started. The Universe gate, console-listener gate, and humanizers still apply because they live in the McpContext / tool layers.

Docs and skills

Disclaimer

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.

Quick Setup
Installation guide for this server

Install Package (if required)

npx @modelcontextprotocol/server-chrome-devtools-mcp-stealth

Cursor configuration (mcp.json)

{ "mcpServers": { "franco-bianco-chrome-devtools-mcp-stealth": { "command": "npx", "args": [ "franco-bianco-chrome-devtools-mcp-stealth" ] } } }