Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, email [email protected] and we’ll put it right.

ExecBro

NPM · EXECBRO · SCANNED AUG 3

Gives AI agents eyes and hands into running React Native apps: logs, REPL, tap, screenshots

Available components

67 Trust /100
Trust breakdown (6 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score →

Supply Chain Security71
  • No malware found by supply-chain analysis.Pass
  • CVE check failed: a known high-severity CVE affects sharp 0.34.5, a direct dependency. A fixed version is available. View diagnostics → Fail
  • No install/post-install scripts declared.Pass
  • Only part of the dependency tree could be resolved (140 of 144), so this covers what we could see, not the whole tree. View diagnostics → Partial
Provenance & Transparency97
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to igorzheludkov/execbro). View diagnostics → Pass
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 0 days ago).Pass
  • Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability52
  • AI-judged instruction clarity (good).Pass
  • Context-footprint check failed: tool/resource definitions use about 18851 tokens (~325/item across 58 items; 58 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management5
  • Stability check failed: the tool surface changed between 2.2.0 and 2.5.0: 1 tool removals, 0 breaking changes, 0 additions. See how to fix → Fail
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Install

Add this component to your MCP client. Where a client-specific snippet is available, pick your client below and copy it straight into your config; otherwise use the connection detail shown.

npm · execbro

# add to Claude Code
claude mcp add com-execbro-execbro -- npx -y execbro
# add to Codex CLI
codex mcp add com-execbro-execbro -- npx -y execbro
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "com-execbro-execbro": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "execbro"
      ],
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add com-execbro-execbro --command npx --arg -y --arg execbro
# ~/.hermes/config.yaml
mcp_servers:
  com-execbro-execbro:
    command: "npx"
    args: ["-y", "execbro"]
// mcp.json
{
  "mcpServers": {
    "com-execbro-execbro": {
      "command": "npx",
      "args": [
        "-y",
        "execbro"
      ]
    }
  }
}
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 3 Aug 26 −2

    No change was recorded against any check on this day. Supply Chain Security went from 81 to 71. Other categories moved too: Stability & Change Management rose 3.

  • 2 Aug 26 −2
    • Stability: unverified → fail security
    • Provenance: pass → unverified security
    • Install scripts: pass → unverified security
    • Known CVEs: fail → unverified security
    • Provenance: pass → fail security
    • Stability: Stability not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet. security
    • The attested source repository moved: igorzheludkov/execbro security
    • The attested source repository moved: igorzheludkov/execbro security
    • Capabilities: pass → unverified functional
    • License: pass → unverified functional
    • Tool coverage: 100 → unverified functional
    • Maintenance: pass → unverified functional
    • Dependency health: partial → unverified functional
    • License: pass → fail functional
    • First check of Schema quality: unverified functional
    • Schema quality: excellent → good functional
    • Licence: MIT functional
    • Licence: MIT functional
    • Package version: 2.2.0 → 2.5.0 functional
    • Package version: 2.2.0 → 2.4.0 functional
    • Package version: 2.2.0 → 2.3.0 functional
  • 1 Aug 26 71

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 3 Aug 2026 · Analysed npm/[email protected]

Provenance verified

Ecosystem: npm · Outcome: verified

Reason: verified

Source repo:
igorzheludkov/execbro
Certificate issuer:
https://token.actions.githubusercontent.com
Certificate SAN:
https://github.com/igorzheludkov/execbro/.github/workflows/publish.yml@refs/tags/v2.5.0
Rekor log index:
2327182441
Predicate type:
https://slsa.dev/provenance/v1
Subject digest:
sha512:f6f8fdfc6ddb1ce480b3b436c026a019e7fc6a23ed919007906e3f9fea63e653ab0016b3d8ea84ed22a51ee2a87dbfd0c433a3fc8541e993111d6e460
Discovery method:
attestation_endpoint
Vulnerabilities 1 finding
ID CVE Severity Vector Fix available
GHSA-f88m-g3jw-g9cj high yes
Dependencies 140 packages

140 packages in the resolved dependency tree · 129 deprecated · 30 stale.

The dependency tree was only partially resolved, so these counts may be incomplete.

MCP tools — 58 exposed · ~18,572 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability.

Tool Tokens
activate_license ~52

Activate a Pro license using an activation token from your dashboard. Use this if you signed up on the website and need to link your account to this MCP installation.

NameTypeReqDescription
tokenstringyesActivation token from your dashboard

No output schema declared.

No examples provided.

android_input_text ~340

Type text on an Android device/emulator. [PLATFORM FALLBACK — prefer `input_text` — it targets, focuses, writes and verifies in one call unless you specifically need native-only behavior] The text will be input at the current focus point (tap an input field first). PURPOSE: Send keystrokes to whichever input currently has focus on Android — the tool does NOT focus a field itself. WHEN TO USE: Only after an input is already focused, or when `tap(text=...)` on the input didn't take focus for some reason. PREREQUISITE: A TextInput must already have focus. Tap the field first (e.g. tap({ testID: 'search' })) — `android_input_text` does NOT focus a field itself; replace:true also requires React focus. REPLACE MODE: pass replace:true to clear the focused field first (via React onChangeText so controlled state stays consistent), then type the new value. Use for pre-filled fields where appending would corrupt the value.

NameTypeReqDescription
devicestringOptional RN device name (substring match) — needed by replace:true when multiple RN apps are connected, to disambiguate which device's focused input to clear. Single-device sessions can omit.
deviceIdstringAndroid target: adb serial, emulator name, or RN device substring. Omit for first.
replacebooleanIf true, clear the focused TextInput via React onChangeText before typing. Use to set a pre-filled field to an exact value without concatenation. Requires Bridgeless/Fabric.
textstringyesText to type

No output schema declared.

No examples provided.

android_key_event ~268

Send a key event to an Android device/emulator. [PLATFORM-SPECIFIC — no cross-platform equivalent; use when sending Android key events (BACK, HOME, MENU, etc.)] Common keys: HOME, BACK, CALL, END_CALL, VOLUME_UP, VOLUME_DOWN, POWER, CAMERA, CLEAR, TAB, ENTER, DEL, MENU, SEARCH, MEDIA_PLAY_PAUSE, MEDIA_STOP, MEDIA_NEXT, MEDIA_PREVIOUS, MOVE_HOME, MOVE_END, APP_SWITCH, ESCAPE PURPOSE: Dispatch Android system keys (BACK, HOME, MENU, ENTER, DEL, etc.) that aren't reachable via on-screen tap. WHEN TO USE: Navigate back from a screen, submit a form with ENTER, dismiss the keyboard, or press hardware-style keys during a flow.

