Skip to content

get_window_state hangs forever on heavy webview apps (Arc, Safari w/ many tabs) on macOS 26 #1537

Description

@obaid

Summary

get_window_state (and by extension the MCP tool that calls it) can hang indefinitely when targeting heavy webview-based apps on macOS 26. The tool never returns — there's no error, no timeout from cua-driver's side — so any agent driving this via the MCP server is stranded until the user force-quits the host process.

I've reproduced this with a downstream Swift app embedding CuaDriverServer via the mcp__operator-driver__* registry. Wrapping our side with a 60s outer timeout works around it, but the root cause is inside cua-driver.

Environment

  • macOS 26.4.1 (25E253) on Apple Silicon
  • cua-driver Swift package: tested on 0.1.5 AND 0.1.9 — reproduces on both
  • replayd (ScreenCaptureKit daemon) and WindowServer both present and healthy
  • Accessibility + Screen Recording TCC granted
  • Reproduces with our wrapper around CuaDriverServer.CuaDriverMCPServer.make driven over StdioTransport

Two flavors observed

Flavor A — Safari with many tabs

  • Symptom: get_window_state(pid: <safari-pid>) hangs.
  • During the hang: com.apple.Safari.History pegs at 100%+, replayd at ~60% CPU, WindowServer at ~45%.
  • Hypothesis: the AX query is blocked behind Safari's history subsystem, which is itself wedged. ScreenCaptureKit may also be involved if the tool grabs a screenshot internally.

Flavor B — Arc browser

  • Symptom: get_window_state(pid: <arc-pid>) hangs.
  • During the hang: replayd is NOT hot (<1% CPU). Helper at ~16% CPU. The MCP helper's main thread is parked in mach_msg2_trap waiting on IPC; the actual work is happening on a background thread.
  • sample of the helper shows the main thread idle in RunCurrentEventLoopInModemach_msg2_trap. The hung AX walk is on a separate thread.
  • Hypothesis: the AX tree on Arc (Chromium-based, lots of nested webviews and subwindows) is large enough that whatever AX API is being walked synchronously never returns. Possibly a known issue with kAXChildrenAttribute enumeration on heavyweight Electron-style apps.

Reproduction

Easiest path:

  1. Open Arc, navigate to any non-trivial page (Gmail, Twitter, LinkedIn — anything with rich DOM).
  2. From an agent (Claude / Codex / Pi) configured to use cua-driver as an MCP server, prompt: "Read what's on screen in Arc."
  3. Watch the agent decide to call get_window_state(pid: <arc-pid>).
  4. The call never returns; the agent shows the tool as in-flight forever.

We've reproduced with no painted highlights, no attachments, no MCP adapters in front — direct cua-driver MCP server. The hang is independent of the agent runtime (saw it on both Claude and Codex CLIs).

Suggested fixes

  1. Add an internal timeout to get_window_state (and probably get_accessibility_tree) — return a partial result or a clear error after N seconds rather than hanging.
  2. Cap the AX tree walk depth/breadth so a pathologically large tree (Arc, Electron apps) doesn't take unbounded time.
  3. Cancel-safe AX queries — current call doesn't seem to honor Swift Task cancellation, which prevents callers from cleaning up.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions