mobile-debug-mcp 0.29.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -75,3 +75,16 @@ For test authoring details, rely on the `test-authoring` skill package rather th
75
75
  ## Notes for maintainers
76
76
 
77
77
  This file is intentionally short. Keep task-specific guidance in `skills/...` so multiple agent systems can reuse the same instructions.
78
+
79
+ ## Testing
80
+
81
+ - `npm run test:unit` runs every automated unit test under `test/unit/...`
82
+ - `npm run test:device` runs the automated device smoke checks under `test/device/automated/...`
83
+ - `npm run verify` runs the default maintainer verification sequence: lint, build, and unit tests
84
+ - Manual and debug-oriented device scripts live under `test/device/manual/...` and are not part of the default test commands
85
+
86
+ ## Utility Scripts
87
+
88
+ - `npm run healthcheck` runs the `idb`/tooling healthcheck helper from `src/utils/cli/idb/check-idb.ts`
89
+ - `npm run install-idb` runs the guided `idb` installer helper from `src/utils/cli/idb/install-idb.ts`
90
+ - `npm run preflight-ios` runs the iOS preflight helper from `src/utils/cli/ios/preflight-ios.ts`
package/README.md CHANGED
@@ -16,7 +16,11 @@ A minimal, secure MCP server for AI-assisted mobile development. Build, install,
16
16
  - Xcode command-line tools for iOS support
