devlens-mcp 0.3.0 → 0.3.1

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 (162) hide show
  1. package/README.md +10 -21
  2. package/docs/setup-guide.md +11 -31
  3. package/package.json +1 -1
  4. package/.claude/settings.json +0 -12
  5. package/.claude/settings.local.json +0 -17
  6. package/bin/cli.ts +0 -22
  7. package/bin/register.ts +0 -96
  8. package/dist/src/config/devlens-config.d.ts +0 -92
  9. package/dist/src/config/devlens-config.d.ts.map +0 -1
  10. package/dist/src/config/devlens-config.js +0 -70
  11. package/dist/src/config/devlens-config.js.map +0 -1
  12. package/dist/src/index.d.ts +0 -35
  13. package/dist/src/index.d.ts.map +0 -1
  14. package/dist/src/index.js +0 -8
  15. package/dist/src/index.js.map +0 -1
  16. package/dist/src/metro/cdp-client.d.ts +0 -48
  17. package/dist/src/metro/cdp-client.d.ts.map +0 -1
  18. package/dist/src/metro/cdp-client.js +0 -127
  19. package/dist/src/metro/cdp-client.js.map +0 -1
  20. package/dist/src/metro/log-collector.d.ts +0 -30
  21. package/dist/src/metro/log-collector.d.ts.map +0 -1
  22. package/dist/src/metro/log-collector.js +0 -114
  23. package/dist/src/metro/log-collector.js.map +0 -1
  24. package/dist/src/metro/metro-bridge.d.ts +0 -56
  25. package/dist/src/metro/metro-bridge.d.ts.map +0 -1
  26. package/dist/src/metro/metro-bridge.js +0 -255
  27. package/dist/src/metro/metro-bridge.js.map +0 -1
  28. package/dist/src/metro/network-inspector.d.ts +0 -34
  29. package/dist/src/metro/network-inspector.d.ts.map +0 -1
  30. package/dist/src/metro/network-inspector.js +0 -100
  31. package/dist/src/metro/network-inspector.js.map +0 -1
  32. package/dist/src/platform/android/adb.d.ts +0 -50
  33. package/dist/src/platform/android/adb.d.ts.map +0 -1
  34. package/dist/src/platform/android/adb.js +0 -137
  35. package/dist/src/platform/android/adb.js.map +0 -1
  36. package/dist/src/platform/android/android-device.d.ts +0 -21
  37. package/dist/src/platform/android/android-device.d.ts.map +0 -1
  38. package/dist/src/platform/android/android-device.js +0 -94
  39. package/dist/src/platform/android/android-device.js.map +0 -1
  40. package/dist/src/platform/android/ui-automator.d.ts +0 -17
  41. package/dist/src/platform/android/ui-automator.d.ts.map +0 -1
  42. package/dist/src/platform/android/ui-automator.js +0 -126
  43. package/dist/src/platform/android/ui-automator.js.map +0 -1
  44. package/dist/src/platform/device-manager.d.ts +0 -28
  45. package/dist/src/platform/device-manager.d.ts.map +0 -1
  46. package/dist/src/platform/device-manager.js +0 -185
  47. package/dist/src/platform/device-manager.js.map +0 -1
  48. package/dist/src/platform/device.d.ts +0 -86
  49. package/dist/src/platform/device.d.ts.map +0 -1
  50. package/dist/src/platform/device.js +0 -7
  51. package/dist/src/platform/device.js.map +0 -1
  52. package/dist/src/platform/ios/accessibility.d.ts +0 -17
  53. package/dist/src/platform/ios/accessibility.d.ts.map +0 -1
  54. package/dist/src/platform/ios/accessibility.js +0 -159
  55. package/dist/src/platform/ios/accessibility.js.map +0 -1
  56. package/dist/src/platform/ios/ios-device.d.ts +0 -22
  57. package/dist/src/platform/ios/ios-device.d.ts.map +0 -1
  58. package/dist/src/platform/ios/ios-device.js +0 -97
  59. package/dist/src/platform/ios/ios-device.js.map +0 -1
  60. package/dist/src/platform/ios/simctl.d.ts +0 -54
  61. package/dist/src/platform/ios/simctl.d.ts.map +0 -1
  62. package/dist/src/platform/ios/simctl.js +0 -192
  63. package/dist/src/platform/ios/simctl.js.map +0 -1
  64. package/dist/src/server.d.ts +0 -3
  65. package/dist/src/server.d.ts.map +0 -1
  66. package/dist/src/server.js +0 -176
  67. package/dist/src/server.js.map +0 -1
  68. package/dist/src/snapshot/formatter.d.ts +0 -18
  69. package/dist/src/snapshot/formatter.d.ts.map +0 -1
  70. package/dist/src/snapshot/formatter.js +0 -86
  71. package/dist/src/snapshot/formatter.js.map +0 -1
  72. package/dist/src/snapshot/ref-registry.d.ts +0 -67
  73. package/dist/src/snapshot/ref-registry.d.ts.map +0 -1
  74. package/dist/src/snapshot/ref-registry.js +0 -169
  75. package/dist/src/snapshot/ref-registry.js.map +0 -1
  76. package/dist/src/snapshot/snapshot-differ.d.ts +0 -57
  77. package/dist/src/snapshot/snapshot-differ.d.ts.map +0 -1
  78. package/dist/src/snapshot/snapshot-differ.js +0 -153
  79. package/dist/src/snapshot/snapshot-differ.js.map +0 -1
  80. package/dist/src/tools/app-tools.d.ts +0 -71
  81. package/dist/src/tools/app-tools.d.ts.map +0 -1
  82. package/dist/src/tools/app-tools.js +0 -97
  83. package/dist/src/tools/app-tools.js.map +0 -1
  84. package/dist/src/tools/device-tools.d.ts +0 -53
  85. package/dist/src/tools/device-tools.d.ts.map +0 -1
  86. package/dist/src/tools/device-tools.js +0 -86
  87. package/dist/src/tools/device-tools.js.map +0 -1
  88. package/dist/src/tools/ds-tools.d.ts +0 -65
  89. package/dist/src/tools/ds-tools.d.ts.map +0 -1
  90. package/dist/src/tools/ds-tools.js +0 -314
  91. package/dist/src/tools/ds-tools.js.map +0 -1
  92. package/dist/src/tools/interaction-tools.d.ts +0 -248
  93. package/dist/src/tools/interaction-tools.d.ts.map +0 -1
  94. package/dist/src/tools/interaction-tools.js +0 -391
  95. package/dist/src/tools/interaction-tools.js.map +0 -1
  96. package/dist/src/tools/metro-tools.d.ts +0 -115
  97. package/dist/src/tools/metro-tools.d.ts.map +0 -1
  98. package/dist/src/tools/metro-tools.js +0 -270
  99. package/dist/src/tools/metro-tools.js.map +0 -1
  100. package/dist/src/tools/navigation-tools.d.ts +0 -36
  101. package/dist/src/tools/navigation-tools.d.ts.map +0 -1
  102. package/dist/src/tools/navigation-tools.js +0 -60
  103. package/dist/src/tools/navigation-tools.js.map +0 -1
  104. package/dist/src/tools/screenshot-tools.d.ts +0 -298
  105. package/dist/src/tools/screenshot-tools.d.ts.map +0 -1
  106. package/dist/src/tools/screenshot-tools.js +0 -565
  107. package/dist/src/tools/screenshot-tools.js.map +0 -1
  108. package/dist/src/tools/snapshot-tools.d.ts +0 -161
  109. package/dist/src/tools/snapshot-tools.d.ts.map +0 -1
  110. package/dist/src/tools/snapshot-tools.js +0 -479
  111. package/dist/src/tools/snapshot-tools.js.map +0 -1
  112. package/dist/src/utils/image-preprocess.d.ts +0 -49
  113. package/dist/src/utils/image-preprocess.d.ts.map +0 -1
  114. package/dist/src/utils/image-preprocess.js +0 -322
  115. package/dist/src/utils/image-preprocess.js.map +0 -1
  116. package/dist/src/utils/retry.d.ts +0 -21
  117. package/dist/src/utils/retry.d.ts.map +0 -1
  118. package/dist/src/utils/retry.js +0 -33
  119. package/dist/src/utils/retry.js.map +0 -1
  120. package/dist/src/visual/comparator.d.ts +0 -51
  121. package/dist/src/visual/comparator.d.ts.map +0 -1
  122. package/dist/src/visual/comparator.js +0 -119
  123. package/dist/src/visual/comparator.js.map +0 -1
  124. package/dist/src/visual/layout-analyzer.d.ts +0 -64
  125. package/dist/src/visual/layout-analyzer.d.ts.map +0 -1
  126. package/dist/src/visual/layout-analyzer.js +0 -198
  127. package/dist/src/visual/layout-analyzer.js.map +0 -1
  128. package/dist/src/visual/screenshot.d.ts +0 -17
  129. package/dist/src/visual/screenshot.d.ts.map +0 -1
  130. package/dist/src/visual/screenshot.js +0 -39
  131. package/dist/src/visual/screenshot.js.map +0 -1
  132. package/src/config/devlens-config.ts +0 -76
  133. package/src/index.ts +0 -5
  134. package/src/metro/cdp-client.ts +0 -160
  135. package/src/metro/log-collector.ts +0 -137
  136. package/src/metro/metro-bridge.ts +0 -307
  137. package/src/metro/network-inspector.ts +0 -134
  138. package/src/platform/android/adb.ts +0 -200
  139. package/src/platform/android/android-device.ts +0 -116
  140. package/src/platform/android/ui-automator.ts +0 -141
  141. package/src/platform/device-manager.ts +0 -229
  142. package/src/platform/device.ts +0 -110
  143. package/src/platform/ios/accessibility.ts +0 -189
  144. package/src/platform/ios/ios-device.ts +0 -116
  145. package/src/platform/ios/simctl.ts +0 -244
  146. package/src/server.ts +0 -228
  147. package/src/snapshot/formatter.ts +0 -102
  148. package/src/snapshot/ref-registry.ts +0 -230
  149. package/src/snapshot/snapshot-differ.ts +0 -220
  150. package/src/tools/app-tools.ts +0 -111
  151. package/src/tools/device-tools.ts +0 -96
  152. package/src/tools/ds-tools.ts +0 -395
  153. package/src/tools/interaction-tools.ts +0 -467
  154. package/src/tools/metro-tools.ts +0 -320
  155. package/src/tools/navigation-tools.ts +0 -71
  156. package/src/tools/screenshot-tools.ts +0 -698
  157. package/src/tools/snapshot-tools.ts +0 -585
  158. package/src/utils/image-preprocess.ts +0 -430
  159. package/src/utils/retry.ts +0 -51
  160. package/src/visual/comparator.ts +0 -191
  161. package/src/visual/layout-analyzer.ts +0 -283
  162. package/src/visual/screenshot.ts +0 -49
