MCP

`peekaboo mcp`

peekaboo mcp

mcp runs Peekaboo as a Model Context Protocol server. peekaboo mcp defaults to serve, so you can launch the server without specifying a subcommand.

#Subcommands

NamePurposeKey options
serveRun Peekaboo’s MCP server over stdio.--transport stdio (default); global --bridge-socket <path> attaches to an existing Bridge host. HTTP/SSE names and --port are reserved for future support and currently fail with an actionable error.

#Implementation notes

  • serve instantiates PeekabooMCPServer and maps the transport string to PeekabooCore.TransportType. Stdio is the default for Claude Code integrations.
  • Public MCP servers are always background-only. Foreground actions, shared desktop input, browser connection setup,
  • and ambient browser auto-connect fail before dispatch. Establish an exact browser connection separately with peekaboo browser connect --foreground; MCP browser calls can then reuse its signed live receipt.

  • Direct-text paste is admitted only with an exact generation-pinned app/PID/window authorization and a canonical
  • background result. Targetless, foreground, current-clipboard, and binary paste are refused before dispatch. The nested agent tool likewise retains immutable background-only authority and never exposes Shell.

  • HTTP/SSE server transports are reserved but not implemented. Selecting either fails before daemon startup and emits a structured error in JSON mode.
  • The MCP process owns its stdio lifecycle and never hosts a Bridge listener. Support stays process-local by default;
  • an explicit --bridge-socket <path> uses that existing Bridge host and skips the embedded daemon.

  • If an unrelated legacy Bridge is still a possible ScreenCaptureKit owner, startup and non-capturing tools remain
  • available through an explicitly selected current host, but pixel-producing calls fail before dispatch with the exact owner diagnostic. That capture refusal is immutable for the connection; after fixing the owner, start a fresh MCP process before retrying capture.

  • The native tool catalog includes bounded capture for live screen/window/region recording or video ingest. It writes retained frames, contact.png, metadata.json, and optional MP4 output, so use tool allow/deny filters when exposing MCP to untrusted clients.
  • UI automation tools include action-first additions: set_value directly mutates a settable accessibility value, and action invokes a named accessibility action on an element from see.
  • verify_state replaces fixed sleeps with bounded native polling. It resolves an app or PID to one exact window, evaluates 1–8 AND predicates for window existence/bounds or exact AX element existence/value/enabled/selected state every 100 ms, and reports satisfied, unsatisfied, or conservative unknown after at most 10 seconds. Explicit PIDs and app-name selectors are pinned to the first resolved PID/process-start generation for the whole invocation; relaunch, PID reuse, and selector drift are unknown. Exact-window ownership is rechecked on every sample and before an optional screenshot, whose capture metadata must confirm the same PID and window ID. A directly read value matching a unique exact AX identifier can satisfy an element_value predicate when unrelated AX siblings are unreadable; missing, mismatched, non-identifier, or ambiguous partial-tree evidence remains unknown. A WindowServer miss is corroborated with a complete app-scoped window inventory before Peekaboo reports absence, preserving minimized AX windows. Ownership ambiguity, partial enumeration, or identity changes are unknown. It never focuses or replays actions.
  • click preserves element IDs and queries when forwarding to automation, so action-first policy can use accessibility actions before synthetic fallback.

#Examples

# Start the Peekaboo MCP server (defaults to stdio)
peekaboo mcp

# Explicit transport selection
peekaboo mcp serve --transport stdio

# Route MCP tools through an existing Bridge host
peekaboo mcp serve --bridge-socket "$HOME/Library/Application Support/Peekaboo/bridge.sock"

An MCP client can wait for stable native state without interrupting the user:

{
  "app": "TextEdit",
  "predicates": [
    {
      "kind": "element_value",
      "selector": { "identifier": "document-content" },
      "expected_value": "Ready"
    },
    { "kind": "window_exists", "expected": true }
  ],
  "stable_samples": 2,
  "timeout_ms": 5000
}

#Troubleshooting

  • Verify Screen Recording + Accessibility permissions (peekaboo permissions status).
  • Confirm your process with peekaboo app list, its exact window with peekaboo window list, and current UI with peekaboo see before rerunning.
  • Re-run with --json or --verbose to surface detailed errors.