17
17
  - [idb](https://github.com/facebook/idb) for iOS device support
18
18
 
19
- ## Configuration example
19
+ ## Configuration
20
+
21
+ <details>
22
+
23
+ <summary>Android Studio</summary>
20
24
 
21
25
  ```json
22
26
  {
@@ -29,7 +33,45 @@ A minimal, secure MCP server for AI-assisted mobile development. Build, install,
29
33
  }
30
34
  }
31
35
  ```
32
- You will need to add ADB_PATH for Android and XCRUN_PATH and IDB_PATH for iOS.
36
+
37
+ </details>
38
+
39
+ <details>
40
+
41
+ <summary>Copilot</summary>
42
+
43
+ ```json
44
+ {
45
+ "mcpServers": {
46
+ "mobile-debug": {
47
+ "command": "npx",
48
+ "args": ["--yes","mobile-debug-mcp","server"],
49
+ "env": { "ADB_PATH": "/path/to/adb", "XCRUN_PATH": "/usr/bin/xcrun", "IDB_PATH": "/path/to/idb" }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ </details>
56
+
57
+ <details>
58
+
59
+ <summary>Codex</summary>
60
+
61
+ Use STDIO
62
+
63
+ command: npx
64
+
65
+ args:
66
+ * --yes
67
+ * mobile-debug-mcp
68
+
69
+ environment variables:
70
+ * ADB_PATH: /path/to/adb
71
+ * XCRUN_PATH: /usr/bin/xcrun
72
+ * IDC_PATH: /path/to/idb"
73
+
74
+ </details>
33
75
 
34
76
  ## Usage
35
77
 
@@ -48,25 +90,6 @@ Feature building:
48
90
  - Agents: [AGENTS.md](AGENTS.md) — cold-start guidance for autonomous agents entering the public repo
49
91
  - Skills: [skills/README.md](skills/README.md) — portable Markdown skill packages for agents such as Copilot, Codex, Claude, or custom systems
50
92
 
51
- ## Testing
52
-
53
- - `npm run test:unit` runs every automated unit test under `test/unit/...`
54
- - `npm run test:device` runs the automated device smoke checks under `test/device/automated/...`
55
- - `npm run verify` runs the default maintainer verification sequence: lint, build, and unit tests
56
- - Manual and debug-oriented device scripts live under `test/device/manual/...` and are not part of the default test commands
57
-
58
- ## Utility Scripts
59
-
60
- - `npm run healthcheck` runs the `idb`/tooling healthcheck helper from `src/utils/cli/idb/check-idb.ts`
61
- - `npm run install-idb` runs the guided `idb` installer helper from `src/utils/cli/idb/install-idb.ts`
62
- - `npm run preflight-ios` runs the iOS preflight helper from `src/utils/cli/ios/preflight-ios.ts`
63
-
64
- ## Agent skills
65
-
66
- - `skills/mcp-builder/` contains reusable build/install guidance for agents
67
- - `skills/test-authoring/` contains reusable test-creation guidance aligned to this repo's current test structure
68
- - Skills are written as plain Markdown packages so they can be consumed by different agent systems rather than one vendor-specific runtime
69
-
70
93
  ## License
71
94
 
72
95
  MIT
@@ -205,6 +205,9 @@ export class ToolsInteract {
205
205
  }
206
206
  return null;
207
207
  }
208
+ static _uiChangeSignaturesEqual(left, right) {
209
+ return left.hierarchy === right.hierarchy && left.text === right.text && left.state === right.state;
210
+ }
208
211
  static _resolvedTargetFromElement(elementId, element, index) {
209
212
  return {
210
213
  elementId,
@@ -1708,13 +1711,16 @@ export class ToolsInteract {
1708
1711
  }
1709
1712
  };
1710
1713
  }
1711
- static async waitForUIChangeHandler({ platform, deviceId, timeout_ms = 60000, stability_window_ms = 250, expected_change }) {
1714
+ static async waitForUIChangeHandler({ platform, deviceId, timeout_ms = 60000, stability_window_ms = 300, expected_change }) {
1712
1715
  const start = Date.now();
1713
1716
  const pollIntervalMs = 300;
1714
- const stabilityWindow = Math.max(0, typeof stability_window_ms === 'number' ? stability_window_ms : 250);
1717
+ const stabilityWindow = Math.max(0, typeof stability_window_ms === 'number' ? stability_window_ms : 300);
1715
1718
  let baseline = null;
1716
1719
  let lastObservedRevision = null;
1717
1720
  let lastLoadingState = null;
1721
+ let candidateSignatures = null;
1722
+ let candidateObservedChange = null;
1723
+ let candidateSinceMs = null;
1718
1724
  while (Date.now() - start < timeout_ms) {
1719
1725
  try {
1720
1726
  const tree = await ToolsObserve.getUITreeHandler({ platform, deviceId });
@@ -1727,30 +1733,29 @@ export class ToolsInteract {
1727
1733
  else {
1728
1734
  const observedChange = ToolsInteract._matchesUiChange(expected_change, baseline, signatures);
1729
1735
  if (observedChange) {
1730
- if (stabilityWindow > 0) {
1731
- await new Promise(resolve => setTimeout(resolve, stabilityWindow));
1732
- const confirmTree = await ToolsObserve.getUITreeHandler({ platform, deviceId });
1733
- const confirmSignatures = ToolsInteract._buildUiChangeSignatures(confirmTree);
1734
- const confirmChange = ToolsInteract._matchesUiChange(expected_change, baseline, confirmSignatures);
1735
- if (!confirmChange || confirmSignatures.hierarchy !== signatures.hierarchy || confirmSignatures.text !== signatures.text || confirmSignatures.state !== signatures.state) {
1736
- lastObservedRevision = typeof confirmTree?.snapshot_revision === 'number' ? confirmTree.snapshot_revision : lastObservedRevision;
1737
- lastLoadingState = confirmTree?.loading_state ?? lastLoadingState;
1738
- await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
1739
- continue;
1740
- }
1741
- lastObservedRevision = typeof confirmTree?.snapshot_revision === 'number' ? confirmTree.snapshot_revision : lastObservedRevision;
1742
- lastLoadingState = confirmTree?.loading_state ?? lastLoadingState;
1736
+ if (!candidateSignatures || !ToolsInteract._uiChangeSignaturesEqual(candidateSignatures, signatures) || candidateObservedChange !== observedChange) {
1737
+ candidateSignatures = signatures;
1738
+ candidateObservedChange = observedChange;
1739
+ candidateSinceMs = Date.now();
1743
1740
  }
1744
- return {
1745
- success: true,
1746
- observed_change: observedChange,
1747
- snapshot_revision: lastObservedRevision ?? undefined,
1748
- timeout: false,
1749
- elapsed_ms: Date.now() - start,
1750
- expected_change,
1751
- loading_state: lastLoadingState ?? null,
1752
- reason: 'UI change observed'
1753
- };
1741
+ const stableForMs = candidateSinceMs === null ? 0 : Date.now() - candidateSinceMs;
1742
+ if (stabilityWindow === 0 || stableForMs >= stabilityWindow) {
1743
+ return {
1744
+ success: true,
1745
+ observed_change: candidateObservedChange ?? observedChange,
1746
+ snapshot_revision: lastObservedRevision ?? undefined,
1747
+ timeout: false,
1748
+ elapsed_ms: Date.now() - start,
1749
+ expected_change,
1750
+ loading_state: lastLoadingState ?? null,
1751
+ reason: 'UI change observed'
1752
+ };
1753
+ }
1754
+ }
1755
+ else {
1756
+ candidateSignatures = null;
1757
+ candidateObservedChange = null;
1758
+ candidateSinceMs = null;
1754
1759
  }
1755
1760
  }
1756
1761
  }
@@ -391,7 +391,7 @@ Failure Handling:
391
391
  deviceId: { type: 'string', description: 'Optional device id/udid to target' },
392
392
  expected_change: { type: 'string', enum: ['hierarchy_diff', 'text_change', 'state_change'], description: 'Optional type of UI change to wait for' },
393
393
  timeout_ms: { type: 'number', description: 'Timeout in ms to wait for change (default 60000)', default: 60000 },
394
- stability_window_ms: { type: 'number', description: 'How long the change must remain stable before success (default 250)', default: 250 }
394
+ stability_window_ms: { type: 'number', description: 'How long the change must remain stable before success (default 300)', default: 300 }
395
395
  }
396
396
  }
397
397
  },
@@ -266,7 +266,7 @@ async function handleWaitForUIChange(args) {
266
266
  const platform = getStringArg(args, 'platform');
267
267
  const deviceId = getStringArg(args, 'deviceId');
268
268
  const timeout_ms = getNumberArg(args, 'timeout_ms') ?? 60000;
269
- const stability_window_ms = getNumberArg(args, 'stability_window_ms') ?? 250;
269
+ const stability_window_ms = getNumberArg(args, 'stability_window_ms') ?? 300;
270
270
  const expected_change = getStringArg(args, 'expected_change');
271
271
  const res = await ToolsInteract.waitForUIChangeHandler({ platform, deviceId, timeout_ms, stability_window_ms, expected_change });
272
272
  return wrapResponse(res);
@@ -6,7 +6,7 @@ import { handleToolCall } from './server/tool-handlers.js';
6
6
  export { wrapResponse, toolDefinitions, handleToolCall };
7
7
  export const serverInfo = {
8
8
  name: 'mobile-debug-mcp',
9
- version: '0.29.0'
9
+ version: '0.30.0'
10
10
  };
11
11
  export function createServer() {
12
12
  const server = new Server(serverInfo, {
package/docs/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  All notable changes to the **Mobile Debug MCP** project will be documented in this file.
4
4
 
5
+ ## [0.30.0]
6
+ - Folded RFC 013 synchronization semantics into the main spec and aligned the interact docs with the shipped `wait_for_ui_change` behavior.
7
+ - Updated `wait_for_ui_change` to use a 300ms stabilization default and to reset stabilization on new in-place mutations.
8
+ - Validated the in-place UI mutation flow on the Modul8 emulator app, including a delayed state-change case.
9
+
5
10
  ## [0.29.0]
6
11
  - Added empty resource handlers and declared the `resources` capability so Codex MCP discovery can complete the handshake against the published npm package.
7
12
  - Moved the startup healthcheck behind an opt-in flag to keep the stdio protocol channel quiet by default.
package/docs/ROADMAP.md CHANGED
@@ -32,6 +32,7 @@ Track roadmap impact across releases using:
32
32
  - Gesture success rate
33
33
  - Mean time to root cause during debugging
34
34
  - Overall agent task completion rate
35
+ - Reduced sequencing errors in multi-step interaction flows
35
36
 
36
37
  Primary KPI:
37
38
  Higher task success with fewer retries.
@@ -47,10 +48,10 @@ Higher task success with fewer retries.
47
48
  - Better Compose / Custom Control Semantics — Complete (Semantic role enrichment and custom-adjustable inference shipped)
48
49
  - Verification Stabilization and Temporal Convergence — Complete (Temporal verification and convergence logic shipped)
49
50
  - Action Trace and Execution Observability — Complete (Structured execution trace model shipped)
51
+ - Wait and Synchronization Reliability — Complete (RFC 013 folded into the main spec and shipped behavior verified on emulator)
50
52
 
51
53
  ## Current Focus
52
54
 
53
- - Wait and Synchronization Reliability (implementation + tuning)
54
55
  - Actionability Resolution
55
56
  - Adjustable Control Precision Hardening
56
57
 
@@ -74,13 +75,14 @@ Addresses friction around:
74
75
  - environment drift across machines
75
76
  - setup failures blocking first use
76
77
 
77
- ## Scope
78
78
  - Automatic discovery of adb
79
79
  - Automatic discovery of xcrun
80
80
  - idb detection and guided bootstrap support
81
81
  - Startup toolchain validation
82
82
  - Environment health diagnostics / doctor-style checks
83
83
  - Minimal-manual-configuration defaults
84
+ - Runtime device/emulator health signals (crash detection, process lifecycle awareness)
85
+ - App stability monitoring during active sessions
84
86
 
85
87
  ## Expected Impact
86
88
  High.
@@ -97,6 +99,7 @@ High.
97
99
  - Lower environment configuration failures
98
100
  - Faster time-to-first-successful-session
99
101
  - Reduced support/debugging caused by local setup issues
102
+ - Reduced unknown-failure sessions caused by app or emulator instability
100
103
 
101
104
  ## Dependencies
102
105
  Depends on:
@@ -151,7 +154,7 @@ Very high.
151
154
  Blocks or strengthens:
152
155
  - Better Compose / Custom Control Semantics
153
156
  - Pinch to Zoom
154
- - Action Trace Correlation
157
+ - Advanced Trace Correlation and Analysis
155
158
 
156
159
  ---
157
160
 
@@ -212,8 +215,11 @@ Addresses failures where agents:
212
215
  - wait_for_ui_change (hierarchy diff based waiting)
213
216
  - Structured loading state detection
214
217
  - Snapshot revision / staleness metadata
215
- - Focused snapshot views / incremental snapshot diffs
218
+ - Incremental / diff-based snapshot delivery (token-efficient)
219
+ - Focused snapshot scoping (subtree / target-based)
216
220
  - Compose-aware wait robustness improvements
221
+ - Explicit interaction sequencing guidance (tap → wait → verify pattern)
222
+ - Exploration of optional action-level synchronization ergonomics (e.g. implicit stabilization or wait flags)
217
223
 
218
224
  ## Expected Impact
219
225
  Very high.
@@ -231,6 +237,8 @@ Very high.
231
237
  - Fewer retries caused by premature actions
232
238
  - Higher wait success rate for dynamic UI flows
233
239
  - Lower fallback usage to network/log checks
240
+ - Reduced need for manual sequencing by agents in stateful flows
241
+ - Reduced average snapshot size (tokens)
234
242
 
235
243
  ## Dependencies
236
244
  Depends on:
@@ -239,7 +247,7 @@ Depends on:
239
247
 
240
248
  Blocks or strengthens:
241
249
  - Better Compose / Custom Control Semantics
242
- - Action Trace Correlation
250
+ - Advanced Trace Correlation and Analysis
243
251
 
244
252
  ---
245
253
 
@@ -307,6 +315,7 @@ Addresses cases where:
307
315
  - Executable-target preference rules
308
316
  - Actionability confidence metadata
309
317
  - Post-action state verification integration
318
+ - Geometry-aware fallback targeting for weak semantic surfaces (e.g. sliders without accessible nodes)
310
319
 
311
320
  ## Expected Impact
312
321
  High.
@@ -321,6 +330,7 @@ High.
321
330
  - Reduced mis-targeted action failures
322
331
  - Lower retarget retries
323
332
  - Higher first-attempt action success
333
+ - Reduced need for empirical coordinate probing on custom controls
324
334
 
325
335
  ## Dependencies
326
336
  Depends on:
@@ -403,6 +413,7 @@ Addresses friction around:
403
413
  - Drag vs tap adjustment strategy heuristics
404
414
  - Improved value snapping convergence
405
415
  - Control-specific adjustment fallback policies
416
+ - Controlled search strategies for value convergence (e.g. binary / progressive adjustment)
406
417
 
407
418
  ## Expected Impact
408
419
  High.
@@ -465,7 +476,7 @@ Depends on:
465
476
  - Wait and Synchronization Reliability
466
477
 
467
478
  Strengthens:
468
- - Action Trace Correlation
479
+ - Advanced Trace Correlation and Analysis
469
480
 
470
481
  ---
471
482
 
@@ -675,7 +686,7 @@ Interaction Expansion
675
686
  - Pinch to Zoom
676
687
 
677
688
  Deep Observability
678
- - Action Trace Correlation
689
+ - Advanced Trace Correlation and Analysis
679
690
 
680
691
  ## Wave 1 (Current Focus)
681
692
  - Stronger State Verification