@@ -1,320 +0,0 @@
1
- import { z } from "zod";
2
- import { MetroBridge } from "../metro/metro-bridge.js";
3
- import type { DeviceManager } from "../platform/device-manager.js";
4
- import { retry } from "../utils/retry.js";
5
-
6
- export const metroToolSchemas = {
7
- devlens_metro_status: {
8
- description:
9
- "Check if the Metro bundler is running and healthy. Reports connection state, port, and packager status. Use this proactively before Metro-dependent operations, or when the app seems stuck or unresponsive.",
10
- parameters: z.object({}),
11
- },
12
- devlens_metro_logs: {
13
- description:
14
- "Get console log output from the React Native app via Metro bundler. Shows console.log, console.warn, console.error messages from your app code. Requires Metro bundler to be running.",
15
- parameters: z.object({
16
- level: z
17
- .enum(["error", "warn", "info", "debug"])
18
- .optional()
19
- .describe(
20
- "Minimum log level to include. 'error' shows only errors, 'warn' includes warnings, 'info' includes info+log, 'debug' includes everything."
21
- ),
22
- since: z
23
- .string()
24
- .optional()
25
- .describe(
26
- "Only show logs after this ISO timestamp (e.g., from a previous call). Omit to get all buffered logs."
27
- ),
28
- }),
29
- },
30
- devlens_component_tree: {
31
- description:
32
- "Get the React component hierarchy of the running app. Shows component names (like <HomeScreen>, <ProductCard>), their props, and nesting structure. Requires React DevTools hook to be available (__DEV__ mode).",
33
- parameters: z.object({
34
- depth: z
35
- .number()
36
- .default(10)
37
- .describe("Maximum depth of the component tree to return (default: 10)"),
38
- }),
39
- },
40
- devlens_hot_reload: {
41
- description:
42
- "Trigger a hot reload / fast refresh of the React Native app. Call this after modifying source code to see changes on the device without a full rebuild.",
43
- parameters: z.object({}),
44
- },
45
- devlens_network_requests: {
46
- description:
47
- "List network requests (fetch/XHR) made by the React Native app. Shows URLs, methods, status codes, and timing. Useful for debugging API calls.",
48
- parameters: z.object({
49
- urlPattern: z
50
- .string()
51
- .optional()
52
- .describe(
53
- "Filter requests by URL substring (e.g., '/api/' or 'graphql')"
54
- ),
55
- }),
56
- },
57
- devlens_dismiss_overlays: {
58
- description:
59
- "Dismiss React Native debug overlays (LogBox warnings, dev menu banners) that interfere with screenshots and visual comparisons. Suppresses LogBox via CDP and optionally presses Back to close modal overlays.",
60
- parameters: z.object({
61
- suppressLogBox: z
62
- .boolean()
63
- .default(true)
64
- .describe(
65
- "Suppress LogBox warnings/errors via JavaScript injection (default: true)"
66
- ),
67
- pressBack: z
68
- .boolean()
69
- .default(false)
70
- .describe(
71
- "Press the device Back button to dismiss modal overlays like the dev menu (default: false)"
72
- ),
73
- }),
74
- },
75
- };
76
-
77
- export function createMetroToolHandlers(
78
- metroPort: number,
79
- deviceManager: DeviceManager
80
- ) {
81
- let bridge: MetroBridge | null = null;
82
-
83
- async function ensureConnected(): Promise<MetroBridge> {
84
- if (bridge && bridge.connected) return bridge;
85
-
86
- bridge = new MetroBridge(metroPort);
87
-
88
- // Check if Metro is even running before attempting CDP connection
89
- const status = await bridge.getStatus();
90
- if (!status.running) {
91
- throw new Error(
92
- `Metro bundler is not running on port ${metroPort}. ` +
93
- `${status.error || ""}\n` +
94
- `Start it with: npx react-native start\n` +
95
- `Check status with: devlens_metro_status`
96
- );
97
- }
98
-
99
- try {
100
- await retry(() => bridge!.connect(), {
101
- maxAttempts: 2,
102
- delayMs: 1000,
103
- backoff: true,
104
- });
105
- } catch (error: any) {
106
- throw new Error(
107
- `Metro is running but CDP connection failed on port ${metroPort}. ` +
108
- `This can happen if another debugger is already connected. Error: ${error.message}`
109
- );
110
- }
111
- return bridge;
112
- }
113
-
114
- return {
115
- devlens_metro_status: async () => {
116
- const probe = new MetroBridge(metroPort);
117
- const status = await probe.getStatus();
118
-
119
- const lines: string[] = [
120
- `Metro Port: ${status.port}`,
121
- `Packager Running: ${status.running ? "YES" : "NO"}`,
122
- `Packager Status: ${status.packagerStatus || "(no response)"}`,
123
- `CDP Connected: ${bridge?.connected ? "YES" : "NO"}`,
124
- ];
125
-
126
- if (status.error) {
127
- lines.push("", `Error: ${status.error}`);
128
- lines.push("", "Suggestion: Run 'npx react-native start' to start Metro.");
129
- } else if (status.running) {
130
- lines.push("", "Metro is healthy and ready.");
131
- }
132
-
133
- return {
134
- content: [
135
- {
136
- type: "text" as const,
137
- text: lines.join("\n"),
138
- },
139
- ],
140
- ...(status.running ? {} : { isError: true }),
141
- };
142
- },
143
-
144
- devlens_metro_logs: async (params: {
145
- level?: "error" | "warn" | "info" | "debug";
146
- since?: string;
147
- }) => {
148
- const b = await ensureConnected();
149
-
150
- const logs = b.logCollector.getLogs({
151
- level: params.level,
152
- since: params.since ? new Date(params.since).getTime() : undefined,
153
- limit: 100,
154
- });
155
-
156
- if (logs.length === 0) {
157
- return {
158
- content: [
159
- {
160
- type: "text" as const,
161
- text: "No console logs captured. Logs appear as the app runs and calls console.log/warn/error.",
162
- },
163
- ],
164
- };
165
- }
166
-
167
- const lines = logs.map((log) => {
168
- const time = new Date(log.timestamp).toISOString().slice(11, 23);
169
- const prefix =
170
- log.level === "error"
171
- ? "ERROR"
172
- : log.level === "warn"
173
- ? "WARN "
174
- : log.level === "debug"
175
- ? "DEBUG"
176
- : "LOG ";
177
- return `[${time}] ${prefix} ${log.message}`;
178
- });
179
-
180
- return {
181
- content: [
182
- {
183
- type: "text" as const,
184
- text: `Metro logs (${logs.length} entries):\n\n${lines.join("\n")}`,
185
- },
186
- ],
187
- };
188
- },
189
-
190
- devlens_component_tree: async (params: { depth: number }) => {
191
- const b = await ensureConnected();
192
-
193
- try {
194
- const tree = await b.getComponentTree(params.depth);
195
- return {
196
- content: [
197
- {
198
- type: "text" as const,
199
- text: `React Component Tree:\n\n${tree}`,
200
- },
201
- ],
202
- };
203
- } catch (error: any) {
204
- return {
205
- content: [
206
- {
207
- type: "text" as const,
208
- text: `Could not retrieve component tree: ${error.message}\n\nEnsure the app is running in __DEV__ mode and React DevTools hook is available.`,
209
- },
210
- ],
211
- isError: true,
212
- };
213
- }
214
- },
215
-
216
- devlens_hot_reload: async () => {
217
- const b = await ensureConnected();
218
- await b.hotReload();
219
-
220
- // Wait a moment for the reload to take effect
221
- await new Promise((resolve) => setTimeout(resolve, 1500));
222
-
223
- return {
224
- content: [
225
- {
226
- type: "text" as const,
227
- text: "Hot reload triggered. The app should reflect your latest code changes.",
228
- },
229
- ],
230
- };
231
- },
232
-
233
- devlens_network_requests: async (params: { urlPattern?: string }) => {
234
- const b = await ensureConnected();
235
- const requests = b.networkInspector.getRequests(params.urlPattern);
236
-
237
- if (requests.length === 0) {
238
- return {
239
- content: [
240
- {
241
- type: "text" as const,
242
- text: params.urlPattern
243
- ? `No network requests matching "${params.urlPattern}" found.`
244
- : "No network requests captured yet. Requests appear as the app makes fetch/XHR calls.",
245
- },
246
- ],
247
- };
248
- }
249
-
250
- const lines = requests.slice(0, 50).map((req) => {
251
- const status = req.error
252
- ? `FAIL (${req.error})`
253
- : req.status
254
- ? `${req.status}`
255
- : "pending";
256
- const duration = req.duration ? `${req.duration}ms` : "...";
257
- const size = req.size ? `${(req.size / 1024).toFixed(1)}KB` : "";
258
- return `${req.method} ${status} ${duration} ${size} ${req.url}`;
259
- });
260
-
261
- return {
262
- content: [
263
- {
264
- type: "text" as const,
265
- text: `Network requests (${requests.length} total, showing up to 50):\n\n${lines.join("\n")}`,
266
- },
267
- ],
268
- };
269
- },
270
-
271
- devlens_dismiss_overlays: async (params: {
272
- suppressLogBox: boolean;
273
- pressBack: boolean;
274
- }) => {
275
- const results: string[] = [];
276
-
277
- if (params.suppressLogBox) {
278
- try {
279
- const b = await ensureConnected();
280
- const jsCode = `(function() {
281
- var r = [];
282
- try { require('react-native').LogBox.ignoreAllLogs(true); r.push('LogBox suppressed'); } catch(e) {}
283
- try { require('react-native/Libraries/LogBox/LogBox').uninstall(); r.push('LogBox uninstalled'); } catch(e) {}
284
- try {
285
- var DevSettings = require('react-native').DevSettings || require('react-native/Libraries/Utilities/DevSettings');
286
- if (DevSettings && DevSettings.setHotLoadingEnabled) { DevSettings.setHotLoadingEnabled(false); }
287
- r.push('DevSettings accessed');
288
- } catch(e) {}
289
- return r.join('; ') || 'No LogBox APIs found';
290
- })()`;
291
- const evalResult = await b.evaluate(jsCode);
292
- results.push(
293
- typeof evalResult === "string" ? evalResult : "LogBox suppression attempted"
294
- );
295
- } catch (error: any) {
296
- results.push(`LogBox suppression failed: ${error.message}`);
297
- }
298
- }
299
-
300
- if (params.pressBack) {
301
- try {
302
- const device = await deviceManager.getDevice();
303
- await device.pressButton("back");
304
- results.push("Back button pressed (dismiss modal overlay)");
305
- } catch (error: any) {
306
- results.push(`Back button failed: ${error.message}`);
307
- }
308
- }
309
-
310
- return {
311
- content: [
312
- {
313
- type: "text" as const,
314
- text: `Overlay dismissal:\n${results.map((r) => ` - ${r}`).join("\n")}`,
315
- },
316
- ],
317
- };
318
- },
319
- };
320
- }
@@ -1,71 +0,0 @@
1
- import { z } from "zod";
2
- import type { DeviceManager } from "../platform/device-manager.js";
3
- import type { RefRegistry } from "../snapshot/ref-registry.js";
4
- import { formatSnapshot } from "../snapshot/formatter.js";
5
-
6
- export const navigationToolSchemas = {
7
- devlens_open_url: {
8
- description:
9
- "Open a URL on the device. Supports deep links (e.g., myapp://screen/home), web URLs, and universal links.",
10
- parameters: z.object({
11
- url: z
12
- .string()
13
- .describe(
14
- "URL to open (e.g., 'https://example.com' or 'myapp://screen/profile')"
15
- ),
16
- }),
17
- },
18
- devlens_go_back: {
19
- description:
20
- "Navigate back on the device. On Android, presses the system back button. On iOS, performs a back swipe gesture.",
21
- parameters: z.object({}),
22
- },
23
- };
24
-
25
- export function createNavigationToolHandlers(
26
- deviceManager: DeviceManager,
27
- refRegistry: RefRegistry,
28
- onNavigate?: () => void
29
- ) {
30
- async function getUpdatedSnapshot(): Promise<string> {
31
- const device = await deviceManager.getDevice();
32
- await new Promise((resolve) => setTimeout(resolve, 500));
33
- const snapshot = await device.getSnapshot();
34
- const nodeToRef = refRegistry.assignRefs(snapshot);
35
- return formatSnapshot(snapshot, nodeToRef);
36
- }
37
-
38
- return {
39
- devlens_open_url: async (params: { url: string }) => {
40
- const device = await deviceManager.getDevice();
41
- await device.openUrl(params.url);
42
- onNavigate?.();
43
-
44
- const snapshot = await getUpdatedSnapshot();
45
- return {
46
- content: [
47
- {
48
- type: "text" as const,
49
- text: `Opened URL: ${params.url}\n\n${snapshot}`,
50
- },
51
- ],
52
- };
53
- },
54
-
55
- devlens_go_back: async () => {
56
- const device = await deviceManager.getDevice();
57
- await device.pressButton("back");
58
- onNavigate?.();
59
-
60
- const snapshot = await getUpdatedSnapshot();
61
- return {
62
- content: [
63
- {
64
- type: "text" as const,
65
- text: `Navigated back\n\n${snapshot}`,
66
- },
67
- ],
68
- };
69
- },
70
- };
71
- }