# 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](/mcp/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](https://github.com/steve228uk/metro-mcp/issues/57) · 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](https://github.com/steve228uk/metro-mcp/issues/69) · 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](https://github.com/steve228uk/metro-mcp/issues/68) · 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:

```ts
// 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](https://github.com/steve228uk/metro-mcp/issues/85) · 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

1. Call `get_navigation_state` on an app with unvisited registered screens.
2. The returned root and nested states expose those screens in `routeNames`.
3. Call `list_routes`; registered names absent from the current `routes` arrays are omitted. In the live test, it returned 12 mounted entries while the state exposed many additional registered…

[Read the thread](https://github.com/steve228uk/metro-mcp/issues/84) · 2026-09-03 · open · 0 comments

### `wait_for_navigation` times out on routes that `get_current_route` already reports

### Reproduction

1. Navigate to a React Navigation screen.
2. `get_current_route({})` returns the focused screen name (the test used `YourAccountScreen`).
3. `wait_for_navigation({routeName:"YourAccountScreen",timeout:1000})` times out.
4. `get_current_route({})` still returns that same focused route.

### Confirmed cause

[automation.ts](https://github.com/steve228uk/metro-mcp/blob/28b0198e6f4851c2d23816771257ac3d150dde1a/src/plugins/automation.ts#L7) only polls…

[Read the thread](https://github.com/steve228uk/metro-mcp/issues/83) · 2026-09-03 · open · 0 comments

### `evaluate_js` returns Hermes Promise internals despite `awaitPromise: true`

### Reproduction

Call:

```json
{"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](https://github.com/steve228uk/metro-mcp/blob/28b0198e6f4851c2d23816771257ac3d150dde1a/src/server.ts#L491) forwards the CDP flag and returns the serialized Promise object. Plugins using freshly created async…

[Read the thread](https://github.com/steve228uk/metro-mcp/issues/82) · 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

1. Run a development app on an iOS simulator.
2. Call `open_app_settings({bundleId:"com.example.test",platform:"ios"})`.
3. The tool executes `xcrun simctl openurl booted app-settings:` and returns `LSApplicationWorkspaceErrorDomain`, code **115**. The settings page does not open.

### Confirmed cause and contract

The [iOS…

[Read the thread](https://github.com/steve228uk/metro-mcp/issues/81) · 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](https://github.com/steve228uk/metro-mcp/issues/80) · 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

1. `list_simulators({platform:"ios",bootedOnly:true})` returns the booted simulator.
2. `get_app_directories({bundleId:"com.example.test"})` returns `{"error":"No simulator/emulator detected"}`.
3. Add `platform:"ios"` to the same call; the app container resolves successfully.
4. `get_screen_orientation({})` incorrectly attempts `adb shell settings get…

[Read the thread](https://github.com/steve228uk/metro-mcp/issues/79) · 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](https://github.com/steve228uk/metro-mcp/issues/73) · 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](https://github.com/steve228uk/metro-mcp/issues/72) · 2026-08-20 · closed · 0 comments

The remaining reports are on [the project's issue tracker](https://github.com/steve228uk/metro-mcp/issues).
