devlens-mcp 0.3.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/.claude/settings.json +12 -0
- package/.claude/settings.local.json +17 -0
- package/INSTALLATION_GUIDE.md +354 -0
- package/QUICK_START.md +153 -0
- package/README.md +354 -0
- package/bin/cli.ts +22 -0
- package/bin/register.ts +96 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +20 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/register.d.ts +10 -0
- package/dist/bin/register.d.ts.map +1 -0
- package/dist/bin/register.js +92 -0
- package/dist/bin/register.js.map +1 -0
- package/dist/src/config/devlens-config.d.ts +92 -0
- package/dist/src/config/devlens-config.d.ts.map +1 -0
- package/dist/src/config/devlens-config.js +70 -0
- package/dist/src/config/devlens-config.js.map +1 -0
- package/dist/src/index.d.ts +35 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +8 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/metro/cdp-client.d.ts +48 -0
- package/dist/src/metro/cdp-client.d.ts.map +1 -0
- package/dist/src/metro/cdp-client.js +127 -0
- package/dist/src/metro/cdp-client.js.map +1 -0
- package/dist/src/metro/log-collector.d.ts +30 -0
- package/dist/src/metro/log-collector.d.ts.map +1 -0
- package/dist/src/metro/log-collector.js +114 -0
- package/dist/src/metro/log-collector.js.map +1 -0
- package/dist/src/metro/metro-bridge.d.ts +56 -0
- package/dist/src/metro/metro-bridge.d.ts.map +1 -0
- package/dist/src/metro/metro-bridge.js +255 -0
- package/dist/src/metro/metro-bridge.js.map +1 -0
- package/dist/src/metro/network-inspector.d.ts +34 -0
- package/dist/src/metro/network-inspector.d.ts.map +1 -0
- package/dist/src/metro/network-inspector.js +100 -0
- package/dist/src/metro/network-inspector.js.map +1 -0
- package/dist/src/platform/android/adb.d.ts +50 -0
- package/dist/src/platform/android/adb.d.ts.map +1 -0
- package/dist/src/platform/android/adb.js +137 -0
- package/dist/src/platform/android/adb.js.map +1 -0
- package/dist/src/platform/android/android-device.d.ts +21 -0
- package/dist/src/platform/android/android-device.d.ts.map +1 -0
- package/dist/src/platform/android/android-device.js +94 -0
- package/dist/src/platform/android/android-device.js.map +1 -0
- package/dist/src/platform/android/ui-automator.d.ts +17 -0
- package/dist/src/platform/android/ui-automator.d.ts.map +1 -0
- package/dist/src/platform/android/ui-automator.js +126 -0
- package/dist/src/platform/android/ui-automator.js.map +1 -0
- package/dist/src/platform/device-manager.d.ts +28 -0
- package/dist/src/platform/device-manager.d.ts.map +1 -0
- package/dist/src/platform/device-manager.js +185 -0
- package/dist/src/platform/device-manager.js.map +1 -0
- package/dist/src/platform/device.d.ts +86 -0
- package/dist/src/platform/device.d.ts.map +1 -0
- package/dist/src/platform/device.js +7 -0
- package/dist/src/platform/device.js.map +1 -0
- package/dist/src/platform/ios/accessibility.d.ts +17 -0
- package/dist/src/platform/ios/accessibility.d.ts.map +1 -0
- package/dist/src/platform/ios/accessibility.js +159 -0
- package/dist/src/platform/ios/accessibility.js.map +1 -0
- package/dist/src/platform/ios/ios-device.d.ts +22 -0
- package/dist/src/platform/ios/ios-device.d.ts.map +1 -0
- package/dist/src/platform/ios/ios-device.js +97 -0
- package/dist/src/platform/ios/ios-device.js.map +1 -0
- package/dist/src/platform/ios/simctl.d.ts +54 -0
- package/dist/src/platform/ios/simctl.d.ts.map +1 -0
- package/dist/src/platform/ios/simctl.js +192 -0
- package/dist/src/platform/ios/simctl.js.map +1 -0
- package/dist/src/server.d.ts +3 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/server.js +176 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/snapshot/formatter.d.ts +18 -0
- package/dist/src/snapshot/formatter.d.ts.map +1 -0
- package/dist/src/snapshot/formatter.js +86 -0
- package/dist/src/snapshot/formatter.js.map +1 -0
- package/dist/src/snapshot/ref-registry.d.ts +67 -0
- package/dist/src/snapshot/ref-registry.d.ts.map +1 -0
- package/dist/src/snapshot/ref-registry.js +169 -0
- package/dist/src/snapshot/ref-registry.js.map +1 -0
- package/dist/src/snapshot/snapshot-differ.d.ts +57 -0
- package/dist/src/snapshot/snapshot-differ.d.ts.map +1 -0
- package/dist/src/snapshot/snapshot-differ.js +153 -0
- package/dist/src/snapshot/snapshot-differ.js.map +1 -0
- package/dist/src/tools/app-tools.d.ts +71 -0
- package/dist/src/tools/app-tools.d.ts.map +1 -0
- package/dist/src/tools/app-tools.js +97 -0
- package/dist/src/tools/app-tools.js.map +1 -0
- package/dist/src/tools/device-tools.d.ts +53 -0
- package/dist/src/tools/device-tools.d.ts.map +1 -0
- package/dist/src/tools/device-tools.js +86 -0
- package/dist/src/tools/device-tools.js.map +1 -0
- package/dist/src/tools/ds-tools.d.ts +65 -0
- package/dist/src/tools/ds-tools.d.ts.map +1 -0
- package/dist/src/tools/ds-tools.js +314 -0
- package/dist/src/tools/ds-tools.js.map +1 -0
- package/dist/src/tools/interaction-tools.d.ts +248 -0
- package/dist/src/tools/interaction-tools.d.ts.map +1 -0
- package/dist/src/tools/interaction-tools.js +391 -0
- package/dist/src/tools/interaction-tools.js.map +1 -0
- package/dist/src/tools/metro-tools.d.ts +115 -0
- package/dist/src/tools/metro-tools.d.ts.map +1 -0
- package/dist/src/tools/metro-tools.js +270 -0
- package/dist/src/tools/metro-tools.js.map +1 -0
- package/dist/src/tools/navigation-tools.d.ts +36 -0
- package/dist/src/tools/navigation-tools.d.ts.map +1 -0
- package/dist/src/tools/navigation-tools.js +60 -0
- package/dist/src/tools/navigation-tools.js.map +1 -0
- package/dist/src/tools/screenshot-tools.d.ts +298 -0
- package/dist/src/tools/screenshot-tools.d.ts.map +1 -0
- package/dist/src/tools/screenshot-tools.js +565 -0
- package/dist/src/tools/screenshot-tools.js.map +1 -0
- package/dist/src/tools/snapshot-tools.d.ts +161 -0
- package/dist/src/tools/snapshot-tools.d.ts.map +1 -0
- package/dist/src/tools/snapshot-tools.js +479 -0
- package/dist/src/tools/snapshot-tools.js.map +1 -0
- package/dist/src/utils/image-preprocess.d.ts +49 -0
- package/dist/src/utils/image-preprocess.d.ts.map +1 -0
- package/dist/src/utils/image-preprocess.js +322 -0
- package/dist/src/utils/image-preprocess.js.map +1 -0
- package/dist/src/utils/retry.d.ts +21 -0
- package/dist/src/utils/retry.d.ts.map +1 -0
- package/dist/src/utils/retry.js +33 -0
- package/dist/src/utils/retry.js.map +1 -0
- package/dist/src/visual/comparator.d.ts +51 -0
- package/dist/src/visual/comparator.d.ts.map +1 -0
- package/dist/src/visual/comparator.js +119 -0
- package/dist/src/visual/comparator.js.map +1 -0
- package/dist/src/visual/layout-analyzer.d.ts +64 -0
- package/dist/src/visual/layout-analyzer.d.ts.map +1 -0
- package/dist/src/visual/layout-analyzer.js +198 -0
- package/dist/src/visual/layout-analyzer.js.map +1 -0
- package/dist/src/visual/screenshot.d.ts +17 -0
- package/dist/src/visual/screenshot.d.ts.map +1 -0
- package/dist/src/visual/screenshot.js +39 -0
- package/dist/src/visual/screenshot.js.map +1 -0
- package/docs/figma-workflow.md +289 -0
- package/docs/setup-guide.md +360 -0
- package/docs/tool-reference.md +622 -0
- package/package.json +57 -0
- package/src/config/devlens-config.ts +76 -0
- package/src/index.ts +5 -0
- package/src/metro/cdp-client.ts +160 -0
- package/src/metro/log-collector.ts +137 -0
- package/src/metro/metro-bridge.ts +307 -0
- package/src/metro/network-inspector.ts +134 -0
- package/src/platform/android/adb.ts +200 -0
- package/src/platform/android/android-device.ts +116 -0
- package/src/platform/android/ui-automator.ts +141 -0
- package/src/platform/device-manager.ts +229 -0
- package/src/platform/device.ts +110 -0
- package/src/platform/ios/accessibility.ts +189 -0
- package/src/platform/ios/ios-device.ts +116 -0
- package/src/platform/ios/simctl.ts +244 -0
- package/src/server.ts +228 -0
- package/src/snapshot/formatter.ts +102 -0
- package/src/snapshot/ref-registry.ts +230 -0
- package/src/snapshot/snapshot-differ.ts +220 -0
- package/src/tools/app-tools.ts +111 -0
- package/src/tools/device-tools.ts +96 -0
- package/src/tools/ds-tools.ts +395 -0
- package/src/tools/interaction-tools.ts +467 -0
- package/src/tools/metro-tools.ts +320 -0
- package/src/tools/navigation-tools.ts +71 -0
- package/src/tools/screenshot-tools.ts +698 -0
- package/src/tools/snapshot-tools.ts +585 -0
- package/src/utils/image-preprocess.ts +430 -0
- package/src/utils/retry.ts +51 -0
- package/src/visual/comparator.ts +191 -0
- package/src/visual/layout-analyzer.ts +283 -0
- package/src/visual/screenshot.ts +49 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
# DevLens Tool Reference
|
|
2
|
+
|
|
3
|
+
Complete reference for all **33** DevLens MCP tools, organized by category.
|
|
4
|
+
|
|
5
|
+
> **Tip:** Use `devlens_metro_status` at the start of every session to verify Metro is healthy before invoking Metro-dependent tools.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Device Management (3)
|
|
10
|
+
|
|
11
|
+
### devlens_list_devices
|
|
12
|
+
List all running iOS Simulators and Android Emulators.
|
|
13
|
+
|
|
14
|
+
**Parameters:** None
|
|
15
|
+
|
|
16
|
+
**Returns:** Device IDs, names, platforms, OS versions, and boot status.
|
|
17
|
+
|
|
18
|
+
**Example response:**
|
|
19
|
+
```
|
|
20
|
+
Found 2 device(s):
|
|
21
|
+
|
|
22
|
+
● Pixel 7 (android, 14) — id: emulator-5554
|
|
23
|
+
● iPhone 16 (ios, 18.0) — id: ABCD-1234-EFGH
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
### devlens_device_info
|
|
29
|
+
Get detailed information about a device.
|
|
30
|
+
|
|
31
|
+
| Param | Type | Required | Description |
|
|
32
|
+
|-------|------|----------|-------------|
|
|
33
|
+
| `deviceId` | string | No | Device ID. Uses first available if omitted. |
|
|
34
|
+
|
|
35
|
+
**Example response:**
|
|
36
|
+
```
|
|
37
|
+
Device: Pixel 7
|
|
38
|
+
Platform: android
|
|
39
|
+
OS Version: 14
|
|
40
|
+
Screen: 1080x2400
|
|
41
|
+
Orientation: portrait
|
|
42
|
+
ID: emulator-5554
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
### devlens_set_orientation
|
|
48
|
+
Set device orientation.
|
|
49
|
+
|
|
50
|
+
| Param | Type | Required | Description |
|
|
51
|
+
|-------|------|----------|-------------|
|
|
52
|
+
| `orientation` | "portrait" \| "landscape" | Yes | Target orientation |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## App Management (4)
|
|
57
|
+
|
|
58
|
+
### devlens_launch_app
|
|
59
|
+
Launch an installed app.
|
|
60
|
+
|
|
61
|
+
| Param | Type | Required | Description |
|
|
62
|
+
|-------|------|----------|-------------|
|
|
63
|
+
| `appId` | string | Yes | Bundle ID (iOS) or package name (Android) |
|
|
64
|
+
|
|
65
|
+
**Example:** `devlens_launch_app(appId: "com.example.myapp")`
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### devlens_terminate_app
|
|
70
|
+
Force stop a running app.
|
|
71
|
+
|
|
72
|
+
| Param | Type | Required | Description |
|
|
73
|
+
|-------|------|----------|-------------|
|
|
74
|
+
| `appId` | string | Yes | Bundle ID or package name |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### devlens_install_app
|
|
79
|
+
Install an app from local file.
|
|
80
|
+
|
|
81
|
+
| Param | Type | Required | Description |
|
|
82
|
+
|-------|------|----------|-------------|
|
|
83
|
+
| `path` | string | Yes | Path to .apk (Android) or .app/.ipa (iOS) |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
### devlens_list_apps
|
|
88
|
+
List all installed third-party apps.
|
|
89
|
+
|
|
90
|
+
**Parameters:** None
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Snapshot & Elements (5)
|
|
95
|
+
|
|
96
|
+
### devlens_snapshot
|
|
97
|
+
**The core tool.** Captures the accessibility tree with Playwright-style ref IDs.
|
|
98
|
+
|
|
99
|
+
| Param | Type | Required | Description |
|
|
100
|
+
|-------|------|----------|-------------|
|
|
101
|
+
| `mode` | "full" \| "incremental" | No | "full" (default) returns entire tree. "incremental" returns only changes since last snapshot. |
|
|
102
|
+
| `validate` | boolean | No | When `true`, appends a **Validation Report** that flags zero-size elements, invisible nodes, and empty containers. Default: `false`. |
|
|
103
|
+
|
|
104
|
+
**Example response:**
|
|
105
|
+
```
|
|
106
|
+
- FrameLayout
|
|
107
|
+
- LinearLayout
|
|
108
|
+
- ImageView "Logo" [ref=e1]
|
|
109
|
+
- TextView "Welcome to MyApp" [ref=e2]
|
|
110
|
+
- EditText "Email" [ref=e3] [focused] [id="email_input"]
|
|
111
|
+
- EditText "Password" [ref=e4] [id="password_input"]
|
|
112
|
+
- Button "Sign In" [ref=e5]
|
|
113
|
+
- TextView "Forgot Password?" [ref=e6]
|
|
114
|
+
- BottomNavigationView
|
|
115
|
+
- MenuItem "Home" [ref=e7]
|
|
116
|
+
- MenuItem "Profile" [ref=e8]
|
|
117
|
+
|
|
118
|
+
8 elements with refs assigned.
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**With `validate: true`:**
|
|
122
|
+
```
|
|
123
|
+
...tree output...
|
|
124
|
+
|
|
125
|
+
=== Validation Report ===
|
|
126
|
+
Total: 42 nodes | Visible: 38 | Zero-size: 4 | Interactive: 12
|
|
127
|
+
|
|
128
|
+
⚠ Issues found:
|
|
129
|
+
• ImageView "BrandLogo" has zero size (0x0) — renders as invisible
|
|
130
|
+
• View id="divider_line" is an empty container (no children, no text)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Use the `ref=eN` values with interaction tools (`devlens_tap`, `devlens_type`, etc.).
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### devlens_find_element
|
|
138
|
+
Find elements matching text, accessibility label, or element type.
|
|
139
|
+
|
|
140
|
+
| Param | Type | Required | Description |
|
|
141
|
+
|-------|------|----------|-------------|
|
|
142
|
+
| `text` | string | No | Text content to search (partial match) |
|
|
143
|
+
| `label` | string | No | Accessibility label to search (partial match) |
|
|
144
|
+
| `type` | string | No | Element type to search (partial, case-insensitive). E.g., "Button", "ScrollView", "EditText" |
|
|
145
|
+
|
|
146
|
+
At least one of `text`, `label`, or `type` must be provided. When `type` is combined with `text`/`label`, elements must match the type AND one of text/label.
|
|
147
|
+
|
|
148
|
+
**Invisible element detection:** If no visible matches are found, DevLens also searches zero-size (invisible) nodes. If a match is found there, a warning is returned:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
No visible elements found for "BrandLogo", but found 1 invisible match:
|
|
152
|
+
⚠ ImageView "BrandLogo" exists but has zero size (0x0) — it renders as invisible.
|
|
153
|
+
This usually means the image source is missing, the style sets width/height to 0,
|
|
154
|
+
or a parent container is collapsing.
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### devlens_wait_for_element
|
|
160
|
+
Wait for an element to appear on screen.
|
|
161
|
+
|
|
162
|
+
| Param | Type | Required | Description |
|
|
163
|
+
|-------|------|----------|-------------|
|
|
164
|
+
| `text` | string | No | Text to wait for |
|
|
165
|
+
| `label` | string | No | Label to wait for |
|
|
166
|
+
| `timeout` | number | No | Max wait in ms (default: 10000) |
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
### devlens_wait_for_screen
|
|
171
|
+
Wait for the screen to stabilize or for specific content to appear. **Replaces manual sleep+screenshot loops.**
|
|
172
|
+
|
|
173
|
+
| Param | Type | Required | Description |
|
|
174
|
+
|-------|------|----------|-------------|
|
|
175
|
+
| `text` | string | No | Wait until this text appears on screen |
|
|
176
|
+
| `label` | string | No | Wait until this label appears on screen |
|
|
177
|
+
| `stableMs` | number | No | Stability window in ms — screen must remain unchanged for this duration (default: 1000) |
|
|
178
|
+
| `timeoutMs` | number | No | Max wait time in ms (default: 10000) |
|
|
179
|
+
|
|
180
|
+
**Two modes:**
|
|
181
|
+
|
|
182
|
+
1. **Content mode** (when `text` or `label` is provided): Polls every 500ms until the specified text/label appears in the snapshot.
|
|
183
|
+
2. **Stability mode** (when neither is provided): Takes periodic snapshots and waits until the screen stops changing (no diff for `stableMs` milliseconds).
|
|
184
|
+
|
|
185
|
+
**Returns:** The current snapshot with ref IDs on success. Returns `isError: true` with the latest snapshot on timeout.
|
|
186
|
+
|
|
187
|
+
**Example usage:**
|
|
188
|
+
```
|
|
189
|
+
# Wait for a specific screen after navigation
|
|
190
|
+
devlens_wait_for_screen(text: "Welcome Back")
|
|
191
|
+
|
|
192
|
+
# Wait for screen to stop animating/loading
|
|
193
|
+
devlens_wait_for_screen(stableMs: 2000)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
### devlens_element_info
|
|
199
|
+
Get detailed info about an element by ref, including **inferred layout direction**.
|
|
200
|
+
|
|
201
|
+
| Param | Type | Required | Description |
|
|
202
|
+
|-------|------|----------|-------------|
|
|
203
|
+
| `ref` | string | Yes | Element ref (e.g., "e5") |
|
|
204
|
+
|
|
205
|
+
**Response includes:**
|
|
206
|
+
- Element type, text, label, resource ID
|
|
207
|
+
- Bounds (x, y, width, height)
|
|
208
|
+
- Interactive status, focused status, visibility
|
|
209
|
+
- Children count
|
|
210
|
+
- **Inferred Layout** (for containers with children): `row`, `column`, `stacked`, `wrap`, or `unknown`
|
|
211
|
+
|
|
212
|
+
**Example response (container):**
|
|
213
|
+
```
|
|
214
|
+
Element [e3]: LinearLayout
|
|
215
|
+
Bounds: 0,200 1080x400
|
|
216
|
+
Interactive: false
|
|
217
|
+
Children: 4
|
|
218
|
+
Inferred Layout: row (children arranged left-to-right)
|
|
219
|
+
1. ImageView "icon" — x:12, y:210
|
|
220
|
+
2. TextView "Title" — x:60, y:210
|
|
221
|
+
3. TextView "Subtitle" — x:400, y:210
|
|
222
|
+
4. Button "Action" — x:800, y:210
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Interaction (8)
|
|
228
|
+
|
|
229
|
+
### devlens_tap
|
|
230
|
+
Tap an element. Like Playwright's `browser_click`.
|
|
231
|
+
|
|
232
|
+
| Param | Type | Required | Description |
|
|
233
|
+
|-------|------|----------|-------------|
|
|
234
|
+
| `ref` | string | Yes | Element ref from devlens_snapshot |
|
|
235
|
+
| `element` | string | Yes | Human description (e.g., "Submit button") |
|
|
236
|
+
|
|
237
|
+
Returns updated snapshot after tap.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
### devlens_type
|
|
242
|
+
Type text into an input.
|
|
243
|
+
|
|
244
|
+
| Param | Type | Required | Description |
|
|
245
|
+
|-------|------|----------|-------------|
|
|
246
|
+
| `ref` | string | Yes | Input element ref |
|
|
247
|
+
| `text` | string | Yes | Text to type |
|
|
248
|
+
| `submit` | boolean | No | Press Enter after typing (default: false) |
|
|
249
|
+
|
|
250
|
+
Automatically taps the element to focus it first.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
### devlens_swipe
|
|
255
|
+
Swipe gesture.
|
|
256
|
+
|
|
257
|
+
| Param | Type | Required | Description |
|
|
258
|
+
|-------|------|----------|-------------|
|
|
259
|
+
| `direction` | "up" \| "down" \| "left" \| "right" | Yes | Direction |
|
|
260
|
+
| `ref` | string | No | Swipe from this element's center |
|
|
261
|
+
| `distance` | number | No | Distance in pixels (default: 500) |
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### devlens_scroll
|
|
266
|
+
Scroll a scrollable container.
|
|
267
|
+
|
|
268
|
+
| Param | Type | Required | Description |
|
|
269
|
+
|-------|------|----------|-------------|
|
|
270
|
+
| `ref` | string | Yes | Scrollable container ref |
|
|
271
|
+
| `direction` | "up" \| "down" | Yes | Scroll direction |
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
### devlens_long_press
|
|
276
|
+
Long press an element.
|
|
277
|
+
|
|
278
|
+
| Param | Type | Required | Description |
|
|
279
|
+
|-------|------|----------|-------------|
|
|
280
|
+
| `ref` | string | Yes | Element ref |
|
|
281
|
+
| `duration` | number | No | Duration in ms (default: 1000) |
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
### devlens_press_button
|
|
286
|
+
Press a hardware/system button.
|
|
287
|
+
|
|
288
|
+
| Param | Type | Required | Description |
|
|
289
|
+
|-------|------|----------|-------------|
|
|
290
|
+
| `button` | "home" \| "back" \| "enter" | Yes | Button to press |
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
### devlens_fill_form
|
|
295
|
+
Fill multiple form fields at once.
|
|
296
|
+
|
|
297
|
+
| Param | Type | Required | Description |
|
|
298
|
+
|-------|------|----------|-------------|
|
|
299
|
+
| `fields` | Array<{ref, value}> | Yes | Fields to fill |
|
|
300
|
+
|
|
301
|
+
**Example:**
|
|
302
|
+
```json
|
|
303
|
+
{
|
|
304
|
+
"fields": [
|
|
305
|
+
{ "ref": "e3", "value": "user@example.com" },
|
|
306
|
+
{ "ref": "e4", "value": "password123" }
|
|
307
|
+
]
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
### devlens_capture_flow
|
|
314
|
+
Execute a sequence of actions and capture labeled screenshots. Batch-verify multiple screens in a single call.
|
|
315
|
+
|
|
316
|
+
| Param | Type | Required | Description |
|
|
317
|
+
|-------|------|----------|-------------|
|
|
318
|
+
| `steps` | Array | Yes | Sequence of step objects |
|
|
319
|
+
|
|
320
|
+
**Step object:**
|
|
321
|
+
|
|
322
|
+
| Field | Type | Required | Description |
|
|
323
|
+
|-------|------|----------|-------------|
|
|
324
|
+
| `action` | "tap" \| "screenshot" \| "go_back" \| "swipe" \| "wait" \| "press_button" | Yes | Action to perform |
|
|
325
|
+
| `ref` | string | No | Element ref for tap/swipe |
|
|
326
|
+
| `element` | string | No | Human description for tap |
|
|
327
|
+
| `label` | string | No | Label for screenshot steps |
|
|
328
|
+
| `direction` | "up" \| "down" \| "left" \| "right" | No | Direction for swipe |
|
|
329
|
+
| `button` | "home" \| "back" \| "enter" | No | Button for press_button |
|
|
330
|
+
| `ms` | number | No | Wait duration in ms (default: 1000) |
|
|
331
|
+
|
|
332
|
+
**Example — verify 3 tabs:**
|
|
333
|
+
```json
|
|
334
|
+
{
|
|
335
|
+
"steps": [
|
|
336
|
+
{ "action": "tap", "ref": "e5", "element": "Chats tab" },
|
|
337
|
+
{ "action": "screenshot", "label": "chats-screen" },
|
|
338
|
+
{ "action": "tap", "ref": "e6", "element": "Tools tab" },
|
|
339
|
+
{ "action": "screenshot", "label": "tools-screen" },
|
|
340
|
+
{ "action": "tap", "ref": "e7", "element": "Media tab" },
|
|
341
|
+
{ "action": "screenshot", "label": "media-screen" }
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Returns all labeled screenshots + a final snapshot with refs.
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Screenshots & Visual Comparison (5)
|
|
351
|
+
|
|
352
|
+
### devlens_screenshot
|
|
353
|
+
Take a screenshot of the current screen.
|
|
354
|
+
|
|
355
|
+
| Param | Type | Required | Description |
|
|
356
|
+
|-------|------|----------|-------------|
|
|
357
|
+
| `filename` | string | No | Save path (defaults to /tmp/devlens-screenshot-{timestamp}.png) |
|
|
358
|
+
|
|
359
|
+
Returns base64-encoded image + saved file path.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
### devlens_compare_screenshot
|
|
364
|
+
Compare current screen against a reference image from a file path, HTTP URL, or base64 data. Supports region cropping.
|
|
365
|
+
|
|
366
|
+
| Param | Type | Required | Description |
|
|
367
|
+
|-------|------|----------|-------------|
|
|
368
|
+
| `referenceImagePath` | string | No | Path to reference PNG, or an HTTP/HTTPS URL to fetch it from |
|
|
369
|
+
| `referenceImageBase64` | string | No | Base64-encoded PNG data (without `data:` prefix) |
|
|
370
|
+
| `threshold` | number | No | Color threshold 0-1 (default: 0.1, lower = stricter) |
|
|
371
|
+
| `resizeStrategy` | "fit" \| "scale" \| "crop" | No | How to handle dimension mismatches (default: "fit") |
|
|
372
|
+
| `cropRef` | string | No | Crop device screenshot to this element's bounds before comparing |
|
|
373
|
+
| `region` | {x, y, width, height} | No | Crop device screenshot to this pixel region before comparing |
|
|
374
|
+
|
|
375
|
+
> At least one of `referenceImagePath` or `referenceImageBase64` must be provided.
|
|
376
|
+
|
|
377
|
+
**Resize strategies:**
|
|
378
|
+
- **`fit`** (default) — Resize both images to the smaller dimensions. Best for general comparison.
|
|
379
|
+
- **`scale`** — Resize the smaller image up to match the larger. Use when the reference is lower resolution.
|
|
380
|
+
- **`crop`** — Extract the overlapping region from both images. Use when comparing a section of the screen.
|
|
381
|
+
|
|
382
|
+
**Returns:**
|
|
383
|
+
- `similarity`: 0.0 to 1.0 (percentage match)
|
|
384
|
+
- `diffPixels`: Number of different pixels
|
|
385
|
+
- `diffImagePath`: Path to diff image (red highlights = differences)
|
|
386
|
+
- `summary`: Human-readable assessment
|
|
387
|
+
- Both the current screenshot and diff image as base64
|
|
388
|
+
|
|
389
|
+
**Example — compare just a component:**
|
|
390
|
+
```
|
|
391
|
+
devlens_snapshot() # get refs
|
|
392
|
+
devlens_compare_screenshot(
|
|
393
|
+
referenceImagePath: "./design-refs/header.png",
|
|
394
|
+
cropRef: "e3" # only compare the header element
|
|
395
|
+
)
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
### devlens_element_screenshot
|
|
401
|
+
Screenshot a specific element.
|
|
402
|
+
|
|
403
|
+
| Param | Type | Required | Description |
|
|
404
|
+
|-------|------|----------|-------------|
|
|
405
|
+
| `ref` | string | Yes | Element ref |
|
|
406
|
+
| `filename` | string | No | Save path |
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
### devlens_compare_images
|
|
411
|
+
Compare two saved images (A/B comparison). Useful for before/after screenshots.
|
|
412
|
+
|
|
413
|
+
| Param | Type | Required | Description |
|
|
414
|
+
|-------|------|----------|-------------|
|
|
415
|
+
| `imageA` | string | Yes | Path or HTTP URL of the first image |
|
|
416
|
+
| `imageB` | string | Yes | Path or HTTP URL of the second image |
|
|
417
|
+
| `threshold` | number | No | Color threshold 0-1 (default: 0.1) |
|
|
418
|
+
| `resizeStrategy` | "fit" \| "scale" \| "crop" | No | Dimension mismatch handling (default: "fit") |
|
|
419
|
+
|
|
420
|
+
Returns similarity score, diff pixel count, and diff image (same format as `devlens_compare_screenshot`).
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
### devlens_compare_with_figma
|
|
425
|
+
**The Figma verification tool.** Compare the device screen directly against a Figma design. Fetches the Figma frame via REST API and runs pixel comparison. Requires `FIGMA_TOKEN` environment variable.
|
|
426
|
+
|
|
427
|
+
| Param | Type | Required | Description |
|
|
428
|
+
|-------|------|----------|-------------|
|
|
429
|
+
| `figmaUrl` | string | No | Full Figma URL (e.g., `https://figma.com/design/ABC/MyApp?node-id=10-200`) |
|
|
430
|
+
| `fileKey` | string | No | Figma file key (alternative to figmaUrl) |
|
|
431
|
+
| `nodeId` | string | No | Figma node ID e.g., "10:200" (use with fileKey) |
|
|
432
|
+
| `scale` | number | No | Export scale (default: 2) |
|
|
433
|
+
| `threshold` | number | No | Color threshold 0-1 (default: 0.1) |
|
|
434
|
+
| `resizeStrategy` | "fit" \| "scale" \| "crop" | No | Dimension mismatch handling (default: "fit") |
|
|
435
|
+
| `cropRef` | string | No | Crop device screenshot to element bounds |
|
|
436
|
+
| `region` | {x, y, width, height} | No | Crop device screenshot to pixel region |
|
|
437
|
+
|
|
438
|
+
> Provide either `figmaUrl`, or both `fileKey` and `nodeId`.
|
|
439
|
+
|
|
440
|
+
**Example:**
|
|
441
|
+
```
|
|
442
|
+
devlens_compare_with_figma(
|
|
443
|
+
figmaUrl: "https://figma.com/design/ABC123/MyApp?node-id=10-200"
|
|
444
|
+
)
|
|
445
|
+
→ Similarity: 94.2%
|
|
446
|
+
→ Diff image highlighting mismatches
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## React Native / Metro (6)
|
|
452
|
+
|
|
453
|
+
### devlens_metro_status
|
|
454
|
+
**Health check tool.** Check if the Metro bundler is running and healthy. Call this at the start of every session and before any Metro-dependent operation.
|
|
455
|
+
|
|
456
|
+
**Parameters:** None
|
|
457
|
+
|
|
458
|
+
**Returns:** Metro health report including running status, port, packager status, and CDP connection state.
|
|
459
|
+
|
|
460
|
+
**Example responses:**
|
|
461
|
+
|
|
462
|
+
When Metro is running:
|
|
463
|
+
```
|
|
464
|
+
Metro Bundler Status:
|
|
465
|
+
Running: true
|
|
466
|
+
Port: 8081
|
|
467
|
+
Packager: packager-status:running
|
|
468
|
+
CDP Connected: false
|
|
469
|
+
|
|
470
|
+
Metro is healthy. You can use hot reload and other Metro tools.
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
When Metro is down:
|
|
474
|
+
```
|
|
475
|
+
Metro Bundler Status:
|
|
476
|
+
Running: false
|
|
477
|
+
Port: 8081
|
|
478
|
+
Packager: —
|
|
479
|
+
CDP Connected: false
|
|
480
|
+
Error: Cannot reach Metro on port 8081: fetch failed
|
|
481
|
+
|
|
482
|
+
Metro is NOT running. Start it with:
|
|
483
|
+
cd your-project && npx react-native start
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
### devlens_metro_logs
|
|
489
|
+
Get console output from the React Native app.
|
|
490
|
+
|
|
491
|
+
| Param | Type | Required | Description |
|
|
492
|
+
|-------|------|----------|-------------|
|
|
493
|
+
| `level` | "error" \| "warn" \| "info" \| "debug" | No | Minimum log level |
|
|
494
|
+
| `since` | string | No | ISO timestamp — only show logs after this time |
|
|
495
|
+
|
|
496
|
+
**Example response:**
|
|
497
|
+
```
|
|
498
|
+
Metro logs (5 entries):
|
|
499
|
+
|
|
500
|
+
[14:32:01.123] LOG User navigated to HomeScreen
|
|
501
|
+
[14:32:02.456] LOG API call: GET /api/products
|
|
502
|
+
[14:32:03.789] WARN Image component has no alt text
|
|
503
|
+
[14:32:04.012] ERROR Network request failed: timeout
|
|
504
|
+
[14:32:05.345] LOG Rendered 24 products
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
### devlens_component_tree
|
|
510
|
+
Get the React component hierarchy.
|
|
511
|
+
|
|
512
|
+
| Param | Type | Required | Description |
|
|
513
|
+
|-------|------|----------|-------------|
|
|
514
|
+
| `depth` | number | No | Max tree depth (default: 10) |
|
|
515
|
+
|
|
516
|
+
Shows component names, props, and nesting. Requires `__DEV__` mode.
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
### devlens_hot_reload
|
|
521
|
+
Trigger a hot reload / fast refresh.
|
|
522
|
+
|
|
523
|
+
**Parameters:** None
|
|
524
|
+
|
|
525
|
+
Call this after modifying React Native source files. Waits 1.5s for the reload to take effect.
|
|
526
|
+
|
|
527
|
+
---
|
|
528
|
+
|
|
529
|
+
### devlens_network_requests
|
|
530
|
+
List network requests made by the app.
|
|
531
|
+
|
|
532
|
+
| Param | Type | Required | Description |
|
|
533
|
+
|-------|------|----------|-------------|
|
|
534
|
+
| `urlPattern` | string | No | Filter by URL substring |
|
|
535
|
+
|
|
536
|
+
**Example response:**
|
|
537
|
+
```
|
|
538
|
+
Network requests (3 total):
|
|
539
|
+
|
|
540
|
+
GET 200 145ms 12.3KB https://api.example.com/products
|
|
541
|
+
POST 201 89ms 0.5KB https://api.example.com/cart
|
|
542
|
+
GET 404 23ms 0.1KB https://api.example.com/user/avatar
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
### devlens_dismiss_overlays
|
|
548
|
+
Dismiss React Native debug overlays (LogBox warnings, dev menu banners) that interfere with screenshots.
|
|
549
|
+
|
|
550
|
+
| Param | Type | Required | Description |
|
|
551
|
+
|-------|------|----------|-------------|
|
|
552
|
+
| `suppressLogBox` | boolean | No | Suppress LogBox via JavaScript injection (default: true) |
|
|
553
|
+
| `pressBack` | boolean | No | Press Back button to close modal overlays (default: false) |
|
|
554
|
+
|
|
555
|
+
**Example:**
|
|
556
|
+
```
|
|
557
|
+
devlens_dismiss_overlays()
|
|
558
|
+
→ LogBox suppressed; LogBox uninstalled
|
|
559
|
+
|
|
560
|
+
devlens_dismiss_overlays(pressBack: true)
|
|
561
|
+
→ LogBox suppressed; Back button pressed (dismiss modal overlay)
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
## Navigation (2)
|
|
567
|
+
|
|
568
|
+
### devlens_open_url
|
|
569
|
+
Open a URL or deep link.
|
|
570
|
+
|
|
571
|
+
| Param | Type | Required | Description |
|
|
572
|
+
|-------|------|----------|-------------|
|
|
573
|
+
| `url` | string | Yes | URL or deep link (e.g., "myapp://profile") |
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
### devlens_go_back
|
|
578
|
+
Navigate back.
|
|
579
|
+
|
|
580
|
+
**Parameters:** None
|
|
581
|
+
|
|
582
|
+
On Android: presses system Back button. On iOS: performs back swipe.
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
## Quick Reference Table
|
|
587
|
+
|
|
588
|
+
| # | Tool | Category | Key Params |
|
|
589
|
+
|---|------|----------|------------|
|
|
590
|
+
| 1 | `devlens_list_devices` | Device | — |
|
|
591
|
+
| 2 | `devlens_device_info` | Device | deviceId? |
|
|
592
|
+
| 3 | `devlens_set_orientation` | Device | orientation |
|
|
593
|
+
| 4 | `devlens_launch_app` | App | appId |
|
|
594
|
+
| 5 | `devlens_terminate_app` | App | appId |
|
|
595
|
+
| 6 | `devlens_install_app` | App | path |
|
|
596
|
+
| 7 | `devlens_list_apps` | App | — |
|
|
597
|
+
| 8 | `devlens_snapshot` | Snapshot | mode?, validate? |
|
|
598
|
+
| 9 | `devlens_find_element` | Snapshot | text?, label?, type? |
|
|
599
|
+
| 10 | `devlens_wait_for_element` | Snapshot | text?, label?, timeout? |
|
|
600
|
+
| 11 | `devlens_wait_for_screen` | Snapshot | text?, label?, stableMs?, timeoutMs? |
|
|
601
|
+
| 12 | `devlens_element_info` | Snapshot | ref |
|
|
602
|
+
| 13 | `devlens_tap` | Interaction | ref, element |
|
|
603
|
+
| 14 | `devlens_type` | Interaction | ref, text, submit? |
|
|
604
|
+
| 15 | `devlens_swipe` | Interaction | direction, ref?, distance? |
|
|
605
|
+
| 16 | `devlens_scroll` | Interaction | ref, direction |
|
|
606
|
+
| 17 | `devlens_long_press` | Interaction | ref, duration? |
|
|
607
|
+
| 18 | `devlens_press_button` | Interaction | button |
|
|
608
|
+
| 19 | `devlens_fill_form` | Interaction | fields |
|
|
609
|
+
| 20 | `devlens_capture_flow` | Interaction | steps |
|
|
610
|
+
| 21 | `devlens_screenshot` | Visual | filename? |
|
|
611
|
+
| 22 | `devlens_compare_screenshot` | Visual | referenceImagePath?, referenceImageBase64?, cropRef?, region? |
|
|
612
|
+
| 23 | `devlens_element_screenshot` | Visual | ref, filename? |
|
|
613
|
+
| 24 | `devlens_compare_images` | Visual | imageA, imageB, threshold?, resizeStrategy? |
|
|
614
|
+
| 25 | `devlens_compare_with_figma` | Visual | figmaUrl?, fileKey?, nodeId?, cropRef?, region? |
|
|
615
|
+
| 26 | `devlens_metro_status` | Metro | — |
|
|
616
|
+
| 27 | `devlens_metro_logs` | Metro | level?, since? |
|
|
617
|
+
| 28 | `devlens_component_tree` | Metro | depth? |
|
|
618
|
+
| 29 | `devlens_hot_reload` | Metro | — |
|
|
619
|
+
| 30 | `devlens_network_requests` | Metro | urlPattern? |
|
|
620
|
+
| 31 | `devlens_dismiss_overlays` | Metro | suppressLogBox?, pressBack? |
|
|
621
|
+
| 32 | `devlens_open_url` | Navigation | url |
|
|
622
|
+
| 33 | `devlens_go_back` | Navigation | — |
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devlens-mcp",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "DevLens — Playwright-style MCP server for mobile development. Take screenshots, compare with Figma designs, interact with iOS Simulators & Android Emulators, and access Metro bundler logs.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"devlens-mcp": "dist/bin/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"postbuild": "node dist/bin/register.js",
|
|
13
|
+
"dev": "tsc --watch",
|
|
14
|
+
"start": "node dist/bin/cli.js",
|
|
15
|
+
"register": "node dist/bin/register.js --register",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:watch": "vitest",
|
|
18
|
+
"lint": "eslint src/",
|
|
19
|
+
"prepublishOnly": "npm run build"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"mcp",
|
|
23
|
+
"mobile",
|
|
24
|
+
"react-native",
|
|
25
|
+
"playwright",
|
|
26
|
+
"automation",
|
|
27
|
+
"ios",
|
|
28
|
+
"android",
|
|
29
|
+
"emulator",
|
|
30
|
+
"simulator",
|
|
31
|
+
"figma",
|
|
32
|
+
"devtools",
|
|
33
|
+
"testing"
|
|
34
|
+
],
|
|
35
|
+
"author": "",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18.0.0"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
42
|
+
"fast-xml-parser": "^4.5.0",
|
|
43
|
+
"pixelmatch": "^5.3.0",
|
|
44
|
+
"pngjs": "^7.0.0",
|
|
45
|
+
"sharp": "^0.33.0",
|
|
46
|
+
"ws": "^8.18.0",
|
|
47
|
+
"zod": "^3.23.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^20.0.0",
|
|
51
|
+
"@types/pixelmatch": "^5.2.6",
|
|
52
|
+
"@types/pngjs": "^6.0.5",
|
|
53
|
+
"@types/ws": "^8.5.0",
|
|
54
|
+
"typescript": "^5.5.0",
|
|
55
|
+
"vitest": "^2.0.0"
|
|
56
|
+
}
|
|
57
|
+
}
|