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.
Files changed (175) hide show
  1. package/.claude/settings.json +12 -0
  2. package/.claude/settings.local.json +17 -0
  3. package/INSTALLATION_GUIDE.md +354 -0
  4. package/QUICK_START.md +153 -0
  5. package/README.md +354 -0
  6. package/bin/cli.ts +22 -0
  7. package/bin/register.ts +96 -0
  8. package/dist/bin/cli.d.ts +3 -0
  9. package/dist/bin/cli.d.ts.map +1 -0
  10. package/dist/bin/cli.js +20 -0
  11. package/dist/bin/cli.js.map +1 -0
  12. package/dist/bin/register.d.ts +10 -0
  13. package/dist/bin/register.d.ts.map +1 -0
  14. package/dist/bin/register.js +92 -0
  15. package/dist/bin/register.js.map +1 -0
  16. package/dist/src/config/devlens-config.d.ts +92 -0
  17. package/dist/src/config/devlens-config.d.ts.map +1 -0
  18. package/dist/src/config/devlens-config.js +70 -0
  19. package/dist/src/config/devlens-config.js.map +1 -0
  20. package/dist/src/index.d.ts +35 -0
  21. package/dist/src/index.d.ts.map +1 -0
  22. package/dist/src/index.js +8 -0
  23. package/dist/src/index.js.map +1 -0
  24. package/dist/src/metro/cdp-client.d.ts +48 -0
  25. package/dist/src/metro/cdp-client.d.ts.map +1 -0
  26. package/dist/src/metro/cdp-client.js +127 -0
  27. package/dist/src/metro/cdp-client.js.map +1 -0
  28. package/dist/src/metro/log-collector.d.ts +30 -0
  29. package/dist/src/metro/log-collector.d.ts.map +1 -0
  30. package/dist/src/metro/log-collector.js +114 -0
  31. package/dist/src/metro/log-collector.js.map +1 -0
  32. package/dist/src/metro/metro-bridge.d.ts +56 -0
  33. package/dist/src/metro/metro-bridge.d.ts.map +1 -0
  34. package/dist/src/metro/metro-bridge.js +255 -0
  35. package/dist/src/metro/metro-bridge.js.map +1 -0
  36. package/dist/src/metro/network-inspector.d.ts +34 -0
  37. package/dist/src/metro/network-inspector.d.ts.map +1 -0
  38. package/dist/src/metro/network-inspector.js +100 -0
  39. package/dist/src/metro/network-inspector.js.map +1 -0
  40. package/dist/src/platform/android/adb.d.ts +50 -0
  41. package/dist/src/platform/android/adb.d.ts.map +1 -0
  42. package/dist/src/platform/android/adb.js +137 -0
  43. package/dist/src/platform/android/adb.js.map +1 -0
  44. package/dist/src/platform/android/android-device.d.ts +21 -0
  45. package/dist/src/platform/android/android-device.d.ts.map +1 -0
  46. package/dist/src/platform/android/android-device.js +94 -0
  47. package/dist/src/platform/android/android-device.js.map +1 -0
  48. package/dist/src/platform/android/ui-automator.d.ts +17 -0
  49. package/dist/src/platform/android/ui-automator.d.ts.map +1 -0
  50. package/dist/src/platform/android/ui-automator.js +126 -0
  51. package/dist/src/platform/android/ui-automator.js.map +1 -0
  52. package/dist/src/platform/device-manager.d.ts +28 -0
  53. package/dist/src/platform/device-manager.d.ts.map +1 -0
  54. package/dist/src/platform/device-manager.js +185 -0
  55. package/dist/src/platform/device-manager.js.map +1 -0
  56. package/dist/src/platform/device.d.ts +86 -0
  57. package/dist/src/platform/device.d.ts.map +1 -0
  58. package/dist/src/platform/device.js +7 -0
  59. package/dist/src/platform/device.js.map +1 -0
  60. package/dist/src/platform/ios/accessibility.d.ts +17 -0
  61. package/dist/src/platform/ios/accessibility.d.ts.map +1 -0
  62. package/dist/src/platform/ios/accessibility.js +159 -0
  63. package/dist/src/platform/ios/accessibility.js.map +1 -0
  64. package/dist/src/platform/ios/ios-device.d.ts +22 -0
  65. package/dist/src/platform/ios/ios-device.d.ts.map +1 -0
  66. package/dist/src/platform/ios/ios-device.js +97 -0
  67. package/dist/src/platform/ios/ios-device.js.map +1 -0
  68. package/dist/src/platform/ios/simctl.d.ts +54 -0
  69. package/dist/src/platform/ios/simctl.d.ts.map +1 -0
  70. package/dist/src/platform/ios/simctl.js +192 -0
  71. package/dist/src/platform/ios/simctl.js.map +1 -0
  72. package/dist/src/server.d.ts +3 -0
  73. package/dist/src/server.d.ts.map +1 -0
  74. package/dist/src/server.js +176 -0
  75. package/dist/src/server.js.map +1 -0
  76. package/dist/src/snapshot/formatter.d.ts +18 -0
  77. package/dist/src/snapshot/formatter.d.ts.map +1 -0
  78. package/dist/src/snapshot/formatter.js +86 -0
  79. package/dist/src/snapshot/formatter.js.map +1 -0
  80. package/dist/src/snapshot/ref-registry.d.ts +67 -0
  81. package/dist/src/snapshot/ref-registry.d.ts.map +1 -0
  82. package/dist/src/snapshot/ref-registry.js +169 -0
  83. package/dist/src/snapshot/ref-registry.js.map +1 -0
  84. package/dist/src/snapshot/snapshot-differ.d.ts +57 -0
  85. package/dist/src/snapshot/snapshot-differ.d.ts.map +1 -0
  86. package/dist/src/snapshot/snapshot-differ.js +153 -0
  87. package/dist/src/snapshot/snapshot-differ.js.map +1 -0
  88. package/dist/src/tools/app-tools.d.ts +71 -0
  89. package/dist/src/tools/app-tools.d.ts.map +1 -0
  90. package/dist/src/tools/app-tools.js +97 -0
  91. package/dist/src/tools/app-tools.js.map +1 -0
  92. package/dist/src/tools/device-tools.d.ts +53 -0
  93. package/dist/src/tools/device-tools.d.ts.map +1 -0
  94. package/dist/src/tools/device-tools.js +86 -0
  95. package/dist/src/tools/device-tools.js.map +1 -0
  96. package/dist/src/tools/ds-tools.d.ts +65 -0
  97. package/dist/src/tools/ds-tools.d.ts.map +1 -0
  98. package/dist/src/tools/ds-tools.js +314 -0
  99. package/dist/src/tools/ds-tools.js.map +1 -0
  100. package/dist/src/tools/interaction-tools.d.ts +248 -0
  101. package/dist/src/tools/interaction-tools.d.ts.map +1 -0
  102. package/dist/src/tools/interaction-tools.js +391 -0
  103. package/dist/src/tools/interaction-tools.js.map +1 -0
  104. package/dist/src/tools/metro-tools.d.ts +115 -0
  105. package/dist/src/tools/metro-tools.d.ts.map +1 -0
  106. package/dist/src/tools/metro-tools.js +270 -0
  107. package/dist/src/tools/metro-tools.js.map +1 -0
  108. package/dist/src/tools/navigation-tools.d.ts +36 -0
  109. package/dist/src/tools/navigation-tools.d.ts.map +1 -0
  110. package/dist/src/tools/navigation-tools.js +60 -0
  111. package/dist/src/tools/navigation-tools.js.map +1 -0
  112. package/dist/src/tools/screenshot-tools.d.ts +298 -0
  113. package/dist/src/tools/screenshot-tools.d.ts.map +1 -0
  114. package/dist/src/tools/screenshot-tools.js +565 -0
  115. package/dist/src/tools/screenshot-tools.js.map +1 -0
  116. package/dist/src/tools/snapshot-tools.d.ts +161 -0
  117. package/dist/src/tools/snapshot-tools.d.ts.map +1 -0
  118. package/dist/src/tools/snapshot-tools.js +479 -0
  119. package/dist/src/tools/snapshot-tools.js.map +1 -0
  120. package/dist/src/utils/image-preprocess.d.ts +49 -0
  121. package/dist/src/utils/image-preprocess.d.ts.map +1 -0
  122. package/dist/src/utils/image-preprocess.js +322 -0
  123. package/dist/src/utils/image-preprocess.js.map +1 -0
  124. package/dist/src/utils/retry.d.ts +21 -0
  125. package/dist/src/utils/retry.d.ts.map +1 -0
  126. package/dist/src/utils/retry.js +33 -0
  127. package/dist/src/utils/retry.js.map +1 -0
  128. package/dist/src/visual/comparator.d.ts +51 -0
  129. package/dist/src/visual/comparator.d.ts.map +1 -0
  130. package/dist/src/visual/comparator.js +119 -0
  131. package/dist/src/visual/comparator.js.map +1 -0
  132. package/dist/src/visual/layout-analyzer.d.ts +64 -0
  133. package/dist/src/visual/layout-analyzer.d.ts.map +1 -0
  134. package/dist/src/visual/layout-analyzer.js +198 -0
  135. package/dist/src/visual/layout-analyzer.js.map +1 -0
  136. package/dist/src/visual/screenshot.d.ts +17 -0
  137. package/dist/src/visual/screenshot.d.ts.map +1 -0
  138. package/dist/src/visual/screenshot.js +39 -0
  139. package/dist/src/visual/screenshot.js.map +1 -0
  140. package/docs/figma-workflow.md +289 -0
  141. package/docs/setup-guide.md +360 -0
  142. package/docs/tool-reference.md +622 -0
  143. package/package.json +57 -0
  144. package/src/config/devlens-config.ts +76 -0
  145. package/src/index.ts +5 -0
  146. package/src/metro/cdp-client.ts +160 -0
  147. package/src/metro/log-collector.ts +137 -0
  148. package/src/metro/metro-bridge.ts +307 -0
  149. package/src/metro/network-inspector.ts +134 -0
  150. package/src/platform/android/adb.ts +200 -0
  151. package/src/platform/android/android-device.ts +116 -0
  152. package/src/platform/android/ui-automator.ts +141 -0
  153. package/src/platform/device-manager.ts +229 -0
  154. package/src/platform/device.ts +110 -0
  155. package/src/platform/ios/accessibility.ts +189 -0
  156. package/src/platform/ios/ios-device.ts +116 -0
  157. package/src/platform/ios/simctl.ts +244 -0
  158. package/src/server.ts +228 -0
  159. package/src/snapshot/formatter.ts +102 -0
  160. package/src/snapshot/ref-registry.ts +230 -0
  161. package/src/snapshot/snapshot-differ.ts +220 -0
  162. package/src/tools/app-tools.ts +111 -0
  163. package/src/tools/device-tools.ts +96 -0
  164. package/src/tools/ds-tools.ts +395 -0
  165. package/src/tools/interaction-tools.ts +467 -0
  166. package/src/tools/metro-tools.ts +320 -0
  167. package/src/tools/navigation-tools.ts +71 -0
  168. package/src/tools/screenshot-tools.ts +698 -0
  169. package/src/tools/snapshot-tools.ts +585 -0
  170. package/src/utils/image-preprocess.ts +430 -0
  171. package/src/utils/retry.ts +51 -0
  172. package/src/visual/comparator.ts +191 -0
  173. package/src/visual/layout-analyzer.ts +283 -0
  174. package/src/visual/screenshot.ts +49 -0
  175. package/tsconfig.json +20 -0
