appium-mcp 1.67.0 → 1.67.1
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/dist/tools/gestures/handlers/pinch.d.ts +13 -0
- package/dist/tools/gestures/handlers/pinch.d.ts.map +1 -1
- package/dist/tools/gestures/handlers/pinch.js +129 -10
- package/dist/tools/gestures/handlers/pinch.js.map +1 -1
- package/dist/tools/gestures/schema.d.ts.map +1 -1
- package/dist/tools/gestures/schema.js +4 -2
- package/dist/tools/gestures/schema.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/pinch.ts +184 -10
- package/src/tools/gestures/schema.ts +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [1.67.1](https://github.com/appium/appium-mcp/compare/v1.67.0...v1.67.1) (2026-04-27)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* support zoom in/out via custom coords ([#291](https://github.com/appium/appium-mcp/issues/291)) ([251e144](https://github.com/appium/appium-mcp/commit/251e144f9a21ca0909df93ba52bc8b748e4e20b4))
|
|
6
|
+
|
|
1
7
|
## [1.67.0](https://github.com/appium/appium-mcp/compare/v1.66.0...v1.67.0) (2026-04-23)
|
|
2
8
|
|
|
3
9
|
### Features
|
|
@@ -1,5 +1,18 @@
|
|
|
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
|
+
type RectLike = {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
};
|
|
10
|
+
type PinchTarget = {
|
|
11
|
+
cx: number;
|
|
12
|
+
cy: number;
|
|
13
|
+
spread: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function resolveElementPinchTarget(elementRect: RectLike, windowRect: RectLike): PinchTarget;
|
|
4
16
|
export declare function handlePinchZoom(driver: DriverInstance, args: GestureArgs): Promise<ContentResult>;
|
|
17
|
+
export {};
|
|
5
18
|
//# sourceMappingURL=pinch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pinch.d.ts","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/pinch.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":"pinch.d.ts","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/pinch.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;AAMhD,KAAK,QAAQ,GAAG;IACd,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAmBF,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,QAAQ,EACrB,UAAU,EAAE,QAAQ,GACnB,WAAW,CAyCb;AAwCD,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,aAAa,CAAC,CA6JxB"}
|
|
@@ -2,12 +2,79 @@ import { getPlatformName, PLATFORM } from '../../../session-store.js';
|
|
|
2
2
|
import { execute, getElementRect, getWindowRect, performActions, } from '../../../command.js';
|
|
3
3
|
import { errorResult, textResult, toolErrorMessage, } from '../../tool-response.js';
|
|
4
4
|
const DEFAULT_VELOCITY = 2.2;
|
|
5
|
+
const DEFAULT_PINCH_SPREAD_RATIO = 0.3;
|
|
6
|
+
const MIN_ELEMENT_PINCH_SPREAD_RATIO = 0.15;
|
|
7
|
+
function clamp(value, min, max) {
|
|
8
|
+
return Math.min(max, Math.max(min, value));
|
|
9
|
+
}
|
|
10
|
+
function maxSpreadForCenter(cx, cy, windowRect) {
|
|
11
|
+
const left = windowRect.x ?? 0;
|
|
12
|
+
const top = windowRect.y ?? 0;
|
|
13
|
+
const right = left + windowRect.width - 1;
|
|
14
|
+
const bottom = top + windowRect.height - 1;
|
|
15
|
+
return Math.max(1, Math.min(cx - left, right - cx, cy - top, bottom - cy));
|
|
16
|
+
}
|
|
17
|
+
export function resolveElementPinchTarget(elementRect, windowRect) {
|
|
18
|
+
const windowLeft = windowRect.x ?? 0;
|
|
19
|
+
const windowTop = windowRect.y ?? 0;
|
|
20
|
+
const windowRight = windowLeft + windowRect.width;
|
|
21
|
+
const windowBottom = windowTop + windowRect.height;
|
|
22
|
+
const visibleLeft = Math.max(windowLeft, elementRect.x);
|
|
23
|
+
const visibleTop = Math.max(windowTop, elementRect.y);
|
|
24
|
+
const visibleRight = Math.min(windowRight, elementRect.x + elementRect.width);
|
|
25
|
+
const visibleBottom = Math.min(windowBottom, elementRect.y + elementRect.height);
|
|
26
|
+
const rawCx = visibleRight > visibleLeft
|
|
27
|
+
? visibleLeft + (visibleRight - visibleLeft) / 2
|
|
28
|
+
: elementRect.x + elementRect.width / 2;
|
|
29
|
+
const rawCy = visibleBottom > visibleTop
|
|
30
|
+
? visibleTop + (visibleBottom - visibleTop) / 2
|
|
31
|
+
: elementRect.y + elementRect.height / 2;
|
|
32
|
+
const cx = Math.floor(clamp(rawCx, windowLeft, windowRight - 1));
|
|
33
|
+
const cy = Math.floor(clamp(rawCy, windowTop, windowBottom - 1));
|
|
34
|
+
const windowBase = Math.min(windowRect.width, windowRect.height);
|
|
35
|
+
const elementBase = Math.min(elementRect.width, elementRect.height);
|
|
36
|
+
const desired = Math.max(Math.floor(elementBase * DEFAULT_PINCH_SPREAD_RATIO), Math.floor(windowBase * MIN_ELEMENT_PINCH_SPREAD_RATIO));
|
|
37
|
+
const cappedDesired = Math.min(desired, Math.floor(windowBase * DEFAULT_PINCH_SPREAD_RATIO));
|
|
38
|
+
return {
|
|
39
|
+
cx,
|
|
40
|
+
cy,
|
|
41
|
+
spread: Math.min(cappedDesired, maxSpreadForCenter(cx, cy, windowRect)),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function resolveWindowPinchTarget(windowRect) {
|
|
45
|
+
const cx = Math.floor((windowRect.x ?? 0) + windowRect.width / 2);
|
|
46
|
+
const cy = Math.floor((windowRect.y ?? 0) + windowRect.height / 2);
|
|
47
|
+
return {
|
|
48
|
+
cx,
|
|
49
|
+
cy,
|
|
50
|
+
spread: Math.floor(Math.min(windowRect.width, windowRect.height) * DEFAULT_PINCH_SPREAD_RATIO),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function resolveCoordinatePinchTarget(x, y, windowRect) {
|
|
54
|
+
const left = windowRect.x ?? 0;
|
|
55
|
+
const top = windowRect.y ?? 0;
|
|
56
|
+
const right = left + windowRect.width;
|
|
57
|
+
const bottom = top + windowRect.height;
|
|
58
|
+
if (x < left || x >= right || y < top || y >= bottom) {
|
|
59
|
+
return `pinch_zoom coordinates (${x}, ${y}) are outside window bounds (${windowRect.width}x${windowRect.height}).`;
|
|
60
|
+
}
|
|
61
|
+
const desired = Math.floor(Math.min(windowRect.width, windowRect.height) * DEFAULT_PINCH_SPREAD_RATIO);
|
|
62
|
+
return {
|
|
63
|
+
cx: x,
|
|
64
|
+
cy: y,
|
|
65
|
+
spread: Math.min(desired, maxSpreadForCenter(x, y, windowRect)),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
5
68
|
export async function handlePinchZoom(driver, args) {
|
|
6
69
|
if (args.scale === undefined) {
|
|
7
70
|
return errorResult('pinch_zoom requires a scale value (e.g. 0.5 to zoom out, 2.0 to zoom in).');
|
|
8
71
|
}
|
|
9
72
|
const scale = args.scale;
|
|
10
73
|
const velocity = args.velocity ?? DEFAULT_VELOCITY;
|
|
74
|
+
if (!args.elementUUID && (args.x !== undefined) !== (args.y !== undefined)) {
|
|
75
|
+
return errorResult('pinch_zoom requires both x and y when using custom coordinates.');
|
|
76
|
+
}
|
|
77
|
+
const useCustomCoords = !args.elementUUID && args.x !== undefined && args.y !== undefined;
|
|
11
78
|
try {
|
|
12
79
|
const platform = getPlatformName(driver);
|
|
13
80
|
let cx;
|
|
@@ -15,19 +82,24 @@ export async function handlePinchZoom(driver, args) {
|
|
|
15
82
|
let spread;
|
|
16
83
|
let windowRect = null;
|
|
17
84
|
if (args.elementUUID) {
|
|
85
|
+
windowRect = await getWindowRect(driver);
|
|
18
86
|
const rect = await getElementRect(driver, args.elementUUID);
|
|
19
|
-
cx =
|
|
20
|
-
|
|
21
|
-
|
|
87
|
+
({ cx, cy, spread } = resolveElementPinchTarget(rect, windowRect));
|
|
88
|
+
}
|
|
89
|
+
else if (useCustomCoords) {
|
|
90
|
+
windowRect = await getWindowRect(driver);
|
|
91
|
+
const target = resolveCoordinatePinchTarget(args.x, args.y, windowRect);
|
|
92
|
+
if (typeof target === 'string') {
|
|
93
|
+
return errorResult(target);
|
|
94
|
+
}
|
|
95
|
+
({ cx, cy, spread } = target);
|
|
22
96
|
}
|
|
23
97
|
else {
|
|
24
98
|
windowRect = await getWindowRect(driver);
|
|
25
|
-
cx =
|
|
26
|
-
cy = Math.floor(windowRect.height / 2);
|
|
27
|
-
spread = Math.floor(Math.min(windowRect.width, windowRect.height) * 0.3);
|
|
99
|
+
({ cx, cy, spread } = resolveWindowPinchTarget(windowRect));
|
|
28
100
|
}
|
|
29
101
|
if (scale < 1) {
|
|
30
|
-
// Zoom out:
|
|
102
|
+
// Zoom out: W3C Actions on all platforms; fingers move together.
|
|
31
103
|
const startSpread = spread;
|
|
32
104
|
const endSpread = Math.max(1, Math.floor(spread * scale));
|
|
33
105
|
const duration = Math.floor((1 / Math.abs(velocity)) * 1000);
|
|
@@ -56,6 +128,49 @@ export async function handlePinchZoom(driver, args) {
|
|
|
56
128
|
},
|
|
57
129
|
]);
|
|
58
130
|
}
|
|
131
|
+
else if (useCustomCoords && platform === PLATFORM.android) {
|
|
132
|
+
// Zoom in at a custom center on Android: use the native pinchOpenGesture
|
|
133
|
+
// with a region centered at (cx, cy). spread is pre-clamped so the region
|
|
134
|
+
// fits within the window.
|
|
135
|
+
const percent = Math.min(0.99, 1 - 1 / scale);
|
|
136
|
+
await execute(driver, 'mobile: pinchOpenGesture', {
|
|
137
|
+
left: cx - spread,
|
|
138
|
+
top: cy - spread,
|
|
139
|
+
width: 2 * spread,
|
|
140
|
+
height: 2 * spread,
|
|
141
|
+
percent,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else if (useCustomCoords) {
|
|
145
|
+
// Zoom in at a custom center on iOS using W3C Actions
|
|
146
|
+
const startSpread = Math.max(1, Math.floor(spread / scale));
|
|
147
|
+
const endSpread = spread;
|
|
148
|
+
const duration = Math.floor((1 / Math.abs(velocity)) * 1000);
|
|
149
|
+
await performActions(driver, [
|
|
150
|
+
{
|
|
151
|
+
type: 'pointer',
|
|
152
|
+
id: 'finger1',
|
|
153
|
+
parameters: { pointerType: 'touch' },
|
|
154
|
+
actions: [
|
|
155
|
+
{ type: 'pointerMove', duration: 0, x: cx - startSpread, y: cy },
|
|
156
|
+
{ type: 'pointerDown', button: 0 },
|
|
157
|
+
{ type: 'pointerMove', duration, x: cx - endSpread, y: cy },
|
|
158
|
+
{ type: 'pointerUp', button: 0 },
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
type: 'pointer',
|
|
163
|
+
id: 'finger2',
|
|
164
|
+
parameters: { pointerType: 'touch' },
|
|
165
|
+
actions: [
|
|
166
|
+
{ type: 'pointerMove', duration: 0, x: cx + startSpread, y: cy },
|
|
167
|
+
{ type: 'pointerDown', button: 0 },
|
|
168
|
+
{ type: 'pointerMove', duration, x: cx + endSpread, y: cy },
|
|
169
|
+
{ type: 'pointerUp', button: 0 },
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
]);
|
|
173
|
+
}
|
|
59
174
|
else if (platform === PLATFORM.ios) {
|
|
60
175
|
const params = {
|
|
61
176
|
scale,
|
|
@@ -67,8 +182,8 @@ export async function handlePinchZoom(driver, args) {
|
|
|
67
182
|
await execute(driver, 'mobile: pinch', params);
|
|
68
183
|
}
|
|
69
184
|
else if (platform === PLATFORM.android) {
|
|
70
|
-
// Convert scale factor to percent (0
|
|
71
|
-
// scale=2
|
|
185
|
+
// Convert scale factor to percent (0-1) for pinchOpenGesture.
|
|
186
|
+
// scale=2 -> 0.5, scale=4 -> 0.75, scale=10 -> 0.9. Capped at 0.99.
|
|
72
187
|
const percent = Math.min(0.99, 1 - 1 / scale);
|
|
73
188
|
const params = { percent };
|
|
74
189
|
if (args.elementUUID) {
|
|
@@ -87,7 +202,11 @@ export async function handlePinchZoom(driver, args) {
|
|
|
87
202
|
return errorResult(`pinch_zoom is not supported on platform '${platform}'. Supported: iOS, Android.`);
|
|
88
203
|
}
|
|
89
204
|
const direction = scale < 1 ? 'out' : 'in';
|
|
90
|
-
const target = args.elementUUID
|
|
205
|
+
const target = args.elementUUID
|
|
206
|
+
? `element ${args.elementUUID}`
|
|
207
|
+
: useCustomCoords
|
|
208
|
+
? `coordinates (${cx}, ${cy})`
|
|
209
|
+
: 'screen';
|
|
91
210
|
return textResult(`Successfully pinched ${direction} (scale=${scale}) on ${target}.`);
|
|
92
211
|
}
|
|
93
212
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pinch.js","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/pinch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EACL,OAAO,EACP,cAAc,EACd,aAAa,EACb,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,WAAW,EACX,UAAU,EACV,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAGhC,MAAM,gBAAgB,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"pinch.js","sourceRoot":"","sources":["../../../../src/tools/gestures/handlers/pinch.ts"],"names":[],"mappings":"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"}
|
|
@@ -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,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoJxB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
|
@@ -47,7 +47,8 @@ export const gestureSchema = z.object({
|
|
|
47
47
|
.optional()
|
|
48
48
|
.describe(`X coordinate. ` +
|
|
49
49
|
`For tap/double_tap/long_press: tap location (alternative to elementUUID). ` +
|
|
50
|
-
`For scroll/swipe: starting X for custom-coordinate mode (requires y, endX, endY)
|
|
50
|
+
`For scroll/swipe: starting X for custom-coordinate mode (requires y, endX, endY). ` +
|
|
51
|
+
`For pinch_zoom: center X of the pinch. Requires y. Ignored if elementUUID is set.`),
|
|
51
52
|
y: z
|
|
52
53
|
.number()
|
|
53
54
|
.int()
|
|
@@ -55,7 +56,8 @@ export const gestureSchema = z.object({
|
|
|
55
56
|
.optional()
|
|
56
57
|
.describe(`Y coordinate. ` +
|
|
57
58
|
`For tap/double_tap/long_press: tap location. ` +
|
|
58
|
-
`For scroll/swipe: starting Y for custom-coordinate mode
|
|
59
|
+
`For scroll/swipe: starting Y for custom-coordinate mode. ` +
|
|
60
|
+
`For pinch_zoom: center Y of the pinch. Requires x. Ignored if elementUUID is set.`),
|
|
59
61
|
endX: z
|
|
60
62
|
.number()
|
|
61
63
|
.int()
|
|
@@ -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,uBAAuB,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAU,CAAC;AAG7E,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,6GAA6G;QAC7G,yIAAyI;QACzI,gFAAgF,CACnF;IAEH,WAAW,EAAE,iBAAiB;SAC3B,QAAQ,EAAE;SACV,QAAQ,CACP,6FAA6F;QAC3F,oDAAoD;QACpD,iIAAiI,CACpI;IAEH,CAAC,EAAE,CAAC;SACD,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CACP,gBAAgB;QACd,4EAA4E;QAC5E,mFAAmF,CACtF;IACH,CAAC,EAAE,CAAC;SACD,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CACP,gBAAgB;QACd,+CAA+C;QAC/C,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/tools/gestures/schema.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.67.
|
|
6
|
+
"version": "1.67.1",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"identifier": "appium-mcp",
|
|
11
|
-
"version": "1.67.
|
|
11
|
+
"version": "1.67.1",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
}
|
|
Binary file
|
|
@@ -15,6 +15,122 @@ import {
|
|
|
15
15
|
import type { GestureArgs } from '../schema.js';
|
|
16
16
|
|
|
17
17
|
const DEFAULT_VELOCITY = 2.2;
|
|
18
|
+
const DEFAULT_PINCH_SPREAD_RATIO = 0.3;
|
|
19
|
+
const MIN_ELEMENT_PINCH_SPREAD_RATIO = 0.15;
|
|
20
|
+
|
|
21
|
+
type RectLike = {
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type PinchTarget = {
|
|
29
|
+
cx: number;
|
|
30
|
+
cy: number;
|
|
31
|
+
spread: number;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function clamp(value: number, min: number, max: number): number {
|
|
35
|
+
return Math.min(max, Math.max(min, value));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function maxSpreadForCenter(
|
|
39
|
+
cx: number,
|
|
40
|
+
cy: number,
|
|
41
|
+
windowRect: RectLike
|
|
42
|
+
): number {
|
|
43
|
+
const left = windowRect.x ?? 0;
|
|
44
|
+
const top = windowRect.y ?? 0;
|
|
45
|
+
const right = left + windowRect.width - 1;
|
|
46
|
+
const bottom = top + windowRect.height - 1;
|
|
47
|
+
|
|
48
|
+
return Math.max(1, Math.min(cx - left, right - cx, cy - top, bottom - cy));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function resolveElementPinchTarget(
|
|
52
|
+
elementRect: RectLike,
|
|
53
|
+
windowRect: RectLike
|
|
54
|
+
): PinchTarget {
|
|
55
|
+
const windowLeft = windowRect.x ?? 0;
|
|
56
|
+
const windowTop = windowRect.y ?? 0;
|
|
57
|
+
const windowRight = windowLeft + windowRect.width;
|
|
58
|
+
const windowBottom = windowTop + windowRect.height;
|
|
59
|
+
|
|
60
|
+
const visibleLeft = Math.max(windowLeft, elementRect.x);
|
|
61
|
+
const visibleTop = Math.max(windowTop, elementRect.y);
|
|
62
|
+
const visibleRight = Math.min(windowRight, elementRect.x + elementRect.width);
|
|
63
|
+
const visibleBottom = Math.min(
|
|
64
|
+
windowBottom,
|
|
65
|
+
elementRect.y + elementRect.height
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const rawCx =
|
|
69
|
+
visibleRight > visibleLeft
|
|
70
|
+
? visibleLeft + (visibleRight - visibleLeft) / 2
|
|
71
|
+
: elementRect.x + elementRect.width / 2;
|
|
72
|
+
const rawCy =
|
|
73
|
+
visibleBottom > visibleTop
|
|
74
|
+
? visibleTop + (visibleBottom - visibleTop) / 2
|
|
75
|
+
: elementRect.y + elementRect.height / 2;
|
|
76
|
+
|
|
77
|
+
const cx = Math.floor(clamp(rawCx, windowLeft, windowRight - 1));
|
|
78
|
+
const cy = Math.floor(clamp(rawCy, windowTop, windowBottom - 1));
|
|
79
|
+
const windowBase = Math.min(windowRect.width, windowRect.height);
|
|
80
|
+
const elementBase = Math.min(elementRect.width, elementRect.height);
|
|
81
|
+
const desired = Math.max(
|
|
82
|
+
Math.floor(elementBase * DEFAULT_PINCH_SPREAD_RATIO),
|
|
83
|
+
Math.floor(windowBase * MIN_ELEMENT_PINCH_SPREAD_RATIO)
|
|
84
|
+
);
|
|
85
|
+
const cappedDesired = Math.min(
|
|
86
|
+
desired,
|
|
87
|
+
Math.floor(windowBase * DEFAULT_PINCH_SPREAD_RATIO)
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
cx,
|
|
92
|
+
cy,
|
|
93
|
+
spread: Math.min(cappedDesired, maxSpreadForCenter(cx, cy, windowRect)),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function resolveWindowPinchTarget(windowRect: RectLike): PinchTarget {
|
|
98
|
+
const cx = Math.floor((windowRect.x ?? 0) + windowRect.width / 2);
|
|
99
|
+
const cy = Math.floor((windowRect.y ?? 0) + windowRect.height / 2);
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
cx,
|
|
103
|
+
cy,
|
|
104
|
+
spread: Math.floor(
|
|
105
|
+
Math.min(windowRect.width, windowRect.height) * DEFAULT_PINCH_SPREAD_RATIO
|
|
106
|
+
),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function resolveCoordinatePinchTarget(
|
|
111
|
+
x: number,
|
|
112
|
+
y: number,
|
|
113
|
+
windowRect: RectLike
|
|
114
|
+
): PinchTarget | string {
|
|
115
|
+
const left = windowRect.x ?? 0;
|
|
116
|
+
const top = windowRect.y ?? 0;
|
|
117
|
+
const right = left + windowRect.width;
|
|
118
|
+
const bottom = top + windowRect.height;
|
|
119
|
+
|
|
120
|
+
if (x < left || x >= right || y < top || y >= bottom) {
|
|
121
|
+
return `pinch_zoom coordinates (${x}, ${y}) are outside window bounds (${windowRect.width}x${windowRect.height}).`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const desired = Math.floor(
|
|
125
|
+
Math.min(windowRect.width, windowRect.height) * DEFAULT_PINCH_SPREAD_RATIO
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
cx: x,
|
|
130
|
+
cy: y,
|
|
131
|
+
spread: Math.min(desired, maxSpreadForCenter(x, y, windowRect)),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
18
134
|
|
|
19
135
|
export async function handlePinchZoom(
|
|
20
136
|
driver: DriverInstance,
|
|
@@ -28,6 +144,14 @@ export async function handlePinchZoom(
|
|
|
28
144
|
const scale = args.scale;
|
|
29
145
|
const velocity = args.velocity ?? DEFAULT_VELOCITY;
|
|
30
146
|
|
|
147
|
+
if (!args.elementUUID && (args.x !== undefined) !== (args.y !== undefined)) {
|
|
148
|
+
return errorResult(
|
|
149
|
+
'pinch_zoom requires both x and y when using custom coordinates.'
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
const useCustomCoords =
|
|
153
|
+
!args.elementUUID && args.x !== undefined && args.y !== undefined;
|
|
154
|
+
|
|
31
155
|
try {
|
|
32
156
|
const platform = getPlatformName(driver);
|
|
33
157
|
|
|
@@ -37,23 +161,69 @@ export async function handlePinchZoom(
|
|
|
37
161
|
let windowRect: Awaited<ReturnType<typeof getWindowRect>> | null = null;
|
|
38
162
|
|
|
39
163
|
if (args.elementUUID) {
|
|
164
|
+
windowRect = await getWindowRect(driver);
|
|
40
165
|
const rect = await getElementRect(driver, args.elementUUID);
|
|
41
|
-
cx =
|
|
42
|
-
|
|
43
|
-
|
|
166
|
+
({ cx, cy, spread } = resolveElementPinchTarget(rect, windowRect));
|
|
167
|
+
} else if (useCustomCoords) {
|
|
168
|
+
windowRect = await getWindowRect(driver);
|
|
169
|
+
const target = resolveCoordinatePinchTarget(args.x!, args.y!, windowRect);
|
|
170
|
+
if (typeof target === 'string') {
|
|
171
|
+
return errorResult(target);
|
|
172
|
+
}
|
|
173
|
+
({ cx, cy, spread } = target);
|
|
44
174
|
} else {
|
|
45
175
|
windowRect = await getWindowRect(driver);
|
|
46
|
-
cx =
|
|
47
|
-
cy = Math.floor(windowRect.height / 2);
|
|
48
|
-
spread = Math.floor(Math.min(windowRect.width, windowRect.height) * 0.3);
|
|
176
|
+
({ cx, cy, spread } = resolveWindowPinchTarget(windowRect));
|
|
49
177
|
}
|
|
50
178
|
|
|
51
179
|
if (scale < 1) {
|
|
52
|
-
// Zoom out:
|
|
180
|
+
// Zoom out: W3C Actions on all platforms; fingers move together.
|
|
53
181
|
const startSpread = spread;
|
|
54
182
|
const endSpread = Math.max(1, Math.floor(spread * scale));
|
|
55
183
|
const duration = Math.floor((1 / Math.abs(velocity)) * 1000);
|
|
56
184
|
|
|
185
|
+
await performActions(driver, [
|
|
186
|
+
{
|
|
187
|
+
type: 'pointer',
|
|
188
|
+
id: 'finger1',
|
|
189
|
+
parameters: { pointerType: 'touch' },
|
|
190
|
+
actions: [
|
|
191
|
+
{ type: 'pointerMove', duration: 0, x: cx - startSpread, y: cy },
|
|
192
|
+
{ type: 'pointerDown', button: 0 },
|
|
193
|
+
{ type: 'pointerMove', duration, x: cx - endSpread, y: cy },
|
|
194
|
+
{ type: 'pointerUp', button: 0 },
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
type: 'pointer',
|
|
199
|
+
id: 'finger2',
|
|
200
|
+
parameters: { pointerType: 'touch' },
|
|
201
|
+
actions: [
|
|
202
|
+
{ type: 'pointerMove', duration: 0, x: cx + startSpread, y: cy },
|
|
203
|
+
{ type: 'pointerDown', button: 0 },
|
|
204
|
+
{ type: 'pointerMove', duration, x: cx + endSpread, y: cy },
|
|
205
|
+
{ type: 'pointerUp', button: 0 },
|
|
206
|
+
],
|
|
207
|
+
},
|
|
208
|
+
]);
|
|
209
|
+
} else if (useCustomCoords && platform === PLATFORM.android) {
|
|
210
|
+
// Zoom in at a custom center on Android: use the native pinchOpenGesture
|
|
211
|
+
// with a region centered at (cx, cy). spread is pre-clamped so the region
|
|
212
|
+
// fits within the window.
|
|
213
|
+
const percent = Math.min(0.99, 1 - 1 / scale);
|
|
214
|
+
await execute(driver, 'mobile: pinchOpenGesture', {
|
|
215
|
+
left: cx - spread,
|
|
216
|
+
top: cy - spread,
|
|
217
|
+
width: 2 * spread,
|
|
218
|
+
height: 2 * spread,
|
|
219
|
+
percent,
|
|
220
|
+
});
|
|
221
|
+
} else if (useCustomCoords) {
|
|
222
|
+
// Zoom in at a custom center on iOS using W3C Actions
|
|
223
|
+
const startSpread = Math.max(1, Math.floor(spread / scale));
|
|
224
|
+
const endSpread = spread;
|
|
225
|
+
const duration = Math.floor((1 / Math.abs(velocity)) * 1000);
|
|
226
|
+
|
|
57
227
|
await performActions(driver, [
|
|
58
228
|
{
|
|
59
229
|
type: 'pointer',
|
|
@@ -88,8 +258,8 @@ export async function handlePinchZoom(
|
|
|
88
258
|
}
|
|
89
259
|
await execute(driver, 'mobile: pinch', params);
|
|
90
260
|
} else if (platform === PLATFORM.android) {
|
|
91
|
-
// Convert scale factor to percent (0
|
|
92
|
-
// scale=2
|
|
261
|
+
// Convert scale factor to percent (0-1) for pinchOpenGesture.
|
|
262
|
+
// scale=2 -> 0.5, scale=4 -> 0.75, scale=10 -> 0.9. Capped at 0.99.
|
|
93
263
|
const percent = Math.min(0.99, 1 - 1 / scale);
|
|
94
264
|
const params: Record<string, unknown> = { percent };
|
|
95
265
|
if (args.elementUUID) {
|
|
@@ -109,7 +279,11 @@ export async function handlePinchZoom(
|
|
|
109
279
|
}
|
|
110
280
|
|
|
111
281
|
const direction = scale < 1 ? 'out' : 'in';
|
|
112
|
-
const target = args.elementUUID
|
|
282
|
+
const target = args.elementUUID
|
|
283
|
+
? `element ${args.elementUUID}`
|
|
284
|
+
: useCustomCoords
|
|
285
|
+
? `coordinates (${cx}, ${cy})`
|
|
286
|
+
: 'screen';
|
|
113
287
|
return textResult(
|
|
114
288
|
`Successfully pinched ${direction} (scale=${scale}) on ${target}.`
|
|
115
289
|
);
|
|
@@ -63,7 +63,8 @@ export const gestureSchema = z.object({
|
|
|
63
63
|
.describe(
|
|
64
64
|
`X coordinate. ` +
|
|
65
65
|
`For tap/double_tap/long_press: tap location (alternative to elementUUID). ` +
|
|
66
|
-
`For scroll/swipe: starting X for custom-coordinate mode (requires y, endX, endY)
|
|
66
|
+
`For scroll/swipe: starting X for custom-coordinate mode (requires y, endX, endY). ` +
|
|
67
|
+
`For pinch_zoom: center X of the pinch. Requires y. Ignored if elementUUID is set.`
|
|
67
68
|
),
|
|
68
69
|
y: z
|
|
69
70
|
.number()
|
|
@@ -73,7 +74,8 @@ export const gestureSchema = z.object({
|
|
|
73
74
|
.describe(
|
|
74
75
|
`Y coordinate. ` +
|
|
75
76
|
`For tap/double_tap/long_press: tap location. ` +
|
|
76
|
-
`For scroll/swipe: starting Y for custom-coordinate mode
|
|
77
|
+
`For scroll/swipe: starting Y for custom-coordinate mode. ` +
|
|
78
|
+
`For pinch_zoom: center Y of the pinch. Requires x. Ignored if elementUUID is set.`
|
|
77
79
|
),
|
|
78
80
|
endX: z
|
|
79
81
|
.number()
|