mobile-debug-mcp 0.23.0 → 0.24.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/dist/interact/index.js +133 -57
- package/dist/server/common.js +66 -0
- package/dist/server/tool-definitions.js +921 -0
- package/dist/server/tool-handlers.js +320 -0
- package/dist/server-core.js +4 -801
- package/docs/CHANGELOG.md +3 -0
- package/docs/tools/TOOLS.md +15 -7
- package/docs/tools/interact.md +270 -107
- package/docs/tools/manage.md +39 -38
- package/docs/tools/observe.md +30 -8
- package/docs/tools/system.md +1 -1
- package/package.json +1 -1
- package/src/interact/index.ts +186 -58
- package/src/server/common.ts +95 -0
- package/src/server/tool-definitions.ts +921 -0
- package/src/server/tool-handlers.ts +365 -0
- package/src/server-core.ts +4 -844
- package/src/types.ts +59 -6
- package/test/unit/interact/expect_tools.test.ts +77 -0
- package/test/unit/interact/tap_element.test.ts +23 -6
- package/test/unit/server/contract.test.ts +26 -0
- package/test/unit/server/response_shapes.test.ts +69 -4
package/docs/CHANGELOG.md
CHANGED
package/docs/tools/TOOLS.md
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
# Tools index
|
|
2
2
|
|
|
3
|
-
This repository groups
|
|
3
|
+
This repository groups the MCP tools into four areas aligned with the codebase:
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- [manage](manage.md) — build, install, launch, restart, and device-management tools
|
|
6
|
+
- [observe](observe.md) — screenshots, logs, UI trees, fingerprints, and debug snapshots
|
|
7
|
+
- [interact](interact.md) — UI resolution, actions, waits, and deterministic verification
|
|
8
|
+
- [system](system.md) — environment and health checks
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
- [observe](observe.md) — logs, screenshots and UI inspection tools
|
|
9
|
-
- [interact](interact.md) — UI interaction tools (tap, swipe, type, wait)
|
|
10
|
-
- [system](system.md) — environment and health checks (get_system_status)
|
|
10
|
+
## Agent guidance
|
|
11
11
|
|
|
12
|
-
For
|
|
12
|
+
For interactive flows, the intended deterministic pattern is:
|
|
13
|
+
|
|
14
|
+
**RESOLVE -> ACT -> WAIT (if needed) -> EXPECT**
|
|
15
|
+
|
|
16
|
+
- **wait_for_\*** tools are for resolution and synchronization
|
|
17
|
+
- **expect_\*** tools are for final outcome verification
|
|
18
|
+
- observation tools are supporting context, not primary success signals
|
|
19
|
+
|
|
20
|
+
Use the linked documents below for per-tool inputs, outputs, and usage guidance.
|
package/docs/tools/interact.md
CHANGED
|
@@ -1,108 +1,144 @@
|
|
|
1
|
-
# Interact (UI actions)
|
|
1
|
+
# Interact (UI actions, waits, and verification)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This document covers deterministic UI resolution, actions, waits, and outcome verification.
|
|
4
|
+
|
|
5
|
+
## Verification pattern
|
|
6
|
+
|
|
7
|
+
For mutation actions, the intended agent loop is:
|
|
8
|
+
|
|
9
|
+
**RESOLVE -> ACT -> WAIT (if needed) -> EXPECT**
|
|
10
|
+
|
|
11
|
+
Role split:
|
|
12
|
+
|
|
13
|
+
- `wait_for_*` = resolution and synchronization
|
|
14
|
+
- `expect_*` = final outcome verification
|
|
15
|
+
|
|
16
|
+
Important:
|
|
17
|
+
|
|
18
|
+
- `wait_for_*` tools must not be used as the final verification of action success when an applicable `expect_*` tool exists.
|
|
19
|
+
- action tools report execution success, not outcome correctness.
|
|
4
20
|
|
|
5
21
|
## tap / swipe / type_text / press_back
|
|
6
22
|
|
|
7
|
-
|
|
23
|
+
These tools return a shared action execution envelope.
|
|
8
24
|
|
|
9
|
-
|
|
25
|
+
Example `tap` input:
|
|
26
|
+
|
|
27
|
+
```json
|
|
10
28
|
{ "platform": "android", "deviceId": "emulator-5554", "x": 100, "y": 200 }
|
|
11
29
|
```
|
|
12
30
|
|
|
13
|
-
|
|
31
|
+
Example response:
|
|
14
32
|
|
|
15
|
-
```
|
|
16
|
-
{
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"action_id": "tap_1710000000000_1",
|
|
36
|
+
"timestamp": 1710000000000,
|
|
37
|
+
"action_type": "tap",
|
|
38
|
+
"target": { "selector": { "x": 100, "y": 200 }, "resolved": null },
|
|
39
|
+
"success": true,
|
|
40
|
+
"ui_fingerprint_before": "fp_before",
|
|
41
|
+
"ui_fingerprint_after": "fp_after"
|
|
42
|
+
}
|
|
17
43
|
```
|
|
18
44
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
45
|
+
Guidance:
|
|
46
|
+
|
|
47
|
+
- `tap` is best for coordinate-based interactions when no resolved element is available.
|
|
48
|
+
- `swipe` is execution-only; use `wait_for_*` and `expect_*` to verify its effect when the expected outcome is known.
|
|
49
|
+
- `type_text` reports whether text entry was dispatched, not whether the intended field state is correct.
|
|
50
|
+
- `press_back` reports whether the back action was dispatched, not whether the intended destination screen was reached.
|
|
51
|
+
|
|
52
|
+
Preferred verification:
|
|
53
|
+
|
|
54
|
+
- navigation outcome known -> `expect_screen`
|
|
55
|
+
- local UI change known -> `expect_element_visible`
|
|
24
56
|
|
|
25
57
|
---
|
|
26
58
|
|
|
27
59
|
## scroll_to_element
|
|
28
60
|
|
|
29
|
-
|
|
30
|
-
- Scrolls the UI until an element matching the provided selector becomes visible, or until a maximum number of scroll attempts is reached.
|
|
31
|
-
- Delegates platform behaviour to Android and iOS implementations for reliable swipes and UI-tree checks.
|
|
61
|
+
Scroll until an element matching the provided selector becomes visible, or until the tool reaches a stopping condition.
|
|
32
62
|
|
|
33
63
|
Input example:
|
|
34
|
-
|
|
64
|
+
|
|
65
|
+
```json
|
|
35
66
|
{ "platform": "android", "selector": { "text": "Offscreen Test Element" }, "direction": "down", "maxScrolls": 10, "scrollAmount": 0.7, "deviceId": "emulator-5554" }
|
|
36
67
|
```
|
|
37
68
|
|
|
38
69
|
Response example (found):
|
|
39
|
-
|
|
40
|
-
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{ "success": true, "reason": "element_found", "element": { "text": "Offscreen Test Element" }, "scrollsPerformed": 2 }
|
|
41
73
|
```
|
|
42
74
|
|
|
43
75
|
Response example (failure - unchanged UI):
|
|
44
|
-
|
|
76
|
+
|
|
77
|
+
```json
|
|
45
78
|
{ "success": false, "reason": "ui_unchanged_after_scroll", "scrollsPerformed": 3 }
|
|
46
79
|
```
|
|
47
80
|
|
|
48
81
|
Notes:
|
|
49
|
-
|
|
50
|
-
-
|
|
51
|
-
- The tool fingerprints the visible UI between scrolls
|
|
52
|
-
-
|
|
53
|
-
- Unit tests are located at `test/unit/observe/scroll_to_element.test.ts`, automated device smoke checks under `test/device/automated/...`, and manual device runners under `test/device/manual/...`.
|
|
82
|
+
|
|
83
|
+
- Matching is exact on provided selector fields (`text`, `resourceId`, `contentDesc`, `className`).
|
|
84
|
+
- The tool fingerprints the visible UI between scrolls and can stop early if the UI does not change after a swipe.
|
|
85
|
+
- `scroll_to_element` can return success when it finds the element, but use `expect_element_visible` when you want explicit final verification of the expected visible result.
|
|
54
86
|
|
|
55
87
|
---
|
|
56
88
|
|
|
57
89
|
## wait_for_screen_change
|
|
58
90
|
|
|
59
|
-
|
|
60
|
-
|
|
91
|
+
Purpose:
|
|
92
|
+
|
|
93
|
+
- detect that a screen transition has occurred by waiting for the current fingerprint to differ from a previous fingerprint
|
|
94
|
+
|
|
95
|
+
Capabilities:
|
|
96
|
+
|
|
97
|
+
- synchronization when transition timing is uncertain
|
|
98
|
+
- detection that something changed on screen
|
|
99
|
+
|
|
100
|
+
Constraints:
|
|
101
|
+
|
|
102
|
+
- does not verify correctness of the resulting state
|
|
103
|
+
- must not be used alone to confirm action success when an applicable `expect_*` tool exists
|
|
61
104
|
|
|
62
105
|
Input example:
|
|
63
|
-
|
|
106
|
+
|
|
107
|
+
```json
|
|
64
108
|
{ "platform": "android", "previousFingerprint": "<hex-fingerprint>", "timeoutMs": 5000, "pollIntervalMs": 300, "deviceId": "emulator-5554" }
|
|
65
109
|
```
|
|
66
110
|
|
|
67
111
|
Success response example:
|
|
68
|
-
|
|
112
|
+
|
|
113
|
+
```json
|
|
69
114
|
{ "success": true, "newFingerprint": "<hex-fingerprint>", "elapsedMs": 420 }
|
|
70
115
|
```
|
|
71
116
|
|
|
72
117
|
Failure (timeout) example:
|
|
73
|
-
|
|
118
|
+
|
|
119
|
+
```json
|
|
74
120
|
{ "success": false, "reason": "timeout", "lastFingerprint": "<hex-fingerprint>", "elapsedMs": 5000 }
|
|
75
121
|
```
|
|
76
122
|
|
|
77
123
|
Notes:
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
124
|
+
|
|
125
|
+
- Always compares to the original `previousFingerprint`.
|
|
126
|
+
- Treats `null` fingerprints as transient and keeps polling.
|
|
127
|
+
- Adds a stability confirmation before returning success to avoid transient animation frames.
|
|
128
|
+
- Follow with `expect_screen` when the expected destination is known.
|
|
83
129
|
|
|
84
130
|
---
|
|
85
131
|
|
|
86
132
|
## find_element
|
|
87
133
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Locate a UI element on the current screen using semantic matching and return an actionable element descriptor (including tap coordinates) and confidence telemetry.
|
|
134
|
+
Locate a UI element on the current screen using semantic matching and return an actionable element descriptor.
|
|
91
135
|
|
|
92
136
|
Input:
|
|
93
137
|
|
|
94
138
|
```json
|
|
95
|
-
{ "query": "
|
|
139
|
+
{ "query": "Login", "exact": false, "timeoutMs": 3000, "platform": "android", "deviceId": "emulator-5554" }
|
|
96
140
|
```
|
|
97
141
|
|
|
98
|
-
Behaviour:
|
|
99
|
-
|
|
100
|
-
- Fetches the current UI tree (get_ui_tree) and scores visible elements using: text, content description, resource-id, and class name.
|
|
101
|
-
- Normalises strings (lowercase, trimmed). If exact=true require exact match; otherwise allow partial matches (contains) and resource-id/class matches.
|
|
102
|
-
- Considers element bounds and visibility; scores non-interactable children as matches and attempts to resolve a clickable ancestor (parent index or containing clickable element) to produce an actionable element.
|
|
103
|
-
- Retries until timeoutMs; stops early for high-confidence matches.
|
|
104
|
-
- Does not block on long operations and returns partial results where appropriate.
|
|
105
|
-
|
|
106
142
|
Output:
|
|
107
143
|
|
|
108
144
|
```json
|
|
@@ -113,10 +149,10 @@ Output:
|
|
|
113
149
|
"resourceId": "com.example:id/login",
|
|
114
150
|
"contentDesc": null,
|
|
115
151
|
"class": "android.widget.Button",
|
|
116
|
-
"bounds": { "left":0, "top":0, "right":100, "bottom":50 },
|
|
152
|
+
"bounds": { "left": 0, "top": 0, "right": 100, "bottom": 50 },
|
|
117
153
|
"clickable": true,
|
|
118
154
|
"enabled": true,
|
|
119
|
-
"tapCoordinates": { "x":50, "y":25 },
|
|
155
|
+
"tapCoordinates": { "x": 50, "y": 25 },
|
|
120
156
|
"telemetry": { "matchedIndex": 3, "matchedInteractable": true }
|
|
121
157
|
},
|
|
122
158
|
"score": 1.0,
|
|
@@ -126,99 +162,226 @@ Output:
|
|
|
126
162
|
|
|
127
163
|
Notes:
|
|
128
164
|
|
|
129
|
-
-
|
|
130
|
-
- `
|
|
131
|
-
-
|
|
132
|
-
- Unit tests for edge cases (parent-clickable child-text, resource-id matches, fuzzy matching) are under `test/unit/observe/find_element.test.ts`.
|
|
165
|
+
- Best used when no precise selector is available yet.
|
|
166
|
+
- `tapCoordinates` are suitable for `tap` calls.
|
|
167
|
+
- Prefer `wait_for_ui` when you already know a deterministic selector and want a stable `elementId`.
|
|
133
168
|
|
|
134
169
|
---
|
|
135
170
|
|
|
136
171
|
## wait_for_ui
|
|
137
172
|
|
|
138
173
|
Purpose:
|
|
139
|
-
- Deterministically wait for a UI selector match and return the matched element metadata.
|
|
140
174
|
|
|
141
|
-
|
|
142
|
-
|
|
175
|
+
- resolve elements and/or detect that a UI availability condition has occurred
|
|
176
|
+
|
|
177
|
+
Capabilities:
|
|
178
|
+
|
|
179
|
+
- deterministic element resolution
|
|
180
|
+
- synchronization when element timing or availability is uncertain
|
|
181
|
+
|
|
182
|
+
Constraints:
|
|
183
|
+
|
|
184
|
+
- does not verify correctness of the resulting state
|
|
185
|
+
- must not be used alone to confirm action success when an applicable `expect_*` tool exists
|
|
186
|
+
|
|
187
|
+
Input:
|
|
188
|
+
|
|
189
|
+
```json
|
|
143
190
|
{
|
|
144
|
-
"selector": { "text": "
|
|
145
|
-
"condition": "
|
|
146
|
-
"timeout_ms":
|
|
191
|
+
"selector": { "text": "Generate Session", "contains": false },
|
|
192
|
+
"condition": "clickable",
|
|
193
|
+
"timeout_ms": 5000,
|
|
147
194
|
"poll_interval_ms": 300,
|
|
148
195
|
"match": { "index": 0 },
|
|
149
196
|
"retry": { "max_attempts": 1, "backoff_ms": 0 },
|
|
150
|
-
"platform": "android
|
|
151
|
-
"deviceId": "
|
|
197
|
+
"platform": "android",
|
|
198
|
+
"deviceId": "emulator-5554"
|
|
152
199
|
}
|
|
153
200
|
```
|
|
154
201
|
|
|
155
|
-
Success response
|
|
156
|
-
- status: `success`
|
|
157
|
-
- matched: number of matches found in the current poll
|
|
158
|
-
- element: matched element metadata including `elementId`
|
|
159
|
-
- metrics: latency, poll count, attempts
|
|
160
|
-
|
|
161
|
-
Failure/timeout response:
|
|
162
|
-
- status: `timeout`
|
|
163
|
-
- error: structured error with `code` and `message`
|
|
164
|
-
- metrics: latency, poll count, attempts
|
|
202
|
+
Success response:
|
|
165
203
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"status": "success",
|
|
207
|
+
"matched": 1,
|
|
208
|
+
"element": {
|
|
209
|
+
"text": "Generate Session",
|
|
210
|
+
"resource_id": null,
|
|
211
|
+
"accessibility_id": null,
|
|
212
|
+
"class": "android.widget.TextView",
|
|
213
|
+
"bounds": [471, 1098, 809, 1158],
|
|
214
|
+
"index": 8,
|
|
215
|
+
"elementId": "el_..."
|
|
216
|
+
},
|
|
217
|
+
"metrics": { "latency_ms": 120, "poll_count": 1, "attempts": 1 }
|
|
218
|
+
}
|
|
219
|
+
```
|
|
170
220
|
|
|
171
|
-
|
|
172
|
-
- Unit: `test/unit/interact/wait_for_ui_contract.test.ts` and `test/unit/interact/wait_for_ui_selector_matching.test.ts`
|
|
173
|
-
- Automated device checks now live under `test/device/automated/...`; manual/debug runners live under `test/device/manual/...` (requires devices/emulators and adb/xcrun in PATH)
|
|
221
|
+
Timeout response:
|
|
174
222
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
platform: 'android'
|
|
182
|
-
})
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"status": "timeout",
|
|
226
|
+
"error": { "code": "ELEMENT_NOT_FOUND", "message": "Condition visible not satisfied within timeout" },
|
|
227
|
+
"metrics": { "latency_ms": 5000, "poll_count": 17, "attempts": 1 }
|
|
228
|
+
}
|
|
183
229
|
```
|
|
184
230
|
|
|
185
|
-
|
|
186
|
-
|
|
231
|
+
Notes:
|
|
232
|
+
|
|
233
|
+
- Use `wait_for_ui` to get a stable `elementId` for `tap_element`.
|
|
234
|
+
- Use it before an action when the target element or timing is uncertain.
|
|
235
|
+
- If the expected outcome is known after the action, follow with `expect_*`.
|
|
236
|
+
|
|
237
|
+
---
|
|
187
238
|
|
|
188
239
|
## tap_element
|
|
189
240
|
|
|
190
|
-
|
|
191
|
-
- Execute a tap against a UI element that has already been resolved by `wait_for_ui`.
|
|
241
|
+
Tap a previously resolved UI element using its `elementId`.
|
|
192
242
|
|
|
193
243
|
Input:
|
|
194
|
-
|
|
244
|
+
|
|
245
|
+
```json
|
|
195
246
|
{ "elementId": "el_..." }
|
|
196
247
|
```
|
|
197
248
|
|
|
198
|
-
Behavior:
|
|
199
|
-
- validates that the element still exists in the current UI context
|
|
200
|
-
- validates that the element is visible
|
|
201
|
-
- validates that the element is enabled
|
|
202
|
-
- performs the tap using the resolved element bounds
|
|
203
|
-
|
|
204
249
|
Success response:
|
|
205
|
-
|
|
206
|
-
|
|
250
|
+
|
|
251
|
+
```json
|
|
252
|
+
{
|
|
253
|
+
"action_id": "tap_element_1710000000000_1",
|
|
254
|
+
"timestamp": 1710000000000,
|
|
255
|
+
"action_type": "tap_element",
|
|
256
|
+
"target": {
|
|
257
|
+
"selector": { "elementId": "el_123" },
|
|
258
|
+
"resolved": {
|
|
259
|
+
"elementId": "el_123",
|
|
260
|
+
"text": "Play session",
|
|
261
|
+
"resource_id": null,
|
|
262
|
+
"accessibility_id": null,
|
|
263
|
+
"class": "android.widget.TextView",
|
|
264
|
+
"bounds": [519, 1770, 762, 1830],
|
|
265
|
+
"index": 11
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
"success": true,
|
|
269
|
+
"ui_fingerprint_before": "fp_before",
|
|
270
|
+
"ui_fingerprint_after": "fp_after"
|
|
271
|
+
}
|
|
207
272
|
```
|
|
208
273
|
|
|
209
274
|
Failure response:
|
|
210
|
-
|
|
275
|
+
|
|
276
|
+
```json
|
|
211
277
|
{
|
|
278
|
+
"action_id": "tap_element_1710000000001_2",
|
|
279
|
+
"timestamp": 1710000000001,
|
|
280
|
+
"action_type": "tap_element",
|
|
281
|
+
"target": { "selector": { "elementId": "el_123" }, "resolved": null },
|
|
212
282
|
"success": false,
|
|
213
|
-
"
|
|
214
|
-
"
|
|
215
|
-
"
|
|
283
|
+
"failure_code": "STALE_REFERENCE",
|
|
284
|
+
"retryable": true,
|
|
285
|
+
"ui_fingerprint_before": "fp_before",
|
|
286
|
+
"ui_fingerprint_after": "fp_before"
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Recommended usage:
|
|
291
|
+
|
|
292
|
+
1. resolve target with `wait_for_ui`
|
|
293
|
+
2. call `tap_element`
|
|
294
|
+
3. if needed, wait for transition with `wait_for_*`
|
|
295
|
+
4. verify with `expect_*`
|
|
296
|
+
|
|
297
|
+
Verification guidance:
|
|
298
|
+
|
|
299
|
+
- navigation -> `expect_screen`
|
|
300
|
+
- local UI change -> `expect_element_visible`
|
|
301
|
+
|
|
302
|
+
Failure handling:
|
|
303
|
+
|
|
304
|
+
- `STALE_REFERENCE` -> re-resolve the element, then retry
|
|
305
|
+
- `ELEMENT_NOT_INTERACTABLE` -> wait or refine the target, then retry
|
|
306
|
+
- `UNKNOWN` -> capture a snapshot and stop
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## expect_screen
|
|
311
|
+
|
|
312
|
+
Deterministically verify that the intended navigation outcome of an action has occurred.
|
|
313
|
+
|
|
314
|
+
Input:
|
|
315
|
+
|
|
316
|
+
```json
|
|
317
|
+
{ "platform": "android", "deviceId": "emulator-5554", "fingerprint": "<expected-fingerprint>" }
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
or
|
|
321
|
+
|
|
322
|
+
```json
|
|
323
|
+
{ "platform": "android", "deviceId": "emulator-5554", "screen": "com.example.app.MainActivity" }
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Response:
|
|
327
|
+
|
|
328
|
+
```json
|
|
329
|
+
{
|
|
330
|
+
"success": true,
|
|
331
|
+
"observed_screen": { "fingerprint": "<actual-fingerprint>", "screen": "com.example.app.MainActivity" },
|
|
332
|
+
"expected_screen": { "fingerprint": "<expected-fingerprint>", "screen": null },
|
|
333
|
+
"confidence": 1
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Notes:
|
|
338
|
+
|
|
339
|
+
- Primary and authoritative verification tool for navigation outcomes.
|
|
340
|
+
- Prefer fingerprints; use semantic screen identifiers as a fallback.
|
|
341
|
+
- Works best when the expected screen identifier is known ahead of time.
|
|
342
|
+
- If transition timing is uncertain, place `wait_for_screen_change` before `expect_screen`.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## expect_element_visible
|
|
347
|
+
|
|
348
|
+
Deterministically verify that the intended UI outcome of an action has occurred by confirming a target element is visible.
|
|
349
|
+
|
|
350
|
+
Input:
|
|
351
|
+
|
|
352
|
+
```json
|
|
353
|
+
{
|
|
354
|
+
"selector": { "text": "Play session" },
|
|
355
|
+
"element_id": "optional-resolved-element-id",
|
|
356
|
+
"timeout_ms": 5000,
|
|
357
|
+
"poll_interval_ms": 300,
|
|
358
|
+
"platform": "android",
|
|
359
|
+
"deviceId": "emulator-5554"
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
Response:
|
|
364
|
+
|
|
365
|
+
```json
|
|
366
|
+
{
|
|
367
|
+
"success": true,
|
|
368
|
+
"selector": { "text": "Play session" },
|
|
369
|
+
"element_id": "el_123",
|
|
370
|
+
"element": {
|
|
371
|
+
"elementId": "el_123",
|
|
372
|
+
"text": "Play session",
|
|
373
|
+
"resource_id": null,
|
|
374
|
+
"accessibility_id": null,
|
|
375
|
+
"class": "android.widget.TextView",
|
|
376
|
+
"bounds": [519, 1770, 762, 1830],
|
|
377
|
+
"index": 11
|
|
378
|
+
}
|
|
216
379
|
}
|
|
217
380
|
```
|
|
218
381
|
|
|
219
382
|
Notes:
|
|
220
|
-
|
|
221
|
-
-
|
|
222
|
-
-
|
|
223
|
-
|
|
224
|
-
|
|
383
|
+
|
|
384
|
+
- Primary and authoritative verification tool for expected element visibility.
|
|
385
|
+
- `selector` is the primary input; `element_id` is optional context only.
|
|
386
|
+
- The tool resolves the selector internally when needed.
|
|
387
|
+
- Use when the screen should remain on the same destination but a specific element should appear or become visible.
|
package/docs/tools/manage.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
# Manage (build & device management)
|
|
2
2
|
|
|
3
|
-
This document covers tools that perform project builds, device selection and lifecycle operations
|
|
3
|
+
This document covers tools that perform project builds, device selection, installation, and app lifecycle operations.
|
|
4
|
+
|
|
5
|
+
For app launch and restart flows, agents should use:
|
|
6
|
+
|
|
7
|
+
**ACT -> WAIT (if needed) -> EXPECT**
|
|
8
|
+
|
|
9
|
+
For example:
|
|
10
|
+
|
|
11
|
+
1. `start_app` or `restart_app`
|
|
12
|
+
2. optional `wait_for_screen_change`
|
|
13
|
+
3. `expect_screen` when the expected landing screen is known
|
|
4
14
|
|
|
5
15
|
## list_devices
|
|
6
16
|
Enumerate connected Android devices and iOS simulators.
|
|
@@ -22,58 +32,32 @@ Notes:
|
|
|
22
32
|
|
|
23
33
|
---
|
|
24
34
|
|
|
25
|
-
## build_app
|
|
26
|
-
Build a project and return the path to the generated artifact
|
|
35
|
+
## build_app
|
|
36
|
+
Build a project and return the path to the generated artifact.
|
|
27
37
|
|
|
28
|
-
Input
|
|
29
|
-
|
|
30
|
-
Android:
|
|
31
|
-
|
|
32
|
-
```json
|
|
33
|
-
{ "projectPath": "/path/to/project", "gradleTask": "assembleDebug", "maxWorkers": 4 }
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
iOS:
|
|
38
|
+
Input:
|
|
37
39
|
|
|
38
40
|
```json
|
|
39
|
-
{ "
|
|
41
|
+
{ "platform": "android", "projectType": "kmp", "projectPath": "/path/to/project", "variant": "Debug" }
|
|
40
42
|
```
|
|
41
43
|
|
|
42
44
|
Response:
|
|
43
45
|
|
|
44
|
-
```
|
|
45
|
-
{ "artifactPath": "/path/to/build/output/app.apk" }
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Notes:
|
|
49
|
-
- Android: honors `MCP_GRADLE_WORKERS` / `MCP_GRADLE_CACHE`; will prefer project gradlew when present.
|
|
50
|
-
- iOS: honors `MCP_DERIVED_DATA`, `MCP_BUILD_JOBS` and `MCP_XCODE_DESTINATION_UDID`.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## build_flutter / build_react_native
|
|
55
|
-
Framework-specific helpers. These are best-effort and may delegate to native subprojects when necessary.
|
|
56
|
-
|
|
57
|
-
Input (flutter example):
|
|
58
|
-
|
|
59
46
|
```json
|
|
60
|
-
{ "projectPath": "/path/to/flutter", "platform": "android", "buildMode": "debug" }
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Response:
|
|
64
|
-
|
|
65
|
-
```
|
|
66
47
|
{ "artifactPath": "/path/to/build/output/app.apk" }
|
|
67
48
|
```
|
|
68
49
|
|
|
69
50
|
Notes:
|
|
70
|
-
-
|
|
71
|
-
-
|
|
51
|
+
- Requires `platform`, `projectType`, and `projectPath`.
|
|
52
|
+
- Android builds prefer the project `gradlew` when present.
|
|
53
|
+
- iOS builds honor environment-based Xcode destination and derived-data settings where configured.
|
|
72
54
|
|
|
73
55
|
---
|
|
74
56
|
|
|
75
57
|
## build_and_install (buildAndInstallHandler)
|
|
76
|
-
Orchestrates build then install and returns streamed NDJSON events
|
|
58
|
+
Orchestrates build then install and returns streamed NDJSON events plus a final result object.
|
|
59
|
+
|
|
60
|
+
This is a documented repository helper, not part of the main public MCP tool list in `toolDefinitions`.
|
|
77
61
|
|
|
78
62
|
Input:
|
|
79
63
|
|
|
@@ -135,6 +119,23 @@ start_app input example:
|
|
|
135
119
|
start_app response example:
|
|
136
120
|
|
|
137
121
|
```json
|
|
138
|
-
{
|
|
122
|
+
{
|
|
123
|
+
"action_id": "start_app_1710000000000_1",
|
|
124
|
+
"timestamp": 1710000000000,
|
|
125
|
+
"action_type": "start_app",
|
|
126
|
+
"target": { "selector": { "appId": "com.example.app" }, "resolved": null },
|
|
127
|
+
"success": true,
|
|
128
|
+
"ui_fingerprint_before": "fp_before",
|
|
129
|
+
"ui_fingerprint_after": "fp_after"
|
|
130
|
+
}
|
|
139
131
|
```
|
|
140
132
|
|
|
133
|
+
restart_app returns the same action envelope shape with `action_type: "restart_app"`.
|
|
134
|
+
|
|
135
|
+
terminate_app and reset_app_data return operation-specific lifecycle results instead of the action envelope.
|
|
136
|
+
|
|
137
|
+
Notes:
|
|
138
|
+
|
|
139
|
+
- `start_app` and `restart_app` report execution success, not outcome correctness.
|
|
140
|
+
- When the landing screen is known, use `expect_screen` as the final verification step.
|
|
141
|
+
- If launch timing is uncertain, insert `wait_for_screen_change` before `expect_screen`.
|