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,54 +0,0 @@
1
- /**
2
- * Wrapper around `xcrun simctl` for iOS Simulator interaction.
3
- */
4
- export declare class Simctl {
5
- private deviceId;
6
- constructor(deviceId: string);
7
- /** Execute a simctl command */
8
- exec(...args: string[]): Promise<string>;
9
- /** Take a screenshot and return PNG buffer */
10
- screenshot(): Promise<Buffer>;
11
- /** Get the accessibility tree using simctl's accessibility audit */
12
- getAccessibilityTree(): Promise<string>;
13
- /**
14
- * Fallback: Get view hierarchy by running a small XCTest snippet.
15
- * This uses `simctl launch` with a debugger approach, but the simplest
16
- * method is to use the accessibility description from the simulator.
17
- */
18
- private getViewHierarchyViaXctest;
19
- /** Get device info from simctl */
20
- getDeviceInfo(): Promise<{
21
- name: string;
22
- runtime: string;
23
- state: string;
24
- }>;
25
- /** Get screen size of the simulator */
26
- getScreenSize(): Promise<{
27
- width: number;
28
- height: number;
29
- }>;
30
- /** Tap at coordinates using simctl */
31
- tap(x: number, y: number): Promise<void>;
32
- /** Swipe on the simulator */
33
- swipe(startX: number, startY: number, endX: number, endY: number): Promise<void>;
34
- /** Type text using simctl keyboard input */
35
- typeText(text: string): Promise<void>;
36
- /** Press a key using simctl */
37
- pressKey(key: string): Promise<void>;
38
- /** Launch an app */
39
- launchApp(bundleId: string): Promise<void>;
40
- /** Terminate an app */
41
- terminateApp(bundleId: string): Promise<void>;
42
- /** Install an app (.app bundle or .ipa) */
43
- installApp(path: string): Promise<void>;
44
- /** List installed apps */
45
- listApps(): Promise<Array<{
46
- bundleId: string;
47
- name: string;
48
- }>>;
49
- /** Open a URL */
50
- openUrl(url: string): Promise<void>;
51
- /** Set device orientation */
52
- setOrientation(orientation: "portrait" | "landscape"): Promise<void>;
53
- }
54
- //# sourceMappingURL=simctl.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"simctl.d.ts","sourceRoot":"","sources":["../../../../src/platform/ios/simctl.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,qBAAa,MAAM;IACL,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAEpC,+BAA+B;IACzB,IAAI,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAS9C,8CAA8C;IACxC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAUnC,oEAAoE;IAC9D,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;IAe7C;;;;OAIG;YACW,yBAAyB;IAcvC,kCAAkC;IAC5B,aAAa,IAAI,OAAO,CAAC;QAC7B,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IA2BF,uCAAuC;IACjC,aAAa,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAqBjE,sCAAsC;IAChC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB9C,6BAA6B;IACvB,KAAK,CACT,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC;IAgBhB,4CAA4C;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,+BAA+B;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C,oBAAoB;IACd,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,uBAAuB;IACjB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInD,2CAA2C;IACrC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,0BAA0B;IACpB,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IA6BpE,iBAAiB;IACX,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC,6BAA6B;IACvB,cAAc,CAAC,WAAW,EAAE,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAc3E"}
@@ -1,192 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Simctl = void 0;
4
- const child_process_1 = require("child_process");
5
- const util_1 = require("util");
6
- const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
7
- /**
8
- * Wrapper around `xcrun simctl` for iOS Simulator interaction.
9
- */
10
- class Simctl {
11
- deviceId;
12
- constructor(deviceId) {
13
- this.deviceId = deviceId;
14
- }
15
- /** Execute a simctl command */
16
- async exec(...args) {
17
- const { stdout } = await execFileAsync("xcrun", ["simctl", ...args], { maxBuffer: 10 * 1024 * 1024, timeout: 30000 });
18
- return stdout;
19
- }
20
- /** Take a screenshot and return PNG buffer */
21
- async screenshot() {
22
- const tmpPath = `/tmp/devlens-screenshot-${Date.now()}.png`;
23
- await this.exec("io", this.deviceId, "screenshot", tmpPath);
24
- const { readFile, unlink } = await import("fs/promises");
25
- const buffer = await readFile(tmpPath);
26
- unlink(tmpPath).catch(() => { });
27
- return buffer;
28
- }
29
- /** Get the accessibility tree using simctl's accessibility audit */
30
- async getAccessibilityTree() {
31
- // Use simctl ui to get the accessibility hierarchy
32
- try {
33
- const output = await this.exec("ui", this.deviceId, "accessibility");
34
- return output;
35
- }
36
- catch {
37
- // Fallback: use the description command for view hierarchy
38
- return this.getViewHierarchyViaXctest();
39
- }
40
- }
41
- /**
42
- * Fallback: Get view hierarchy by running a small XCTest snippet.
43
- * This uses `simctl launch` with a debugger approach, but the simplest
44
- * method is to use the accessibility description from the simulator.
45
- */
46
- async getViewHierarchyViaXctest() {
47
- // Use the simctl subprocess to query the UI
48
- // We'll use `simctl ui <device> describe` to get the UI hierarchy
49
- try {
50
- const output = await this.exec("ui", this.deviceId, "describe");
51
- return output;
52
- }
53
- catch {
54
- throw new Error("Could not extract accessibility tree from iOS Simulator. " +
55
- "Ensure the simulator is booted and has an app running.");
56
- }
57
- }
58
- /** Get device info from simctl */
59
- async getDeviceInfo() {
60
- const { stdout } = await execFileAsync("xcrun", [
61
- "simctl",
62
- "list",
63
- "devices",
64
- "--json",
65
- ]);
66
- const data = JSON.parse(stdout);
67
- for (const [runtime, devices] of Object.entries(data.devices)) {
68
- for (const device of devices) {
69
- if (device.udid === this.deviceId) {
70
- return {
71
- name: device.name,
72
- runtime: runtime
73
- .replace(/^com\.apple\.CoreSimulator\.SimRuntime\./, "")
74
- .replace(/-/g, "."),
75
- state: device.state,
76
- };
77
- }
78
- }
79
- }
80
- throw new Error(`Device ${this.deviceId} not found in simctl list`);
81
- }
82
- /** Get screen size of the simulator */
83
- async getScreenSize() {
84
- // Take a tiny screenshot and check its dimensions via sharp
85
- const tmpPath = `/tmp/devlens-size-check-${Date.now()}.png`;
86
- await this.exec("io", this.deviceId, "screenshot", tmpPath);
87
- try {
88
- const sharp = (await import("sharp")).default;
89
- const metadata = await sharp(tmpPath).metadata();
90
- const { unlink } = await import("fs/promises");
91
- unlink(tmpPath).catch(() => { });
92
- return {
93
- width: metadata.width || 390,
94
- height: metadata.height || 844,
95
- };
96
- }
97
- catch {
98
- // Fallback defaults (iPhone 14)
99
- return { width: 390, height: 844 };
100
- }
101
- }
102
- /** Tap at coordinates using simctl */
103
- async tap(x, y) {
104
- // simctl doesn't have a direct tap command, so we use the io command
105
- // with the AppleScript approach or the simctl interact command
106
- try {
107
- await this.exec("io", this.deviceId, "tap", String(Math.round(x)), String(Math.round(y)));
108
- }
109
- catch {
110
- // Fallback: use AppleScript to tap on the simulator
111
- await execFileAsync("osascript", [
112
- "-e",
113
- `tell application "Simulator" to activate`,
114
- ]);
115
- // Use cliclick or similar for coordinate-based tapping
116
- throw new Error("Direct tap not supported on this simctl version. Consider using a newer Xcode.");
117
- }
118
- }
119
- /** Swipe on the simulator */
120
- async swipe(startX, startY, endX, endY) {
121
- try {
122
- await this.exec("io", this.deviceId, "swipe", String(Math.round(startX)), String(Math.round(startY)), String(Math.round(endX)), String(Math.round(endY)));
123
- }
124
- catch {
125
- throw new Error("Swipe not supported on this simctl version.");
126
- }
127
- }
128
- /** Type text using simctl keyboard input */
129
- async typeText(text) {
130
- await this.exec("io", this.deviceId, "keyboard", "type", text);
131
- }
132
- /** Press a key using simctl */
133
- async pressKey(key) {
134
- await this.exec("io", this.deviceId, "keyboard", "key", key);
135
- }
136
- /** Launch an app */
137
- async launchApp(bundleId) {
138
- await this.exec("launch", this.deviceId, bundleId);
139
- }
140
- /** Terminate an app */
141
- async terminateApp(bundleId) {
142
- await this.exec("terminate", this.deviceId, bundleId);
143
- }
144
- /** Install an app (.app bundle or .ipa) */
145
- async installApp(path) {
146
- await this.exec("install", this.deviceId, path);
147
- }
148
- /** List installed apps */
149
- async listApps() {
150
- try {
151
- const output = await this.exec("listapps", this.deviceId);
152
- // Parse the plist/json output
153
- const apps = [];
154
- const bundleIdMatches = output.matchAll(/"CFBundleIdentifier"\s*=\s*"([^"]+)"/g);
155
- const nameMatches = output.matchAll(/"CFBundleDisplayName"\s*=\s*"([^"]+)"/g);
156
- const bundleIds = [...bundleIdMatches].map((m) => m[1]);
157
- const names = [...nameMatches].map((m) => m[1]);
158
- for (let i = 0; i < bundleIds.length; i++) {
159
- apps.push({
160
- bundleId: bundleIds[i],
161
- name: names[i] || bundleIds[i],
162
- });
163
- }
164
- return apps;
165
- }
166
- catch {
167
- return [];
168
- }
169
- }
170
- /** Open a URL */
171
- async openUrl(url) {
172
- await this.exec("openurl", this.deviceId, url);
173
- }
174
- /** Set device orientation */
175
- async setOrientation(orientation) {
176
- // simctl doesn't have a direct orientation command
177
- // Use the Simulator menu via AppleScript
178
- const rotation = orientation === "portrait" ? "0" : "90";
179
- try {
180
- await execFileAsync("osascript", [
181
- "-e",
182
- `tell application "System Events" to tell process "Simulator" to ` +
183
- `click menu item "Rotate ${orientation === "landscape" ? "Right" : "Left"}" of menu "Device" of menu bar 1`,
184
- ]);
185
- }
186
- catch {
187
- // Orientation setting may not be available in all environments
188
- }
189
- }
190
- }
191
- exports.Simctl = Simctl;
192
- //# sourceMappingURL=simctl.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"simctl.js","sourceRoot":"","sources":["../../../../src/platform/ios/simctl.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
- export declare function startServer(): Promise<Server>;
3
- //# sourceMappingURL=server.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAuCnE,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAsHnD"}
@@ -1,176 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.startServer = startServer;
4
- const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
5
- const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
6
- const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
7
- const device_manager_js_1 = require("./platform/device-manager.js");
8
- const ref_registry_js_1 = require("./snapshot/ref-registry.js");
9
- const devlens_config_js_1 = require("./config/devlens-config.js");
10
- const ds_tools_js_1 = require("./tools/ds-tools.js");
11
- const device_tools_js_1 = require("./tools/device-tools.js");
12
- const snapshot_tools_js_1 = require("./tools/snapshot-tools.js");
13
- const interaction_tools_js_1 = require("./tools/interaction-tools.js");
14
- const screenshot_tools_js_1 = require("./tools/screenshot-tools.js");
15
- const app_tools_js_1 = require("./tools/app-tools.js");
16
- const metro_tools_js_1 = require("./tools/metro-tools.js");
17
- const navigation_tools_js_1 = require("./tools/navigation-tools.js");
18
- async function startServer() {
19
- const server = new index_js_1.Server({
20
- name: "devlens-mcp",
21
- version: "0.3.0",
22
- }, {
23
- capabilities: {
24
- tools: {},
25
- },
26
- });
27
- // Load config (from DEVLENS_CONFIG env var or ./devlens.config.json)
28
- const devlensConfig = await (0, devlens_config_js_1.loadDevLensConfig)();
29
- // Shared state
30
- const deviceManager = new device_manager_js_1.DeviceManager();
31
- const refRegistry = new ref_registry_js_1.RefRegistry();
32
- const metroPort = parseInt(process.env.METRO_PORT || "8081", 10);
33
- // Create tool handlers
34
- const dsHandlers = (0, ds_tools_js_1.createDsToolHandlers)(devlensConfig.designSystem);
35
- const deviceHandlers = (0, device_tools_js_1.createDeviceToolHandlers)(deviceManager);
36
- const { handlers: snapshotHandlers, resetPreviousSnapshot } = (0, snapshot_tools_js_1.createSnapshotToolHandlers)(deviceManager, refRegistry);
37
- const interactionHandlers = (0, interaction_tools_js_1.createInteractionToolHandlers)(deviceManager, refRegistry, resetPreviousSnapshot);
38
- const screenshotHandlers = (0, screenshot_tools_js_1.createScreenshotToolHandlers)(deviceManager, refRegistry);
39
- const appHandlers = (0, app_tools_js_1.createAppToolHandlers)(deviceManager);
40
- const metroHandlers = (0, metro_tools_js_1.createMetroToolHandlers)(metroPort, deviceManager);
41
- const navigationHandlers = (0, navigation_tools_js_1.createNavigationToolHandlers)(deviceManager, refRegistry, resetPreviousSnapshot);
42
- // Merge all tool schemas
43
- const allSchemas = {
44
- ...ds_tools_js_1.dsToolSchemas,
45
- ...device_tools_js_1.deviceToolSchemas,
46
- ...snapshot_tools_js_1.snapshotToolSchemas,
47
- ...interaction_tools_js_1.interactionToolSchemas,
48
- ...screenshot_tools_js_1.screenshotToolSchemas,
49
- ...app_tools_js_1.appToolSchemas,
50
- ...metro_tools_js_1.metroToolSchemas,
51
- ...navigation_tools_js_1.navigationToolSchemas,
52
- };
53
- // Merge all handlers
54
- const allHandlers = {
55
- ...dsHandlers,
56
- ...deviceHandlers,
57
- ...snapshotHandlers,
58
- ...interactionHandlers,
59
- ...screenshotHandlers,
60
- ...appHandlers,
61
- ...metroHandlers,
62
- ...navigationHandlers,
63
- };
64
- // Register tools/list handler
65
- server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
66
- return {
67
- tools: Object.entries(allSchemas).map(([name, schema]) => ({
68
- name,
69
- description: schema.description,
70
- inputSchema: zodToJsonSchema(schema.parameters),
71
- })),
72
- };
73
- });
74
- // Register tools/call handler
75
- server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
76
- const { name, arguments: args } = request.params;
77
- const handler = allHandlers[name];
78
- if (!handler) {
79
- return {
80
- content: [
81
- {
82
- type: "text",
83
- text: `Unknown tool: ${name}`,
84
- },
85
- ],
86
- isError: true,
87
- };
88
- }
89
- try {
90
- // Validate params with Zod schema
91
- const schema = allSchemas[name];
92
- const validatedArgs = schema.parameters.parse(args || {});
93
- return await handler(validatedArgs);
94
- }
95
- catch (error) {
96
- return {
97
- content: [
98
- {
99
- type: "text",
100
- text: `Error: ${error.message || String(error)}`,
101
- },
102
- ],
103
- isError: true,
104
- };
105
- }
106
- });
107
- // Connect via stdio transport
108
- const transport = new stdio_js_1.StdioServerTransport();
109
- await server.connect(transport);
110
- return server;
111
- }
112
- /**
113
- * Convert a Zod schema to JSON Schema for MCP tool registration.
114
- * This is a simplified converter that handles the common cases.
115
- */
116
- function zodToJsonSchema(schema) {
117
- // Use Zod's built-in JSON schema support if available
118
- if (schema._def) {
119
- return convertZodDef(schema._def);
120
- }
121
- return { type: "object", properties: {} };
122
- }
123
- function convertZodDef(def) {
124
- switch (def.typeName) {
125
- case "ZodObject": {
126
- const properties = {};
127
- const required = [];
128
- for (const [key, value] of Object.entries(def.shape())) {
129
- const propDef = value._def;
130
- if (propDef.typeName === "ZodOptional" || propDef.typeName === "ZodDefault") {
131
- properties[key] = convertZodDef(propDef.typeName === "ZodDefault" ? propDef.innerType._def : propDef.innerType._def);
132
- }
133
- else {
134
- properties[key] = convertZodDef(propDef);
135
- required.push(key);
136
- }
137
- // Add description from Zod describe()
138
- if (propDef.description) {
139
- properties[key].description = propDef.description;
140
- }
141
- else if (value.description) {
142
- properties[key].description = value.description;
143
- }
144
- }
145
- return {
146
- type: "object",
147
- properties,
148
- ...(required.length > 0 ? { required } : {}),
149
- };
150
- }
151
- case "ZodString":
152
- return { type: "string", ...(def.description ? { description: def.description } : {}) };
153
- case "ZodNumber":
154
- return { type: "number", ...(def.description ? { description: def.description } : {}) };
155
- case "ZodBoolean":
156
- return { type: "boolean", ...(def.description ? { description: def.description } : {}) };
157
- case "ZodEnum":
158
- return { type: "string", enum: def.values, ...(def.description ? { description: def.description } : {}) };
159
- case "ZodArray":
160
- return {
161
- type: "array",
162
- items: convertZodDef(def.type._def),
163
- ...(def.description ? { description: def.description } : {}),
164
- };
165
- case "ZodDefault":
166
- return {
167
- ...convertZodDef(def.innerType._def),
168
- default: def.defaultValue(),
169
- };
170
- case "ZodOptional":
171
- return convertZodDef(def.innerType._def);
172
- default:
173
- return {};
174
- }
175
- }
176
- //# sourceMappingURL=server.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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"}
@@ -1,18 +0,0 @@
1
- import type { SnapshotNode } from "../platform/device.js";
2
- /**
3
- * Formats a SnapshotNode tree into a YAML-like text representation
4
- * that LLMs can easily parse and reason about.
5
- *
6
- * Output format (inspired by Playwright MCP):
7
- *
8
- * - FrameLayout
9
- * - LinearLayout
10
- * - TextView "Hello World" [ref=e1]
11
- * - Button "Submit" [ref=e2]
12
- * - EditText "Email" [ref=e3] [focused]
13
- * - RecyclerView [ref=e4]
14
- * - CardView
15
- * - TextView "Item 1" [ref=e5]
16
- */
17
- export declare function formatSnapshot(root: SnapshotNode, nodeToRef: Map<SnapshotNode, string>): string;
18
- //# sourceMappingURL=formatter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../../src/snapshot/formatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,GACnC,MAAM,CAIR"}
@@ -1,86 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.formatSnapshot = formatSnapshot;
4
- /**
5
- * Formats a SnapshotNode tree into a YAML-like text representation
6
- * that LLMs can easily parse and reason about.
7
- *
8
- * Output format (inspired by Playwright MCP):
9
- *
10
- * - FrameLayout
11
- * - LinearLayout
12
- * - TextView "Hello World" [ref=e1]
13
- * - Button "Submit" [ref=e2]
14
- * - EditText "Email" [ref=e3] [focused]
15
- * - RecyclerView [ref=e4]
16
- * - CardView
17
- * - TextView "Item 1" [ref=e5]
18
- */
19
- function formatSnapshot(root, nodeToRef) {
20
- const lines = [];
21
- formatNode(root, nodeToRef, 0, lines);
22
- return lines.join("\n");
23
- }
24
- function formatNode(node, nodeToRef, depth, lines) {
25
- const indent = " ".repeat(depth);
26
- const parts = [];
27
- // Type
28
- parts.push(node.type);
29
- // Text content
30
- if (node.text) {
31
- parts.push(`"${truncate(node.text, 60)}"`);
32
- }
33
- // Accessibility label (if different from text)
34
- if (node.label && node.label !== node.text) {
35
- parts.push(`label="${truncate(node.label, 40)}"`);
36
- }
37
- // Annotations
38
- const annotations = [];
39
- // Ref
40
- const ref = nodeToRef.get(node);
41
- if (ref) {
42
- annotations.push(`ref=${ref}`);
43
- }
44
- // State annotations
45
- if (node.focused)
46
- annotations.push("focused");
47
- if (node.value)
48
- annotations.push(`value="${node.value}"`);
49
- if (node.enabled === false)
50
- annotations.push("disabled");
51
- if (node.resourceId) {
52
- const shortId = node.resourceId.includes("/")
53
- ? node.resourceId.split("/").pop()
54
- : node.resourceId;
55
- annotations.push(`id="${shortId}"`);
56
- }
57
- if (annotations.length > 0) {
58
- parts.push(`[${annotations.join("] [")}]`);
59
- }
60
- // Build the line
61
- const line = `${indent}- ${parts.join(" ")}`;
62
- // Only include nodes that have refs, text, labels, or children with refs
63
- if (ref || node.text || node.label || hasRefInSubtree(node, nodeToRef)) {
64
- lines.push(line);
65
- }
66
- // Recurse into children
67
- for (const child of node.children) {
68
- formatNode(child, nodeToRef, depth + 1, lines);
69
- }
70
- }
71
- /** Check if any descendant has a ref assigned */
72
- function hasRefInSubtree(node, nodeToRef) {
73
- for (const child of node.children) {
74
- if (nodeToRef.has(child))
75
- return true;
76
- if (hasRefInSubtree(child, nodeToRef))
77
- return true;
78
- }
79
- return false;
80
- }
81
- function truncate(str, maxLen) {
82
- if (str.length <= maxLen)
83
- return str;
84
- return str.slice(0, maxLen - 3) + "...";
85
- }
86
- //# sourceMappingURL=formatter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../../src/snapshot/formatter.ts"],"names":[],"mappings":"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"}
@@ -1,67 +0,0 @@
1
- import type { SnapshotNode, Bounds } from "../platform/device.js";
2
- /**
3
- * RefRegistry — the Playwright-style ref assignment system.
4
- *
5
- * Assigns monotonically increasing refs (e1, e2, ...) to every interactive
6
- * or meaningful node in the accessibility tree. Maintains a map from ref
7
- * to node info (bounds, center coords) so interaction tools can resolve
8
- * "tap ref=e5" to actual screen coordinates.
9
- */
10
- export interface RefEntry {
11
- ref: string;
12
- node: SnapshotNode;
13
- centerX: number;
14
- centerY: number;
15
- bounds: Bounds;
16
- }
17
- export interface ValidationIssue {
18
- type: "zero-size" | "invisible" | "empty-container";
19
- nodeType: string;
20
- text?: string;
21
- label?: string;
22
- resourceId?: string;
23
- bounds: Bounds;
24
- detail: string;
25
- }
26
- export interface ValidationReport {
27
- issues: ValidationIssue[];
28
- totalNodes: number;
29
- visibleNodes: number;
30
- zeroSizeNodes: number;
31
- interactiveNodes: number;
32
- }
33
- export declare class RefRegistry {
34
- private refMap;
35
- private counter;
36
- /** Clear all refs and reset counter (call before each new snapshot) */
37
- reset(): void;
38
- /**
39
- * Walk the snapshot tree and assign refs to all interactive or content-bearing nodes.
40
- * Returns a new tree with refs attached (as annotations in the formatter output).
41
- */
42
- assignRefs(root: SnapshotNode): Map<SnapshotNode, string>;
43
- private walkAndAssign;
44
- /** Determine if a node should get a ref */
45
- private shouldAssignRef;
46
- /** Resolve a ref string to its entry (coordinates + node info) */
47
- resolve(ref: string): RefEntry | undefined;
48
- /** Get all current ref entries */
49
- getAllRefs(): RefEntry[];
50
- /** Get the total number of assigned refs */
51
- get size(): number;
52
- /**
53
- * Validate the snapshot tree for visibility issues.
54
- * Flags zero-size elements that should be visible, explicitly invisible elements,
55
- * and empty containers that might indicate missing content.
56
- */
57
- validateTree(root: SnapshotNode): ValidationReport;
58
- /**
59
- * Search the full snapshot tree (including zero-size nodes) for text/label matches.
60
- * Used by find_element to detect invisible elements that the refMap skips.
61
- */
62
- findInTree(root: SnapshotNode, query: {
63
- text?: string;
64
- label?: string;
65
- }): SnapshotNode[];
66
- }
67
- //# sourceMappingURL=ref-registry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ref-registry.d.ts","sourceRoot":"","sources":["../../../src/snapshot/ref-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAElE;;;;;;;GAOG;AAEH,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,GAAG,WAAW,GAAG,iBAAiB,CAAC;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAoC;IAClD,OAAO,CAAC,OAAO,CAAa;IAE5B,uEAAuE;IACvE,KAAK,IAAI,IAAI;IAKb;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC;IAOzD,OAAO,CAAC,aAAa;IAwBrB,2CAA2C;IAC3C,OAAO,CAAC,eAAe;IAiBvB,kEAAkE;IAClE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI1C,kCAAkC;IAClC,UAAU,IAAI,QAAQ,EAAE;IAIxB,4CAA4C;IAC5C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;OAIG;IACH,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,gBAAgB;IA4ElD;;;OAGG;IACH,UAAU,CACR,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GACvC,YAAY,EAAE;CA0BlB"}