{"name":"io.github.rn-devtools-hub/rn-devtools-hub","slug":"rn-devtools-hub","title":"rn-devtools-hub","description":"Drive a running React Native or Expo app from inside its JS runtime: see, act, prove.","url":"https://mcp.market/server/rn-devtools-hub","rating":null,"grade":"A","score":91,"certified":false,"status":"active","category":"productivity","tags":["productivity"],"presence":{"score":39,"stars":4,"forks":1,"downloads_week":604,"last_push_at":"2026-09-05T23:32:54.000Z","license":"MIT"},"uptime":null,"claimed":false,"transport":"npm","callable_via_gateway":false,"default_price_micros":0,"repository":"https://github.com/rn-devtools-hub/rn-devtools-hub","website":"https://rn-devtools-hub.github.io/rn-devtools-hub/","version":"0.22.0","remotes":[],"packages":[{"registryType":"npm","registryBaseUrl":"https://registry.npmjs.org","identifier":"rn-devtools-hub","version":"0.22.0","runtimeHint":"npx","transport":{"type":"stdio"},"packageArguments":[{"description":"Speak MCP over stdio, bridging to the local hub and starting it if needed","value":"mcp","type":"positional","valueHint":"mcp"}]},{"registryType":"npm","registryBaseUrl":"https://registry.npmjs.org","identifier":"rn-devtools-hub","version":"0.22.0","transport":{"type":"streamable-http","url":"http://127.0.0.1:8973/mcp"}}],"tools":[{"name":"advance_time","description":"Moves the frozen clock forward by ms. It moves the clock, it does NOT fire pending timers: driving the scheduler would mean replacing setTimeout under a running app.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_distribute_build","description":"Hands a build to a TestFlight group, or takes it back (action: add or remove). An internal group receives it immediately; an external one needs a beta review, which submitForReview requests in the same call. The group is matched by name or id, and an unknown name is refused with the list of real ones rather than guessed.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_expire_build","description":"Expires a build, which removes it from TestFlight for every tester. Irreversible: an expired build cannot be un-expired, only replaced by a new upload.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_list_apps","description":"Lists the apps this App Store Connect key can see (id, name, bundleId, sku). Call it when a bundle identifier is refused: the key may be scoped to other apps.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_list_beta_groups","description":"Lists the TestFlight groups of the app: name, internal or external, and the public link when one is enabled. Internal groups get a build immediately; external ones need a beta review first.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_list_builds","description":"Lists recent TestFlight builds, newest first: build number, the version they belong to, processingState (PROCESSING, VALID, FAILED, INVALID) and whether they expired. This is the answer to \"is the build I just uploaded usable yet\", which nothing inside the app can give. Defaults to the bundle identifier the project declares.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_list_versions","description":"Lists the App Store versions and the state each one is in (PREPARE_FOR_SUBMISSION, WAITING_FOR_REVIEW, IN_REVIEW, PENDING_DEVELOPER_RELEASE, READY_FOR_SALE, REJECTED...), with the build attached to each. The state field Apple returns is passed through under the name it used, because it has changed between API versions.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_phased_release","description":"Drives the phased release of a version: start it, pause it when something looks wrong, resume it, complete it to reach everyone at once, or cancel it. Apple advances the phases on its own daily schedule; this only controls the state.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_prepare_version","description":"Brings an App Store version to the point where it can be submitted, in one idempotent call: creates the version if it does not exist, attaches the build, and writes the release notes for a locale. Safe to run twice; the answer lists what it actually changed and what was already right. Nothing is submitted here, asc_submit_for_review does that.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_release_version","description":"Releases a version that Apple has approved and that is waiting on you (PENDING_DEVELOPER_RELEASE). It goes to the App Store, for everyone. Refused with the current state when the version is not actually waiting for a release.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_request","description":"Signed GET against any App Store Connect endpoint, for what the other tools do not cover (app info localizations, sales reports, custom filters). path is an absolute API path such as /v1/apps/{id}/appStoreVersions; query is passed through, including filter[...] and include. Reads only: asc_write_request is the one that changes things.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_set_whats_new","description":"Sets the \"What to Test\" note testers read on a build, creating the localization if it does not exist yet. TestFlight refuses an external distribution without one, so this is usually the step before asc_distribute_build.","write_action":false,"price_micros":0,"input_schema":null},{"name":"asc_submit_for_review","description":"Submits a prepared version to App Review. This is the step a human normally takes deliberately: after it, the version leaves your hands and Apple starts reviewing. It reuses an open review submission when there is one rather than creating a second, and returns the submission with its state.","write_action":true,"price_micros":0,"input_schema":null},{"name":"asc_upload_screenshots","description":"Uploads the screenshots capture_store_screenshots wrote to an App Store version, grouped by locale and by device class. The display type is read from each capture's pixel size and a size the table does not recognise is refused rather than uploaded as the wrong class; pass displayType to override. replace clears the existing set first, which is what a new release usually wants. Nothing is resized. ","write_action":true,"price_micros":0,"input_schema":null},{"name":"asc_write_request","description":"Signed POST, PATCH or DELETE against any App Store Connect endpoint, for the parts of the release this file does not model (pricing, in-app purchases, app info, territories). body is the JSON:API document Apple expects. The blunt instrument: it will do exactly what it is told, including things no other tool here will do.","write_action":true,"price_micros":0,"input_schema":null},{"name":"assert","description":"Checks runtime evidence. network_response RETRIES until timeoutMs for an observed response matching required urlContains, method and status; mocked responses require allowMocked:true. Success carries the response evidence. network_ok means only no observed network error, never that a request completed. Negative event assertions require current capture coverage; unavailable coverage returns ok:fals","write_action":false,"price_micros":0,"input_schema":null},{"name":"audit_accessibility","description":"Compares what React renders with what the OS exposes and reports the DIFFERENCE: pressables with no accessible name, and text or controls missing from the accessibility tree. A tool with only the accessibility tree cannot find what is missing from it. Returns conclusive:false rather than a clean report when either tree came back empty.","write_action":false,"price_micros":0,"input_schema":null},{"name":"boot_device","description":"Boots an iOS simulator by target id (sim:<udid>) and opens the Simulator app. Android emulators must be started externally.","write_action":false,"price_micros":0,"input_schema":null},{"name":"build_app","description":"Builds the app by delegating to expo run:ios, expo run:android or eas build, and streams the build's failures onto the SAME timestamped bus as the crashes and the requests. Compile error at t0, relaunch at t1, first JS crash at t2, one clock: the agent reads a continuous stream from broken code to running app. xcodebuild and gradle are delegated to, never reimplemented.","write_action":false,"price_micros":0,"input_schema":null},{"name":"capture_store_screenshots","description":"Captures the App Store and Play Store screenshots from the running app, driven by a manifest (devices from list_targets, locales, screens). Each screen is reached with the app's own dev actions (nav:*, seed:*, auth:*) and waited on with an event rather than a sleep, so the same set can be regenerated identically next release. Files are written to disk at the device's native resolution and NOTHING ","write_action":false,"price_micros":0,"input_schema":null},{"name":"compare_snapshot","description":"Compares the current screen with a named baseline and EXPLAINS the difference: the changed ratio, the bounding box, the component that owns that region with its source file and line, and what the event bus recorded since the baseline. A percentage alone says something moved; this says what to edit.","write_action":false,"price_micros":0,"input_schema":null},{"name":"export_flow","description":"Exports runtime actions and subsequent observed events. attribution:temporal means ordering, not proven causality; review background traffic before using the recording as a test. format:mcp returns replay calls, text a readable script, json the structure. Recorded failures make clean:false.","write_action":false,"price_micros":0,"input_schema":null},{"name":"export_session","description":"Exports one session as a single correlated artifact: network, console, crashes, navigation and UI changes on ONE timeline relative to the session start, plus the crash, failed-request and console-error sections an investigation opens first. Omit sessionId for the most recent session. format:\"markdown\" pastes into a GitHub issue as it is; format:\"json\" is for further processing.","write_action":false,"price_micros":0,"input_schema":null},{"name":"freeze_time","description":"Freezes the app's JS clock at an ISO instant (or now), so relative dates and time-dependent rendering stop drifting between runs. Deterministic at the JS level only: Date, new Date() and Date.now(). Native animations and Reanimated read native clocks and are unaffected.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_accessibility_tree","description":"Reads the accessibility tree the OS exposes, which is what assistive technology and any external automation see. Works when the React runtime cannot be reached (release build, WebView, native screen, splash). Android uses uiautomator; iOS needs AXe installed. Every node carries source:\"accessibility\" so it is never confused with a React node.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_app_info","description":"Returns app, device, OS, development mode and network connection information.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_capabilities","description":"Reports what the selected app attached and the exact SDK call that enables each missing capability.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_crashes","description":"Returns recent crashes and unhandled errors.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_endpoint_stats","description":"Computes calls, errors and p50/p95 latencies per endpoint from the captured requests. With nothing captured it returns {endpoints: [], capture} instead, where capture says whether the network is instrumented at all.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_events_since","description":"Returns device events after a cursor (monotonic seq). Poll with the returned cursor to follow network, console, crash, nav, screen.ready and ui.change without missing anything. Omit cursor for the most recent events.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_flow","description":"Reads and validates one project-relative .hubflow scenario.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_logs","description":"Returns captured JavaScript console entries filtered by level, text and cursor.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_native_logs","description":"Native device logs the JS console cannot see, with looping duplicates collapsed. Android: bounded logcat dump, fast (filter by app package via process). iOS: unified log dump of the last sinceMinutes (default 1); SLOW, roughly 10-30 s per minute of window, so keep the window small and filter by process. Catches crashes before the bundle loads and dev-client startup issues.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_orientation","description":"Reads the current rotation (Android).","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_overlay","description":"Says whether the expo-dev-menu floating button is currently shown, and returns the dev-menu preferences behind it.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_project_context","description":"Returns what the project DECLARES (installed versions, Expo SDK, New Architecture, JS engine, plugins), what the app ACTUALLY runs (engine, Fabric, bridgeless, TurboModules, native React Native version, mounted React renderer), and the contradictions between the two. The divergence block catches stale native builds, Expo Go running a plugin project and release bundles before any other debugging.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_recent_network","description":"Returns recent network events and explains whether an empty result means quiet traffic or missing instrumentation.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_state","description":"Reads a store the app registered with devtools.registerStore (Zustand, Redux, React Query or a custom adapter). Omit store to list what is available. path drills in with dots; for React Query it is the JSON query key.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_ui_tree","description":"Returns the visible React semantic tree with props, measured rectangles and source locations. Requires attachUiAutomation.","write_action":false,"price_micros":0,"input_schema":null},{"name":"gplay_get_track","description":"Same as gplay_list_tracks for a single track, when only production or only internal matters.","write_action":false,"price_micros":0,"input_schema":null},{"name":"gplay_list_artifacts","description":"Lists the app bundles and APKs uploaded to Play, with their version codes and sha256. Answers whether the artifact a build just produced actually reached Play, and which version code it was given.","write_action":false,"price_micros":0,"input_schema":null},{"name":"gplay_list_reviews","description":"Returns recent Play Store reviews with their star rating, text, device, Android version and the app version they were written against. Reviews name the crashes a reporter never receives and the regressions that only happen on one OEM. Play only exposes reviews from the last week or so, and none at all for an app that has never been published.","write_action":false,"price_micros":0,"input_schema":null},{"name":"gplay_list_tracks","description":"Lists every Play track (production, beta, alpha, internal and any custom one) with the releases sitting in it: version codes, status (completed, inProgress, draft, halted), staged rollout fraction and release notes. This is where a rollout still at 10% shows up, which no signal inside the app reports. Reads through an edit that is opened and immediately discarded, never committed.","write_action":false,"price_micros":0,"input_schema":null},{"name":"gplay_promote_release","description":"Takes what a track is serving and puts it in another one, then commits: internal to beta, beta to production. Release notes are carried over unless new ones are given. Promoting to production with status completed ships to every user, so the usual first step is status inProgress with a userFraction.","write_action":false,"price_micros":0,"input_schema":null},{"name":"gplay_reply_review","description":"Publishes a public reply under a Play Store review, signed as the developer and visible to everyone. One reply per review: sending another replaces the previous one.","write_action":true,"price_micros":0,"input_schema":null},{"name":"gplay_request","description":"Authenticated GET against any Play Developer API v3 endpoint, for what the other tools do not cover (subscriptions, in-app products, device tier configs). path is relative to androidpublisher/v3, e.g. /applications/{packageName}/reviews/{reviewId}. Paths under /edits are refused: an edit read outside the tools that manage one would be left open on the listing.","write_action":false,"price_micros":0,"input_schema":null},{"name":"gplay_update_track","description":"Writes the release of a track and COMMITS it, which is what makes it live: start a staged rollout (status inProgress with userFraction 0.1), widen it, halt it when something looks wrong, or send it to everyone (status completed). Omit versionCodes to keep the ones the track already serves, which is how a rollout is paused or widened without repeating them. The answer carries the track before and a","write_action":true,"price_micros":0,"input_schema":null},{"name":"gplay_upload_screenshots","description":"Uploads the screenshots capture_store_screenshots wrote to the Play listing, grouped by language and by form factor (phone, seven inch, ten inch, read from the shortest side of each capture). replace clears the existing images of that form factor first, which is what a new release usually wants. Everything happens in one Play edit that is committed at the end, so a listing is never left half updat","write_action":true,"price_micros":0,"input_schema":null},{"name":"gplay_write_request","description":"Authenticated POST, PUT, PATCH or DELETE against any Play Developer API v3 endpoint, for the parts of the console this file does not model (in-app products, subscriptions, testers). Paths under /edits stay refused even here: an edit opened outside gplay_update_track is a lock nobody closes.","write_action":true,"price_micros":0,"input_schema":null},{"name":"install_app","description":"Installs an app bundle on the target (simctl install / adb install -r).","write_action":false,"price_micros":0,"input_schema":null},{"name":"launch_app","description":"Launches the app with zero dialogs and nothing floating over the screen. iOS: simctl launch with --initialUrl (dev-client loads the given Metro URL directly, no deep link). Android: explicit-component am start with the URL as VIEW data. coldStart terminates first; the expo dev-menu onboarding is skipped automatically, and its floating action button is hidden (iOS), because it sits in its own windo","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_actions","description":"Lists the dev actions the app registered (name, label, description, argsSchema, danger). Conventions: nav:* navigate directly to a screen, auth:* instant sessions, seed:* fixtures, reset:* deterministic state.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_devices","description":"Lists the React Native devices known to the hub and their connection state.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_flows","description":"Lists versioned .hubflow scenarios in tests/hub with their latest local run.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_plugins","description":"Lists the hub plugins, which reach the services around the app rather than the app itself (App Store Connect, Google Play). For each one: whether it is configured, which tools it exposes, which of them CHANGE something (writeTools) and whether writes are enabled, the exact configuration keys still missing and where to set them, and every host it will contact. A plugin with no credentials exposes n","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_previews","description":"Lists the components the app registered with devtools.registerPreview, and whether the preview outlet is mounted.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_sessions","description":"Lists the persisted sessions, most recent first. Sessions survive hub restarts and app reloads, so an investigation can start long after the run it is about.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_targets","description":"Lists OS-level targets: iOS simulators (simctl) and Android devices/emulators (adb), with their boot state. Native tools take these targets, distinct from the JS deviceId of list_devices.","write_action":false,"price_micros":0,"input_schema":null},{"name":"mock_network","description":"Controls the requests going through the instrumented fetch: rules to stub a status and a body, or a condition among normal, offline, 3g and flaky. Failures are spaced deterministically rather than randomly, so a flaky profile stays reproducible. Mocked responses are flagged on the bus so an agent never mistakes a fixture for the backend. Only covers wrapFetch; an axios instance keeps its own adapt","write_action":false,"price_micros":0,"input_schema":null},{"name":"open_url","description":"Opens a deep link on the target (simctl openurl / am start VIEW). On Android pass appId to pin the handler and avoid the chooser.","write_action":false,"price_micros":0,"input_schema":null},{"name":"propose_flow_repair","description":"Writes a sibling .candidate.hubflow for a failed target only when recorded identity evidence strongly matches a reported candidate. It never changes assertions or the original file.","write_action":true,"price_micros":0,"input_schema":null},{"name":"query_sqlite","description":"Runs a SQLite SELECT or PRAGMA query on the connected device.","write_action":true,"price_micros":0,"input_schema":null},{"name":"query_ui","description":"Finds visible elements by semantic selector and returns values, rectangles and source locations. Retries until timeoutMs.","write_action":false,"price_micros":0,"input_schema":null},{"name":"render_component","description":"Mounts a registered component INSIDE the running app, under its real providers, session and cache: nothing to mock, unlike an isolated preview. Returns the measured rect and the rendered subtree. Verifying a component no longer means navigating to the screen that contains it.","write_action":false,"price_micros":0,"input_schema":null},{"name":"repair_adb_routes","description":"Restores adb reverse mappings lost after an emulator or USB reconnection. Defaults to Metro 8081 and the current Hub port. Omit target only when exactly one Android target is ready.","write_action":false,"price_micros":0,"input_schema":null},{"name":"resolve_source","description":"Retries Metro symbolication for a source that remained via stack after the short inline budget expired. This is separate so source enrichment never delays a successful UI action.","write_action":false,"price_micros":0,"input_schema":null},{"name":"restore_time","description":"Gives the app its real clock back.","write_action":false,"price_micros":0,"input_schema":null},{"name":"run_action","description":"Runs an action declared by the app with optional typed args (e.g. nav:packageDetail {id}). Discover actions and their schemas with list_actions. Dangerous actions must be confirmed in the MCP client.","write_action":true,"price_micros":0,"input_schema":null},{"name":"run_flow","description":"Runs a validated .hubflow with explicit expectations and writes screenshots and a human-readable report under .rn-devtools. Recorded event association is temporal, not proven causality.","write_action":true,"price_micros":0,"input_schema":null},{"name":"save_flow","description":"Saves the current action and consequence recording as a versioned .hubflow file under tests/hub by default.","write_action":false,"price_micros":0,"input_schema":null},{"name":"screenshot_native","description":"Pixel screenshot of the target screen (PNG), complementing get_ui_tree: the tree gives structure, this gives the actual rendering.","write_action":false,"price_micros":0,"input_schema":null},{"name":"send_push","description":"Simulates a remote push notification on an iOS simulator (simctl push). payload is the APNs JSON with a top-level aps key. Rendering still depends on the app having notification permission.","write_action":true,"price_micros":0,"input_schema":null},{"name":"session_start","description":"One-call bootstrap and app switch: resolve target, pre-grant permissions, launch the dev build on the given Metro server, then wait for the expected app to connect. Pass appName when several runtimes share the hub so an event from the wrong app cannot satisfy the wait. Android derives the development-client scheme from app.json when scheme is omitted.","write_action":false,"price_micros":0,"input_schema":null},{"name":"set_animations","description":"Enables or disables system animations on Android (window/transition/animator scales) for deterministic captures. Remember to re-enable at session end.","write_action":false,"price_micros":0,"input_schema":null},{"name":"set_appearance","description":"Switches the target to light or dark mode (simctl ui appearance / adb cmd uimode night). Useful before screenshots.","write_action":false,"price_micros":0,"input_schema":null},{"name":"set_location","description":"Sets the simulated GPS position: simctl location (iOS) or the emulator console geo fix (Android emulators only). Deterministic replacement for real GPS in dev.","write_action":false,"price_micros":0,"input_schema":null},{"name":"set_orientation","description":"Rotates the device. Android only: iOS simulators expose no scriptable rotation, and that limit is reported rather than faked.","write_action":false,"price_micros":0,"input_schema":null},{"name":"set_overlay","description":"Shows or hides the expo-dev-menu floating button, immediately and without relaunching the app. That bubble lives in its own window above everything the app renders, so no UI tree can show it and it swallows the taps meant for whatever is underneath, the button in the top corner of the iOS photo picker being the usual casualty. Hide it before driving a native modal, put it back afterwards. Runtime ","write_action":false,"price_micros":0,"input_schema":null},{"name":"set_permission","description":"Pre-grants or revokes an app permission so the popup never appears: location, location-always, camera, microphone, photos, media-library, contacts, calendar, notifications (Android 13+ only; iOS cannot pre-grant notifications), motion/reminders/photos-add (iOS). Grant BEFORE launching.","write_action":false,"price_micros":0,"input_schema":null},{"name":"set_state","description":"Writes a store (the store name may be given as \"store\" or \"name\", the payload as \"value\" or \"patch\"), putting the app into an exact state without walking through ten screens. Only possible from inside the runtime, and what makes a recorded flow hermetic: start from an injected session instead of replaying a login. Redux is written by dispatching an action, React Query by query key.","write_action":true,"price_micros":0,"input_schema":null},{"name":"shutdown_device","description":"Shuts down an iOS simulator, or kills an Android emulator (adb emu kill).","write_action":false,"price_micros":0,"input_schema":null},{"name":"snapshot_baseline","description":"Captures the current screen and stores it as the named visual baseline. Take it on the device and orientation the comparison will use.","write_action":false,"price_micros":0,"input_schema":null},{"name":"start_recording","description":"Records runtime actions and events observed between them. Association is temporal and may include background work. Everything up to stop_recording becomes an exportable flow.","write_action":false,"price_micros":0,"input_schema":null},{"name":"start_screen_recording","description":"Starts recording the screen. Returns startedAt on the SAME clock as the event bus, so a frame maps back to the event that produced it: video offset = event.ts - startedAt. Attaching a run's video to a bug report is what this is for.","write_action":false,"price_micros":0,"input_schema":null},{"name":"stop_recording","description":"Stops the current recording. The flow stays available for export_flow.","write_action":false,"price_micros":0,"input_schema":null},{"name":"stop_screen_recording","description":"Stops the recording and returns the file, its start instant and its duration.","write_action":false,"price_micros":0,"input_schema":null},{"name":"swipe_native","description":"Drags a real finger across the screen, from x1,y1 to x2,y2 in device coordinates. This is the gesture ui_act cannot perform: it acts through the JS props, so it reaches onPress and scrollTo but never produces a MOVING touch. Use it to scroll a long form that exposes no scrollable instance, and to exercise anything reading the native touch stream: a Swipeable row, a pan handler, a carousel, any rea","write_action":false,"price_micros":0,"input_schema":null},{"name":"tap_native","description":"LAST-RESORT tap for native dialogs the JS runtime cannot reach. Android: adb input tap (x/y). iOS: AXe if installed (tap by accessibility label, e.g. label='Allow', or x/y in points), else idb. Prefer ui_act and set_permission/launch_app, which make this unnecessary.","write_action":false,"price_micros":0,"input_schema":null},{"name":"terminate_app","description":"Force-stops the app (simctl terminate / am force-stop).","write_action":false,"price_micros":0,"input_schema":null},{"name":"ui_act","description":"Acts inside the app runtime. tap and longPress invoke JS handlers, bypassing native hit testing; execution reports the mode and nativeGesture:false. Use tap_native or swipe_native to test physical reachability or gestures. Ambiguous or invalid targets are refused.","write_action":false,"price_micros":0,"input_schema":null},{"name":"uninstall_app","description":"Removes the app from the target, wiping its data.","write_action":true,"price_micros":0,"input_schema":null},{"name":"unmount_component","description":"Clears the preview outlet and gives the screen back to the app.","write_action":false,"price_micros":0,"input_schema":null},{"name":"wait_for_event","description":"Waits for a matching event. With since, first checks retained events after that cursor, so events emitted during the action are not missed. Without since, waits for future events only. type and payloadContains are substrings. Use assert network_response to check HTTP method and status.","write_action":false,"price_micros":0,"input_schema":null}],"scan":{"score":91,"grade":"A","scanned_at":"2026-09-20T11:36:46.043Z","report":{"scannerVersion":"0.1.9","scannedAt":"2026-09-20T11:36:45.979Z","components":{"code":{"score":25,"max":25,"notes":["54 source files scanned","54 source files scanned"]},"reliability":{"score":-1,"max":20,"notes":["no gateway calls yet and no remote to probe"]},"poisoning":{"score":-1,"max":15,"notes":["tools not inspected (local package is not executed); not counted"]},"auth":{"score":12,"max":15,"notes":["local package, no credentials required"]},"maintenance":{"score":15,"max":15,"notes":["last push 15 days ago"]},"identity":{"score":7,"max":10,"notes":["registry namespace matches repository owner"]}},"findings":[],"inputs":{"packages":[{"registryType":"npm","identifier":"rn-devtools-hub","version":"0.22.0","found":true,"license":"MIT","hasInstallScripts":false,"dependencyCount":0,"publishedAt":"2026-09-05T23:32:46.836Z","repositoryUrl":"git+https://github.com/rn-devtools-hub/rn-devtools-hub.git","weeklyDownloads":302},{"registryType":"npm","identifier":"rn-devtools-hub","version":"0.22.0","found":true,"license":"MIT","hasInstallScripts":false,"dependencyCount":0,"publishedAt":"2026-09-05T23:32:46.836Z","repositoryUrl":"git+https://github.com/rn-devtools-hub/rn-devtools-hub.git","weeklyDownloads":302}],"repo":{"found":true,"owner":"rn-devtools-hub","repo":"rn-devtools-hub","archived":false,"pushedAt":"2026-09-05T23:32:54Z","stars":4,"forks":1,"openIssues":1,"ownerType":"Organization","ownerAvatarUrl":"https://avatars.githubusercontent.com/u/306898863?v=4","ownerCreatedAt":"2026-07-19T22:44:05Z","license":"MIT"},"icon":{"url":null,"source":"none"},"presence":{"stars":4,"forks":1,"downloadsWeek":604,"license":"MIT","lastPushAt":"2026-09-05T23:32:54.000Z","score":39}}}},"grade_history":[],"reviews":[]}