{"name":"io.github.steve228uk/metro-mcp","slug":"steve228uk-metro-mcp","title":"Metro MCP","description":"MCP server for React Native/Expo runtime debugging, inspection, and automation via Metro/CDP","url":"https://mcp.market/server/steve228uk-metro-mcp","rating":null,"grade":"B","score":74,"certified":false,"status":"active","category":"other","tags":[],"presence":{"score":47,"stars":81,"forks":7,"downloads_week":432,"last_push_at":"2026-09-04T20:37:37.000Z","license":"MIT"},"uptime":null,"claimed":false,"transport":"npm","callable_via_gateway":false,"default_price_micros":0,"repository":"https://github.com/steve228uk/metro-mcp","website":null,"version":"0.15.0","remotes":[],"packages":[{"registryType":"npm","identifier":"metro-mcp","version":"0.15.0","transport":{"type":"stdio"}}],"tools":[{"name":"add_recording_annotation","description":"Add a human-readable annotation (comment marker) to the current recording.","write_action":false,"price_micros":0,"input_schema":null},{"name":"app_lifecycle","description":"Launch, terminate, install, or uninstall an app on the simulator/emulator.","write_action":false,"price_micros":0,"input_schema":null},{"name":"audit_accessibility","description":"Audit the current screen within bounded Fiber traversal limits. Checks labels, roles, testIDs, and alt text; returns issues, summary, and traversal coverage.","write_action":false,"price_micros":0,"input_schema":null},{"name":"check_element_accessibility","description":"Check accessibility properties of a specific component by name or testID.","write_action":false,"price_micros":0,"input_schema":null},{"name":"clear_console_logs","description":"Clear the console log buffer.","write_action":false,"price_micros":0,"input_schema":null},{"name":"clear_errors","description":"Clear the error buffer.","write_action":false,"price_micros":0,"input_schema":null},{"name":"clear_network_requests","description":"Clear the network request buffer.","write_action":false,"price_micros":0,"input_schema":null},{"name":"delete_file","description":"Delete a file from the app sandbox.","write_action":true,"price_micros":0,"input_schema":null},{"name":"dispatch_redux_action","description":"Dispatch a Redux action to the store.","write_action":false,"price_micros":0,"input_schema":null},{"name":"evaluate_js","description":"Execute a JavaScript expression in the running React Native app and return the result. Use this for inspecting variables, calling functions, or querying app state.","write_action":true,"price_micros":0,"input_schema":null},{"name":"find_components","description":"Search for components by name inside the app runtime. Check traversal.complete before treating no matches as definitive.","write_action":false,"price_micros":0,"input_schema":null},{"name":"generate_test_from_recording","description":"Convert the most recent recording into a test file.","write_action":false,"price_micros":0,"input_schema":null},{"name":"generate_wdio_config","description":"Generate a minimal but runnable wdio.conf.ts for Appium + React Native testing, along with the npm install command.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_accessibility_summary","description":"Quick overview: counts of elements with and without proper accessibility props.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_all_storage","description":"Dump all AsyncStorage key-value pairs.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_app_directories","description":"Get known app sandbox directory paths (documents, cache, temp, library).","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_app_info","description":"Get information about the connected React Native app (bundle URL, platform, device name).","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_build_info","description":"Return build-time and runtime flags for the running React Native app: __DEV__, platform, OS version, RN version, Hermes engine, New Architecture, and expo-application fields if available.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_bundle_errors","description":"Get recent Metro compilation/transform errors.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_component_tree","description":"Get a paged flat React component tree. Follow nextCursor to complete the snapshot and check traversal.complete before treating an empty page as authoritative.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_connection_status","description":"Check the connection status to Metro bundler.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_console_logs","description":"Get recent console output. Filter by level or search text.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_current_route","description":"Get the currently focused route name and params.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_env_vars","description":"Return a filtered subset of process.env from the running app. Credential-like keys (SECRET, KEY, TOKEN, PASSWORD, etc.) are redacted by default. Use filter to search by key name substring.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_errors","description":"Get recent uncaught exceptions from the React Native app.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_expo_config","description":"Return expo-constants manifest/expoConfig fields if the app uses Expo, otherwise null.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_file_info","description":"Get file or directory metadata: size, modification date, and whether it is a directory.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_flamegraph","description":"Return the current profiling results as a human-readable text chart.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_memory_info","description":"Get current JavaScript heap memory usage from the running app.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_native_logs","description":"Get native platform logs from iOS simulator (syslog) or Android device (logcat).","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_navigation_state","description":"Get the full React Navigation / Expo Router state tree including current route, params, and stack history.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_network_requests","description":"Get recent network requests from the React Native app.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_network_stats","description":"Get aggregated network statistics: breakdown by domain, status code, and response times.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_platform_constants","description":"Return the full Platform.constants object from React Native, including OS-specific build details.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_profile_status","description":"Check whether profiling is active, which mode is in use, and whether a previous profile is available.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_react_renders","description":"Read React render timing data collected via <Profiler onRender={trackRender}>.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_redux_actions","description":"Get recent Redux actions (requires metro-mcp client SDK for real-time tracking).","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_redux_state","description":"Get the current Redux state tree or a specific slice. Works without client SDK if Redux DevTools extension is present or store is exposed globally.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_request_details","description":"Get full details of a specific network request including headers and body.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_response_body","description":"Get response body for a network request (cached if small; requires active session if large).","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_route_history","description":"Get the navigation back stack / history.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_screen_orientation","description":"Get the current screen orientation of the device.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_storage_item","description":"Read a specific AsyncStorage key value.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_storage_keys","description":"List all AsyncStorage keys in the React Native app.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_testable_elements","description":"Get elements with testID or accessibilityLabel. Check traversal.complete before treating an empty elements array as definitive.","write_action":false,"price_micros":0,"input_schema":null},{"name":"grant_permission","description":"Grant a permission to the app on the connected iOS simulator or Android emulator.","write_action":false,"price_micros":0,"input_schema":null},{"name":"hello_world","description":"A sample tool — replace with your own logic","write_action":false,"price_micros":0,"input_schema":null},{"name":"inspect_at_point","description":"Inspect the smallest measured host component at screen coordinates. Uses awaited Fabric/Paper measurement and returns traversal completeness metadata.","write_action":false,"price_micros":0,"input_schema":null},{"name":"inspect_component","description":"Get props, state, and hooks for the first exact component-name match, with traversal completeness metadata.","write_action":false,"price_micros":0,"input_schema":null},{"name":"install_certificate","description":"Install a root certificate on the iOS simulator or Android device.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_commands","description":"List all custom commands registered by the app. Commands are registered on global.__METRO_BRIDGE__.commands or global.__METRO_BRIDGE_COMMANDS__.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_debug_globals","description":"Auto-discover well-known global debugging objects (Redux stores, Apollo Client, Expo Router, React DevTools hook, etc.) available in the app runtime.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_devices","description":"List connected devices and debuggable targets from Metro bundler.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_directory","description":"List files and directories in an app sandbox path.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_elements","description":"Get labelled or interactive elements from the focused React screen. Check traversal.complete before treating an empty elements array as definitive.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_permissions","description":"List all app permission statuses on the connected iOS simulator or Android emulator. Returns compact text: one name=status line per permission.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_routes","description":"List registered route names from available navigation state. Uninitialized nested navigators are not discoverable.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_simulators","description":"List available iOS simulators or Android emulators.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_test_recordings","description":"List all previously saved test recordings in ~/.metro-mcp/recordings/.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_url_schemes","description":"List URL schemes registered by an installed iOS app or Android package.","write_action":false,"price_micros":0,"input_schema":null},{"name":"load_test_recording","description":"Load a previously saved recording from disk and make it available for test generation.","write_action":false,"price_micros":0,"input_schema":null},{"name":"long_press","description":"Long press using a React handler by label/testID, then semantic native input through SimView or IDB when the handler is unavailable. Explicit coordinates use native input directly; native results identify the backend and dispatch state.","write_action":false,"price_micros":0,"input_schema":null},{"name":"open_app_settings","description":"Open the connected app's system settings page using React Native Linking.openSettings().","write_action":false,"price_micros":0,"input_schema":null},{"name":"open_deeplink","description":"Open a URL or deep link on the connected iOS simulator or Android device.","write_action":false,"price_micros":0,"input_schema":null},{"name":"open_devtools","description":"Open the React Native DevTools debugger panel in Chrome. Connects through the CDP proxy so DevTools and the MCP can share the same Hermes connection.","write_action":false,"price_micros":0,"input_schema":null},{"name":"press_button","description":"Press a device button (HOME, BACK, VOLUME_UP, etc.).","write_action":false,"price_micros":0,"input_schema":null},{"name":"profile_action","description":"Profile a specific JavaScript expression or code path in a single call.","write_action":false,"price_micros":0,"input_schema":null},{"name":"read_file","description":"Read the contents of a file from the app sandbox.","write_action":false,"price_micros":0,"input_schema":null},{"name":"reload_app","description":"Reload the connected app and verify a fresh runtime. Uses Page.reload, with a directed Metro message fallback only for a verified app/device peer.","write_action":false,"price_micros":0,"input_schema":null},{"name":"reset_permissions","description":"Reset one or all permissions for the app on the connected iOS simulator or Android emulator. On iOS, omitting service resets all services. On Android, omitting service resets all runtime permissions.","write_action":false,"price_micros":0,"input_schema":null},{"name":"revoke_permission","description":"Revoke a permission from the app on the connected iOS simulator or Android emulator.","write_action":false,"price_micros":0,"input_schema":null},{"name":"run_command","description":"Execute a custom command registered by the app. Pass parameters as a JSON object.","write_action":true,"price_micros":0,"input_schema":null},{"name":"save_test_recording","description":"Save the current recording events to disk as JSON so they can be reloaded later.","write_action":false,"price_micros":0,"input_schema":null},{"name":"search_network","description":"Search network requests by URL pattern, method, or status code.","write_action":false,"price_micros":0,"input_schema":null},{"name":"setup_statusline","description":"Writes the Metro CDP connection status script to ~/.claude/metro-mcp-statusline.sh.","write_action":true,"price_micros":0,"input_schema":null},{"name":"start_heap_sampling","description":"Start Hermes heap allocation sampling via CDP HeapProfiler.","write_action":false,"price_micros":0,"input_schema":null},{"name":"start_profiling","description":"Start profiling the running React Native app.","write_action":false,"price_micros":0,"input_schema":null},{"name":"start_test_recording","description":"Inject interaction interceptors into the running app via the React fiber tree.","write_action":false,"price_micros":0,"input_schema":null},{"name":"stop_heap_sampling","description":"Stop heap allocation sampling and return the top allocation sites.","write_action":false,"price_micros":0,"input_schema":null},{"name":"stop_profiling","description":"Stop profiling and return an analysis of the captured data.","write_action":false,"price_micros":0,"input_schema":null},{"name":"stop_test_recording","description":"Stop the active recording, retrieve all captured events, and store them for test generation.","write_action":false,"price_micros":0,"input_schema":null},{"name":"swipe","description":"Scroll through React, then use installed SimView or IDB on iOS and the selected ADB serial on Android. Native results identify the backend and dispatch state.","write_action":false,"price_micros":0,"input_schema":null},{"name":"symbolicate","description":"Symbolicate a stack trace using Metro bundler source maps. Converts minified/bundled locations back to original source files.","write_action":false,"price_micros":0,"input_schema":null},{"name":"take_screenshot","description":"Capture a screenshot from the connected iOS simulator or Android device.","write_action":false,"price_micros":0,"input_schema":null},{"name":"tap_element","description":"Tap by label, testID, or logical device-point coordinates. Uses React handlers, then installed SimView or IDB on iOS and adb on Android. Coordinates use native input directly; native results identify the backend and dispatch state.","write_action":false,"price_micros":0,"input_schema":null},{"name":"type_text","description":"Type text into an input field. Targets a specific input by testID/label, or the first visible TextInput. Uses the React handler first, then SimView or IDB on iOS and the selected ADB serial on Android.","write_action":false,"price_micros":0,"input_schema":null},{"name":"wait_for_condition","description":"Poll a JavaScript expression in the app until it returns a truthy value, then return that value.","write_action":false,"price_micros":0,"input_schema":null},{"name":"wait_for_element","description":"Poll the component tree until an element matching the given testID or accessibilityLabel appears.","write_action":false,"price_micros":0,"input_schema":null},{"name":"wait_for_navigation","description":"Poll the active navigation route until it matches the expected route name, then return.","write_action":false,"price_micros":0,"input_schema":null}],"scan":{"score":74,"grade":"B","scanned_at":"2026-09-20T11:40:16.379Z","report":{"scannerVersion":"0.1.9","scannedAt":"2026-09-20T11:40:16.304Z","components":{"code":{"score":13,"max":25,"notes":["73 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 16 days ago"]},"identity":{"score":8,"max":10,"notes":["registry namespace matches repository owner","GitHub account older than a year"]}},"findings":[{"id":"exec.shell-concat","severity":"high","component":"code","title":"Shell command built from a string (injection risk)","evidence":"dist/bin/metro-mcp.js: …allations.push(customChromePath); } execSync(`${LSREGISTER} -dump` + \" | grep -i 'google…"}],"inputs":{"packages":[{"registryType":"npm","identifier":"metro-mcp","version":"0.15.0","found":true,"license":"MIT","hasInstallScripts":false,"dependencyCount":10,"publishedAt":"2026-09-04T20:40:22.096Z","repositoryUrl":"git+https://github.com/steve228uk/metro-mcp.git","weeklyDownloads":432}],"repo":{"found":true,"owner":"steve228uk","repo":"metro-mcp","archived":false,"pushedAt":"2026-09-04T20:37:37Z","stars":81,"forks":7,"openIssues":0,"ownerType":"User","ownerAvatarUrl":"https://avatars.githubusercontent.com/u/1169297?v=4","ownerCreatedAt":"2011-11-03T08:56:15Z","license":"MIT"},"icon":{"url":"https://avatars.githubusercontent.com/u/1169297?v=4&s=128","source":"github"},"presence":{"stars":81,"forks":7,"downloadsWeek":432,"license":"MIT","lastPushAt":"2026-09-04T20:37:37.000Z","score":47}}}},"grade_history":[],"reviews":[]}