mobile-debug-mcp 0.33.0 → 0.35.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 (448) hide show
  1. package/.agents/skills/mcp-builder/SKILL.md +44 -64
  2. package/.agents/skills/mcp-builder/references/build-flags.md +44 -43
  3. package/.agents/skills/mcp-builder/references/diagnostics-schema.md +4 -1
  4. package/.agents/skills/mcp-builder/references/toolchain-details.md +49 -62
  5. package/.agents/skills/spec-review/references/spec-review-checklist.md +7 -0
  6. package/.agents/skills/test-authoring/SKILL.md +7 -6
  7. package/.agents/skills/test-authoring/references/repo-test-layout.md +3 -1
  8. package/.agents/skills/test-authoring/references/test-authoring-workflow.md +16 -7
  9. package/.agents/skills/test-authoring/references/test-quality-checklist.md +2 -1
  10. package/.github/copilot-instructions.md +14 -36
  11. package/.github/workflows/ci.yml +23 -2
  12. package/AGENTS.md +12 -3
  13. package/CONTRIBUTING.md +79 -0
  14. package/README.md +158 -124
  15. package/agent-plugin/.claude-plugin/plugin.json +2 -2
  16. package/agent-plugin/.codex-plugin/plugin.json +1 -1
  17. package/agent-plugin/.cursor-plugin/plugin.json +2 -2
  18. package/agent-plugin/.mcp.json +1 -1
  19. package/agent-plugin/README.md +20 -6
  20. package/agent-plugin/mcp.json +1 -1
  21. package/agent-plugin/plugin.json +1 -1
  22. package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +113 -4
  23. package/dist/contracts/execution-controls.js +24 -0
  24. package/dist/contracts/selector.js +8 -0
  25. package/dist/contracts/target.js +15 -0
  26. package/dist/contracts/ui.js +1 -0
  27. package/dist/debugger/android.js +79 -0
  28. package/dist/debugger/diagnostics.js +54 -0
  29. package/dist/debugger/guard.js +30 -0
  30. package/dist/debugger/protocol.js +33 -0
  31. package/dist/debugger/sessions.js +304 -0
  32. package/dist/debugger/worker.js +176 -0
  33. package/dist/interact/adjustment/adjustment-context.js +41 -0
  34. package/dist/interact/adjustment/adjustment-gestures.js +55 -0
  35. package/dist/interact/adjustment/adjustment-plan.js +18 -0
  36. package/dist/interact/adjustment/adjustment-resolution.js +127 -0
  37. package/dist/interact/adjustment/adjustment-result.js +19 -0
  38. package/dist/interact/adjustment/adjustment-semantic.js +64 -0
  39. package/dist/interact/adjustment/adjustment-verification.js +35 -0
  40. package/dist/interact/adjustment/adjustment.js +52 -0
  41. package/dist/interact/adjustment/control-geometry.js +87 -0
  42. package/dist/interact/adjustment/control-values.js +136 -0
  43. package/dist/interact/adjustment/slider-labels.js +84 -0
  44. package/dist/interact/assertions/screen-assertion.js +37 -0
  45. package/dist/interact/assertions/state-assertion-context.js +35 -0
  46. package/dist/interact/assertions/state-assertion.js +76 -0
  47. package/dist/interact/assertions/state-comparison.js +141 -0
  48. package/dist/interact/assertions/visibility-assertion.js +34 -0
  49. package/dist/interact/conditional-action.js +12 -7
  50. package/dist/interact/index.js +65 -3074
  51. package/dist/interact/input-service.js +1 -0
  52. package/dist/interact/interaction-trace.js +21 -0
  53. package/dist/interact/model.js +1 -0
  54. package/dist/interact/observation.js +1 -0
  55. package/dist/interact/targeting/candidate-ancestor.js +58 -0
  56. package/dist/interact/targeting/candidate-result.js +23 -0
  57. package/dist/interact/targeting/candidate-scoring.js +50 -0
  58. package/dist/interact/targeting/element-helpers.js +216 -0
  59. package/dist/interact/targeting/find-element.js +65 -0
  60. package/dist/interact/targeting/nearby-control.js +56 -0
  61. package/dist/interact/targeting/resolved-elements.js +21 -0
  62. package/dist/interact/targeting/tap-target.js +17 -0
  63. package/dist/interact/targeting/target-scope.js +104 -0
  64. package/dist/interact/waits/legacy-log-wait.js +38 -0
  65. package/dist/interact/waits/legacy-wait-observations.js +103 -0
  66. package/dist/interact/waits/legacy-wait-state.js +34 -0
  67. package/dist/interact/waits/legacy-wait.js +48 -0
  68. package/dist/interact/waits/screen-wait.js +49 -0
  69. package/dist/interact/waits/ui-change-helpers.js +157 -0
  70. package/dist/interact/waits/ui-change-state.js +18 -0
  71. package/dist/interact/waits/ui-change-wait.js +77 -0
  72. package/dist/interact/waits/ui-wait-condition.js +56 -0
  73. package/dist/interact/waits/ui-wait-state.js +38 -0
  74. package/dist/interact/waits/ui-wait.js +106 -0
  75. package/dist/manage/android.js +55 -51
  76. package/dist/manage/index.js +38 -75
  77. package/dist/manage/ios/build-types.js +1 -0
  78. package/dist/manage/ios/build.js +210 -0
  79. package/dist/manage/ios/project-discovery.js +29 -0
  80. package/dist/manage/ios/scheme.js +18 -0
  81. package/dist/manage/ios.js +42 -256
  82. package/dist/observe/android/context.js +1 -0
  83. package/dist/observe/android/current-screen.js +55 -0
  84. package/dist/observe/android/fingerprint.js +13 -0
  85. package/dist/observe/android/log-stream.js +132 -0
  86. package/dist/observe/android/logs.js +107 -0
  87. package/dist/observe/android/screenshot.js +70 -0
  88. package/dist/observe/android/ui-tree.js +107 -0
  89. package/dist/observe/android.js +16 -520
  90. package/dist/observe/evidence.js +122 -76
  91. package/dist/observe/index.js +16 -263
  92. package/dist/observe/ios/context.js +16 -0
  93. package/dist/observe/ios/fingerprint.js +12 -0
  94. package/dist/observe/ios/log-stream.js +105 -0
  95. package/dist/observe/ios/logs.js +168 -0
  96. package/dist/observe/ios/screenshot.js +22 -0
  97. package/dist/observe/ios/ui-elements.js +241 -0
  98. package/dist/observe/ios/ui-tree.js +137 -0
  99. package/dist/observe/ios.js +17 -715
  100. package/dist/observe/logs/model.js +1 -0
  101. package/dist/{network → observe/network}/index.js +2 -2
  102. package/dist/observe/readiness-service.js +13 -2
  103. package/dist/observe/readiness.js +44 -18
  104. package/dist/observe/screenshot-encoding.js +41 -0
  105. package/dist/observe/snapshot-collection.js +79 -0
  106. package/dist/observe/snapshot-logs.js +30 -0
  107. package/dist/observe/snapshot-metadata.js +43 -31
  108. package/dist/observe/snapshot-semantic.js +115 -0
  109. package/dist/observe/system-trace-android.js +135 -0
  110. package/dist/observe/system-trace.js +294 -0
  111. package/dist/runtime/action-results.js +270 -0
  112. package/dist/runtime/clock.js +4 -0
  113. package/dist/server/common.js +1 -256
  114. package/dist/server/definitions/assert.js +162 -0
  115. package/dist/server/definitions/diagnostic.js +118 -0
  116. package/dist/server/definitions/input.js +274 -0
  117. package/dist/server/definitions/manage.js +194 -0
  118. package/dist/server/definitions/observe.js +149 -0
  119. package/dist/server/definitions/target.js +138 -0
  120. package/dist/server/definitions/wait.js +105 -0
  121. package/dist/server/handlers/action-execution.js +163 -0
  122. package/dist/server/handlers/correlation.js +23 -0
  123. package/dist/server/handlers/debugger-handlers.js +48 -0
  124. package/dist/server/handlers/debugger-response.js +9 -0
  125. package/dist/server/handlers/diagnostic.js +69 -0
  126. package/dist/server/handlers/handler-types.js +1 -0
  127. package/dist/server/handlers/input.js +154 -0
  128. package/dist/server/handlers/interact.js +113 -0
  129. package/dist/server/handlers/journey-assertions.js +35 -0
  130. package/dist/server/handlers/journey.js +147 -0
  131. package/dist/server/handlers/manage.js +119 -0
  132. package/dist/server/handlers/observe.js +95 -0
  133. package/dist/server/handlers/payload.js +4 -0
  134. package/dist/server/handlers/tool-handlers.js +160 -0
  135. package/dist/server/schemas/condition-schema.js +2 -0
  136. package/dist/server/schemas/debugger-schema.js +47 -0
  137. package/dist/server/{journey-schema.js → schemas/journey-schema.js} +8 -22
  138. package/dist/server/schemas/system-trace-schema.js +17 -0
  139. package/dist/server/tool-definitions.js +62 -1134
  140. package/dist/server-core.js +4 -4
  141. package/dist/server.js +34 -0
  142. package/dist/system/android-status.js +101 -0
  143. package/dist/system/android.js +37 -27
  144. package/dist/system/index.js +13 -438
  145. package/dist/system/ios-status.js +132 -0
  146. package/dist/system/ios.js +11 -8
  147. package/dist/system/model.js +1 -0
  148. package/dist/system/probes.js +105 -0
  149. package/dist/system/status-summary.js +43 -0
  150. package/dist/system/unsupported-status.js +52 -0
  151. package/dist/utils/android/commands.js +89 -0
  152. package/dist/utils/android/gradle.js +139 -0
  153. package/dist/utils/android/logs.js +103 -0
  154. package/dist/utils/android/ui-tree.js +233 -0
  155. package/dist/utils/android/utils.js +6 -564
  156. package/dist/utils/cli/idb/idb-helper.js +4 -6
  157. package/dist/utils/cli/idb/install-idb.js +13 -9
  158. package/dist/utils/cli/ios/preflight-ios.js +42 -38
  159. package/dist/utils/exec.js +2 -0
  160. package/dist/utils/ios/utils.js +45 -46
  161. package/dist/utils/java.js +75 -57
  162. package/dist/utils/operation-budget.js +2 -0
  163. package/dist/utils/resolve-device.js +6 -2
  164. package/dist/utils/ui/index.js +26 -26
  165. package/docs/CHANGELOG.md +48 -0
  166. package/docs/README.md +38 -0
  167. package/docs/benchmarks/README.md +18 -0
  168. package/docs/benchmarks/interaction-latency/README.md +14 -0
  169. package/docs/benchmarks/interaction-latency/final.md +4 -1
  170. package/docs/benchmarks/interaction-latency/ios-validation.md +2 -0
  171. package/docs/benchmarks/ui-tree-performance/README.md +24 -16
  172. package/docs/benchmarks/ui-tree-performance/comparison.md +11 -10
  173. package/docs/code-structure.md +118 -0
  174. package/docs/specs/001-state-verification/spec.md +16 -14
  175. package/docs/specs/002-richer-element-identity/spec.md +12 -10
  176. package/docs/specs/003-wait-and-synchronization-reliability/spec.md +12 -10
  177. package/docs/specs/004-action-verification-routing/spec.md +3 -3
  178. package/docs/specs/005-unified-action-execution-and-verification-model/spec.md +2 -0
  179. package/docs/specs/006-runtime-action-instrumentation-and-binding-layer/spec.md +2 -0
  180. package/docs/specs/007-actionability-resolution-and-executable-target-selection/spec.md +3 -1
  181. package/docs/specs/008-adjustable-control-support-and-semantic-value-manipulation/spec.md +3 -4
  182. package/docs/specs/009-semantic-control-modeling-for-custom-and-composite-controls/spec.md +2 -0
  183. package/docs/specs/010-verification-stabilization-and-temporal-convergence/spec.md +2 -2
  184. package/docs/specs/011-recovery-and-replanning-for-failed-or-ambiguous-interaction-flows/spec.md +2 -2
  185. package/docs/specs/011.1-recovery-contract-types-and-runtime-wiring-spec/spec.md +2 -0
  186. package/docs/specs/012-action-trace-and-xecution-observability/spec.md +2 -3
  187. package/docs/specs/013-wait-and-synchronization-reliability/spec.md +19 -19
  188. package/docs/specs/014-actionability-resolution/spec.md +20 -18
  189. package/docs/specs/015-adjustable-control-support/spec.md +17 -15
  190. package/docs/specs/016-environment-tools/spec.md +20 -20
  191. package/docs/specs/018-interaction-latency-and-batched-journeys/spec.md +2 -0
  192. package/docs/specs/019-ui-tree-observation-performance/spec.md +3 -1
  193. package/docs/specs/020-conditional-actions/intent.md +5 -3
  194. package/docs/specs/020-conditional-actions/plan.md +8 -9
  195. package/docs/specs/020-conditional-actions/spec.md +4 -2
  196. package/docs/specs/021-app-readiness-signals/intent.md +4 -2
  197. package/docs/specs/021-app-readiness-signals/plan.md +7 -6
  198. package/docs/specs/021-app-readiness-signals/spec.md +3 -1
  199. package/docs/specs/022-correlated-evidence/intent.md +4 -4
  200. package/docs/specs/022-correlated-evidence/plan.md +10 -11
  201. package/docs/specs/022-correlated-evidence/spec.md +3 -1
  202. package/docs/specs/023-android-system-traces/device-evidence.json +38 -0
  203. package/docs/specs/023-android-system-traces/emulator-recheck.json +38 -0
  204. package/docs/specs/023-android-system-traces/intent.md +41 -0
  205. package/docs/specs/023-android-system-traces/plan.md +115 -0
  206. package/docs/specs/023-android-system-traces/spec.md +122 -0
  207. package/docs/specs/024-android-heap-dump-capture/intent.md +41 -0
  208. package/docs/specs/025-android-runtime-debugger/intent.md +41 -0
  209. package/docs/specs/025-android-runtime-debugger/plan.md +106 -0
  210. package/docs/specs/025-android-runtime-debugger/spec.md +183 -0
  211. package/docs/specs/026-code-structure-and-quality-gates/health-plan.md +88 -0
  212. package/docs/specs/026-code-structure-and-quality-gates/intent.md +47 -0
  213. package/docs/specs/026-code-structure-and-quality-gates/plan.md +191 -0
  214. package/docs/specs/026-code-structure-and-quality-gates/spec.md +138 -0
  215. package/docs/specs/026-code-structure-and-quality-gates/verification-final.json +200 -0
  216. package/docs/specs/026-code-structure-and-quality-gates/verification-thin-facade.json +154 -0
  217. package/docs/specs/026-code-structure-and-quality-gates/verification.json +136 -0
  218. package/docs/specs/027-debugger-failure-diagnostics/intent.md +43 -0
  219. package/docs/specs/027-debugger-failure-diagnostics/plan.md +86 -0
  220. package/docs/specs/027-debugger-failure-diagnostics/spec.md +133 -0
  221. package/docs/specs/028-compact-debugger-responses/intent.md +41 -0
  222. package/docs/specs/028-compact-debugger-responses/plan.md +112 -0
  223. package/docs/specs/028-compact-debugger-responses/spec.md +108 -0
  224. package/docs/specs/029-kotlin-locals-validation/report.md +119 -0
  225. package/docs/specs/030-android-coroutine-validation/evidence.json +475 -0
  226. package/docs/specs/030-android-coroutine-validation/intent.md +47 -0
  227. package/docs/specs/030-android-coroutine-validation/plan.md +147 -0
  228. package/docs/specs/030-android-coroutine-validation/report.md +240 -0
  229. package/docs/specs/030-android-coroutine-validation/spec.md +107 -0
  230. package/docs/tools/TOOLS.md +31 -16
  231. package/docs/tools/{evidence.md → correlated-evidence.md} +14 -3
  232. package/docs/tools/debugger.md +180 -0
  233. package/docs/tools/interact.md +42 -20
  234. package/docs/tools/manage.md +25 -44
  235. package/docs/tools/observe.md +64 -25
  236. package/docs/tools/system-traces.md +134 -0
  237. package/docs/tools/system.md +12 -5
  238. package/package.json +11 -8
  239. package/scripts/architecture-graph.mjs +69 -0
  240. package/scripts/check-architecture.mjs +47 -0
  241. package/scripts/code-quality-baseline.json +1 -0
  242. package/scripts/code-quality.mjs +161 -0
  243. package/src/contracts/execution-controls.ts +26 -0
  244. package/src/contracts/selector.ts +17 -0
  245. package/src/contracts/target.ts +19 -0
  246. package/src/contracts/ui.ts +94 -0
  247. package/src/debugger/android.ts +66 -0
  248. package/src/debugger/diagnostics.ts +43 -0
  249. package/src/debugger/guard.ts +31 -0
  250. package/src/debugger/java/DebuggerWorker.java +166 -0
  251. package/src/debugger/protocol.ts +37 -0
  252. package/src/debugger/sessions.ts +327 -0
  253. package/src/debugger/worker.ts +135 -0
  254. package/src/interact/adjustment/adjustment-context.ts +83 -0
  255. package/src/interact/adjustment/adjustment-gestures.ts +48 -0
  256. package/src/interact/adjustment/adjustment-plan.ts +23 -0
  257. package/src/interact/adjustment/adjustment-resolution.ts +104 -0
  258. package/src/interact/adjustment/adjustment-result.ts +34 -0
  259. package/src/interact/adjustment/adjustment-semantic.ts +53 -0
  260. package/src/interact/adjustment/adjustment-verification.ts +60 -0
  261. package/src/interact/adjustment/adjustment.ts +49 -0
  262. package/src/interact/adjustment/control-geometry.ts +120 -0
  263. package/src/interact/adjustment/control-values.ts +141 -0
  264. package/src/interact/adjustment/slider-labels.ts +84 -0
  265. package/src/interact/assertions/screen-assertion.ts +39 -0
  266. package/src/interact/assertions/state-assertion-context.ts +48 -0
  267. package/src/interact/assertions/state-assertion.ts +64 -0
  268. package/src/interact/assertions/state-comparison.ts +168 -0
  269. package/src/interact/assertions/visibility-assertion.ts +41 -0
  270. package/src/interact/conditional-action.ts +18 -12
  271. package/src/interact/index.ts +76 -3491
  272. package/src/interact/input-service.ts +11 -0
  273. package/src/interact/interaction-trace.ts +36 -0
  274. package/src/interact/model.ts +109 -0
  275. package/src/interact/observation.ts +7 -0
  276. package/src/interact/targeting/candidate-ancestor.ts +49 -0
  277. package/src/interact/targeting/candidate-result.ts +24 -0
  278. package/src/interact/targeting/candidate-scoring.ts +42 -0
  279. package/src/interact/targeting/element-helpers.ts +243 -0
  280. package/src/interact/targeting/find-element.ts +47 -0
  281. package/src/interact/targeting/nearby-control.ts +46 -0
  282. package/src/interact/targeting/resolved-elements.ts +20 -0
  283. package/src/interact/targeting/tap-target.ts +22 -0
  284. package/src/interact/targeting/target-scope.ts +121 -0
  285. package/src/interact/waits/legacy-log-wait.ts +30 -0
  286. package/src/interact/waits/legacy-wait-observations.ts +55 -0
  287. package/src/interact/waits/legacy-wait-state.ts +48 -0
  288. package/src/interact/waits/legacy-wait.ts +34 -0
  289. package/src/interact/waits/screen-wait.ts +37 -0
  290. package/src/interact/waits/ui-change-helpers.ts +184 -0
  291. package/src/interact/waits/ui-change-state.ts +26 -0
  292. package/src/interact/waits/ui-change-wait.ts +59 -0
  293. package/src/interact/waits/ui-wait-condition.ts +52 -0
  294. package/src/interact/waits/ui-wait-state.ts +55 -0
  295. package/src/interact/waits/ui-wait.ts +84 -0
  296. package/src/manage/android.ts +56 -50
  297. package/src/manage/index.ts +63 -93
  298. package/src/manage/ios/build-types.ts +14 -0
  299. package/src/manage/ios/build.ts +230 -0
  300. package/src/manage/ios/project-discovery.ts +26 -0
  301. package/src/manage/ios/scheme.ts +16 -0
  302. package/src/manage/ios.ts +65 -298
  303. package/src/observe/android/context.ts +1 -0
  304. package/src/observe/android/current-screen.ts +63 -0
  305. package/src/observe/android/fingerprint.ts +13 -0
  306. package/src/observe/android/log-stream.ts +127 -0
  307. package/src/observe/android/logs.ts +110 -0
  308. package/src/observe/android/screenshot.ts +79 -0
  309. package/src/observe/android/ui-tree.ts +113 -0
  310. package/src/observe/android.ts +17 -531
  311. package/src/observe/evidence.ts +130 -71
  312. package/src/observe/index.ts +24 -286
  313. package/src/observe/ios/context.ts +22 -0
  314. package/src/observe/ios/fingerprint.ts +12 -0
  315. package/src/observe/ios/log-stream.ts +103 -0
  316. package/src/observe/ios/logs.ts +179 -0
  317. package/src/observe/ios/screenshot.ts +26 -0
  318. package/src/observe/ios/ui-elements.ts +266 -0
  319. package/src/observe/ios/ui-tree.ts +143 -0
  320. package/src/observe/ios.ts +18 -749
  321. package/src/observe/logs/model.ts +11 -0
  322. package/src/{network → observe/network}/index.ts +2 -2
  323. package/src/observe/readiness-service.ts +10 -3
  324. package/src/observe/readiness.ts +49 -22
  325. package/src/observe/screenshot-encoding.ts +32 -0
  326. package/src/observe/snapshot-collection.ts +69 -0
  327. package/src/observe/snapshot-logs.ts +26 -0
  328. package/src/observe/snapshot-metadata.ts +51 -31
  329. package/src/observe/snapshot-semantic.ts +153 -0
  330. package/src/observe/system-trace-android.ts +133 -0
  331. package/src/observe/system-trace.ts +227 -0
  332. package/src/runtime/action-results.ts +376 -0
  333. package/src/runtime/clock.ts +9 -0
  334. package/src/server/common.ts +9 -359
  335. package/src/server/definitions/assert.ts +164 -0
  336. package/src/server/definitions/diagnostic.ts +120 -0
  337. package/src/server/definitions/input.ts +276 -0
  338. package/src/server/definitions/manage.ts +196 -0
  339. package/src/server/definitions/observe.ts +151 -0
  340. package/src/server/definitions/target.ts +140 -0
  341. package/src/server/definitions/wait.ts +107 -0
  342. package/src/server/handlers/action-execution.ts +164 -0
  343. package/src/server/handlers/correlation.ts +20 -0
  344. package/src/server/handlers/debugger-handlers.ts +39 -0
  345. package/src/server/handlers/debugger-response.ts +7 -0
  346. package/src/server/handlers/diagnostic.ts +79 -0
  347. package/src/server/handlers/handler-types.ts +7 -0
  348. package/src/server/handlers/input.ts +173 -0
  349. package/src/server/handlers/interact.ts +135 -0
  350. package/src/server/handlers/journey-assertions.ts +39 -0
  351. package/src/server/handlers/journey.ts +132 -0
  352. package/src/server/handlers/manage.ts +141 -0
  353. package/src/server/handlers/observe.ts +116 -0
  354. package/src/server/handlers/payload.ts +36 -0
  355. package/src/server/handlers/tool-handlers.ts +159 -0
  356. package/src/server/schemas/condition-schema.ts +2 -0
  357. package/src/server/schemas/debugger-schema.ts +43 -0
  358. package/src/server/{journey-schema.ts → schemas/journey-schema.ts} +8 -22
  359. package/src/server/schemas/system-trace-schema.ts +17 -0
  360. package/src/server/tool-definitions.ts +69 -1140
  361. package/src/server-core.ts +4 -4
  362. package/src/server.ts +25 -1
  363. package/src/system/android-status.ts +124 -0
  364. package/src/system/android.ts +33 -21
  365. package/src/system/index.ts +21 -523
  366. package/src/system/ios-status.ts +147 -0
  367. package/src/system/ios.ts +14 -10
  368. package/src/system/model.ts +41 -0
  369. package/src/system/probes.ts +114 -0
  370. package/src/system/status-summary.ts +47 -0
  371. package/src/system/unsupported-status.ts +55 -0
  372. package/src/types.ts +16 -106
  373. package/src/utils/android/commands.ts +81 -0
  374. package/src/utils/android/gradle.ts +132 -0
  375. package/src/utils/android/logs.ts +103 -0
  376. package/src/utils/android/ui-tree.ts +239 -0
  377. package/src/utils/android/utils.ts +16 -556
  378. package/src/utils/cli/idb/check-idb.ts +4 -4
  379. package/src/utils/cli/idb/idb-helper.ts +6 -8
  380. package/src/utils/cli/idb/install-idb.ts +15 -9
  381. package/src/utils/cli/ios/preflight-ios.ts +39 -31
  382. package/src/utils/cli/ios/run-ios-ui-tree-tap.ts +4 -4
  383. package/src/utils/exec.ts +2 -0
  384. package/src/utils/ios/utils.ts +57 -61
  385. package/src/utils/java.ts +71 -51
  386. package/src/utils/operation-budget.ts +2 -0
  387. package/src/utils/resolve-device.ts +11 -6
  388. package/src/utils/ui/index.ts +28 -28
  389. package/test/device/automated/debugger/coroutine-lifecycle.ts +27 -0
  390. package/test/device/automated/debugger/coroutine-support.ts +140 -0
  391. package/test/device/automated/debugger/coroutine.android.test.ts +169 -0
  392. package/test/device/automated/debugger/kotlin.android.test.ts +127 -0
  393. package/test/device/automated/debugger/runtime.android.test.ts +219 -0
  394. package/test/device/automated/interact/interaction.android.test.ts +56 -0
  395. package/test/device/automated/observe/system-trace.smoke.ts +104 -0
  396. package/test/device/manual/interact/modul8_selector_tap.manual.ts +1 -1
  397. package/test/fixtures/contracts/tool-definitions.json +3536 -0
  398. package/test/fixtures/coroutine-app/MainActivity.kt +100 -0
  399. package/test/fixtures/coroutine-app/README.md +48 -0
  400. package/test/fixtures/coroutine-app/build.ts +35 -0
  401. package/test/fixtures/debugger-app/MainActivity.java +67 -0
  402. package/test/fixtures/debugger-app/MainActivity.kt +32 -0
  403. package/test/fixtures/debugger-app/NoLocals.java +7 -0
  404. package/test/fixtures/debugger-app/README.md +65 -0
  405. package/test/fixtures/debugger-app/build.ts +39 -0
  406. package/test/fixtures/latency-journey-app/README.md +2 -0
  407. package/test/fixtures/readiness-app/README.md +2 -0
  408. package/test/helpers/perfetto.ts +59 -0
  409. package/test/unit/debugger/coroutine-lifecycle.test.ts +43 -0
  410. package/test/unit/debugger/diagnostic-sessions.test.ts +67 -0
  411. package/test/unit/debugger/diagnostics.test.ts +80 -0
  412. package/test/unit/debugger/guards.test.ts +50 -0
  413. package/test/unit/debugger/native.test.ts +33 -0
  414. package/test/unit/debugger/preparation.test.ts +32 -0
  415. package/test/unit/debugger/protocol.test.ts +15 -0
  416. package/test/unit/debugger/sessions.test.ts +83 -0
  417. package/test/unit/interact/adjustment_service.test.ts +42 -0
  418. package/test/unit/interact/adjustment_verification.test.ts +35 -0
  419. package/test/unit/interact/clock_dependencies.test.ts +63 -0
  420. package/test/unit/interact/element_helpers.test.ts +19 -0
  421. package/test/unit/interact/legacy_wait_service.test.ts +17 -0
  422. package/test/unit/interact/state_comparison.test.ts +20 -0
  423. package/test/unit/interact/target_scope.test.ts +35 -0
  424. package/test/unit/network/get_network_activity.test.ts +1 -1
  425. package/test/unit/observe/readiness.test.ts +3 -1
  426. package/test/unit/observe/screenshot-encoding.test.ts +30 -0
  427. package/test/unit/observe/snapshot-logs.test.ts +14 -0
  428. package/test/unit/observe/system-trace-android.test.ts +52 -0
  429. package/test/unit/observe/system-trace.test.ts +166 -0
  430. package/test/unit/quality/architecture.test.ts +60 -0
  431. package/test/unit/quality/code-quality.test.ts +58 -0
  432. package/test/unit/quality/interaction_boundaries.test.ts +24 -0
  433. package/test/unit/server/conditional_actions.test.ts +1 -1
  434. package/test/unit/server/conditional_schema.test.ts +2 -2
  435. package/test/unit/server/debugger-response.test.ts +63 -0
  436. package/test/unit/server/system-trace.test.ts +64 -0
  437. package/test/unit/server/tool_definitions_parity.test.ts +8 -0
  438. package/dist/server/tool-handlers.js +0 -893
  439. package/docs/ROADMAP.md +0 -646
  440. package/docs/benchmarks/ui-tree-performance/bridge-probe.json +0 -29
  441. package/docs/benchmarks/ui-tree-performance/initial-baseline.json +0 -59560
  442. package/docs/specs/baseline-spec-v0.md +0 -312
  443. package/docs/specs/mcp-tooling-spec-v1.md +0 -446
  444. package/src/server/tool-handlers.ts +0 -923
  445. /package/dist/{server/condition-schema.js → contracts/condition.js} +0 -0
  446. /package/dist/server/{readiness-schema.js → schemas/readiness-schema.js} +0 -0
  447. /package/src/{server/condition-schema.ts → contracts/condition.ts} +0 -0
  448. /package/src/server/{readiness-schema.ts → schemas/readiness-schema.ts} +0 -0