NameTypeReqDescription
deviceIdstringAndroid target: adb serial, emulator name, or RN device substring. Omit for first.
keystringyesKey name (HOME, BACK, CALL, END_CALL, VOLUME_UP, VOLUME_DOWN, POWER, CAMERA, CLEAR, TAB, ENTER, DEL, MENU, SEARCH, MEDIA_PLAY_PAUSE, MEDIA_STOP, MEDIA_NEXT, MEDIA_PREVIOUS, MOVE_HOME, MOVE_END, APP_S…

No output schema declared.

No examples provided.

android_launch_app ~167

Launch an app on an Android device/emulator by package name [PLATFORM-SPECIFIC — no cross-platform equivalent; use when launching an Android app by package name] PURPOSE: Start an installed Android app by its package (and optional activity) so the next tool calls hit a running process. WHEN TO USE: After a force-stop or install, or when the app isn't foregrounded before interaction.

NameTypeReqDescription
activityNamestringOptional activity name to launch (e.g., .MainActivity). If not provided, launches the main activity.
deviceIdstringAndroid target: adb serial, emulator name, or RN device substring. Omit for first.
packageNamestringyesPackage name of the app (e.g., com.example.myapp)

No output schema declared.

No examples provided.

android_list_packages ~131

List installed packages on an Android device/emulator [PLATFORM-SPECIFIC — no cross-platform equivalent; use when listing installed Android packages] PURPOSE: Enumerate package names visible to adb so you can confirm installation or pick the right target for android_launch_app. WHEN TO USE: Before android_launch_app when you don't know the exact package name, or to verify an install succeeded.

NameTypeReqDescription
deviceIdstringAndroid target: adb serial, emulator name, or RN device substring. Omit for first.
filterstringOptional filter to search packages by name (case-insensitive)

No output schema declared.

No examples provided.

android_long_press ~169

Long press at specific coordinates on an Android device/emulator screen [PLATFORM FALLBACK — prefer `tap` for short taps; keep android_long_press for long-press gestures specifically unless you specifically need native-only behavior] PURPOSE: Emit a sustained touch at raw pixel coordinates to trigger long-press handlers (context menus, drag starts, multi-select). WHEN TO USE: Only when a long-press gesture is required — regular taps should go through `tap`.

NameTypeReqDescription
deviceIdstringAndroid target: adb serial, emulator name, or RN device substring. Omit for first.
durationMsnumberPress duration in milliseconds (default: 1000)
xnumberyesX coordinate in pixels
ynumberyesY coordinate in pixels

No output schema declared.

No examples provided.

android_screenshot ~343

Take a screenshot from an Android device/emulator. Returns the image plus a screen-state summary: active route (name + navigation stack), overlay-grouped tappable elements (pressables behind an open sheet/modal are excluded), component names as JSX tags, labels, testIDs, and frames — all in ready-to-tap pixel coordinates. Prefer tap(text="...") when text is exact and unique; otherwise use tap(x, y) with coordinates from the list — this is the most reliable way to tap icons or visually-identified elements. Use component names for inspect_component/find_components. PURPOSE: Snapshot what the user sees on Android AND get tap-ready pressables + a structured component map in one call. WHEN TO USE: Any visual verification, before/after comparison, or as the starting point for tapping UI by coordinates on Android. WORKFLOW: android_screenshot -> pick element from pressables -> tap(x, y) or tap(testID=...) -> android_screenshot to verify. LIMITATIONS: Requires adb in PATH and a running device/emulator. For non-RN surfaces (system dialogs, permission prompts), combine with tap(..., native=true). GOOD: android_screenshot() BAD: android_screenshot({ deviceId: "guess" }) with a made-up serial — run list_devices first. SOURCE: to jump from a pixel to the code that renders it, call inspect_at_point(x, y).

NameTypeReqDescription
deviceIdstringAndroid target: adb serial, emulator name, or RN device substring. Omit for first.
outputPathstringOptional path to save the screenshot. If not provided, saves to temp directory.

No output schema declared.

No examples provided.

app_request ~370

Issue an HTTP request from inside the running app, as the logged-in user. PURPOSE: Probe your backend through the app's real network stack, TLS trust and proxy config — without pasting credentials into the conversation. WHY THIS EXISTS: hand-written fetch calls either dig the token out of redux or embed a JWT literal in the expression, which puts the credential in the transcript. auth="auto" resolves it in-app instead. WHEN TO USE: reproduce a 4xx, check what an endpoint returns for an edge case, clean up test records the UI can't reach. WORKFLOW: app_request({ method: "GET", url: "https://api.example.com/me" }) -> inspect status + body. LIMITATIONS: needs a connected app. Token lookup covers state.user.accessToken, state.auth.accessToken and state.auth.token; pass an explicit Authorization header if your app stores it elsewhere. GOOD: app_request({ method: "DELETE", url: "https://api.example.com/address/17" }) BAD: embedding a bearer token in an execute_in_app expression — it lands in the transcript.

NameTypeReqDescription
authstring"auto" (default) resolves a bearer token from app state; "none" sends no Authorization header.
bodyJSON-serialisable request body. Sets Content-Type: application/json unless you override it.
devicestringTarget device name (substring match). Omit for the default device.
headersobjectExtra request headers. An explicit Authorization here wins over auth="auto".
maxResultLengthnumberTarget size for the returned body in characters (default 25000). Oversized bodies are bounded structurally.
methodstringyesHTTP method.
urlstringyesAbsolute URL to request.

No output schema declared.

No examples provided.

clear_logs ~142

Clear the log buffer. PURPOSE: Empty the in-memory console buffer (and the SDK buffer if installed) so the next get_logs / search_logs only sees fresh entries. WHEN TO USE: Before reproducing a bug so the resulting logs are isolated; between test iterations to avoid noise from earlier runs. WORKFLOW: clear_logs -> reproduce the issue (tap / navigate / reload_app) -> get_logs or search_logs. GOOD: clear_logs() right before tap(text="Submit") BAD: clear_logs() AFTER the repro — you just deleted the evidence.

NameTypeReqDescription
devicestringRN device name (substring). Omit for all devices; see get_apps.

No output schema declared.

No examples provided.

clear_network ~152

Clear the network request buffer. PURPOSE: Reset the captured request list to isolate new traffic from a specific user action. WHEN TO USE: Right before reproducing a bug so the buffer contains only the relevant requests. WORKFLOW: clear_network -> trigger action (tap, execute_in_app) -> get_network_requests / search_network. LIMITATIONS: Irreversible — cleared requests cannot be recovered. Also clears the SDK's in-app buffer when SDK is present. GOOD: clear_network() before a reproduction. BAD: Using clear_network as a workaround for stale connections — use scan_metro / ensure_connection instead.

NameTypeReqDescription
devicestringRN device name (substring). Omit for all devices; see get_apps.

No output schema declared.

No examples provided.

connect_metro ~142

Connect to a Metro server on a specific port — the only way to reach a port scan_metro does not probe. PURPOSE: Establish a CDP WebSocket connection to a Metro server on a known port. WHEN TO USE: Metro is on a port outside 8081-8090. For any port in that range, scan_metro is strictly better — it probes them all and attaches every Bridgeless target in one call, where this connects to one port only. SEE ALSO: scan_metro for auto-discovery; get_apps afterwards to confirm the device attached.

NameTypeReqDescription
portnumberMetro server port (default: 8081)

No output schema declared.

No examples provided.

delete_account ~65

Permanently delete your account and reset this MCP installation. Removes your server-side data and local cache. You will get a new installation ID on next restart. Requires confirm: 'DELETE' to proceed.

NameTypeReqDescription
confirmstringMust be exactly 'DELETE' to confirm account deletion

No output schema declared.

No examples provided.

disconnect_metro ~241

Disconnect from Metro servers and stop auto-reconnection. Without device param: disconnects ALL devices. With device param: disconnects only the matching device. Use this to remove stale connections or free the CDP slot for the built-in debugger. Log and network buffers are preserved. Reconnect later with scan_metro. PURPOSE: Cleanly release CDP slots so another debugger (Flipper, React DevTools, Chrome) can attach, or nuke a stale connection the MCP keeps reviving. WHEN TO USE: Before launching a native debugger, when connections keep flapping, or after a simulator/device restart left zombie targets. WORKFLOW: disconnect_metro -> attach other debugger / restart app -> scan_metro to reconnect. LIMITATIONS: Suppresses auto-reconnect until scan_metro or connect_metro is called again; buffers persist but won't receive new events. GOOD: disconnect_metro(); disconnect_metro({ device: "iPhone" }) BAD: Using disconnect_metro to clear logs — use clear_logs instead; disconnect breaks capture.

NameTypeReqDescription
devicestringRN device name (substring). Omit for all devices; see get_apps.

No output schema declared.

No examples provided.

dismiss_keyboard ~166

Blur the currently focused TextInput, dismissing the on-screen keyboard. PURPOSE: Close the keyboard when it's blocking content beneath the input, or move focus off an input before a tap that would otherwise be intercepted. WHEN TO USE: After typing into a field and before tapping a button that is hidden by the keyboard. Or to verify a 'tap outside dismisses' UX is wired up. PREREQUISITE: A TextInput must already have React focus. Tap the field first (e.g. tap({ testID: 'search' })). LIMITATIONS: Requires Bridgeless/Fabric (RN new architecture). Returns 'no focused TextInput' if nothing is focused.

NameTypeReqDescription
devicestringOptional device name (substring match). Uses default device if not specified.

No output schema declared.

No examples provided.

ensure_connection ~240

Verify or establish a healthy connection to a React Native app. Use before running commands if connection may be stale, or after navigation/reload. This tool runs a health check and will auto-reconnect if needed. PURPOSE: Health-check the existing CDP connection and transparently reconnect if it has gone stale, without rescanning all Metro ports. WHEN TO USE: After a suspected disconnect (silent gaps, reload_app, app crash) or before long-running flows where a mid-flow drop would be costly. Cheaper than scan_metro when you already connected once this session. WORKFLOW: scan_metro (once) -> ensure_connection(healthCheck=true) -> resume tool calls. Use forceRefresh=true if the first probe still looks dead. GOOD: ensure_connection({ healthCheck: true }) BAD: ensure_connection() before scan_metro has ever run — call scan_metro first.

NameTypeReqDescription
forceRefreshbooleanForce close existing connection and reconnect (default: false)
healthCheckbooleanRun health check to verify page context is responsive (default: true)
portnumberMetro port (default: auto-detect)

No output schema declared.

No examples provided.

execute_in_app ~695

Execute JavaScript code in the connected React Native app and return the result. Use this for inspecting app state, calling methods on exposed global objects, or running diagnostic code. Hermes compatible: 'global' is automatically polyfilled to 'globalThis', so both global.__REDUX_STORE__ and globalThis.__REDUX_STORE__ work. RECOMMENDED WORKFLOW: 1) list_debug_globals to discover available objects, 2) inspect_global to see properties/methods, 3) execute_in_app to call methods or read values. LIMITATIONS (Hermes engine): - NO require() or import — only pre-existing globals are available - Async: use `Promise.resolve(foo()).then(function(r){ return r; })` (resolved for you when awaitPromise:true). `async`/`await` syntax is engine-dependent — many Hermes builds reject it. - Multi-statement input is auto-wrapped into an IIFE returning the last statement's value. If that can't yield a value (`if`/`for`/declaration), write the IIFE yourself with an explicit `return`. - Non-ASCII in string literals (emoji, Arabic, CJK) is auto-escaped server-side. Write it as-is. GOOD examples: `__DEV__`, `__APOLLO_CLIENT__.cache.extract()`, `__EXPO_ROUTER__.navigate('/settings')` BAD examples: `await fetch(...)` (bare top-level await), `require('react-native')` Pass timeoutMs (ms) for long-running expressions; capped at 120000. Auto-reconnect surfaces _meta.reconnected when a transport drop was self-healed.

