react-native-mcp-kit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +868 -0
- package/dist/babel/index.d.ts +3 -0
- package/dist/babel/index.d.ts.map +1 -0
- package/dist/babel/index.js +11 -0
- package/dist/babel/index.js.map +1 -0
- package/dist/babel/stripPlugin.d.ts +5 -0
- package/dist/babel/stripPlugin.d.ts.map +1 -0
- package/dist/babel/stripPlugin.js +100 -0
- package/dist/babel/stripPlugin.js.map +1 -0
- package/dist/babel/testIdPlugin.d.ts +5 -0
- package/dist/babel/testIdPlugin.d.ts.map +1 -0
- package/dist/babel/testIdPlugin.js +69 -0
- package/dist/babel/testIdPlugin.js.map +1 -0
- package/dist/client/contexts/McpContext/McpContext.d.ts +3 -0
- package/dist/client/contexts/McpContext/McpContext.d.ts.map +1 -0
- package/dist/client/contexts/McpContext/McpContext.js +6 -0
- package/dist/client/contexts/McpContext/McpContext.js.map +1 -0
- package/dist/client/contexts/McpContext/McpProvider.d.ts +3 -0
- package/dist/client/contexts/McpContext/McpProvider.d.ts.map +1 -0
- package/dist/client/contexts/McpContext/McpProvider.js +28 -0
- package/dist/client/contexts/McpContext/McpProvider.js.map +1 -0
- package/dist/client/contexts/McpContext/index.d.ts +4 -0
- package/dist/client/contexts/McpContext/index.d.ts.map +1 -0
- package/dist/client/contexts/McpContext/index.js +8 -0
- package/dist/client/contexts/McpContext/index.js.map +1 -0
- package/dist/client/contexts/McpContext/types.d.ts +12 -0
- package/dist/client/contexts/McpContext/types.d.ts.map +1 -0
- package/dist/client/contexts/McpContext/types.js +3 -0
- package/dist/client/contexts/McpContext/types.js.map +1 -0
- package/dist/client/contexts/McpTreeContext/McpTracker.d.ts +10 -0
- package/dist/client/contexts/McpTreeContext/McpTracker.d.ts.map +1 -0
- package/dist/client/contexts/McpTreeContext/McpTracker.js +101 -0
- package/dist/client/contexts/McpTreeContext/McpTracker.js.map +1 -0
- package/dist/client/contexts/McpTreeContext/McpTreeContext.d.ts +2 -0
- package/dist/client/contexts/McpTreeContext/McpTreeContext.d.ts.map +1 -0
- package/dist/client/contexts/McpTreeContext/McpTreeContext.js +6 -0
- package/dist/client/contexts/McpTreeContext/McpTreeContext.js.map +1 -0
- package/dist/client/contexts/McpTreeContext/McpTreeRegistry.d.ts +16 -0
- package/dist/client/contexts/McpTreeContext/McpTreeRegistry.d.ts.map +1 -0
- package/dist/client/contexts/McpTreeContext/McpTreeRegistry.js +96 -0
- package/dist/client/contexts/McpTreeContext/McpTreeRegistry.js.map +1 -0
- package/dist/client/contexts/McpTreeContext/index.d.ts +5 -0
- package/dist/client/contexts/McpTreeContext/index.d.ts.map +1 -0
- package/dist/client/contexts/McpTreeContext/index.js +10 -0
- package/dist/client/contexts/McpTreeContext/index.js.map +1 -0
- package/dist/client/contexts/McpTreeContext/types.d.ts +14 -0
- package/dist/client/contexts/McpTreeContext/types.d.ts.map +1 -0
- package/dist/client/contexts/McpTreeContext/types.js +3 -0
- package/dist/client/contexts/McpTreeContext/types.js.map +1 -0
- package/dist/client/core/McpClient.d.ts +25 -0
- package/dist/client/core/McpClient.d.ts.map +1 -0
- package/dist/client/core/McpClient.js +183 -0
- package/dist/client/core/McpClient.js.map +1 -0
- package/dist/client/hooks/useMcpModule.d.ts +4 -0
- package/dist/client/hooks/useMcpModule.d.ts.map +1 -0
- package/dist/client/hooks/useMcpModule.js +17 -0
- package/dist/client/hooks/useMcpModule.js.map +1 -0
- package/dist/client/hooks/useMcpState.d.ts +3 -0
- package/dist/client/hooks/useMcpState.d.ts.map +1 -0
- package/dist/client/hooks/useMcpState.js +20 -0
- package/dist/client/hooks/useMcpState.js.map +1 -0
- package/dist/client/hooks/useMcpTool.d.ts +4 -0
- package/dist/client/hooks/useMcpTool.d.ts.map +1 -0
- package/dist/client/hooks/useMcpTool.js +20 -0
- package/dist/client/hooks/useMcpTool.js.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +15 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/models/types.d.ts +12 -0
- package/dist/client/models/types.d.ts.map +1 -0
- package/dist/client/models/types.js +3 -0
- package/dist/client/models/types.js.map +1 -0
- package/dist/client/utils/connection.d.ts +17 -0
- package/dist/client/utils/connection.d.ts.map +1 -0
- package/dist/client/utils/connection.js +71 -0
- package/dist/client/utils/connection.js.map +1 -0
- package/dist/client/utils/moduleRunner.d.ts +13 -0
- package/dist/client/utils/moduleRunner.d.ts.map +1 -0
- package/dist/client/utils/moduleRunner.js +59 -0
- package/dist/client/utils/moduleRunner.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/alert/alert.d.ts +3 -0
- package/dist/modules/alert/alert.d.ts.map +1 -0
- package/dist/modules/alert/alert.js +50 -0
- package/dist/modules/alert/alert.js.map +1 -0
- package/dist/modules/alert/index.d.ts +2 -0
- package/dist/modules/alert/index.d.ts.map +1 -0
- package/dist/modules/alert/index.js +6 -0
- package/dist/modules/alert/index.js.map +1 -0
- package/dist/modules/components/components.d.ts +8 -0
- package/dist/modules/components/components.d.ts.map +1 -0
- package/dist/modules/components/components.js +315 -0
- package/dist/modules/components/components.js.map +1 -0
- package/dist/modules/components/index.d.ts +3 -0
- package/dist/modules/components/index.d.ts.map +1 -0
- package/dist/modules/components/index.js +6 -0
- package/dist/modules/components/index.js.map +1 -0
- package/dist/modules/components/types.d.ts +18 -0
- package/dist/modules/components/types.d.ts.map +1 -0
- package/dist/modules/components/types.js +3 -0
- package/dist/modules/components/types.js.map +1 -0
- package/dist/modules/components/utils.d.ts +18 -0
- package/dist/modules/components/utils.d.ts.map +1 -0
- package/dist/modules/components/utils.js +386 -0
- package/dist/modules/components/utils.js.map +1 -0
- package/dist/modules/console/console.d.ts +4 -0
- package/dist/modules/console/console.d.ts.map +1 -0
- package/dist/modules/console/console.js +176 -0
- package/dist/modules/console/console.js.map +1 -0
- package/dist/modules/console/index.d.ts +3 -0
- package/dist/modules/console/index.d.ts.map +1 -0
- package/dist/modules/console/index.js +6 -0
- package/dist/modules/console/index.js.map +1 -0
- package/dist/modules/console/types.d.ts +13 -0
- package/dist/modules/console/types.d.ts.map +1 -0
- package/dist/modules/console/types.js +3 -0
- package/dist/modules/console/types.js.map +1 -0
- package/dist/modules/device/device.d.ts +3 -0
- package/dist/modules/device/device.d.ts.map +1 -0
- package/dist/modules/device/device.js +182 -0
- package/dist/modules/device/device.js.map +1 -0
- package/dist/modules/device/index.d.ts +3 -0
- package/dist/modules/device/index.d.ts.map +1 -0
- package/dist/modules/device/index.js +6 -0
- package/dist/modules/device/index.js.map +1 -0
- package/dist/modules/device/types.d.ts +24 -0
- package/dist/modules/device/types.d.ts.map +1 -0
- package/dist/modules/device/types.js +3 -0
- package/dist/modules/device/types.js.map +1 -0
- package/dist/modules/errors/errors.d.ts +4 -0
- package/dist/modules/errors/errors.d.ts.map +1 -0
- package/dist/modules/errors/errors.js +133 -0
- package/dist/modules/errors/errors.js.map +1 -0
- package/dist/modules/errors/index.d.ts +3 -0
- package/dist/modules/errors/index.d.ts.map +1 -0
- package/dist/modules/errors/index.js +6 -0
- package/dist/modules/errors/index.js.map +1 -0
- package/dist/modules/errors/types.d.ts +12 -0
- package/dist/modules/errors/types.d.ts.map +1 -0
- package/dist/modules/errors/types.js +3 -0
- package/dist/modules/errors/types.js.map +1 -0
- package/dist/modules/fiberTree/fiberTree.d.ts +8 -0
- package/dist/modules/fiberTree/fiberTree.d.ts.map +1 -0
- package/dist/modules/fiberTree/fiberTree.js +337 -0
- package/dist/modules/fiberTree/fiberTree.js.map +1 -0
- package/dist/modules/fiberTree/index.d.ts +3 -0
- package/dist/modules/fiberTree/index.d.ts.map +1 -0
- package/dist/modules/fiberTree/index.js +6 -0
- package/dist/modules/fiberTree/index.js.map +1 -0
- package/dist/modules/fiberTree/types.d.ts +18 -0
- package/dist/modules/fiberTree/types.d.ts.map +1 -0
- package/dist/modules/fiberTree/types.js +3 -0
- package/dist/modules/fiberTree/types.js.map +1 -0
- package/dist/modules/fiberTree/utils.d.ts +18 -0
- package/dist/modules/fiberTree/utils.d.ts.map +1 -0
- package/dist/modules/fiberTree/utils.js +386 -0
- package/dist/modules/fiberTree/utils.js.map +1 -0
- package/dist/modules/i18next/i18next.d.ts +4 -0
- package/dist/modules/i18next/i18next.d.ts.map +1 -0
- package/dist/modules/i18next/i18next.js +133 -0
- package/dist/modules/i18next/i18next.js.map +1 -0
- package/dist/modules/i18next/index.d.ts +3 -0
- package/dist/modules/i18next/index.d.ts.map +1 -0
- package/dist/modules/i18next/index.js +6 -0
- package/dist/modules/i18next/index.js.map +1 -0
- package/dist/modules/i18next/types.d.ts +12 -0
- package/dist/modules/i18next/types.d.ts.map +1 -0
- package/dist/modules/i18next/types.js +3 -0
- package/dist/modules/i18next/types.js.map +1 -0
- package/dist/modules/index.d.ts +12 -0
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/modules/index.js +26 -0
- package/dist/modules/index.js.map +1 -0
- package/dist/modules/navigation/index.d.ts +3 -0
- package/dist/modules/navigation/index.d.ts.map +1 -0
- package/dist/modules/navigation/index.js +6 -0
- package/dist/modules/navigation/index.js.map +1 -0
- package/dist/modules/navigation/navigation.d.ts +4 -0
- package/dist/modules/navigation/navigation.d.ts.map +1 -0
- package/dist/modules/navigation/navigation.js +240 -0
- package/dist/modules/navigation/navigation.js.map +1 -0
- package/dist/modules/navigation/types.d.ts +34 -0
- package/dist/modules/navigation/types.d.ts.map +1 -0
- package/dist/modules/navigation/types.js +3 -0
- package/dist/modules/navigation/types.js.map +1 -0
- package/dist/modules/network/index.d.ts +3 -0
- package/dist/modules/network/index.d.ts.map +1 -0
- package/dist/modules/network/index.js +6 -0
- package/dist/modules/network/index.js.map +1 -0
- package/dist/modules/network/network.d.ts +4 -0
- package/dist/modules/network/network.d.ts.map +1 -0
- package/dist/modules/network/network.js +276 -0
- package/dist/modules/network/network.js.map +1 -0
- package/dist/modules/network/types.d.ts +26 -0
- package/dist/modules/network/types.d.ts.map +1 -0
- package/dist/modules/network/types.js +3 -0
- package/dist/modules/network/types.js.map +1 -0
- package/dist/modules/reactQuery/index.d.ts +3 -0
- package/dist/modules/reactQuery/index.d.ts.map +1 -0
- package/dist/modules/reactQuery/index.js +6 -0
- package/dist/modules/reactQuery/index.js.map +1 -0
- package/dist/modules/reactQuery/reactQuery.d.ts +4 -0
- package/dist/modules/reactQuery/reactQuery.d.ts.map +1 -0
- package/dist/modules/reactQuery/reactQuery.js +160 -0
- package/dist/modules/reactQuery/reactQuery.js.map +1 -0
- package/dist/modules/reactQuery/types.d.ts +29 -0
- package/dist/modules/reactQuery/types.d.ts.map +1 -0
- package/dist/modules/reactQuery/types.js +3 -0
- package/dist/modules/reactQuery/types.js.map +1 -0
- package/dist/modules/screenshot/index.d.ts +3 -0
- package/dist/modules/screenshot/index.d.ts.map +1 -0
- package/dist/modules/screenshot/index.js +6 -0
- package/dist/modules/screenshot/index.js.map +1 -0
- package/dist/modules/screenshot/screenshot.d.ts +4 -0
- package/dist/modules/screenshot/screenshot.d.ts.map +1 -0
- package/dist/modules/screenshot/screenshot.js +89 -0
- package/dist/modules/screenshot/screenshot.js.map +1 -0
- package/dist/modules/screenshot/types.d.ts +5 -0
- package/dist/modules/screenshot/types.d.ts.map +1 -0
- package/dist/modules/screenshot/types.js +3 -0
- package/dist/modules/screenshot/types.js.map +1 -0
- package/dist/modules/storage/index.d.ts +3 -0
- package/dist/modules/storage/index.d.ts.map +1 -0
- package/dist/modules/storage/index.js +6 -0
- package/dist/modules/storage/index.js.map +1 -0
- package/dist/modules/storage/storage.d.ts +4 -0
- package/dist/modules/storage/storage.d.ts.map +1 -0
- package/dist/modules/storage/storage.js +124 -0
- package/dist/modules/storage/storage.js.map +1 -0
- package/dist/modules/storage/types.d.ts +11 -0
- package/dist/modules/storage/types.d.ts.map +1 -0
- package/dist/modules/storage/types.js +3 -0
- package/dist/modules/storage/types.js.map +1 -0
- package/dist/modules/tree/index.d.ts +2 -0
- package/dist/modules/tree/index.d.ts.map +1 -0
- package/dist/modules/tree/index.js +6 -0
- package/dist/modules/tree/index.js.map +1 -0
- package/dist/modules/tree/tree.d.ts +3 -0
- package/dist/modules/tree/tree.d.ts.map +1 -0
- package/dist/modules/tree/tree.js +274 -0
- package/dist/modules/tree/tree.js.map +1 -0
- package/dist/server/bridge.d.ts +24 -0
- package/dist/server/bridge.d.ts.map +1 -0
- package/dist/server/bridge.js +152 -0
- package/dist/server/bridge.js.map +1 -0
- package/dist/server/cli.d.ts +3 -0
- package/dist/server/cli.d.ts.map +1 -0
- package/dist/server/cli.js +17 -0
- package/dist/server/cli.js.map +1 -0
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +30 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/mcpServer.d.ts +19 -0
- package/dist/server/mcpServer.d.ts.map +1 -0
- package/dist/server/mcpServer.js +303 -0
- package/dist/server/mcpServer.js.map +1 -0
- package/dist/server/types.d.ts +12 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +3 -0
- package/dist/server/types.js.map +1 -0
- package/dist/shared/protocol.d.ts +54 -0
- package/dist/shared/protocol.d.ts.map +1 -0
- package/dist/shared/protocol.js +8 -0
- package/dist/shared/protocol.js.map +1 -0
- package/package.json +95 -0
package/README.md
ADDED
|
@@ -0,0 +1,868 @@
|
|
|
1
|
+
# react-native-mcp-kit
|
|
2
|
+
|
|
3
|
+
A bidirectional [MCP](https://modelcontextprotocol.io/) bridge that connects AI agents to running React Native apps. The server is a proxy — all business logic runs inside your RN app.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
AI Agent --stdio/MCP--> MCP Server (Node.js) --WebSocket--> RN App (device)
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Features](#features)
|
|
12
|
+
- [Quick Start](#quick-start)
|
|
13
|
+
- [Modules](#modules)
|
|
14
|
+
- [alert](#alert)
|
|
15
|
+
- [fiberTree](#fibertree)
|
|
16
|
+
- [console](#console)
|
|
17
|
+
- [device](#device)
|
|
18
|
+
- [errors](#errors)
|
|
19
|
+
- [i18next](#i18next)
|
|
20
|
+
- [navigation](#navigation)
|
|
21
|
+
- [network](#network)
|
|
22
|
+
- [reactQuery](#reactquery)
|
|
23
|
+
- [screenshot](#screenshot)
|
|
24
|
+
- [storage](#storage)
|
|
25
|
+
- [Hooks](#hooks)
|
|
26
|
+
- [useMcpState](#usemcpstate)
|
|
27
|
+
- [useMcpTool](#usemcptool)
|
|
28
|
+
- [useMcpModule](#usemcpmodule)
|
|
29
|
+
- [Babel Plugins](#babel-plugins)
|
|
30
|
+
- [testIdPlugin](#testidplugin)
|
|
31
|
+
- [stripPlugin](#stripplugin)
|
|
32
|
+
- [Dev vs Production](#dev-vs-production)
|
|
33
|
+
- [MCP Server Tools](#mcp-server-tools)
|
|
34
|
+
- [Custom Modules](#custom-modules)
|
|
35
|
+
- [Debug Logging](#debug-logging)
|
|
36
|
+
- [API Reference](#api-reference)
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- **11 built-in modules** — navigation, fiber tree, screenshot, network, console, storage, device, errors, i18next, React Query, alerts
|
|
41
|
+
- **React fiber inspection** — walk the component tree, read props, invoke callbacks, call ref methods
|
|
42
|
+
- **Screenshots** — capture app screenshots via `@shopify/react-native-skia` with resize and JPEG compression
|
|
43
|
+
- **Developer hooks** — expose state and tools from any component with `useMcpState` and `useMcpTool`
|
|
44
|
+
- **Navigation history** — full log of screen transitions with timestamps and slice access
|
|
45
|
+
- **Modular** — register only the modules you need, or write your own with `description` for AI context
|
|
46
|
+
- **Zero production overhead** — Babel strip plugin removes all MCP code from prod builds
|
|
47
|
+
- **Babel testID plugin** — auto-adds `data-mcp-id` attributes for component identification
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
### 1. Install
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
yarn add react-native-mcp-kit
|
|
55
|
+
# or
|
|
56
|
+
npm install react-native-mcp-kit
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 2. Initialize in your app
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import {
|
|
63
|
+
McpClient,
|
|
64
|
+
McpProvider,
|
|
65
|
+
consoleModule,
|
|
66
|
+
deviceModule,
|
|
67
|
+
fiberTreeModule,
|
|
68
|
+
navigationModule,
|
|
69
|
+
networkModule,
|
|
70
|
+
screenshotModule,
|
|
71
|
+
} from 'react-native-mcp-kit';
|
|
72
|
+
import { createRef } from 'react';
|
|
73
|
+
import { View } from 'react-native';
|
|
74
|
+
|
|
75
|
+
const rootRef = createRef<View>();
|
|
76
|
+
const navigationRef = createNavigationContainerRef();
|
|
77
|
+
|
|
78
|
+
// Initialize client (call once, before any module registration)
|
|
79
|
+
const client = McpClient.initialize({ debug: true });
|
|
80
|
+
|
|
81
|
+
// Register modules
|
|
82
|
+
client.registerModules([
|
|
83
|
+
consoleModule(),
|
|
84
|
+
deviceModule(),
|
|
85
|
+
fiberTreeModule({ rootRef }),
|
|
86
|
+
navigationModule(navigationRef),
|
|
87
|
+
networkModule(),
|
|
88
|
+
screenshotModule({ rootRef }),
|
|
89
|
+
]);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 3. Wrap your app with McpProvider
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
const App = () => {
|
|
96
|
+
return (
|
|
97
|
+
<View ref={rootRef} collapsable={false} style={{ flex: 1 }}>
|
|
98
|
+
<NavigationContainer ref={navigationRef}>
|
|
99
|
+
<McpProvider>{/* your app */}</McpProvider>
|
|
100
|
+
</NavigationContainer>
|
|
101
|
+
</View>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 4. Configure the MCP server
|
|
107
|
+
|
|
108
|
+
Add to your project's `.mcp.json`:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"mcpServers": {
|
|
113
|
+
"react-native-mcp-kit": {
|
|
114
|
+
"command": "npx",
|
|
115
|
+
"args": ["react-native-mcp-kit"]
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Or with a custom port:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"mcpServers": {
|
|
126
|
+
"react-native-mcp-kit": {
|
|
127
|
+
"command": "npx",
|
|
128
|
+
"args": ["react-native-mcp-kit", "--port", "8347"]
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 5. Connect
|
|
135
|
+
|
|
136
|
+
1. Start Metro and run your app
|
|
137
|
+
2. The AI agent connects via MCP and can now inspect and interact with your app
|
|
138
|
+
3. For Android emulator, run `adb reverse tcp:8347 tcp:8347` to forward the port
|
|
139
|
+
|
|
140
|
+
## Modules
|
|
141
|
+
|
|
142
|
+
| Module | Factory | Description |
|
|
143
|
+
| ------------------------- | ------------------------------- | --------------------------------------------------------------- |
|
|
144
|
+
| [alert](#alert) | `alertModule()` | Show native alerts with custom buttons and styles |
|
|
145
|
+
| [fiberTree](#fibertree) | `fiberTreeModule({ rootRef })` | React fiber tree inspection, invoke callbacks, call ref methods |
|
|
146
|
+
| [console](#console) | `consoleModule(options?)` | Capture console.log/warn/error/info/debug |
|
|
147
|
+
| [device](#device) | `deviceModule()` | Device info, app state, keyboard, linking, reload |
|
|
148
|
+
| [errors](#errors) | `errorsModule(options?)` | Capture unhandled errors and promise rejections |
|
|
149
|
+
| [i18next](#i18next) | `i18nextModule(i18n)` | Translation inspection and language management |
|
|
150
|
+
| [navigation](#navigation) | `navigationModule(ref)` | Navigation state, history, navigate, push, pop, replace, reset |
|
|
151
|
+
| [network](#network) | `networkModule(options?)` | HTTP request/response interception |
|
|
152
|
+
| [reactQuery](#reactquery) | `reactQueryModule(queryClient)` | React Query cache inspection and management |
|
|
153
|
+
| [screenshot](#screenshot) | `screenshotModule({ rootRef })` | Capture screenshots via Skia |
|
|
154
|
+
| [storage](#storage) | `storageModule(...storages)` | Key-value storage inspection (MMKV, AsyncStorage, custom) |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### alert
|
|
159
|
+
|
|
160
|
+
Show native alert dialogs with custom buttons and styles.
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
client.registerModules([alertModule()]);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
| Tool | Description | Args |
|
|
167
|
+
| ------ | ----------------- | ---------------------------------------------------------- |
|
|
168
|
+
| `show` | Show alert dialog | `title?: string`, `message?: string`, `buttons?: Button[]` |
|
|
169
|
+
|
|
170
|
+
Buttons can be strings or objects with style:
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// Simple
|
|
174
|
+
call(tool: "alert__show", args: '{"title": "Confirm", "buttons": ["Cancel", "OK"]}')
|
|
175
|
+
|
|
176
|
+
// With styles
|
|
177
|
+
call(tool: "alert__show", args: '{"title": "Delete?", "buttons": [{"text": "Cancel", "style": "cancel"}, {"text": "Delete", "style": "destructive"}]}')
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Button styles: `default`, `cancel`, `destructive`. Returns `{ button: string, index: number }`. Timeout: 60s.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
### fiberTree
|
|
185
|
+
|
|
186
|
+
React fiber tree inspection with the ability to invoke callbacks and call ref methods.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
client.registerModules([fiberTreeModule({ rootRef })]);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Inspection tools:**
|
|
193
|
+
|
|
194
|
+
| Tool | Description | Args |
|
|
195
|
+
| --------------- | ---------------------------- | -------------------------------------------------------------------- |
|
|
196
|
+
| `get_tree` | Get full component tree | `depth?: number` (default: 10) |
|
|
197
|
+
| `get_component` | Find a component | `name?`, `testID?`, `text?`, `mcpId?`, `within?`, `index?`, `depth?` |
|
|
198
|
+
| `find_all` | Find all matching components | `name?`, `testID?`, `text?`, `mcpId?`, `hasProps?`, `within?` |
|
|
199
|
+
| `get_props` | Get component props | same find params |
|
|
200
|
+
| `get_children` | Get component children | same find params, `depth?` |
|
|
201
|
+
|
|
202
|
+
**Interaction tools:**
|
|
203
|
+
|
|
204
|
+
| Tool | Description | Args |
|
|
205
|
+
| ----------------- | -------------------------- | --------------------------------------------------- |
|
|
206
|
+
| `invoke` | Call any callback prop | find params, `callback: string`, `args?: unknown[]` |
|
|
207
|
+
| `call_ref` | Call method on native ref | find params, `method: string`, `args?: unknown[]` |
|
|
208
|
+
| `get_ref_methods` | List available ref methods | find params |
|
|
209
|
+
|
|
210
|
+
**Finding components:**
|
|
211
|
+
|
|
212
|
+
Components can be found by `testID`, `name`, `text`, or `mcpId` (from the Babel testID plugin). Use `within` to scope the search to children of a specific component:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
// Find by testID
|
|
216
|
+
call(tool: "fiber_tree__get_component", args: '{"testID": "login-button"}')
|
|
217
|
+
|
|
218
|
+
// Find by name within a parent
|
|
219
|
+
call(tool: "fiber_tree__get_component", args: '{"name": "Pressable", "within": "LoginForm"}')
|
|
220
|
+
|
|
221
|
+
// Use index for multiple matches (0-based)
|
|
222
|
+
call(tool: "fiber_tree__get_component", args: '{"name": "TextInput", "within": "LoginForm", "index": 1}')
|
|
223
|
+
|
|
224
|
+
// Nested within path with index
|
|
225
|
+
call(tool: "fiber_tree__get_component", args: '{"name": "Text", "within": "Button:1/Pressable"}')
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Invoking callbacks:**
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
// Press a button
|
|
232
|
+
call(tool: "fiber_tree__invoke", args: '{"testID": "submit-btn", "callback": "onPress"}')
|
|
233
|
+
|
|
234
|
+
// Type text
|
|
235
|
+
call(tool: "fiber_tree__invoke", args: '{"mcpId": "Input:screens/Login:42", "callback": "onChangeText", "args": ["user@example.com"]}')
|
|
236
|
+
|
|
237
|
+
// Toggle checkbox with custom args
|
|
238
|
+
call(tool: "fiber_tree__invoke", args: '{"name": "Checkbox", "within": "TermsForm", "callback": "onPress", "args": [true]}')
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Calling ref methods:**
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// Focus an input
|
|
245
|
+
call(tool: "fiber_tree__call_ref", args: '{"testID": "email-input", "method": "focus"}')
|
|
246
|
+
|
|
247
|
+
// List available methods
|
|
248
|
+
call(tool: "fiber_tree__get_ref_methods", args: '{"testID": "email-input"}')
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
### console
|
|
254
|
+
|
|
255
|
+
Intercepts console output with a ring buffer.
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
client.registerModules([consoleModule()]);
|
|
259
|
+
|
|
260
|
+
// With options
|
|
261
|
+
client.registerModules([
|
|
262
|
+
consoleModule({
|
|
263
|
+
maxEntries: 200,
|
|
264
|
+
levels: ['error', 'warn', 'log'],
|
|
265
|
+
stackTrace: ['error', 'warn'], // or true for all levels
|
|
266
|
+
}),
|
|
267
|
+
]);
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
| Tool | Description | Args |
|
|
271
|
+
| -------------- | ---------------- | ---------------------------------- |
|
|
272
|
+
| `get_logs` | Get all logs | `level?: string`, `limit?: number` |
|
|
273
|
+
| `get_errors` | Get error logs | `limit?: number` |
|
|
274
|
+
| `get_warnings` | Get warning logs | `limit?: number` |
|
|
275
|
+
| `get_info` | Get info logs | `limit?: number` |
|
|
276
|
+
| `get_debug` | Get debug logs | `limit?: number` |
|
|
277
|
+
| `clear_logs` | Clear all logs | — |
|
|
278
|
+
|
|
279
|
+
Serializes complex values: functions, class instances, circular refs, Errors, Dates, RegExp, Symbols.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
### device
|
|
284
|
+
|
|
285
|
+
Device info and system APIs.
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
client.registerModules([deviceModule()]);
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
| Tool | Description | Args |
|
|
292
|
+
| ------------------------ | ----------------------------------------------------------------------------------- | ------------------- |
|
|
293
|
+
| `get_device_info` | Comprehensive device info (platform, dimensions, pixel ratio, appearance, dev mode) | — |
|
|
294
|
+
| `get_platform` | Platform (OS, version, constants) | — |
|
|
295
|
+
| `get_dimensions` | Screen and window dimensions | — |
|
|
296
|
+
| `get_pixel_ratio` | Pixel density and font scale | — |
|
|
297
|
+
| `get_appearance` | Color scheme (light/dark) | — |
|
|
298
|
+
| `get_app_state` | App state (active/background/inactive) | — |
|
|
299
|
+
| `get_accessibility_info` | Accessibility settings | — |
|
|
300
|
+
| `get_keyboard_state` | Keyboard visibility and metrics | — |
|
|
301
|
+
| `dismiss_keyboard` | Dismiss keyboard | — |
|
|
302
|
+
| `open_url` | Open URL in appropriate app | `url: string` |
|
|
303
|
+
| `can_open_url` | Check if URL can be opened | `url: string` |
|
|
304
|
+
| `get_initial_url` | Get deep link that launched app | — |
|
|
305
|
+
| `open_settings` | Open app settings | — |
|
|
306
|
+
| `reload` | Reload app (dev only) | — |
|
|
307
|
+
| `vibrate` | Vibrate device | `duration?: number` |
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
### errors
|
|
312
|
+
|
|
313
|
+
Captures unhandled JS errors and promise rejections.
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
client.registerModules([errorsModule()]);
|
|
317
|
+
|
|
318
|
+
// With options
|
|
319
|
+
client.registerModules([errorsModule({ maxEntries: 100 })]);
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
| Tool | Description | Args |
|
|
323
|
+
| -------------- | --------------------- | ------------------------------------------------------ |
|
|
324
|
+
| `get_errors` | Get captured errors | `source?: string`, `fatal?: boolean`, `limit?: number` |
|
|
325
|
+
| `get_fatal` | Get fatal errors only | `limit?: number` |
|
|
326
|
+
| `get_stats` | Error statistics | — |
|
|
327
|
+
| `clear_errors` | Clear all errors | — |
|
|
328
|
+
|
|
329
|
+
Error sources: `global` (ErrorUtils), `promise` (unhandled rejections). Deduplicates within 100ms window.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
### i18next
|
|
334
|
+
|
|
335
|
+
Translation inspection and language management. Accepts an i18next instance.
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
import i18n from './i18n';
|
|
339
|
+
|
|
340
|
+
client.registerModules([i18nextModule(i18n)]);
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
| Tool | Description | Args |
|
|
344
|
+
| ----------------- | ------------------------------------------------- | ---------------------------------------- |
|
|
345
|
+
| `get_info` | Current language, available languages, namespaces | — |
|
|
346
|
+
| `get_resource` | Get full translation resource | `language?`, `namespace?` |
|
|
347
|
+
| `get_keys` | List translation keys | `language?`, `namespace?` |
|
|
348
|
+
| `translate` | Translate a key | `key: string`, `options?: string` (JSON) |
|
|
349
|
+
| `search` | Search keys and values | `query: string`, `language?` |
|
|
350
|
+
| `change_language` | Change current language | `language: string` |
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
// Translate with interpolation
|
|
354
|
+
call(tool: "i18n__translate", args: '{"key": "welcome", "options": "{\"name\": \"John\"}"}')
|
|
355
|
+
|
|
356
|
+
// Search translations
|
|
357
|
+
call(tool: "i18n__search", args: '{"query": "password"}')
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
### navigation
|
|
363
|
+
|
|
364
|
+
Full navigation control with history tracking. Accepts a React Navigation ref.
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import { createNavigationContainerRef } from '@react-navigation/native';
|
|
368
|
+
|
|
369
|
+
const navigationRef = createNavigationContainerRef();
|
|
370
|
+
|
|
371
|
+
client.registerModules([navigationModule(navigationRef)]);
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
| Tool | Description | Args |
|
|
375
|
+
| ------------------------- | ------------------------------------ | -------------------------------------------------- |
|
|
376
|
+
| `get_state` | Full navigation state tree | — |
|
|
377
|
+
| `get_current_route` | Current focused route | — |
|
|
378
|
+
| `get_current_route_state` | Current route with nested state | — |
|
|
379
|
+
| `get_history` | Log of all screen transitions | `offset?`, `limit?`, `full?: boolean` |
|
|
380
|
+
| `navigate` | Navigate to screen (reuses existing) | `screen: string`, `params?: object` |
|
|
381
|
+
| `push` | Push new screen onto stack | `screen: string`, `params?: object` |
|
|
382
|
+
| `pop` | Pop screens | `count?: number` |
|
|
383
|
+
| `pop_to` | Pop to specific screen | `screen: string`, `params?: object` |
|
|
384
|
+
| `pop_to_top` | Pop to first screen | — |
|
|
385
|
+
| `go_back` | Go back to previous screen | — |
|
|
386
|
+
| `replace` | Replace current screen | `screen: string`, `params?: object` |
|
|
387
|
+
| `reset` | Reset navigation state | `routes: Array<{name, params?}>`, `index?: number` |
|
|
388
|
+
|
|
389
|
+
**Navigation history:**
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
// Get simplified history (name, key, params, timestamp)
|
|
393
|
+
call(tool: "navigation__get_history")
|
|
394
|
+
|
|
395
|
+
// Get last 5 transitions
|
|
396
|
+
call(tool: "navigation__get_history", args: '{"limit": 5}')
|
|
397
|
+
|
|
398
|
+
// Get full navigation state for each transition
|
|
399
|
+
call(tool: "navigation__get_history", args: '{"full": true}')
|
|
400
|
+
|
|
401
|
+
// Slice: skip first 10, get next 5
|
|
402
|
+
call(tool: "navigation__get_history", args: '{"offset": 10, "limit": 5}')
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
### network
|
|
408
|
+
|
|
409
|
+
Intercepts `fetch` and `XMLHttpRequest`. Captures request/response bodies, headers, status, duration.
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
client.registerModules([networkModule()]);
|
|
413
|
+
|
|
414
|
+
// With options
|
|
415
|
+
client.registerModules([
|
|
416
|
+
networkModule({
|
|
417
|
+
maxEntries: 200,
|
|
418
|
+
includeBodies: true,
|
|
419
|
+
ignoreUrls: ['https://analytics.example.com', /\.png$/],
|
|
420
|
+
}),
|
|
421
|
+
]);
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
| Tool | Description | Args |
|
|
425
|
+
| ---------------- | ------------------------------ | -------------------------------------- |
|
|
426
|
+
| `get_requests` | Get captured requests | `method?`, `status?`, `url?`, `limit?` |
|
|
427
|
+
| `get_request` | Find requests by URL substring | `url: string` |
|
|
428
|
+
| `get_pending` | Get in-flight requests | — |
|
|
429
|
+
| `get_errors` | Get failed requests | `limit?: number` |
|
|
430
|
+
| `get_stats` | Request statistics | — |
|
|
431
|
+
| `clear_requests` | Clear captured requests | — |
|
|
432
|
+
|
|
433
|
+
Auto-ignores WebSocket, Metro, and symbolicate URLs.
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
### reactQuery
|
|
438
|
+
|
|
439
|
+
React Query cache inspection and management. Accepts a `QueryClient` instance.
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
443
|
+
|
|
444
|
+
const queryClient = new QueryClient();
|
|
445
|
+
|
|
446
|
+
client.registerModules([reactQueryModule(queryClient)]);
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
| Tool | Description | Args |
|
|
450
|
+
| ------------- | ------------------------------- | ----------------------------- |
|
|
451
|
+
| `get_queries` | List all cached queries | `status?`, `key?` (substring) |
|
|
452
|
+
| `get_data` | Get cached data for a query | `key: string` (JSON format) |
|
|
453
|
+
| `get_stats` | Cache statistics | — |
|
|
454
|
+
| `invalidate` | Invalidate queries (mark stale) | `key?: string` |
|
|
455
|
+
| `refetch` | Refetch queries | `key?: string` |
|
|
456
|
+
| `remove` | Remove from cache | `key?: string` |
|
|
457
|
+
| `reset` | Reset to initial state | `key?: string` |
|
|
458
|
+
|
|
459
|
+
```typescript
|
|
460
|
+
// Get data for a specific query
|
|
461
|
+
call(tool: "query__get_data", args: '{"key": "[\"users\",\"list\"]"}')
|
|
462
|
+
|
|
463
|
+
// Invalidate all user queries
|
|
464
|
+
call(tool: "query__invalidate", args: '{"key": "users"}')
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
### screenshot
|
|
470
|
+
|
|
471
|
+
Capture screenshots of the app via `@shopify/react-native-skia`. Requires Skia as a peer dependency.
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
yarn add @shopify/react-native-skia
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
```typescript
|
|
478
|
+
import { createRef } from 'react';
|
|
479
|
+
import { View } from 'react-native';
|
|
480
|
+
|
|
481
|
+
const rootRef = createRef<View>();
|
|
482
|
+
|
|
483
|
+
client.registerModules([screenshotModule({ rootRef })]);
|
|
484
|
+
|
|
485
|
+
// JSX — rootRef must have collapsable={false}
|
|
486
|
+
<View ref={rootRef} collapsable={false} style={{ flex: 1 }}>
|
|
487
|
+
{/* app */}
|
|
488
|
+
</View>
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
| Tool | Description | Args |
|
|
492
|
+
| --------- | ------------------ | ----------------------------------------------------------------- |
|
|
493
|
+
| `capture` | Capture screenshot | `format?: 'jpeg'\|'png'`, `quality?: number`, `maxWidth?: number` |
|
|
494
|
+
|
|
495
|
+
Default: JPEG, quality 80, max width 600px (height scales proportionally). Images are resized via `Skia.Surface.Make` + `drawImageRectOptions` for optimal size.
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
// Default (JPEG, 600px wide)
|
|
499
|
+
call(tool: "screenshot__capture")
|
|
500
|
+
|
|
501
|
+
// High quality PNG
|
|
502
|
+
call(tool: "screenshot__capture", args: '{"format": "png", "quality": 100}')
|
|
503
|
+
|
|
504
|
+
// Smaller image
|
|
505
|
+
call(tool: "screenshot__capture", args: '{"maxWidth": 400, "quality": 50}')
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
### storage
|
|
511
|
+
|
|
512
|
+
Key-value storage inspection. Supports multiple named storage instances with flexible adapters.
|
|
513
|
+
|
|
514
|
+
```typescript
|
|
515
|
+
// Single storage
|
|
516
|
+
client.registerModules([storageModule({ name: 'app', adapter: myStorageAdapter })]);
|
|
517
|
+
|
|
518
|
+
// Multiple storages
|
|
519
|
+
client.registerModules([
|
|
520
|
+
storageModule({ name: 'app', adapter: appStorage }, { name: 'cache', adapter: cacheStorage }),
|
|
521
|
+
]);
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
**Adapter interface** — only `get` is required:
|
|
525
|
+
|
|
526
|
+
```typescript
|
|
527
|
+
interface StorageAdapter {
|
|
528
|
+
get(key: string): string | undefined | null | Promise<string | undefined | null>;
|
|
529
|
+
set?(key: string, value: string): void | Promise<void>;
|
|
530
|
+
delete?(key: string): void | Promise<void>;
|
|
531
|
+
getAllKeys?(): string[] | Promise<string[]>;
|
|
532
|
+
}
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
| Tool | Description | Args |
|
|
536
|
+
| --------------- | ------------------------ | -------------------------------------------------- |
|
|
537
|
+
| `get_item` | Get value by key | `key: string`, `storage?: string` |
|
|
538
|
+
| `set_item` | Set value | `key: string`, `value: string`, `storage?: string` |
|
|
539
|
+
| `delete_item` | Delete key | `key: string`, `storage?: string` |
|
|
540
|
+
| `list_keys` | List all keys | `storage?: string` |
|
|
541
|
+
| `get_all` | Get all key-value pairs | `storage?: string` |
|
|
542
|
+
| `list_storages` | List registered storages | — |
|
|
543
|
+
|
|
544
|
+
Works with MMKV, AsyncStorage, or any custom adapter.
|
|
545
|
+
|
|
546
|
+
## Hooks
|
|
547
|
+
|
|
548
|
+
Hooks let you expose state and tools from React components.
|
|
549
|
+
|
|
550
|
+
### useMcpState
|
|
551
|
+
|
|
552
|
+
Expose reactive state to the AI agent:
|
|
553
|
+
|
|
554
|
+
```typescript
|
|
555
|
+
useMcpState(
|
|
556
|
+
key: string,
|
|
557
|
+
factory: () => unknown,
|
|
558
|
+
deps: DependencyList
|
|
559
|
+
): void
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
const UserProvider = ({ children }) => {
|
|
564
|
+
const [user, setUser] = useState(null);
|
|
565
|
+
|
|
566
|
+
useMcpState(
|
|
567
|
+
'user',
|
|
568
|
+
() => ({
|
|
569
|
+
email: user?.email,
|
|
570
|
+
id: user?.id,
|
|
571
|
+
loggedIn: user !== null,
|
|
572
|
+
}),
|
|
573
|
+
[user]
|
|
574
|
+
);
|
|
575
|
+
|
|
576
|
+
// ...
|
|
577
|
+
};
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
The agent reads state via `state_get` and `state_list` tools — no WebSocket roundtrip needed.
|
|
581
|
+
|
|
582
|
+
### useMcpTool
|
|
583
|
+
|
|
584
|
+
Register a dynamic tool from a component:
|
|
585
|
+
|
|
586
|
+
```typescript
|
|
587
|
+
useMcpTool(
|
|
588
|
+
name: string,
|
|
589
|
+
factory: () => ToolHandler,
|
|
590
|
+
deps: DependencyList
|
|
591
|
+
): void
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
const UserProvider = ({ children }) => {
|
|
596
|
+
const logout = useCallback(() => {
|
|
597
|
+
/* ... */
|
|
598
|
+
}, []);
|
|
599
|
+
|
|
600
|
+
useMcpTool(
|
|
601
|
+
'logout',
|
|
602
|
+
() => ({
|
|
603
|
+
description: 'Log out the current user',
|
|
604
|
+
handler: () => {
|
|
605
|
+
logout();
|
|
606
|
+
return { success: true };
|
|
607
|
+
},
|
|
608
|
+
}),
|
|
609
|
+
[logout]
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
// ...
|
|
613
|
+
};
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
Dynamic tools are accessible via `call(tool: "_dynamic_logout")` and appear in `list_tools` with a `(dynamic)` label.
|
|
617
|
+
|
|
618
|
+
### useMcpModule
|
|
619
|
+
|
|
620
|
+
Register a full module from a component (tied to component lifecycle):
|
|
621
|
+
|
|
622
|
+
```typescript
|
|
623
|
+
useMcpModule(
|
|
624
|
+
factory: () => McpModule,
|
|
625
|
+
deps: DependencyList
|
|
626
|
+
): void
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
```typescript
|
|
630
|
+
const App = () => {
|
|
631
|
+
const queryClient = useQueryClient();
|
|
632
|
+
|
|
633
|
+
useMcpModule(() => reactQueryModule(queryClient), [queryClient]);
|
|
634
|
+
|
|
635
|
+
// ...
|
|
636
|
+
};
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
## Babel Plugins
|
|
640
|
+
|
|
641
|
+
### testIdPlugin
|
|
642
|
+
|
|
643
|
+
Auto-adds `data-mcp-id` attributes to JSX components for reliable component identification.
|
|
644
|
+
|
|
645
|
+
```javascript
|
|
646
|
+
// babel.config.js
|
|
647
|
+
module.exports = {
|
|
648
|
+
plugins: [
|
|
649
|
+
[
|
|
650
|
+
'react-native-mcp-kit/babel/test-id-plugin',
|
|
651
|
+
{
|
|
652
|
+
attr: 'data-mcp-id', // attribute name (default)
|
|
653
|
+
separator: ':', // separator (default)
|
|
654
|
+
exclude: ['Fragment'], // components to skip
|
|
655
|
+
include: ['Button', 'Input'], // if set, only these get IDs
|
|
656
|
+
},
|
|
657
|
+
],
|
|
658
|
+
],
|
|
659
|
+
};
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
Generated ID format: `ComponentName:filePath:line`
|
|
663
|
+
|
|
664
|
+
```tsx
|
|
665
|
+
// Before
|
|
666
|
+
<LoginButton onPress={handleLogin} />
|
|
667
|
+
|
|
668
|
+
// After (dev build)
|
|
669
|
+
<LoginButton onPress={handleLogin} data-mcp-id="LoginButton:src/screens/Login:42" />
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
### stripPlugin
|
|
673
|
+
|
|
674
|
+
Removes all MCP code from production builds. Zero MCP code in the final bundle.
|
|
675
|
+
|
|
676
|
+
```javascript
|
|
677
|
+
// babel.config.js
|
|
678
|
+
module.exports = (api) => {
|
|
679
|
+
const isDev = api.cache(() => process.env.NODE_ENV !== 'production');
|
|
680
|
+
|
|
681
|
+
return {
|
|
682
|
+
plugins: [
|
|
683
|
+
isDev && ['react-native-mcp-kit/babel/test-id-plugin'],
|
|
684
|
+
!isDev && ['react-native-mcp-kit/babel/strip-plugin'],
|
|
685
|
+
].filter(Boolean),
|
|
686
|
+
};
|
|
687
|
+
};
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
**What it removes:**
|
|
691
|
+
|
|
692
|
+
- All imports from `react-native-mcp-kit`
|
|
693
|
+
- `McpClient.initialize()`, `registerModule()`, `registerModules()` calls
|
|
694
|
+
- `useMcpState()`, `useMcpTool()`, `useMcpModule()` calls
|
|
695
|
+
- `<McpProvider>` JSX (replaced with children)
|
|
696
|
+
- `data-mcp-id` JSX attributes
|
|
697
|
+
|
|
698
|
+
With the strip plugin, you don't need `if (__DEV__)` guards — just write MCP code normally and it gets removed in production.
|
|
699
|
+
|
|
700
|
+
## Dev vs Production
|
|
701
|
+
|
|
702
|
+
Two strategies for production safety:
|
|
703
|
+
|
|
704
|
+
1. **Strip plugin** (Babel) — removes all MCP imports, calls, and JSX from the production bundle. No MCP code ships to users.
|
|
705
|
+
2. **Without strip plugin** — MCP code stays but WebSocket connection to non-existent server is harmless.
|
|
706
|
+
|
|
707
|
+
## MCP Server Tools
|
|
708
|
+
|
|
709
|
+
The server exposes 5 static tools (no dynamic registration needed):
|
|
710
|
+
|
|
711
|
+
| Tool | Description |
|
|
712
|
+
| ------------------- | ------------------------------------------------------------- |
|
|
713
|
+
| `call` | Universal proxy — calls any tool registered by the RN app |
|
|
714
|
+
| `list_tools` | Lists all available tools grouped by module with descriptions |
|
|
715
|
+
| `connection_status` | Check if the RN app is connected |
|
|
716
|
+
| `state_get` | Read state exposed by `useMcpState` |
|
|
717
|
+
| `state_list` | List all available state keys |
|
|
718
|
+
|
|
719
|
+
**Using `call`:**
|
|
720
|
+
|
|
721
|
+
```
|
|
722
|
+
call(tool: "navigation__navigate", args: '{"screen": "Settings"}')
|
|
723
|
+
call(tool: "console__get_errors")
|
|
724
|
+
call(tool: "_dynamic_logout")
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
The `tool` argument uses `module__method` format (double underscore). Dynamic tools from `useMcpTool` use the `_dynamic_` prefix.
|
|
728
|
+
|
|
729
|
+
The server includes instructions and tool annotations to help AI agents understand how to interact with the app.
|
|
730
|
+
|
|
731
|
+
## Custom Modules
|
|
732
|
+
|
|
733
|
+
Create your own module by returning an `McpModule` object:
|
|
734
|
+
|
|
735
|
+
```typescript
|
|
736
|
+
import { type McpModule } from 'react-native-mcp-kit';
|
|
737
|
+
|
|
738
|
+
const myModule = (): McpModule => {
|
|
739
|
+
return {
|
|
740
|
+
description: 'My custom module for AI agents',
|
|
741
|
+
name: 'myModule',
|
|
742
|
+
tools: {
|
|
743
|
+
greet: {
|
|
744
|
+
description: 'Returns a greeting',
|
|
745
|
+
handler: async (args) => {
|
|
746
|
+
const name = args.name as string;
|
|
747
|
+
return { message: `Hello, ${name}!` };
|
|
748
|
+
},
|
|
749
|
+
},
|
|
750
|
+
getStatus: {
|
|
751
|
+
description: 'Get current status',
|
|
752
|
+
handler: () => {
|
|
753
|
+
return { status: 'ok', timestamp: Date.now() };
|
|
754
|
+
},
|
|
755
|
+
timeout: 5000, // custom timeout in ms (default: 10s)
|
|
756
|
+
},
|
|
757
|
+
},
|
|
758
|
+
};
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
// Register
|
|
762
|
+
client.registerModules([myModule()]);
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
**Module registration methods:**
|
|
766
|
+
|
|
767
|
+
```typescript
|
|
768
|
+
// At init time
|
|
769
|
+
const client = McpClient.initialize();
|
|
770
|
+
client.registerModules([myModule()]);
|
|
771
|
+
|
|
772
|
+
// After init
|
|
773
|
+
McpClient.getInstance().registerModule(myModule());
|
|
774
|
+
|
|
775
|
+
// From a component (tied to lifecycle)
|
|
776
|
+
useMcpModule(() => myModule(), []);
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
## Debug Logging
|
|
780
|
+
|
|
781
|
+
Enable colored console output for all MCP communication:
|
|
782
|
+
|
|
783
|
+
```typescript
|
|
784
|
+
McpClient.initialize({ debug: true });
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
Output shows:
|
|
788
|
+
|
|
789
|
+
- `[rn-mcp-kit]` tag (bold purple)
|
|
790
|
+
- Colored module names (12 bold ANSI colors, assigned by registration order)
|
|
791
|
+
- Bold method names
|
|
792
|
+
- `→` incoming tool requests (cyan)
|
|
793
|
+
- `←` responses (green)
|
|
794
|
+
- `✕` errors (red)
|
|
795
|
+
|
|
796
|
+
Debug logs use the original `console.log` (captured before the console module intercepts), so they don't appear in the console module buffer.
|
|
797
|
+
|
|
798
|
+
## API Reference
|
|
799
|
+
|
|
800
|
+
### McpClient
|
|
801
|
+
|
|
802
|
+
```typescript
|
|
803
|
+
// Initialize (creates singleton)
|
|
804
|
+
static initialize(options?: { debug?: boolean; host?: string; port?: number }): McpClient
|
|
805
|
+
|
|
806
|
+
// Get existing instance (throws if not initialized)
|
|
807
|
+
static getInstance(): McpClient
|
|
808
|
+
|
|
809
|
+
// Module registration
|
|
810
|
+
registerModule(module: McpModule): void
|
|
811
|
+
registerModules(modules: McpModule[]): void
|
|
812
|
+
|
|
813
|
+
// Dynamic tools
|
|
814
|
+
registerTool(name: string, tool: ToolHandler): void
|
|
815
|
+
unregisterTool(name: string): void
|
|
816
|
+
|
|
817
|
+
// State
|
|
818
|
+
setState(key: string, value: unknown): void
|
|
819
|
+
removeState(key: string): void
|
|
820
|
+
|
|
821
|
+
// Lifecycle
|
|
822
|
+
dispose(): void
|
|
823
|
+
enableDebug(enabled: boolean): void
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
### McpModule
|
|
827
|
+
|
|
828
|
+
```typescript
|
|
829
|
+
interface McpModule {
|
|
830
|
+
description?: string;
|
|
831
|
+
name: string;
|
|
832
|
+
tools: Record<string, ToolHandler>;
|
|
833
|
+
}
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
### ToolHandler
|
|
837
|
+
|
|
838
|
+
```typescript
|
|
839
|
+
interface ToolHandler {
|
|
840
|
+
description: string;
|
|
841
|
+
handler: (args: Record<string, unknown>) => unknown | Promise<unknown>;
|
|
842
|
+
inputSchema?: Record<string, unknown>;
|
|
843
|
+
timeout?: number; // per-tool timeout in ms (default: 10s)
|
|
844
|
+
}
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
## Symlink Setup (for local development)
|
|
848
|
+
|
|
849
|
+
If you're developing with the library linked locally via symlink/portal:
|
|
850
|
+
|
|
851
|
+
```javascript
|
|
852
|
+
// metro.config.js
|
|
853
|
+
const mcpPath = require('path').resolve(__dirname, '../path-to/react-native-mcp-kit');
|
|
854
|
+
|
|
855
|
+
module.exports = {
|
|
856
|
+
watchFolders: [mcpPath],
|
|
857
|
+
resolver: {
|
|
858
|
+
nodeModulesPaths: [
|
|
859
|
+
path.resolve(__dirname, 'node_modules'),
|
|
860
|
+
path.resolve(mcpPath, 'node_modules'),
|
|
861
|
+
],
|
|
862
|
+
},
|
|
863
|
+
};
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
## License
|
|
867
|
+
|
|
868
|
+
MIT
|