appium-mcp 1.66.0 → 1.67.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/CHANGELOG.md +6 -0
- package/README.md +19 -2
- package/dist/tools/gestures/handlers/scroll-to-element.d.ts.map +1 -1
- package/dist/tools/gestures/handlers/scroll-to-element.js +38 -35
- package/dist/tools/gestures/handlers/scroll-to-element.js.map +1 -1
- package/dist/tools/gestures/handlers/swipe-scroll.d.ts +9 -0
- package/dist/tools/gestures/handlers/swipe-scroll.d.ts.map +1 -1
- package/dist/tools/gestures/handlers/swipe-scroll.js +59 -0
- package/dist/tools/gestures/handlers/swipe-scroll.js.map +1 -1
- package/dist/tools/gestures/schema.d.ts +9 -0
- package/dist/tools/gestures/schema.d.ts.map +1 -1
- package/dist/tools/gestures/schema.js +24 -1
- package/dist/tools/gestures/schema.js.map +1 -1
- package/dist/tools/interactions/find.d.ts.map +1 -1
- package/dist/tools/interactions/find.js +3 -1
- package/dist/tools/interactions/find.js.map +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/resources/submodules.zip +0 -0
- package/src/tools/gestures/handlers/scroll-to-element.ts +50 -46
- package/src/tools/gestures/handlers/swipe-scroll.ts +78 -0
- package/src/tools/gestures/schema.ts +35 -1
- package/src/tools/interactions/find.ts +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [1.67.0](https://github.com/appium/appium-mcp/compare/v1.66.0...v1.67.0) (2026-04-23)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* scroll-until-found for appium_find_element ([#277](https://github.com/appium/appium-mcp/issues/277)) ([f69eb71](https://github.com/appium/appium-mcp/commit/f69eb71f959d550d01619ec79fc832aa3f81a4db))
|
|
6
|
+
|
|
1
7
|
## [1.66.0](https://github.com/appium/appium-mcp/compare/v1.65.0...v1.66.0) (2026-04-23)
|
|
2
8
|
|
|
3
9
|
### Features
|
package/README.md
CHANGED
|
@@ -335,8 +335,8 @@ The default regex pattern allows any URL that starts with `http://` or `https://
|
|
|
335
335
|
|
|
336
336
|
| Tool | Description |
|
|
337
337
|
| --------------------- | -------------------------------------------------------------------------------------------- |
|
|
338
|
-
| `appium_find_element` | Find a specific element using traditional locator strategies (xpath, id, accessibility id, etc.) **OR** AI-powered natural language descriptions (e.g., "yellow search button at bottom").
|
|
339
|
-
| `appium_gesture` | Perform a touch gesture. `action` = `tap`, `double_tap`, `long_press`, `scroll`, `swipe`, `pinch_zoom`, or
|
|
338
|
+
| `appium_find_element` | Find a specific element using traditional locator strategies (xpath, id, accessibility id, etc.) **OR** AI-powered natural language descriptions (e.g., "yellow search button at bottom"). To scroll until an element appears, use **`appium_gesture`** with **`action=scroll_to_element`** (same `strategy` / `selector` as find). |
|
|
339
|
+
| `appium_gesture` | Perform a touch gesture. `action` = `tap`, `double_tap`, `long_press`, `scroll`, `swipe`, `pinch_zoom`, or **`scroll_to_element`**. **`scroll_to_element`** scrolls vertically (`direction` = `up` \| `down`) until the locator matches, **page source stops changing** after a scroll (end of list), or **`maxScrollAttempts`** (default 10, max 80). Optional **`scrollDistance`** (0.05–1) or **`scrollDistancePreset`** = `small` \| `medium` \| `large`. Supports element UUIDs and raw coordinates for other actions. For swipe, use `speed` = `slow` \| `normal` \| `fast` (fast for pull-to-refresh). |
|
|
340
340
|
| `appium_drag_and_drop` | Perform a drag and drop gesture from a source location to a target location (supports element-to-element, element-to-coordinates, coordinates-to-element, and coordinates-to-coordinates) |
|
|
341
341
|
| `appium_perform_actions` | Execute raw W3C Actions API sequences for custom multi-touch gestures (rotate, three-finger swipe, edge swipes, precise timing). Prefer `appium_gesture` for standard gestures. |
|
|
342
342
|
| `appium_set_value` | Enter text into an input field |
|
|
@@ -413,6 +413,23 @@ This example demonstrates a complete e-commerce checkout flow that can be automa
|
|
|
413
413
|
}
|
|
414
414
|
```
|
|
415
415
|
|
|
416
|
+
**Scroll until element is on screen (`appium_gesture` / `scroll_to_element`):**
|
|
417
|
+
```json
|
|
418
|
+
{
|
|
419
|
+
"tool": "appium_gesture",
|
|
420
|
+
"arguments": {
|
|
421
|
+
"action": "scroll_to_element",
|
|
422
|
+
"strategy": "xpath",
|
|
423
|
+
"selector": "//*[contains(@text,'My header')]",
|
|
424
|
+
"direction": "down",
|
|
425
|
+
"maxScrollAttempts": 40,
|
|
426
|
+
"scrollDistancePreset": "medium"
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Use **`scrollDistance`** (0.05–1) instead of **`scrollDistancePreset`** when you want an exact fraction. Then call **`appium_find_element`** with the same `strategy` / `selector` to obtain the element id.
|
|
432
|
+
|
|
416
433
|
**AI Mode (Natural Language):**
|
|
417
434
|
```json
|
|
418
435
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-to-element.d.ts","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/scroll-to-element.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"scroll-to-element.d.ts","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/scroll-to-element.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAmChD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,aAAa,CAAC,CA0DxB"}
|
|
@@ -1,7 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { getPageSource } from '../../../command.js';
|
|
2
|
+
import log from '../../../logger.js';
|
|
3
3
|
import { errorResult, textResult, toolErrorMessage, } from '../../tool-response.js';
|
|
4
|
-
|
|
4
|
+
import { performVerticalScroll } from './swipe-scroll.js';
|
|
5
|
+
const PRESET_TO_DISTANCE = {
|
|
6
|
+
small: 0.25,
|
|
7
|
+
medium: 0.45,
|
|
8
|
+
large: 1,
|
|
9
|
+
};
|
|
10
|
+
function resolveScrollDistance(args) {
|
|
11
|
+
if (args.scrollDistancePreset) {
|
|
12
|
+
return PRESET_TO_DISTANCE[args.scrollDistancePreset];
|
|
13
|
+
}
|
|
14
|
+
if (args.scrollDistance !== undefined) {
|
|
15
|
+
return args.scrollDistance;
|
|
16
|
+
}
|
|
17
|
+
return 0.45;
|
|
18
|
+
}
|
|
5
19
|
async function tryFindElement(driver, strategy, selector) {
|
|
6
20
|
try {
|
|
7
21
|
await driver.findElement(strategy, selector);
|
|
@@ -11,34 +25,6 @@ async function tryFindElement(driver, strategy, selector) {
|
|
|
11
25
|
return false;
|
|
12
26
|
}
|
|
13
27
|
}
|
|
14
|
-
async function performW3CScroll(driver, direction) {
|
|
15
|
-
const { width, height } = await getWindowRect(driver);
|
|
16
|
-
const startX = Math.floor(width / 2);
|
|
17
|
-
const startY = direction === 'down' ? Math.floor(height * 0.8) : Math.floor(height * 0.2);
|
|
18
|
-
const endY = direction === 'down' ? Math.floor(height * 0.2) : Math.floor(height * 0.8);
|
|
19
|
-
await performActions(driver, [
|
|
20
|
-
{
|
|
21
|
-
type: 'pointer',
|
|
22
|
-
id: 'finger1',
|
|
23
|
-
parameters: { pointerType: 'touch' },
|
|
24
|
-
actions: [
|
|
25
|
-
{ type: 'pointerMove', duration: 0, x: startX, y: startY },
|
|
26
|
-
{ type: 'pointerDown', button: 0 },
|
|
27
|
-
{ type: 'pause', duration: 250 },
|
|
28
|
-
{ type: 'pointerMove', duration: 600, x: startX, y: endY },
|
|
29
|
-
{ type: 'pointerUp', button: 0 },
|
|
30
|
-
],
|
|
31
|
-
},
|
|
32
|
-
]);
|
|
33
|
-
}
|
|
34
|
-
async function scrollOnce(driver, direction) {
|
|
35
|
-
const platform = getPlatformName(driver);
|
|
36
|
-
if (platform === PLATFORM.ios) {
|
|
37
|
-
await execute(driver, 'mobile: scroll', { direction });
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
await performW3CScroll(driver, direction);
|
|
41
|
-
}
|
|
42
28
|
export async function handleScrollToElement(driver, args) {
|
|
43
29
|
if (!args.strategy || !args.selector) {
|
|
44
30
|
return errorResult('scroll_to_element requires both strategy and selector.');
|
|
@@ -46,17 +32,34 @@ export async function handleScrollToElement(driver, args) {
|
|
|
46
32
|
const direction = args.direction === 'up' || args.direction === 'down'
|
|
47
33
|
? args.direction
|
|
48
34
|
: 'down';
|
|
35
|
+
const maxScroll = args.maxScrollAttempts;
|
|
36
|
+
if (args.scrollDistancePreset && args.scrollDistance !== undefined) {
|
|
37
|
+
log.warn('scroll_to_element: scrollDistancePreset is set; ignoring scrollDistance');
|
|
38
|
+
}
|
|
39
|
+
const distance = resolveScrollDistance(args);
|
|
49
40
|
try {
|
|
50
41
|
if (await tryFindElement(driver, args.strategy, args.selector)) {
|
|
51
42
|
return textResult(`Element ${args.selector} is already visible on screen.`);
|
|
52
43
|
}
|
|
53
|
-
|
|
54
|
-
|
|
44
|
+
let scrollsDone = 0;
|
|
45
|
+
while (scrollsDone < maxScroll) {
|
|
46
|
+
const xmlBefore = await getPageSource(driver);
|
|
47
|
+
try {
|
|
48
|
+
await performVerticalScroll(driver, { direction, distance });
|
|
49
|
+
}
|
|
50
|
+
catch (scrollErr) {
|
|
51
|
+
return errorResult(`Scroll failed during scroll_to_element: ${toolErrorMessage(scrollErr)}`);
|
|
52
|
+
}
|
|
53
|
+
const xmlAfter = await getPageSource(driver);
|
|
54
|
+
scrollsDone++;
|
|
55
55
|
if (await tryFindElement(driver, args.strategy, args.selector)) {
|
|
56
|
-
return textResult(`Successfully scrolled to element ${args.selector} after ${
|
|
56
|
+
return textResult(`Successfully scrolled to element ${args.selector} after ${scrollsDone} scroll(s).`);
|
|
57
|
+
}
|
|
58
|
+
if (xmlBefore === xmlAfter) {
|
|
59
|
+
return errorResult(`Element not found; page source did not change after scroll (likely end of scrollable content). selector=${args.selector}`);
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
|
-
return errorResult(`Element ${args.selector} not found after ${
|
|
62
|
+
return errorResult(`Element ${args.selector} not found after ${maxScroll} scroll(s) in direction '${direction}'.`);
|
|
60
63
|
}
|
|
61
64
|
catch (err) {
|
|
62
65
|
return errorResult(`Failed to scroll_to_element. ${toolErrorMessage(err)}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-to-element.js","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/scroll-to-element.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"scroll-to-element.js","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/scroll-to-element.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { ContentResult } from 'fastmcp';
|
|
2
2
|
import type { DriverInstance } from '../../../session-store.js';
|
|
3
3
|
import type { GestureArgs } from '../schema.js';
|
|
4
|
+
export type VerticalScrollOptions = {
|
|
5
|
+
direction: 'up' | 'down';
|
|
6
|
+
distance: number;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Vertical swipe in the middle of the window, scaled by `distance` (0.05–1).
|
|
10
|
+
* Used by `appium_gesture` `scroll_to_element`; matches legacy scroll distances.
|
|
11
|
+
*/
|
|
12
|
+
export declare function performVerticalScroll(driver: DriverInstance, options: VerticalScrollOptions): Promise<void>;
|
|
4
13
|
export declare function handleScroll(driver: DriverInstance, args: GestureArgs): Promise<ContentResult>;
|
|
5
14
|
export declare function handleSwipe(driver: DriverInstance, args: GestureArgs): Promise<ContentResult>;
|
|
6
15
|
//# sourceMappingURL=swipe-scroll.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"swipe-scroll.d.ts","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/swipe-scroll.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAahE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"swipe-scroll.d.ts","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/swipe-scroll.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAahE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAoChD,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,CA2Cf;AAwGD,wBAAsB,YAAY,CAChC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,aAAa,CAAC,CA8BxB;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,aAAa,CAAC,CA+CxB"}
|
|
@@ -3,6 +3,65 @@ import { execute, getElementRect, getWindowRect, performActions, } from '../../.
|
|
|
3
3
|
import { errorResult, textResult, toolErrorMessage, } from '../../tool-response.js';
|
|
4
4
|
const SCROLL_DURATION_MS = 800;
|
|
5
5
|
const SCROLL_INITIAL_PAUSE_MS = 250;
|
|
6
|
+
/** Pointer move duration for programmatic vertical scroll (matches legacy appium_scroll). */
|
|
7
|
+
const VERTICAL_SCROLL_MOVE_MS = 600;
|
|
8
|
+
function verticalScrollYs(height, direction, distance) {
|
|
9
|
+
const mid = height * 0.5;
|
|
10
|
+
const halfSpan = height * 0.3 * distance;
|
|
11
|
+
if (direction === 'down') {
|
|
12
|
+
return {
|
|
13
|
+
startY: Math.floor(mid + halfSpan),
|
|
14
|
+
endY: Math.floor(mid - halfSpan),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
startY: Math.floor(mid - halfSpan),
|
|
19
|
+
endY: Math.floor(mid + halfSpan),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Vertical swipe in the middle of the window, scaled by `distance` (0.05–1).
|
|
24
|
+
* Used by `appium_gesture` `scroll_to_element`; matches legacy scroll distances.
|
|
25
|
+
*/
|
|
26
|
+
export async function performVerticalScroll(driver, options) {
|
|
27
|
+
const rect = await getWindowRect(driver);
|
|
28
|
+
const { width, height } = rect;
|
|
29
|
+
const startX = Math.floor(width / 2);
|
|
30
|
+
const { startY, endY } = verticalScrollYs(height, options.direction, options.distance);
|
|
31
|
+
if (getPlatformName(driver) === PLATFORM.android) {
|
|
32
|
+
await performActions(driver, [
|
|
33
|
+
{
|
|
34
|
+
type: 'pointer',
|
|
35
|
+
id: 'finger1',
|
|
36
|
+
parameters: { pointerType: 'touch' },
|
|
37
|
+
actions: [
|
|
38
|
+
{ type: 'pointerMove', duration: 0, x: startX, y: startY },
|
|
39
|
+
{ type: 'pointerDown', button: 0 },
|
|
40
|
+
{ type: 'pause', duration: SCROLL_INITIAL_PAUSE_MS },
|
|
41
|
+
{
|
|
42
|
+
type: 'pointerMove',
|
|
43
|
+
duration: VERTICAL_SCROLL_MOVE_MS,
|
|
44
|
+
x: startX,
|
|
45
|
+
y: endY,
|
|
46
|
+
},
|
|
47
|
+
{ type: 'pointerUp', button: 0 },
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
else if (getPlatformName(driver) === PLATFORM.ios) {
|
|
53
|
+
await execute(driver, 'mobile: scroll', {
|
|
54
|
+
direction: options.direction,
|
|
55
|
+
startX,
|
|
56
|
+
startY,
|
|
57
|
+
endX: startX,
|
|
58
|
+
endY,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
throw new Error(`Unsupported platform: ${getPlatformName(driver)}. Only Android and iOS are supported.`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
6
65
|
const SWIPE_SPEED_PROFILES = {
|
|
7
66
|
slow: { duration: 600, initialPause: 250 },
|
|
8
67
|
normal: { duration: 300, initialPause: 200 },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"swipe-scroll.js","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/swipe-scroll.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"swipe-scroll.js","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/swipe-scroll.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,8 @@ export declare const GESTURE_ACTIONS: readonly ["tap", "double_tap", "long_press
|
|
|
3
3
|
export type GestureAction = (typeof GESTURE_ACTIONS)[number];
|
|
4
4
|
export declare const SWIPE_SPEEDS: readonly ["slow", "normal", "fast"];
|
|
5
5
|
export type SwipeSpeed = (typeof SWIPE_SPEEDS)[number];
|
|
6
|
+
export declare const SCROLL_DISTANCE_PRESETS: readonly ["small", "medium", "large"];
|
|
7
|
+
export type ScrollDistancePreset = (typeof SCROLL_DISTANCE_PRESETS)[number];
|
|
6
8
|
export declare const LOCATOR_STRATEGIES: readonly ["xpath", "id", "name", "class name", "accessibility id", "css selector", "-android uiautomator", "-ios predicate string", "-ios class chain"];
|
|
7
9
|
export declare const gestureSchema: z.ZodObject<{
|
|
8
10
|
action: z.ZodEnum<{
|
|
@@ -45,6 +47,13 @@ export declare const gestureSchema: z.ZodObject<{
|
|
|
45
47
|
"css selector": "css selector";
|
|
46
48
|
}>>;
|
|
47
49
|
selector: z.ZodOptional<z.ZodString>;
|
|
50
|
+
maxScrollAttempts: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
51
|
+
scrollDistance: z.ZodOptional<z.ZodNumber>;
|
|
52
|
+
scrollDistancePreset: z.ZodOptional<z.ZodEnum<{
|
|
53
|
+
small: "small";
|
|
54
|
+
medium: "medium";
|
|
55
|
+
large: "large";
|
|
56
|
+
}>>;
|
|
48
57
|
sessionId: z.ZodOptional<z.ZodString>;
|
|
49
58
|
}, z.core.$strip>;
|
|
50
59
|
export type GestureArgs = z.infer<typeof gestureSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/tools/gestures/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,eAAe,oGAQlB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,eAAO,MAAM,YAAY,qCAAsC,CAAC;AAChE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,eAAO,MAAM,kBAAkB,yJAUrB,CAAC;AAEX,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/tools/gestures/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,eAAe,oGAQlB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,eAAO,MAAM,YAAY,qCAAsC,CAAC;AAChE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,eAAO,MAAM,uBAAuB,uCAAwC,CAAC;AAC7E,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E,eAAO,MAAM,kBAAkB,yJAUrB,CAAC;AAEX,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkJxB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
|
@@ -10,6 +10,7 @@ export const GESTURE_ACTIONS = [
|
|
|
10
10
|
'scroll_to_element',
|
|
11
11
|
];
|
|
12
12
|
export const SWIPE_SPEEDS = ['slow', 'normal', 'fast'];
|
|
13
|
+
export const SCROLL_DISTANCE_PRESETS = ['small', 'medium', 'large'];
|
|
13
14
|
export const LOCATOR_STRATEGIES = [
|
|
14
15
|
'xpath',
|
|
15
16
|
'id',
|
|
@@ -31,7 +32,9 @@ export const gestureSchema = z.object({
|
|
|
31
32
|
`scroll: browse a list, feed, or page to reveal content. ` +
|
|
32
33
|
`swipe: dismiss a card, switch screens or tabs, navigate a carousel, or pull-to-refresh (use speed=fast). ` +
|
|
33
34
|
`pinch_zoom: zoom in (scale > 1) or out (scale < 1) on maps, images, or any zoomable view. ` +
|
|
34
|
-
`scroll_to_element: scroll until a specific element is on screen
|
|
35
|
+
`scroll_to_element: scroll until a specific element is on screen (strategy + selector + direction up|down). ` +
|
|
36
|
+
`Stops when the element is found, page source is unchanged after a scroll (end of scrollable content), or maxScrollAttempts is reached. ` +
|
|
37
|
+
`Optional scrollDistance (0.05–1) or scrollDistancePreset (small|medium|large).`),
|
|
35
38
|
elementUUID: elementUUIDScheme
|
|
36
39
|
.optional()
|
|
37
40
|
.describe(`UUID of the element to act on. Supports AI coordinate UUIDs (format: ai-element:x,y:bbox). ` +
|
|
@@ -102,6 +105,26 @@ export const gestureSchema = z.object({
|
|
|
102
105
|
.string()
|
|
103
106
|
.optional()
|
|
104
107
|
.describe(`Locator selector value. Required for: scroll_to_element.`),
|
|
108
|
+
maxScrollAttempts: z
|
|
109
|
+
.number()
|
|
110
|
+
.int()
|
|
111
|
+
.min(1)
|
|
112
|
+
.max(80)
|
|
113
|
+
.optional()
|
|
114
|
+
.default(10)
|
|
115
|
+
.describe(`scroll_to_element only: maximum scroll attempts after the element is not yet visible (default 10).`),
|
|
116
|
+
scrollDistance: z
|
|
117
|
+
.number()
|
|
118
|
+
.min(0.05)
|
|
119
|
+
.max(1)
|
|
120
|
+
.optional()
|
|
121
|
+
.describe(`scroll_to_element only: vertical swipe length as a fraction 0.05–1 (same scale as legacy scroll). ` +
|
|
122
|
+
`Ignored when scrollDistancePreset is set. Default 0.45 if neither preset nor scrollDistance is set.`),
|
|
123
|
+
scrollDistancePreset: z
|
|
124
|
+
.enum(SCROLL_DISTANCE_PRESETS)
|
|
125
|
+
.optional()
|
|
126
|
+
.describe(`scroll_to_element only: convenience preset — small ≈ light nudge (0.25), medium ≈ 0.45, large = full default swipe (1). ` +
|
|
127
|
+
`When set, overrides scrollDistance.`),
|
|
105
128
|
sessionId: z
|
|
106
129
|
.string()
|
|
107
130
|
.optional()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/tools/gestures/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK;IACL,YAAY;IACZ,YAAY;IACZ,QAAQ;IACR,OAAO;IACP,YAAY;IACZ,mBAAmB;CACX,CAAC;AAIX,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAU,CAAC;AAGhE,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,OAAO;IACP,IAAI;IACJ,MAAM;IACN,YAAY;IACZ,kBAAkB;IAClB,cAAc;IACd,sBAAsB;IACtB,uBAAuB;IACvB,kBAAkB;CACV,CAAC;AAEX,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,MAAM,EAAE,CAAC;SACN,IAAI,CAAC,eAAe,CAAC;SACrB,QAAQ,CACP,sBAAsB;QACpB,uCAAuC;QACvC,uFAAuF;QACvF,sEAAsE;QACtE,0DAA0D;QAC1D,2GAA2G;QAC3G,4FAA4F;QAC5F,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/tools/gestures/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../../src/tools/interactions/find.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAuBxB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;iBA+B5B,CAAC;AAEH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../../src/tools/interactions/find.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAuBxB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;iBA+B5B,CAAC;AAEH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAiHzD"}
|
|
@@ -60,7 +60,9 @@ export default function findElement(server) {
|
|
|
60
60
|
- AI_VISION_API_BASE_URL: Vision model API endpoint (required)
|
|
61
61
|
- AI_VISION_API_KEY: API authentication key (required)
|
|
62
62
|
- AI_VISION_MODEL: Model name (optional, defaults to Qwen3-VL-235B-A22B-Instruct)
|
|
63
|
-
- AI_VISION_COORD_TYPE: Coordinate type (optional, defaults to normalized)
|
|
63
|
+
- AI_VISION_COORD_TYPE: Coordinate type (optional, defaults to normalized)
|
|
64
|
+
|
|
65
|
+
**Scrolling until an element appears**: use \`appium_gesture\` with \`action=scroll_to_element\` (same strategy + selector), not this tool.`,
|
|
64
66
|
parameters: findElementSchema,
|
|
65
67
|
annotations: {
|
|
66
68
|
readOnlyHint: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find.js","sourceRoot":"","sources":["../../../src/tools/interactions/find.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,GAAG,MAAM,iBAAiB,CAAC;AAClC,OAAO,EACL,aAAa,EACb,8BAA8B,EAC9B,WAAW,EACX,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,4EAA4E;AAC5E,iFAAiF;AACjF,IAAI,eAAe,GAA0B,IAAI,CAAC;AAClD,SAAS,iBAAiB;IACxB,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,eAAe,GAAG,IAAI,cAAc,EAAE,CAAC;IACzC,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC;QACf,OAAO;QACP,IAAI;QACJ,MAAM;QACN,YAAY;QACZ,kBAAkB;QAClB,cAAc;QACd,sBAAsB;QACtB,uBAAuB;QACvB,kBAAkB;QAClB,gBAAgB,EAAE,yCAAyC;KAC5D,CAAC;IACF,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,oCAAoC;QAClC,wKAAwK;QACxK,oFAAoF,CACvF;IACH,cAAc,EAAE,CAAC;SACd,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,sGAAsG,CACvG;IACH,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,4DAA4D,CAAC;CAC1E,CAAC,CAAC;AAEH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,MAAe;IACjD,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE
|
|
1
|
+
{"version":3,"file":"find.js","sourceRoot":"","sources":["../../../src/tools/interactions/find.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"name": "io.github.appium/appium-mcp",
|
|
4
4
|
"title": "MCP Appium - Mobile Development and Automation Server",
|
|
5
5
|
"description": "MCP server for Appium mobile automation on iOS and Android devices with test creation tools.",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.67.0",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"identifier": "appium-mcp",
|
|
11
|
-
"version": "1.
|
|
11
|
+
"version": "1.67.0",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
}
|
|
Binary file
|
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
import type { ContentResult } from 'fastmcp';
|
|
2
2
|
import type { DriverInstance } from '../../../session-store.js';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { getPageSource } from '../../../command.js';
|
|
4
|
+
import log from '../../../logger.js';
|
|
5
5
|
import {
|
|
6
6
|
errorResult,
|
|
7
7
|
textResult,
|
|
8
8
|
toolErrorMessage,
|
|
9
9
|
} from '../../tool-response.js';
|
|
10
10
|
import type { GestureArgs } from '../schema.js';
|
|
11
|
+
import { performVerticalScroll } from './swipe-scroll.js';
|
|
11
12
|
|
|
12
|
-
const
|
|
13
|
+
const PRESET_TO_DISTANCE: Record<
|
|
14
|
+
NonNullable<GestureArgs['scrollDistancePreset']>,
|
|
15
|
+
number
|
|
16
|
+
> = {
|
|
17
|
+
small: 0.25,
|
|
18
|
+
medium: 0.45,
|
|
19
|
+
large: 1,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function resolveScrollDistance(args: GestureArgs): number {
|
|
23
|
+
if (args.scrollDistancePreset) {
|
|
24
|
+
return PRESET_TO_DISTANCE[args.scrollDistancePreset];
|
|
25
|
+
}
|
|
26
|
+
if (args.scrollDistance !== undefined) {
|
|
27
|
+
return args.scrollDistance;
|
|
28
|
+
}
|
|
29
|
+
return 0.45;
|
|
30
|
+
}
|
|
13
31
|
|
|
14
32
|
async function tryFindElement(
|
|
15
33
|
driver: DriverInstance,
|
|
@@ -24,45 +42,6 @@ async function tryFindElement(
|
|
|
24
42
|
}
|
|
25
43
|
}
|
|
26
44
|
|
|
27
|
-
async function performW3CScroll(
|
|
28
|
-
driver: DriverInstance,
|
|
29
|
-
direction: 'up' | 'down'
|
|
30
|
-
): Promise<void> {
|
|
31
|
-
const { width, height } = await getWindowRect(driver);
|
|
32
|
-
const startX = Math.floor(width / 2);
|
|
33
|
-
const startY =
|
|
34
|
-
direction === 'down' ? Math.floor(height * 0.8) : Math.floor(height * 0.2);
|
|
35
|
-
const endY =
|
|
36
|
-
direction === 'down' ? Math.floor(height * 0.2) : Math.floor(height * 0.8);
|
|
37
|
-
|
|
38
|
-
await performActions(driver, [
|
|
39
|
-
{
|
|
40
|
-
type: 'pointer',
|
|
41
|
-
id: 'finger1',
|
|
42
|
-
parameters: { pointerType: 'touch' },
|
|
43
|
-
actions: [
|
|
44
|
-
{ type: 'pointerMove', duration: 0, x: startX, y: startY },
|
|
45
|
-
{ type: 'pointerDown', button: 0 },
|
|
46
|
-
{ type: 'pause', duration: 250 },
|
|
47
|
-
{ type: 'pointerMove', duration: 600, x: startX, y: endY },
|
|
48
|
-
{ type: 'pointerUp', button: 0 },
|
|
49
|
-
],
|
|
50
|
-
},
|
|
51
|
-
]);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async function scrollOnce(
|
|
55
|
-
driver: DriverInstance,
|
|
56
|
-
direction: 'up' | 'down'
|
|
57
|
-
): Promise<void> {
|
|
58
|
-
const platform = getPlatformName(driver);
|
|
59
|
-
if (platform === PLATFORM.ios) {
|
|
60
|
-
await execute(driver, 'mobile: scroll', { direction });
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
await performW3CScroll(driver, direction);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
45
|
export async function handleScrollToElement(
|
|
67
46
|
driver: DriverInstance,
|
|
68
47
|
args: GestureArgs
|
|
@@ -77,6 +56,14 @@ export async function handleScrollToElement(
|
|
|
77
56
|
? args.direction
|
|
78
57
|
: 'down';
|
|
79
58
|
|
|
59
|
+
const maxScroll = args.maxScrollAttempts;
|
|
60
|
+
if (args.scrollDistancePreset && args.scrollDistance !== undefined) {
|
|
61
|
+
log.warn(
|
|
62
|
+
'scroll_to_element: scrollDistancePreset is set; ignoring scrollDistance'
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
const distance = resolveScrollDistance(args);
|
|
66
|
+
|
|
80
67
|
try {
|
|
81
68
|
if (await tryFindElement(driver, args.strategy, args.selector)) {
|
|
82
69
|
return textResult(
|
|
@@ -84,17 +71,34 @@ export async function handleScrollToElement(
|
|
|
84
71
|
);
|
|
85
72
|
}
|
|
86
73
|
|
|
87
|
-
|
|
88
|
-
|
|
74
|
+
let scrollsDone = 0;
|
|
75
|
+
while (scrollsDone < maxScroll) {
|
|
76
|
+
const xmlBefore = await getPageSource(driver);
|
|
77
|
+
try {
|
|
78
|
+
await performVerticalScroll(driver, { direction, distance });
|
|
79
|
+
} catch (scrollErr: unknown) {
|
|
80
|
+
return errorResult(
|
|
81
|
+
`Scroll failed during scroll_to_element: ${toolErrorMessage(scrollErr)}`
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
const xmlAfter = await getPageSource(driver);
|
|
85
|
+
scrollsDone++;
|
|
86
|
+
|
|
89
87
|
if (await tryFindElement(driver, args.strategy, args.selector)) {
|
|
90
88
|
return textResult(
|
|
91
|
-
`Successfully scrolled to element ${args.selector} after ${
|
|
89
|
+
`Successfully scrolled to element ${args.selector} after ${scrollsDone} scroll(s).`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (xmlBefore === xmlAfter) {
|
|
94
|
+
return errorResult(
|
|
95
|
+
`Element not found; page source did not change after scroll (likely end of scrollable content). selector=${args.selector}`
|
|
92
96
|
);
|
|
93
97
|
}
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
return errorResult(
|
|
97
|
-
`Element ${args.selector} not found after ${
|
|
101
|
+
`Element ${args.selector} not found after ${maxScroll} scroll(s) in direction '${direction}'.`
|
|
98
102
|
);
|
|
99
103
|
} catch (err) {
|
|
100
104
|
return errorResult(`Failed to scroll_to_element. ${toolErrorMessage(err)}`);
|
|
@@ -26,6 +26,84 @@ interface Rect {
|
|
|
26
26
|
|
|
27
27
|
const SCROLL_DURATION_MS = 800;
|
|
28
28
|
const SCROLL_INITIAL_PAUSE_MS = 250;
|
|
29
|
+
/** Pointer move duration for programmatic vertical scroll (matches legacy appium_scroll). */
|
|
30
|
+
const VERTICAL_SCROLL_MOVE_MS = 600;
|
|
31
|
+
|
|
32
|
+
function verticalScrollYs(
|
|
33
|
+
height: number,
|
|
34
|
+
direction: 'up' | 'down',
|
|
35
|
+
distance: number
|
|
36
|
+
): { startY: number; endY: number } {
|
|
37
|
+
const mid = height * 0.5;
|
|
38
|
+
const halfSpan = height * 0.3 * distance;
|
|
39
|
+
if (direction === 'down') {
|
|
40
|
+
return {
|
|
41
|
+
startY: Math.floor(mid + halfSpan),
|
|
42
|
+
endY: Math.floor(mid - halfSpan),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
startY: Math.floor(mid - halfSpan),
|
|
47
|
+
endY: Math.floor(mid + halfSpan),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type VerticalScrollOptions = {
|
|
52
|
+
direction: 'up' | 'down';
|
|
53
|
+
distance: number;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Vertical swipe in the middle of the window, scaled by `distance` (0.05–1).
|
|
58
|
+
* Used by `appium_gesture` `scroll_to_element`; matches legacy scroll distances.
|
|
59
|
+
*/
|
|
60
|
+
export async function performVerticalScroll(
|
|
61
|
+
driver: DriverInstance,
|
|
62
|
+
options: VerticalScrollOptions
|
|
63
|
+
): Promise<void> {
|
|
64
|
+
const rect = await getWindowRect(driver);
|
|
65
|
+
const { width, height } = rect;
|
|
66
|
+
const startX = Math.floor(width / 2);
|
|
67
|
+
const { startY, endY } = verticalScrollYs(
|
|
68
|
+
height,
|
|
69
|
+
options.direction,
|
|
70
|
+
options.distance
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
if (getPlatformName(driver) === PLATFORM.android) {
|
|
74
|
+
await performActions(driver, [
|
|
75
|
+
{
|
|
76
|
+
type: 'pointer',
|
|
77
|
+
id: 'finger1',
|
|
78
|
+
parameters: { pointerType: 'touch' },
|
|
79
|
+
actions: [
|
|
80
|
+
{ type: 'pointerMove', duration: 0, x: startX, y: startY },
|
|
81
|
+
{ type: 'pointerDown', button: 0 },
|
|
82
|
+
{ type: 'pause', duration: SCROLL_INITIAL_PAUSE_MS },
|
|
83
|
+
{
|
|
84
|
+
type: 'pointerMove',
|
|
85
|
+
duration: VERTICAL_SCROLL_MOVE_MS,
|
|
86
|
+
x: startX,
|
|
87
|
+
y: endY,
|
|
88
|
+
},
|
|
89
|
+
{ type: 'pointerUp', button: 0 },
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
]);
|
|
93
|
+
} else if (getPlatformName(driver) === PLATFORM.ios) {
|
|
94
|
+
await execute(driver, 'mobile: scroll', {
|
|
95
|
+
direction: options.direction,
|
|
96
|
+
startX,
|
|
97
|
+
startY,
|
|
98
|
+
endX: startX,
|
|
99
|
+
endY,
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Unsupported platform: ${getPlatformName(driver)}. Only Android and iOS are supported.`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
29
107
|
|
|
30
108
|
const SWIPE_SPEED_PROFILES = {
|
|
31
109
|
slow: { duration: 600, initialPause: 250 },
|
|
@@ -16,6 +16,9 @@ export type GestureAction = (typeof GESTURE_ACTIONS)[number];
|
|
|
16
16
|
export const SWIPE_SPEEDS = ['slow', 'normal', 'fast'] as const;
|
|
17
17
|
export type SwipeSpeed = (typeof SWIPE_SPEEDS)[number];
|
|
18
18
|
|
|
19
|
+
export const SCROLL_DISTANCE_PRESETS = ['small', 'medium', 'large'] as const;
|
|
20
|
+
export type ScrollDistancePreset = (typeof SCROLL_DISTANCE_PRESETS)[number];
|
|
21
|
+
|
|
19
22
|
export const LOCATOR_STRATEGIES = [
|
|
20
23
|
'xpath',
|
|
21
24
|
'id',
|
|
@@ -39,7 +42,9 @@ export const gestureSchema = z.object({
|
|
|
39
42
|
`scroll: browse a list, feed, or page to reveal content. ` +
|
|
40
43
|
`swipe: dismiss a card, switch screens or tabs, navigate a carousel, or pull-to-refresh (use speed=fast). ` +
|
|
41
44
|
`pinch_zoom: zoom in (scale > 1) or out (scale < 1) on maps, images, or any zoomable view. ` +
|
|
42
|
-
`scroll_to_element: scroll until a specific element is on screen
|
|
45
|
+
`scroll_to_element: scroll until a specific element is on screen (strategy + selector + direction up|down). ` +
|
|
46
|
+
`Stops when the element is found, page source is unchanged after a scroll (end of scrollable content), or maxScrollAttempts is reached. ` +
|
|
47
|
+
`Optional scrollDistance (0.05–1) or scrollDistancePreset (small|medium|large).`
|
|
43
48
|
),
|
|
44
49
|
|
|
45
50
|
elementUUID: elementUUIDScheme
|
|
@@ -139,6 +144,35 @@ export const gestureSchema = z.object({
|
|
|
139
144
|
.optional()
|
|
140
145
|
.describe(`Locator selector value. Required for: scroll_to_element.`),
|
|
141
146
|
|
|
147
|
+
maxScrollAttempts: z
|
|
148
|
+
.number()
|
|
149
|
+
.int()
|
|
150
|
+
.min(1)
|
|
151
|
+
.max(80)
|
|
152
|
+
.optional()
|
|
153
|
+
.default(10)
|
|
154
|
+
.describe(
|
|
155
|
+
`scroll_to_element only: maximum scroll attempts after the element is not yet visible (default 10).`
|
|
156
|
+
),
|
|
157
|
+
|
|
158
|
+
scrollDistance: z
|
|
159
|
+
.number()
|
|
160
|
+
.min(0.05)
|
|
161
|
+
.max(1)
|
|
162
|
+
.optional()
|
|
163
|
+
.describe(
|
|
164
|
+
`scroll_to_element only: vertical swipe length as a fraction 0.05–1 (same scale as legacy scroll). ` +
|
|
165
|
+
`Ignored when scrollDistancePreset is set. Default 0.45 if neither preset nor scrollDistance is set.`
|
|
166
|
+
),
|
|
167
|
+
|
|
168
|
+
scrollDistancePreset: z
|
|
169
|
+
.enum(SCROLL_DISTANCE_PRESETS)
|
|
170
|
+
.optional()
|
|
171
|
+
.describe(
|
|
172
|
+
`scroll_to_element only: convenience preset — small ≈ light nudge (0.25), medium ≈ 0.45, large = full default swipe (1). ` +
|
|
173
|
+
`When set, overrides scrollDistance.`
|
|
174
|
+
),
|
|
175
|
+
|
|
142
176
|
sessionId: z
|
|
143
177
|
.string()
|
|
144
178
|
.optional()
|
|
@@ -74,7 +74,9 @@ export default function findElement(server: FastMCP): void {
|
|
|
74
74
|
- AI_VISION_API_BASE_URL: Vision model API endpoint (required)
|
|
75
75
|
- AI_VISION_API_KEY: API authentication key (required)
|
|
76
76
|
- AI_VISION_MODEL: Model name (optional, defaults to Qwen3-VL-235B-A22B-Instruct)
|
|
77
|
-
- AI_VISION_COORD_TYPE: Coordinate type (optional, defaults to normalized)
|
|
77
|
+
- AI_VISION_COORD_TYPE: Coordinate type (optional, defaults to normalized)
|
|
78
|
+
|
|
79
|
+
**Scrolling until an element appears**: use \`appium_gesture\` with \`action=scroll_to_element\` (same strategy + selector), not this tool.`,
|
|
78
80
|
parameters: findElementSchema,
|
|
79
81
|
annotations: {
|
|
80
82
|
readOnlyHint: true,
|