NameTypeReqDescription
awaitPromisebooleanWhether to await promises (default: true)
collectstringCollect a deferred promise result by handle. When a promise outlives its poll budget the result is kept in the app and its handle returned; pass it here to retrieve the settled value. Use instead of…
devicestringRN device name (substring). Omit for default; see get_apps.
expressionstringJavaScript expression to execute. Must be valid Hermes syntax — no require(), no `await`/`async` (use `Promise.resolve(foo()).then(function(r){ return r; })`), no unbalanced quotes. Multi-statement i…
maxResultLengthnumberTarget size of the result in characters (default: 2000, 0 for unlimited). Oversized results are bounded structurally — arrays and objects are elided with count-preserving markers like "…+150 more" —…
timeoutMsnumberPer-call timeout in milliseconds. Default: 10000. Hard cap: 120000 (values above are clamped with a warning surfaced in the response). A timeout here is a logical failure and does NOT trigger auto-re…
verbosebooleanDisable result truncation. Tip: Be cautious - Redux stores or large state can return 10KB+.

No output schema declared.

No examples provided.

find_components ~505

Find components matching a name pattern. **TARGETED SEARCH**: Use after get_screen_layout or get_component_tree(structureOnly=true) to find specific components by pattern. Use includeLayout=true to get padding/margin/flex styles. [PRIMARY INTERACTION TOOL — works on iOS and Android; prefer over ios_*/android_* siblings] PURPOSE: Fast regex search over the entire fiber tree — including off-screen and wrapper components — to locate every instance of a component by name. WHEN TO USE: You know roughly what the component is called (e.g., "Button", "Screen$") but not where it lives, or you need counts/paths before drilling in with inspect_component. WORKFLOW: get_screen_layout (orient) -> find_components(pattern="...") -> inspect_component(componentName="...", index=N). LIMITATIONS: Matches the React display name only; minified builds may return opaque names. Large result sets — use maxResults or a tighter pattern. GOOD: find_components({ pattern: "Button" }); find_components({ pattern: "Screen$" }) BAD: find_components({ pattern: ".*" }) — floods the response; narrow the regex. SOURCE: searching by name to find a file? If you can point at it on screen, inspect_at_point(x, y) returns the file and line directly.

NameTypeReqDescription
devicestringRN device name (substring). Omit for default; see get_apps.
formatstringOutput format: 'json' or 'compact' (default, pipe-delimited rows — roughly 4.5x smaller than json)
includeLayoutbooleanInclude layout styles (padding, margin, flex) for each matched component
maxResultsnumberMaximum number of results to return (default: 20)
patternstringyesRegex pattern to match component names (case-insensitive). Examples: 'Button', 'Screen$', 'List.*Item'
shortPathbooleanShow only last 3 path segments (default: true)
summarybooleanReturn only component counts by name instead of full list (default: false)
timeoutMsnumberPer-call timeout in milliseconds. Default: 5000. Hard cap: 120000.
visibleOnlybooleanSkip components inside hidden/inactive navigation scenes (unfocused Drawer/Tab destinations, inactive screens). Default false = search the entire fiber tree.

No output schema declared.

No examples provided.

get_apps ~172

List currently connected React Native apps and their connection status. If no apps are connected, run scan_metro first to establish a connection. PURPOSE: Enumerate active debug targets with device names, platforms, ports, and detected RN/Expo versions so you can target the right one. WHEN TO USE: After scan_metro to confirm what connected, or before passing a device="..." filter to another tool. WORKFLOW: scan_metro -> get_apps -> get_logs / ios_screenshot / tap (with device="..." if multiple). LIMITATIONS: Only lists devices the MCP has successfully connected to — stale targets don't appear here, use get_connection_status for health details. GOOD: get_apps() BAD: Calling get_apps in a tight loop — the list doesn't change without a scan_metro or disconnect_metro.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

get_bundle_errors ~386

Retrieve captured Metro bundling/compilation errors. These are errors that occur during the bundle build process (import resolution, syntax errors, transform errors) that prevent the app from loading. If no errors are captured but Metro is running without connected apps, automatically falls back to screenshot+OCR to capture the error from the device screen. PURPOSE: Surface Metro's build-time failures (not runtime JS errors) that keep the app from booting or hot-reloading. WHEN TO USE: App shows the red error screen, refuses to connect, or Fast Refresh stops working after an edit. Also use when get_logs is silent but the app is clearly broken. WORKFLOW: get_bundle_status -> get_bundle_errors -> fix source -> get_bundle_errors({ clear: true }) -> reload_app. LIMITATIONS: Captures errors Metro emits via its WebSocket; the screenshot+OCR fallback requires a booted simulator and the platform param. GOOD: get_bundle_errors({ platform: "ios" }); get_bundle_errors({ clear: true }) after fixing, so the next read reflects only new errors. BAD: Using get_bundle_errors to look for runtime TypeErrors — those live in get_logs, not the bundler.

NameTypeReqDescription
clearbooleanIf true, empty the bundle error buffer after reading it. Use once a bundling error is fixed so the next call reflects only fresh errors. The errors are still returned in this response.
deviceIdstringOptional device target for screenshot fallback. Accepts an adb serial / iOS UDID, an emulator/simulator name, or a substring of the connected RN device name. Uses first available device if not specif…
maxErrorsnumberMaximum number of errors to return (default: 10)
platformstringPlatform for screenshot fallback when no errors are captured via CDP. Required to enable fallback.

No output schema declared.

No examples provided.

get_bundle_status ~193

Get the current Metro bundler status including build state and any recent bundling errors. Use this to check if there are compilation/bundling errors that prevent the app from loading. PURPOSE: Snapshot Metro's current build state (idle / transforming / error) together with any captured errors — a fast "is the bundler healthy?" check. WHEN TO USE: Before diving into runtime debugging — rules out compile-time failures that would make get_logs and tap pointless. WORKFLOW: get_bundle_status -> if errors present: get_bundle_errors for detail -> fix -> get_bundle_errors({ clear: true }). LIMITATIONS: Relies on Metro's WebSocket event stream; if Metro isn't running or the connection dropped, status may be stale. GOOD: get_bundle_status() at the start of a debug session. BAD: Polling every second — Metro events are push-based; just call once and act on the result.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

get_component_tree ~482

