Architecture
How React Native MCP works under the hood.
Overview
React Native MCP enables AI tools (Cursor, Claude Desktop, Copilot) to control and inspect React Native apps. React Native has no DOM — so this project uses React Fiber tree, Babel code injection, and native CLI tools (adb/idb).
Comparison with browser-based MCP
Three-Layer Architecture
Layer 1: AI Client
The AI client (Cursor, Claude Desktop, Copilot CLI) communicates with the MCP server over stdio using the MCP protocol. It sends tool calls and receives results — the client doesn't know about React Native internals.
Layer 2: MCP Server
A Node.js process that:
- Exposes 38 MCP tools across 12 categories (interaction, assertions, screen capture, network mocking, state inspection, render profiling, etc.)
- Runs a WebSocket server on port 12300 for bidirectional communication with the app
- Executes native CLI commands (adb for Android, idb for iOS simulator) for screenshots, tap, swipe, and text input
Layer 3: App Runtime + Native Tools
- Runtime (
runtime.js): Pure JavaScript injected into the app bundle by the Babel preset. Connects tows://localhost:12300, exposes the Fiber tree, handles eval requests, intercepts network/console, and tracks state changes. - Native tools: Screenshots and touch injection use host CLI tools (
adb exec-out screencap,xcrun simctl io screenshot,idb ui tap), so no native module is installed in the app.
Communication Flow
Device Registration
Tool Execution
Multi-Device Support
Every tool accepts optional deviceId and platform parameters:
deviceIdspecified → routes to that deviceplatformspecified + 1 device → auto-selects- Only 1 device total → auto-selects (backwards compatible)
- Multiple devices without specifier → error (must specify
deviceId)
Build Pipeline
How the Babel Preset Works
The Babel preset (@ohah/react-native-mcp-server/babel-preset) does two things at build time:
- Auto testID injection: Adds
testIDprops to components for reliable element selection - AppRegistry wrapping: Wraps
AppRegistry.registerComponentto inject the runtime
In production builds, the runtime is included but doesn't connect unless REACT_NATIVE_MCP_ENABLED=true is set when running Metro.
Tool Categories and Data Flow
Port Usage
The MCP server does not modify Metro's port or configuration. It runs independently and the app runtime connects to both Metro (for bundling) and the MCP server (for tool communication).
Package Structure
Everything is in a single package for simplicity: