appium-mcp 1.54.0 → 1.55.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.55.0](https://github.com/appium/appium-mcp/compare/v1.54.0...v1.55.0) (2026-04-13)
2
+
3
+ ### Features
4
+
5
+ * consolidate geolocation functionality into a single tool ([#256](https://github.com/appium/appium-mcp/issues/256)) ([9cdedbd](https://github.com/appium/appium-mcp/commit/9cdedbd876ee70e85be17a786cb22069af65f9c0))
6
+
1
7
  ## [1.54.0](https://github.com/appium/appium-mcp/compare/v1.53.1...v1.54.0) (2026-04-11)
2
8
 
3
9
  ### Features
package/README.md CHANGED
@@ -347,9 +347,7 @@ The default regex pattern allows any URL that starts with `http://` or `https://
347
347
  | `appium_swipe` | Swipe the screen in a direction (left, right, up, down) or between custom coordinates |
348
348
  | `appium_get_page_source` | Get the page source (XML) from the current screen |
349
349
  | `appium_orientation` | Get or set device/screen orientation with `action` = `get` or `set` (requires `orientation` for set). |
350
- | `appium_set_geolocation` | Set the GPS coordinates (latitude, longitude, altitude) of the device. |
351
- | `appium_get_geolocation` | Get the current GPS coordinates (latitude, longitude, altitude) of the device. |
352
- | `appium_reset_geolocation` | Reset the simulated/mocked geolocation back to the system default. On iOS, clears the simulated location. On Android real devices, removes the mock location provider. Not supported on Android emulators. |
350
+ | `appium_geolocation` | Get, set, or reset the device GPS coordinates with `action` = `get`, `set`, or `reset`. For `set`, provide `latitude` and `longitude` (and optional `altitude` on Android). Not supported on Android emulators for `reset`. |
353
351
  | `appium_screen_recording` | Start or stop screen recording with `action` = `start` or `stop`. On stop, returns the saved MP4 path. |
354
352
  | `appium_mobile_device_info` | Get device information, battery status, or current device time. Use `action` = `info` (model, OS version, locale, timezone, screen density, etc.), `battery` (level as percentage and charging state), or `time` (current device time; accepts an optional `format` moment.js string, defaults to ISO 8601). Works on both iOS and Android. |
355
353
 
@@ -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;AA2DlC,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CA8I3D"}
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;AAuDlC,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CA4I3D"}
@@ -10,7 +10,7 @@ import selectDevice from './session/select-device.js';
10
10
  import openNotifications from './session/open-notifications.js';
11
11
  import shakeDevice from './session/shake.js';
12
12
  import { lockDevice, unlockDevice } from './session/lock.js';
13
- import { setGeolocation, getGeolocation, resetGeolocation, } from './session/geolocation.js';
13
+ import geolocation from './session/geolocation.js';
14
14
  import deviceInfo from './session/device-info.js';
15
15
  import fileTransfer from './session/file-transfer.js';
16
16
  import driverSettings from './session/driver-settings.js';
@@ -123,9 +123,7 @@ export default function registerTools(server) {
123
123
  shakeDevice(server);
124
124
  lockDevice(server);
125
125
  unlockDevice(server);
126
- setGeolocation(server);
127
- getGeolocation(server);
128
- resetGeolocation(server);
126
+ geolocation(server);
129
127
  deviceInfo(server);
130
128
  fileTransfer(server);
131
129
  driverSettings(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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"}
@@ -1,5 +1,3 @@
1
1
  import type { FastMCP } from 'fastmcp';
2
- export declare function setGeolocation(server: FastMCP): void;
3
- export declare function getGeolocation(server: FastMCP): void;
4
- export declare function resetGeolocation(server: FastMCP): void;
2
+ export default function geolocation(server: FastMCP): void;
5
3
  //# sourceMappingURL=geolocation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"geolocation.d.ts","sourceRoot":"","sources":["../../../src/tools/session/geolocation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAKtD,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAqFpD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CA4DpD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CA6DtD"}
1
+ {"version":3,"file":"geolocation.d.ts","sourceRoot":"","sources":["../../../src/tools/session/geolocation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAyItD,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CA8BzD"}
@@ -1,186 +1,127 @@
1
1
  import { z } from 'zod';
2
2
  import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
3
3
  import { execute } from '../../command.js';
4
- export function setGeolocation(server) {
5
- const setGeolocationSchema = z.object({
6
- sessionId: z
7
- .string()
8
- .optional()
9
- .describe('Session ID to target. If omitted, uses the active session.'),
10
- latitude: z
11
- .number()
12
- .min(-90)
13
- .max(90)
14
- .describe('Latitude value (-90 to 90). Measurement of distance north or south of the Equator.'),
15
- longitude: z
16
- .number()
17
- .min(-180)
18
- .max(180)
19
- .describe('Longitude value (-180 to 180). Measurement of distance east or west of the prime meridian.'),
20
- altitude: z
21
- .number()
22
- .optional()
23
- .describe('Altitude value in meters. Android only. Defaults to 0.'),
24
- });
25
- server.addTool({
26
- name: 'appium_set_geolocation',
27
- description: 'Set the geolocation (GPS coordinates) of the device. Works on both iOS (simulators and real devices) and Android (emulators and real devices with mock location enabled).',
28
- parameters: setGeolocationSchema,
29
- annotations: {
30
- readOnlyHint: false,
31
- openWorldHint: false,
32
- },
33
- execute: async (args, _context) => {
34
- const driver = getDriver(args.sessionId);
35
- if (!driver) {
36
- throw new Error('No driver found');
37
- }
38
- try {
39
- const platform = getPlatformName(driver);
40
- const { latitude, longitude, altitude } = args;
41
- if (platform === PLATFORM.ios) {
42
- await execute(driver, 'mobile: setSimulatedLocation', {
43
- latitude,
44
- longitude,
45
- });
46
- }
47
- else if (platform === PLATFORM.android) {
48
- await execute(driver, 'mobile: setGeolocation', {
49
- latitude,
50
- longitude,
51
- ...(altitude !== undefined && { altitude }),
52
- });
53
- }
54
- else {
55
- throw new Error(`Unsupported platform: ${platform}. Only Android and iOS are supported.`);
56
- }
57
- return {
58
- content: [
59
- {
60
- type: 'text',
61
- text: `Successfully set geolocation to latitude=${latitude}, longitude=${longitude}${altitude !== undefined ? `, altitude=${altitude}` : ''}.`,
62
- },
63
- ],
64
- };
65
- }
66
- catch (err) {
67
- return {
68
- content: [
69
- {
70
- type: 'text',
71
- text: `Failed to set geolocation. Error: ${err.toString()}`,
72
- },
73
- ],
74
- };
75
- }
76
- },
77
- });
4
+ const schema = z.object({
5
+ action: z
6
+ .enum(['get', 'set', 'reset'])
7
+ .describe('Action to perform. ' +
8
+ 'get: read the current device geolocation. ' +
9
+ 'set: set the device geolocation (requires latitude and longitude; optional altitude for Android). ' +
10
+ 'reset: reset the geolocation to the default/system value. Not supported on Android emulators — use action=set instead.'),
11
+ latitude: z.coerce
12
+ .number()
13
+ .min(-90)
14
+ .max(90)
15
+ .optional()
16
+ .describe('Latitude value (-90 to 90). Measurement of distance north or south of the Equator. Required for: set.'),
17
+ longitude: z.coerce
18
+ .number()
19
+ .min(-180)
20
+ .max(180)
21
+ .optional()
22
+ .describe('Longitude value (-180 to 180). Measurement of distance east or west of the prime meridian. Required for: set.'),
23
+ altitude: z.coerce
24
+ .number()
25
+ .optional()
26
+ .refine((v) => v === undefined || !isNaN(v), 'altitude must be a valid number')
27
+ .describe('Altitude value in meters. Android only, defaults to 0. Ignored on iOS. Used with: set.'),
28
+ sessionId: z
29
+ .string()
30
+ .optional()
31
+ .describe('Session ID to target. If omitted, uses the active session.'),
32
+ });
33
+ function textResult(text) {
34
+ return { content: [{ type: 'text', text }] };
78
35
  }
79
- export function getGeolocation(server) {
80
- const getGeolocationSchema = z.object({
81
- sessionId: z
82
- .string()
83
- .optional()
84
- .describe('Session ID to target. If omitted, uses the active session.'),
85
- });
86
- server.addTool({
87
- name: 'appium_get_geolocation',
88
- description: 'Get the current geolocation (GPS coordinates) of the device. Returns latitude, longitude, and altitude.',
89
- parameters: getGeolocationSchema,
90
- annotations: {
91
- readOnlyHint: true,
92
- openWorldHint: false,
93
- },
94
- execute: async (args, _context) => {
95
- const driver = getDriver(args.sessionId);
96
- if (!driver) {
97
- throw new Error('No driver found');
98
- }
99
- try {
100
- const platform = getPlatformName(driver);
101
- let result;
102
- if (platform === PLATFORM.ios) {
103
- result = await execute(driver, 'mobile: getSimulatedLocation', {});
104
- }
105
- else if (platform === PLATFORM.android) {
106
- result = await execute(driver, 'mobile: getGeolocation', {});
107
- }
108
- else {
109
- throw new Error(`Unsupported platform: ${platform}. Only Android and iOS are supported.`);
110
- }
111
- return {
112
- content: [
113
- {
114
- type: 'text',
115
- text: `Current geolocation: latitude=${result.latitude}, longitude=${result.longitude}${result.altitude !== undefined ? `, altitude=${result.altitude}` : ''}.`,
116
- },
117
- ],
118
- };
119
- }
120
- catch (err) {
121
- return {
122
- content: [
123
- {
124
- type: 'text',
125
- text: `Failed to get geolocation. Error: ${err.toString()}`,
126
- },
127
- ],
128
- };
129
- }
130
- },
131
- });
36
+ async function handleGet(args) {
37
+ const driver = getDriver(args.sessionId);
38
+ if (!driver) {
39
+ throw new Error('No driver found');
40
+ }
41
+ const platform = getPlatformName(driver);
42
+ let result;
43
+ if (platform === PLATFORM.ios) {
44
+ result = await execute(driver, 'mobile: getSimulatedLocation', {});
45
+ }
46
+ else if (platform === PLATFORM.android) {
47
+ result = await execute(driver, 'mobile: getGeolocation', {});
48
+ }
49
+ else {
50
+ throw new Error(`Unsupported platform: ${platform}. Only Android and iOS are supported.`);
51
+ }
52
+ const altitudeText = result.altitude !== undefined ? `, altitude=${result.altitude}` : '';
53
+ return textResult(`Current geolocation: latitude=${result.latitude}, longitude=${result.longitude}${altitudeText}.`);
132
54
  }
133
- export function resetGeolocation(server) {
134
- const resetGeolocationSchema = z.object({
135
- sessionId: z
136
- .string()
137
- .optional()
138
- .describe('Session ID to target. If omitted, uses the active session.'),
139
- });
55
+ async function handleSet(args) {
56
+ if (args.latitude === undefined || args.longitude === undefined) {
57
+ throw new Error('latitude and longitude are required for action=set');
58
+ }
59
+ const driver = getDriver(args.sessionId);
60
+ if (!driver) {
61
+ throw new Error('No driver found');
62
+ }
63
+ const platform = getPlatformName(driver);
64
+ const { latitude, longitude, altitude } = args;
65
+ if (platform === PLATFORM.ios) {
66
+ await execute(driver, 'mobile: setSimulatedLocation', {
67
+ latitude,
68
+ longitude,
69
+ });
70
+ }
71
+ else if (platform === PLATFORM.android) {
72
+ await execute(driver, 'mobile: setGeolocation', {
73
+ latitude,
74
+ longitude,
75
+ ...(altitude !== undefined && { altitude }),
76
+ });
77
+ }
78
+ else {
79
+ throw new Error(`Unsupported platform: ${platform}. Only Android and iOS are supported.`);
80
+ }
81
+ const altitudeText = altitude !== undefined ? `, altitude=${altitude}` : '';
82
+ return textResult(`Successfully set geolocation to latitude=${latitude}, longitude=${longitude}${altitudeText}.`);
83
+ }
84
+ async function handleReset(args) {
85
+ const driver = getDriver(args.sessionId);
86
+ if (!driver) {
87
+ throw new Error('No driver found');
88
+ }
89
+ const platform = getPlatformName(driver);
90
+ if (platform === PLATFORM.ios) {
91
+ await execute(driver, 'mobile: resetSimulatedLocation', {});
92
+ }
93
+ else if (platform === PLATFORM.android) {
94
+ await execute(driver, 'mobile: resetGeolocation', {});
95
+ // Refresh GPS cache
96
+ await execute(driver, 'mobile: refreshGpsCache', {});
97
+ }
98
+ else {
99
+ throw new Error(`Unsupported platform: ${platform}. Only Android and iOS are supported.`);
100
+ }
101
+ return textResult('Successfully reset geolocation to default.');
102
+ }
103
+ export default function geolocation(server) {
140
104
  server.addTool({
141
- name: 'appium_reset_geolocation',
142
- description: 'Reset the geolocation to the default/system value. On iOS, resets the simulated location. On Android real devices, resets the mocked geolocation provider (note: GPS cache behavior varies by device the mocked location may persist until the cache refreshes). On Android emulators, reset is not supported — use appium_set_geolocation to manually set the desired coordinates instead.',
143
- parameters: resetGeolocationSchema,
105
+ name: 'appium_geolocation',
106
+ description: 'Get, set, or reset the device geolocation (GPS coordinates). Works on both iOS (simulators and real devices) and Android (emulators and real devices with mock location enabled). Use action=get to read current coordinates, action=set with latitude/longitude (and optional altitude for Android) to simulate a location, or action=reset to restore the system default. Note: On Android emulators, reset is not supported — use action=set to manually restore coordinates instead. On Android real devices, the mocked location may persist until the GPS cache refreshes.',
107
+ parameters: schema,
144
108
  annotations: {
145
109
  readOnlyHint: false,
146
110
  openWorldHint: false,
147
111
  },
148
112
  execute: async (args, _context) => {
149
- const driver = getDriver(args.sessionId);
150
- if (!driver) {
151
- throw new Error('No driver found');
152
- }
153
113
  try {
154
- const platform = getPlatformName(driver);
155
- if (platform === PLATFORM.ios) {
156
- await execute(driver, 'mobile: resetSimulatedLocation', {});
157
- }
158
- else if (platform === PLATFORM.android) {
159
- await execute(driver, 'mobile: resetGeolocation', {});
160
- // Refresh GPS cache
161
- await execute(driver, 'mobile: refreshGpsCache', {});
162
- }
163
- else {
164
- throw new Error(`Unsupported platform: ${platform}. Only Android and iOS are supported.`);
114
+ switch (args.action) {
115
+ case 'get':
116
+ return await handleGet(args);
117
+ case 'set':
118
+ return await handleSet(args);
119
+ case 'reset':
120
+ return await handleReset(args);
165
121
  }
166
- return {
167
- content: [
168
- {
169
- type: 'text',
170
- text: 'Successfully reset geolocation to default.',
171
- },
172
- ],
173
- };
174
122
  }
175
123
  catch (err) {
176
- return {
177
- content: [
178
- {
179
- type: 'text',
180
- text: `Failed to reset geolocation. Error: ${err.toString()}`,
181
- },
182
- ],
183
- };
124
+ return textResult(`Failed to ${args.action} geolocation. Error: ${err.toString()}`);
184
125
  }
185
126
  },
186
127
  });
@@ -1 +1 @@
1
- {"version":3,"file":"geolocation.js","sourceRoot":"","sources":["../../../src/tools/session/geolocation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"geolocation.js","sourceRoot":"","sources":["../../../src/tools/session/geolocation.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.54.0",
4
+ "version": "1.55.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.54.0",
6
+ "version": "1.55.0",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "identifier": "appium-mcp",
11
- "version": "1.54.0",
11
+ "version": "1.55.0",
12
12
  "transport": {
13
13
  "type": "stdio"
14
14
  }
Binary file
@@ -25,11 +25,7 @@ import selectDevice from './session/select-device.js';
25
25
  import openNotifications from './session/open-notifications.js';
26
26
  import shakeDevice from './session/shake.js';
27
27
  import { lockDevice, unlockDevice } from './session/lock.js';
28
- import {
29
- setGeolocation,
30
- getGeolocation,
31
- resetGeolocation,
32
- } from './session/geolocation.js';
28
+ import geolocation from './session/geolocation.js';
33
29
  import deviceInfo from './session/device-info.js';
34
30
  import fileTransfer from './session/file-transfer.js';
35
31
  import driverSettings from './session/driver-settings.js';
@@ -148,9 +144,7 @@ export default function registerTools(server: FastMCP): void {
148
144
  shakeDevice(server);
149
145
  lockDevice(server);
150
146
  unlockDevice(server);
151
- setGeolocation(server);
152
- getGeolocation(server);
153
- resetGeolocation(server);
147
+ geolocation(server);
154
148
  deviceInfo(server);
155
149
  fileTransfer(server);
156
150
  driverSettings(server);
@@ -3,213 +3,165 @@ import { z } from 'zod';
3
3
  import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
4
4
  import { execute } from '../../command.js';
5
5
 
6
- export function setGeolocation(server: FastMCP): void {
7
- const setGeolocationSchema = z.object({
8
- sessionId: z
9
- .string()
10
- .optional()
11
- .describe('Session ID to target. If omitted, uses the active session.'),
12
- latitude: z
13
- .number()
14
- .min(-90)
15
- .max(90)
16
- .describe(
17
- 'Latitude value (-90 to 90). Measurement of distance north or south of the Equator.'
18
- ),
19
- longitude: z
20
- .number()
21
- .min(-180)
22
- .max(180)
23
- .describe(
24
- 'Longitude value (-180 to 180). Measurement of distance east or west of the prime meridian.'
25
- ),
26
- altitude: z
27
- .number()
28
- .optional()
29
- .describe('Altitude value in meters. Android only. Defaults to 0.'),
30
- });
6
+ const schema = z.object({
7
+ action: z
8
+ .enum(['get', 'set', 'reset'])
9
+ .describe(
10
+ 'Action to perform. ' +
11
+ 'get: read the current device geolocation. ' +
12
+ 'set: set the device geolocation (requires latitude and longitude; optional altitude for Android). ' +
13
+ 'reset: reset the geolocation to the default/system value. Not supported on Android emulators — use action=set instead.'
14
+ ),
15
+ latitude: z.coerce
16
+ .number()
17
+ .min(-90)
18
+ .max(90)
19
+ .optional()
20
+ .describe(
21
+ 'Latitude value (-90 to 90). Measurement of distance north or south of the Equator. Required for: set.'
22
+ ),
23
+ longitude: z.coerce
24
+ .number()
25
+ .min(-180)
26
+ .max(180)
27
+ .optional()
28
+ .describe(
29
+ 'Longitude value (-180 to 180). Measurement of distance east or west of the prime meridian. Required for: set.'
30
+ ),
31
+ altitude: z.coerce
32
+ .number()
33
+ .optional()
34
+ .refine(
35
+ (v) => v === undefined || !isNaN(v),
36
+ 'altitude must be a valid number'
37
+ )
38
+ .describe(
39
+ 'Altitude value in meters. Android only, defaults to 0. Ignored on iOS. Used with: set.'
40
+ ),
41
+ sessionId: z
42
+ .string()
43
+ .optional()
44
+ .describe('Session ID to target. If omitted, uses the active session.'),
45
+ });
31
46
 
32
- server.addTool({
33
- name: 'appium_set_geolocation',
34
- description:
35
- 'Set the geolocation (GPS coordinates) of the device. Works on both iOS (simulators and real devices) and Android (emulators and real devices with mock location enabled).',
36
- parameters: setGeolocationSchema,
37
- annotations: {
38
- readOnlyHint: false,
39
- openWorldHint: false,
40
- },
41
- execute: async (
42
- args: z.infer<typeof setGeolocationSchema>,
43
- _context: Record<string, unknown> | undefined
44
- ): Promise<ContentResult> => {
45
- const driver = getDriver(args.sessionId);
46
- if (!driver) {
47
- throw new Error('No driver found');
48
- }
47
+ type GeolocationArgs = z.infer<typeof schema>;
49
48
 
50
- try {
51
- const platform = getPlatformName(driver);
52
- const { latitude, longitude, altitude } = args;
53
-
54
- if (platform === PLATFORM.ios) {
55
- await execute(driver, 'mobile: setSimulatedLocation', {
56
- latitude,
57
- longitude,
58
- });
59
- } else if (platform === PLATFORM.android) {
60
- await execute(driver, 'mobile: setGeolocation', {
61
- latitude,
62
- longitude,
63
- ...(altitude !== undefined && { altitude }),
64
- });
65
- } else {
66
- throw new Error(
67
- `Unsupported platform: ${platform}. Only Android and iOS are supported.`
68
- );
69
- }
49
+ function textResult(text: string): ContentResult {
50
+ return { content: [{ type: 'text', text }] };
51
+ }
70
52
 
71
- return {
72
- content: [
73
- {
74
- type: 'text',
75
- text: `Successfully set geolocation to latitude=${latitude}, longitude=${longitude}${altitude !== undefined ? `, altitude=${altitude}` : ''}.`,
76
- },
77
- ],
78
- };
79
- } catch (err: any) {
80
- return {
81
- content: [
82
- {
83
- type: 'text',
84
- text: `Failed to set geolocation. Error: ${err.toString()}`,
85
- },
86
- ],
87
- };
88
- }
89
- },
90
- });
53
+ async function handleGet(args: GeolocationArgs): Promise<ContentResult> {
54
+ const driver = getDriver(args.sessionId);
55
+ if (!driver) {
56
+ throw new Error('No driver found');
57
+ }
58
+
59
+ const platform = getPlatformName(driver);
60
+ let result: Record<string, any>;
61
+
62
+ if (platform === PLATFORM.ios) {
63
+ result = await execute(driver, 'mobile: getSimulatedLocation', {});
64
+ } else if (platform === PLATFORM.android) {
65
+ result = await execute(driver, 'mobile: getGeolocation', {});
66
+ } else {
67
+ throw new Error(
68
+ `Unsupported platform: ${platform}. Only Android and iOS are supported.`
69
+ );
70
+ }
71
+
72
+ const altitudeText =
73
+ result.altitude !== undefined ? `, altitude=${result.altitude}` : '';
74
+ return textResult(
75
+ `Current geolocation: latitude=${result.latitude}, longitude=${result.longitude}${altitudeText}.`
76
+ );
91
77
  }
92
78
 
93
- export function getGeolocation(server: FastMCP): void {
94
- const getGeolocationSchema = z.object({
95
- sessionId: z
96
- .string()
97
- .optional()
98
- .describe('Session ID to target. If omitted, uses the active session.'),
99
- });
79
+ async function handleSet(args: GeolocationArgs): Promise<ContentResult> {
80
+ if (args.latitude === undefined || args.longitude === undefined) {
81
+ throw new Error('latitude and longitude are required for action=set');
82
+ }
100
83
 
101
- server.addTool({
102
- name: 'appium_get_geolocation',
103
- description:
104
- 'Get the current geolocation (GPS coordinates) of the device. Returns latitude, longitude, and altitude.',
105
- parameters: getGeolocationSchema,
106
- annotations: {
107
- readOnlyHint: true,
108
- openWorldHint: false,
109
- },
110
- execute: async (
111
- args: z.infer<typeof getGeolocationSchema>,
112
- _context: Record<string, unknown> | undefined
113
- ): Promise<ContentResult> => {
114
- const driver = getDriver(args.sessionId);
115
- if (!driver) {
116
- throw new Error('No driver found');
117
- }
84
+ const driver = getDriver(args.sessionId);
85
+ if (!driver) {
86
+ throw new Error('No driver found');
87
+ }
118
88
 
119
- try {
120
- const platform = getPlatformName(driver);
121
- let result: Record<string, any>;
122
-
123
- if (platform === PLATFORM.ios) {
124
- result = await execute(driver, 'mobile: getSimulatedLocation', {});
125
- } else if (platform === PLATFORM.android) {
126
- result = await execute(driver, 'mobile: getGeolocation', {});
127
- } else {
128
- throw new Error(
129
- `Unsupported platform: ${platform}. Only Android and iOS are supported.`
130
- );
131
- }
89
+ const platform = getPlatformName(driver);
90
+ const { latitude, longitude, altitude } = args;
132
91
 
133
- return {
134
- content: [
135
- {
136
- type: 'text',
137
- text: `Current geolocation: latitude=${result.latitude}, longitude=${result.longitude}${result.altitude !== undefined ? `, altitude=${result.altitude}` : ''}.`,
138
- },
139
- ],
140
- };
141
- } catch (err: any) {
142
- return {
143
- content: [
144
- {
145
- type: 'text',
146
- text: `Failed to get geolocation. Error: ${err.toString()}`,
147
- },
148
- ],
149
- };
150
- }
151
- },
152
- });
92
+ if (platform === PLATFORM.ios) {
93
+ await execute(driver, 'mobile: setSimulatedLocation', {
94
+ latitude,
95
+ longitude,
96
+ });
97
+ } else if (platform === PLATFORM.android) {
98
+ await execute(driver, 'mobile: setGeolocation', {
99
+ latitude,
100
+ longitude,
101
+ ...(altitude !== undefined && { altitude }),
102
+ });
103
+ } else {
104
+ throw new Error(
105
+ `Unsupported platform: ${platform}. Only Android and iOS are supported.`
106
+ );
107
+ }
108
+
109
+ const altitudeText = altitude !== undefined ? `, altitude=${altitude}` : '';
110
+ return textResult(
111
+ `Successfully set geolocation to latitude=${latitude}, longitude=${longitude}${altitudeText}.`
112
+ );
153
113
  }
154
114
 
155
- export function resetGeolocation(server: FastMCP): void {
156
- const resetGeolocationSchema = z.object({
157
- sessionId: z
158
- .string()
159
- .optional()
160
- .describe('Session ID to target. If omitted, uses the active session.'),
161
- });
115
+ async function handleReset(args: GeolocationArgs): Promise<ContentResult> {
116
+ const driver = getDriver(args.sessionId);
117
+ if (!driver) {
118
+ throw new Error('No driver found');
119
+ }
120
+
121
+ const platform = getPlatformName(driver);
122
+
123
+ if (platform === PLATFORM.ios) {
124
+ await execute(driver, 'mobile: resetSimulatedLocation', {});
125
+ } else if (platform === PLATFORM.android) {
126
+ await execute(driver, 'mobile: resetGeolocation', {});
127
+ // Refresh GPS cache
128
+ await execute(driver, 'mobile: refreshGpsCache', {});
129
+ } else {
130
+ throw new Error(
131
+ `Unsupported platform: ${platform}. Only Android and iOS are supported.`
132
+ );
133
+ }
162
134
 
135
+ return textResult('Successfully reset geolocation to default.');
136
+ }
137
+
138
+ export default function geolocation(server: FastMCP): void {
163
139
  server.addTool({
164
- name: 'appium_reset_geolocation',
140
+ name: 'appium_geolocation',
165
141
  description:
166
- 'Reset the geolocation to the default/system value. On iOS, resets the simulated location. On Android real devices, resets the mocked geolocation provider (note: GPS cache behavior varies by device the mocked location may persist until the cache refreshes). On Android emulators, reset is not supported — use appium_set_geolocation to manually set the desired coordinates instead.',
167
- parameters: resetGeolocationSchema,
142
+ 'Get, set, or reset the device geolocation (GPS coordinates). Works on both iOS (simulators and real devices) and Android (emulators and real devices with mock location enabled). Use action=get to read current coordinates, action=set with latitude/longitude (and optional altitude for Android) to simulate a location, or action=reset to restore the system default. Note: On Android emulators, reset is not supported — use action=set to manually restore coordinates instead. On Android real devices, the mocked location may persist until the GPS cache refreshes.',
143
+ parameters: schema,
168
144
  annotations: {
169
145
  readOnlyHint: false,
170
146
  openWorldHint: false,
171
147
  },
172
148
  execute: async (
173
- args: z.infer<typeof resetGeolocationSchema>,
149
+ args: GeolocationArgs,
174
150
  _context: Record<string, unknown> | undefined
175
151
  ): Promise<ContentResult> => {
176
- const driver = getDriver(args.sessionId);
177
- if (!driver) {
178
- throw new Error('No driver found');
179
- }
180
-
181
152
  try {
182
- const platform = getPlatformName(driver);
183
-
184
- if (platform === PLATFORM.ios) {
185
- await execute(driver, 'mobile: resetSimulatedLocation', {});
186
- } else if (platform === PLATFORM.android) {
187
- await execute(driver, 'mobile: resetGeolocation', {});
188
- // Refresh GPS cache
189
- await execute(driver, 'mobile: refreshGpsCache', {});
190
- } else {
191
- throw new Error(
192
- `Unsupported platform: ${platform}. Only Android and iOS are supported.`
193
- );
153
+ switch (args.action) {
154
+ case 'get':
155
+ return await handleGet(args);
156
+ case 'set':
157
+ return await handleSet(args);
158
+ case 'reset':
159
+ return await handleReset(args);
194
160
  }
195
-
196
- return {
197
- content: [
198
- {
199
- type: 'text',
200
- text: 'Successfully reset geolocation to default.',
201
- },
202
- ],
203
- };
204
161
  } catch (err: any) {
205
- return {
206
- content: [
207
- {
208
- type: 'text',
209
- text: `Failed to reset geolocation. Error: ${err.toString()}`,
210
- },
211
- ],
212
- };
162
+ return textResult(
163
+ `Failed to ${args.action} geolocation. Error: ${err.toString()}`
164
+ );
213
165
  }
214
166
  },
215
167
  });