Get the React component tree from the running app — the fiber hierarchy including providers, navigation wrappers, and internal components. For a screen overview with positions and text, use get_screen_layout instead. Returns compact names-only structure by default; pass structureOnly=false for the full detailed tree. PURPOSE: Expose the entire fiber tree — including providers, navigators, and off-screen subtrees — when get_screen_layout's visible-only view isn't enough. WHEN TO USE: Debugging context propagation, navigation wrappers, hidden modals, or when you need to understand the full React architecture. WORKFLOW: get_component_tree() for overview -> find_components for targeted lookup -> inspect_component for props/state. LIMITATIONS: The detailed tree (structureOnly=false) is very large and routinely exceeds response-size limits on real apps — reach for inspect_component on a specific node instead. Ignores non-React native views. Minified builds return display names that may be opaque. GOOD: get_component_tree() BAD: get_component_tree({ structureOnly: false, includeProps: true, includeStyles: true }) on a large app — prefer inspect_component for specific nodes.

NameTypeReqDescription
devicestringRN device name (substring). Omit for default; see get_apps.
formatstringOutput format: 'json' or 'compact' (default, indented tree — roughly 6x smaller than json). Ignored if structureOnly=true.
hideInternalsbooleanHide internal RN components (RCTView, RNS*, Animated, etc.) for cleaner output (default: true)
includePropsbooleanInclude component props (excluding children and style). Ignored if structureOnly=true.
includeStylesbooleanInclude layout styles (padding, margin, flex, etc.). Ignored if structureOnly=true.
maxDepthnumberMaximum tree depth (default: 5000)
structureOnlybooleanReturn ultra-compact structure with just component names (no props, styles, or paths). Default true — the detailed tree averages tens of thousands of tokens and is rarely what you want. Set false onl…
timeoutMsnumberPer-call timeout in milliseconds. Default: 5000. Hard cap: 120000.

No output schema declared.

No examples provided.

get_connection_status ~298

Get detailed connection health status including uptime, recent disconnects/reconnects, and connection gaps that may indicate missing data. PURPOSE: Diagnose flaky CDP sessions — quantify uptime, count reconnects, and expose gaps where logs/network data could be missing. WHEN TO USE: When logs look suspiciously empty, tools complain about disconnect/reconnect, or the app was suspended and resumed. WORKFLOW: get_connection_status -> if unhealthy: disconnect_metro -> scan_metro to rebuild a clean session. LIMITATIONS: Reports only MCP-side view; doesn't know why Metro dropped the socket (simulator sleep, app backgrounded, etc). GOOD: get_connection_status() after noticing stale data. BAD: Polling get_connection_status as a heartbeat — use ensure_connection(healthCheck=true) for a live probe. Pass events=true to include the recent connection event log (connect/close/reconnect lifecycle) — useful when a target drops mid-session and you need to see why reconnect didn't recover it.

NameTypeReqDescription
eventAppKeystringWhen events=true, filter the event log to a single appKey (format: '<port>-<deviceId>').
eventLimitnumberWhen events=true, show only the last N events. Default: 50.
eventsbooleanInclude the recent connection event log (lifecycle: connect, close, reconnect attempts/failures, stale-target, etc). Default: false.

No output schema declared.

No examples provided.

get_images ~355

Access the shared image buffer containing screenshots from all tools (ios_screenshot, android_screenshot, ocr_screenshot, tap verification). Returns metadata only by default — use id or groupId+frameIndex to retrieve actual image data. Tap burst verification stores frame groups here when burst=true is used. PURPOSE: Retrieve prior screenshots — especially tap burst frames — without re-taking them, for visual diffing or reviewing transient UI states. WHEN TO USE: After tap(burst=true) reports transientChangeDetected, or to compare before/after frames without another screenshot round-trip. WORKFLOW: tap(burst=true) -> note verification.burstGroupId -> get_images(groupId, frameIndex=N) to inspect individual frames. LIMITATIONS: Circular buffer (50 entries) — old images are evicted. Metadata is cheap; fetching image data is not — request specific ids, not bulk. GOOD: get_images({ list: true }); get_images({ groupId: "burst-abc", frameIndex: 2 }) BAD: get_images() with no filter when buffer is full — floods context. Use list:true or last:N first.

NameTypeReqDescription
clearbooleanClear the buffer
frameIndexnumberRetrieve a specific frame from a group (requires groupId)
groupIdstringList frames in a group (metadata only), or combine with frameIndex to retrieve a specific frame
idstringRetrieve a specific image by ID (returns image data)
lastnumberReturn the N most recent entries (metadata only)
listbooleanList all entries and groups (metadata only, no image data)
sourcestringFilter entries by source

No output schema declared.

No examples provided.

get_license_status ~53

Get your installation ID, license tier, and this month's usage against the free cap. Shows the Installation ID (needed to link Pro in the dashboard), current tier, cache validity, and calls used / remaining this month.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

get_log_details ~241

Get the full payload of a single log event — complete stack trace, backtrace, or oversized message. PURPOSE: Expand one row from get_logs into its full text. A crash row collapses a 60-line backtrace; this returns all of it. WHEN TO USE: After get_logs shows an event you need to read in full (a crash, an exception, a large payload). WORKFLOW: get_logs -> copy the id (e.g. "n7") -> get_log_details(id="n7"). LIMITATIONS: Ids are valid until that device's buffer rolls over or clear_logs runs, not for the whole server session — call get_logs again to get fresh ones. Reads the buffer — it does not re-query the device. GOOD: get_log_details({ id: "n7" }) BAD: Guessing ids — always take them from get_logs.

NameTypeReqDescription
idstringyesEvent id from get_logs (e.g. "n7")
maxLengthnumberMax characters of payload (default: 4000, 0 for unlimited)
verbosebooleanDisable truncation entirely

No output schema declared.

No examples provided.

get_logs ~637

Retrieve console logs from connected React Native app. Tip: Use summary=true first for a quick overview (counts by level + last 5 messages), then fetch specific logs as needed. PURPOSE: Pull captured console output (log/warn/error/info/debug) from the in-memory buffer, and optionally native device logs (crashes, ANRs) via source="native". WHEN TO USE: Start of any log-driven investigation, verifying a code change picked up via Fast Refresh, or confirming a reported error actually fires. WORKFLOW: scan_metro -> get_logs(summary=true) -> narrow with search_logs(text="...") or get_logs(level="error") -> clear_logs between reproductions. LIMITATIONS: Circular buffer (~500 entries). Only captures logs emitted after the app connected; pre-connect logs are lost. GOOD: get_logs({ summary: true }) then get_logs({ level: "error", maxLogs: 20 }) BAD: get_logs({ maxLogs: 500, verbose: true }) as a first call — floods context; start with summary=true.

NameTypeReqDescription
devicestringRN device name (substring). Omit for all devices; see get_apps.
epochFilter by app run. 'current' = the live run only; a number targets a specific run; omit or 'all' for everything including pre-restart data (default).
kindstringFilter native/merged events by kind. Omit for all kinds.
levelstringFilter by log level (default: all)
maxLogsnumberMaximum number of logs to return (default: 50)
maxMessageLengthnumberMax characters per message (default: 500, set to 0 for unlimited). Tip: Use lower values for overview, higher when debugging specific data structures.
minLevelstringRelevance floor for native events (default: warn). Crashes and ANRs are always returned regardless. Lower to 'debug' to see native library loading.
sincestringNative acquisition window — ISO timestamp or a duration like "5m". Widens the device query; already-seen events are still deduped.
sourcestringWhich log stream to read. 'js' (default) = console output over CDP, instant. 'native' = device logs (Android logcat / iOS os_log) filtered to this app — surfaces crashes, ANRs and OOM kills that neve…
startFromTextstringStart from the first log line containing this text
summarybooleanReturn summary statistics instead of full logs (count by level + last 5 messages). Use for quick overview.
verbosebooleanDisable all truncation and return full messages. Tip: Use with lower maxLogs (e.g., 10) to avoid token overload when inspecting large objects.

No output schema declared.

No examples provided.

get_network_requests ~448