package/README.md ADDED
@@ -0,0 +1,354 @@
1
+ # DevLens
2
+
3
+ ### Playwright-style MCP server for React Native mobile development
4
+
5
+ DevLens gives AI agents the ability to **see, interact with, and verify** your mobile app running on a simulator or emulator. It bridges the gap between "AI writes code" and "AI confirms the code works" — enabling a fully automated **design-to-code-to-verification loop**.
6
+
7
+ ```
8
+ Figma Design ──► AI Agent ──► Code Changes ──► Hot Reload ──► Screenshot ──► Compare
9
+ ▲ │
10
+ └───────────────── Fix & repeat until > 95% match ──────────────────┘
11
+ ```
12
+
13
+ ---
14
+
15
+ ## Quick Start
16
+
17
+ ### Step 1 — Clone and build
18
+
19
+ ```bash
20
+ git clone https://JioOmni@dev.azure.com/JioOmni/OmniAI/_git/mcp-devlens
21
+ cd mcp-devlens
22
+ npm install
23
+ npm run build
24
+ ```
25
+
26
+ Note the **absolute path** to the cloned folder — you'll need it in the next step (e.g. `/Users/yourname/mcp-devlens`).
27
+
28
+ ### Step 2 — Add to your AI client
29
+
30
+ **Cursor IDE** — edit `~/.cursor/mcp.json`:
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "devlens": {
35
+ "command": "node",
36
+ "args": ["/absolute/path/to/mcp-devlens/dist/bin/cli.js"],
37
+ "env": {
38
+ "METRO_PORT": "8081",
39
+ "FIGMA_TOKEN": "figd_xxxxx"
40
+ }
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ **Claude Code**:
47
+ ```bash
48
+ claude mcp add devlens -- node /absolute/path/to/mcp-devlens/dist/bin/cli.js
49
+ ```
50
+
51
+ **Claude Desktop** — edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
52
+ ```json
53
+ {
54
+ "mcpServers": {
55
+ "devlens": {
56
+ "command": "node",
57
+ "args": ["/absolute/path/to/mcp-devlens/dist/bin/cli.js"],
58
+ "env": {
59
+ "METRO_PORT": "8081",
60
+ "FIGMA_TOKEN": "figd_xxxxx"
61
+ }
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ Restart your AI client after editing the config.
68
+
69
+ ---
70
+
71
+ ## What Problems Does It Solve?
72
+
73
+ Without DevLens, AI agents resort to manual, error-prone workflows:
74
+
75
+ | Without DevLens (Manual) | With DevLens |
76
+ |---|---|
77
+ | `adb exec-out screencap -p > /tmp/screenshot.png` | `devlens_screenshot` |
78
+ | `adb shell input tap 100 180` (coordinate guessing) | `devlens_tap(ref: "e5")` (element refs) |
79
+ | Visually comparing screenshot to Figma export | `devlens_compare_with_figma(figmaUrl: "...")` |
80
+ | `adb shell am force-stop` + `am start` | `devlens_terminate_app` + `devlens_launch_app` |
81
+ | `curl http://localhost:8081/status` | `devlens_metro_status` |
82
+ | Multiple manual reload attempts | `devlens_hot_reload` |
83
+ | Guessing if an element rendered | `devlens_find_element` + `devlens_snapshot(validate: true)` |
84
+ | `sleep 3 && adb screencap` loops | `devlens_wait_for_screen` |
85
+ | Grep-reading token files and component interfaces | `devlens_ds_context` |
86
+
87
+ ---
88
+
89
+ ## New in v0.3.1
90
+
91
+ - **Layout-Aware Comparison** — `devlens_compare_with_figma` now reports per-element similarity scores using the accessibility tree. Instead of a single misleading global pixel-diff number, you get `"Header: 94%, ChatInput: 61%, ToolsGrid: 44% ← investigate"`. Set `layoutReport: false` to disable.
92
+ - **Design System Context** — new `devlens_ds_context` tool reads your design token file, component interfaces, and scans actual usage patterns in `.tsx` files. AI agents use this to write correct DS-compliant code instead of guessing token names.
93
+ - **Moved/Resized Element Detection** — incremental snapshot diffs now distinguish elements that moved from elements that were removed and re-added:
94
+ ```
95
+ MOVED:
96
+ -> Button "Sign In" moved by (+0, +16)px
97
+ RESIZED:
98
+ <> LinearLayout 1080x200 → 1080x248
99
+ ```
100
+ - **Side-by-Side Comparison Output** — `devlens_compare_with_figma` now returns three images: device screenshot, Figma reference, and pixel diff — so the AI sees both sides simultaneously.
101
+
102
+ ---
103
+
104
+ ## New in v0.3.0
105
+
106
+ - **Direct Figma Comparison** — `devlens_compare_with_figma` fetches a Figma design via REST API and compares against the device in a single call. No more broken base64 piping.
107
+ - **Debug Overlay Dismissal** — `devlens_dismiss_overlays` suppresses React Native LogBox banners and debug menus that ruin screenshots
108
+ - **Batch Flow Capture** — `devlens_capture_flow` executes a sequence of actions (tap → screenshot → back) and returns all labeled screenshots in one call
109
+ - **Region Comparison** — `devlens_compare_screenshot` now accepts `cropRef` or `region` to compare a specific element or area instead of the full screen
110
+ - **Type Filter** — `devlens_find_element(type: "Button")` searches by element type (Button, ScrollView, EditText, etc.)
111
+ - **Auto-Reset Incremental Snapshots** — Navigation actions (tap, swipe, go_back) automatically reset incremental snapshot state
112
+ - **A/B Image Comparison** — `devlens_compare_images` compares any two saved screenshots (before/after)
113
+
114
+ ---
115
+
116
+ ## Tools (34)
117
+
118
+ ### Device Management (3)
119
+ | Tool | Description |
120
+ |------|-------------|
121
+ | `devlens_list_devices` | List running simulators/emulators |
122
+ | `devlens_device_info` | Screen size, OS version, orientation |
123
+ | `devlens_set_orientation` | Set portrait/landscape |
124
+
125
+ ### App Management (4)
126
+ | Tool | Description |
127
+ |------|-------------|
128
+ | `devlens_launch_app` | Launch app by bundle/package ID |
129
+ | `devlens_terminate_app` | Force stop an app |
130
+ | `devlens_install_app` | Install .apk/.app/.ipa |
131
+ | `devlens_list_apps` | List installed apps |
132
+
133
+ ### Snapshot & Elements (5)
134
+ | Tool | Description |
135
+ |------|-------------|
136
+ | `devlens_snapshot` | Accessibility tree with ref IDs + optional validation |
137
+ | `devlens_find_element` | Find elements by text, label, or type (warns about invisible matches) |
138
+ | `devlens_wait_for_element` | Wait for element to appear |
139
+ | `devlens_wait_for_screen` | Wait for screen stability or specific content |
140
+ | `devlens_element_info` | Detailed info + inferred layout direction |
141
+
142
+ ### Interaction (8)
143
+ | Tool | Description |
144
+ |------|-------------|
145
+ | `devlens_tap` | Tap element by ref |
146
+ | `devlens_type` | Type text into input |
147
+ | `devlens_swipe` | Swipe gesture |
148
+ | `devlens_scroll` | Scroll a container |
149
+ | `devlens_long_press` | Long press element |
150
+ | `devlens_press_button` | Home/Back/Enter |
151
+ | `devlens_fill_form` | Fill multiple fields at once |
152
+ | `devlens_capture_flow` | Batch execute actions + capture labeled screenshots |
153
+
154
+ ### Screenshots & Visual (5)
155
+ | Tool | Description |
156
+ |------|-------------|
157
+ | `devlens_screenshot` | Take screenshot (base64 + file) |
158
+ | `devlens_compare_screenshot` | Compare with reference (file, URL, base64) + cropRef/region support |
159
+ | `devlens_element_screenshot` | Screenshot a specific element |
160
+ | `devlens_compare_images` | A/B compare two saved screenshots |
161
+ | `devlens_compare_with_figma` | Compare device screen against Figma design with per-element layout report |
162
+
163
+ ### React Native / Metro (6)
164
+ | Tool | Description |
165
+ |------|-------------|
166
+ | `devlens_metro_status` | Check if Metro is running and healthy |
167
+ | `devlens_metro_logs` | Console.log/warn/error from Metro |
168
+ | `devlens_component_tree` | React component hierarchy |
169
+ | `devlens_hot_reload` | Trigger fast refresh |
170
+ | `devlens_network_requests` | Fetch/XHR requests from the app |
171
+ | `devlens_dismiss_overlays` | Dismiss React Native debug banners and LogBox |
172
+
173
+ ### Navigation (2)
174
+ | Tool | Description |
175
+ |------|-------------|
176
+ | `devlens_open_url` | Open URL / deep link |
177
+ | `devlens_go_back` | Navigate back |
178
+
179
+ ### Design System (1)
180
+ | Tool | Description |
181
+ |------|-------------|
182
+ | `devlens_ds_context` | Load design tokens, component interfaces, and usage patterns from your codebase |
183
+
184
+ ---
185
+
186
+ ## The Figma Verification Workflow
187
+
188
+ DevLens integrates with Figma to create an automated design verification loop:
189
+
190
+ ```
191
+ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
192
+ │ Figma │────►│ AI │────►│ Code │────►│ Device │
193
+ │ Design │ │ Agent │ │ Editor │ │ Screen │
194
+ └──────────┘ └──────┬───┘ └──────────┘ └────┬─────┘
195
+ │ │
196
+ │◄─── devlens_compare ───────────┘
197
+ │ (similarity < 95%?)
198
+ │ │
199
+ ▼ ▼
200
+ Fix Code ◄─── Layout Report
201
+ (per-element scores)
202
+ ```
203
+
204
+ ### Step-by-step:
205
+
206
+ 1. **Check Metro** — `devlens_metro_status` to verify Metro is healthy
207
+ 2. **Dismiss overlays** — `devlens_dismiss_overlays` to remove debug banners
208
+ 3. **Load DS context** — `devlens_ds_context` so the AI knows token names and component props
209
+ 4. **Generate code** — AI creates/updates the React Native component using correct DS tokens
210
+ 5. **Hot reload** — `devlens_hot_reload` triggers Metro fast refresh
211
+ 6. **Wait for stability** — `devlens_wait_for_screen` waits until UI stops changing
212
+ 7. **Validate elements** — `devlens_snapshot(validate: true)` catches invisible/zero-size elements
213
+ 8. **Compare with Figma** — `devlens_compare_with_figma(figmaUrl: "...")` returns device screenshot, Figma reference, diff image, and per-element layout scores
214
+ 9. **Analyze diff** — AI reads which elements are `poor`/`partial` and fixes those specifically
215
+ 10. **Fix & repeat** — Adjust code until overall similarity > 95%
216
+
217
+ ---
218
+
219
+ ## How It Works
220
+
221
+ ### Architecture
222
+
223
+ ```
224
+ AI Agent ──(MCP JSON-RPC over stdio)──► DevLens Server ──(ADB/simctl)──► Device
225
+
226
+ ├──(CDP WebSocket)──► Metro Bundler
227
+
228
+ └──(fs/regex)──► Design System Files
229
+
230
+ AI Agent ◄──(accessibility tree + refs)── DevLens Server ◄──(UI hierarchy)── Device
231
+ ```
232
+
233
+ ### Playwright-style Ref System
234
+
235
+ Every interactive element gets a unique ref (e1, e2, e3...). Instead of guessing pixel coordinates, AI agents use refs:
236
+
237
+ ```
238
+ - LinearLayout
239
+ - TextView "Welcome to MyApp" [ref=e1]
240
+ - EditText "Email" [ref=e2] [focused]
241
+ - EditText "Password" [ref=e3]
242
+ - Button "Sign In" [ref=e4]
243
+ ```
244
+
245
+ Then: `devlens_tap(ref="e4")` — no coordinate math, no misses.
246
+
247
+ ### Incremental Snapshots
248
+
249
+ In `incremental` mode, DevLens only sends what changed since the last snapshot — saving 60-80% tokens in iterative workflows. Elements that move are now tracked as moved, not as a remove+add pair:
250
+
251
+ ```
252
+ [Incremental update]
253
+ CHANGED:
254
+ ~ Button "Submit": text: "Submit" → "Save"
255
+ ADDED:
256
+ + TextView "Changes saved!"
257
+ MOVED:
258
+ -> Button "Sign In" moved by (+0, +16)px
259
+ RESIZED:
260
+ <> LinearLayout 1080x200 → 1080x248
261
+ ```
262
+
263
+ ### Layout-Aware Visual Comparison
264
+
265
+ `devlens_compare_with_figma` uses the accessibility tree to compare per UI region instead of the full screen:
266
+
267
+ - Scales each element's device-space bounds into Figma image space using `scaleX = figmaW / screenW`
268
+ - Crops both images to the scaled region and runs `pixelmatch` independently per element
269
+ - Returns a weighted similarity score per element plus an area-weighted overall score
270
+ - Elements with area < 3000px² are skipped (too small for reliable comparison)
271
+
272
+ Example output:
273
+ ```
274
+ --- Layout Region Analysis ---
275
+ Device: 1080x2400px | Figma: 430x932px | Scale: 2.51x
276
+ Regions: 8 analyzed, 12 too small
277
+
278
+ [✓] [e2] "Welcome Back": 94.1%
279
+ [~] [e7] "Sign In" (Button): 83.2%
280
+ [!] [e3] AssistantCards: 61.4% <- investigate (312 diff pixels)
281
+ [X] [e5] ToolsGrid: 44.2% <- investigate (1,089 diff pixels)
282
+
283
+ Overall (area-weighted): 68.7%
284
+ ```
285
+
286
+ ### Design System Context
287
+
288
+ `devlens_ds_context` reads directly from your codebase — no build step, no separate service:
289
+
290
+ - **Tokens** — regex-parsed from your token constants file (e.g. `FIGMA_COLORS`, `FIGMA_SPACING`)
291
+ - **Component interfaces** — reads generated TypeScript prop types from `componentsDir`
292
+ - **Usage patterns** — scans `.tsx` files for `<JDS*>`, `<Icon>`, `<Chip>` with their actual prop values
293
+
294
+ Configure via `devlens.config.json` in your app root (see [Setup Guide](./docs/setup-guide.md)).
295
+
296
+ ---
297
+
298
+ ## Prerequisites
299
+
300
+ - **Node.js** >= 18
301
+ - **Android**: Android SDK with `adb` in PATH (Android Studio)
302
+ - **iOS** (macOS only): Xcode with Command Line Tools
303
+ - **React Native**: Metro bundler running (`npx react-native start`)
304
+
305
+ ## Configuration
306
+
307
+ | Variable | Default | Description |
308
+ |----------|---------|-------------|
309
+ | `FIGMA_TOKEN` | — | Figma personal access token (required for `devlens_compare_with_figma`). Needs **File content: Read** scope. |
310
+ | `DEVLENS_CONFIG` | — | Absolute path to `devlens.config.json`. Enables `devlens_ds_context`. |
311
+ | `METRO_PORT` | `8081` | Metro bundler port |
312
+ | `ANDROID_HOME` | auto-detect | Android SDK path |
313
+ | `ANDROID_SDK_ROOT` | auto-detect | Alternative to `ANDROID_HOME` |
314
+ | `DEVICE_ID` | first available | Target a specific device |
315
+
316
+ ## Platform Support
317
+
318
+ | Feature | Android Emulator | iOS Simulator |
319
+ |---------|-----------------|---------------|
320
+ | Accessibility snapshots | UI Automator | simctl + a11y API |
321
+ | Screenshots | ADB screencap | simctl screenshot |
322
+ | Tap/Type/Swipe | ADB input | simctl io |
323
+ | App management | ADB + pm | simctl |
324
+ | Metro integration | CDP WebSocket | CDP WebSocket |
325
+
326
+ ## Troubleshooting
327
+
328
+ | Problem | Solution |
329
+ |---------|----------|
330
+ | "No running simulators or emulators" | Start a device from Android Studio or Xcode |
331
+ | "Could not connect to Metro bundler" | Run `npx react-native start` and check `METRO_PORT` |
332
+ | "ADB command not found" | Set `ANDROID_HOME` or add `platform-tools` to PATH |
333
+ | "simctl not found" | Install Xcode Command Line Tools: `xcode-select --install` |
334
+ | DevLens tools not available | Run `npm run register` (local dev) or check MCP config |
335
+ | "Invalid token" on Figma compare | Use a personal access token (`figd_...`), not an OAuth token. Required scope: **File content: Read**. |
336
+ | "File not exportable" on Figma compare | Disable "Prevent viewers from copying and exporting" in Figma share settings |
337
+ | `devlens_ds_context` returns empty | Set `DEVLENS_CONFIG` env var to your `devlens.config.json` path |
338
+ | Comparison similarity always low | Run `devlens_snapshot` first so layout report has element bounds to work with |
339
+
340
+ ---
341
+
342
+ ## Documentation
343
+
344
+ - **[docs/setup-guide.md](./docs/setup-guide.md)** - Full setup guide: prerequisites, Figma token, design system config
345
+ - **[docs/figma-workflow.md](./docs/figma-workflow.md)** - Figma integration workflow
346
+ - **[docs/tool-reference.md](./docs/tool-reference.md)** - Detailed tool API reference
347
+
348
+ ## Repository
349
+
350
+ - **Azure DevOps**: https://dev.azure.com/JioOmni/OmniAI/_git/mcp-devlens
351
+
352
+ ## License
353
+
354
+ MIT
package/bin/cli.ts ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createServer } from "../src/index.js";
4
+
5
+ async function main() {
6
+ const server = await createServer();
7
+
8
+ process.on("SIGINT", async () => {
9
+ await server.close();
10
+ process.exit(0);
11
+ });
12
+
13
+ process.on("SIGTERM", async () => {
14
+ await server.close();
15
+ process.exit(0);
16
+ });
17
+ }
18
+
19
+ main().catch((error) => {
20
+ console.error("DevLens failed to start:", error);
21
+ process.exit(1);
22
+ });
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * DevLens MCP Registration Script
5
+ *
6
+ * Usage:
7
+ * node dist/bin/register.js — Check status + print instructions
8
+ * node dist/bin/register.js --register — Actually register with Claude Code
9
+ */
10
+
11
+ import { execFile } from "child_process";
12
+ import { promisify } from "util";
13
+ import { resolve } from "path";
14
+ import { existsSync, readFileSync } from "fs";
15
+
16
+ const execFileAsync = promisify(execFile);
17
+
18
+ async function register(): Promise<void> {
19
+ const cliPath = resolve(__dirname, "cli.js");
20
+
21
+ if (!existsSync(cliPath)) {
22
+ console.error("Error: dist/bin/cli.js not found. Run 'npm run build' first.");
23
+ process.exit(1);
24
+ }
25
+
26
+ const autoRegister = process.argv.includes("--register");
27
+
28
+ // Check common config locations for existing registration
29
+ const home = process.env.HOME || process.env.USERPROFILE || "~";
30
+ const configPaths = [
31
+ resolve(home, ".claude", "mcp.json"),
32
+ resolve(home, ".claude", "settings.json"),
33
+ resolve(home, ".config", "claude", "mcp.json"),
34
+ ];
35
+
36
+ let alreadyRegistered = false;
37
+ for (const configPath of configPaths) {
38
+ if (existsSync(configPath)) {
39
+ try {
40
+ const content = readFileSync(configPath, "utf-8");
41
+ if (content.includes("devlens")) {
42
+ alreadyRegistered = true;
43
+ console.log(`DevLens already registered in: ${configPath}`);
44
+ break;
45
+ }
46
+ } catch {
47
+ // Ignore read errors
48
+ }
49
+ }
50
+ }
51
+
52
+ if (alreadyRegistered) {
53
+ console.log("DevLens MCP server is already registered. No action needed.");
54
+ return;
55
+ }
56
+
57
+ const command = `claude mcp add devlens -- node ${cliPath}`;
58
+
59
+ if (autoRegister) {
60
+ console.log("Registering DevLens MCP server...");
61
+ console.log(`Running: ${command}`);
62
+ try {
63
+ const { stdout, stderr } = await execFileAsync("claude", [
64
+ "mcp",
65
+ "add",
66
+ "devlens",
67
+ "--",
68
+ "node",
69
+ cliPath,
70
+ ]);
71
+ if (stdout) console.log(stdout);
72
+ if (stderr) console.error(stderr);
73
+ console.log("DevLens registered successfully!");
74
+ } catch (error: any) {
75
+ console.error(`Registration failed: ${error.message}`);
76
+ console.log(`\nPlease register manually:\n ${command}`);
77
+ process.exit(1);
78
+ }
79
+ } else {
80
+ console.log("");
81
+ console.log("=== DevLens MCP Registration ===");
82
+ console.log("");
83
+ console.log("DevLens is not registered as an MCP tool.");
84
+ console.log("To register, run one of these commands:");
85
+ console.log("");
86
+ console.log(` npm run register`);
87
+ console.log(` # or manually:`);
88
+ console.log(` ${command}`);
89
+ console.log("");
90
+ }
91
+ }
92
+
93
+ register().catch((err) => {
94
+ console.error("Registration error:", err);
95
+ process.exit(1);
96
+ });
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const index_js_1 = require("../src/index.js");
5
+ async function main() {
6
+ const server = await (0, index_js_1.createServer)();
7
+ process.on("SIGINT", async () => {
8
+ await server.close();
9
+ process.exit(0);
10
+ });
11
+ process.on("SIGTERM", async () => {
12
+ await server.close();
13
+ process.exit(0);
14
+ });
15
+ }
16
+ main().catch((error) => {
17
+ console.error("DevLens failed to start:", error);
18
+ process.exit(1);
19
+ });
20
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":";;;AAEA,8CAA+C;AAE/C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAY,GAAE,CAAC;IAEpC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;IACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * DevLens MCP Registration Script
4
+ *
5
+ * Usage:
6
+ * node dist/bin/register.js — Check status + print instructions
7
+ * node dist/bin/register.js --register — Actually register with Claude Code
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../bin/register.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG"}
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * DevLens MCP Registration Script
5
+ *
6
+ * Usage:
7
+ * node dist/bin/register.js — Check status + print instructions
8
+ * node dist/bin/register.js --register — Actually register with Claude Code
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ const child_process_1 = require("child_process");
12
+ const util_1 = require("util");
13
+ const path_1 = require("path");
14
+ const fs_1 = require("fs");
15
+ const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
16
+ async function register() {
17
+ const cliPath = (0, path_1.resolve)(__dirname, "cli.js");
18
+ if (!(0, fs_1.existsSync)(cliPath)) {
19
+ console.error("Error: dist/bin/cli.js not found. Run 'npm run build' first.");
20
+ process.exit(1);
21
+ }
22
+ const autoRegister = process.argv.includes("--register");
23
+ // Check common config locations for existing registration
24
+ const home = process.env.HOME || process.env.USERPROFILE || "~";
25
+ const configPaths = [
26
+ (0, path_1.resolve)(home, ".claude", "mcp.json"),
27
+ (0, path_1.resolve)(home, ".claude", "settings.json"),
28
+ (0, path_1.resolve)(home, ".config", "claude", "mcp.json"),
29
+ ];
30
+ let alreadyRegistered = false;
31
+ for (const configPath of configPaths) {
32
+ if ((0, fs_1.existsSync)(configPath)) {
33
+ try {
34
+ const content = (0, fs_1.readFileSync)(configPath, "utf-8");
35
+ if (content.includes("devlens")) {
36
+ alreadyRegistered = true;
37
+ console.log(`DevLens already registered in: ${configPath}`);
38
+ break;
39
+ }
40
+ }
41
+ catch {
42
+ // Ignore read errors
43
+ }
44
+ }
45
+ }
46
+ if (alreadyRegistered) {
47
+ console.log("DevLens MCP server is already registered. No action needed.");
48
+ return;
49
+ }
50
+ const command = `claude mcp add devlens -- node ${cliPath}`;
51
+ if (autoRegister) {
52
+ console.log("Registering DevLens MCP server...");
53
+ console.log(`Running: ${command}`);
54
+ try {
55
+ const { stdout, stderr } = await execFileAsync("claude", [
56
+ "mcp",
57
+ "add",
58
+ "devlens",
59
+ "--",
60
+ "node",
61
+ cliPath,
62
+ ]);
63
+ if (stdout)
64
+ console.log(stdout);
65
+ if (stderr)
66
+ console.error(stderr);
67
+ console.log("DevLens registered successfully!");
68
+ }
69
+ catch (error) {
70
+ console.error(`Registration failed: ${error.message}`);
71
+ console.log(`\nPlease register manually:\n ${command}`);
72
+ process.exit(1);
73
+ }
74
+ }
75
+ else {
76
+ console.log("");
77
+ console.log("=== DevLens MCP Registration ===");
78
+ console.log("");
79
+ console.log("DevLens is not registered as an MCP tool.");
80
+ console.log("To register, run one of these commands:");
81
+ console.log("");
82
+ console.log(` npm run register`);
83
+ console.log(` # or manually:`);
84
+ console.log(` ${command}`);
85
+ console.log("");
86
+ }
87
+ }
88
+ register().catch((err) => {
89
+ console.error("Registration error:", err);
90
+ process.exit(1);
91
+ });
92
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../bin/register.ts"],"names":[],"mappings":"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"}