appium-mcp 1.24.2 → 1.25.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 CHANGED
@@ -1,3 +1,9 @@
1
+ ## [1.25.0](https://github.com/appium/appium-mcp/compare/v1.24.2...v1.25.0) (2026-03-11)
2
+
3
+ ### Features
4
+
5
+ * add `appium_pinch` gesture tool for iOS and Android ([#203](https://github.com/appium/appium-mcp/issues/203)) ([ee0896e](https://github.com/appium/appium-mcp/commit/ee0896eb0d9a5dac6002c59683bee1aeee9d2b82))
6
+
1
7
  ## [1.24.2](https://github.com/appium/appium-mcp/compare/v1.24.1...v1.24.2) (2026-03-10)
2
8
 
3
9
  ### Bug Fixes
package/README.md CHANGED
@@ -263,6 +263,7 @@ MCP Appium provides a comprehensive set of tools organized into the following ca
263
263
  | `appium_double_tap` | Perform double tap on an element |
264
264
  | `appium_long_press` | Perform a long press (press and hold) gesture on an element |
265
265
  | `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) |
266
+ | `appium_pinch` | Perform a pinch gesture to zoom in (scale > 1) or zoom out (scale < 1) on an element or the whole screen. Works on both iOS and Android. |
266
267
  | `appium_set_value` | Enter text into an input field |
267
268
  | `appium_get_text` | Get text content from an element |
268
269
  | `appium_handle_alert` | Accept or dismiss system/permission alerts, or click a dialog button by label |
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAwClC,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CA+H3D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAyClC,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAgI3D"}
@@ -19,6 +19,7 @@ import clickElement from './interactions/click.js';
19
19
  import doubleTap from './interactions/double-tap.js';
20
20
  import longPress from './interactions/long-press.js';
21
21
  import dragAndDrop from './interactions/drag-and-drop.js';
22
+ import pinch from './interactions/pinch.js';
22
23
  import pressKey from './interactions/press-key.js';
23
24
  import setValue from './interactions/set-value.js';
24
25
  import getText from './interactions/get-text.js';
@@ -124,6 +125,7 @@ export default function registerTools(server) {
124
125
  doubleTap(server);
125
126
  longPress(server);
126
127
  dragAndDrop(server);
128
+ pinch(server);
127
129
  pressKey(server);
128
130
  setValue(server);
129
131
  getText(server);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { FastMCP } from 'fastmcp';
2
+ export default function pinch(server: FastMCP): void;
3
+ //# sourceMappingURL=pinch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pinch.d.ts","sourceRoot":"","sources":["../../../src/tools/interactions/pinch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAWtD,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAgKnD"}
@@ -0,0 +1,152 @@
1
+ import { z } from 'zod';
2
+ import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
3
+ import { elementUUIDScheme } from '../../schema.js';
4
+ import { execute, getElementRect, getWindowRect, performActions, } from '../../command.js';
5
+ export default function pinch(server) {
6
+ const pinchSchema = z.object({
7
+ scale: z
8
+ .number()
9
+ .min(0.01)
10
+ .max(10)
11
+ .describe('Pinch scale. Use a value between 0 and 1 to zoom out (pinch close), and a value greater than 1 to zoom in (pinch open). Example: 0.5 = zoom out 50%, 2.0 = zoom in 2x.'),
12
+ elementUUID: elementUUIDScheme
13
+ .trim()
14
+ .min(1)
15
+ .optional()
16
+ .describe('Optional UUID of the element to pinch on. If not provided, the pinch gesture is applied to the whole screen.'),
17
+ velocity: z
18
+ .number()
19
+ .min(0.1)
20
+ .max(20)
21
+ .default(2.2)
22
+ .optional()
23
+ .describe('The velocity of the pinch in scale factor per second. Used natively by iOS for zoom in, and controls gesture speed for zoom out on both platforms. Default is 2.2.'),
24
+ });
25
+ server.addTool({
26
+ name: 'appium_pinch',
27
+ description: 'Perform a pinch gesture to zoom in or zoom out. Use scale < 1 to zoom out (pinch close) and scale > 1 to zoom in (pinch open). Works on both iOS and Android. Optionally target a specific element, otherwise the gesture applies to the whole screen.',
28
+ parameters: pinchSchema,
29
+ annotations: {
30
+ readOnlyHint: false,
31
+ openWorldHint: false,
32
+ },
33
+ execute: async (args, _context) => {
34
+ const driver = getDriver();
35
+ if (!driver) {
36
+ throw new Error('No driver found');
37
+ }
38
+ try {
39
+ const platform = getPlatformName(driver);
40
+ const { scale, elementUUID, velocity = 2.2 } = args;
41
+ const direction = scale < 1 ? 'close (zoom out)' : 'open (zoom in)';
42
+ // Compute center and spread from element or full screen
43
+ let cx, cy, spread;
44
+ let windowRect = null;
45
+ if (elementUUID) {
46
+ const rect = await getElementRect(driver, elementUUID);
47
+ cx = Math.floor(rect.x + rect.width / 2);
48
+ cy = Math.floor(rect.y + rect.height / 2);
49
+ spread = Math.floor(Math.min(rect.width, rect.height) * 0.3);
50
+ }
51
+ else {
52
+ windowRect = await getWindowRect(driver);
53
+ cx = Math.floor(windowRect.width / 2);
54
+ cy = Math.floor(windowRect.height / 2);
55
+ spread = Math.floor(Math.min(windowRect.width, windowRect.height) * 0.3);
56
+ }
57
+ if (scale < 1) {
58
+ // Zoom out on both platforms: W3C Actions, fingers start far, move close
59
+ const startSpread = spread;
60
+ const endSpread = Math.max(1, Math.floor(spread * scale));
61
+ const duration = Math.floor((1 / Math.abs(velocity)) * 1000);
62
+ await performActions(driver, [
63
+ {
64
+ type: 'pointer',
65
+ id: 'finger1',
66
+ parameters: { pointerType: 'touch' },
67
+ actions: [
68
+ {
69
+ type: 'pointerMove',
70
+ duration: 0,
71
+ x: cx - startSpread,
72
+ y: cy,
73
+ },
74
+ { type: 'pointerDown', button: 0 },
75
+ { type: 'pointerMove', duration, x: cx - endSpread, y: cy },
76
+ { type: 'pointerUp', button: 0 },
77
+ ],
78
+ },
79
+ {
80
+ type: 'pointer',
81
+ id: 'finger2',
82
+ parameters: { pointerType: 'touch' },
83
+ actions: [
84
+ {
85
+ type: 'pointerMove',
86
+ duration: 0,
87
+ x: cx + startSpread,
88
+ y: cy,
89
+ },
90
+ { type: 'pointerDown', button: 0 },
91
+ { type: 'pointerMove', duration, x: cx + endSpread, y: cy },
92
+ { type: 'pointerUp', button: 0 },
93
+ ],
94
+ },
95
+ ]);
96
+ }
97
+ else if (platform === PLATFORM.ios) {
98
+ // Zoom in on iOS: mobile: pinch
99
+ const params = {
100
+ scale,
101
+ velocity: Math.abs(velocity),
102
+ };
103
+ if (elementUUID) {
104
+ params.elementId = elementUUID;
105
+ }
106
+ await execute(driver, 'mobile: pinch', params);
107
+ }
108
+ else if (platform === PLATFORM.android) {
109
+ // Zoom in on Android: mobile: pinchOpenGesture
110
+ // Convert scale factor to percent (0–1) for pinchOpenGesture:
111
+ // scale=2 → 0.5, scale=4 → 0.75, scale=10 → 0.9. Capped at 0.99 to avoid edge collisions.
112
+ const percent = Math.min(0.99, 1 - 1 / scale);
113
+ const params = { percent };
114
+ if (elementUUID) {
115
+ params.elementId = elementUUID;
116
+ }
117
+ else {
118
+ const rect = windowRect;
119
+ params.left = rect.x ?? 0;
120
+ params.top = rect.y ?? 0;
121
+ params.width = rect.width;
122
+ params.height = rect.height;
123
+ }
124
+ await execute(driver, 'mobile: pinchOpenGesture', params);
125
+ }
126
+ else {
127
+ throw new Error(`Unsupported platform: ${platform}. Only Android and iOS are supported.`);
128
+ }
129
+ const target = elementUUID ? `element ${elementUUID}` : 'screen';
130
+ return {
131
+ content: [
132
+ {
133
+ type: 'text',
134
+ text: `Successfully performed pinch ${direction} (scale=${scale}) on ${target}.`,
135
+ },
136
+ ],
137
+ };
138
+ }
139
+ catch (err) {
140
+ return {
141
+ content: [
142
+ {
143
+ type: 'text',
144
+ text: `Failed to perform pinch gesture. err: ${err.toString()}`,
145
+ },
146
+ ],
147
+ };
148
+ }
149
+ },
150
+ });
151
+ }
152
+ //# sourceMappingURL=pinch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pinch.js","sourceRoot":"","sources":["../../../src/tools/interactions/pinch.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "appium-mcp",
3
3
  "mcpName": "io.github.appium/appium-mcp",
4
- "version": "1.24.2",
4
+ "version": "1.25.0",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
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.24.2",
6
+ "version": "1.25.0",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "identifier": "appium-mcp",
11
- "version": "1.24.2",
11
+ "version": "1.25.0",
12
12
  "transport": {
13
13
  "type": "stdio"
14
14
  }
@@ -34,6 +34,7 @@ import clickElement from './interactions/click.js';
34
34
  import doubleTap from './interactions/double-tap.js';
35
35
  import longPress from './interactions/long-press.js';
36
36
  import dragAndDrop from './interactions/drag-and-drop.js';
37
+ import pinch from './interactions/pinch.js';
37
38
  import pressKey from './interactions/press-key.js';
38
39
  import setValue from './interactions/set-value.js';
39
40
  import getText from './interactions/get-text.js';
@@ -148,6 +149,7 @@ export default function registerTools(server: FastMCP): void {
148
149
  doubleTap(server);
149
150
  longPress(server);
150
151
  dragAndDrop(server);
152
+ pinch(server);
151
153
  pressKey(server);
152
154
  setValue(server);
153
155
  getText(server);
@@ -0,0 +1,172 @@
1
+ import type { ContentResult, FastMCP } from 'fastmcp';
2
+ import { z } from 'zod';
3
+ import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
4
+ import { elementUUIDScheme } from '../../schema.js';
5
+ import {
6
+ execute,
7
+ getElementRect,
8
+ getWindowRect,
9
+ performActions,
10
+ } from '../../command.js';
11
+
12
+ export default function pinch(server: FastMCP): void {
13
+ const pinchSchema = z.object({
14
+ scale: z
15
+ .number()
16
+ .min(0.01)
17
+ .max(10)
18
+ .describe(
19
+ 'Pinch scale. Use a value between 0 and 1 to zoom out (pinch close), and a value greater than 1 to zoom in (pinch open). Example: 0.5 = zoom out 50%, 2.0 = zoom in 2x.'
20
+ ),
21
+ elementUUID: elementUUIDScheme
22
+ .trim()
23
+ .min(1)
24
+ .optional()
25
+ .describe(
26
+ 'Optional UUID of the element to pinch on. If not provided, the pinch gesture is applied to the whole screen.'
27
+ ),
28
+ velocity: z
29
+ .number()
30
+ .min(0.1)
31
+ .max(20)
32
+ .default(2.2)
33
+ .optional()
34
+ .describe(
35
+ 'The velocity of the pinch in scale factor per second. Used natively by iOS for zoom in, and controls gesture speed for zoom out on both platforms. Default is 2.2.'
36
+ ),
37
+ });
38
+
39
+ server.addTool({
40
+ name: 'appium_pinch',
41
+ description:
42
+ 'Perform a pinch gesture to zoom in or zoom out. Use scale < 1 to zoom out (pinch close) and scale > 1 to zoom in (pinch open). Works on both iOS and Android. Optionally target a specific element, otherwise the gesture applies to the whole screen.',
43
+ parameters: pinchSchema,
44
+ annotations: {
45
+ readOnlyHint: false,
46
+ openWorldHint: false,
47
+ },
48
+ execute: async (
49
+ args: z.infer<typeof pinchSchema>,
50
+ _context: Record<string, unknown> | undefined
51
+ ): Promise<ContentResult> => {
52
+ const driver = getDriver();
53
+ if (!driver) {
54
+ throw new Error('No driver found');
55
+ }
56
+
57
+ try {
58
+ const platform = getPlatformName(driver);
59
+ const { scale, elementUUID, velocity = 2.2 } = args;
60
+ const direction = scale < 1 ? 'close (zoom out)' : 'open (zoom in)';
61
+
62
+ // Compute center and spread from element or full screen
63
+ let cx: number, cy: number, spread: number;
64
+ let windowRect: Awaited<ReturnType<typeof getWindowRect>> | null = null;
65
+ if (elementUUID) {
66
+ const rect = await getElementRect(driver, elementUUID);
67
+ cx = Math.floor(rect.x + rect.width / 2);
68
+ cy = Math.floor(rect.y + rect.height / 2);
69
+ spread = Math.floor(Math.min(rect.width, rect.height) * 0.3);
70
+ } else {
71
+ windowRect = await getWindowRect(driver);
72
+ cx = Math.floor(windowRect.width / 2);
73
+ cy = Math.floor(windowRect.height / 2);
74
+ spread = Math.floor(
75
+ Math.min(windowRect.width, windowRect.height) * 0.3
76
+ );
77
+ }
78
+
79
+ if (scale < 1) {
80
+ // Zoom out on both platforms: W3C Actions, fingers start far, move close
81
+ const startSpread = spread;
82
+ const endSpread = Math.max(1, Math.floor(spread * scale));
83
+ const duration = Math.floor((1 / Math.abs(velocity)) * 1000);
84
+
85
+ await performActions(driver, [
86
+ {
87
+ type: 'pointer',
88
+ id: 'finger1',
89
+ parameters: { pointerType: 'touch' },
90
+ actions: [
91
+ {
92
+ type: 'pointerMove',
93
+ duration: 0,
94
+ x: cx - startSpread,
95
+ y: cy,
96
+ },
97
+ { type: 'pointerDown', button: 0 },
98
+ { type: 'pointerMove', duration, x: cx - endSpread, y: cy },
99
+ { type: 'pointerUp', button: 0 },
100
+ ],
101
+ },
102
+ {
103
+ type: 'pointer',
104
+ id: 'finger2',
105
+ parameters: { pointerType: 'touch' },
106
+ actions: [
107
+ {
108
+ type: 'pointerMove',
109
+ duration: 0,
110
+ x: cx + startSpread,
111
+ y: cy,
112
+ },
113
+ { type: 'pointerDown', button: 0 },
114
+ { type: 'pointerMove', duration, x: cx + endSpread, y: cy },
115
+ { type: 'pointerUp', button: 0 },
116
+ ],
117
+ },
118
+ ]);
119
+ } else if (platform === PLATFORM.ios) {
120
+ // Zoom in on iOS: mobile: pinch
121
+ const params: Record<string, any> = {
122
+ scale,
123
+ velocity: Math.abs(velocity),
124
+ };
125
+ if (elementUUID) {
126
+ params.elementId = elementUUID;
127
+ }
128
+ await execute(driver, 'mobile: pinch', params);
129
+ } else if (platform === PLATFORM.android) {
130
+ // Zoom in on Android: mobile: pinchOpenGesture
131
+ // Convert scale factor to percent (0–1) for pinchOpenGesture:
132
+ // scale=2 → 0.5, scale=4 → 0.75, scale=10 → 0.9. Capped at 0.99 to avoid edge collisions.
133
+ const percent = Math.min(0.99, 1 - 1 / scale);
134
+ const params: Record<string, any> = { percent };
135
+ if (elementUUID) {
136
+ params.elementId = elementUUID;
137
+ } else {
138
+ const rect = windowRect!;
139
+ params.left = rect.x ?? 0;
140
+ params.top = rect.y ?? 0;
141
+ params.width = rect.width;
142
+ params.height = rect.height;
143
+ }
144
+ await execute(driver, 'mobile: pinchOpenGesture', params);
145
+ } else {
146
+ throw new Error(
147
+ `Unsupported platform: ${platform}. Only Android and iOS are supported.`
148
+ );
149
+ }
150
+
151
+ const target = elementUUID ? `element ${elementUUID}` : 'screen';
152
+ return {
153
+ content: [
154
+ {
155
+ type: 'text',
156
+ text: `Successfully performed pinch ${direction} (scale=${scale}) on ${target}.`,
157
+ },
158
+ ],
159
+ };
160
+ } catch (err: any) {
161
+ return {
162
+ content: [
163
+ {
164
+ type: 'text',
165
+ text: `Failed to perform pinch gesture. err: ${err.toString()}`,
166
+ },
167
+ ],
168
+ };
169
+ }
170
+ },
171
+ });
172
+ }