Retrieve captured network requests from connected React Native app. Shows URL, method, status, and timing. Note: On Bridgeless targets (Expo SDK 52+) without the SDK, capture may miss early startup requests. Install execbro-sdk for full capture with headers and response bodies. Tip: Use summary=true first for stats overview. PURPOSE: Inspect HTTP traffic the app made since connection — URLs, methods, status codes, and timings — to debug API, auth, and caching issues. WHEN TO USE: User reports a failed login/load, slow screen, or wrong data. Confirm a request fired, check its status, and pivot to get_request_details for headers/body. WORKFLOW: scan_metro -> reproduce action -> get_network_requests({ summary: true }) -> get_network_requests({ status: 500 }) or search_network -> get_request_details(id). LIMITATIONS: Bridgeless targets without the SDK may miss pre-connect requests and response bodies — install execbro-sdk for full fidelity. GOOD: get_network_requests({ summary: true }) then get_network_requests({ urlPattern: "/login", status: 401 }) BAD: get_network_requests({ maxRequests: 500 }) as the first call — start with summary=true.

NameTypeReqDescription
devicestringRN device name (substring). Omit for all devices; see get_apps.
epochFilter by app run. 'current' = the live run only; a number targets a specific run; omit or 'all' for everything including pre-restart data (default).
maxRequestsnumberMaximum number of requests to return (default: 50)
methodstringFilter by HTTP method (GET, POST, PUT, DELETE, etc.)
statusnumberFilter by HTTP status code (e.g., 200, 401, 500)
summarybooleanReturn statistics only (count, methods, domains, status codes). Use for quick overview.
urlPatternstringFilter by URL pattern (case-insensitive substring match). Also matches GraphQL operation names (e.g. "GetCharacters"), since every GraphQL call shares one URL.

No output schema declared.

No examples provided.

get_refresh_status ~351

Pull-style probe: did the JS runtime accept a Fast Refresh (HMR) update since `since`? Returns lastUpdateAt, updateCount, and recentUpdates from a 32-entry ring buffer fed by a recorder around __ReactRefresh.performReactRefresh (preferred) or \$RefreshReg\$ (fallback). PURPOSE: Confirm an edit landed in the running app without polling logs or screenshots. After editing TSX, wait ~2s then call with `since` = a Date.now() captured BEFORE the edit. updateCount > 0 means Fast Refresh accepted. WHEN TO USE: After editing .tsx/.ts files (prefer over reload_app). To distinguish runtime acceptance (this) from Metro build state (get_bundle_status). FILTER: `since` (epoch ms) keeps entries with at > since. `sincePath` (substring) matches modulePath — available on the \$RefreshReg\$ path but often omitted on performReactRefresh; if so the filter matches nothing — drop it. LIMITATIONS: A full reload resets the buffer (next call reports `recorder just installed`). Edits to non-React utility files still increment. Requires the React 18+ refresh runtime. SEE ALSO: get_bundle_status (did Metro compile?), get_bundle_errors (compile failures), reload_app (force full reload).

NameTypeReqDescription
devicestringRN device name (substring). Omit for default; see get_apps.
sincenumberEpoch ms; only count refresh entries with at > since. Capture Date.now() before your edit.
sincePathstringSubstring matched against entry modulePath. Must not contain double quotes. Omit on builds where modulePath is unavailable.

No output schema declared.

No examples provided.

get_request_details ~303

Get full details of a specific network request including headers, body, and timing. With the SDK installed, includes full request/response bodies. Without SDK, bodies are not available on most targets. Use get_network_requests first to find the request ID. PURPOSE: Drill into a single network entry — full request/response headers, body, status, and timing breakdown. WHEN TO USE: After get_network_requests or search_network returns a suspect ID and you need the payload to diagnose. WORKFLOW: get_network_requests / search_network -> copy id -> get_request_details(requestId). LIMITATIONS: Bodies require the execbro-sdk in the app; on CDP-only targets response bodies are missing. Large bodies are truncated — raise maxBodyLength. GOOD: get_request_details({ requestId: "42", maxBodyLength: 4000 }) BAD: Guessing requestIds — always get them from get_network_requests / search_network first.

NameTypeReqDescription
devicestringRN device name (substring). Omit for all devices; see get_apps.
maxBodyLengthnumberMax characters for request body (default: 500, set to 0 for unlimited). Tip: Large POST bodies (file uploads, base64) can be 10KB+.
requestIdstringyesThe request ID to get details for
verbosebooleanDisable body truncation. Tip: Use when you need to inspect full JSON payloads.

No output schema declared.

No examples provided.

get_screen_layout ~408

Get a screen map showing visible components as an indented tree with actual screen positions. Uses measureInWindow for real coordinates and filters out off-screen components. Returns meaningful component names with text content and frame data (x,y width x height). Coordinates are delivered-screenshot pixels — the same space screenshots, get_screen_state and tap() use, so pass them through unchanged. Use extended=true to include layout styles (padding, margin, flex, backgroundColor, etc.). [PRIMARY INTERACTION TOOL — works on iOS and Android; prefer over ios_*/android_* siblings] PURPOSE: Quickest textual map of what is actually on screen right now — component names, positions, and text — so you can plan taps and inspections without guessing. WHEN TO USE: First step whenever the user asks "what's on screen", "why is X covering Y", or before tapping a visually ambiguous element. WORKFLOW: get_screen_layout -> find_components(pattern="...") or inspect_component(componentName="...") -> tap(testID=...) -> get_screen_layout again to confirm. LIMITATIONS: pass coordinates straight to tap(), which handles conversion — never multiply by devicePixelRatio yourself. GOOD: get_screen_layout({ extended: true }) BAD: get_screen_layout({ summary: true }) when you actually need to pick a specific element — summary hides the tree. SOURCE: file:line for an element? inspect_at_point(x, y).

NameTypeReqDescription
devicestringRN device name (substring). Omit for default; see get_apps.
extendedbooleanInclude layout styles (padding, margin, flex, backgroundColor, borderRadius, etc.) for each component. Default: false for compact output.
summarybooleanReturn only component counts by name instead of full tree (default: false)
timeoutMsnumberPer-call timeout in milliseconds. Default: 5000; bumped to 15000 when extended=true. Hard cap: 120000.

No output schema declared.

No examples provided.

get_screen_state ~487

Screenshot-free snapshot of the current screen: active route + params, blocking overlays (sheets, modals, alerts), and every on-screen element merged top-to-bottom within reachability groups. Call after any tap or navigation to orient before the next action. Each line carries an (x, y) center + frame bounds (so anything is a tap(x, y) target), typed by a leading marker: 🔘 pressable (with component JSX tag, label, testID, onPress hint), 📝 text, 🖼 image (with src/alt). Elements covered by an open overlay are grouped under 🚫 Blocked — visible for context, but taps will NOT reach them until the overlay closes. WHEN TO USE: After every tap/swipe that may navigate, and to read screen content (prices, labels, which image loaded) without a screenshot+OCR round-trip. COORDINATES: delivered-screenshot pixels — the same space as ios_screenshot/android_screenshot, get_screen_layout, inspect_at_point, measure and tap(). Pass them through unchanged; never scale by devicePixelRatio yourself. LIMITATIONS: route is null without React Navigation / Expo Router. Requires a live Metro connection. HISTORY: includeHistory=true appends the route trail (dwell + origin per screen). SOURCE: this lists what is on screen, not where it lives in code — for the file:line that renders an element, call inspect_at_point(x, y). SEE ALSO: get_screen_layout for the full hierarchical component tree (deep inspection) — this gives a flat, tap-ready content list instead.

NameTypeReqDescription
devicestringRN device name (substring). Omit for default; see get_apps.
fullTextbooleanEmit each text node's full string instead of the 80-char truncation. Default false.
includeHistorybooleanAppend the route trail — which screens the app has been on, most recent first, with dwell time and the route each was entered from. Recorded from connection time; an app restart shows an epoch divide…
pressablesOnlybooleanReturn only route + overlays + pressables (the lean orientation snapshot), omitting on-screen text and images. Default false.

No output schema declared.

No examples provided.

get_usage_guide ~93

Get recommended workflows and best practices for using the debugging tools. Call without parameters to see all available topics with short descriptions. Call with a topic parameter to get the full guide for that topic.

NameTypeReqDescription
topicstringTopic to get the full guide for. Available topics: setup, inspect, layout, interact, logs, network, state, bundle, feedback. Omit to see the overview of all topics.

No output schema declared.

No examples provided.

input_text ~531

