Skip to main content
Glama

react-native-eye connects Claude Code, Cursor or any other MCP client to your app through Metro's Chrome DevTools Protocol endpoint. The agent reads the screen, taps and types, and checks logs, network and state. The app needs no SDK and no code changes.

It is built for agent speed. Composite tools run a whole interaction in one call, so the agent does not pay one model round trip per tap.

Contents

Related MCP server: React Native Debug MCP

Quick start

1. Add the server to your MCP client.

Claude Code, from your project folder:

claude mcp add react-native-eye -- npx -y react-native-eye@latest

Cursor (.cursor/mcp.json), Claude Desktop and any other client that takes the standard config:

{
  "mcpServers": {
    "react-native-eye": {
      "command": "npx",
      "args": ["-y", "react-native-eye@latest"]
    }
  }
}

Codex (~/.codex/config.toml):

[mcp_servers.react-native-eye]
command = "npx"
args = ["-y", "react-native-eye@latest"]

2. Start Metro and a dev build. Run the app in an iOS simulator or an Android emulator the way you usually do. Metro on the standard ports (8081–8083, 19000–19002) is found automatically. For any other port, pass --port 8090 in args, set METRO_PORT, or give the port to the connect tool.

3. Ask the agent.

Connect to my app and tell me what is on the screen.

The agent calls connect, then observe. The first call on each device installs the native driver once.

Requirements

Node

18 or newer

App

React Native 0.70+ or Expo SDK 54+, as a dev build with Metro and Hermes running

iOS

macOS with Xcode and a simulator. AXe CLI (brew install cameroncooke/axe/axe) is the fallback for OS input and OS layout when the native driver is unavailable or switched off

Android

adb (Android platform-tools) on your PATH

OCR (read_screen_text)

A macOS host with the Xcode Command Line Tools (xcode-select --install). The Apple Vision helper is compiled once on first use into ~/Library/Caches/react-native-eye

The JS paths (layout from the runtime, via: "js" taps and typing) need only a connected app.

What the agent can do

35 tools in five groups. Tools in bold are composite: one call instead of many. Prefer them.

Group

Tools

See the screen

observe, screenshot, get_layout, read_screen_text, get_component_tree

Act

run_flow, tap, type_text, swipe, scroll_to, press_key, navigate, open_url

Debug

check_state, get_logs, get_errors, get_network, get_state, eval_js, get_job

Measure

profile_renders, profile_js, sample_cpu, get_fps

Manage devices

connect, list_targets, list_devices, launch_app, reload_app, install_app, open_simulator, set_permission, record_video, stop_recording, ping

The composite tools:

Tool

What it does

observe

Screenshot + interactive elements + recent errors + recent logs, in one call

run_flow

A whole UI flow server-side: taps, typing, waits, assertions — aborts instantly on app errors, returns per-step results + an observe at the stop point

check_state

Current route + store state + unhandled errors

A whole flow in one call

{ "steps": [
  { "type": { "text": "a@b.c", "into": { "placeholder": "Email" } } },
  { "type": { "text": "hunter2", "into": { "placeholder": "Password" } } },
  { "tap": { "text": "Log in", "via": "os" } },
  { "wait_for": { "text": "Home", "timeout_ms": 3000 } },
  { "expect_not": { "text": "Error" } }
] }

Each step takes exactly one action (settle is a modifier) — a step with two actions is a validation error, not a silently skipped assertion. Steps run back-to-back with adaptive settling (two rendered frames, capped at 1s; override per step with "settle": 200). A redbox or uncaught exception anywhere in the flow aborts it immediately with full context, and steps that never ran are listed as such.

tap and type steps take the same selectors, via and into as the standalone tools — into accepts {testID}, {placeholder} or {label}, and a bare string is still a testID — and each step's result names the path it used. A step that asks for via: "os" gets a real touch even when a JS press was available: use it for anything driven by the responder lifecycle, and leave the default auto everywhere else.

How it works

The server reaches the app two ways and picks the cheaper one for each call.

Through the JS runtime. The server walks React's fiber tree over CDP. It measures elements and calls press and text handlers directly, with no touch involved. A press takes about a millisecond and a full-screen layout about 80 ms.

Through the device. A prebuilt driver ships in the npm package and installs itself on first use: an XCUITest runner on iOS, an instrumentation server on Android. It delivers real touches for gestures, system dialogs and native views, and types any Unicode text on Android. If it cannot start, input falls back to axe or adb.

No silent switching. Every response says which path ran: (input: js), (input: os/runner), (layout: js), (layout: os), with the reason when a path was skipped.

Measured in the project's own field tests against a busy video feed:

Native driver

The tool it replaces

iOS simulator, one feed swipe, median of 40

0.93 s

axe: 26.68 s, 3 of 40 timed out at 90 s

Android emulator, view hierarchy over a playing video, median of 10

4.60 s, 10 of 10 answered

uiautomator dump: 27.10 s, 9 of 10 failed

Tool reference

