Environment
chrome-devtools-mcp 1.0.1 (via npx -y chrome-devtools-mcp@latest)
- Connected to a running Chrome via
--browser-url=http://127.0.0.1:9222
- Windows 11, Chrome stable
Summary
A single emulate call that sets both a mobile viewport and a network throttle (e.g. Slow 3G) reliably throws Navigation timeout of 10000ms exceeded. Because the handler throws partway through, the page's tracked emulationSettings is never updated and the per-page timeouts are never refreshed — leaving the tool's tracked emulation state out of sync with the actual CDP overrides on the page.
Repro
- Navigate to any page.
- Call
emulate in one shot:
{
"viewport": "390x844x3,mobile,touch",
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1",
"networkConditions": "Slow 3G"
}
- →
Error: Navigation timeout of 10000ms exceeded.
A subsequent emulate call that omits userAgent (intending to clear it) then leaves a phantom mobile (Nexus 5) UA, because mobile device-metrics remained active from the partially-applied previous call.
Likely cause
In src/McpContext.js, emulate() (≈L194–271) applies settings in this order:
- network throttle (≈L213)
- … cpu / geolocation / userAgent / colorScheme …
setViewport(...) (≈L264) — when isMobile/hasTouch change, Puppeteer applies this via a page reload
mcpPage.emulationSettings = … (≈L267)
#updateSelectedPageTimeouts() (≈L270), which is what finally calls setDefaultNavigationTimeout(NAVIGATION_TIMEOUT * networkMultiplier) (≈L338; NAVIGATION_TIMEOUT = 10_000 at L20)
So the reload triggered by step 3 runs while the network is already throttled (step 1) but the navigation-timeout multiplier hasn't been applied yet (step 5) — the reload is bounded by the default 10 s and times out under Slow 3G. The throw at step 3 means steps 4–5 never run, so the tracked state desyncs from the live page.
Suggested fix
Apply the network-condition navigation-timeout multiplier before setViewport() (e.g. set the navigation timeout right after applying networkConditions, or reorder so timeouts update before any operation that can trigger a navigation). Optionally make emulate transactional (update emulationSettings incrementally, or wrap in try/finally) so a mid-operation failure doesn't leave tracked state inconsistent.
Workaround
Split into two calls: set networkConditions in one emulate, then change viewport in a second (either order works).
Possibly related
Environment
chrome-devtools-mcp1.0.1 (vianpx -y chrome-devtools-mcp@latest)--browser-url=http://127.0.0.1:9222Summary
A single
emulatecall that sets both a mobile viewport and a network throttle (e.g.Slow 3G) reliably throwsNavigation timeout of 10000ms exceeded. Because the handler throws partway through, the page's trackedemulationSettingsis never updated and the per-page timeouts are never refreshed — leaving the tool's tracked emulation state out of sync with the actual CDP overrides on the page.Repro
emulatein one shot:{ "viewport": "390x844x3,mobile,touch", "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", "networkConditions": "Slow 3G" }Error: Navigation timeout of 10000ms exceeded.A subsequent
emulatecall that omitsuserAgent(intending to clear it) then leaves a phantom mobile (Nexus 5) UA, because mobile device-metrics remained active from the partially-applied previous call.Likely cause
In
src/McpContext.js,emulate()(≈L194–271) applies settings in this order:setViewport(...)(≈L264) — whenisMobile/hasTouchchange, Puppeteer applies this via a page reloadmcpPage.emulationSettings = …(≈L267)#updateSelectedPageTimeouts()(≈L270), which is what finally callssetDefaultNavigationTimeout(NAVIGATION_TIMEOUT * networkMultiplier)(≈L338;NAVIGATION_TIMEOUT = 10_000at L20)So the reload triggered by step 3 runs while the network is already throttled (step 1) but the navigation-timeout multiplier hasn't been applied yet (step 5) — the reload is bounded by the default 10 s and times out under Slow 3G. The throw at step 3 means steps 4–5 never run, so the tracked state desyncs from the live page.
Suggested fix
Apply the network-condition navigation-timeout multiplier before
setViewport()(e.g. set the navigation timeout right after applyingnetworkConditions, or reorder so timeouts update before any operation that can trigger a navigation). Optionally makeemulatetransactional (updateemulationSettingsincrementally, or wrap in try/finally) so a mid-operation failure doesn't leave tracked state inconsistent.Workaround
Split into two calls: set
networkConditionsin oneemulate, then changeviewportin a second (either order works).Possibly related
emulatethrottling not reflected inperformance_start_trace(sameemulate+throttling area, different symptom).