Write text into a React Native TextInput and verify it landed. [PRIMARY INTERACTION TOOL — works on iOS and Android; prefer over ios_*/android_* siblings] PURPOSE: Set a field's text and confirm, by reading the value back, that the field holds exactly what you sent. WHEN TO USE: Any text entry in a React Native app. Pass testID (or component/textMatch) and this tool focuses the field itself — no separate tap needed. WORKFLOW: get_screen_state to see the fields -> input_text({ testID, text }) -> read `verified`. VERIFICATION: the write is read back and compared EXACTLY. A mismatch retries once, then fails with `sent` vs `landed`. A success means the field really holds your string. AMBIGUITY: if the target matches several inputs the tool refuses and returns a numbered candidate list (label, placeholder, value, testID) — pick one with `index` rather than guessing. Forms routinely share a placeholder across every field. KEYBOARD: after the text is in, the software keyboard is raised on a best-effort basis so keyboard-up layout can be inspected. Failure there is reported, never fatal. LIMITATIONS: fields with no onChangeText (uncontrolled, or non-RN) fall back to the platform driver, which is US-keyboard only — non-ASCII fails there and the result may be verified:false. GOOD: input_text({ testID: "new-topic-title", text: "Q3 budget", replace: true }) BAD: input_text({ text: "..." }) with nothing focused — pass a target instead.

NameTypeReqDescription
componentstringTarget by React component name (case-insensitive substring), e.g. 'FormInput'. Use when there is no testID.
devicestringRN device name (substring match). Omit when one app is connected; see get_apps.
indexnumberZero-based choice when the target matches several inputs. The response's candidate list gives the indexes.
replacebooleanReplace the field's contents instead of appending. Default false (append).
testIDstringTarget the input with this testID. Most reliable — the tool focuses it itself, no prior tap needed.
textstringyesThe text to write into the field.
textMatchstringTarget by the field's visible label, placeholder, or current value (case-insensitive substring). NOTE: this picks WHICH field to write to; `text` is what gets written.

No output schema declared.

No examples provided.

inspect_at_point ~432

Inspect layout AND props at (x, y). Returns FRAME PER ANCESTOR (position/size in delivered-screenshot pixels, the same space as screenshots/get_screen_state/tap, for every ancestor that hit-tested the point) + the innermost component's PROPS (handlers as [Function], refs, custom props like onPress/data/testID). Pure JS hit-test via fiber + measureInWindow — no overlay toggled, zero visual side effect. Works on Paper and Fabric. PURPOSE: Layout/props diagnosis — "where is each ancestor positioned, and what props does the touched component expose?" WHEN TO USE: A button is clipped, hit area is wrong, animated frame is unexpected — or you need handler/ref/non-style props. Also preferred for tight loops (no overlay flicker). WORKFLOW: screenshot or get_screen_state → take the coordinate as-is → inspect_at_point(x, y). LIMITATIONS: Style is the node's own style object, not the merged cascade. `frame` is the element's own box; `hitFrame` (when present) is the innermost node actually under the point. SOURCE: also returns `source: {file, line, column}` for the component at the point, plus the owner chain as `Source ancestors` (set source=false to skip in tight loops).

NameTypeReqDescription
devicestringRN device name (substring). Omit for default; see get_apps.
includeFramebooleanInclude position/dimensions (frame) in the output (default: true)
includePropsbooleanInclude component props in the output (default: true)
sourcebooleanResolve the component's source file and line via Metro symbolication. Default true. Set false to skip in tight loops.
xnumberyesX coordinate in screen space — take it straight from a screenshot, get_screen_state or get_screen_layout. No conversion.
ynumberyesY coordinate in screen space — take it straight from a screenshot, get_screen_state or get_screen_layout. No conversion.

No output schema declared.

No examples provided.

inspect_component ~528

Inspect a specific React component by name. **DRILL-DOWN TOOL**: Use after get_screen_layout or find_components to identify which component to inspect. Returns props, style, state (hooks), and optionally children tree. Use childrenDepth to control how deep nested children go. [PRIMARY INTERACTION TOOL — works on iOS and Android; prefer over ios_*/android_* siblings] PURPOSE: Reveal a mounted component's live props, hook state, and (optionally) child subtree so you can reason about why it renders the way it does. WHEN TO USE: User asks "why is this button disabled", "what props does X receive", or you need to confirm state changed after a tap. WORKFLOW: get_screen_layout or find_components -> inspect_component(componentName="Foo") -> tap or execute_in_app to change state -> inspect_component again. LIMITATIONS: Requires the component to be currently mounted in the fiber tree. Name matching is exact; use find_components for fuzzy/regex lookup. GOOD: inspect_component({ componentName: "SneakerCard", index: 0 }) BAD: inspect_component({ componentName: "Card" }) when many Card instances exist — pass index or narrow via find_components.

NameTypeReqDescription
childrenDepthnumberHow many levels deep to show children (default: 1 = direct children only, 2+ = nested tree)
componentNamestringyesName of the component to inspect (e.g., 'Button', 'HomeScreen', 'FlatList')
devicestringRN device name (substring). Omit for default; see get_apps.
includeChildrenbooleanInclude children component tree
includeStatebooleanInclude component state/hooks (default: true)
includeStylebooleanInclude flattened style on each child entry (only with includeChildren). Use when debugging 'why isn't X style applying' or cascade-like inheritance on nested elements (e.g., textAlign on an inner Te…
indexnumberIf multiple instances exist, which one to inspect (0-based index, default: 0)
shortPathbooleanShow only last 3 path segments (default: true)
simplifyHooksbooleanSimplify hooks output by hiding effects and reducing depth (default: true)
timeoutMsnumberPer-call timeout in milliseconds. Default: 5000. Hard cap: 120000.

No output schema declared.

No examples provided.

inspect_global ~374

Inspect a global object (or a dotted path into one) to see its properties, types, and whether they are callable functions. Use this BEFORE calling methods on unfamiliar objects to avoid errors. PURPOSE: Surface the shape of a global (Apollo client, Redux store, Expo Router, SDK-registered store, etc.) — keys, types, and which members are callable — without executing arbitrary code. WHEN TO USE: After list_debug_globals identifies a promising global and before you try execute_in_app on it. WORKFLOW: list_debug_globals -> inspect_global(objectName="__APOLLO_CLIENT__") -> execute_in_app("__APOLLO_CLIENT__.cache.extract()"). DOTTED PATHS: Pass dotted paths to drill into the SDK surface, e.g. inspect_global({ objectName: "__RN_AI_DEVTOOLS__.stores.redux" }) or "__RN_AI_DEVTOOLS__.custom.mmkv". Only identifier paths are accepted — for arbitrary expressions, use execute_in_app. LIMITATIONS: Only reads one level deep; nested objects show as a 100-char JSON preview — re-inspect the child path. Returns an error object (not a throw) when the path doesn't resolve. GOOD: inspect_global({ objectName: "__APOLLO_CLIENT__" }) | inspect_global({ objectName: "__RN_AI_DEVTOOLS__.stores.redux" }) BAD: inspect_global({ objectName: "store.getState()" }) — call expressions aren't supported; use execute_in_app.

NameTypeReqDescription
devicestringRN device name (substring). Omit for default; see get_apps.
objectNamestringyesIdentifier or dotted path of the global to inspect (e.g., '__APOLLO_CLIENT__', '__RN_AI_DEVTOOLS__.stores.redux', '__RN_AI_DEVTOOLS__.custom.mmkv')

No output schema declared.

No examples provided.

ios_boot_simulator ~107

Boot an iOS simulator by UDID. PURPOSE: Bring a specific simulator online so you can install/launch an app in it. WHEN TO USE: At session start when no simulator is running, or after switching between device models. [PLATFORM-SPECIFIC — no cross-platform equivalent; use when booting an iOS simulator] Use list_devices to find available simulators.

NameTypeReqDescription
udidstringyesUDID of the simulator to boot (from list_devices)

No output schema declared.

No examples provided.

ios_button ~207

Press a hardware button on an iOS simulator. [PLATFORM-SPECIFIC — no cross-platform equivalent; use when pressing iOS hardware buttons (HOME, LOCK, SIRI, APPLE_PAY)] Requires an iOS UI driver: AXe (recommended: brew install cameroncooke/axe/axe) or IDB (brew install idb-companion). PURPOSE: Trigger iOS hardware buttons (HOME, LOCK, SIDE_BUTTON, SIRI, APPLE_PAY) that aren't reachable via on-screen tap. WHEN TO USE: Send the app to background (HOME), lock the simulator (LOCK), or exercise Siri/Apple Pay flows.

