Reported issues for Metro MCP
Pod holds 17 of 17 GitHub reports that passed its relevance review. This can include external user reports, maintainer-confirmed bugs, and concrete feature gaps. Treat them as evidence to inspect, not a count of distinct defects.
Back to Metro MCP.
Most discussed
MCP Server does not support multiple concurrent clients
Environment
- metro-mcp: latest (npx -y metro-mcp)
- React Native 0.81.6, Hermes engine, legacy bridge (old arch)
- MCP client: Claude Code (multiple windows via SSE / supergateway)
Problem
metro-mcp creates a single MCP Server instance and calls .connect(transport) once at startup. The MCP SDK Server class does not allow a second .connect() call, so connecting more than one AI window fails in two different ways depending on the transport:
**With SSE transport…
Read the thread · 2026-05-28 · closed · external user · 4 comments
take_screenshot returns full-resolution base64 in a JSON text payload (584K–2M chars) — always exceeds client response limits
Summary
take_screenshot returns the PNG as base64 inside a JSON text payload at full
device resolution. On a 3x iOS simulator that is 584K–2M characters, which is over the
response limit of every MCP client I have tried, so the tool is effectively unusable —
it never fails, it just always overflows.
Two separate problems: the payload is not an MCP image content block, and there is no way to ask for a smaller image.
Environment
| metro-mcp | 0.13.2 |
| React… |
Read the thread · 2026-08-07 · closed · external user · 1 comment
Fiber-walking read tools never reach screen content on Expo Router + New Arch (silently return empty, while tap_element finds the same elements)
Summary
On a real-world Expo Router app, every fiber-walking read tool stops at the navigator providers and never reaches screen content. They return empty results rather than an error, so an agent reads them as "the element isn't there" instead of "the traversal didn't get that far".
tap_element is unaffected — it uses a different search path and finds the same
elements the read tools claim don't exist. That asymmetry is the clearest proof the
elements are present and reachable.
##…
Read the thread · 2026-08-07 · closed · external user · 1 comment
get_network_requests returns nothing on RN 0.76+ (fusebox): initiator.stack dedup guard drops all requests
Summary
On React Native 0.76+ using the new fusebox debugger, get_network_requests always returns an empty list even though the app is actively making requests and the CDP connection is healthy. Console logs, Redux, component tree, etc. all work — only network capture is empty.
Root cause
In src/plugins/network.ts, the Network.requestWillBeSent handler drops any event whose initiator.stack is set:
// Drop the JS-layer event (identified by having a call stack) ...
if…
[Read the thread](https://github.com/steve228uk/metro-mcp/issues/64) · 2026-07-07 · closed · external user · 1 comment
### `audit_accessibility` still reports no issues after silently truncating Fiber traversal at depth 50
The read-tool improvements for #68 do not cover the accessibility audit. It can claim a clean audit without inspecting the mounted screen.
### Reproduction
1. Use an app whose screen content is beneath a deep provider/navigation tree.
2. Call `audit_accessibility({severity:"all"})`; it returns `No accessibility issues found!`.
3. Compare with `get_accessibility_summary` and an independent deeper Fiber walk.
In the live app, the summary reported 73 touchables without labels and 14 images…
[Read the thread](https://github.com/steve228uk/metro-mcp/issues/89) · 2026-09-03 · open · 0 comments
### Generated Appium tests use Jest hooks with a Mocha Wdio config and fixed simulator capabilities
The two generation tools produce incompatible test/setup artifacts for the connected simulator.
### Reproduction
1. Record a tab tap.
2. Call `generate_test_from_recording({format:"appium",includeSetup:true,bundleId:"com.example.test"})`.
3. Call `generate_wdio_config({platform:"ios",bundleId:"com.example.test"})`.
The Appium test contains `beforeAll` and `afterAll`, but the generated config selects `framework: 'mocha'`. Mocha's BDD setup/teardown hooks are `before` and `after`, so this…
[Read the thread](https://github.com/steve228uk/metro-mcp/issues/88) · 2026-09-03 · open · 0 comments
### `start_test_recording` can miss the first interaction after reporting it is ready
The recorder reports that recording started before handlers on already-mounted components have been intercepted.
### Reproduction
1. Open a screen with mounted tab buttons and call `start_test_recording`.
2. Add a recording annotation, then immediately tap another tab using `tap_element`.
3. Confirm `get_current_route` reports the new screen.
4. Tap a second tab, then call `stop_test_recording`.
Actual: the recording contains the annotation and second tap only. The first tap changed the…
[Read the thread](https://github.com/steve228uk/metro-mcp/issues/87) · 2026-09-03 · open · 0 comments
### `reload_app` reports success without restarting the Expo JavaScript runtime
### Reproduction
1. `evaluate_js({expression:"globalThis.__metroReloadSmoke = 'before-reload'"})`.
2. `reload_app({})` returns **App reloaded via Metro.**
3. `wait_for_condition({expression:"typeof globalThis.__metroReloadSmoke === 'undefined'",timeout:5000})` times out.
4. The current route's instance key also remains unchanged. Remove the test marker afterward.
### Confirmed cause…
[Read the thread](https://github.com/steve228uk/metro-mcp/issues/86) · 2026-09-03 · open · 0 comments
## Most recent
### `list_url_schemes` fails on Hermes and has no iOS Info.plist fallback
### Reproduction
With an installed iOS app that declares `CFBundleURLTypes`, call:
```json
{"bundleId":"com.example.test"}
Actual: {"error":"Property 'require' doesn't exist"}. Expected: the registered URL schemes from the specified installed app. The identifier above is a placeholder; the tested app's built Info.plist contains multiple registered schemes.
Confirmed cause
[The runtime…
Read the thread · 2026-09-03 · open · 0 comments
list_routes omits registered routes present in navigation state's routeNames
The tool describes its result as all registered route names, but returns only routes currently present in navigation history/state.
Reproduction
- Call
get_navigation_stateon an app with unvisited registered screens. - The returned root and nested states expose those screens in
routeNames. - Call
list_routes; registered names absent from the currentroutesarrays are omitted. In the live test, it returned 12 mounted entries while the state exposed many additional registered…
Read the thread · 2026-09-03 · open · 0 comments
wait_for_navigation times out on routes that get_current_route already reports
Reproduction
- Navigate to a React Navigation screen.
get_current_route({})returns the focused screen name (the test usedYourAccountScreen).wait_for_navigation({routeName:"YourAccountScreen",timeout:1000})times out.get_current_route({})still returns that same focused route.
Confirmed cause
automation.ts only polls…
Read the thread · 2026-09-03 · open · 0 comments
evaluate_js returns Hermes Promise internals despite awaitPromise: true
Reproduction
Call:
{"expression":"Promise.resolve({answer:42})","awaitPromise":true}
Expected: {"answer":42}.
Actual: {"_A":null,"_x":0,"_y":1,"_z":{"answer":42}}.
The public tool promises to wait for the expression's Promise. Instead, the shared evaluation helper forwards the CDP flag and returns the serialized Promise object. Plugins using freshly created async…
Read the thread · 2026-09-03 · open · 0 comments
open_app_settings fails on iOS Simulator with LSApplicationWorkspace error 115
The tool promises to open app settings on iOS, but its host-side URL invocation fails for the connected simulator app.
Reproduction
- Run a development app on an iOS simulator.
- Call
open_app_settings({bundleId:"com.example.test",platform:"ios"}). - The tool executes
xcrun simctl openurl booted app-settings:and returnsLSApplicationWorkspaceErrorDomain, code 115. The settings page does not open.
Confirmed cause and contract
The [iOS…
Read the thread · 2026-09-03 · open · 0 comments
iOS input fallbacks fail because IDB receives --udid booted
The iOS native-input fallbacks pass simctl's booted alias to IDB, which expects a concrete device UDID.
Reproduction
With IDB installed and an iOS simulator booted, invoke swipe({direction:"up",platform:"ios"}) on a screen where the Fiber scroll path cannot run. A type_text call that falls back to IDB reproduces the same failure.
Actual command: idb ui swipe 500 1500 500 500 --udid booted.
Actual result: `Cannot spawn companion for booted, no matching target in available udids…
Read the thread · 2026-09-03 · open · 0 comments
iOS platform auto-detection uses invalid simctl list booted syntax
On a booted iOS simulator, tools using platform: "auto" fail to detect iOS even though explicitly selecting "ios" works.
Reproduction
list_simulators({platform:"ios",bootedOnly:true})returns the booted simulator.get_app_directories({bundleId:"com.example.test"})returns{"error":"No simulator/emulator detected"}.- Add
platform:"ios"to the same call; the app container resolves successfully. get_screen_orientation({})incorrectly attempts `adb shell settings get…
Read the thread · 2026-09-03 · open · 0 comments
Daemon never exits after its last client disconnects — orphaned daemons keep the single CDP slot
Summary
The daemon is spawned detached on purpose, but it has no shutdown condition: it keeps running after its last stdio client goes away. Since only one CDP client may attach to a Metro inspector target at a time, every orphaned daemon permanently occupies that slot, which starves other tools (React Native DevTools opened with j, native profilers) until the process is killed by hand.
A second, smaller problem: stale daemon records are never removed.
Environment
- metro-mcp:…
Read the thread · 2026-08-21 · closed · external user · 0 comments
Ignore react-native-worklets CDP targets instead of attaching to them
Summary
metro-mcp discovers Hermes targets via Metro’s CDP /json list and attaches to them. react-native-worklets (createWorkletRuntime) registers extra Hermes runtimes that also show up in that list. Attaching the MCP (or reconnecting) to those runtimes can crash or hang the app.
Worklet runtimes are not the app JS runtime. They exist to run worklets off-thread (Reanimated UI runtime, streamdown’s remend-processor, etc.). They are not fully inspectable over CDP.
Why this…
Read the thread · 2026-08-20 · closed · 0 comments
The remaining reports are on the project's issue tracker.