guide · AI and agents
Debug a React Native app with Claude Code or Cursor
Updated September 16, 2026
A coding agent reads your files. The bug lives in state that only exists while the app runs, so the agent fills the gap with a guess and asks you to add log lines. An MCP connection closes that gap: the agent queries the running app directly for its network activity, stored values, framework state and current screen. Setup is an MCP server in your editor's config plus a package inside the app.
Why agents guess about runtime bugs
Ask Claude Code or Cursor why a checkout screen shows an empty cart and it will read your reducer, your query hooks and your API client, then offer three plausible causes. All three are reasonable readings of the source. None of them can be checked, because the answer is in a cache key, a stale stored token or a response body that only exists on the device.
So the agent asks you to add logging and report back. You paste output, it revises the guess, you paste more. The loop works, and it is slow because every round trip goes through you.
What a runtime connection gives the agent
With an MCP server attached to the running app, the agent can read what is actually happening and act on it. What is available depends on which packages the app installed, so the list below is a ceiling rather than a default.
- Network requests with their ids, status and optionally their bodies, filtered to errors or a URL pattern.
- Stored values, console output, route history, and framework state for Redux, Zustand, Jotai and React Query where those integrations are registered.
- The current screen as a structured list of elements with labels, testIDs and control values, plus the ability to tap, type and toggle. This reads the React tree rather than pixels, so it also works on a physical device.
- Actions: navigate a route, edit a stored value, dispatch, invalidate a query, put the device offline or add latency, reload the bundle.
The practical change is that the agent stops asking you for output. It reads the failing request itself, checks the stored token, looks at what the screen currently renders, and comes back with a cause instead of a list of candidates.
Set it up
You need Node.js 18 or newer on the machine running your editor, the app running with Buoy devtools open, and a Buoy Pro account. The MCP data and action tools are a Pro feature, and the MCP process needs its own account configuration; a device key does not sign it in.
React Native apps also need @buoy-gg/external-sync installed and Metro restarted, with <FloatingDevTools /> mounted. Run setup from the app project:
npx -y @buoy-gg/mcp@latest initThat writes .mcp.json and .cursor/mcp.json, and updates .vscode/mcp.json when a .vscode directory exists. Other server entries are preserved. Restart your editor afterwards, or reconnect the MCP server.
To wire it by hand instead:
{
"mcpServers": {
"buoy": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@buoy-gg/mcp@latest"],
"env": { "BUOY_VERIFY": "auto" }
}
}
}On a work laptop whose .npmrc points at a private registry that is unreachable off VPN, the npx entry would stall on every editor launch. Setup probes the registry first and falls back to a pinned local install, or you can force it with init --local. Full setup detail is in the MCP documentation.
The first loop worth running
Start by asking the agent to call list_devices. It returns the connected apps and the tools each one exposes, which tells you immediately whether an integration you expected is missing. Then point it at the symptom rather than the whole app.
For a failing checkout, the useful sequence is to find the request, retain it, then read the state around it:
get_network_requests({ status: "errors" })
→ 3. fetch_1021 500 POST /api/checkout
network_action({ action: "pin", id: "fetch_1021" })
get_network_requests({ flagged: "pinned", includeBodies: true })
get_storage({ includeValues: true })
describe_screen()Pinning matters more than it looks. It survives the live list rolling over, so the request is still there when you come back, and it works in both directions: pin the broken call yourself and tell the agent to look at the pinned request, or let the agent pin what it found so it is waiting at the top of your Network list.
To exercise an error path rather than wait for one, the agent can set a network condition, drive the UI, and read what the app actually renders:
network_conditions({ action: "set", profile: "offline" })
tap_element({ testID: "checkout-submit" })
describe_screen()
network_conditions({ action: "set", profile: "normal" })The condition lives in memory on the device and resets on a full JS reload. An agent that sets one should clear it, or the next session starts offline for reasons nobody remembers.
What it will not do for you
A successful tool call is not evidence that a user-visible problem is fixed. After changing code, repeat the interaction that exposed the bug and check the result on the device. The MCP server ships a reminder for this, controlled by BUOY_VERIFY, and clearing a reminder proves nothing on its own.
Captured data has retention limits, and an app that has stopped cannot answer at all. If the app crashed, the evidence from before the crash may already be gone. An unresponsive app is not proof of a crash either.
Build type decides a lot. Sync is off in release builds unless you opt in explicitly, and network conditions refuse anything except normal there. Flutter runs debug only. Capture also depends on transports: native networking that bypasses global fetch and React Native's XHR is not intercepted, so it will not appear in the request list.
Other ways to give an agent runtime access
Buoy is not the only option, and the right comparison is which commands each one exposes for the data you need.
- Reactotron documents a built-in MCP server. If you already run Reactotron for desktop inspection, check which commands your installed version exposes before adding anything else.
- Rozenite documents agent access to running apps through its CLI, covering runtime domains and the tools a registered app or plugin exposes. It builds on React Native DevTools panels and also runs standalone. Its documentation does not address production builds.
- React Native DevTools stays the right tool for source breakpoints and stepping through JavaScript. It is a different job from handing an agent structured runtime data, and worth keeping alongside whatever you pick.
We make Buoy, so treat this section as where we would look rather than a benchmark. We have not installed and run every alternative listed.
Questions people ask
Does this work on a physical device?
Can the agent change my app state, and can I undo it?
Does it work in Expo Go?
Do I need Buoy Pro?
Let your agent read the running app
Start with a Free account. Follow the quick start for package requirements, account setup and tool integration.
npm i @buoy-gg/coresources
Capability claims on this page come from each vendor's own documentation, read on the date shown. We did not install and run every tool listed.
- Reactotron MCP documentation · checked September 13, 2026
- Rozenite documentation · checked September 16, 2026
- React Native DevTools documentation · checked September 13, 2026