NameTypeReqDescription
buttonstringyesHardware button to press: HOME, LOCK, SIDE_BUTTON, SIRI, or APPLE_PAY
durationnumberOptional button press duration in seconds
udidstringiOS target: UDID, simulator name, or RN device substring. Omit for booted.

No output schema declared.

No examples provided.

ios_input_text ~411

Type text on an iOS simulator. [PLATFORM FALLBACK — prefer `input_text` — it targets, focuses, writes and verifies in one call unless you specifically need native-only behavior] The text is typed into whichever field currently has focus (tap an input first). Mirrors `android_input_text` so cross-platform agents can use `<platform>_input_text` without branching on the iOS driver shell-out. PURPOSE: Send keystrokes to the focused field on an iOS simulator via the active UI driver (AXe — preferred — or IDB). WHEN TO USE: Only after an input is already focused, or when `tap(testID=...)` on the input didn't take focus for some reason. Use the testID-first flow whenever possible — it's faster and survives UI repositioning. REPLACE MODE: pass replace:true to clear the focused field first (via React onChangeText so controlled state stays consistent), then type the new value. Use for pre-filled fields where appending would corrupt the value. LIMITATIONS: AXe types via the US-keyboard HID — non-ASCII characters (Cyrillic, CJK, Arabic) may not transmit correctly. If the active driver is AXe and the text contains non-ASCII chars, prefer pasting via the simulator pasteboard or setting IOS_DRIVER=idb.

NameTypeReqDescription
devicestringOptional RN device name (substring match) — needed by replace:true when multiple RN apps are connected, to disambiguate which device's focused input to clear. Single-device sessions can omit.
replacebooleanIf true, clear the focused TextInput via React onChangeText before typing. Use to set a pre-filled field to an exact value without concatenation. Requires Bridgeless/Fabric.
textstringyesText to type into the currently focused field.
udidstringiOS target: UDID, simulator name, or RN device substring. Omit for booted.

No output schema declared.

No examples provided.

ios_launch_app ~139

Launch an app on an iOS simulator by bundle ID [PLATFORM-SPECIFIC — no cross-platform equivalent; use when launching an iOS app by bundle ID] PURPOSE: Start an installed iOS app by its bundle ID so the next tool calls hit a running process. WHEN TO USE: After ios_terminate_app or an install, or when the app isn't foregrounded before interaction.

NameTypeReqDescription
bundleIdstringyesBundle ID of the app (e.g., com.example.myapp)
udidstringiOS target: UDID, simulator name, or RN device substring. Omit for booted.

No output schema declared.

No examples provided.

ios_open_url ~249

Open a URL in the iOS simulator (opens in default handler or Safari). PURPOSE: Drive an iOS simulator into a deep link or universal link entry point so you can exercise routing from an external entry. WHEN TO USE: Testing deep-link handlers, universal link routing, OAuth/SSO callback URLs, or any flow that enters the app via a URL. WORKFLOW: ios_boot_simulator -> ios_launch_app (or have the app running) -> ios_open_url -> ios_screenshot / get_screen_layout to verify the target screen rendered. GOOD: ios_open_url(url="myapp://product/42") to land directly on a product screen. BAD: ios_open_url(url="...") used as a substitute for in-app navigation when the user would normally tap — prefer `tap` for normal interaction flows. [PLATFORM-SPECIFIC — no cross-platform equivalent; use when testing iOS deep links or universal links]