Three parameters appear on many tools.

  • device — on every device-facing tool (tap, swipe, scroll_to, type_text, press_key, screenshot, get_layout, read_screen_text, observe, run_flow, launch_app, install_app, open_url, set_permission, record_video): a udid or device-name substring. Without it the device is taken from the connected app's target, and two booted devices with no hint is an error rather than a silent guess.

  • via — on tap, type_text, scroll_to, swipe, press_key and the tap/type steps of run_flow: "js" | "os" | "auto", default auto.

    • js goes through the app's own fiber tree — the element under the resolved point is found, its nearest onPress/onChangeText is called directly, and the whole round trip is about a millisecond.

    • os delivers a real touch or HID keystroke through the simulator or device.

    • auto tries js and falls back to os, naming the reason.

    • Every response says which path ran — (input: js), or (input: os/axe — no press handler in ancestry) (os/runner, os/axe or os/adb names the OS mechanism that delivered it) — mirroring (layout: js)/(layout: os).

    • Selector, ambiguity and visibility rules are identical on both paths: the JS path replaces delivery, not judgement, so an off-screen or hidden element is refused either way.

  • connect — port, target_id (from list_targets), or device.

  • tap — duration_ms for a long press (also available on run_flow tap steps). On the JS path a duration_ms of 500 or more calls the element's onLongPress; an element that has none falls back to os, which is what the response then says.

  • swipe — direction or x1,y1,x2,y2, duration_ms, via. The JS path scrolls the container under the start point by the gesture's own vector (FlatList.scrollToOffset 0 → 640), so a feed scrolls in a millisecond instead of a 20 s touch; no scroll container under the point falls back to os with the reason.

  • scroll_to — {text | testID}, plus via and max_swipes (default 10): bring an element into view. The JS path finds the element's nearest scrollable ancestor and scrolls that container (ScrollView, FlatList/VirtualizedList, FlashList, @legendapp/list; an unrecognised container falls back to os). The OS path swipes toward the element, re-reading the layout after each swipe and stopping the moment it is visible. This is the missing half of tap's "element is off-screen — scroll to it first".

  • type_text — into chooses the field: {"testID": "…"}, {"placeholder": "…"} or {"label": "…"} (accessibilityLabel); a bare string is still read as a testID. Omitted, it types into the one TextInput on the focused, topmost screen and refuses — listing the candidates by placeholder and position — when there is more than one. Two instances of the same screen in a stack (each with the same composer) are told apart by react-navigation / react-native-screens state: the field on the focused screen wins and the response says so; a match only on a background screen is typed into with a warning. submit: true fires the field's submit handlers after typing (see press_key enter). verify (default true) reads the field back after typing and fails loudly, naming both strings, when what arrived is not what was sent. via as above; the JS path calls onChangeText, so the app's real pipeline (debounce, request, re-render) runs.

  • press_key — key: back | home | enter, via, into. back on the JS path calls the react-navigation container's goBack(); an empty stack is reported as Did not go back: nothing to go back to and deliberately does not fall through to the hardware key (on Android that would background the app). enter fires the field's own onSubmitEditing → onEndEditing → onBlur (JS only; into picks the field, otherwise the focused one).

  • navigate — action: stack | navigate | push | back | pop | pop_to_top | reset, with name/params (navigate, push), count (pop), state (reset). The react-navigation container is found by walking the React tree for its ref context (react-navigation 6/7, Expo Router), cached on globalThis.__RNE_NAV__; no app change needed. stack prints the focused branch level by level; every mutating action returns the new stack, and an action no navigator handled is an error carrying react-navigation's own message.

  • run_flow — observe controls the trailing snapshot: auto (default) attaches a screenshot and adds the full layout only when the flow failed, full always, none never.

  • get_layout — search (terms matched against text/testID), type, match: substring|exact, case_sensitive, or at: {x, y} to identify the element at a point.

  • read_screen_text — on-host OCR of the current screen (Apple Vision, nothing leaves the machine): one line per text run as <text> @x,y, coordinates in tap units usable directly with tap {x,y}. search (substring filters), languages (e.g. ["de","en"]; auto-detected by default), compare_tree (default true — lines that also exist in the JS layout are marked [tree]; prefer tap {text} for those). Sees text the layout tree cannot: images, canvases, WebViews, native dialogs.

  • screenshot — output_path saves to a file (format: png|jpeg, mask on iOS) and returns the path instead of an inline image.

  • get_component_tree — max_depth. The budget counts only components a developer actually authored: host components (RCTView, RCTText, ...) and structural wrappers (forwardRef/memo/context, styling HOCs like NativeWind's cssInterop) are free and can repeat any number of times without spending depth. RN's own dev-only infrastructure (LogBox, the debugging overlay, the root tag context) is dropped from the output entirely, not just made free. A very large tree is capped and marked truncated rather than returned unbounded.

  • get_state — path (dot-path) and depth; the value is summarised inside the app, so the result is always valid JSON. found says whether a store exists at all; resolved says whether the path walked all the way to a value — a mistyped segment reports resolved:false with failedAt and availableKeys instead of looking identical to an honest undefined.

  • eval_js — timeout_ms for a legitimately slow promise (default 10s). background: true starts the evaluation as a job and returns its id at once, for a measurement that outlives a tool call or a JS thread that is busy right now; the CDP message is queued by Hermes and runs when the thread frees. label names the job.

  • get_job — id returns a background job's status and value (or error); without id, lists jobs. profile_renders also runs as a job with background: true, so a profile can be driven with tap/swipe while it collects.

  • get_network — search (URL substring to keep), exclude (URL substrings to drop), include_dev (show dev-tooling noise: Metro/devtools ports and /symbolicate, /logs, /status on local hosts are hidden by default — the footer says how many). Query strings are cut short in the list; detail: <seq> has the full URL and bodies.

All four work on a dev build with zero app setup.

Tool

What it does

profile_renders

Which components rendered, how often, and how long, over a window: per-commit render roots with why (changed props / own state / mount), self time per component from React's profiler fields — computed per commit, not the accumulated actualDuration React leaves on the root. Hooks onCommitFiberRoot and walks only the subtrees that did work, so it costs nothing while idle and little while active

profile_js

One-shot Hermes CPU profile over CDP: busy/idle/GC split, top functions by self and inclusive time, symbolicated through Metro; the raw .cpuprofile is saved for Chrome DevTools

sample_cpu

CPU by thread from the host: main vs JS vs render/shadow, share of the app's work and busy fraction per thread, top native frames (macOS sample on the simulator, top -H on Android)

get_fps

Frame timing: real UI-thread frames on Android (dumpsys gfxinfo framestats — janky %, p50/p90/p99), and a JS-thread rAF measure on both platforms, labelled as such

  • profile_renders — duration_ms (default 5s), top, background. Needs a dev build (the React DevTools hook is what it wraps).

  • profile_js — duration_ms (default 5s), top, sampling_interval_us (Hermes may ignore it — the output says so), save (default true, to $RNE_OUTPUT_DIR or ~/Downloads).

  • sample_cpu — duration_s (default 3), app_id when the connected target does not name the app.

  • get_fps — duration_ms (default 2s), app_id. On iOS only the JS-thread number is available without native code: UI-thread frames need a physical device and xctrace's Core Animation instrument.

  • launch_app — terminate_running restarts a running app; env passes launch environment variables (iOS only).

  • open_url — opens a deeplink or universal link (simctl openurl on iOS, am start -a android.intent.action.VIEW on Android). No touch is involved, so on iOS it is by a wide margin the cheapest way to reach a screen — see the touch cost in Limitations.

  • set_permission — {service, status: "grant" | "revoke" | "reset", app_id?} (simctl privacy on iOS, pm grant/pm revoke on Android). Granting before launch is the reliable way to keep a permission alert off the screen; dismissing one costs a touch, and on iOS some services only pick up the change after the app is terminated — the response says so rather than failing quietly.

  • record_video / stop_recording — screen recording; defaults to $RNE_OUTPUT_DIR or ~/Downloads. Android clips cap at 3 minutes (screenrecord limit).

  • ping — no arguments, returns pong. It answers without touching Metro, the app or a device, which is exactly what makes it useful: it separates "the MCP server is not running" from "the app is not connected".

Configuration

Variable

Effect

METRO_PORT

Metro's port when it is not one of the standard ones. --port in args and the connect tool's port do the same

RNE_OUTPUT_DIR

Default directory for recordings and saved profiles (default ~/Downloads)

RNE_FILTERED_TOOLS

Comma-separated tool names to hide

RNE_CACHE_DIR

Where the compiled OCR helper lives (default ~/Library/Caches/react-native-eye)

RNE_NATIVE_DRIVER=off

Never install or start the on-device runner (iOS) or server (Android). Taps, swipes, typing and OS layout go through axe/adb exactly as before the driver existed. On Android it also force-stops a server left running by an earlier session

Native driver

For faster, more reliable OS input the package ships prebuilt on-device drivers; there is nothing to build (scripts/build-drivers.sh is only for contributors). On first use it installs, per device:

Platform

What is installed

iOS simulator

The runner app dev.rneye.runnerUITests.xctrunner, started as an XCUITest

Android

dev.rneye.server and dev.rneye.server.test. The app also registers an input method, switched on only while typing non-ASCII text and restored to your keyboard afterwards

If a driver cannot be installed or started, input and layout fall back to axe/adb automatically, and the response names the path that ran. RNE_NATIVE_DRIVER=off opts out entirely.

While the Android server is up it holds UiAutomation, so other UiAutomation clients on that device (Appium, uiautomator dump) fail until it is stopped (adb shell am force-stop dev.rneye.server, or RNE_NATIVE_DRIVER=off).

Privacy

No telemetry. No accounts. No cloud. The only network traffic is to localhost (Metro) and local device drivers. This is enforced by an automated test that fails the build if any external URL appears in the source, and another that fails if a license/account/feedback tool ever shows up in the tool surface.

Limitations

The short version: dev builds only, and the JS path calls handlers rather than performing gestures.

Limitation

Detail

Dev builds only

Requires Metro + Hermes; production builds are unsupported.

Single debugger (RN < 0.85)

Hermes allows one CDP client at a time; RN 0.85+ supports multiple.

Input path

A JS press calls a handler; it is not a gesture. Native views outside the React tree, system dialogs and permission alerts, Reanimated gestures that run on the UI thread, drag handles and swipeable rows, and momentum scrolling are not reproduced — those need via: "os". swipe's JS path moves a scroll container's offset — it is not a gesture either, so a swipeable row or a pull-to-refresh needs via: "os". Every response names the path it used, so a fallback is never silent.

Cold start

Logs/network before connect are missed; reload_app after connecting captures everything from the next start (it waits for the new runtime and confirms it). Gaps in the log stream are reported.

Store access

Reliable get_state needs globalThis.__RNE_STORES__ assigned in the app (falls back to common globals). Accepts either a single store (an object with getState()) or a map of named stores (e.g. { cart: { getState }, auth: { getState } }); each store in a map has its own getState() called and is exposed under its key. If a store's getState() throws, that key reports { __rneStoreError: <message> } instead of app data — the other stores in the map are unaffected.

Limitation

Detail

In-app interceptor

The network hooks live in the app, so they outlive the server. Connecting with a newer build replaces them; if an older build left hooks that cannot be removed, connect says so and reload_app clears them.

Screenshots

Inline screenshots are downscaled to 800px JPEG by default (pass full_res: true for the native PNG). Compression tries sips (macOS), then ImageMagick (magick, then convert), then ffmpeg — whichever is installed first wins, so non-macOS hosts get downscaling too, not just macOS. An inline image (compressed or, with full_res/no downscaler available, raw) that would still exceed ~7500px on a side or ~4.5MB base64-encoded is never returned — the call fails with the measured size and how to get the image anyway (output_path to save the full file, or drop full_res). File output via output_path is always native and has no size ceiling.

Layout source

get_layout/observe read element positions from the app's JS runtime when possible (Paper and Fabric, ~80ms for a full screen) and fall back to the native driver or axe/uiautomator; output is marked (layout: js) / (layout: os) — with the reason when the JS path was skipped — and a source param can force either path.

Off-screen and hidden elements

Elements scrolled out of the viewport, and those on a screen that is mounted but not on display (an inactive tab, a stack screen below the top, display:none), are listed separately and marked. Tapping one is an error, and expect/wait_for do not treat one as present. Tap points are the centre of the visible part of an element, so a control wider than the screen is still hit.

Which screen is live

Taken from react-navigation / react-native-screens state (focused, the scene index vs the navigator's, activityState). An app with a custom navigator that keeps screens mounted without those props may still report hidden screens as visible.

Text input

axe type (iOS) and input text (Android) both send positional key events and are ASCII-only on their own — non-ASCII text on those paths is refused rather than reported as typed (Android's on-device server lifts this, see below). On iOS the host's keyboard layout also rewrites what arrives: the keycodes are positional, so under a non-Latin layout the field receives different characters than were sent, and the tool used to report success anyway. type_text now refuses the OS path when the host's active layout is not ASCII-safe (naming the layout and the fix), and verify (default true) reads the field back to catch anything else. via: "js" writes through onChangeText and never touches a keyboard, so it is immune to both. On Android, while the on-device server is ready ((input: os/runner)), type_text types any Unicode through its own keyboard, which is selected for the call and then switched back. input text (the os/adb fallback) is still ASCII-only and refuses the rest.

Touch cost on the iOS simulator without the native driver

Delivering a touch through axe to a foregrounded, busy RN app measured 17–25 s (worst 29.8 s) on iPhone 17 Pro / iOS 26.2 with axe 1.7.1, while HID typing, hardware buttons and screenshots against the same app in the same state stayed at 0.3–0.6 s. The cost is per touch event, not per process, so batching does not amortise it (axe batch: 3 taps 57 s, 6 taps 117 s). The budgets are split to match — 90 s for touch (tap, swipe, and iOS press_key: "back", which is an edge swipe), 10 s for keyboard and hardware buttons — and a touch that does exhaust its budget reports whether the screen changed, so a timeout is not left ambiguous. via: "js", scroll_to's JS path, open_url and set_permission deliver no touches and are unaffected.

Error capture

In a dev build LogBox is the ErrorUtils global handler: it paints the redbox and swallows the exception, so an app crash never reaches the debugger and a plain CDP listener reports no errors under a full-screen redbox. connect chains onto that handler instead of replacing it — the redbox still shows, and get_errors, observe, check_state and run_flow's abort watermark all see the crash. A runtime with no ErrorUtils to hook is named as such at connect time rather than silently reporting no errors. Two kinds never reach it: an unhandled promise rejection (it never goes through ErrorUtils) and an error caught by the app's own ErrorBoundary. Both still show up in LogBox on screen — get_errors names both when it has nothing else to report; check with screenshot or read_screen_text.

Route in check_state

Found by walking the React tree for a react-navigation container (react-navigation 6/7, Expo Router). An app that navigates some other way can still expose a ref on globalThis.__RNE_NAV__ (or set globalThis.__RNE_ROUTE__); otherwise the route is null with the reason.

Profiling

profile_renders and profile_js need a dev build (DevTools hook, Hermes Profiler domain). profile_js stops only when the JS thread yields, so a thread that is blocked for the whole window times out — sample_cpu reads the same thread from outside and does not. sample_cpu on iOS covers the simulator only (macOS sample); get_fps UI-thread frames are Android-only.

OCR

read_screen_text runs Apple Vision on the host: macOS with the Command Line Tools only (other hosts get an error); the first call compiles a small helper (~10–30s, cached per version). It reads the native-resolution screenshot and converts boxes to tap units using the simulator's screen scale (1:1 on Android). OCR lines are text runs, not controls — they carry no press semantics, and confidence below 0.5 is flagged.

Development

npm install
npm run build        # compile to build/
npm test             # unit tests
npm run dev          # run the server from source
  • npm run test:integration runs the device tests. They need a booted iOS simulator (its udid in RNE_INTEGRATION_UDID) or an Android emulator (its serial in RNE_INTEGRATION_ANDROID_SERIAL).

  • scripts/build-drivers.sh rebuilds the native drivers under native/ (Xcode for iOS; JDK 17+ and the Android SDK for Android). Any change under native/ changes the driver version.

  • scripts/pack-test.sh packs the tarball, installs it into a fresh project and checks that the drivers arrive intact and the server answers.

Pull requests are welcome: see CONTRIBUTING.md. Report security issues privately as described in SECURITY.md.

License

MIT for react-native-eye itself. The native drivers include third-party components under Apache-2.0, BSD and MIT licenses. Attributions are in NOTICE, the Apache-2.0 text is in native/LICENSE-APACHE, and per-driver details are in native/ios-runner/THIRD_PARTY.md and native/android-server/THIRD_PARTY.md.

Available Tools

35 tools
check_stateCheck stateA

One-shot: current route + store state (optional dot-path) + recent errors. The route is discovered automatically — the react-navigation container ref is found by walking the React tree, so no app-side setup is needed (globalThis.RNE_ROUTE / globalThis.RNE_NAV still take precedence when the app publishes them). If no navigator is found the route is null and the hint says why.

NameRequiredDescriptionDefault
pathNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does real work: it discloses the auto-discovery mechanism (walking the React tree for the react-navigation container ref), the precedence rule for globalThis.__RNE_ROUTE__/__RNE_NAV__, and the explicit failure mode (route null plus a hint explaining why). It stops short of describing read-only semantics or how many/which 'recent errors' are included.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The payload summary is front-loaded in the first sentence, with mechanism and fallback following in descending priority. The parenthetical about globalThis is slightly dense but genuinely informative, and no sentence is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema and no annotations, so the description must define the response — it names the three components and the null-route edge case but never describes the actual shape (route object fields, store state serialization, error list size/format). Adequate for a call decision, incomplete for interpreting the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter has 0% schema description coverage, so the description must compensate — and it does, explaining that `path` is an optional dot-path into the store state, which tells the agent both its purpose and that it can be omitted. It does not state the default (whole store) or the path syntax, keeping it below a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action (one-shot snapshot) and enumerates exactly what it returns: current route, store state at an optional dot-path, and recent errors. This is far more concrete than the sibling names get_state/get_errors, but the description never names those siblings or explains how this combined snapshot differs from calling them separately, leaving differentiation to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The word 'one-shot' plus the combined payload imply this is the quick triage call rather than a targeted getter, and it notes no app-side setup is required. However there is no explicit when-to-use/when-not guidance and no mention of alternatives like get_errors, get_state, or observe, so routing between them is left implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

connectConnectA

Connect to a running React Native app via Metro. Optionally pass a port, a target_id from list_targets, or a device name — otherwise standard ports are scanned and the app's JS runtime is picked.

NameRequiredDescriptionDefault
portNo
deviceNo
target_idNo

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It does disclose useful non-obvious behavior: default port scanning and that the app's JS runtime is selected automatically. However it says nothing about idempotency (what happens if already connected), timeouts, failure modes, or whether an existing session is replaced — meaningful gaps for a stateful connection tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact clauses, front-loaded with the action and then the argument options. No filler, no restating the tool name, and the default-scanning fallback is stated inline rather than in a separate sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema and no annotations mean the description is the only source of behavioral detail, and while it covers parameters and default discovery, it omits what a successful connection yields and how errors surface. Adequate to call the tool, but thin for a session-establishing operation that everything else depends on.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate, and it does name all three parameters with meaning: port, target_id (sourced from list_targets), and device name. The 'or' framing also implies these are alternatives, which the bare schema does not convey. It lacks format detail for device (name vs UDID) and precedence rules if multiple are supplied.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — 'Connect to a running React Native app via Metro' — which is unambiguous and clearly distinct from sibling tools like list_targets or ping. It does not explicitly say how it differs from connect-adjacent siblings (e.g., launch_app), but the resource and transport are named precisely.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context for the two modes of use: pass one of port/target_id/device, or rely on default port scanning. It names list_targets as the source for target_id, which routes the agent correctly. It stops short of stating prerequisites (app must already be running, Metro must be up) or what to do if connection fails.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

eval_jsEvaluate JSA

Evaluate JavaScript in the app's runtime and return the result. Statements are allowed, and a promise result is awaited (await fetch(...), AsyncStorage.getItem(...)) — pass the promise itself, not await (Hermes has no async/await in evaluated code). Pass background: true for work that outlives one tool call (a long measurement, a snippet that samples for 30s) and collect the result with get_job.

NameRequiredDescriptionDefault
codeYes
labelNoName for a background job, shown by get_job.
backgroundNoStart the evaluation and return a job id immediately instead of waiting for the result.
timeout_msNoHow long to wait for a promise result (default 10000; background jobs default to 600000).

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses promise awaiting, the Hermes no-async/await constraint, and the semantics of background mode and result collection. It omits the most consequential trait — that this executes arbitrary code in the app with side effects and potential to mutate app state.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, then constraint details in a tight sequence. The parenthetical examples earn their place by showing valid promise usage, though the sentence structure is slightly dense and runs together multiple rules.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description plus schema together convey the return behavior (immediate result vs job id). What is missing is safety/error context — whether failures throw, what happens on timeout — which matters for an arbitrary-code-execution tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 75%, and the description meaningfully supplements it: it explains what background: true does behaviorally and how its result is retrieved, beyond the schema's 'return a job id immediately'. 'code' and 'label' are left to the schema, which is acceptable at this coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Evaluate JavaScript in the app's runtime and return the result'), which is unambiguous. It does not, however, distinguish itself from sibling 'profile_js', which likely also executes JS, leaving the agent to infer the boundary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete guidance on when to pass a promise vs await, and explicitly says to use background: true for work outliving one call and to collect via get_job — naming a sibling correctly. It stops short of saying when NOT to use this tool or how it differs from profile_js/get_state.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_component_treeGet component treeA

Depth-limited React component tree via the React DevTools hook, with testID and text where present. max_depth counts only components a developer actually authored — host components (RCTView, RCTText, ...) and structural wrappers (forwardRef/memo/context, styling HOCs) are free and can repeat any number of times without spending budget. RN's own dev-only infrastructure (LogBox, the debugging overlay, the root tag context) is omitted from the output entirely. Large trees are capped and marked truncated rather than returned unbounded.

NameRequiredDescriptionDefault
max_depthNo

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does substantial work: it defines what counts against budget, states that LogBox/overlay/root-tag-context nodes are omitted entirely, and that oversized trees are capped and flagged truncated rather than returned unbounded. What it leaves out is failure behavior — what happens if the React DevTools hook isn't present — and required app/connection state.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the purpose, then parameter semantics, then output filtering and truncation. Parenthetical examples are dense but each earns its place; there is no filler or restatement of the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with no output schema and no annotations, it covers content of the returned nodes, exclusions, and truncation marking. The remaining gap is the response shape (nested tree vs flat list of nodes) and the runtime precondition for the DevTools hook, which an agent would need before calling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate, and it does: max_depth is explained as counting only developer-authored components, with host components, forwardRef/memo/context and styling HOCs explicitly free and repeatable. That is a real semantic rule an agent could not derive from the bare integer schema with a 1–10 range.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: a depth-limited React component tree obtained via the React DevTools hook, enriched with testID and text. The resource is distinct enough from neighbors like get_layout or read_screen_text to be selectable, but the description never names a sibling or explicitly contrasts itself with them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: an agent can infer this is for inspecting the React component hierarchy on a connected RN app, and that dev-only infrastructure is filtered out. There is no explicit 'use this when…' or 'prefer X instead' guidance, and no mention of prerequisites such as the DevTools hook being available or the app running in dev mode.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_errorsGet errorsB

Uncaught exceptions and redboxes captured since connecting. Includes the errors LogBox swallows, which never reach the debugger on their own.

NameRequiredDescriptionDefault
limitNo

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It usefully discloses the capture window ('since connecting') and the unusual coverage (LogBox-swallowed errors that bypass the debugger), which is genuine behavioral value. It says nothing about ordering, whether results accumulate or are cleared, or what happens past the limit, so the transparency is partial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with zero filler, and the core scope is front-loaded in the first sentence before the LogBox qualifier. Every clause adds information an agent could not get from the name alone.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-annotation, no-output-schema tool, the description adequately conveys what data is returned and over what time window. However, it omits the limit parameter's behavior and any sense of result shape or volume, leaving gaps an agent would need to discover by calling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for the sole parameter 'limit', which has a max of 100 and an exclusive minimum of 0 but no documented meaning. The description never mentions limit at all, so it fails to compensate for the coverage gap; an agent must guess whether it caps error count, is a default of all, or affects ordering.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource with a verb implied by the noun: 'Uncaught exceptions and redboxes captured since connecting.' The second sentence sharpens the scope further by naming LogBox and noting these errors never reach the debugger, which implicitly separates it from get_logs. It never names the sibling explicitly, so differentiation is inferred rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit 'use this when...' guidance and no named alternative such as get_logs or read_screen_text. The usage is inferable from the content scope (errors since connecting), which is enough for an agent debugging a failure, but the boundary versus get_logs is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_fpsMeasure frame timingB

Measure frame timing for a short window. Android also reports real UI-thread frames from dumpsys gfxinfo; on the iOS simulator only the JS-thread requestAnimationFrame rate is available (UI-thread frames need a physical device and xctrace).

NameRequiredDescriptionDefault
app_idNo
deviceNo
duration_msNo

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden. It does disclose a genuinely important behavioral trait: results are platform-dependent, with real UI-thread frames only on Android/dumpsys gfxinfo and physical iOS devices via xctrace, while the iOS simulator yields only JS-thread rAF rate. It omits whether a device/app must be connected first, what the returned metrics look like, and any cost or blocking behavior of the 'short window'.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action, and the platform caveat follows efficiently. Slight vagueness in 'short window' rather than a concrete default keeps it from being maximally crisp.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no annotations, no output schema, and zero schema description coverage on three parameters, the description should compensate but doesn't. It covers platform data-quality caveats well yet leaves the agent without guidance on required setup (connected device, running app) or what the measurement returns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for three parameters (app_id, device, duration_ms), and the description never explains any of them. 'Short window' loosely gestures at duration_ms but gives no units or default, and app_id/device semantics (target selection, whether device is required) are entirely undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Measure frame timing for a short window'), which is clear on its own. It doesn't name which sibling to prefer over it (profile_renders, profile_js, sample_cpu all sound related to performance measurement), so an agent must infer differentiation from the names alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies a measurement use case but never says when to pick this over profile_renders, profile_js, or sample_cpu. The platform caveats tell the agent what data is trustworthy on Android vs the iOS simulator, which is useful context but not a when-to-use rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_jobGet background jobA

Collect the result of a background job started by eval_js (background: true). Without an id, lists every job the server is holding.

NameRequiredDescriptionDefault
idNoJob id, e.g. "j1". Omit to list all jobs.

TDQS

A3.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. It does not disclose whether reading a job result is non-destructive, whether jobs are consumed or retained after collection, whether the call blocks until completion, or what happens if the job is still running. For a job-result retrieval tool, these are meaningful gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no wasted words. The primary purpose and the originating call are front-loaded, and the no-id listing behavior follows directly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple with one optional parameter and no output schema, so the description does not need to explain return values in detail. However, it leaves job lifecycle and result-availability semantics unstated, which matters for an agent deciding whether and how to poll for results. It is adequate but incomplete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the single id parameter is already well documented in the schema. The description repeats that omitting the id lists all jobs, but adds no syntax, format, or meaning beyond that. Baseline 3 is appropriate when the schema does the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: it collects the result of a background job, and explicitly names the originating sibling call eval_js with background: true. It also distinguishes the no-id case as a listing operation, so an agent can identify the tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context for when to use the tool: after starting a background job via eval_js (background: true). It also explains the no-id behavior. It does not explicitly state when not to use it or name alternatives, but the prerequisite condition is clear enough for correct selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_layoutGet layoutA

Interactive on-screen elements with center coordinates. Elements scrolled out of view are listed separately as off-screen. Optional: filter with search terms (matched against text/testID), narrow by element type, or pass at:{x,y} to get the element at a point. source picks the capture path (js = app runtime, os = axe/uiautomator, default auto).

NameRequiredDescriptionDefault
atNo
typeNo
matchNo
deviceNo
searchNo
sourceNo
case_sensitiveNo

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden; it does disclose useful behavior — center-coordinate semantics, that out-of-view elements are segregated as off-screen, and the default capture path. It says nothing about cost, permissions, freshness of the snapshot, or the shape of the returned data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with the core result (elements + coordinates) front-loaded and the optional modifiers following. No filler, though the parenthetical enumerations compress a lot of meaning into semicolons.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% with 7 parameters, so the description has to compensate and only partly does: it explains search (matched against text/testID), type, at:{x,y}, and source (js/os/auto with default). It leaves match, case_sensitive, and device undocumented, so three of seven parameters remain opaque.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: retrieves interactive on-screen elements with their center coordinates, plus off-screen elements listed separately. Clear enough to know what you get back, but it never distinguishes itself from siblings like get_component_tree, read_screen_text, or observe, which an agent must choose between.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Offers usage patterns for the optional modes (filter by search terms, narrow by type, point query via at:{x,y}) and explains the source default, so the agent knows how to use the parameters. It gives no guidance on when to prefer this over the sibling tree/state/text tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_logsGet logsA

Recent console logs from the app. Filter by level and/or search substring. Note: only logs emitted after connect are captured — reload_app to catch cold-start output.

NameRequiredDescriptionDefault
levelNo
limitNo
searchNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations at all, the description carries the full burden and does disclose a non-obvious behavioral limit — only logs emitted after connect are captured — plus the reload_app remedy. It still omits return shape (fields, ordering), whether the buffer is capped, and whether the call blocks or polls.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences: purpose first, filtering second, and a caveat that earns its place because it prevents a wrong conclusion about missing cold-start logs. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with zero annotations, zero schema descriptions, and no output schema, the definition covers purpose and the capture-window caveat well but leaves the agent guessing about the return payload and the `limit` semantics. Adequate, not complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It adds meaning for two of three params ('filter by level', 'search substring'), but says nothing about `limit` — neither default value nor whether it returns the newest or oldest N — and the schema gives that param no description either.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource — 'Recent console logs from the app' — plus what can be filtered. It is distinct from get_errors/get_network in substance, but it never names those siblings, so the agent must infer the boundary rather than being told.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete usage context ('Filter by level and/or search substring') and an explicit alternative with a condition: use reload_app to catch cold-start output that predates connect. That is clear when-to-use guidance, though it lacks an exclusion pointing to get_errors when only errors are wanted.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_networkGet networkA

Recent HTTP requests captured in-app. The list view shortens long URLs (query strings collapse to a char count) — pass detail: for the full URL and request/response bodies. Dev-tooling traffic (Metro, Expo, react-devtools, dev polls) is hidden unless include_dev:true; exclude:[...] drops URLs by substring. Note: requests before connect are missed (cold start).

NameRequiredDescriptionDefault
limitNo
detailNo
searchNo
excludeNo
include_devNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations the description carries the full burden and does well: it discloses that the list view truncates query strings, that dev traffic is hidden by default, and that requests before connect are missed due to cold start. It implies a read-only capture but never states whether results persist or how they are ordered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences, front-loaded with what the tool returns before the modifier mechanics. Every clause carries usable information; the only mild cost is that the truncation/dev-filter/cold-start notes are packed into one paragraph.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a five-param capture tool with no annotations and no output schema, the description covers the behaviors an agent most needs (truncation, default hidden dev traffic, cold-start gap). The remaining gap is the undocumented limit/search semantics, which is minor given their conventional meaning.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It explains detail, exclude and include_dev with concrete mechanics, but limit and search are left entirely unexplained in both schema and description, so compensation is partial.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific resource (recent in-app HTTP requests) that is clearly distinct from network-adjacent siblings like get_logs and get_errors. It doesn't explicitly name a sibling to differentiate against, which keeps it from a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete conditional guidance: pass detail:<seq> to get full URLs and bodies, include_dev:true reveals dev-tooling traffic, exclude:[...] drops by substring. That tells the agent how to shape the call, though it never states when to prefer this tool over get_logs or get_errors.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_stateGet stateA

Read app store state (Redux/Zustand/custom), summarised depth-first inside the app so the result stays valid JSON. Optionally a dot-path (e.g. 'user.name') and a depth (default 3). resolved says whether the path actually walked to a value — a mistyped segment reports resolved:false with failedAt and availableKeys instead of silently looking the same as an honest undefined. Assign your store to globalThis.RNE_STORES for reliable access.

NameRequiredDescriptionDefault
pathNo
depthNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and discloses depth-first summarization to keep JSON valid, default depth, resolved/failedAt/availableKeys error semantics for bad paths, and a store-global prerequisite. It does not explicitly state read-only/no side effects or what happens if the store is not registered beyond 'reliable access'.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with purpose, then parameters, resolution behavior, and setup. Each sentence adds useful information with no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description is fairly complete: purpose, parameter usage, error-resolution semantics, and store setup. It still leaves some return-shape and side-effect details implicit, so it is not fully comprehensive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains both parameters: optional dot-path with example 'user.name' and depth default 3. It does not restate schema bounds (maximum 8, exclusiveMinimum 0), but adds meaningful semantics beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Read app store state (Redux/Zustand/custom)' with depth-first summarization. It does not explicitly contrast with sibling tools like check_state or observe, so the purpose is clear but sibling differentiation is absent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies usage for reading Redux/Zustand/custom stores and includes a setup prerequisite ('Assign your store to globalThis.__RNE_STORES__'). It gives no explicit when-to-use/when-not guidance or alternatives such as check_state, observe, or eval_js.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

install_appInstall appC

Install an app bundle on the active device (.app/.ipa on iOS, .apk on Android).

NameRequiredDescriptionDefault
deviceNo
app_pathYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. It identifies target device and bundle formats, but does not disclose whether installation overwrites an existing app, preserves app data, requires signing, or what happens on failure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The definition is a single front-loaded sentence with no filler. It is efficient, though somewhat under-informative for a mutation tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a mutation tool with no annotations, no output schema, and low schema coverage, the description is incomplete. It covers bundle formats but not prerequisites, side effects, or device selection semantics.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It usefully explains the app_path file formats, but it never clarifies the optional device parameter: whether it takes an ID, name, or defaults to the active device.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: install an app bundle on the active device. It also names accepted platform-specific bundle types (.app/.ipa/.apk), though it does not explicitly distinguish itself from siblings like launch_app or reload_app.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies the basic use case but gives no guidance on when to choose install_app over launch_app or reload_app, and it omits prerequisites such as a connected or booted device.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

launch_appLaunch appB

Launch an app by bundle id (iOS) / package name (Android) on the active device. Optional: terminate_running to restart a running app, env to pass launch environment variables (iOS only).

NameRequiredDescriptionDefault
envNo
app_idYes
deviceNo
terminate_runningNo

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It usefully discloses that env is iOS-only and that terminate_running restarts a running app, but says nothing about error behavior (e.g. app not installed), whether the call waits for launch to complete, or whether it foregrounds an already-running app.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, front-loaded with the core action and identifier format, then the optional behaviors. Almost no waste; only the unexplained device parameter leaves something missing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no annotations and no output schema, the description covers the main action and two optional parameters but omits the device parameter and any launch-failure or post-condition behavior. Adequate but with clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It explains terminate_running, env (including the iOS-only restriction absent from the schema), and the app_id format, but the device parameter is never mentioned despite the schema exposing it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (launch) and resource (an app), and clarifies the identifier format per platform (bundle id on iOS / package name on Android). It does not explicitly distinguish itself from siblings like install_app or reload_app, but the action is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: launch an app on the active device. There is no explicit guidance on when to use this versus install_app, reload_app, or open_url, nor any stated prerequisite such as the app needing to be installed first.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_devicesList devicesA

List available iOS simulators and Android devices (booted ones are marked).

NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it does disclose one useful trait beyond the name: booted devices are marked. It says nothing about whether the call is read-only in effect, whether it starts or scans for devices, latency, or how many devices are returned.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence, front-loaded with the verb and scope, with the useful "booted ones are marked" detail appended. No filler sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter lister with no output schema, the description nearly suffices: it states what is listed and that boot status is flagged. It omits the return shape (device identifiers/names) that an agent needs to feed connect or install_app, which is the main remaining gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is no parameter semantics for the description to explain; the baseline of 4 applies. The description correctly implies the tool is unfiltered and returns all devices.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource ("List available iOS simulators and Android devices") and adds the platform scope, so the agent knows what will be enumerated. It does not differentiate from the sibling list_targets, so the agent cannot tell at a glance which listing tool to pick.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: an agent can infer this is a discovery step before connect/install_app/open_simulator, but nothing says when to use it or when to prefer list_targets or ping instead. No exclusions or prerequisites are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_targetsList targetsA

List every debuggable React Native target Metro exposes (a device can have several: the JS runtime, the UI page, stale pages from earlier reloads). Pass a target_id to connect.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations, so the description carries the burden. It usefully warns that stale pages from earlier reloads appear in results — a genuine behavioral caveat that prevents the agent from assuming duplicates are bugs. However, it says nothing about failure modes when Metro is unreachable, ordering, or whether the call is cheap/safe to repeat.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the action, with the parenthetical carrying only genuinely clarifying content. Nothing is redundant and nothing needs trimming.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and no annotations, the description does the important work of explaining what comes back (targets, including several per device, and a target_id to feed connect). Missing only the preconditions for calling it and any hint of the result shape beyond target_id.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so the baseline is 4; the schema has nothing to explain. The mention of target_id is not a parameter but an output-field hint, which adds value in the absence of an output schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource ('List every debuggable React Native target Metro exposes') with a clarifying parenthetical that defines what a target is and why one device can yield several. It implicitly distinguishes itself from list_devices by noting targets live behind Metro, though it never names that sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Pass a target_id to connect' establishes the downstream relationship to the connect tool, which is real routing guidance. But there is no explicit when-to-use or prerequisite statement (e.g., must Metro already be reachable? call list_devices first?), leaving the agent to infer the workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

observeObserveA

One-shot snapshot of the screen: screenshot + interactive elements + recent errors + recent logs. Sections are independent — one failing does not lose the rest. Prefer this over separate screenshot/get_layout/get_logs calls.

NameRequiredDescriptionDefault
deviceNo
sourceNo
full_resNo
screenshotNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full disclosure burden, and it does useful work: "Sections are independent — one failing does not lose the rest" tells the agent that partial results are a normal outcome rather than a hard error. It does not mention that the tool is read-only, the cost or latency of capturing a full snapshot, or what the default device is when the device parameter is omitted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler, with the payload description front-loaded and the routing preference and failure-tolerant behavior in the second. Every clause adds information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema and no annotations, so the description must explain what the agent gets back, and it only names the four sections without describing their shape or size. Combined with the unexplained parameters, an agent knows when to call this but not how to configure it or what the payload will look like.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so all four parameters (device, source, full_res, screenshot) are undocumented in both the schema and the description. The words "screenshot" and "full" appear in prose, but the description never explains what these flags do, what the js/os/auto source enum means, or what the defaults are.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

"One-shot snapshot of the screen" states a specific verb+resource, then enumerates exactly what is bundled (screenshot, interactive elements, recent errors, recent logs). This is enough to distinguish it from the sibling tools screenshot, get_layout, and get_logs without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Prefer this over separate screenshot/get_layout/get_logs calls" gives an explicit routing rule with the alternatives named, which is exactly the guidance an agent needs. It stops short of saying when this tool should NOT be used, for example when only logs are needed or full-resolution fidelity is required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

open_simulatorOpen SimulatorB

Open the iOS Simulator app (macOS only).

NameRequiredDescriptionDefault

No parameters

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It discloses the macOS-only constraint, which is real value, but says nothing about whether the call is idempotent when the simulator is already running, whether it blocks until ready, or whether it affects existing sessions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence with the platform caveat wrapped in parentheses — front-loaded and with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, no-output-schema tool the description is nearly sufficient, but lacking annotations it should still say what state the simulator is left in and whether re-invocation is safe.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline of 4 applies; there is no parameter semantics to clarify or omit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Open the iOS Simulator app') and adds a platform qualifier, so an agent can tell it is not launch_app or open_url. It does not explicitly name those siblings, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No statement of when to reach for this versus launching an app or navigating to a URL, and no prerequisites (e.g. that a device may need to be booted first) are given. The agent must infer usage from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

open_urlOpen URLA

Open a deeplink or universal link on the active device (myapp://screen, https://…). Touch-free: it delivers no touch event, so it is unaffected by slow touch delivery and is usually the cheapest way to reach a screen.

NameRequiredDescriptionDefault
urlYes
deviceNo

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it does disclose a real behavioral trait: it delivers no touch event, so it is immune to slow touch delivery. It omits other important behavior such as what happens on an invalid or unhandled URL, whether the target app must be installed, and what the call returns.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the action and its input form, followed by a performance rationale. Every clause adds usable information and nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter tool with no output schema, this covers purpose, input form, and a genuine cost/performance consideration. The remaining gaps, device identification and error/return behavior, are minor but non-trivial since no output schema exists to fill them in.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It usefully illustrates the 'url' format with two concrete schemes and 'active device' hints that 'device' defaults, but it never explains how the 'device' parameter is identified or formatted, leaving half the parameters undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (open) and resource (deeplink or universal link) with concrete URL examples (myapp://screen, https://…), making the input shape immediately obvious. It does not explicitly distinguish itself from the related sibling 'navigate', though the 'cheapest way to reach a screen' phrasing hints at that trade-off.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'usually the cheapest way to reach a screen' remark implies when to prefer this over touch-driven tools like tap, but no alternative is named and no when-not condition is given. The agent must infer the decision rule rather than being routed explicitly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pingPingA

Health check. Returns 'pong'.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden; it does disclose the return payload ('pong'), which is the key behavioral fact for a no-argument read-only probe. It omits what happens on failure (error vs. alternate string) and whether any side effects exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two terse sentences, zero filler, with the core purpose front-loaded and the return value immediately after.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a trivial parameterless probe with no output schema, the description covers what it does and what it returns. The only gap is failure behavior, which is minor but would help an agent interpret a non-'pong' result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline of 4 applies; there is nothing further the description could reasonably add on this dimension.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action (health check) and its exact return value ('pong'), which immediately distinguishes it from functional siblings like get_state or check_state. It does not explicitly contrast itself with nearby tools, but the purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: an agent can infer this is for verifying connectivity before other calls, but the description never says when to use it or what to do with the result. No alternatives or exclusions are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

press_keyPress keyA

Press a hardware key. "back" goes up one screen — via "js" (tried first by default) calls the navigation container's own goBack() with no touch, via "os" uses the hardware key (Android) or an edge swipe (iOS). "home" is OS-only. "enter" submits a text field by firing its own onSubmitEditing, the only route to a submit handler that does not need the OS keyboard — pass into to name the field when more than one is on screen and none holds focus.

NameRequiredDescriptionDefault
keyYes
viaNo
intoNo
deviceNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses that 'js' bypasses the OS entirely by invoking the navigation container's goBack(), that 'os' degrades to a hardware key or edge swipe depending on platform, and that 'enter' fires onSubmitEditing without the OS keyboard. It omits failure behavior (e.g., what happens if no navigation container exists) and the role of the `device` parameter.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core action is front-loaded and every clause about back/home/enter earns its place by disambiguating behavior. The prose is dense with parenthetical asides and em-dashes, which slightly impedes scanning but does not waste words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no annotations, no output schema, and a nested object parameter, the description supplies most of what an agent needs: key semantics, strategy selection, and field targeting. The remaining gaps are the undocumented `device` parameter and the absence of any statement about return values or error cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does for three of four parameters: it defines the semantics of each `key` value, the two `via` strategies plus the implicit default, and what `into` matches (label/testID/placeholder) when multiple fields are present. The `device` parameter is completely undiscussed, and the 'auto' enum value is never named.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Press a hardware key') and then enumerates the three supported keys with their distinct behaviors. This is clearly distinguishable from siblings like tap, swipe, or navigate, which perform touch/gesture or route-level actions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly guides the choice of `via`: 'js' is tried first by default and calls goBack() without touch, 'os' uses the hardware key or an edge swipe, and 'home' is OS-only. It also explains when to pass `into` for 'enter'. It stops short of telling the agent when to prefer this tool over navigate or tap in a navigation flow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

profile_jsProfile JSA

Record a Hermes CPU profile for duration_ms, then report where the JS thread spent its time: busy/idle/GC split, the functions with the most self time, and the ones with the most inclusive time (symbolicated through Metro when it can). The raw .cpuprofile is saved to disk and opens in Chrome DevTools → Performance → Load. Drive the app (or leave it alone) while this runs — the profile covers whatever happens during the window.

NameRequiredDescriptionDefault
topNoRows per table (default 20).
saveNoWrite the raw .cpuprofile to disk (default true). Set false to get the summary only.
duration_msNoHow long to sample for (default 5000, max 120000).
sampling_interval_usNoSampling interval in microseconds. Hermes may ignore it and keep its own default.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden and does a solid job: it discloses that a raw .cpuprofile is written to disk, that it can be loaded in Chrome DevTools, that symbolication is best-effort ('through Metro when it can'), and that sampling is bounded by a window. It stops short of saying whether the call blocks the app, what its overhead is, or what happens when symbolication or the device connection fails.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences: capability and output first, artifact/DevTools second, capture-window advice last. No sentence is filler — even the parenthetical 'or leave it alone' resolves a real operator question.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and no annotations, the description steps up by enumerating the report contents and the on-disk artifact. It leaves a modest gap around blocking behavior, failure modes (no Metro, device disconnect), and what the summary looks like when save=false.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and each parameter already documents its default, bounds, and even Hermes' tendency to ignore sampling_interval_us, so the description can safely defer. It adds only the implicit link between duration_ms and 'the window' and no syntax or behavior beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource ('Record a Hermes CPU profile') and even previews the output (busy/idle/GC split, top self-time and inclusive-time tables). It never names the closely related siblings sample_cpu or profile_renders, so the agent has to infer the distinction from the 'JS thread' phrasing rather than being told outright.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Drive the app (or leave it alone) while this runs — the profile covers whatever happens during the window' is genuinely useful operating guidance for the capture window. But there is no explicit when-to-use/when-not or routing to alternatives such as sample_cpu (process-level CPU) or profile_renders (render profiling), which is the main ambiguity an agent would face.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

profile_rendersProfile rendersA

Count React re-renders over a window: which components rendered, how many times, how long they spent, and which update started each commit. Installs a switchable hook on the React DevTools global hook (dev builds only) that prunes untouched subtrees, so it costs roughly what the commits cost rather than what the tree costs. Nothing re-renders on its own — drive the app during the window, which usually means background: true plus tap/swipe, then get_job to collect.

NameRequiredDescriptionDefault
topNoHow many components to list by render count (default 15).
labelNoName for the background job, shown by get_job.
backgroundNoStart profiling and return a job id immediately, so you can drive the app while it runs.
duration_msNoHow long to profile (default 5000, max 60000).

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full load and does well: it names the React DevTools global hook, restricts to dev builds, explains subtree pruning and its cost model, and warns that nothing re-renders on its own. It omits lifecycle details such as whether the hook stays installed after the window or must be removed, which matters for a tool that mutates global state.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three front-loaded sentences: capability first, cost/constraint second, how-to-drive-it third. Dense with zero filler, and each sentence carries distinct information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, yet the description still tells the agent what comes back (per-component render counts, durations, initiating update) and points to get_job for collection. Only gap is post-window behavior of the installed hook.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all four parameters (top, label, background, duration_ms) are already documented in the schema with defaults and maxima. The description adds the background/get_job workflow context but no new semantics for top, label, or duration beyond what the schema states. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource ('Count React re-renders over a window') and enumerates the exact outputs: components rendered, counts, time spent, and the update that started each commit. That is specific enough to separate it from siblings like profile_js or get_fps without reading schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete operating instructions: drive the app during the window, use background: true plus tap/swipe, then get_job to collect. It never explicitly says when to prefer this over profile_js or sample_cpu, so it stops short of full alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_screen_textRead screen textA

Read the visible text off the screen with on-host OCR (Apple Vision). Works without a Metro connection and sees text the layout tree cannot: images, canvases, WebViews, native dialogs. Returns one line per recognized text run as <text> @x,y — x,y is the centre in tap units and can be passed straight to tap {x,y}. Lines that also exist in the app's JS layout are marked [tree]: prefer tap {text} for those, since an OCR box is just text, not a control. Optional: search (substring filters, case-insensitive), languages (e.g. ["de","en"]; auto-detected by default), compare_tree (default true). macOS host only; the first call compiles a small Vision helper (~10–30s, cached).

NameRequiredDescriptionDefault
deviceNo
searchNo
languagesNo
compare_treeNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden and does: it discloses the OCR engine (Apple Vision), that it runs on-host, the macOS-only platform constraint, and a first-call latency cost (~10-30s helper compile, then cached). It also explains the return line format and the [tree] marker semantics — none of which any structured field provides.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded: purpose first, then differentiators, then output format, then optional params, then platform/latency caveats. Every sentence carries information an agent needs — no filler and no restatement of the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, and the description compensates by specifying the exact line format (`<text> @x,y` in tap units) and the [tree] marker. Combined with platform limits, cold-start latency and parameter defaults, an agent has everything needed to call and interpret this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does for three of four params: search is substring/case-insensitive, languages takes codes like ["de","en"] and defaults to auto-detect, compare_tree defaults true. The `device` parameter is never mentioned, leaving one of four params undocumented in both schema and prose.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ("Read the visible text off the screen with on-host OCR") and immediately scopes it against siblings: it sees text the layout tree cannot (images, canvases, WebViews, native dialogs). An agent can distinguish this from get_component_tree, get_layout and screenshot without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use (works without a Metro connection; text the layout tree can't see), and explicit routing rules for interpreting results: lines marked [tree] should be handled with tap {text}, OCR boxes with tap {x,y}. Alternatives are named, not implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

record_videoRecord videoA

Start a screen recording (one at a time). Stop with stop_recording. Android uses screenrecord, which caps a clip at 3 minutes. codec applies to iOS only.

NameRequiredDescriptionDefault
codecNo
deviceNo
output_pathNo

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description carries the full burden. It discloses real traits (single concurrent recording, Android's 3-minute cap, codec being iOS-only) but leaves out permissions, where the file lands / how to retrieve it, and what output_path means.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four terse sentences, front-loaded with the core action and constraint; each clause (stop tool, duration cap, codec platform note) carries information the agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers concurrency, platform limits, and how to stop, but with 3 undocumented params, no output schema, and no annotations, it should also explain output_path and device to be truly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate, yet it only clarifies codec ('applies to iOS only'). device and output_path get no explanation of format, defaults, or effect, and codec's enum values already live in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource ('Start a screen recording') with scope ('one at a time'), and it explicitly names the sibling used to stop it. An agent can distinguish this from other capture tools without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the operating constraint (one at a time) and routes the agent to stop_recording to end it, plus platform-specific constraints. It does not discuss when to prefer this over screenshot, keeping it just short of explicit alternatives reasoning.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

reload_appReload appA

Reload the JS bundle and wait for the new runtime (captures cold-start logs/network on the next run).

NameRequiredDescriptionDefault

No parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description does useful work by disclosing that the tool waits for the new runtime and captures cold-start logs/network on the next run. It omits important side effects such as whether current app state is lost or whether this behaves like a restart.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with a useful parenthetical and no wasted words. The key action and the blocking behavior are immediately clear.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter action with no annotations and no output schema, the description covers the core operation and the wait behavior. It is not fully complete because it does not disclose whether reloading resets app state or other destructive side effects.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4. There is nothing schema-related for the description to compensate for.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Reload') and resource ('the JS bundle') and adds the effect of waiting for a new runtime. It is clearly distinct from launch_app/install_app, though it does not explicitly name those siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The parenthetical implies a use case: capturing cold-start logs/network on the next run. However, it gives no explicit when-not guidance or comparison with siblings like launch_app or install_app.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

run_flowRun flowA

Run a sequence of UI steps server-side in one call (tap/type/swipe/wait_for/expect/expect_not/eval). Set via:'js' to dispatch taps and typing through the app's fiber tree instead of paying a simulator touch per step; each step's report line names the path it used. Aborts on the first failure or app error, and returns an observe snapshot at the stop point. Prefer this over many separate tap/observe calls.

NameRequiredDescriptionDefault
viaNoDefault input path for every tap/type step: js dispatches the press through the app's own fiber tree (~1ms), os delivers a real simulator touch (17-25s against a hot iOS app), auto tries js and falls back naming the reason. A step's own `via` wins. Default auto.
stepsYesArray of step objects, one action each, e.g. [{tap:{text:'Login'}},{expect:{text:'Home'}}]
deviceNo
observeNoTrailing snapshot: auto (default) = screenshot always, full layout only if the flow failed; full = both; none = neither.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations, so the description carries the burden, and it discloses key runtime semantics: aborts on the first failure or app error, and returns an observe snapshot at the stop point. It also notes that each report line names the input path used. It does not state whether steps already executed before the abort remain applied to the app state (no rollback semantics), which is the main missing behavioral fact for a mutating batch tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the purpose and the alternative, with no filler. The middle clause about fiber-tree dispatch and per-step path naming partly duplicates the via enum description already in the schema, which is minor redundancy but keeps it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description does cover the return behavior (stop-point observe snapshot, per-step report lines), which is the right call. But for a tool whose required parameter is an array of untyped step objects, the agent is left without the step vocabulary at the payload level (what fields tap/type/swipe/wait_for/expect take), so it cannot reliably construct a multi-step flow from this description alone.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The core required parameter, steps, has an unstructured item schema (additionalProperties: {}), and the description compensates with a list of step kinds and a short example, which is real added meaning. However, via and observe already have detailed enum descriptions in the schema, so the description mostly restates them rather than adding new semantics, and the payload shape of each step kind remains undefined.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — 'Run a sequence of UI steps server-side in one call' — and enumerates the supported step kinds (tap/type/swipe/wait_for/expect/expect_not/eval). It explicitly contrasts itself with the sibling tools tap and observe, so an agent can pick it without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear selection rule: 'Prefer this over many separate tap/observe calls,' naming the alternatives directly. It also explains the via:'js' tradeoff as the reason to batch. It stops short of stating when NOT to use it (e.g. a single interactive tap you want to inspect step by step), so it is strong but not fully exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sample_cpuSample CPU by threadA

Profile the running app's threads for a few seconds and report which one is hot — the UI/main thread, the JS thread, or something else. iOS simulator: macOS sample, with native call-graph frames. Android: top -H, per-thread %CPU only (no frames).

NameRequiredDescriptionDefault
app_idNo
deviceNo
duration_sNo

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does disclose valuable platform-specific behavior: macOS `sample` with native call-graph frames on iOS simulator versus `top -H` giving only per-thread %CPU on Android. It also implies a short fixed sampling window. However, it omits prerequisites (app running, permissions), failure modes on unsupported platforms, and whether sampling blocks other calls.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the purpose and outcome, followed by the platform-specific mechanism. No filler, and the em-dash structure keeps the hot-thread enumeration scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-annotation, no-output-schema tool, the description does well on explaining what comes back and how it differs by platform, but it leaves the parameter surface and prerequisites undocumented, which is significant given three optional parameters at 0% schema coverage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate for all three parameters, yet it never names app_id, device, or duration_s. 'For a few seconds' loosely hints at a duration and the platform branches hint at device, but app_id is entirely unexplained and no defaults or accepted values are given for a tool where every parameter is optional.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (profile) and resource (running app's threads) with the concrete outcome: identifying the hot thread among UI/main, JS, or other. This clearly distinguishes it from siblings like profile_js and profile_renders, which target JS work or renders rather than CPU-per-thread.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the outcome ('report which one is hot'), but the description never says when to pick this over profile_js or profile_renders, nor what prerequisites exist (does the app need to be running/foregrounded?). The agent must infer the selection criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

screenshotScreenshotA

Capture the current screen. Without output_path returns an inline JPEG downscaled to 800px (pass full_res:true for the native PNG); an image that would still be too large for the caller fails with an actionable error instead of being returned. With output_path saves to a file (format png/jpeg; mask is iOS-only) and returns the path.

NameRequiredDescriptionDefault
maskNo
deviceNo
formatNo
full_resNo
output_pathNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does real work: it discloses the 800px JPEG downscale default, the native PNG override, the actionable-error failure path when the image is too large, and that mask is iOS-only. It omits operational context such as permission or device prerequisites.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action, with the two modes laid out in a readable order. The second sentence is dense and slightly run-on, but every clause carries distinct information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema and no annotations, yet the description states what is returned in both modes (inline image vs. file path) and the failure behavior, which is the key completeness requirement here. Only the undocumented `device` parameter keeps it from being fully self-sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it explains four of five parameters: output_path (save vs. inline), full_res (native PNG), format (png/jpeg), and mask (iOS-only). The `device` parameter is left entirely unexplained, which is the main remaining gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource ('Capture the current screen') and immediately splits into two well-defined modes (inline return vs. file save). It is clear what the tool does, but it never names the obvious alternatives (record_video, read_screen_text) to sharpen the boundary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit conditions for the two main branches: 'Without output_path...' versus 'With output_path...', plus the full_res escape hatch for native resolution. It tells the agent how to choose a mode, but offers no guidance about when to reach for this tool instead of sibling capture/inspection tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

scroll_toScroll to elementA

Bring an off-screen element into view. Returns immediately when it is already visible. via: js asks the element's own scroll container to jump to it (no touch, no swipe); os swipes toward it and re-reads the layout after each swipe, stopping as soon as it appears; auto (default) tries js and names the reason when it falls back.

NameRequiredDescriptionDefault
viaNo
textNo
deviceNo
testIDNo
max_swipesNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses the early-return short-circuit when the element is already visible, that os mode re-reads layout after each swipe and stops as soon as it appears, and that auto names its fallback reason. It omits failure behavior (what happens when the element is never found), interaction with max_swipes, and the return shape.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose in one sentence, then the early-return rule, then the mode breakdown. Dense but every clause carries information; the semicolon-delimited mode list is efficient rather than padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter action tool with no annotations and no output schema, the description covers the mechanism well but leaves element targeting, device selection, swipe budget, and the return/error contract entirely unaddressed. Adequate to call it, insufficient to call it correctly on the first try.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 5 parameters, so the description must compensate. It thoroughly explains the `via` enum semantics, but says nothing about `text` vs `testID` (are they alternatives or combined? is one required?), `device`, or `max_swipes` — the latter is only obliquely implied by 're-reads the layout after each swipe'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Bring an off-screen element into view') and immediately separates itself from the sibling swipe/tap tools by noting js mode does 'no touch, no swipe'. An agent can tell this is the element-targeted scrolling tool, not a raw gesture tool, without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives concrete mode-selection guidance: js asks the element's own scroll container, os swipes and re-reads layout, auto (default) tries js then falls back. It explains why you'd pick each mode, but never states when NOT to use this tool or when to prefer siblings like swipe/navigate directly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_permissionSet permissionA

Grant, revoke or reset one privacy permission for an app, so the system alert never appears. iOS services: camera, photos, photos-add, location, location-always, contacts, contacts-limited, microphone, motion, calendar, reminders, media-library, siri, all. Android services: camera, microphone, photos, location, contacts, notifications. app_id defaults to the connected app.

NameRequiredDescriptionDefault
app_idNo
deviceNo
statusYes
serviceYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden. It does disclose the most important behavioral trait — that this bypasses the system permission alert — plus the app_id default to the connected app. It does not explain reversibility of 'reset', whether the target app must be installed/running, or what an invalid service does.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with zero filler, and the core action leads. The long service enumerations consume most of the length but each entry is functionally necessary given the free-string schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter mutation tool with no annotations and no output schema, the definition covers action, services, and one default but leaves the device parameter, reset semantics, and failure modes unexplained. Adequate to call correctly in the common case, incomplete at the edges.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate, and it does: it documents the valid service strings per platform (iOS vs Android lists differ), which the bare 'service: string' schema omits, and it explains the app_id default. The 'device' parameter and the semantics of 'reset' remain undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb triple (grant, revoke, reset) applied to a precise resource ('one privacy permission for an app'), and enumerates the valid services per platform. No sibling in the list manipulates permissions, so the agent can immediately tell this apart from tap/launch_app/observe.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'so the system alert never appears' gives a concrete decision context: use this instead of letting the OS permission dialog surface. It does not state exclusions (e.g. what to do if the app is not installed, or when to prefer manual UI handling), so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

stop_recordingStop recordingA

Stop the active screen recording and return the file path.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden; it does disclose the output (file path), which is helpful since there is no output schema. However, it omits whether the file is finalized/saved at a default location, whether the operation is idempotent, and what error occurs when no recording is running.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler; the action and its result are stated immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless stop/teardown tool, action plus return value is nearly everything an agent needs. The only real gap is failure behavior when no recording is active, which is minor but non-zero.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the description has nothing to compensate for and correctly stays silent on inputs. Baseline 4 applies for a parameterless tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Stop the active screen recording') and names the artifact produced (file path). It is clearly distinguishable from siblings like record_video, though it never names that sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'active screen recording' implies a precondition (a recording must be in progress), but the description never states what happens if none is active, nor does it point to record_video as the way to start one. Usage is inferable but not explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

swipeSwipeA

Swipe in a direction (scaled to the screen), or between explicit coordinates. via picks the delivery path: js scrolls the container under the start point by the same distance through the app runtime (no touch), os is a real simulator/device gesture, auto (default) tries js and names the reason when it falls back.

NameRequiredDescriptionDefault
x1No
x2No
y1No
y2No
viaNo
deviceNo
directionNo
duration_msNo

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses that js mode performs a container scroll with no touch, os mode is a real device gesture, and auto tries js first and reports the fallback reason. It does not cover permissions, return values, or what happens with missing parameters, but the core behavioral distinctions are unusually well explained.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The two operating modes are front-loaded in the first sentence, and the delivery-path explanation follows efficiently. The second sentence is dense but every clause adds useful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter tool with zero required parameters, no annotations, and no output schema, the description leaves important gaps: it does not clarify that at least a direction or a full coordinate pair is needed, nor does it explain duration_ms or device. It is minimally viable for the core use cases but not complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for 8 parameters, so the description must compensate. It meaningfully explains 'via' values and implies that direction and coordinate modes exist, but it does not clarify whether x1/y1/x2/y2 must be supplied together, what device selects, or what duration_ms controls.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (swipe) and two clear modes: by direction scaled to the screen, or between explicit coordinates. It is clear what the tool does, though it does not explicitly distinguish itself from the sibling scroll_to tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides useful guidance on how to choose the 'via' delivery path (js vs os vs auto), including fallback behavior. However, it gives no guidance on when to use swipe instead of sibling tools like scroll_to or tap, and does not state when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tapTapA

Tap an element by text, testID, or x+y coordinates. Pass duration_ms for a long press. via picks the delivery path (js = call the component's own press handler through the app runtime, os = a real simulator/device touch, default auto). Returns the coordinates tapped, the path used, and what changed on screen.

NameRequiredDescriptionDefault
xNo
yNo
viaNo
textNo
deviceNo
testIDNo
duration_msNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden and does well: it discloses the default delivery path ('default auto'), the two execution semantics (calling the component's own handler through the app runtime vs a real device touch), and what is returned (coordinates, path used, screen changes). It omits failure behavior, such as what happens when text/testID matches nothing or matches multiple elements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core action and targeting modes before the modifiers and the return contract. No filler or restated name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter tool with no annotations and no output schema, the description covers the essential contract including return values and the default path. The remaining gaps are the undocumented 'device' parameter and ambiguous-selector/error handling, which an agent would need in edge cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate and largely does: text, testID, x, y, duration_ms, and the via enum are all given meaning beyond their names. However, the 7th parameter 'device' is never mentioned, and the precedence between element selectors and coordinates (or whether x and y must be supplied together) is left unspecified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Tap an element') and enumerates the three targeting modes (text, testID, x+y coordinates), which cleanly separates it from siblings like swipe, type_text, and press_key. An agent can pick this tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives conditional guidance within the tool: duration_ms selects a long press, and via selects js vs os with an explicit 'auto' default. It does not name alternatives (e.g. when to prefer swipe or scroll_to instead), so exclusion guidance is absent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

type_textType textA

Type text into a text input. into selects the field by testID, placeholder or accessibilityLabel — omit it only when a single input is on screen. via "js" (default via "auto" tries it first) calls the field's own onChangeText in ~1ms and runs the app's real onChange pipeline; via "os" drives the simulator keyboard. verify (default true) reads the value back afterwards and fails loudly if it differs — the OS keyboard sends positional keycodes that a non-ASCII host keyboard layout silently rewrites.

NameRequiredDescriptionDefault
viaNo
intoNo
textYes
deviceNo
submitNo
verifyNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does it well: it explains the mechanism of each `via` mode, gives a timing figure (~1ms), states that verify defaults to true and fails loudly, and warns about positional keycodes being rewritten by non-ASCII host layouts. It omits the behavior of `submit` and `device`, which are behavioral as well as structural.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the action, then field targeting, then strategy selection, then verification — a sensible order with no filler. The em-dash clauses are dense but each carries real information; the sentence on keyboard layouts is long but earns its place as a warning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter tool with a nested targeting object, no output schema and no annotations, the description covers the hard parts (targeting ambiguity, mode choice, verification). The gap is `submit` and `device`, which an agent would have to infer from the bare schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It meaningfully documents `into` (matching by testID, placeholder, accessibilityLabel), `via` with defaults, and `verify` with its default and failure mode, but `text`, `device` and `submit` are entirely unaddressed. It also refers to `accessibilityLabel` while the schema field is named `label`, creating a naming mismatch an agent must resolve.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource: 'Type text into a text input.' An agent can immediately separate this from tap, press_key or eval_js. It does not explicitly name a sibling to contrast with, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete selection conditions: omit `into` only when a single input is on screen, and pick `js`/`os`/`auto` based on the tradeoff described. It lacks any guidance on when typing is not appropriate (e.g. use press_key for special keys) or ordering relative to tap/observe.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 35 tool updatesv0.1.0
    • First observedcheck_state
    • First observedconnect
    • First observedeval_js
    • First observedget_component_tree
    • First observedget_errors
    • First observedget_fps
    • First observedget_job
    • First observedget_layout
    • First observedget_logs
    • First observedget_network
    • First observedget_state
    • First observedinstall_app
    • First observedlaunch_app
    • First observedlist_devices
    • First observedlist_targets
    • First observednavigate
    • First observedobserve
    • First observedopen_simulator
    • First observedopen_url
    • First observedping
    • First observedpress_key
    • First observedprofile_js
    • First observedprofile_renders
    • First observedread_screen_text
    • First observedrecord_video
    • First observedreload_app
    • First observedrun_flow
    • First observedsample_cpu
    • First observedscreenshot
    • First observedscroll_to
    • First observedset_permission
    • First observedstop_recording
    • First observedswipe
    • First observedtap
    • First observedtype_text

TDQS

B3.4/5.0

Scored across 35 tools

Disambiguation4/5

Most tools target distinct resources or actions, but several composite tools intentionally overlap with atomic tools: observe vs screenshot/get_layout/get_logs, check_state vs get_state/navigate, and run_flow vs tap/type_text/swipe/eval_js. Descriptions explicitly recommend the composite tools, which keeps selection mostly clear, though press_key 'back' and navigate 'back' also overlap.

Naming Consistency4/5

Names consistently use snake_case and are mostly verb-first (list_devices, get_logs, type_text, profile_js). Minor deviations are single-word operational verbs such as tap, swipe, connect, and navigate, plus the noun 'screenshot', but the overall convention remains readable.

Tool Count2/5

With 35 tools, the surface is well beyond a tightly scoped 3–15 range and past the 16–25 'heavy' bracket. Although the server spans many React Native debugging domains, the large number of atomic plus composite tools makes the selection surface excessive for an agent.

Completeness4/5

Coverage is broad: device/app management, targets, logs/errors/network, eval and background jobs, state/component tree, OCR/layout/tap/type/swipe, navigation/flows, recording, and performance profiling. Minor gaps remain around explicit app terminate/uninstall and standalone wait/assert helpers, but launch_app terminate_running and run_flow provide workarounds.

Maintenance

ActivityNo data
ResponsivenessSyncing

Related MCP Connectors

Related MCP Servers

  • A
    license
    C
    quality
    F
    maintenance
    Provides AI agents with visibility into React applications by exposing tools to inspect component state, props, and performance metrics. It enables debugging and state analysis for both web and React Native applications through the Model Context Protocol.
    45
    4 npm
    1
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables agents and LLMs to automate, inspect, and scrape native iOS and Android apps across simulators, emulators, and real devices through a platform-agnostic interface using accessibility snapshots or screenshot-based coordinates. It provides device, app, screen, input, log, and crash management tools, including optional cloud device reservation.
    34
    55,275 npm
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Lets MCP-capable AI agents control an Expo / React Native app running live in Expo Go on a real phone, reading a compact token-cheap outline of the visible screen and performing taps, text entry, scrolling, toggles and navigation. Also exposes screenshots, layout, console logs, network requests and hardware keys, and attaches new JS errors and failed requests to the action that caused them.
    107 npm
    1
    MIT