mobile-debug-mcp 0.26.3 → 0.26.5

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.
@@ -555,6 +555,62 @@ Failure Handling:
555
555
  required: ['property', 'expected']
556
556
  }
557
557
  },
558
+ {
559
+ name: 'adjust_control',
560
+ description: `Purpose:
561
+ Adjust a numeric control value with verification.
562
+
563
+ This is the initial adjustable-control surface for slider-like controls and other controls that expose a numeric value or value_range.
564
+
565
+ Inputs:
566
+ - selector or element_id
567
+ - property (defaults to "value")
568
+ - targetValue
569
+ - tolerance (optional)
570
+ - maxAttempts (optional)
571
+ - platform/deviceId (optional)
572
+
573
+ Output Structure:
574
+ - action_id, timestamp (ISO 8601), action_type
575
+ - lifecycle_state: post-dispatch lifecycle state (pending_verification or failed)
576
+ - source_module: runtime source of the action envelope
577
+ - target_state / actual_state / within_tolerance / converged / attempts / adjustment_mode
578
+ - target.selector = original selector or element handle
579
+ - success = true when the control converges within tolerance
580
+
581
+ Verification Guidance:
582
+ - Prefer direct target placement when value_range is available; fall back to a drag only if the direct tap does not converge
583
+ - Use expect_state for the control value readback
584
+ - Treat coordinate fallback as degraded mode
585
+
586
+ Failure Handling:
587
+ - ELEMENT_NOT_FOUND → re-resolve the control
588
+ - ELEMENT_NOT_INTERACTABLE → the control cannot be adjusted through the current runtime
589
+ - TIMEOUT → the control did not converge within bounded retries
590
+ - UNKNOWN → capture a snapshot and stop`,
591
+ inputSchema: {
592
+ type: 'object',
593
+ properties: {
594
+ selector: {
595
+ type: 'object',
596
+ properties: {
597
+ text: { type: 'string' },
598
+ resource_id: { type: 'string' },
599
+ accessibility_id: { type: 'string' },
600
+ contains: { type: 'boolean', default: false }
601
+ }
602
+ },
603
+ element_id: { type: 'string', description: 'Optional previously resolved element identifier.' },
604
+ property: { type: 'string', description: 'Readable numeric state property to adjust.', default: 'value' },
605
+ targetValue: { type: 'number', description: 'Target numeric value.' },
606
+ tolerance: { type: 'number', description: 'Accepted numeric tolerance around the target value.', default: 0 },
607
+ maxAttempts: { type: 'number', description: 'Maximum adjustment attempts.', default: 3 },
608
+ platform: { type: 'string', enum: ['android', 'ios'], description: 'Optional platform override' },
609
+ deviceId: { type: 'string', description: 'Optional device serial/udid' }
610
+ },
611
+ required: ['targetValue']
612
+ }
613
+ },
558
614
  {
559
615
  name: 'wait_for_ui',
560
616
  description: `Purpose:
@@ -226,6 +226,30 @@ async function handleExpectState(args) {
226
226
  const res = await ToolsInteract.expectStateHandler({ selector: selector ?? undefined, element_id: element_id ?? undefined, property, expected, platform, deviceId });
227
227
  return wrapResponse(res);
228
228
  }
229
+ async function handleAdjustControl(args) {
230
+ const selector = getObjectArg(args, 'selector');
231
+ const element_id = getStringArg(args, 'element_id');
232
+ const property = getStringArg(args, 'property') ?? 'value';
233
+ const targetValue = requireNumberArg(args, 'targetValue');
234
+ const tolerance = getNumberArg(args, 'tolerance') ?? 0;
235
+ const maxAttempts = getNumberArg(args, 'maxAttempts') ?? 3;
236
+ const platform = getStringArg(args, 'platform');
237
+ const deviceId = getStringArg(args, 'deviceId');
238
+ if (!selector && !element_id) {
239
+ throw new Error('Missing selector or element_id argument');
240
+ }
241
+ const res = await ToolsInteract.adjustControlHandler({
242
+ selector: selector ?? undefined,
243
+ element_id: element_id ?? undefined,
244
+ property,
245
+ targetValue,
246
+ tolerance,
247
+ maxAttempts,
248
+ platform,
249
+ deviceId
250
+ });
251
+ return wrapResponse(res);
252
+ }
229
253
  async function handleWaitForUI(args) {
230
254
  const selector = getObjectArg(args, 'selector');
231
255
  const condition = getStringArg(args, 'condition') ?? 'exists';
@@ -431,6 +455,7 @@ export const toolHandlers = {
431
455
  expect_screen: handleExpectScreen,
432
456
  expect_element_visible: handleExpectElementVisible,
433
457
  expect_state: handleExpectState,
458
+ adjust_control: handleAdjustControl,
434
459
  wait_for_ui: handleWaitForUI,
435
460
  find_element: handleFindElement,
436
461
  tap: handleTap,
@@ -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.26.3'
9
+ version: '0.26.5'
10
10
  };
11
11
  export function createServer() {
12
12
  const server = new Server(serverInfo, {
@@ -360,8 +360,14 @@ function normalizeClassName(value) {
360
360
  return typeof value === 'string' ? value.trim().toLowerCase() : '';
361
361
  }
362
362
  function inferAndroidRole(className) {
363
- if (/seekbar|slider|progress/.test(className))
363
+ if (/seekbar|slider/.test(className))
364
364
  return 'slider';
365
+ if (/stepper|numberpicker/.test(className))
366
+ return 'stepper';
367
+ if (/spinner|dropdown/.test(className))
368
+ return 'dropdown';
369
+ if (/segment|tablayout/.test(className))
370
+ return 'segmented_control';
365
371
  if (/switch|toggle/.test(className))
366
372
  return 'switch';
367
373
  if (/checkbox/.test(className))
@@ -403,15 +409,41 @@ function buildAndroidSelector(text, contentDescription, resourceId, className) {
403
409
  return { value: className, confidence: buildAndroidSelectorConfidence('class') };
404
410
  return null;
405
411
  }
406
- function buildAndroidSemantic(clickable, className) {
407
- return {
412
+ function buildAndroidSemantic(clickable, className, role) {
413
+ const semantic = {
408
414
  is_clickable: clickable,
409
415
  is_container: /recyclerview|scroll|layout|viewgroup|frame/.test(className)
410
416
  };
417
+ if (role === 'slider') {
418
+ semantic.semantic_role = 'slider';
419
+ semantic.adjustable = true;
420
+ semantic.supported_actions = ['adjust'];
421
+ semantic.state_shape = 'continuous';
422
+ }
423
+ else if (role === 'stepper') {
424
+ semantic.semantic_role = 'stepper';
425
+ semantic.adjustable = true;
426
+ semantic.supported_actions = ['increment', 'decrement'];
427
+ semantic.state_shape = 'discrete';
428
+ }
429
+ else if (role === 'dropdown') {
430
+ semantic.semantic_role = 'dropdown';
431
+ semantic.supported_actions = ['tap', 'expand'];
432
+ semantic.state_shape = 'semantic';
433
+ }
434
+ else if (role === 'segmented_control') {
435
+ semantic.semantic_role = 'segmented_control';
436
+ semantic.supported_actions = ['tap'];
437
+ semantic.state_shape = 'discrete';
438
+ }
439
+ else if (clickable) {
440
+ semantic.supported_actions = ['tap'];
441
+ }
442
+ return semantic;
411
443
  }
412
444
  function isSliderLikeAndroid(node) {
413
445
  const className = String(node['@_class'] || '').toLowerCase();
414
- return /seekbar|slider|range|progress/i.test(className);
446
+ return /seekbar|slider|range/i.test(className);
415
447
  }
416
448
  function extractAndroidState(node) {
417
449
  const checked = parseBooleanAttr(node['@_checked']);
@@ -487,7 +519,7 @@ export function traverseNode(node, elements, parentIndex = -1, depth = 0) {
487
519
  const stableId = resourceId ?? (typeof contentDescription === 'string' && contentDescription.trim().length > 0 ? contentDescription : null);
488
520
  const testTag = stableId;
489
521
  const selector = buildAndroidSelector(text, contentDescription, resourceId, normalizeClassName(className));
490
- const semantic = buildAndroidSemantic(clickable, normalizeClassName(className));
522
+ const semantic = buildAndroidSemantic(clickable, normalizeClassName(className), role);
491
523
  const isUseful = clickable || (text && text.length > 0) || (contentDescription && contentDescription.length > 0);
492
524
  if (isUseful) {
493
525
  const element = {
package/docs/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All notable changes to the **Mobile Debug MCP** project will be documented in this file.
4
4
 
5
+ ## [0.26.5]
6
+ - Introduces a semantic control model to improve the identification and interaction with custom and composite UI controls.
7
+
8
+ ## [0.26.4]
9
+ - Improved slider accuracy
10
+
5
11
  ## [0.26.3]
6
12
  - updates the `find_element` tool to return detailed resolution metadata, including confidence scores,
7
13
 
package/docs/ROADMAP.md CHANGED
@@ -44,6 +44,7 @@ Higher task success with fewer retries.
44
44
 
45
45
  - Stronger State Verification — Complete (Foundational verification layer shipped)
46
46
  - Richer Element Identity — Complete (Identity and selector confidence foundations shipped)
47
+ - Better Compose / Custom Control Semantics — Complete (Semantic role enrichment and custom-adjustable inference shipped)
47
48
 
48
49
  ## Current Focus
49
50
 
@@ -52,10 +53,61 @@ Higher task success with fewer retries.
52
53
 
53
54
  ## Upcoming Work
54
55
 
56
+ - Environment Auto-Configuration and Toolchain Discovery
55
57
  - Adjustable Control Support
56
- - Better Compose / Custom Control Semantics
57
58
  - Signal-Oriented Diagnostic Filtering
58
59
  - Long Press Gesture
60
+ # Stronger State Verification
61
+ # Richer Element Identity
62
+ # Wait and Synchronization Reliability
63
+ # Environment Auto-Configuration and Toolchain Discovery
64
+
65
+ ## Rationale
66
+ Reduce onboarding friction and improve developer experience by minimizing manual setup dependencies.
67
+
68
+ **Status:** Planned
69
+
70
+ Addresses friction around:
71
+ - manual idb installation
72
+ - manual adb path configuration
73
+ - manual xcrun path configuration
74
+ - environment drift across machines
75
+ - setup failures blocking first use
76
+
77
+ ## Scope
78
+ - Automatic discovery of adb
79
+ - Automatic discovery of xcrun
80
+ - idb detection and guided bootstrap support
81
+ - Startup toolchain validation
82
+ - Environment health diagnostics / doctor-style checks
83
+ - Minimal-manual-configuration defaults
84
+
85
+ ## Expected Impact
86
+ High.
87
+
88
+ ## Exit Criteria
89
+ - adb and xcrun auto-discovery implemented
90
+ - Missing dependencies surfaced with guided remediation
91
+ - Startup environment validation available
92
+ - Manual path configuration eliminated or minimized for standard setups
93
+ - First-run setup validated on representative developer environments
94
+
95
+ ## Success Metrics
96
+ - Reduced setup friction during onboarding
97
+ - Lower environment configuration failures
98
+ - Faster time-to-first-successful-session
99
+ - Reduced support/debugging caused by local setup issues
100
+
101
+ ## Dependencies
102
+ Depends on:
103
+ - Stronger State Verification
104
+ - Richer Element Identity
105
+
106
+ Strengthens:
107
+ - Actionability Resolution
108
+ - Broader user adoption readiness
109
+
110
+ ---
59
111
 
60
112
  ## Later Horizon
61
113
 
@@ -383,7 +435,7 @@ Strengthens:
383
435
  ## Rationale
384
436
  Higher priority after agent feedback exposed custom control semantics as a core reliability gap, not a later optimization.
385
437
 
386
- **Status:** Spec Ready
438
+ **Status:** Completed
387
439
 
388
440
  Semantics become more useful once:
389
441
  - identity is stronger
@@ -394,8 +446,8 @@ Semantics become more useful once:
394
446
 
395
447
  ## Scope
396
448
  - Composite control traits
397
- - Control role enrichment (adjustable, expandable, selectable_group)
398
- - Interaction contracts metadata
449
+ - Control role enrichment (`slider`, `stepper`, `dropdown`, `segmented_control`, `custom_adjustable`)
450
+ - Interaction contract metadata (`supported_actions`, `adjustable`, `state_shape`)
399
451
  - Custom widget gesture affordance hints
400
452
  - Semantic confidence annotations
401
453
  - Compose-aware selectors for waits (merged semantics and element relationships)
@@ -405,7 +457,7 @@ High.
405
457
 
406
458
  ## Exit Criteria
407
459
  - Semantic traits implemented for major custom control classes
408
- - Interaction contracts surfaced in snapshot model
460
+ - Interaction contracts surfaced in observation and resolution paths
409
461
  - Confidence model defined for derived semantics
410
462
  - Custom control manipulation success validated in benchmark flows
411
463
 
@@ -516,6 +568,7 @@ Foundation
516
568
  - Richer Element Identity
517
569
 
518
570
  Synchronization & Actionability
571
+ - Environment Auto-Configuration and Toolchain Discovery
519
572
  - Wait and Synchronization Reliability
520
573
  - Actionability Resolution
521
574
 
@@ -536,9 +589,10 @@ Deep Observability
536
589
  - Richer Element Identity
537
590
  - Wait and Synchronization Reliability
538
591
  - Actionability Resolution
592
+ - Environment Auto-Configuration and Toolchain Discovery
539
593
 
540
594
  Focus:
541
- Make core loop more reliable.
595
+ Make core loop reliable and reduce onboarding friction.
542
596
 
543
597
  ---
544
598
 
@@ -575,16 +629,17 @@ Roadmap Ordering:
575
629
  1. Stronger State Verification
576
630
  2. Richer Element Identity
577
631
  3. Wait and Synchronization Reliability
578
- 4. Actionability Resolution
579
- 5. Adjustable Control Support
580
- 6. Better Compose / Custom Control Semantics
581
- 7. Signal-Oriented Diagnostic Filtering
582
- 8. Long Press Gesture
583
- 9. Pinch to Zoom
584
- 10. Action Trace Correlation
632
+ 4. Environment Auto-Configuration and Toolchain Discovery
633
+ 5. Actionability Resolution
634
+ 6. Adjustable Control Support
635
+ 7. Better Compose / Custom Control Semantics
636
+ 8. Signal-Oriented Diagnostic Filtering
637
+ 9. Long Press Gesture
638
+ 10. Pinch to Zoom
639
+ 11. Action Trace Correlation
585
640
 
586
641
  Rationale:
587
- - Early roadmap items harden state, targeting, synchronization, action execution.
642
+ - Early roadmap items harden state, targeting, synchronization, environment readiness, and action execution.
588
643
  - Mid roadmap items improve control precision and signal observability.
589
644
  - Later interaction-focused items expand interaction coverage.
590
645
  - Final observability work deepens debugging observability.
@@ -0,0 +1,273 @@
1
+
2
+
3
+
4
+ # RFC 008 — Adjustable Control Support and Semantic Value Manipulation
5
+
6
+ ## 1. Summary
7
+
8
+ This RFC defines semantic interaction support for adjustable controls whose primary interaction changes a value rather than triggering a discrete action.
9
+
10
+ Examples include:
11
+ - sliders
12
+ - steppers
13
+ - seek bars
14
+ - drag-based range controls
15
+ - quantized parameter selectors
16
+
17
+ Goal:
18
+ Enable reliable value-setting interactions with verification, minimizing coordinate guessing and brittle gesture calibration.
19
+
20
+ Builds on:
21
+ - RFC 005 — correctness model
22
+ - RFC 006 — runtime execution binding
23
+ - RFC 007 — target resolution
24
+
25
+ ---
26
+
27
+ ## 2. Problem Statement
28
+
29
+ Current control adjustment often degrades into coordinate heuristics.
30
+
31
+ Observed failure modes:
32
+ - slider handles not semantically surfaced
33
+ - coordinate calibration guesswork
34
+ - snapping or quantized values behaving unexpectedly
35
+ - weak confirmation of resulting value
36
+ - retries caused by partial adjustment success
37
+
38
+ This is not primarily a gesture problem.
39
+
40
+ It is:
41
+ - a control semantics problem
42
+ - a value verification problem
43
+ - an adjustment convergence problem
44
+
45
+ ---
46
+
47
+ ## 3. Design Goals
48
+
49
+ Support MUST:
50
+ - Prefer semantic adjustment over coordinate manipulation
51
+ - Support deterministic value targeting
52
+ - Verify resulting value after adjustment
53
+ - Handle quantized or snapping controls
54
+ - Support bounded tolerance when exact values are impossible
55
+ - Use coordinate fallback only as degraded mode
56
+
57
+ ---
58
+
59
+ ## 4. Adjustable Control Model
60
+
61
+ Treat adjustable controls as a combination of:
62
+ - target control
63
+ - value model
64
+ - adjustment mechanism
65
+ - verification loop
66
+
67
+ Control should expose where possible:
68
+ - current value
69
+ - minimum and maximum range
70
+ - step granularity (if known)
71
+ - adjustable role metadata
72
+
73
+ ---
74
+
75
+ ## 5. Primary Primitive
76
+
77
+ Illustrative adjustment primitive (conceptual, not yet a committed tool surface):
78
+
79
+ set_slider_value(target, value, tolerance?)
80
+
81
+ This denotes an adjustment capability, not a required standalone tool API. Implementations may realize it as:
82
+ - an extension of existing gesture tools
83
+ - an internal adjustment helper
84
+ - a future dedicated control-adjustment tool surface
85
+
86
+ This RFC does not mandate which mechanism is used.
87
+
88
+ Semantics:
89
+ - resolve control target
90
+ - perform adjustment
91
+ - read back resulting value
92
+ - converge or fail explicitly
93
+
94
+ This is not:
95
+ blind drag gestures
96
+
97
+ It is:
98
+ set and verify
99
+
100
+ ## 5.1 Tool Surface Boundary
101
+
102
+ This RFC specifies adjustment semantics, not a committed tool API.
103
+
104
+ It does not assume a new public tool is introduced in this RFC.
105
+ Implementation may extend existing gesture/runtime surfaces before introducing any dedicated adjustment command.
106
+
107
+ ---
108
+
109
+ ## 6. Adjustment Modes
110
+
111
+ ### Semantic mode (preferred)
112
+ Use control semantics to set value directly or intelligently drive adjustment.
113
+
114
+ ---
115
+
116
+ ### Gesture-assisted mode
117
+ Use controlled drag informed by:
118
+ - bounds
119
+ - target percentage
120
+ - snapping model
121
+
122
+ ---
123
+
124
+ ### Coordinate fallback (last resort)
125
+ Allowed only when semantic control support is absent.
126
+
127
+ Must be explicit degraded mode.
128
+
129
+ ---
130
+
131
+ ## 7. Verification Loop
132
+
133
+ Adjustment is incomplete until verified.
134
+
135
+ Loop:
136
+ - adjust
137
+ - read back
138
+ - compare to target or tolerance
139
+ - converge or fail after bounded retries
140
+
141
+ Possible outcomes:
142
+ - Verified
143
+ - Tolerance satisfied
144
+ - Failed to converge
145
+
146
+ Aligns with RFC 005.
147
+ Verification may initially be realized through explicit expect_state mappings for control value assertions. Dedicated value verifiers are a possible future extension, not a prerequisite of this RFC.
148
+
149
+ ---
150
+
151
+ ## 8. Quantized / Snapping Controls
152
+
153
+ Support:
154
+ - discrete step controls
155
+ - snapping values
156
+ - non-linear scales (where detectable)
157
+
158
+ Tolerance model required.
159
+
160
+ Example:
161
+ Target 30
162
+ Actual 29.8
163
+ Within tolerance acceptable
164
+ Discrete or non-numeric controls may satisfy convergence through semantic state equivalence rather than numeric tolerance alone.
165
+
166
+ ---
167
+
168
+ ## 9. Control Resolution Dependency
169
+
170
+ Uses RFC 007 target resolution for:
171
+ - locating actual adjustable control
172
+ - avoiding fake slider containers
173
+ - resolving executable adjustable target
174
+
175
+ RFC 007 resolves what to adjust.
176
+ RFC 008 defines how to adjust it.
177
+
178
+ ---
179
+
180
+ ## 10. Compose / Custom Control Support
181
+
182
+ Support derived adjustable semantics for:
183
+ - Compose sliders
184
+ - custom parameter widgets
185
+ - composite adjustable controls
186
+
187
+ Strengthens Better Compose / Custom Control Semantics.
188
+
189
+ ---
190
+
191
+ ## 11. Output / Result Model (Illustrative)
192
+
193
+ Illustrative result shape:
194
+
195
+ {
196
+ "target_state": 30,
197
+ "actual_state": 30,
198
+ "converged": true,
199
+ "adjustment_mode": "semantic"
200
+ }
201
+
202
+ State may be numeric, discrete, or semantic depending on control type. This model is illustrative and current implementations may expose only a subset through existing verification surfaces.
203
+
204
+ ---
205
+
206
+ ## 12. Success Metrics
207
+
208
+ Track:
209
+ - reduction in coordinate fallback usage
210
+ - reduced retries adjusting controls
211
+ - improved first-pass value convergence
212
+ - improved custom control adjustment success
213
+
214
+ ---
215
+
216
+ ## 13. Dependencies
217
+
218
+ Depends on:
219
+ - Stronger State Verification
220
+ - Actionability Resolution (RFC 007)
221
+
222
+ Strengthens:
223
+ - Better Compose / Custom Control Semantics
224
+ - Pinch to Zoom (future)
225
+
226
+ ---
227
+
228
+ ## 14. Relationship to Prior RFCs
229
+
230
+ RFC 005
231
+ Defines successful adjustment verification.
232
+
233
+ RFC 006
234
+ Defines runtime execution interpretation.
235
+
236
+ RFC 007
237
+ Defines which adjustable target gets selected.
238
+
239
+ RFC 008
240
+ Defines how value-changing controls are manipulated reliably.
241
+
242
+ Together:
243
+ - RFC 005 — correctness
244
+ - RFC 006 — runtime binding
245
+ - RFC 007 — target resolution
246
+ - RFC 008 — value manipulation
247
+
248
+ ---
249
+
250
+ ## 15. Summary
251
+
252
+ This RFC moves adjustable controls from:
253
+ - gesture guesswork
254
+
255
+ to:
256
+ - semantic value manipulation with verification
257
+
258
+ It reduces one of the largest remaining sources of interaction brittleness.
259
+
260
+ ---
261
+
262
+ ## 16. Non-Goals / Scope Boundary
263
+
264
+ This RFC defines adjustment semantics and convergence behavior.
265
+
266
+ It does not commit in this RFC to:
267
+ - a specific runtime tool API
268
+ - full adjustable control support across all control types
269
+ - generalized gesture framework support
270
+ - arbitrary drag or canvas manipulation
271
+ - pinch-to-zoom or broader gesture semantics
272
+
273
+ This RFC specifies the behavioral model adjustable-control support should satisfy as implementations mature.