| name | ghostframe-troubleshoot |
| description | Diagnoses Chrome DevTools MCP failures in this stealth fork. Use when a tool call fails (list_pages, new_page, navigate_page), the server won't start, the target site detects the browser as a bot, or `evaluate_script` results don't match what's on the page. |
Troubleshooting
You are diagnosing a failed call. Work the steps in order; do not skip ahead.
How to run these
Use the mcp__ghostframe__* tools, one call per step. The snippets below are shown as
CLI commands for readability; the tool takes the same arguments. Only shell out to
ghostframe <tool> if you are working outside an MCP session โ it costs a process
spawn per call and shell-quoted JavaScript breaks easily.
navigator.userAgentData is gated to secure contexts. Read it on an HTTPS page, never
on about:blank, or it comes back empty and looks like a failure it is not.
Step 1: Categorize the symptom
Read the error or describe the unexpected behavior. Categorize as one of:
- A. Server / connection failure. MCP didn't start,
list_pages errors immediately, Target closed, ERR_MODULE_NOT_FOUND, etc.
- B. Target detects the browser. Cloudflare/DataDome/Akamai/PerimeterX/Imperva/Kasada interstitial on first navigation; 403 on a previously-working URL; CAPTCHA storm.
- C.
evaluate_script returns the wrong thing. Returns undefined for a known-present page global; returns stale values; returns isolated-world values when the page-side state is needed.
- D. Persona disagreement. Site detects mismatched UA / timezone / locale / proxy IP after
emulate.
- E. Tool not found. Expected tool isn't available.
Each category has its own playbook below.
Step 2A: Server / connection failure
Locate the MCP configuration first. Search the workspace for .mcp.json, gemini-extension.json, .claude/settings.json, .vscode/launch.json, .gemini/settings.json. Read for:
- Incorrect args or flag names (typos like
--autoBronnect).
- Missing env vars referenced in args.
If no config file is found, ask the user for theirs.
Then triage the error string:
Could not find DevToolsActivePort
- Confirm Chrome (right channel โ Stable / Canary as the error mentions) is currently running.
- Instruct: open
chrome://inspect/#remote-debugging and tick "Enable remote debugging".
- Run
list_pages. Don't retry the original failed command yet.
Target closed
Browser failed to launch. Close existing Chrome instances, confirm Chrome installs cleanly, retry.
Server starts but creates a new empty profile
Argument typo. Check flag spelling exactly.
ProtocolError: Network.enable timed out / socket connection was closed unexpectedly
- Chrome 144+ already running.
- Remote debugging enabled.
- Connection prompt accepted.
- No competing tool on the debug port.
ERR_MODULE_NOT_FOUND
Wrong Node version or corrupted npx cache:
rm -rf ~/.npm/_npx
npm cache clean --force
Sandboxing / Host validation / WSL / Windows-specific
Map to the corresponding section in docs/troubleshooting.md.
Step 2B: Target detects the browser
Probable cause is launch posture, persona, or behavioral. Read all three signals in
one evaluate_script, on an HTTPS page:
() => {
const gl = document.createElement('canvas').getContext('webgl');
const dbg = gl && gl.getExtension('WEBGL_debug_renderer_info');
return {
webdriver: navigator.webdriver,
uaHasHeadless: /Headless/.test(navigator.userAgent),
renderer: dbg ? gl.getParameter(dbg.UNMASKED_RENDERER_WEBGL) : 'no-webgl',
};
};
webdriver is true. Launch flags are leaking โ --enable-automation not
stripped, or --disable-blink-features=AutomationControlled missing. Fix at launch.
Do not set the property in JS; the override is itself the signal.
uaHasHeadless is true. The launcher rewrites a headless user agent, so this
means the init script did not run. Check the stealth install path before anything
else.
renderer contains SwiftShader, or reads Google Inc. (Google). Software
rendering, which is a bot tell. Run on a host with GPU access.
If all three are clean, run bot.sannysoft.com โ the matrix tells you which signal
class flipped you. Hand off to ghostframe-detect-test for the full sweep, and to
ghostframe-diagnose-block if all four detectors pass and the target still blocks.
Step 2C: evaluate_script returns the wrong thing
Most common cause: world mismatch.
| Symptom | Likely cause | Fix |
|---|
Script returns undefined for a window.foo set by the page | Ran in isolated world | Pass world: "main" |
| Script reads stale DOM after a click | Page-side handler hasn't run yet | Add wait_for between click and eval |
Script throws Cannot read property 'X' of undefined for a page-defined global | Isolated world cannot see page globals | Pass world: "main" |
| Script in main world is rejected | Stealth mode gates main-world for agent-injected scripts | Re-route through user-supplied call, or rewrite to be isolated-world-safe |
See skills/ghostframe/SKILL.md for the routing rules.
Step 2D: Persona disagreement
Run the coherence probe:
() => ({
ua: navigator.userAgent,
uaCH: navigator.userAgentData?.toJSON(),
langs: navigator.languages,
platform: navigator.platform,
tz: Intl.DateTimeFormat().resolvedOptions().timeZone,
locale: Intl.DateTimeFormat().resolvedOptions().locale,
});
Then compare against:
- The persona you passed to
emulate. Any disagreement means emulate did not bundle the attribute.
- The proxy egress IP geo. Verify externally โ
https://ipinfo.io/json โ and confirm the IP's geo aligns with the timezone and locale.
A US-Pacific timezone behind a Frankfurt egress IP is a stronger detection signal than any single mismatched value.
Step 2E: Tool not found
- The fork removes Lighthouse, memory, performance, extension, in-page and WebMCP
tools. They are intentionally absent. Do not request them.
- Some MCP clients enforce read-only mode and hide tools annotated
readOnlyHint: false. The full set requires turning off the client's read-only / plan-mode setting.
Step 3: Read upstream known issues
Map remaining symptoms to docs/troubleshooting.md. It has the inherited environment cases (sandboxing, WSL, Windows shell wrapping, Web Bluetooth on macOS).
Step 4: Capture verbose logs
If the issue is still unclear:
DEBUG=* node /absolute/path/to/ghostframe-mcp/build/src/bin/ghostframe-mcp.js --logFile=/tmp/cdm.log
Read the log for:
- Launch flags actually applied (compare against expected stealth posture).
- CDP domains enabled at startup.
- Persona application (one
emulate call should produce multiple CDP calls; confirm all of them happened).
Step 5: Confirm with diagnostics
If the user is still stuck:
node /absolute/path/to/ghostframe-mcp/build/src/bin/ghostframe-mcp.js --help
Confirms install, Node version, basic startup. If this fails, the rest is moot โ fix the install.
Step 6: Search known issues
Check the upstream repo for similar symptoms before declaring novel:
gh issue list --repo ChromeDevTools/chrome-devtools-mcp --search "<error snippet>" --state all