# Metro MCP [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/steve228uk/metro-mcp  
**GitHub Stars:** 85  
**npm Downloads (last month):** 3223  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/metro-mcp

## Description
MCP server for React Native/Expo runtime debugging, inspection, and automation via Metro/CDP

## Tools
Capabilities this server exposes over MCP:

- **get_console_logs** — Get recent console output. Filter by level or search text.
- **clear_console_logs** — Clear the console log buffer.
- **get_network_requests** — Get recent network requests from the React Native app.
- **get_request_details** — Get full details of a specific network request including headers and body.
- **get_response_body** — Get response body for a network request (cached if small; requires active session if large).
- **search_network** — Search network requests by URL pattern, method, or status code.
- **clear_network_requests** — Clear the network request buffer.
- **get_network_stats** — Get aggregated network statistics: breakdown by domain, status code, and response times.
- **get_errors** — Get recent uncaught exceptions from the React Native app.
- **clear_errors** — Clear the error buffer.
- **get_bundle_errors** — Get recent Metro compilation/transform errors.
- **evaluate_js** — 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.
- **list_devices** — List connected devices and debuggable targets from Metro bundler.
- **get_app_info** — Get information about the connected React Native app (bundle URL, platform, device name).
- **get_connection_status** — Check the connection status to Metro bundler.
- **reload_app** — 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.
- **symbolicate** — Symbolicate a stack trace using Metro bundler source maps. Converts minified/bundled locations back to original source files.
- **get_redux_state** — 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.
- **dispatch_redux_action** — Dispatch a Redux action to the store.
- **get_redux_actions** — Get recent Redux actions (requires metro-mcp client SDK for real-time tracking).
- **get_component_tree** — Get a paged flat React component tree. Follow nextCursor to complete the snapshot and check traversal.complete before treating an empty page as authoritative.
- **find_components** — Search for components by name inside the app runtime. Check traversal.complete before treating no matches as definitive.
- **inspect_component** — Get props, state, and hooks for the first exact component-name match, with traversal completeness metadata.
- **get_testable_elements** — Get elements with testID or accessibilityLabel. Check traversal.complete before treating an empty elements array as definitive.
- **get_storage_keys** — List all AsyncStorage keys in the React Native app.
- **get_storage_item** — Read a specific AsyncStorage key value.
- **get_all_storage** — Dump all AsyncStorage key-value pairs.
- **take_screenshot** — Capture a screenshot from the connected iOS simulator or Android device.
- **list_simulators** — List available iOS simulators or Android emulators.
- **install_certificate** — Install a root certificate on the iOS simulator or Android device.
- **get_native_logs** — Get native platform logs from iOS simulator (syslog) or Android device (logcat).
- **app_lifecycle** — Launch, terminate, install, or uninstall an app on the simulator/emulator.
- **get_screen_orientation** — Get the current screen orientation of the device.
- **open_deeplink** — Open a URL or deep link on the connected iOS simulator or Android device.
- **list_url_schemes** — List URL schemes registered by an installed iOS app or Android package.
- **list_permissions** — List all app permission statuses on the connected iOS simulator or Android emulator. Returns compact text: one name=status line per permission.
- **grant_permission** — Grant a permission to the app on the connected iOS simulator or Android emulator.
- **revoke_permission** — Revoke a permission from the app on the connected iOS simulator or Android emulator.
- **reset_permissions** — 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.
- **open_app_settings** — Open the connected app's system settings page using React Native Linking.openSettings().
- **list_elements** — Get labelled or interactive elements from the focused React screen. Check traversal.complete before treating an empty elements array as definitive.
- **tap_element** — 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.
- **type_text** — 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.
- **long_press** — 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.
- **swipe** — 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.
- **press_button** — Press a device button (HOME, BACK, VOLUME_UP, etc.).
- **get_navigation_state** — Get the full React Navigation / Expo Router state tree including current route, params, and stack history.
- **get_current_route** — Get the currently focused route name and params.
- **get_route_history** — Get the navigation back stack / history.
- **list_routes** — List registered route names from available navigation state. Uninitialized nested navigators are not discoverable.
- **audit_accessibility** — Audit the current screen within bounded Fiber traversal limits. Checks labels, roles, testIDs, and alt text; returns issues, summary, and traversal coverage.
- **check_element_accessibility** — Check accessibility properties of a specific component by name or testID.
- **get_accessibility_summary** — Quick overview: counts of elements with and without proper accessibility props.
- **list_commands** — List all custom commands registered by the app. Commands are registered on global.__METRO_BRIDGE__.commands or global.__METRO_BRIDGE_COMMANDS__.
- **run_command** — Execute a custom command registered by the app. Pass parameters as a JSON object.
- **start_test_recording** — Inject interaction interceptors into the running app via the React fiber tree. Captures taps, text entry, long presses, keyboard submits, and scroll/swipe gestures — with no changes to your app code. Works with ScrollView, FlatList, SectionList, FlashList, and other scroll containers. Call stop_test_recording when done, then generate_test_from_recording to get the test.
- **stop_test_recording** — Stop the active recording, retrieve all captured events, and store them for test generation. Returns a summary of what was recorded. Call generate_test_from_recording next to produce Appium, Maestro, or Detox test code.
- **generate_test_from_recording** — Convert the most recent recording into a test file. Supports three formats: appium (WebdriverIO + Mocha), maestro (YAML), and detox (Jest). Call stop_test_recording first.
- **generate_wdio_config** — Generate a minimal but runnable wdio.conf.ts for Appium + React Native testing, along with the npm install command.
- **add_recording_annotation** — Add a human-readable annotation (comment marker) to the current recording. Useful for labelling major flow checkpoints like "reached checkout", "error appeared here", "navigated to payment". Annotations appear as code comments in generated tests.
- **save_test_recording** — Save the current recording events to disk as JSON so they can be reloaded later. Useful for regenerating the same flow in a different test format without re-recording. Files are saved to ~/.metro-mcp/recordings/<filename>.json.
- **load_test_recording** — Load a previously saved recording from disk and make it available for test generation. After loading, call generate_test_from_recording with any format to regenerate the test. Use list_test_recordings to see available files.
- **list_test_recordings** — List all previously saved test recordings in ~/.metro-mcp/recordings/. Returns filenames and sizes. Use load_test_recording to load one for test generation.
- **start_profiling** — Start profiling the running React Native app. Primary path: injects into the React DevTools hook (__REACT_DEVTOOLS_GLOBAL_HOOK__) via evalInApp — captures all component render durations without requiring <Profiler> wrappers, works on all architectures. Fallback (legacy arch only): CDP Profiler domain for JS CPU call-graph sampling. Perform the interaction you want to measure, then call stop_profiling.
- **stop_profiling** — Stop profiling and return an analysis of the captured data. DevTools hook mode: returns top components by total render duration across all commits. CDP mode: returns top JS functions by self time and total time. Must call start_profiling first.
- **get_profile_status** — Check whether profiling is active, which mode is in use, and whether a previous profile is available.
- **get_flamegraph** — Return the current profiling results as a human-readable text chart. Shows React DevTools component profile (if captured), CPU flamegraph (if CDP profile captured), and React render data from <Profiler> components (if set up). Call stop_profiling first to populate the profile data.
- **get_react_renders** — Read React render timing data collected via <Profiler onRender={trackRender}>. Returns all recorded renders sorted by actualDuration descending, with memoization savings from baseDuration. Requires importing trackRender from metro-mcp/client. Use clear=true to reset the buffer.
- **get_memory_info** — Get current JavaScript heap memory usage from the running app. Returns used heap, total heap, and heap size limit (when available). Call repeatedly to track memory growth over time or to detect leaks.
- **profile_action** — Profile a specific JavaScript expression or code path in a single call. Starts profiling, evaluates the expression, waits for it to complete (plus optional extra duration), then stops and returns the top functions by self time. Use instead of calling start_profiling / stop_profiling manually for focused measurements.
- **start_heap_sampling** — Start Hermes heap allocation sampling via CDP HeapProfiler. Records memory allocation call stacks to identify where objects are being allocated. Call stop_heap_sampling to retrieve the top allocation sites.
- **stop_heap_sampling** — Stop heap allocation sampling and return the top allocation sites. Shows which functions are allocating the most memory, useful for diagnosing memory leaks. Must call start_heap_sampling first.
- **wait_for_element** — Poll the component tree until an element matching the given testID or accessibilityLabel appears. Returns element info on success. Use after tap_element, navigate(), or any action that triggers async screen transitions or data loading — instead of immediately calling the next tool. Returns traversal metadata immediately when the bounded search is incomplete.
- **wait_for_condition** — Poll a JavaScript expression in the app until it returns a truthy value, then return that value. Useful for waiting on state changes, loading flags, API responses, or any async condition. Example: wait for globalThis.myStore?.isLoaded === true.
- **wait_for_navigation** — Poll the active navigation route until it matches the expected route name, then return. Requires the navigation plugin to be set up (get_current_route must work). Use after tap_element on a link or after dispatching a navigate() action.
- **setup_statusline** — Writes the Metro CDP connection status script to ~/.claude/metro-mcp-statusline.sh. Does not modify settings.json — tell the user to add it to their status line themselves (e.g. ask Claude: "/statusline add the script at ~/.claude/metro-mcp-statusline.sh"). Only works with Claude Code.
- **list_debug_globals** — Auto-discover well-known global debugging objects (Redux stores, Apollo Client, Expo Router, React DevTools hook, etc.) available in the app runtime.
- **inspect_at_point** — Inspect the smallest measured host component at screen coordinates. Uses awaited Fabric/Paper measurement and returns traversal completeness metadata.
- **open_devtools** — 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.
- **get_app_directories** — Get known app sandbox directory paths (documents, cache, temp, library). Returns absolute paths usable with list_directory and read_file.
- **list_directory** — List files and directories in an app sandbox path. Call get_app_directories first to obtain the root path.
- **read_file** — Read the contents of a file from the app sandbox. Enforces a configurable size cap (default 50 KB, max 1 MB) to avoid flooding context.
- **get_file_info** — Get file or directory metadata: size, modification date, and whether it is a directory.
- **delete_file** — Delete a file from the app sandbox. Requires confirm: true to prevent accidental deletion.
- **get_build_info** — 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.
- **get_env_vars** — 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.
- **get_platform_constants** — Return the full Platform.constants object from React Native, including OS-specific build details.
- **get_expo_config** — Return expo-constants manifest/expoConfig fields if the app uses Expo, otherwise null.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "metro-mcp": {
    "command": "npx",
    "args": ["-y","metro-mcp"]
  }
}
```

## Documentation

## What the Metro MCP MCP server does

Metro MCP MCP server gives MCP clients access to a running React Native development session. It works with Expo, bare React Native, and other projects using Metro with Hermes. The server connects to Metro through Chrome DevTools Protocol (CDP), then exposes runtime information and device actions as MCP tools, resources, and prompts.

Core debugging does not require changes to application code. Available capabilities cover console logs, network requests and response bodies, runtime and bundle errors, JavaScript evaluation, environment and Expo configuration inspection, stack trace symbolication, Redux state, React component trees, AsyncStorage, navigation state, and accessibility checks.

The plugin set also includes simulator and emulator control, deep-link testing, permissions, UI actions such as tapping, swiping, and typing, polling helpers, CPU and heap profiling, render tracking, file inspection, and discovery of debug globals such as Redux stores or Apollo Client. Test recording can generate Appium, Maestro, or Detox tests.

## How the Metro MCP MCP server works

When started, the server scans common Metro ports, including 8081, 8082, and 19000 through 19002. It connects to the Hermes runtime over CDP and keeps buffers for console output, network activity, and errors. MCP clients then query those buffers or invoke runtime and device operations.

Hermes normally permits only one CDP debugger connection. The Metro MCP MCP server includes a CDP proxy so its MCP connection can coexist with Chrome DevTools. Use the provided DevTools-opening tool rather than opening the debugger through Metro’s usual shortcuts, which can otherwise take over the connection.

Standard stdio installations can reuse a local shared daemon for the same project directory and Metro settings. This lets multiple configured clients connect to one running application and observe shared runtime state.

## Setup and configuration

Node.js 18 or newer, or Bun 1.0 or newer, is required. iOS workflows require Xcode 14 or later with the Simulator; Android workflows require the Android SDK and `adb` on the PATH. Some iOS operations can use IDB as a fallback, and the relevant tools indicate when it is needed.

A typical MCP configuration starts the package with `npx -y metro-mcp`, or with `bunx metro-mcp`. The server can receive a custom Metro port, for example `--port 19000`. To run one long-lived endpoint, use `metro-mcp serve --mcp-port 8765`; this exposes Streamable HTTP at `http://127.0.0.1:8765/mcp`. The documented endpoint does not provide `/sse` or `/messages` routes.

## Tools and capabilities

The repository organizes functionality into plugins:

- Console collection and filtering
- Network tracking, response inspection, and statistics
- Runtime and Metro bundle error reporting
- JavaScript evaluation and custom app commands
- Device status, reloads, simulator, emulator, and permission control
- Environment, Expo configuration, navigation, and deep-link inspection
- React components, Redux, storage, accessibility, and debug-global inspection
- UI interaction, waiting, profiling, and test recording
- Sandbox filesystem access, source symbolication, and Chrome DevTools support

The exact tool count and names are maintained in the project’s tools reference. The inspect-point plugin is experimental, and the statusline plugin integrates with Claude Code.

## Limitations and notes

The application must be running with a reachable Metro development server for runtime inspection. The server targets Metro plus Hermes, so projects using a different bundler or JavaScript runtime are outside the stated compatibility scope.

Opening the debugger through Metro or the React Native development menu can disconnect the MCP by taking Hermes’s single debugger connection. Use the built-in proxy workflow when Chrome DevTools is needed alongside MCP access. iOS and Android automation also depends on the platform tooling installed on the host.

_Full upstream README: https://allmcps.com/mcp/metro-mcp/readme_

