Contribute

Thank you for contributing to React Native MCP. This page is for developers who want to set up the repo, run tests, or understand the architecture. User-facing docs (install, tools, test) are in mcp and test.


How to contribute

  • Bug reports: Open an issue with clear steps to reproduce.
  • Feature ideas: Start a Discussion or open an issue.
  • Docs: Fix typos, add examples, or improve explanations.
  • Code: Submit a Pull Request for bug fixes, features, or refactors.

Development environment

The project uses mise for Bun version management.

mise trust
mise install
bun install

Run development

# All-in-one (MCP server + optional services)
bun run dev

# MCP server only
bun run dev:server

Tests and code quality

# Unit tests
bun run test:unit

# With coverage
bun run test:coverage

# E2E (YAML scenarios, demo app)
bun run test:e2e -- -p ios
bun run test:e2e -- -p android

Before opening a PR, run:

bun run lint
bun run format

Pull Request process

  1. Fork the repo and create a branch.
  2. Implement changes and run lint/format/tests locally.
  3. Commit using the commit guidelines below.
  4. Push and open a PR to main. CI will run lint, build, and tests.

Commit guidelines

We follow Conventional Commits.

Format: (<scope>): <subject> (body/footer optional)

Types: feat | fix | refactor | test | docs | chore | style

Scopes (optional): server | react-native | docs | scripts | config

Principles: One purpose per commit; separate unrelated changes; keep commits small and independently meaningful.


VS Code extension development

The DevTools extension lives in editor/vscode.

Build:

cd editor/vscode
bun install
bun run build    # dist/extension.js + dist/webview.js
bun run watch    # Auto-rebuild on file changes

Debug (Extension Development Host): Open editor/vscode in VS Code → press F5 → new window with extension loaded.

Architecture: Extension connects to MCP server at ws://localhost:12300 as an extension-init client (same server as Cursor/Claude via stdio). Flow: VS Code Extension → WebSocket → MCP Server → eval → RN App.


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

AspectBrowser (DOM) MCPReact Native MCP
TreeDOM treeReact Fiber tree
SelectorsCSS selectorstestID, querySelector (Fiber selectors)
InteractionquerySelector + clickFiber + native touch injection (tap/swipe)
SnapshotHTML snapshotComponent tree JSON
ScreenshotBrowser DevTools APIadb / xcrun simctl (host CLI, no native module)
CommunicationWebSocket (DevTools)WebSocket + eval
Code injectionNot neededBabel/Metro required

Three-Layer Architecture

  • Layer 1 — AI Client: Communicates with the MCP server over stdio (MCP protocol).
  • Layer 2 — MCP Server: Node.js process exposing 42 tools, WebSocket on port 12300, and native CLI (adb/idb).
  • Layer 3 — App Runtime + Native Tools: In-app runtime.js (Fiber, eval, network/console intercept) and host CLI for screenshot/tap (no native module in the app).

Communication flow

Tools accept optional deviceId and platform for multi-device routing.

Build pipeline

Babel preset (@ohah/react-native-mcp-server/babel-preset):

  1. Auto testID injection for element selection.
  2. AppRegistry wrapping to inject the runtime.

In production, runtime does not connect unless REACT_NATIVE_MCP_ENABLED=true when running Metro.

Tool categories and data flow

CategoryExamplesData path
Snapshot / Querytake_snapshot, query_selectorWebSocket → Fiber tree walk → JSON
Interactiontap, swipe, input_textNative CLI (adb/idb) → device
Assertionsassert_text, assert_visibleWebSocket → Fiber tree check
Screenshottake_screenshotNative CLI → PNG file
Stateinspect_state, get_state_changesWebSocket → React hooks inspection
Networklist_network_requests, set_network_mockWebSocket → XHR/fetch intercept
Consolelist_console_messagesWebSocket → console intercept
Renderstart_render_profile, get_render_reportWebSocket → render tracking
Evalevaluate_scriptWebSocket → JS eval in app
WebViewwebview_evaluate_scriptWebSocket → WebView JS bridge
Devicelist_devices, set_locationNative CLI
Filefile_push, add_mediaNative CLI

Ports

PortPurpose
12300MCP server WebSocket
8081 (default)Metro bundler

Package structure

packages/react-native-mcp-server/
├── src/
│   ├── index.ts                 # CLI + MCP server (stdio)
│   ├── websocket-server.ts      # WebSocket (12300)
│   ├── tools/                   # 42 MCP tools
│   ├── babel/                   # Babel preset (testID)
│   ├── metro/                   # Metro transformer
│   └── runtime/                 # Runtime source → runtime.js
├── runtime.js                   # Injected runtime (generated)
├── babel-preset.js
└── metro-transformer.cjs