Metro MCP
NPM · METRO-MCP · SCANNED SEP 21
MCP server for React Native/Expo runtime debugging, inspection, and automation via Metro/CDP
Available components
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security99
- No malware found by supply-chain analysis.Pass
- No known CVEs affecting this package version or its production dependencies.Pass
- No install/post-install scripts declared.Pass
- 5 of 43 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency97
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Cryptographically verified build provenance (signed, bound to steve228uk/metro-mcp). View diagnostics → Pass
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 16 days ago).Pass
- Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability80
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (good).Pass
- Tool/resource definitions use about 6585 tokens (~62/item across 105 items; 88 tools + 17 resources), lean.Pass
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management60
- Stability observed for 18 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage96
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 89% of tool parameters carry a description.Partial
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 4 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 90 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
- Supports UI / widget rendering.Pass
How do I install the Metro MCP server?
Metro MCP runs locally as an npm package, launched with npx -y metro-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
npm · metro-mcp
claude mcp add steve228uk-metro-mcp -- npx -y metro-mcp
{
"mcpServers": {
"steve228uk-metro-mcp": {
"command": "npx",
"args": [
"-y",
"metro-mcp"
]
}
}
} {
"servers": {
"steve228uk-metro-mcp": {
"command": "npx",
"args": [
"-y",
"metro-mcp"
]
}
}
} codex mcp add steve228uk-metro-mcp -- npx -y metro-mcp
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"steve228uk-metro-mcp": {
"type": "local",
"command": [
"npx",
"-y",
"metro-mcp"
],
"enabled": true
}
}
} openclaw mcp add steve228uk-metro-mcp --command npx --arg -y --arg metro-mcp
mcp_servers:
steve228uk-metro-mcp:
command: "npx"
args: ["-y", "metro-mcp"] {
"McpServers": {
"steve228uk-metro-mcp": {
"Transport": "stdio",
"Command": "npx",
"Arguments": [
"-y",
"metro-mcp"
]
}
}
} assistant mcp add steve228uk-metro-mcp -t stdio -c npx -a -y metro-mcp
{
"mcpServers": {
"steve228uk-metro-mcp": {
"command": "npx",
"args": [
"-y",
"metro-mcp"
]
}
}
} Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 21 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 57 to 60. That category is still filling its 30-day observation window: 17 days of observed history at the previous scan, 18 at this one. The score rises as the window fills, whether or not the server changes.
- 19 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 50 to 53. That category is still filling its 30-day observation window: 15 days of observed history at the previous scan, 16 at this one. The score rises as the window fills, whether or not the server changes.
- 17 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 43 to 47. That category is still filling its 30-day observation window: 13 days of observed history at the previous scan, 14 at this one. The score rises as the window fills, whether or not the server changes.
- 15 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 37 to 40. That category is still filling its 30-day observation window: 11 days of observed history at the previous scan, 12 at this one. The score rises as the window fills, whether or not the server changes.
- 13 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 30 to 33. That category is still filling its 30-day observation window: 9 days of observed history at the previous scan, 10 at this one. The score rises as the window fills, whether or not the server changes.
- 12 Sept 26 0
- Security disclosure: unverified → fail ▼ functional
- 11 Sept 26 +1
- Security disclosure: fail → unverified ▼ functional
- 8 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 13 to 17. That category is still filling its 30-day observation window: 4 days of observed history at the previous scan, 5 at this one. The score rises as the window fills, whether or not the server changes.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 21 Sept 2026 · Analysed npm/metro-mcp@0.15.0
Provenance Verified
A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.
| Result | Verified |
|---|---|
| Ecosystem | npm |
| Reason | Verified |
| Discovered via | Registry attestation endpoint |
| Source repo | steve228uk/metro-mcp |
| Certificate issuer | https://token.actions.githubusercontent.com |
| Certificate SAN | https://github.com/steve228uk/metro-mcp/.github/workflows/publish.yml@refs/tags/v0.15.0 |
| Rekor log index | 2715930430 |
| Predicate type | https://slsa.dev/provenance/v1 |
| Subject digest | sha512:a2adae7e32186f50e7e305a441e66742f4d441bf92fcf2e15165f94fae5b44321e5644856af9ea7d6d7a35490703c2357312c883985cf32064f97fab7 |
Background: How many MCP packages publish verified provenance →
Dependencies 43 packages
| Packages resolved | 43 |
|---|---|
| Stale | 5 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
list_debug_globals ~55
Auto-discover well-known global debugging objects (Redux stores, Apollo Client, Expo Router, React DevTools hook, etc.) available in the app runtime.
| Name | Type | Req | Description |
|---|---|---|---|
| detailed | boolean | – | Include top-level keys for each discovered global |
No output schema declared.
No examples provided.
list_devices ~34
List connected devices and debuggable targets from Metro bundler.
| Name | Type | Req | Description |
|---|---|---|---|
| rescan | boolean | – | Rescan all Metro ports |
No output schema declared.
No examples provided.
list_directory ~111
List files and directories in an app sandbox path. Call get_app_directories first to obtain the root path.
| Name | Type | Req | Description |
|---|---|---|---|
| bundleId | string | – | App bundle ID (iOS) or package name (Android). Required when path is omitted; also used for Android run-as access. |
| path | string | – | Absolute directory path to list. Defaults to the app data container root (bundleId required). |
| platform | string | – | – |
| recursive | boolean | – | Recursively list subdirectories (returns raw text) |
No output schema declared.
No examples provided.
list_elements ~62
Get labelled or interactive elements from the focused React screen. Check traversal.complete before treating an empty elements array as definitive.
| Name | Type | Req | Description |
|---|---|---|---|
| interactiveOnly | boolean | – | Return only elements with onPress handlers |
| maxDepth | integer | – | – |
| maxNodes | integer | – | – |
No output schema declared.
No examples provided.
list_permissions ~68
List all app permission statuses on the connected iOS simulator or Android emulator. Returns compact text: one name=status line per permission.
| Name | Type | Req | Description |
|---|---|---|---|
| bundleId | string | – | Bundle ID (iOS) or package name (Android). Auto-detected if omitted. |
| platform | string | – | Target platform |
No output schema declared.
No examples provided.
list_routes ~27
List registered route names from available navigation state. Uninitialized nested navigators are not discoverable.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
list_simulators ~43
List available iOS simulators or Android emulators.
| Name | Type | Req | Description |
|---|---|---|---|
| bootedOnly | boolean | – | Show only booted/running devices |
| platform | string | – | – |
No output schema declared.
No examples provided.
list_test_recordings ~42
List all previously saved test recordings in ~/.metro-mcp/recordings/. Returns filenames and sizes. Use load_test_recording to load one for test generation.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
list_url_schemes ~53
List URL schemes registered by an installed iOS app or Android package.
| Name | Type | Req | Description |
|---|---|---|---|
| bundleId | string | – | Bundle ID to check (auto-detected if not provided) |
| platform | string | – | Target platform |
No output schema declared.
No examples provided.
load_test_recording ~69
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.
| Name | Type | Req | Description |
|---|---|---|---|
| filename | string | yes | Name of the saved recording (without .json extension) |
No output schema declared.
No examples provided.
long_press ~104
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.
| Name | Type | Req | Description |
|---|---|---|---|
| duration | number | – | Duration in milliseconds |
| label | string | – | Accessibility label or testID of the element to long press |
| platform | string | – | – |
| x | number | – | X coordinate |
| y | number | – | Y coordinate |
No output schema declared.
No examples provided.
open_app_settings ~62
Open the connected app's system settings page using React Native Linking.openSettings().
| Name | Type | Req | Description |
|---|---|---|---|
| bundleId | string | – | Bundle ID (iOS) or package name (Android). If supplied, it must match the connected app. |
| platform | string | – | Target platform |
No output schema declared.
No examples provided.
open_deeplink ~64
Open a URL or deep link on the connected iOS simulator or Android device.
| Name | Type | Req | Description |
|---|---|---|---|
| platform | string | – | – |
| url | string | yes | URL or deep link to open (e.g., "myapp://screen/details" or "https://example.com/path") |
No output schema declared.
No examples provided.
open_devtools ~53
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.
| Name | Type | Req | Description |
|---|---|---|---|
| open | boolean | – | Attempt to open the browser automatically |
No output schema declared.
No examples provided.
press_button ~40
Press a device button (HOME, BACK, VOLUME_UP, etc.).
| Name | Type | Req | Description |
|---|---|---|---|
| button | string | yes | Button to press |
| platform | string | – | – |
No output schema declared.
No examples provided.
profile_action ~124
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.
| Name | Type | Req | Description |
|---|---|---|---|
| expression | string | yes | JavaScript expression to profile (can be an async IIFE) |
| extraMs | integer | – | Additional milliseconds to wait after the expression resolves before stopping (default 0) |
| topN | integer | – | Number of top functions to return |
No output schema declared.
No examples provided.
read_file ~126
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.
| Name | Type | Req | Description |
|---|---|---|---|
| bundleId | string | – | App package name (Android, for run-as access to private files) |
| encoding | string | – | Output encoding. Use base64 for binary files (images, SQLite, etc.) |
| maxBytes | number | – | Maximum bytes to read (default 50 KB, hard cap 1 MB) |
| path | string | yes | Absolute path to the file |
| platform | string | – | – |
No output schema declared.
No examples provided.
reload_app ~53
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.
| Name | Type | Req | Description |
|---|---|---|---|
| timeout | integer | – | Maximum time in milliseconds to submit and verify the reload |
No output schema declared.
No examples provided.
reset_permissions ~126
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.
| Name | Type | Req | Description |
|---|---|---|---|
| bundleId | string | – | Bundle ID (iOS) or package name (Android). Auto-detected if omitted. |
| platform | string | – | Target platform |
| service | string | – | iOS: specific service to reset (e.g. "location"); omit to reset all. Android: permission name (e.g. "CAMERA"); omit to reset all runtime permissions. |
No output schema declared.
No examples provided.
revoke_permission ~121
Revoke a permission from the app on the connected iOS simulator or Android emulator.
| Name | Type | Req | Description |
|---|---|---|---|
| bundleId | string | – | Bundle ID (iOS) or package name (Android). Auto-detected if omitted. |
| platform | string | – | Target platform |
| service | string | yes | iOS: simctl service (calendar, contacts, contacts-limited, location, location-always, microphone, motion, photos, photos-add, media-library, reminders, siri). Android: runtime permission (e.g. "CAMER… |
No output schema declared.
No examples provided.
run_command ~67
Execute a custom command registered by the app. Pass parameters as a JSON object.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | Command name to execute |
| params | object | – | Parameters to pass to the command |
| timeout | number | – | Max ms to wait for async commands (default 15000) |
No output schema declared.
No examples provided.
save_test_recording ~77
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.
| Name | Type | Req | Description |
|---|---|---|---|
| filename | string | yes | Name for the saved recording (without .json extension) |
No output schema declared.
No examples provided.
search_network ~98
Search network requests by URL pattern, method, or status code.
| Name | Type | Req | Description |
|---|---|---|---|
| device | string | – | Device key or "all". Defaults to current device. |
| errorsOnly | boolean | – | Show only failed requests |
| limit | number | – | Maximum number of results to return |
| method | string | – | HTTP method filter |
| statusCode | number | – | HTTP status code filter |
| urlPattern | string | – | URL substring or regex pattern |
No output schema declared.
No examples provided.
setup_statusline ~77
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
start_heap_sampling ~69
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.
| Name | Type | Req | Description |
|---|---|---|---|
| samplingInterval | integer | – | Average bytes between samples (default 32768). Lower = more detail, higher overhead. |
No output schema declared.
No examples provided.
start_profiling ~118
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.
| Name | Type | Req | Description |
|---|---|---|---|
| samplingInterval | integer | – | CDP fallback only: sampling interval in microseconds (default 1000). |
No output schema declared.
No examples provided.
start_test_recording ~89
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
stop_heap_sampling ~57
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.
| Name | Type | Req | Description |
|---|---|---|---|
| topN | integer | – | Number of top allocation sites to return |
No output schema declared.
No examples provided.
stop_profiling ~92
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.
| Name | Type | Req | Description |
|---|---|---|---|
| includeNative | boolean | – | CDP mode only: include native/internal Hermes frames. |
| topN | integer | – | Number of top entries to return. |
No output schema declared.
No examples provided.
stop_test_recording ~54
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.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
swipe ~56
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.
| Name | Type | Req | Description |
|---|---|---|---|
| direction | string | yes | Swipe direction |
| platform | string | – | – |
No output schema declared.
No examples provided.
symbolicate ~47
Symbolicate a stack trace using Metro bundler source maps. Converts minified/bundled locations back to original source files.
| Name | Type | Req | Description |
|---|---|---|---|
| stack | array | yes | Array of stack frames to symbolicate |
No output schema declared.
No examples provided.
take_screenshot ~49
Capture a screenshot from the connected iOS simulator or Android device.
| Name | Type | Req | Description |
|---|---|---|---|
| delivery | string | – | Return a retained temporary file path or an inline MCP image |
| platform | string | – | Target platform |
No output schema declared.
No examples provided.
tap_element ~98
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.
| Name | Type | Req | Description |
|---|---|---|---|
| label | string | – | Accessibility label, aria-label, or testID to tap |
| platform | string | – | – |
| x | number | – | X coordinate |
| y | number | – | Y coordinate |
No output schema declared.
No examples provided.
type_text ~98
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.
| Name | Type | Req | Description |
|---|---|---|---|
| platform | string | – | – |
| testID | string | – | testID or accessibilityLabel of the TextInput to target (defaults to first visible input) |
| text | string | yes | Text to type |
No output schema declared.
No examples provided.
wait_for_condition ~116
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.
| Name | Type | Req | Description |
|---|---|---|---|
| expression | string | yes | JS expression to evaluate; polling stops when it returns truthy |
| pollInterval | integer | – | How often to check in milliseconds (default 500) |
| timeout | integer | – | Maximum wait time in milliseconds (default 10000) |
No output schema declared.
No examples provided.
wait_for_element ~147
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.
| Name | Type | Req | Description |
|---|---|---|---|
| maxDepth | integer | – | Maximum fiber depth inspected per poll |
| maxNodes | integer | – | Maximum fibers inspected per poll |
| pollInterval | integer | – | How often to check in milliseconds (default 500) |
| selector | string | yes | testID or accessibilityLabel to wait for |
| timeout | integer | – | Maximum wait time in milliseconds (default 10000) |
No output schema declared.
No examples provided.
wait_for_navigation ~98
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.
| Name | Type | Req | Description |
|---|---|---|---|
| routeName | string | yes | Expected route name to wait for (e.g. "HomeScreen", "ProfileTab") |
| timeout | integer | – | Maximum wait time in milliseconds (default 10000) |
No output schema declared.
No examples provided.
What is the Metro MCP server?
Metro MCP is listed in the public MCP registry as io.github.steve228uk/metro-mcp. MCP server for React Native/Expo runtime debugging, inspection, and automation via Metro/CDP. This page covers its npm package (metro-mcp).
Is the Metro MCP server safe to use?
Metro MCP scores 90 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 21 September 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Metro MCP server expose?
Metro MCP exposes 88 tools: get_console_logs, clear_console_logs, get_network_requests, get_request_details, get_response_body, and 83 more. Their descriptions and schemas cost roughly 6,214 tokens of context every time the server is loaded.
Is the Metro MCP server still maintained?
Metro MCP is still listed as active in the MCP registry. We last reached this channel on 21 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the Metro MCP server under?
Metro MCP declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.