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 +13 -0
- package/README.md +44 -21
- package/dist/interact/index.js +30 -25
- package/dist/server/tool-definitions.js +1 -1
- package/dist/server/tool-handlers.js +1 -1
- package/dist/server-core.js +1 -1
- package/docs/CHANGELOG.md +5 -0
- package/docs/ROADMAP.md +18 -7
- package/docs/rfcs/013-wait-and-synchronization-reliability.md +890 -0
- package/docs/rfcs/014-actionability-resolution.md +392 -0
- package/docs/specs/mcp-tooling-spec-v1.md +28 -0
- package/docs/tools/interact.md +6 -0
- package/package.json +1 -1
- package/src/interact/index.ts +29 -24
- package/src/server/tool-definitions.ts +1 -1
- package/src/server/tool-handlers.ts +1 -1
- package/src/server-core.ts +1 -1
- package/test/unit/interact/wait_for_ui_change.test.ts +105 -52
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
|
|
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
|
-
|
|
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
|
package/dist/interact/index.js
CHANGED
|
@@ -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 =
|
|
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 :
|
|
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 (
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
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
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
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
|
|
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') ??
|
|
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);
|
package/dist/server-core.js
CHANGED
|
@@ -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.
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
-
-
|
|
689
|
+
- Advanced Trace Correlation and Analysis
|
|
679
690
|
|
|
680
691
|
## Wave 1 (Current Focus)
|
|
681
692
|
- Stronger State Verification
|