NameTypeReqDescription
udidstringiOS target: UDID, simulator name, or RN device substring. Omit for booted.
urlstringyesURL to open (e.g., https://example.com or myapp://path)

No output schema declared.

No examples provided.

ios_screenshot ~396

Take a screenshot from an iOS simulator. Returns the image plus a screen-state summary: active route (name + navigation stack), overlay-grouped tappable elements (pressables behind an open sheet/modal are excluded), component names as JSX tags, labels, testIDs, and frames — all in ready-to-tap pixel coordinates. Prefer tap(text="...") when text is exact and unique; otherwise use tap(x, y) with coordinates from the list — this is the most reliable way to tap icons or visually-identified elements. Use component names for inspect_component/find_components. PURPOSE: Snapshot what the user sees on iOS AND get tap-ready pressables + a structured component map in one call. WHEN TO USE: Any visual verification, before/after comparison, or as the starting point for tapping UI by coordinates. WORKFLOW: ios_screenshot -> pick element from pressables -> tap(x, y) or tap(testID=...) -> ios_screenshot to verify. LIMITATIONS: Requires a booted iOS simulator (simctl). For physical devices or system dialogs without RN, combine with tap(..., native=true). GOOD: ios_screenshot() BAD: ios_screenshot({ udid: "guess" }) with a made-up UDID — run list_devices first. SOURCE: to jump from a pixel to the code that renders it, call inspect_at_point(x, y) — it returns the absolute file and line.

NameTypeReqDescription
devicestringAlias for `udid` — same accepted values. Provided for consistency with tap/get_screen_layout/get_screen_state, which all use `device`. If both are given, `udid` wins.
outputPathstringOptional path to save the screenshot. If not provided, saves to temp directory.
udidstringiOS target: UDID, simulator name, or RN device substring. Omit for booted.

No output schema declared.

No examples provided.

ios_terminate_app ~133

Terminate a running app on an iOS simulator [PLATFORM-SPECIFIC — no cross-platform equivalent; use when force-terminating an iOS app] PURPOSE: Force-kill an iOS app process so the next launch starts from a cold state. WHEN TO USE: To reset app state fully (beyond what reload_app does), or before reinstalling a new build.

NameTypeReqDescription
bundleIdstringyesBundle ID of the app to terminate
udidstringiOS target: UDID, simulator name, or RN device substring. Omit for booted.

No output schema declared.

No examples provided.

list_debug_globals ~321

List globally available debugging objects in the connected app (Apollo, Redux, React DevTools, etc.). PURPOSE: Enumerate the app's globalThis.* surface so you know which stores, clients, and debug hooks you can drill into. WHEN TO USE: Start of a state-debugging session, or when you don't know whether the app exposes a Redux/Apollo/Zustand handle. WORKFLOW: list_debug_globals -> inspect_global(objectName="...") -> execute_in_app for reads/mutations. SDK INTEGRATION: When react-native-ai-devtools-sdk's init({ stores, navigation, custom }) was called, the response includes an sdk.paths array of dotted paths (e.g. __RN_AI_DEVTOOLS__.stores.redux). Pass them to inspect_global or execute_in_app. RN NAMESPACE: The rn field reports globalThis.__rn__ — a curated set of seven RN modules (I18nManager, PixelRatio, Platform, StyleSheet, AppRegistry, NativeModules, Dimensions) populated by SDK exposeRnGlobals() or the executor's fallback bootstrap. Use paths like __rn__.Platform.OS. rn=null → bootstrap not yet run; keys=[] → ran but no match. OUTPUT: { sdk: {...}|null, rn: {keys, hint}|null, categories: {...} } LIMITATIONS: Only sees variables explicitly assigned to a global. Module-scoped state is invisible — expose it first or use the SDK.

NameTypeReqDescription
devicestringRN device name (substring). Omit for default; see get_apps.

No output schema declared.

No examples provided.

list_devices ~225

List every iOS simulator, Android emulator, and connected physical device on the host machine, in one structured response. PURPOSE: Single discovery entry point. Returns booted+shutdown iOS sims (from simctl), running+stopped Android emulators (from `emulator -list-avds` cross-referenced with `adb devices`), and attached physical devices. Each row is enriched with `rnConnected` when an RN app from get_apps matches the same identifier. WHEN TO USE: Before tap/swipe to pick a device, when a tool reports an ambiguous-device error, or to check whether a simulator is booted before targeting it. WORKS WITHOUT RN: No Metro connection required. Safe to call before scan_metro. WORKFLOW: list_devices -> tap({ device: '<udid-or-serial-or-name>', ... }) SEE ALSO: get_apps for RN-specific connection details (RN version, JS engine, network capture mode).

NameTypeReqDescription
refreshbooleanForce re-query of simctl/adb/emulator instead of returning cached results (5s TTL).

No output schema declared.

No examples provided.

logbox ~535

Interact with React Native's LogBox overlay (dev mode only). Actions: "dismiss" clears all entries and returns their content. "push" displays a message in the LogBox error banner (visible to the developer watching the device). "ignore" adds patterns to suppress future LogBox entries for this session. "detect" reads current LogBox state without modifying it. Only works in __DEV__ mode — LogBox does not exist in production builds. PURPOSE: Control RN's on-device red/yellow overlay — clear it when it blocks UI, suppress noisy repeats, or push a message back to the developer. WHEN TO USE: Screenshot/tap reports LogBox is obstructing the screen, an error banner prevents interaction, or you want to surface info to the dev watching the simulator. WORKFLOW: logbox(action="detect") -> if present: logbox(action="dismiss") to read + clear -> continue UI work. Use action="ignore" with patterns to stop repeat noise. LIMITATIONS: Dev-only — no effect in production builds. "push" at level="warning" won't show a banner unless LogBox is already open. GOOD: logbox({ action: "dismiss" }); logbox({ action: "ignore", patterns: ["[APOLLO]"] }) BAD: Spamming logbox(action="push") for every tool step — annoys the developer.

NameTypeReqDescription
actionstringyesAction to perform: "dismiss", "push", "ignore", or "detect"
devicestringRN device name (substring). Omit for default; see get_apps.
expandedbooleanWhen true, opens the full-screen LogBox detail view instead of the minimized bottom banner. Useful for important messages with clickable URLs (default: false)
levelstringLogBox level for push (default: "error"). Only "error" shows a visible bottom banner; "warning" is stored but not visually shown unless LogBox is already open
messagestringMessage to push into LogBox (required when action="push")
patternsarrayPatterns to ignore (required when action="ignore"), e.g. ["[APOLLO]", "deprecated"]
subtitlestringAdditional info shown in the call stack area when expanded=true (default: "MCP Server"). Use for context like "License Check", "Usage Limit", etc.
targetstringWhere to push the message (default: "logbox"). "logbox" shows on device screen, "metro" outputs to Metro terminal via console.log

No output schema declared.

No examples provided.

measure ~374

Get on-screen geometry {x, y, width, height} for a named React component instance. Calls measureInWindow on the matched fiber (or its nearest host descendant for composite components). Coordinates are delivered-screenshot pixels, the same space as screenshots, get_screen_layout, get_screen_state, inspect_at_point and tap(). PURPOSE: One-shot, name-based component measurement — avoids hand-rolling fiber walks and Promise-wrapping measureInWindow callbacks in execute_in_app. WHEN TO USE: You already know the component's display name (from get_screen_layout or find_components) and just need its current bounds — e.g. to verify a layout change, compute a tap target, or compare against design specs. WORKFLOW: find_components(pattern="...") -> measure(componentName="...", index=N) -> tap(x, y) at the center, or inspect_at_point at the center to verify identity. LIMITATIONS: Returns post-layout on-screen geometry only — for static style use find_components({ includeLayout: true }). For point-based lookup use inspect_at_point. Off-screen fibers may return zeros; that's the truth, not an error. Composites with multiple host descendants return the first host descendant's bounds. GOOD: measure({ componentName: "SneakerCard", index: 0 }) BAD: measure({ componentName: "View" }) — too generic; narrow with find_components first. SEE ALSO: inspect_at_point for point-based variant; find_components({ includeLayout: true }) for static style.

NameTypeReqDescription
componentNamestringyesExact React display name to match (same matcher as inspect_component).
devicestringRN device name (substring). Omit for default; see get_apps.
indexnumber0-based index when multiple instances match (default: 0).

No output schema declared.

No examples provided.

navigate ~323

Navigate the app's router directly, and verify it actually moved. PURPOSE: Jump to a screen without tapping through the UI, with a settled before/after route check. WHY THIS EXISTS: hand-written router calls report success whenever nothing throws. A path sent to a React Navigation ref changes nothing and warns only in LogBox, so a no-op reads as a success. DESTINATIONS ARE NOT INTERCHANGEABLE: Expo Router takes paths ("/event-details?id=1"); React Navigation takes route names ("TarotNav"). The response reports which router resolved. Unknown React Navigation names are rejected before dispatch, with nearest-match suggestions. WORKFLOW: navigate({ to: "/settings" }) -> check changed -> get_screen_state. LIMITATIONS: push/replace are unavailable on a React Navigation root ref (stack-scoped). changed=false means it settled without moving; indeterminate=true means no settled reading. GOOD: navigate({ to: "TarotNav" }); navigate({ action: "back" }) BAD: navigate({ to: "/TarotNav" }) on React Navigation — that is a path, not a route name.

NameTypeReqDescription
actionstringDefault "navigate".
devicestringTarget device name (substring match).
paramsobjectRoute params, passed as the second navigate argument.
routeTablebooleanInclude the app's registered route names in the response.
tostringDestination: a path for Expo Router, a route name for React Navigation. Required unless action is "back" or "reset".

No output schema declared.

No examples provided.

ocr_screenshot ~368

RECOMMENDED: Use this tool FIRST when you need to find and tap UI elements. Takes a screenshot and extracts all visible text with tap-ready coordinates using OCR. ADVANTAGES over accessibility trees: (1) Works on ANY visible text regardless of accessibility labels, (2) Returns ready-to-use tapX/tapY coordinates - no conversion needed, (3) Faster than parsing accessibility hierarchies, (4) Works consistently across iOS and Android. USE THIS FOR: Finding buttons, labels, menu items, tab bars, or any text you need to tap. Simply find the text in the results and use its tapX/tapY with the tap command. PURPOSE: Visually locate text on screen and return coordinates safe to pass straight into tap. WHEN TO USE: Non-RN surfaces, third-party WebViews, accessibility-poor screens, or when fiber/testID strategies have failed. WORKFLOW: ocr_screenshot(platform="ios") -> scan results for the label -> tap(x=tapX, y=tapY) -> ios_screenshot to verify. LIMITATIONS: OCR accuracy degrades on very small or stylized text; icons with no label won't appear — use tap(component=...) instead. GOOD: ocr_screenshot({ platform: "ios" }) BAD: ocr_screenshot used just to view the screen — plain ios_screenshot / android_screenshot is cheaper when you don't need OCR text. SOURCE: for RN screens, inspect_at_point(x, y) returns the file and line that render an element — no OCR needed.

NameTypeReqDescription
deviceIdstringOptional device ID (Android) or UDID (iOS). Uses first available device if not specified.
platformstringyesPlatform to capture screenshot from

No output schema declared.

No examples provided.

redux_dispatch ~468

Dispatch a Redux action to the store bound to the app's <Provider>, triggering useSelector subscribers and React re-renders. Resolves the live store by walking the React fiber tree on each call (no SDK setup needed; works even if no store was registered with init()). PURPOSE: Drive state-controlled UI (loaders, modals, toasts, error overlays) without exercising the real flow (network, OTP, etc.). WHY THIS EXISTS: __RN_AI_DEVTOOLS__.stores.redux often holds a different store reference than the one passed to <Provider>, so dispatching through it updates state but does NOT notify react-redux subscribers. This tool dispatches through the actual Provider store, so views re-render. WHEN TO USE: Verify state-driven UI by seeding redux state directly. Example: dispatch app/setIsLoading: true, then ios_screenshot to confirm the loader rendered. WORKFLOW: redux_dispatch({ action: { type: 'app/setIsLoading', payload: true } }) -> ios_screenshot -> redux_dispatch({ action: { type: 'app/setIsLoading', payload: false } }). LIMITATIONS: Requires React DevTools hook (dev mode). Action must be plain JSON-serializable (no thunks/functions). If the app has multiple <Provider> roots, pass storeIndex (default 0). GOOD: redux_dispatch({ action: { type: 'app/setIsLoading', payload: true } }) BAD: redux_dispatch({ action: () => ... }) — actions must be plain objects; for thunks use execute_in_app to call your action creator.

NameTypeReqDescription
actionobjectyesPlain JSON-serializable Redux action object, e.g. { type: 'app/setIsLoading', payload: true }.
devicestringRN device name (substring). Omit for default; see get_apps.
returnPathstringOptional dotted path into the post-dispatch state to return for verification (e.g. 'app' or 'auth.user'). Omit to skip returning state — keeps the response small. Use redux_get_state for ad-hoc reads.
storeIndexintegerIndex of the Provider store to dispatch to when the app has multiple <Provider> roots (default: 0).

No output schema declared.

No examples provided.