@@ -1,441 +1,12 @@
1
- import { spawnSync } from 'child_process';
2
- import path from 'path';
3
1
  import { checkAndroid } from './android.js';
4
2
  import { checkGradle } from './gradle.js';
5
3
  import { checkIOS } from './ios.js';
6
- import { resolveAdbCmd } from '../utils/android/utils.js';
7
- import { getIdbCmd, getXcrunCmd } from '../utils/ios/utils.js';
8
- import { probeIdb } from '../utils/cli/idb/idb-helper.js';
9
4
  import { detectJavaHome } from '../utils/java.js';
10
- function normalizeHostOs(platform) {
11
- switch (platform) {
12
- case 'darwin':
13
- return 'macos';
14
- case 'linux':
15
- return 'linux';
16
- case 'win32':
17
- return 'windows';
18
- case 'freebsd':
19
- case 'openbsd':
20
- case 'netbsd':
21
- case 'sunos':
22
- return platform;
23
- default:
24
- return 'unknown';
25
- }
26
- }
27
- function isSupportedHost(hostOs) {
28
- return hostOs === 'macos' || hostOs === 'linux' || hostOs === 'windows';
29
- }
30
- function firstVersionToken(raw) {
31
- if (!raw)
32
- return null;
33
- const match = String(raw).match(/(\d+(?:\.\d+)+|\d+)/);
34
- return match?.[1] ?? null;
35
- }
36
- function probeCommand(command, args, timeoutMs = 2000) {
37
- try {
38
- const result = spawnSync(command, args, { encoding: 'utf8', timeout: timeoutMs, stdio: ['ignore', 'pipe', 'pipe'] });
39
- const raw = `${result.stdout || ''}${result.stderr || ''}`.trim() || null;
40
- return {
41
- ok: result.status === 0,
42
- raw,
43
- parsedVersion: firstVersionToken(raw)
44
- };
45
- }
46
- catch {
47
- return { ok: false, raw: null, parsedVersion: null };
48
- }
49
- }
50
- function makeFailure(code, platform, message, opts = {}) {
51
- return {
52
- code,
53
- platform,
54
- tool: opts.tool ?? null,
55
- message,
56
- searchedLocations: opts.searchedLocations ?? [],
57
- selectedProvider: opts.selectedProvider ?? null,
58
- rawVersion: opts.rawVersion ?? null,
59
- remediation: opts.remediation ?? []
60
- };
61
- }
62
- function makeToolEntry(resolvedPath, discoverySource, rawVersionOutput, validationStatus) {
63
- return {
64
- resolvedPath,
65
- discoverySource,
66
- parsedVersion: firstVersionToken(rawVersionOutput),
67
- rawVersionOutput,
68
- validationStatus
69
- };
70
- }
71
- function describeAdbDiscovery(adbCmd) {
72
- const searchedLocations = ['ADB_PATH', 'ANDROID_SDK_ROOT/platform-tools/adb', 'ANDROID_HOME/platform-tools/adb', '~/Library/Android/sdk/platform-tools/adb', 'PATH'];
73
- if (process.env.ADB_PATH && process.env.ADB_PATH.trim())
74
- return { discoverySource: 'ADB_PATH', searchedLocations };
75
- if (process.env.ANDROID_SDK_ROOT)
76
- return { discoverySource: 'ANDROID_SDK_ROOT', searchedLocations };
77
- if (process.env.ANDROID_HOME)
78
- return { discoverySource: 'ANDROID_HOME', searchedLocations };
79
- if (adbCmd.includes('Library/Android/sdk'))
80
- return { discoverySource: 'HOME_SDK', searchedLocations };
81
- if (adbCmd === 'adb')
82
- return { discoverySource: 'PATH_OR_FALLBACK', searchedLocations };
83
- return { discoverySource: 'PATH', searchedLocations };
84
- }
85
- function describeXcrunDiscovery(xcrunCmd) {
86
- const searchedLocations = ['XCRUN_PATH', 'PATH'];
87
- if (process.env.XCRUN_PATH && process.env.XCRUN_PATH.trim())
88
- return { discoverySource: 'XCRUN_PATH', searchedLocations };
89
- return { discoverySource: xcrunCmd === 'xcrun' ? 'PATH' : 'PATH', searchedLocations };
90
- }
91
- function describeIdbDiscovery(idbCmd) {
92
- const searchedLocations = ['MCP_IDB_PATH', 'IDB_PATH', 'mcp.config.json', '~/.mcp/config.json', 'PATH', '/opt/homebrew/bin/idb', '/usr/local/bin/idb'];
93
- if (process.env.MCP_IDB_PATH && process.env.MCP_IDB_PATH.trim())
94
- return { discoverySource: 'MCP_IDB_PATH', searchedLocations };
95
- if (process.env.IDB_PATH && process.env.IDB_PATH.trim())
96
- return { discoverySource: 'IDB_PATH', searchedLocations };
97
- return { discoverySource: idbCmd === 'idb' ? 'PATH_OR_FALLBACK' : 'PATH', searchedLocations };
98
- }
99
- function describeJavaDiscovery(javaHome) {
100
- const searchedLocations = ['GRADLE_JAVA_HOME', 'JAVA_HOME', 'GRADLE_HOME', 'detectJavaHome'];
101
- if (process.env.GRADLE_JAVA_HOME && process.env.GRADLE_JAVA_HOME.trim())
102
- return { discoverySource: 'GRADLE_JAVA_HOME', searchedLocations };
103
- if (process.env.JAVA_HOME && process.env.JAVA_HOME.trim())
104
- return { discoverySource: 'JAVA_HOME', searchedLocations };
105
- if (process.env.GRADLE_HOME && process.env.GRADLE_HOME.trim())
106
- return { discoverySource: 'GRADLE_HOME', searchedLocations };
107
- return { discoverySource: javaHome ? 'detected' : null, searchedLocations };
108
- }
109
- function resolveJavaBinaryPath(javaHome, hostOs) {
110
- const javaBinary = hostOs === 'windows' ? 'java.exe' : 'java';
111
- return path.join(javaHome, 'bin', javaBinary);
112
- }
113
- function buildUnsupportedHostStatus(hostOs) {
114
- const failureMessage = `Host operating system '${hostOs}' is not supported.`;
115
- const remediation = ['Run Mobile Debug MCP on macOS, Linux, or Windows.'];
116
- const failureAndroid = makeFailure('HOST_OS_UNSUPPORTED', 'android', failureMessage, {
117
- remediation
118
- });
119
- const failureIos = makeFailure('HOST_OS_UNSUPPORTED', 'ios', failureMessage, {
120
- remediation
121
- });
122
- return {
123
- success: false,
124
- status: 'blocked',
125
- adbAvailable: false,
126
- adbVersion: '',
127
- devices: 0,
128
- deviceStates: '',
129
- logsAvailable: false,
130
- envValid: false,
131
- issues: [failureMessage],
132
- appInstalled: undefined,
133
- iosAvailable: false,
134
- iosDevices: 0,
135
- gradleJavaHome: undefined,
136
- gradleValid: false,
137
- gradleFilesChecked: [],
138
- gradleSuggestedFixes: [],
139
- host: { os: hostOs, supported: false },
140
- android: {
141
- status: 'unsupported',
142
- tools: {},
143
- providers: {},
144
- capabilities: {},
145
- devices: [],
146
- failures: [failureAndroid]
147
- },
148
- ios: {
149
- status: 'unsupported',
150
- tools: {},
151
- providers: {},
152
- capabilities: {},
153
- devices: [],
154
- failures: [failureIos]
155
- },
156
- summary: {
157
- overall: 'blocked',
158
- android: { ready: false, summary: `Host operating system '${hostOs}' is not supported.`, blockers: [failureMessage] },
159
- ios: { ready: false, summary: `Host operating system '${hostOs}' is not supported.`, blockers: [failureMessage] },
160
- gradle: { ready: false, summary: 'Gradle status unavailable on unsupported host', blockers: [], suggestedFixes: [] }
161
- }
162
- };
163
- }
164
- function buildAndroidPlatform(android, hostSupported) {
165
- const resolvedAdbCmd = resolveAdbCmd();
166
- const adbDiscovery = describeAdbDiscovery(resolvedAdbCmd);
167
- const adbTool = makeToolEntry(resolvedAdbCmd, adbDiscovery.discoverySource, android.adbVersion || null, android.adbAvailable ? 'valid' : 'invalid');
168
- const adbAvailable = !!android.adbAvailable;
169
- const deviceIssues = android.issues.filter((issue) => /unauthorized|offline|No Android devices connected/i.test(issue));
170
- const envFailure = !android.envValid
171
- ? makeFailure('TOOL_VALIDATION_FAILED', 'android', 'Android environment prerequisites are incomplete.', {
172
- tool: 'adb',
173
- searchedLocations: ['ANDROID_SDK_ROOT', 'ANDROID_HOME', 'PATH'],
174
- selectedProvider: 'adb',
175
- rawVersion: android.adbVersion || null,
176
- remediation: ['Set ANDROID_SDK_ROOT or ANDROID_HOME, or ensure adb is on PATH.']
177
- })
178
- : null;
179
- const adbFailure = !adbAvailable
180
- ? makeFailure(process.env.ADB_PATH && process.env.ADB_PATH.trim() ? 'TOOL_NOT_EXECUTABLE' : 'TOOL_NOT_FOUND', 'android', 'Android adb could not be resolved or executed.', {
181
- tool: 'adb',
182
- searchedLocations: adbDiscovery.searchedLocations,
183
- selectedProvider: null,
184
- rawVersion: android.adbVersion || null,
185
- remediation: [
186
- 'Install Android platform-tools.',
187
- 'Set ADB_PATH or ANDROID_SDK_ROOT/ANDROID_HOME if adb is installed in a non-standard location.'
188
- ]
189
- })
190
- : null;
191
- const deviceFailure = adbAvailable && android.devices === 0
192
- ? makeFailure('DEVICE_NOT_FOUND', 'android', 'No Android devices or emulators are connected.', {
193
- tool: 'adb',
194
- searchedLocations: ['adb devices -l'],
195
- selectedProvider: 'adb',
196
- rawVersion: android.adbVersion || null,
197
- remediation: ['Start an emulator or connect a device, then re-run adb devices.']
198
- })
199
- : null;
200
- const diagnosticFailures = [adbFailure, envFailure, deviceFailure].filter((value) => value !== null);
201
- const status = !hostSupported
202
- ? 'unsupported'
203
- : !adbAvailable
204
- ? 'unavailable'
205
- : (android.devices === 0 || deviceIssues.length > 0 || !android.logsAvailable || !android.envValid)
206
- ? 'partially_ready'
207
- : 'ready';
208
- const deviceEntries = android.devices > 0
209
- ? Array.from({ length: android.devices }, (_, index) => ({
210
- id: `android-device-${index + 1}`,
211
- state: deviceIssues.length > 0 ? 'degraded' : 'connected'
212
- }))
213
- : [];
214
- const deviceDiscoveryAvailable = adbAvailable;
215
- const installAvailable = adbAvailable && android.devices > 0 && deviceIssues.length === 0;
216
- const logAvailable = adbAvailable && android.logsAvailable;
217
- return {
218
- status,
219
- tools: {
220
- adb: adbTool
221
- },
222
- providers: {
223
- adb: { available: adbAvailable, selected: true, tool: 'adb' },
224
- jdwp: { available: adbAvailable && android.devices > 0, selected: false, tool: 'adb' }
225
- },
226
- capabilities: {
227
- device_discovery: {
228
- availability: deviceDiscoveryAvailable,
229
- selectedProvider: deviceDiscoveryAvailable ? 'adb' : null,
230
- blockingFailure: deviceDiscoveryAvailable ? null : diagnosticFailures[0] ?? null
231
- },
232
- install_app: {
233
- availability: installAvailable,
234
- selectedProvider: installAvailable ? 'adb' : null,
235
- blockingFailure: installAvailable ? null : deviceFailure ?? adbFailure ?? envFailure
236
- },
237
- launch_app: {
238
- availability: installAvailable,
239
- selectedProvider: installAvailable ? 'adb' : null,
240
- blockingFailure: installAvailable ? null : deviceFailure ?? adbFailure ?? envFailure
241
- },
242
- ui_interaction: {
243
- availability: installAvailable,
244
- selectedProvider: installAvailable ? 'adb' : null,
245
- blockingFailure: installAvailable ? null : deviceFailure ?? adbFailure ?? envFailure
246
- },
247
- screenshot: {
248
- availability: installAvailable,
249
- selectedProvider: installAvailable ? 'adb' : null,
250
- blockingFailure: installAvailable ? null : deviceFailure ?? adbFailure ?? envFailure
251
- },
252
- log_capture: {
253
- availability: logAvailable,
254
- selectedProvider: logAvailable ? 'adb' : null,
255
- blockingFailure: logAvailable ? null : adbFailure ?? envFailure
256
- },
257
- debug: {
258
- availability: adbAvailable && android.devices > 0,
259
- selectedProvider: adbAvailable && android.devices > 0 ? 'JDWP' : null,
260
- blockingFailure: adbAvailable && android.devices > 0 ? null : deviceFailure ?? adbFailure ?? envFailure
261
- }
262
- },
263
- devices: deviceEntries,
264
- failures: diagnosticFailures
265
- };
266
- }
267
- function buildIOSPlatform(ios, hostSupported, hostOs) {
268
- const platformUnsupported = !hostSupported || hostOs === 'linux' || hostOs === 'windows';
269
- if (platformUnsupported) {
270
- return {
271
- status: 'unsupported',
272
- tools: {},
273
- providers: {},
274
- capabilities: {},
275
- devices: [],
276
- failures: [
277
- makeFailure('PLATFORM_UNAVAILABLE', 'ios', 'iOS tooling is only supported on macOS.', {
278
- tool: null,
279
- searchedLocations: [],
280
- selectedProvider: null,
281
- rawVersion: null,
282
- remediation: ['Run Mobile Debug MCP on macOS for iOS toolchain discovery.']
283
- })
284
- ]
285
- };
286
- }
287
- const xcrunCmd = getXcrunCmd();
288
- const xcrunProbe = ios.iosAvailable ? probeCommand(xcrunCmd, ['--version']) : { ok: false, raw: null, parsedVersion: null };
289
- const idbCmd = getIdbCmd();
290
- const idbProbe = hostSupported && hostOs === 'macos' ? probeIdb(idbCmd) : { ok: false, raw: null, parsedVersion: null };
291
- const idbCompanionProbe = hostSupported && hostOs === 'macos' ? probeCommand('idb_companion', ['--version']) : { ok: false, raw: null, parsedVersion: null };
292
- const xcrunTool = makeToolEntry(xcrunCmd, describeXcrunDiscovery(xcrunCmd).discoverySource, xcrunProbe.raw, xcrunProbe.ok ? 'valid' : 'invalid');
293
- const idbTool = makeToolEntry(idbCmd, describeIdbDiscovery(idbCmd).discoverySource, idbProbe.raw, idbProbe.ok ? 'valid' : 'invalid');
294
- const idbCompanionTool = makeToolEntry('idb_companion', 'PATH', idbCompanionProbe.raw, idbCompanionProbe.ok ? 'valid' : 'invalid');
295
- const lldbTool = makeToolEntry('xcrun lldb', 'xcrun', xcrunProbe.raw, xcrunProbe.ok ? 'valid' : 'invalid');
296
- const simctlAvailable = !!ios.iosAvailable;
297
- const idbAvailable = !!idbProbe.ok;
298
- const bootedDevices = ios.iosDevices > 0
299
- ? Array.from({ length: ios.iosDevices }, (_, index) => ({
300
- id: `ios-simulator-${index + 1}`,
301
- state: 'booted'
302
- }))
303
- : [];
304
- const platformUnavailableFailure = !platformUnsupported && !simctlAvailable
305
- ? makeFailure('PLATFORM_UNAVAILABLE', 'ios', 'iOS tooling is unavailable on this host.', {
306
- tool: 'xcrun',
307
- searchedLocations: describeXcrunDiscovery(xcrunCmd).searchedLocations,
308
- selectedProvider: null,
309
- rawVersion: xcrunProbe.raw,
310
- remediation: ['Install Xcode Command Line Tools and ensure xcrun is on PATH.']
311
- })
312
- : null;
313
- const deviceFailure = simctlAvailable && !bootedDevices.length
314
- ? makeFailure('DEVICE_NOT_FOUND', 'ios', 'No iOS simulators are booted.', {
315
- tool: 'simctl',
316
- searchedLocations: ['xcrun simctl list devices booted --json'],
317
- selectedProvider: 'simctl',
318
- rawVersion: xcrunProbe.raw,
319
- remediation: ['Boot a simulator in Xcode or via xcrun simctl boot.']
320
- })
321
- : null;
322
- const selectedInstallProvider = idbAvailable ? 'idb' : simctlAvailable ? 'simctl' : null;
323
- const selectedDebugProvider = simctlAvailable ? 'LLDB' : null;
324
- const selectedDiscoveryProvider = idbAvailable ? 'idb' : simctlAvailable ? 'simctl' : null;
325
- const status = platformUnsupported
326
- ? 'unsupported'
327
- : !simctlAvailable
328
- ? 'unavailable'
329
- : !bootedDevices.length
330
- ? 'partially_ready'
331
- : 'ready';
332
- const iosFailure = platformUnsupported
333
- ? makeFailure('PLATFORM_UNAVAILABLE', 'ios', 'iOS tooling is only supported on macOS.', {
334
- tool: null,
335
- searchedLocations: [],
336
- selectedProvider: null,
337
- rawVersion: null,
338
- remediation: ['Run Mobile Debug MCP on macOS for iOS toolchain discovery.']
339
- })
340
- : platformUnavailableFailure ?? deviceFailure ?? null;
341
- const failureList = [iosFailure].filter((value) => value !== null);
342
- return {
343
- status,
344
- tools: {
345
- xcrun: xcrunTool,
346
- idb: idbTool,
347
- idb_companion: idbCompanionTool,
348
- lldb: lldbTool
349
- },
350
- providers: {
351
- idb: { available: idbAvailable, selected: selectedInstallProvider === 'idb', tool: 'idb' },
352
- simctl: { available: simctlAvailable, selected: selectedInstallProvider === 'simctl', tool: 'xcrun' },
353
- lldb: { available: simctlAvailable, selected: selectedDebugProvider === 'LLDB', tool: 'xcrun' }
354
- },
355
- capabilities: {
356
- device_discovery: {
357
- availability: !!selectedDiscoveryProvider,
358
- selectedProvider: selectedDiscoveryProvider,
359
- blockingFailure: selectedDiscoveryProvider ? null : iosFailure
360
- },
361
- install_app: {
362
- availability: !!selectedInstallProvider && bootedDevices.length > 0,
363
- selectedProvider: selectedInstallProvider,
364
- blockingFailure: selectedInstallProvider && bootedDevices.length > 0 ? null : deviceFailure ?? iosFailure
365
- },
366
- launch_app: {
367
- availability: !!selectedInstallProvider && bootedDevices.length > 0,
368
- selectedProvider: selectedInstallProvider,
369
- blockingFailure: selectedInstallProvider && bootedDevices.length > 0 ? null : deviceFailure ?? iosFailure
370
- },
371
- ui_interaction: {
372
- availability: !!selectedInstallProvider && bootedDevices.length > 0,
373
- selectedProvider: selectedInstallProvider,
374
- blockingFailure: selectedInstallProvider && bootedDevices.length > 0 ? null : deviceFailure ?? iosFailure
375
- },
376
- screenshot: {
377
- availability: !!selectedInstallProvider && bootedDevices.length > 0,
378
- selectedProvider: selectedInstallProvider,
379
- blockingFailure: selectedInstallProvider && bootedDevices.length > 0 ? null : deviceFailure ?? iosFailure
380
- },
381
- log_capture: {
382
- availability: simctlAvailable && bootedDevices.length > 0,
383
- selectedProvider: simctlAvailable ? 'simctl' : null,
384
- blockingFailure: simctlAvailable && bootedDevices.length > 0 ? null : deviceFailure ?? iosFailure
385
- },
386
- debug: {
387
- availability: !!selectedDebugProvider,
388
- selectedProvider: selectedDebugProvider,
389
- blockingFailure: selectedDebugProvider ? null : iosFailure
390
- }
391
- },
392
- devices: bootedDevices,
393
- failures: failureList
394
- };
395
- }
396
- function buildLegacySummary(androidStatus, iosStatus, gradle) {
397
- const androidReady = androidStatus.status === 'ready';
398
- const iosReady = iosStatus.status === 'ready';
399
- const gradleReady = (gradle.issues || []).length === 0;
400
- const overallStatus = (androidReady || iosReady || gradleReady)
401
- ? ((androidReady && iosReady && gradleReady) ? 'ready' : 'degraded')
402
- : 'blocked';
403
- return {
404
- overall: overallStatus,
405
- android: {
406
- ready: androidReady,
407
- summary: androidStatus.status === 'ready'
408
- ? `${androidStatus.devices.length} Android device(s) connected; log access available`
409
- : androidStatus.status === 'partially_ready'
410
- ? 'Android toolchain available but device-dependent capabilities are limited'
411
- : androidStatus.status === 'unsupported'
412
- ? 'Android unsupported on this host'
413
- : 'ADB unavailable',
414
- blockers: androidStatus.failures.map((failure) => failure.message)
415
- },
416
- ios: {
417
- ready: iosReady,
418
- summary: iosStatus.status === 'ready'
419
- ? `${iosStatus.devices.length} iOS simulator(s) booted`
420
- : iosStatus.status === 'partially_ready'
421
- ? 'iOS toolchain available but device-dependent capabilities are limited'
422
- : iosStatus.status === 'unsupported'
423
- ? 'iOS unsupported on this host'
424
- : 'xcrun unavailable',
425
- blockers: iosStatus.failures.map((failure) => failure.message)
426
- },
427
- gradle: {
428
- ready: gradleReady,
429
- summary: !gradle.gradleJavaHome
430
- ? 'No explicit Gradle JDK override detected'
431
- : gradleReady
432
- ? `Gradle JDK configured at ${gradle.gradleJavaHome}`
433
- : `Gradle JDK override invalid: ${gradle.gradleJavaHome}`,
434
- blockers: gradle.issues || [],
435
- suggestedFixes: gradle.suggestedFixes || []
436
- }
437
- };
438
- }
5
+ import { buildAndroidPlatform } from './android-status.js';
6
+ import { buildIOSPlatform } from './ios-status.js';
7
+ import { buildLegacySummary } from './status-summary.js';
8
+ import { buildUnsupportedHostStatus } from './unsupported-status.js';
9
+ import { normalizeHostOs, isSupportedHost, probeCommand, makeToolEntry, describeJavaDiscovery, resolveJavaBinaryPath } from './probes.js';
439
10
  export async function getSystemStatus() {
440
11
  const hostOs = normalizeHostOs((process.env.MOBILE_DEBUG_MCP_HOST_OS || process.platform));
441
12
  if (!isSupportedHost(hostOs)) {
@@ -458,10 +29,7 @@ export async function getSystemStatus() {
458
29
  const androidReady = androidRaw.adbAvailable && androidRaw.devices > 0 && !androidRaw.issues.some((issue) => /unauthorized|offline/i.test(issue));
459
30
  const iosReady = hostOs === 'macos' ? (iosRaw.iosAvailable && iosRaw.iosDevices > 0) : false;
460
31
  const overallStatus = success ? 'ready' : (androidReady || iosReady ? 'degraded' : 'blocked');
461
- const javaHome = gradle.gradleJavaHome || (await detectJavaHome().catch(() => undefined));
462
- const javaBin = javaHome ? resolveJavaBinaryPath(javaHome, hostOs) : null;
463
- const javaProbe = javaBin ? probeCommand(javaBin, ['-version']) : { ok: false, raw: null, parsedVersion: null };
464
- const javaTool = makeToolEntry(javaBin, describeJavaDiscovery(javaHome ?? null).discoverySource, javaProbe.raw, javaProbe.ok ? 'valid' : (javaHome ? 'invalid' : 'missing'));
32
+ const javaTool = await javaStatus(gradle, hostOs);
465
33
  return {
466
34
  success,
467
35
  status: overallStatus,
@@ -518,3 +86,10 @@ export async function getSystemStatus() {
518
86
  };
519
87
  }
520
88
  }
89
+ async function javaStatus(gradle, hostOs) {
90
+ const javaHome = gradle.gradleJavaHome || (await detectJavaHome().catch(() => undefined));
91
+ const javaBin = javaHome ? resolveJavaBinaryPath(javaHome, hostOs) : null;
92
+ const javaProbe = javaBin ? probeCommand(javaBin, ['-version']) : { ok: false, raw: null, parsedVersion: null };
93
+ const javaTool = makeToolEntry(javaBin, describeJavaDiscovery(javaHome ?? null).discoverySource, javaProbe.raw, javaProbe.ok ? 'valid' : (javaHome ? 'invalid' : 'missing'));
94
+ return javaTool;
95
+ }
@@ -0,0 +1,132 @@
1
+ import { getIdbCmd, getXcrunCmd } from '../utils/ios/utils.js';
2
+ import { probeIdb } from '../utils/cli/idb/idb-helper.js';
3
+ import { probeCommand, makeFailure, makeToolEntry, describeXcrunDiscovery, describeIdbDiscovery } from './probes.js';
4
+ export function buildIOSPlatform(ios, hostSupported, hostOs) {
5
+ const platformUnsupported = !hostSupported || hostOs === 'linux' || hostOs === 'windows';
6
+ if (platformUnsupported) {
7
+ return {
8
+ status: 'unsupported',
9
+ tools: {},
10
+ providers: {},
11
+ capabilities: {},
12
+ devices: [],
13
+ failures: [
14
+ makeFailure('PLATFORM_UNAVAILABLE', 'ios', 'iOS tooling is only supported on macOS.', {
15
+ tool: null,
16
+ searchedLocations: [],
17
+ selectedProvider: null,
18
+ rawVersion: null,
19
+ remediation: ['Run Mobile Debug MCP on macOS for iOS toolchain discovery.']
20
+ })
21
+ ]
22
+ };
23
+ }
24
+ const { xcrunCmd, xcrunProbe, idbProbe, xcrunTool, idbTool, idbCompanionTool, lldbTool } = iosTools(ios, hostSupported, hostOs);
25
+ const simctlAvailable = !!ios.iosAvailable;
26
+ const idbAvailable = !!idbProbe.ok;
27
+ const bootedDevices = ios.iosDevices > 0
28
+ ? Array.from({ length: ios.iosDevices }, (_, index) => ({
29
+ id: `ios-simulator-${index + 1}`,
30
+ state: 'booted'
31
+ }))
32
+ : [];
33
+ const { platformUnavailableFailure, deviceFailure } = iosFailures(platformUnsupported, simctlAvailable, bootedDevices.length, xcrunCmd, xcrunProbe.raw);
34
+ const selectedInstallProvider = idbAvailable ? 'idb' : simctlAvailable ? 'simctl' : null;
35
+ const selectedDebugProvider = simctlAvailable ? 'LLDB' : null;
36
+ const selectedDiscoveryProvider = idbAvailable ? 'idb' : simctlAvailable ? 'simctl' : null;
37
+ const status = platformUnsupported
38
+ ? 'unsupported'
39
+ : !simctlAvailable
40
+ ? 'unavailable'
41
+ : !bootedDevices.length
42
+ ? 'partially_ready'
43
+ : 'ready';
44
+ const iosFailure = platformUnsupported
45
+ ? makeFailure('PLATFORM_UNAVAILABLE', 'ios', 'iOS tooling is only supported on macOS.', {
46
+ tool: null,
47
+ searchedLocations: [],
48
+ selectedProvider: null,
49
+ rawVersion: null,
50
+ remediation: ['Run Mobile Debug MCP on macOS for iOS toolchain discovery.']
51
+ })
52
+ : platformUnavailableFailure ?? deviceFailure ?? null;
53
+ const failureList = [iosFailure].filter((value) => value !== null);
54
+ return {
55
+ status,
56
+ tools: {
57
+ xcrun: xcrunTool,
58
+ idb: idbTool,
59
+ idb_companion: idbCompanionTool,
60
+ lldb: lldbTool
61
+ },
62
+ providers: {
63
+ idb: { available: idbAvailable, selected: selectedInstallProvider === 'idb', tool: 'idb' },
64
+ simctl: { available: simctlAvailable, selected: selectedInstallProvider === 'simctl', tool: 'xcrun' },
65
+ lldb: { available: simctlAvailable, selected: selectedDebugProvider === 'LLDB', tool: 'xcrun' }
66
+ },
67
+ capabilities: iosCapabilities(selectedDiscoveryProvider, selectedInstallProvider, selectedDebugProvider, simctlAvailable, bootedDevices.length, deviceFailure, iosFailure),
68
+ devices: bootedDevices,
69
+ failures: failureList
70
+ };
71
+ }
72
+ function iosTools(ios, hostSupported, hostOs) {
73
+ const xcrunCmd = getXcrunCmd();
74
+ const xcrunProbe = ios.iosAvailable ? probeCommand(xcrunCmd, ['--version']) : { ok: false, raw: null, parsedVersion: null };
75
+ const idbCmd = getIdbCmd();
76
+ const idbProbe = hostSupported && hostOs === 'macos' ? probeIdb(idbCmd) : { ok: false, raw: null, parsedVersion: null };
77
+ const idbCompanionProbe = hostSupported && hostOs === 'macos' ? probeCommand('idb_companion', ['--version']) : { ok: false, raw: null, parsedVersion: null };
78
+ const xcrunTool = makeToolEntry(xcrunCmd, describeXcrunDiscovery(xcrunCmd).discoverySource, xcrunProbe.raw, xcrunProbe.ok ? 'valid' : 'invalid');
79
+ const idbTool = makeToolEntry(idbCmd, describeIdbDiscovery(idbCmd).discoverySource, idbProbe.raw, idbProbe.ok ? 'valid' : 'invalid');
80
+ const idbCompanionTool = makeToolEntry('idb_companion', 'PATH', idbCompanionProbe.raw, idbCompanionProbe.ok ? 'valid' : 'invalid');
81
+ const lldbTool = makeToolEntry('xcrun lldb', 'xcrun', xcrunProbe.raw, xcrunProbe.ok ? 'valid' : 'invalid');
82
+ return { xcrunCmd, xcrunProbe, idbProbe, xcrunTool, idbTool, idbCompanionTool, lldbTool };
83
+ }
84
+ function iosFailures(platformUnsupported, simctlAvailable, deviceCount, xcrunCmd, rawVersion) {
85
+ const platformUnavailableFailure = !platformUnsupported && !simctlAvailable
86
+ ? makeFailure('PLATFORM_UNAVAILABLE', 'ios', 'iOS tooling is unavailable on this host.', {
87
+ tool: 'xcrun',
88
+ searchedLocations: describeXcrunDiscovery(xcrunCmd).searchedLocations,
89
+ selectedProvider: null,
90
+ rawVersion: rawVersion,
91
+ remediation: ['Install Xcode Command Line Tools and ensure xcrun is on PATH.']
92
+ })
93
+ : null;
94
+ const deviceFailure = simctlAvailable && !deviceCount
95
+ ? makeFailure('DEVICE_NOT_FOUND', 'ios', 'No iOS simulators are booted.', {
96
+ tool: 'simctl',
97
+ searchedLocations: ['xcrun simctl list devices booted --json'],
98
+ selectedProvider: 'simctl',
99
+ rawVersion: rawVersion,
100
+ remediation: ['Boot a simulator in Xcode or via xcrun simctl boot.']
101
+ })
102
+ : null;
103
+ return { platformUnavailableFailure, deviceFailure };
104
+ }
105
+ function iosCapabilities(selectedDiscoveryProvider, selectedInstallProvider, selectedDebugProvider, simctlAvailable, deviceCount, deviceFailure, iosFailure) {
106
+ const applicationCapability = {
107
+ availability: !!selectedInstallProvider && deviceCount > 0,
108
+ selectedProvider: selectedInstallProvider,
109
+ blockingFailure: selectedInstallProvider && deviceCount > 0 ? null : deviceFailure ?? iosFailure
110
+ };
111
+ return {
112
+ device_discovery: {
113
+ availability: !!selectedDiscoveryProvider,
114
+ selectedProvider: selectedDiscoveryProvider,
115
+ blockingFailure: selectedDiscoveryProvider ? null : iosFailure
116
+ },
117
+ install_app: { ...applicationCapability },
118
+ launch_app: { ...applicationCapability },
119
+ ui_interaction: { ...applicationCapability },
120
+ screenshot: { ...applicationCapability },
121
+ log_capture: {
122
+ availability: simctlAvailable && deviceCount > 0,
123
+ selectedProvider: simctlAvailable ? 'simctl' : null,
124
+ blockingFailure: simctlAvailable && deviceCount > 0 ? null : deviceFailure ?? iosFailure
125
+ },
126
+ debug: {
127
+ availability: !!selectedDebugProvider,
128
+ selectedProvider: selectedDebugProvider,
129
+ blockingFailure: selectedDebugProvider ? null : iosFailure
130
+ }
131
+ };
132
+ }
@@ -12,14 +12,7 @@ export async function checkIOS() {
12
12
  try {
13
13
  const simOut = execSync(`${xcrun} simctl list devices booted --json`, { encoding: 'utf8', timeout: 1500, stdio: ['ignore', 'pipe', 'ignore'] });
14
14
  try {
15
- const data = JSON.parse(simOut);
16
- let count = 0;
17
- for (const k in data.devices) {
18
- const arr = data.devices[k];
19
- if (Array.isArray(arr))
20
- count += arr.filter((d) => (d.state || '').toLowerCase() === 'booted').length;
21
- }
22
- iosDevices = count;
15
+ iosDevices = countBooted(simOut);
23
16
  }
24
17
  catch {
25
18
  // Some xcrun builds include extra text around the JSON response.
@@ -44,3 +37,13 @@ export async function checkIOS() {
44
37
  }
45
38
  return { iosAvailable, iosDevices, issues };
46
39
  }
40
+ function countBooted(simOut) {
41
+ const data = JSON.parse(simOut);
42
+ let count = 0;
43
+ for (const k in data.devices) {
44
+ const arr = data.devices[k];
45
+ if (Array.isArray(arr))
46
+ count += arr.filter((d) => (d.state || '').toLowerCase() === 'booted').length;
47
+ }
48
+ return count;
49
+ }
@@ -0,0 +1 @@
1
+ export {};