appium-mcp 1.53.1 → 1.54.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 +1 -3
- package/dist/tests/tools/session/device-info.test.d.ts +2 -0
- package/dist/tests/tools/session/device-info.test.d.ts.map +1 -0
- package/dist/tests/tools/session/device-info.test.js +135 -0
- package/dist/tests/tools/session/device-info.test.js.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +0 -4
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/session/device-info.d.ts.map +1 -1
- package/dist/tools/session/device-info.js +114 -29
- package/dist/tools/session/device-info.js.map +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/resources/submodules.zip +0 -0
- package/src/tools/index.ts +0 -4
- package/src/tools/session/device-info.ts +127 -33
- package/dist/tests/tools/session/battery-info.test.d.ts +0 -2
- package/dist/tests/tools/session/battery-info.test.d.ts.map +0 -1
- package/dist/tests/tools/session/battery-info.test.js +0 -69
- package/dist/tests/tools/session/battery-info.test.js.map +0 -1
- package/dist/tools/session/battery-info.d.ts +0 -3
- package/dist/tools/session/battery-info.d.ts.map +0 -1
- package/dist/tools/session/battery-info.js +0 -76
- package/dist/tools/session/battery-info.js.map +0 -1
- package/dist/tools/session/device-time.d.ts +0 -3
- package/dist/tools/session/device-time.d.ts.map +0 -1
- package/dist/tools/session/device-time.js +0 -57
- package/dist/tools/session/device-time.js.map +0 -1
- package/src/tools/session/battery-info.ts +0 -89
- package/src/tools/session/device-time.ts +0 -63
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [1.54.0](https://github.com/appium/appium-mcp/compare/v1.53.1...v1.54.0) (2026-04-11)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* **device-info:** consolidate device info commands ([#257](https://github.com/appium/appium-mcp/issues/257)) ([29e2f17](https://github.com/appium/appium-mcp/commit/29e2f1713e8fbef860dfede31e05b2f013533cbb))
|
|
6
|
+
|
|
1
7
|
## [1.53.1](https://github.com/appium/appium-mcp/compare/v1.53.0...v1.53.1) (2026-04-11)
|
|
2
8
|
|
|
3
9
|
### Miscellaneous Chores
|
package/README.md
CHANGED
|
@@ -351,9 +351,7 @@ The default regex pattern allows any URL that starts with `http://` or `https://
|
|
|
351
351
|
| `appium_get_geolocation` | Get the current GPS coordinates (latitude, longitude, altitude) of the device. |
|
|
352
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. |
|
|
353
353
|
| `appium_screen_recording` | Start or stop screen recording with `action` = `start` or `stop`. On stop, returns the saved MP4 path. |
|
|
354
|
-
| `
|
|
355
|
-
| `appium_mobile_get_battery_info` | Get the current battery level (as a percentage) and charging state of the device. Works on both iOS and Android. |
|
|
356
|
-
| `appium_mobile_get_device_time` | Get the current time on the device. Accepts an optional `format` parameter (moment.js format string); defaults to ISO 8601. Works on both iOS and Android. |
|
|
354
|
+
| `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. |
|
|
357
355
|
|
|
358
356
|
### App Management
|
|
359
357
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-info.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/tools/session/device-info.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { describe, test, expect, jest } from '@jest/globals';
|
|
2
|
+
jest.unstable_mockModule('../../../session-store', () => ({
|
|
3
|
+
getDriver: jest.fn(),
|
|
4
|
+
getPlatformName: jest.fn(),
|
|
5
|
+
PLATFORM: { ios: 'iOS', android: 'Android' },
|
|
6
|
+
}));
|
|
7
|
+
jest.unstable_mockModule('../../../command', () => ({
|
|
8
|
+
execute: jest.fn(),
|
|
9
|
+
}));
|
|
10
|
+
jest.unstable_mockModule('../../../logger', () => ({
|
|
11
|
+
default: { debug: () => { }, info: () => { }, warn: () => { }, error: () => { } },
|
|
12
|
+
}));
|
|
13
|
+
const { getDriver, getPlatformName, PLATFORM } = await import('../../../session-store.js');
|
|
14
|
+
const { execute } = await import('../../../command.js');
|
|
15
|
+
const mockGetDriver = getDriver;
|
|
16
|
+
const mockGetPlatformName = getPlatformName;
|
|
17
|
+
const mockExecute = execute;
|
|
18
|
+
describe('appium_mobile_device_info tool', () => {
|
|
19
|
+
const mockServer = { addTool: jest.fn() };
|
|
20
|
+
async function getToolExecute() {
|
|
21
|
+
const { default: deviceInfo } = await import('../../../tools/session/device-info.js');
|
|
22
|
+
deviceInfo(mockServer);
|
|
23
|
+
return mockServer.addTool.mock.calls.at(-1)?.[0];
|
|
24
|
+
}
|
|
25
|
+
describe('battery action', () => {
|
|
26
|
+
test('returns error when no driver is active', async () => {
|
|
27
|
+
const tool = await getToolExecute();
|
|
28
|
+
mockGetDriver.mockReturnValue(null);
|
|
29
|
+
const result = await tool.execute({ action: 'battery' }, undefined);
|
|
30
|
+
expect(result.isError).toBe(true);
|
|
31
|
+
expect(result.content[0].text).toBe('No driver found');
|
|
32
|
+
});
|
|
33
|
+
test('returns formatted iOS battery info', async () => {
|
|
34
|
+
const tool = await getToolExecute();
|
|
35
|
+
mockGetDriver.mockReturnValue({});
|
|
36
|
+
mockGetPlatformName.mockReturnValue(PLATFORM.ios);
|
|
37
|
+
mockExecute.mockResolvedValue({ level: 0.75, state: 2 });
|
|
38
|
+
const result = await tool.execute({ action: 'battery' }, undefined);
|
|
39
|
+
const parsed = JSON.parse(result.content[0].text);
|
|
40
|
+
expect(parsed).toEqual({
|
|
41
|
+
platform: 'iOS',
|
|
42
|
+
level: '75%',
|
|
43
|
+
state: 'charging',
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
test('returns formatted Android battery info', async () => {
|
|
47
|
+
const tool = await getToolExecute();
|
|
48
|
+
mockGetDriver.mockReturnValue({});
|
|
49
|
+
mockGetPlatformName.mockReturnValue(PLATFORM.android);
|
|
50
|
+
mockExecute.mockResolvedValue({ level: 0.3, state: 3 });
|
|
51
|
+
const result = await tool.execute({ action: 'battery' }, undefined);
|
|
52
|
+
const parsed = JSON.parse(result.content[0].text);
|
|
53
|
+
expect(parsed).toEqual({
|
|
54
|
+
platform: 'Android',
|
|
55
|
+
level: '30%',
|
|
56
|
+
state: 'discharging',
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
test('returns error when execute rejects', async () => {
|
|
60
|
+
const tool = await getToolExecute();
|
|
61
|
+
mockGetDriver.mockReturnValue({});
|
|
62
|
+
mockGetPlatformName.mockReturnValue(PLATFORM.ios);
|
|
63
|
+
mockExecute.mockRejectedValue(new Error('driver error'));
|
|
64
|
+
const result = await tool.execute({ action: 'battery' }, undefined);
|
|
65
|
+
expect(result.isError).toBe(true);
|
|
66
|
+
expect(result.content[0].text).toBe('Failed to get battery info: driver error');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('info action', () => {
|
|
70
|
+
test('returns error when no driver is active', async () => {
|
|
71
|
+
const tool = await getToolExecute();
|
|
72
|
+
mockGetDriver.mockReturnValue(null);
|
|
73
|
+
const result = await tool.execute({ action: 'info' }, undefined);
|
|
74
|
+
expect(result.isError).toBe(true);
|
|
75
|
+
expect(result.content[0].text).toBe('No driver found');
|
|
76
|
+
});
|
|
77
|
+
test('returns device info as formatted JSON', async () => {
|
|
78
|
+
const tool = await getToolExecute();
|
|
79
|
+
mockGetDriver.mockReturnValue({});
|
|
80
|
+
const deviceData = {
|
|
81
|
+
model: 'iPhone 15',
|
|
82
|
+
os: 'iOS 17.0',
|
|
83
|
+
locale: 'en_US',
|
|
84
|
+
};
|
|
85
|
+
mockExecute.mockResolvedValue(deviceData);
|
|
86
|
+
const result = await tool.execute({ action: 'info' }, undefined);
|
|
87
|
+
expect(result.isError).toBeUndefined();
|
|
88
|
+
const parsed = JSON.parse(result.content[0].text);
|
|
89
|
+
expect(parsed).toEqual(deviceData);
|
|
90
|
+
});
|
|
91
|
+
test('returns error when execute rejects', async () => {
|
|
92
|
+
const tool = await getToolExecute();
|
|
93
|
+
mockGetDriver.mockReturnValue({});
|
|
94
|
+
mockExecute.mockRejectedValue(new Error('device unavailable'));
|
|
95
|
+
const result = await tool.execute({ action: 'info' }, undefined);
|
|
96
|
+
expect(result.isError).toBe(true);
|
|
97
|
+
expect(result.content[0].text).toBe('Failed to get device info: device unavailable');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('time action', () => {
|
|
101
|
+
test('returns error when no driver is active', async () => {
|
|
102
|
+
const tool = await getToolExecute();
|
|
103
|
+
mockGetDriver.mockReturnValue(null);
|
|
104
|
+
const result = await tool.execute({ action: 'time' }, undefined);
|
|
105
|
+
expect(result.isError).toBe(true);
|
|
106
|
+
expect(result.content[0].text).toBe('No driver found');
|
|
107
|
+
});
|
|
108
|
+
test('returns device time as string', async () => {
|
|
109
|
+
const tool = await getToolExecute();
|
|
110
|
+
mockGetDriver.mockReturnValue({});
|
|
111
|
+
mockExecute.mockResolvedValue('2024-01-15T10:30:00+00:00');
|
|
112
|
+
const result = await tool.execute({ action: 'time' }, undefined);
|
|
113
|
+
expect(result.isError).toBeUndefined();
|
|
114
|
+
expect(result.content[0].text).toBe('2024-01-15T10:30:00+00:00');
|
|
115
|
+
});
|
|
116
|
+
test('passes format parameter to execute', async () => {
|
|
117
|
+
const tool = await getToolExecute();
|
|
118
|
+
mockGetDriver.mockReturnValue({});
|
|
119
|
+
mockExecute.mockResolvedValue('15/01/2024');
|
|
120
|
+
const result = await tool.execute({ action: 'time', format: 'DD/MM/YYYY' }, undefined);
|
|
121
|
+
expect(result.isError).toBeUndefined();
|
|
122
|
+
expect(result.content[0].text).toBe('15/01/2024');
|
|
123
|
+
expect(mockExecute).toHaveBeenCalledWith(expect.anything(), 'mobile: getDeviceTime', { format: 'DD/MM/YYYY' });
|
|
124
|
+
});
|
|
125
|
+
test('returns error when execute rejects', async () => {
|
|
126
|
+
const tool = await getToolExecute();
|
|
127
|
+
mockGetDriver.mockReturnValue({});
|
|
128
|
+
mockExecute.mockRejectedValue(new Error('timeout'));
|
|
129
|
+
const result = await tool.execute({ action: 'time' }, undefined);
|
|
130
|
+
expect(result.isError).toBe(true);
|
|
131
|
+
expect(result.content[0].text).toBe('Failed to get device time: timeout');
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
//# sourceMappingURL=device-info.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-info.test.js","sourceRoot":"","sources":["../../../../src/tests/tools/session/device-info.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -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;
|
|
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"}
|
package/dist/tools/index.js
CHANGED
|
@@ -12,9 +12,7 @@ import shakeDevice from './session/shake.js';
|
|
|
12
12
|
import { lockDevice, unlockDevice } from './session/lock.js';
|
|
13
13
|
import { setGeolocation, getGeolocation, resetGeolocation, } from './session/geolocation.js';
|
|
14
14
|
import deviceInfo from './session/device-info.js';
|
|
15
|
-
import batteryInfo from './session/battery-info.js';
|
|
16
15
|
import fileTransfer from './session/file-transfer.js';
|
|
17
|
-
import deviceTime from './session/device-time.js';
|
|
18
16
|
import driverSettings from './session/driver-settings.js';
|
|
19
17
|
import prepareIosSimulator from './ios/prepare-ios-simulator.js';
|
|
20
18
|
import generateTest from './test-generation/generate-tests.js';
|
|
@@ -129,9 +127,7 @@ export default function registerTools(server) {
|
|
|
129
127
|
getGeolocation(server);
|
|
130
128
|
resetGeolocation(server);
|
|
131
129
|
deviceInfo(server);
|
|
132
|
-
batteryInfo(server);
|
|
133
130
|
fileTransfer(server);
|
|
134
|
-
deviceTime(server);
|
|
135
131
|
driverSettings(server);
|
|
136
132
|
// iOS Setup
|
|
137
133
|
prepareIosSimulator(server);
|
package/dist/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAeA,OAAO,GAAG,MAAM,cAAc,CAAC;AAC/B,OAAO,YAAY,MAAM,kCAAkC,CAAC;AAC5D,OAAO,YAAY,MAAM,kCAAkC,CAAC;AAC5D,OAAO,aAAa,MAAM,6BAA6B,CAAC;AACxD,OAAO,aAAa,MAAM,6BAA6B,CAAC;AACxD,OAAO,YAAY,MAAM,4BAA4B,CAAC;AACtD,OAAO,aAAa,MAAM,6BAA6B,CAAC;AACxD,OAAO,gBAAgB,MAAM,+BAA+B,CAAC;AAC7D,OAAO,YAAY,MAAM,4BAA4B,CAAC;AACtD,OAAO,iBAAiB,MAAM,iCAAiC,CAAC;AAChE,OAAO,WAAW,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,cAAc,EACd,cAAc,EACd,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAClD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAeA,OAAO,GAAG,MAAM,cAAc,CAAC;AAC/B,OAAO,YAAY,MAAM,kCAAkC,CAAC;AAC5D,OAAO,YAAY,MAAM,kCAAkC,CAAC;AAC5D,OAAO,aAAa,MAAM,6BAA6B,CAAC;AACxD,OAAO,aAAa,MAAM,6BAA6B,CAAC;AACxD,OAAO,YAAY,MAAM,4BAA4B,CAAC;AACtD,OAAO,aAAa,MAAM,6BAA6B,CAAC;AACxD,OAAO,gBAAgB,MAAM,+BAA+B,CAAC;AAC7D,OAAO,YAAY,MAAM,4BAA4B,CAAC;AACtD,OAAO,iBAAiB,MAAM,iCAAiC,CAAC;AAChE,OAAO,WAAW,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,cAAc,EACd,cAAc,EACd,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAClD,OAAO,YAAY,MAAM,4BAA4B,CAAC;AACtD,OAAO,cAAc,MAAM,8BAA8B,CAAC;AAC1D,OAAO,mBAAmB,MAAM,gCAAgC,CAAC;AACjE,OAAO,YAAY,MAAM,qCAAqC,CAAC;AAC/D,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,eAAe,MAAM,oCAAoC,CAAC;AACjE,OAAO,KAAK,MAAM,wBAAwB,CAAC;AAC3C,OAAO,WAAW,MAAM,wBAAwB,CAAC;AACjD,OAAO,GAAG,MAAM,uBAAuB,CAAC;AACxC,OAAO,YAAY,MAAM,yBAAyB,CAAC;AACnD,OAAO,SAAS,MAAM,8BAA8B,CAAC;AACrD,OAAO,SAAS,MAAM,8BAA8B,CAAC;AACrD,OAAO,WAAW,MAAM,iCAAiC,CAAC;AAC1D,OAAO,KAAK,MAAM,yBAAyB,CAAC;AAC5C,OAAO,QAAQ,MAAM,6BAA6B,CAAC;AACnD,OAAO,QAAQ,MAAM,6BAA6B,CAAC;AACnD,OAAO,QAAQ,MAAM,4BAA4B,CAAC;AAClD,OAAO,OAAO,MAAM,4BAA4B,CAAC;AACjD,OAAO,mBAAmB,MAAM,yCAAyC,CAAC;AAC1E,OAAO,gBAAgB,MAAM,kCAAkC,CAAC;AAChE,OAAO,aAAa,MAAM,mCAAmC,CAAC;AAC9D,OAAO,WAAW,MAAM,+BAA+B,CAAC;AACxD,OAAO,SAAS,MAAM,6BAA6B,CAAC;AACpD,OAAO,KAAK,MAAM,gCAAgC,CAAC;AACnD,OAAO,UAAU,MAAM,8BAA8B,CAAC;AACtD,OAAO,aAAa,MAAM,+BAA+B,CAAC;AAC1D,OAAO,eAAe,MAAM,oCAAoC,CAAC;AACjE,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAC3D,OAAO,aAAa,MAAM,oCAAoC,CAAC;AAC/D,OAAO,UAAU,MAAM,iCAAiC,CAAC;AACzD,OAAO,YAAY,MAAM,mCAAmC,CAAC;AAC7D,OAAO,YAAY,MAAM,mCAAmC,CAAC;AAC7D,OAAO,QAAQ,MAAM,+BAA+B,CAAC;AACrD,OAAO,cAAc,MAAM,sCAAsC,CAAC;AAClE,OAAO,aAAa,MAAM,qCAAqC,CAAC;AAChE,OAAO,QAAQ,MAAM,+BAA+B,CAAC;AACrD,OAAO,iBAAiB,MAAM,iCAAiC,CAAC;AAChE,OAAO,QAAQ,MAAM,+BAA+B,CAAC;AACrD,OAAO,OAAO,MAAM,sBAAsB,CAAC;AAE3C,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,MAAe;IACnD,uDAAuD;IACvD,MAAM,eAAe,GAAI,MAAc,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5D,MAAc,CAAC,OAAO,GAAG,CAAC,OAAY,EAAE,EAAE;QACzC,MAAM,QAAQ,GAAG,OAAO,EAAE,IAAI,IAAI,cAAc,CAAC;QACjD,MAAM,eAAe,GAAG,OAAO,EAAE,OAAO,CAAC;QACzC,IAAI,OAAO,eAAe,KAAK,UAAU,EAAE,CAAC;YAC1C,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QACD,MAAM,cAAc,GAAG;YACrB,UAAU;YACV,OAAO;YACP,aAAa;YACb,eAAe;YACf,QAAQ;YACR,QAAQ;YACR,QAAQ;YACR,cAAc;SACf,CAAC;QACF,MAAM,UAAU,GAAG,CAAC,GAAQ,EAAE,EAAE;YAC9B,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CACf,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;oBACjC,IACE,GAAG;wBACH,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EACzD,CAAC;wBACD,OAAO,YAAY,CAAC;oBACtB,CAAC;oBACD,gDAAgD;oBAChD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;wBAC9D,OAAO,WAAW,KAAK,CAAC,MAAM,GAAG,CAAC;oBACpC,CAAC;oBACD,IACE,KAAK;wBACL,OAAO,MAAM,KAAK,WAAW;wBAC7B,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EACtB,CAAC;wBACD,OAAO,WAAY,KAAgB,CAAC,MAAM,GAAG,CAAC;oBAChD,CAAC;oBACD,OAAO,KAAK,CAAC;gBACf,CAAC,CAAC,CACH,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,uBAAuB,CAAC;YACjC,CAAC;QACH,CAAC,CAAC;QACF,OAAO,eAAe,CAAC;YACrB,GAAG,OAAO;YACV,OAAO,EAAE,KAAK,EAAE,IAAS,EAAE,OAAY,EAAE,EAAE;gBACzC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACzB,GAAG,CAAC,IAAI,CAAC,gBAAgB,QAAQ,EAAE,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;gBACvD,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;oBACpC,GAAG,CAAC,IAAI,CAAC,cAAc,QAAQ,KAAK,QAAQ,KAAK,CAAC,CAAC;oBACnD,OAAO,MAAM,CAAC;gBAChB,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;oBACpC,MAAM,GAAG,GAAG,GAAG,EAAE,KAAK,IAAI,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;oBACtD,GAAG,CAAC,KAAK,CAAC,gBAAgB,QAAQ,KAAK,QAAQ,QAAQ,GAAG,EAAE,CAAC,CAAC;oBAC9D,MAAM,GAAG,CAAC;gBACZ,CAAC;YACH,CAAC;SACF,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,qBAAqB;IACrB,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,WAAW,CAAC,MAAM,CAAC,CAAC;IACpB,UAAU,CAAC,MAAM,CAAC,CAAC;IACnB,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,UAAU,CAAC,MAAM,CAAC,CAAC;IACnB,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,YAAY;IACZ,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAE5B,aAAa;IACb,MAAM,CAAC,MAAM,CAAC,CAAC;IACf,eAAe,CAAC,MAAM,CAAC,CAAC;IACxB,KAAK,CAAC,MAAM,CAAC,CAAC;IAEd,uBAAuB;IACvB,qCAAqC;IACrC,8EAA8E;IAC9E,sEAAsE;IACtE,mFAAmF;IACnF,GAAG,CAAC,MAAM,CAAC,CAAC;IACZ,WAAW,CAAC,MAAM,CAAC,CAAC;IACpB,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,SAAS,CAAC,MAAM,CAAC,CAAC;IAClB,SAAS,CAAC,MAAM,CAAC,CAAC;IAClB,WAAW,CAAC,MAAM,CAAC,CAAC;IACpB,KAAK,CAAC,MAAM,CAAC,CAAC;IACd,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjB,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjB,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjB,OAAO,CAAC,MAAM,CAAC,CAAC;IAChB,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,SAAS,CAAC,MAAM,CAAC,CAAC;IAClB,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,WAAW,CAAC,MAAM,CAAC,CAAC;IACpB,KAAK,CAAC,MAAM,CAAC,CAAC;IACd,UAAU,CAAC,MAAM,CAAC,CAAC;IACnB,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,eAAe,CAAC,MAAM,CAAC,CAAC;IAExB,iBAAiB;IACjB,WAAW,CAAC,MAAM,CAAC,CAAC;IACpB,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,UAAU,CAAC,MAAM,CAAC,CAAC;IACnB,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjB,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjB,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEjB,qBAAqB;IACrB,OAAO,CAAC,MAAM,CAAC,CAAC;IAEhB,kBAAkB;IAClB,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,YAAY,CAAC,MAAM,CAAC,CAAC;IAErB,gBAAgB;IAChB,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,GAAG,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-info.d.ts","sourceRoot":"","sources":["../../../src/tools/session/device-info.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"device-info.d.ts","sourceRoot":"","sources":["../../../src/tools/session/device-info.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAsCtD,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CA4GxD"}
|
|
@@ -1,46 +1,131 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { getDriver } from '../../session-store.js';
|
|
2
|
+
import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
|
|
3
3
|
import { execute } from '../../command.js';
|
|
4
|
+
import { BatteryState } from 'appium-xcuitest-driver/build/lib/commands/enum.js';
|
|
5
|
+
// iOS: maps UIDeviceBatteryState values to human-readable strings
|
|
6
|
+
// @see https://github.com/appium/appium-xcuitest-driver/blob/5bdad71/lib/commands/enum.ts#L91
|
|
7
|
+
const IOS_BATTERY_STATES = {
|
|
8
|
+
[BatteryState.UIDeviceBatteryStateUnknown]: 'unknown',
|
|
9
|
+
[BatteryState.UIDeviceBatteryStateUnplugged]: 'unplugged',
|
|
10
|
+
[BatteryState.UIDeviceBatteryStateCharging]: 'charging',
|
|
11
|
+
[BatteryState.UIDeviceBatteryStateFull]: 'full',
|
|
12
|
+
};
|
|
13
|
+
// Android: state matches BatteryManager constants
|
|
14
|
+
const ANDROID_BATTERY_STATES = {
|
|
15
|
+
1: 'unknown',
|
|
16
|
+
2: 'charging',
|
|
17
|
+
3: 'discharging',
|
|
18
|
+
4: 'not charging',
|
|
19
|
+
5: 'full',
|
|
20
|
+
};
|
|
21
|
+
function formatBatteryInfo(platform, raw) {
|
|
22
|
+
const levelPercent = Math.round((raw.level ?? 0) * 100);
|
|
23
|
+
const states = platform === PLATFORM.ios ? IOS_BATTERY_STATES : ANDROID_BATTERY_STATES;
|
|
24
|
+
return {
|
|
25
|
+
platform: platform === PLATFORM.ios ? 'iOS' : 'Android',
|
|
26
|
+
level: `${levelPercent}%`,
|
|
27
|
+
state: states[raw.state ?? -1] ?? 'unknown',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
4
30
|
export default function deviceInfo(server) {
|
|
31
|
+
const schema = z.object({
|
|
32
|
+
action: z
|
|
33
|
+
.enum(['info', 'battery', 'time'])
|
|
34
|
+
.describe('Action to perform: "info" returns device model/OS/locale/etc., "battery" returns battery level and charging state, "time" returns the current device time.'),
|
|
35
|
+
format: z
|
|
36
|
+
.string()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe('Only used when action is "time". moment.js format string for the returned time. Defaults to ISO 8601 (YYYY-MM-DDTHH:mm:ssZ).'),
|
|
39
|
+
sessionId: z
|
|
40
|
+
.string()
|
|
41
|
+
.optional()
|
|
42
|
+
.describe('Session ID to target. If omitted, uses the active session.'),
|
|
43
|
+
});
|
|
5
44
|
server.addTool({
|
|
6
|
-
name: '
|
|
7
|
-
description: 'Get device information
|
|
8
|
-
parameters:
|
|
9
|
-
sessionId: z
|
|
10
|
-
.string()
|
|
11
|
-
.optional()
|
|
12
|
-
.describe('Session ID to target. If omitted, uses the active session.'),
|
|
13
|
-
}),
|
|
45
|
+
name: 'appium_mobile_device_info',
|
|
46
|
+
description: 'Get device information, battery status, or current device time in a single call. Use the "action" parameter to select which data to retrieve. Works on both iOS and Android.',
|
|
47
|
+
parameters: schema,
|
|
14
48
|
annotations: {
|
|
15
49
|
readOnlyHint: true,
|
|
16
50
|
openWorldHint: false,
|
|
17
51
|
},
|
|
18
|
-
execute: async (args
|
|
52
|
+
execute: async (args) => {
|
|
19
53
|
const driver = getDriver(args.sessionId);
|
|
20
54
|
if (!driver) {
|
|
21
|
-
throw new Error('No driver found');
|
|
22
|
-
}
|
|
23
|
-
try {
|
|
24
|
-
const result = await execute(driver, 'mobile: deviceInfo', {});
|
|
25
55
|
return {
|
|
26
|
-
content: [
|
|
27
|
-
|
|
28
|
-
type: 'text',
|
|
29
|
-
text: JSON.stringify(result, null, 2),
|
|
30
|
-
},
|
|
31
|
-
],
|
|
56
|
+
content: [{ type: 'text', text: 'No driver found' }],
|
|
57
|
+
isError: true,
|
|
32
58
|
};
|
|
33
59
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
60
|
+
if (args.action === 'info') {
|
|
61
|
+
try {
|
|
62
|
+
const result = await execute(driver, 'mobile: deviceInfo', {});
|
|
63
|
+
return {
|
|
64
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
return {
|
|
69
|
+
content: [
|
|
70
|
+
{
|
|
71
|
+
type: 'text',
|
|
72
|
+
text: `Failed to get device info: ${err instanceof Error ? err.message : String(err)}`,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
isError: true,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (args.action === 'battery') {
|
|
80
|
+
try {
|
|
81
|
+
const platform = getPlatformName(driver);
|
|
82
|
+
const raw = await execute(driver, 'mobile: batteryInfo', {});
|
|
83
|
+
const formatted = formatBatteryInfo(platform, raw);
|
|
84
|
+
return {
|
|
85
|
+
content: [
|
|
86
|
+
{ type: 'text', text: JSON.stringify(formatted, null, 2) },
|
|
87
|
+
],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
return {
|
|
92
|
+
content: [
|
|
93
|
+
{
|
|
94
|
+
type: 'text',
|
|
95
|
+
text: `Failed to get battery info: ${err instanceof Error ? err.message : String(err)}`,
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
isError: true,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (args.action === 'time') {
|
|
103
|
+
try {
|
|
104
|
+
const params = {};
|
|
105
|
+
if (args.format != null) {
|
|
106
|
+
params.format = args.format;
|
|
107
|
+
}
|
|
108
|
+
const time = await execute(driver, 'mobile: getDeviceTime', params);
|
|
109
|
+
return {
|
|
110
|
+
content: [{ type: 'text', text: String(time) }],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
return {
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
117
|
+
type: 'text',
|
|
118
|
+
text: `Failed to get device time: ${err instanceof Error ? err.message : String(err)}`,
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
isError: true,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
43
124
|
}
|
|
125
|
+
return {
|
|
126
|
+
content: [{ type: 'text', text: `Unknown action: ${args.action}` }],
|
|
127
|
+
isError: true,
|
|
128
|
+
};
|
|
44
129
|
},
|
|
45
130
|
});
|
|
46
131
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-info.js","sourceRoot":"","sources":["../../../src/tools/session/device-info.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"device-info.js","sourceRoot":"","sources":["../../../src/tools/session/device-info.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.54.0",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"identifier": "appium-mcp",
|
|
11
|
-
"version": "1.
|
|
11
|
+
"version": "1.54.0",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
}
|
|
Binary file
|
package/src/tools/index.ts
CHANGED
|
@@ -31,9 +31,7 @@ import {
|
|
|
31
31
|
resetGeolocation,
|
|
32
32
|
} from './session/geolocation.js';
|
|
33
33
|
import deviceInfo from './session/device-info.js';
|
|
34
|
-
import batteryInfo from './session/battery-info.js';
|
|
35
34
|
import fileTransfer from './session/file-transfer.js';
|
|
36
|
-
import deviceTime from './session/device-time.js';
|
|
37
35
|
import driverSettings from './session/driver-settings.js';
|
|
38
36
|
import prepareIosSimulator from './ios/prepare-ios-simulator.js';
|
|
39
37
|
import generateTest from './test-generation/generate-tests.js';
|
|
@@ -154,9 +152,7 @@ export default function registerTools(server: FastMCP): void {
|
|
|
154
152
|
getGeolocation(server);
|
|
155
153
|
resetGeolocation(server);
|
|
156
154
|
deviceInfo(server);
|
|
157
|
-
batteryInfo(server);
|
|
158
155
|
fileTransfer(server);
|
|
159
|
-
deviceTime(server);
|
|
160
156
|
driverSettings(server);
|
|
161
157
|
|
|
162
158
|
// iOS Setup
|
|
@@ -1,53 +1,147 @@
|
|
|
1
1
|
import type { ContentResult, FastMCP } from 'fastmcp';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { getDriver } from '../../session-store.js';
|
|
3
|
+
import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
|
|
4
4
|
import { execute } from '../../command.js';
|
|
5
|
+
import { BatteryState } from 'appium-xcuitest-driver/build/lib/commands/enum.js';
|
|
6
|
+
|
|
7
|
+
// iOS: maps UIDeviceBatteryState values to human-readable strings
|
|
8
|
+
// @see https://github.com/appium/appium-xcuitest-driver/blob/5bdad71/lib/commands/enum.ts#L91
|
|
9
|
+
const IOS_BATTERY_STATES: Record<number, string> = {
|
|
10
|
+
[BatteryState.UIDeviceBatteryStateUnknown]: 'unknown',
|
|
11
|
+
[BatteryState.UIDeviceBatteryStateUnplugged]: 'unplugged',
|
|
12
|
+
[BatteryState.UIDeviceBatteryStateCharging]: 'charging',
|
|
13
|
+
[BatteryState.UIDeviceBatteryStateFull]: 'full',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// Android: state matches BatteryManager constants
|
|
17
|
+
const ANDROID_BATTERY_STATES: Record<number, string> = {
|
|
18
|
+
1: 'unknown',
|
|
19
|
+
2: 'charging',
|
|
20
|
+
3: 'discharging',
|
|
21
|
+
4: 'not charging',
|
|
22
|
+
5: 'full',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function formatBatteryInfo(
|
|
26
|
+
platform: string,
|
|
27
|
+
raw: { level?: number; state?: number }
|
|
28
|
+
): Record<string, string> {
|
|
29
|
+
const levelPercent = Math.round((raw.level ?? 0) * 100);
|
|
30
|
+
const states =
|
|
31
|
+
platform === PLATFORM.ios ? IOS_BATTERY_STATES : ANDROID_BATTERY_STATES;
|
|
32
|
+
return {
|
|
33
|
+
platform: platform === PLATFORM.ios ? 'iOS' : 'Android',
|
|
34
|
+
level: `${levelPercent}%`,
|
|
35
|
+
state: states[raw.state ?? -1] ?? 'unknown',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
5
38
|
|
|
6
39
|
export default function deviceInfo(server: FastMCP): void {
|
|
40
|
+
const schema = z.object({
|
|
41
|
+
action: z
|
|
42
|
+
.enum(['info', 'battery', 'time'])
|
|
43
|
+
.describe(
|
|
44
|
+
'Action to perform: "info" returns device model/OS/locale/etc., "battery" returns battery level and charging state, "time" returns the current device time.'
|
|
45
|
+
),
|
|
46
|
+
format: z
|
|
47
|
+
.string()
|
|
48
|
+
.optional()
|
|
49
|
+
.describe(
|
|
50
|
+
'Only used when action is "time". moment.js format string for the returned time. Defaults to ISO 8601 (YYYY-MM-DDTHH:mm:ssZ).'
|
|
51
|
+
),
|
|
52
|
+
sessionId: z
|
|
53
|
+
.string()
|
|
54
|
+
.optional()
|
|
55
|
+
.describe('Session ID to target. If omitted, uses the active session.'),
|
|
56
|
+
});
|
|
57
|
+
|
|
7
58
|
server.addTool({
|
|
8
|
-
name: '
|
|
59
|
+
name: 'appium_mobile_device_info',
|
|
9
60
|
description:
|
|
10
|
-
'Get device information
|
|
11
|
-
parameters:
|
|
12
|
-
sessionId: z
|
|
13
|
-
.string()
|
|
14
|
-
.optional()
|
|
15
|
-
.describe('Session ID to target. If omitted, uses the active session.'),
|
|
16
|
-
}),
|
|
61
|
+
'Get device information, battery status, or current device time in a single call. Use the "action" parameter to select which data to retrieve. Works on both iOS and Android.',
|
|
62
|
+
parameters: schema,
|
|
17
63
|
annotations: {
|
|
18
64
|
readOnlyHint: true,
|
|
19
65
|
openWorldHint: false,
|
|
20
66
|
},
|
|
21
|
-
execute: async (
|
|
22
|
-
args: { sessionId?: string },
|
|
23
|
-
_context: Record<string, unknown> | undefined
|
|
24
|
-
): Promise<ContentResult> => {
|
|
67
|
+
execute: async (args: z.infer<typeof schema>): Promise<ContentResult> => {
|
|
25
68
|
const driver = getDriver(args.sessionId);
|
|
26
69
|
if (!driver) {
|
|
27
|
-
|
|
70
|
+
return {
|
|
71
|
+
content: [{ type: 'text', text: 'No driver found' }],
|
|
72
|
+
isError: true,
|
|
73
|
+
};
|
|
28
74
|
}
|
|
29
75
|
|
|
30
|
-
|
|
31
|
-
|
|
76
|
+
if (args.action === 'info') {
|
|
77
|
+
try {
|
|
78
|
+
const result = await execute(driver, 'mobile: deviceInfo', {});
|
|
79
|
+
return {
|
|
80
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
81
|
+
};
|
|
82
|
+
} catch (err: unknown) {
|
|
83
|
+
return {
|
|
84
|
+
content: [
|
|
85
|
+
{
|
|
86
|
+
type: 'text',
|
|
87
|
+
text: `Failed to get device info: ${err instanceof Error ? err.message : String(err)}`,
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
isError: true,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
32
94
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
95
|
+
if (args.action === 'battery') {
|
|
96
|
+
try {
|
|
97
|
+
const platform = getPlatformName(driver);
|
|
98
|
+
const raw = await execute(driver, 'mobile: batteryInfo', {});
|
|
99
|
+
const formatted = formatBatteryInfo(platform, raw);
|
|
100
|
+
return {
|
|
101
|
+
content: [
|
|
102
|
+
{ type: 'text', text: JSON.stringify(formatted, null, 2) },
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
} catch (err: unknown) {
|
|
106
|
+
return {
|
|
107
|
+
content: [
|
|
108
|
+
{
|
|
109
|
+
type: 'text',
|
|
110
|
+
text: `Failed to get battery info: ${err instanceof Error ? err.message : String(err)}`,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
isError: true,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (args.action === 'time') {
|
|
119
|
+
try {
|
|
120
|
+
const params: Record<string, unknown> = {};
|
|
121
|
+
if (args.format != null) {
|
|
122
|
+
params.format = args.format;
|
|
123
|
+
}
|
|
124
|
+
const time = await execute(driver, 'mobile: getDeviceTime', params);
|
|
125
|
+
return {
|
|
126
|
+
content: [{ type: 'text', text: String(time) }],
|
|
127
|
+
};
|
|
128
|
+
} catch (err: unknown) {
|
|
129
|
+
return {
|
|
130
|
+
content: [
|
|
131
|
+
{
|
|
132
|
+
type: 'text',
|
|
133
|
+
text: `Failed to get device time: ${err instanceof Error ? err.message : String(err)}`,
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
isError: true,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
50
139
|
}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
content: [{ type: 'text', text: `Unknown action: ${args.action}` }],
|
|
143
|
+
isError: true,
|
|
144
|
+
};
|
|
51
145
|
},
|
|
52
146
|
});
|
|
53
147
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"battery-info.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/tools/session/battery-info.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, jest } from '@jest/globals';
|
|
2
|
-
jest.unstable_mockModule('../../../session-store', () => ({
|
|
3
|
-
getDriver: jest.fn(),
|
|
4
|
-
getPlatformName: jest.fn(),
|
|
5
|
-
PLATFORM: { ios: 'iOS', android: 'Android' },
|
|
6
|
-
}));
|
|
7
|
-
jest.unstable_mockModule('../../../command', () => ({
|
|
8
|
-
execute: jest.fn(),
|
|
9
|
-
}));
|
|
10
|
-
jest.unstable_mockModule('../../../logger', () => ({
|
|
11
|
-
default: { debug: () => { }, info: () => { }, warn: () => { }, error: () => { } },
|
|
12
|
-
}));
|
|
13
|
-
const { getDriver, getPlatformName, PLATFORM } = await import('../../../session-store.js');
|
|
14
|
-
const { execute } = await import('../../../command.js');
|
|
15
|
-
const mockGetDriver = getDriver;
|
|
16
|
-
const mockGetPlatformName = getPlatformName;
|
|
17
|
-
const mockExecute = execute;
|
|
18
|
-
describe('appium_mobile_get_battery_info tool', () => {
|
|
19
|
-
const mockServer = { addTool: jest.fn() };
|
|
20
|
-
test('throws when no driver is active', async () => {
|
|
21
|
-
const { default: batteryInfo } = await import('../../../tools/session/battery-info.js');
|
|
22
|
-
mockGetDriver.mockReturnValue(null);
|
|
23
|
-
batteryInfo(mockServer);
|
|
24
|
-
const tool = mockServer.addTool.mock.calls.at(-1)?.[0];
|
|
25
|
-
await expect(tool.execute({}, undefined)).rejects.toThrow('No driver found');
|
|
26
|
-
});
|
|
27
|
-
test('returns formatted iOS battery info', async () => {
|
|
28
|
-
const { default: batteryInfo } = await import('../../../tools/session/battery-info.js');
|
|
29
|
-
mockGetDriver.mockReturnValue({});
|
|
30
|
-
mockGetPlatformName.mockReturnValue(PLATFORM.ios);
|
|
31
|
-
mockExecute.mockResolvedValue({ level: 0.75, state: 2 });
|
|
32
|
-
batteryInfo(mockServer);
|
|
33
|
-
const tool = mockServer.addTool.mock.calls.at(-1)?.[0];
|
|
34
|
-
const result = await tool.execute({}, undefined);
|
|
35
|
-
const parsed = JSON.parse(result.content[0].text);
|
|
36
|
-
expect(parsed).toEqual({
|
|
37
|
-
platform: 'iOS',
|
|
38
|
-
level: '75%',
|
|
39
|
-
state: 'charging',
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
test('returns formatted Android battery info', async () => {
|
|
43
|
-
const { default: batteryInfo } = await import('../../../tools/session/battery-info.js');
|
|
44
|
-
mockGetDriver.mockReturnValue({});
|
|
45
|
-
mockGetPlatformName.mockReturnValue(PLATFORM.android);
|
|
46
|
-
mockExecute.mockResolvedValue({ level: 0.3, state: 3 });
|
|
47
|
-
batteryInfo(mockServer);
|
|
48
|
-
const tool = mockServer.addTool.mock.calls.at(-1)?.[0];
|
|
49
|
-
const result = await tool.execute({}, undefined);
|
|
50
|
-
const parsed = JSON.parse(result.content[0].text);
|
|
51
|
-
expect(parsed).toEqual({
|
|
52
|
-
platform: 'Android',
|
|
53
|
-
level: '30%',
|
|
54
|
-
state: 'discharging',
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
test('returns error message when execute throws', async () => {
|
|
58
|
-
const { default: batteryInfo } = await import('../../../tools/session/battery-info.js');
|
|
59
|
-
mockGetDriver.mockReturnValue({});
|
|
60
|
-
mockGetPlatformName.mockReturnValue(PLATFORM.ios);
|
|
61
|
-
mockExecute.mockRejectedValue(new Error('driver error'));
|
|
62
|
-
batteryInfo(mockServer);
|
|
63
|
-
const tool = mockServer.addTool.mock.calls.at(-1)?.[0];
|
|
64
|
-
const result = await tool.execute({}, undefined);
|
|
65
|
-
expect(result.content[0].text).toContain('Failed to get battery info');
|
|
66
|
-
expect(result.content[0].text).toContain('driver error');
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
//# sourceMappingURL=battery-info.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"battery-info.test.js","sourceRoot":"","sources":["../../../../src/tests/tools/session/battery-info.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"battery-info.d.ts","sourceRoot":"","sources":["../../../src/tools/session/battery-info.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAsCtD,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAkDzD"}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
|
|
3
|
-
import { execute } from '../../command.js';
|
|
4
|
-
import { BatteryState } from 'appium-xcuitest-driver/build/lib/commands/enum.js';
|
|
5
|
-
// iOS: maps UIDeviceBatteryState values to human-readable strings
|
|
6
|
-
// @see https://github.com/appium/appium-xcuitest-driver/blob/5bdad71/lib/commands/enum.ts#L91
|
|
7
|
-
const IOS_BATTERY_STATES = {
|
|
8
|
-
[BatteryState.UIDeviceBatteryStateUnknown]: 'unknown', // UIDeviceBatteryStateUnknown
|
|
9
|
-
[BatteryState.UIDeviceBatteryStateUnplugged]: 'unplugged', // UIDeviceBatteryStateUnplugged
|
|
10
|
-
[BatteryState.UIDeviceBatteryStateCharging]: 'charging', // UIDeviceBatteryStateCharging
|
|
11
|
-
[BatteryState.UIDeviceBatteryStateFull]: 'full', // UIDeviceBatteryStateFull
|
|
12
|
-
};
|
|
13
|
-
// Android: state matches BatteryManager constants
|
|
14
|
-
const ANDROID_BATTERY_STATES = {
|
|
15
|
-
1: 'unknown',
|
|
16
|
-
2: 'charging',
|
|
17
|
-
3: 'discharging',
|
|
18
|
-
4: 'not charging',
|
|
19
|
-
5: 'full',
|
|
20
|
-
};
|
|
21
|
-
function formatBatteryInfo(platform, raw) {
|
|
22
|
-
const levelPercent = Math.round((raw.level ?? 0) * 100);
|
|
23
|
-
const states = platform === PLATFORM.ios ? IOS_BATTERY_STATES : ANDROID_BATTERY_STATES;
|
|
24
|
-
return {
|
|
25
|
-
platform: platform === PLATFORM.ios ? 'iOS' : 'Android',
|
|
26
|
-
level: `${levelPercent}%`,
|
|
27
|
-
state: states[raw.state ?? -1] ?? 'unknown',
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
export default function batteryInfo(server) {
|
|
31
|
-
server.addTool({
|
|
32
|
-
name: 'appium_mobile_get_battery_info',
|
|
33
|
-
description: 'Get the current battery level and charging state of the device. Works on both iOS and Android.',
|
|
34
|
-
parameters: z.object({
|
|
35
|
-
sessionId: z
|
|
36
|
-
.string()
|
|
37
|
-
.optional()
|
|
38
|
-
.describe('Session ID to target. If omitted, uses the active session.'),
|
|
39
|
-
}),
|
|
40
|
-
annotations: {
|
|
41
|
-
readOnlyHint: true,
|
|
42
|
-
openWorldHint: false,
|
|
43
|
-
},
|
|
44
|
-
execute: async (args, _context) => {
|
|
45
|
-
const driver = getDriver(args.sessionId);
|
|
46
|
-
if (!driver) {
|
|
47
|
-
throw new Error('No driver found');
|
|
48
|
-
}
|
|
49
|
-
try {
|
|
50
|
-
const platform = getPlatformName(driver);
|
|
51
|
-
const raw = await execute(driver, 'mobile: batteryInfo', {});
|
|
52
|
-
const formatted = formatBatteryInfo(platform, raw);
|
|
53
|
-
return {
|
|
54
|
-
content: [
|
|
55
|
-
{
|
|
56
|
-
type: 'text',
|
|
57
|
-
text: JSON.stringify(formatted, null, 2),
|
|
58
|
-
},
|
|
59
|
-
],
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
catch (err) {
|
|
63
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
64
|
-
return {
|
|
65
|
-
content: [
|
|
66
|
-
{
|
|
67
|
-
type: 'text',
|
|
68
|
-
text: `Failed to get battery info. Error: ${message}`,
|
|
69
|
-
},
|
|
70
|
-
],
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
//# sourceMappingURL=battery-info.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"battery-info.js","sourceRoot":"","sources":["../../../src/tools/session/battery-info.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"device-time.d.ts","sourceRoot":"","sources":["../../../src/tools/session/device-time.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAKtD,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAyDxD"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { getDriver } from '../../session-store.js';
|
|
3
|
-
import { execute } from '../../command.js';
|
|
4
|
-
export default function deviceTime(server) {
|
|
5
|
-
const schema = z.object({
|
|
6
|
-
format: z
|
|
7
|
-
.string()
|
|
8
|
-
.optional()
|
|
9
|
-
.describe('moment.js format string for the returned time. Defaults to ISO 8601 (YYYY-MM-DDTHH:mm:ssZ).'),
|
|
10
|
-
sessionId: z
|
|
11
|
-
.string()
|
|
12
|
-
.optional()
|
|
13
|
-
.describe('Session ID to target. If omitted, uses the active session.'),
|
|
14
|
-
});
|
|
15
|
-
server.addTool({
|
|
16
|
-
name: 'appium_mobile_get_device_time',
|
|
17
|
-
description: 'Get the current time on the device. Works on both iOS and Android.',
|
|
18
|
-
parameters: schema,
|
|
19
|
-
annotations: {
|
|
20
|
-
readOnlyHint: true,
|
|
21
|
-
openWorldHint: false,
|
|
22
|
-
},
|
|
23
|
-
execute: async (args) => {
|
|
24
|
-
const driver = getDriver(args.sessionId);
|
|
25
|
-
if (!driver) {
|
|
26
|
-
throw new Error('No driver found');
|
|
27
|
-
}
|
|
28
|
-
try {
|
|
29
|
-
const params = {};
|
|
30
|
-
if (args.format != null) {
|
|
31
|
-
params.format = args.format;
|
|
32
|
-
}
|
|
33
|
-
const time = await execute(driver, 'mobile: getDeviceTime', params);
|
|
34
|
-
return {
|
|
35
|
-
content: [
|
|
36
|
-
{
|
|
37
|
-
type: 'text',
|
|
38
|
-
text: String(time),
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
catch (err) {
|
|
44
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
45
|
-
return {
|
|
46
|
-
content: [
|
|
47
|
-
{
|
|
48
|
-
type: 'text',
|
|
49
|
-
text: `Failed to get device time. Error: ${message}`,
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=device-time.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"device-time.js","sourceRoot":"","sources":["../../../src/tools/session/device-time.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,MAAe;IAChD,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;QACtB,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,6FAA6F,CAC9F;QACH,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,4DAA4D,CAAC;KAC1E,CAAC,CAAC;IAEH,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,+BAA+B;QACrC,WAAW,EACT,oEAAoE;QACtE,UAAU,EAAE,MAAM;QAClB,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,aAAa,EAAE,KAAK;SACrB;QACD,OAAO,EAAE,KAAK,EAAE,IAA4B,EAA0B,EAAE;YACtE,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACrC,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,MAAM,GAA4B,EAAE,CAAC;gBAC3C,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;oBACxB,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;gBAC9B,CAAC;gBACD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,uBAAuB,EAAE,MAAM,CAAC,CAAC;gBAEpE,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;yBACnB;qBACF;iBACF,CAAC;YACJ,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,qCAAqC,OAAO,EAAE;yBACrD;qBACF;iBACF,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import type { ContentResult, FastMCP } from 'fastmcp';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
|
|
4
|
-
import { execute } from '../../command.js';
|
|
5
|
-
import { BatteryState } from 'appium-xcuitest-driver/build/lib/commands/enum.js';
|
|
6
|
-
|
|
7
|
-
// iOS: maps UIDeviceBatteryState values to human-readable strings
|
|
8
|
-
// @see https://github.com/appium/appium-xcuitest-driver/blob/5bdad71/lib/commands/enum.ts#L91
|
|
9
|
-
const IOS_BATTERY_STATES: Record<number, string> = {
|
|
10
|
-
[BatteryState.UIDeviceBatteryStateUnknown]: 'unknown', // UIDeviceBatteryStateUnknown
|
|
11
|
-
[BatteryState.UIDeviceBatteryStateUnplugged]: 'unplugged', // UIDeviceBatteryStateUnplugged
|
|
12
|
-
[BatteryState.UIDeviceBatteryStateCharging]: 'charging', // UIDeviceBatteryStateCharging
|
|
13
|
-
[BatteryState.UIDeviceBatteryStateFull]: 'full', // UIDeviceBatteryStateFull
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
// Android: state matches BatteryManager constants
|
|
17
|
-
const ANDROID_BATTERY_STATES: Record<number, string> = {
|
|
18
|
-
1: 'unknown',
|
|
19
|
-
2: 'charging',
|
|
20
|
-
3: 'discharging',
|
|
21
|
-
4: 'not charging',
|
|
22
|
-
5: 'full',
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
function formatBatteryInfo(
|
|
26
|
-
platform: string,
|
|
27
|
-
raw: { level?: number; state?: number }
|
|
28
|
-
): Record<string, string> {
|
|
29
|
-
const levelPercent = Math.round((raw.level ?? 0) * 100);
|
|
30
|
-
const states =
|
|
31
|
-
platform === PLATFORM.ios ? IOS_BATTERY_STATES : ANDROID_BATTERY_STATES;
|
|
32
|
-
return {
|
|
33
|
-
platform: platform === PLATFORM.ios ? 'iOS' : 'Android',
|
|
34
|
-
level: `${levelPercent}%`,
|
|
35
|
-
state: states[raw.state ?? -1] ?? 'unknown',
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export default function batteryInfo(server: FastMCP): void {
|
|
40
|
-
server.addTool({
|
|
41
|
-
name: 'appium_mobile_get_battery_info',
|
|
42
|
-
description:
|
|
43
|
-
'Get the current battery level and charging state of the device. Works on both iOS and Android.',
|
|
44
|
-
parameters: z.object({
|
|
45
|
-
sessionId: z
|
|
46
|
-
.string()
|
|
47
|
-
.optional()
|
|
48
|
-
.describe('Session ID to target. If omitted, uses the active session.'),
|
|
49
|
-
}),
|
|
50
|
-
annotations: {
|
|
51
|
-
readOnlyHint: true,
|
|
52
|
-
openWorldHint: false,
|
|
53
|
-
},
|
|
54
|
-
execute: async (
|
|
55
|
-
args: { sessionId?: string },
|
|
56
|
-
_context: Record<string, unknown> | undefined
|
|
57
|
-
): Promise<ContentResult> => {
|
|
58
|
-
const driver = getDriver(args.sessionId);
|
|
59
|
-
if (!driver) {
|
|
60
|
-
throw new Error('No driver found');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
try {
|
|
64
|
-
const platform = getPlatformName(driver);
|
|
65
|
-
const raw = await execute(driver, 'mobile: batteryInfo', {});
|
|
66
|
-
const formatted = formatBatteryInfo(platform, raw);
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
content: [
|
|
70
|
-
{
|
|
71
|
-
type: 'text',
|
|
72
|
-
text: JSON.stringify(formatted, null, 2),
|
|
73
|
-
},
|
|
74
|
-
],
|
|
75
|
-
};
|
|
76
|
-
} catch (err: unknown) {
|
|
77
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
78
|
-
return {
|
|
79
|
-
content: [
|
|
80
|
-
{
|
|
81
|
-
type: 'text',
|
|
82
|
-
text: `Failed to get battery info. Error: ${message}`,
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import type { ContentResult, FastMCP } from 'fastmcp';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import { getDriver } from '../../session-store.js';
|
|
4
|
-
import { execute } from '../../command.js';
|
|
5
|
-
|
|
6
|
-
export default function deviceTime(server: FastMCP): void {
|
|
7
|
-
const schema = z.object({
|
|
8
|
-
format: z
|
|
9
|
-
.string()
|
|
10
|
-
.optional()
|
|
11
|
-
.describe(
|
|
12
|
-
'moment.js format string for the returned time. Defaults to ISO 8601 (YYYY-MM-DDTHH:mm:ssZ).'
|
|
13
|
-
),
|
|
14
|
-
sessionId: z
|
|
15
|
-
.string()
|
|
16
|
-
.optional()
|
|
17
|
-
.describe('Session ID to target. If omitted, uses the active session.'),
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
server.addTool({
|
|
21
|
-
name: 'appium_mobile_get_device_time',
|
|
22
|
-
description:
|
|
23
|
-
'Get the current time on the device. Works on both iOS and Android.',
|
|
24
|
-
parameters: schema,
|
|
25
|
-
annotations: {
|
|
26
|
-
readOnlyHint: true,
|
|
27
|
-
openWorldHint: false,
|
|
28
|
-
},
|
|
29
|
-
execute: async (args: z.infer<typeof schema>): Promise<ContentResult> => {
|
|
30
|
-
const driver = getDriver(args.sessionId);
|
|
31
|
-
if (!driver) {
|
|
32
|
-
throw new Error('No driver found');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
const params: Record<string, unknown> = {};
|
|
37
|
-
if (args.format != null) {
|
|
38
|
-
params.format = args.format;
|
|
39
|
-
}
|
|
40
|
-
const time = await execute(driver, 'mobile: getDeviceTime', params);
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
content: [
|
|
44
|
-
{
|
|
45
|
-
type: 'text',
|
|
46
|
-
text: String(time),
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
};
|
|
50
|
-
} catch (err: unknown) {
|
|
51
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
52
|
-
return {
|
|
53
|
-
content: [
|
|
54
|
-
{
|
|
55
|
-
type: 'text',
|
|
56
|
-
text: `Failed to get device time. Error: ${message}`,
|
|
57
|
-
},
|
|
58
|
-
],
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
}
|