appium-mcp 1.7.5 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/.github/workflows/ci.yml +3 -0
  2. package/CHANGELOG.md +22 -0
  3. package/dist/devicemanager/adb-manager.d.ts +1 -0
  4. package/dist/devicemanager/adb-manager.d.ts.map +1 -0
  5. package/dist/devicemanager/adb-manager.js +5 -5
  6. package/dist/devicemanager/adb-manager.js.map +1 -1
  7. package/dist/devicemanager/ios-manager.d.ts +1 -0
  8. package/dist/devicemanager/ios-manager.d.ts.map +1 -0
  9. package/dist/devicemanager/ios-manager.js +2 -0
  10. package/dist/devicemanager/ios-manager.js.map +1 -1
  11. package/dist/index.d.ts +1 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/locators/element-filter.d.ts +1 -0
  14. package/dist/locators/element-filter.d.ts.map +1 -0
  15. package/dist/locators/generate-all-locators.d.ts +1 -0
  16. package/dist/locators/generate-all-locators.d.ts.map +1 -0
  17. package/dist/locators/locator-generation.d.ts +1 -0
  18. package/dist/locators/locator-generation.d.ts.map +1 -0
  19. package/dist/locators/source-parsing.d.ts +1 -0
  20. package/dist/locators/source-parsing.d.ts.map +1 -0
  21. package/dist/logger.d.ts +2 -1
  22. package/dist/logger.d.ts.map +1 -0
  23. package/dist/resources/index.d.ts +1 -0
  24. package/dist/resources/index.d.ts.map +1 -0
  25. package/dist/resources/java/template.d.ts +1 -0
  26. package/dist/resources/java/template.d.ts.map +1 -0
  27. package/dist/schema.d.ts +1 -0
  28. package/dist/schema.d.ts.map +1 -0
  29. package/dist/scripts/simple-index-documentation.d.ts +1 -0
  30. package/dist/scripts/simple-index-documentation.d.ts.map +1 -0
  31. package/dist/scripts/simple-query-documentation.d.ts +1 -0
  32. package/dist/scripts/simple-query-documentation.d.ts.map +1 -0
  33. package/dist/server.d.ts +1 -0
  34. package/dist/server.d.ts.map +1 -0
  35. package/dist/session-store.d.ts +16 -2
  36. package/dist/session-store.d.ts.map +1 -0
  37. package/dist/session-store.js +21 -0
  38. package/dist/session-store.js.map +1 -1
  39. package/dist/tests/__mocks__/@appium/support.d.ts +1 -0
  40. package/dist/tests/__mocks__/@appium/support.d.ts.map +1 -0
  41. package/dist/tests/generate-all-locators.test.d.ts +1 -0
  42. package/dist/tests/generate-all-locators.test.d.ts.map +1 -0
  43. package/dist/tests/screenshot.test.d.ts +1 -0
  44. package/dist/tests/screenshot.test.d.ts.map +1 -0
  45. package/dist/tests/screenshot.test.js +6 -5
  46. package/dist/tests/screenshot.test.js.map +1 -1
  47. package/dist/tests/test-setup-wda.d.ts +1 -0
  48. package/dist/tests/test-setup-wda.d.ts.map +1 -0
  49. package/dist/tests/test-setup-wda.js +1 -3
  50. package/dist/tests/test-setup-wda.js.map +1 -1
  51. package/dist/tools/app-management/activate-app.d.ts +2 -1
  52. package/dist/tools/app-management/activate-app.d.ts.map +1 -0
  53. package/dist/tools/app-management/activate-app.js.map +1 -1
  54. package/dist/tools/app-management/install-app.d.ts +2 -1
  55. package/dist/tools/app-management/install-app.d.ts.map +1 -0
  56. package/dist/tools/app-management/install-app.js +6 -2
  57. package/dist/tools/app-management/install-app.js.map +1 -1
  58. package/dist/tools/app-management/list-apps.d.ts +2 -1
  59. package/dist/tools/app-management/list-apps.d.ts.map +1 -0
  60. package/dist/tools/app-management/list-apps.js +4 -1
  61. package/dist/tools/app-management/list-apps.js.map +1 -1
  62. package/dist/tools/app-management/terminate-app.d.ts +2 -1
  63. package/dist/tools/app-management/terminate-app.d.ts.map +1 -0
  64. package/dist/tools/app-management/terminate-app.js +6 -2
  65. package/dist/tools/app-management/terminate-app.js.map +1 -1
  66. package/dist/tools/app-management/uninstall-app.d.ts +2 -1
  67. package/dist/tools/app-management/uninstall-app.d.ts.map +1 -0
  68. package/dist/tools/app-management/uninstall-app.js +6 -2
  69. package/dist/tools/app-management/uninstall-app.js.map +1 -1
  70. package/dist/tools/context/get-contexts.d.ts +2 -1
  71. package/dist/tools/context/get-contexts.d.ts.map +1 -0
  72. package/dist/tools/context/get-contexts.js +4 -1
  73. package/dist/tools/context/get-contexts.js.map +1 -1
  74. package/dist/tools/context/switch-context.d.ts +2 -1
  75. package/dist/tools/context/switch-context.d.ts.map +1 -0
  76. package/dist/tools/context/switch-context.js +4 -1
  77. package/dist/tools/context/switch-context.js.map +1 -1
  78. package/dist/tools/documentation/answer-appium.d.ts +1 -0
  79. package/dist/tools/documentation/answer-appium.d.ts.map +1 -0
  80. package/dist/tools/documentation/index.d.ts +1 -0
  81. package/dist/tools/documentation/index.d.ts.map +1 -0
  82. package/dist/tools/documentation/reasoning-rag.d.ts +1 -0
  83. package/dist/tools/documentation/reasoning-rag.d.ts.map +1 -0
  84. package/dist/tools/documentation/reasoning-rag.js +3 -3
  85. package/dist/tools/documentation/reasoning-rag.js.map +1 -1
  86. package/dist/tools/documentation/sentence-transformers-embeddings.d.ts +1 -0
  87. package/dist/tools/documentation/sentence-transformers-embeddings.d.ts.map +1 -0
  88. package/dist/tools/documentation/sentence-transformers-embeddings.js +4 -3
  89. package/dist/tools/documentation/sentence-transformers-embeddings.js.map +1 -1
  90. package/dist/tools/documentation/simple-pdf-indexer.d.ts +1 -0
  91. package/dist/tools/documentation/simple-pdf-indexer.d.ts.map +1 -0
  92. package/dist/tools/index.d.ts +2 -1
  93. package/dist/tools/index.d.ts.map +1 -0
  94. package/dist/tools/interactions/click.d.ts +2 -1
  95. package/dist/tools/interactions/click.d.ts.map +1 -0
  96. package/dist/tools/interactions/click.js +4 -2
  97. package/dist/tools/interactions/click.js.map +1 -1
  98. package/dist/tools/interactions/double-tap.d.ts +2 -1
  99. package/dist/tools/interactions/double-tap.d.ts.map +1 -0
  100. package/dist/tools/interactions/double-tap.js +8 -4
  101. package/dist/tools/interactions/double-tap.js.map +1 -1
  102. package/dist/tools/interactions/drag-and-drop.d.ts +2 -1
  103. package/dist/tools/interactions/drag-and-drop.d.ts.map +1 -0
  104. package/dist/tools/interactions/drag-and-drop.js +4 -4
  105. package/dist/tools/interactions/drag-and-drop.js.map +1 -1
  106. package/dist/tools/interactions/find.d.ts +2 -1
  107. package/dist/tools/interactions/find.d.ts.map +1 -0
  108. package/dist/tools/interactions/find.js.map +1 -1
  109. package/dist/tools/interactions/get-page-source.d.ts +2 -1
  110. package/dist/tools/interactions/get-page-source.d.ts.map +1 -0
  111. package/dist/tools/interactions/get-page-source.js.map +1 -1
  112. package/dist/tools/interactions/get-text.d.ts +2 -1
  113. package/dist/tools/interactions/get-text.d.ts.map +1 -0
  114. package/dist/tools/interactions/get-text.js +4 -2
  115. package/dist/tools/interactions/get-text.js.map +1 -1
  116. package/dist/tools/interactions/long-press.d.ts +2 -1
  117. package/dist/tools/interactions/long-press.d.ts.map +1 -0
  118. package/dist/tools/interactions/long-press.js +12 -5
  119. package/dist/tools/interactions/long-press.js.map +1 -1
  120. package/dist/tools/interactions/screenshot.d.ts +6 -4
  121. package/dist/tools/interactions/screenshot.d.ts.map +1 -0
  122. package/dist/tools/interactions/screenshot.js +6 -3
  123. package/dist/tools/interactions/screenshot.js.map +1 -1
  124. package/dist/tools/interactions/set-value.d.ts +2 -1
  125. package/dist/tools/interactions/set-value.d.ts.map +1 -0
  126. package/dist/tools/interactions/set-value.js +4 -2
  127. package/dist/tools/interactions/set-value.js.map +1 -1
  128. package/dist/tools/ios/boot-simulator.d.ts +1 -0
  129. package/dist/tools/ios/boot-simulator.d.ts.map +1 -0
  130. package/dist/tools/ios/install-wda.d.ts +1 -0
  131. package/dist/tools/ios/install-wda.d.ts.map +1 -0
  132. package/dist/tools/ios/setup-wda.d.ts +1 -0
  133. package/dist/tools/ios/setup-wda.d.ts.map +1 -0
  134. package/dist/tools/navigations/scroll-to-element.d.ts +1 -0
  135. package/dist/tools/navigations/scroll-to-element.d.ts.map +1 -0
  136. package/dist/tools/navigations/scroll-to-element.js +2 -2
  137. package/dist/tools/navigations/scroll-to-element.js.map +1 -1
  138. package/dist/tools/navigations/scroll.d.ts +1 -0
  139. package/dist/tools/navigations/scroll.d.ts.map +1 -0
  140. package/dist/tools/navigations/scroll.js +19 -9
  141. package/dist/tools/navigations/scroll.js.map +1 -1
  142. package/dist/tools/navigations/swipe.d.ts +1 -0
  143. package/dist/tools/navigations/swipe.d.ts.map +1 -0
  144. package/dist/tools/navigations/swipe.js +11 -5
  145. package/dist/tools/navigations/swipe.js.map +1 -1
  146. package/dist/tools/session/create-session.d.ts +31 -0
  147. package/dist/tools/session/create-session.d.ts.map +1 -0
  148. package/dist/tools/session/create-session.js +88 -21
  149. package/dist/tools/session/create-session.js.map +1 -1
  150. package/dist/tools/session/delete-session.d.ts +1 -0
  151. package/dist/tools/session/delete-session.d.ts.map +1 -0
  152. package/dist/tools/session/delete-session.js +10 -1
  153. package/dist/tools/session/delete-session.js.map +1 -1
  154. package/dist/tools/session/select-device.d.ts +1 -0
  155. package/dist/tools/session/select-device.d.ts.map +1 -0
  156. package/dist/tools/session/select-device.js +11 -4
  157. package/dist/tools/session/select-device.js.map +1 -1
  158. package/dist/tools/session/select-platform.d.ts +1 -0
  159. package/dist/tools/session/select-platform.d.ts.map +1 -0
  160. package/dist/tools/session/select-platform.js +12 -5
  161. package/dist/tools/session/select-platform.js.map +1 -1
  162. package/dist/tools/test-generation/generate-tests.d.ts +2 -1
  163. package/dist/tools/test-generation/generate-tests.d.ts.map +1 -0
  164. package/dist/tools/test-generation/locators.d.ts +1 -0
  165. package/dist/tools/test-generation/locators.d.ts.map +1 -0
  166. package/dist/tools/test-generation/locators.js +4 -2
  167. package/dist/tools/test-generation/locators.js.map +1 -1
  168. package/dist/ui/mcp-ui-utils.d.ts +1 -0
  169. package/dist/ui/mcp-ui-utils.d.ts.map +1 -0
  170. package/package.json +6 -6
  171. package/server.json +2 -2
  172. package/src/session-store.ts +34 -2
  173. package/src/tests/screenshot.test.ts +6 -5
  174. package/src/tools/app-management/activate-app.ts +2 -2
  175. package/src/tools/app-management/install-app.ts +12 -3
  176. package/src/tools/app-management/list-apps.ts +12 -3
  177. package/src/tools/app-management/terminate-app.ts +12 -3
  178. package/src/tools/app-management/uninstall-app.ts +12 -3
  179. package/src/tools/context/get-contexts.ts +10 -4
  180. package/src/tools/context/switch-context.ts +17 -6
  181. package/src/tools/index.ts +1 -1
  182. package/src/tools/interactions/click.ts +6 -3
  183. package/src/tools/interactions/double-tap.ts +19 -7
  184. package/src/tools/interactions/drag-and-drop.ts +16 -7
  185. package/src/tools/interactions/find.ts +5 -2
  186. package/src/tools/interactions/get-page-source.ts +2 -2
  187. package/src/tools/interactions/get-text.ts +6 -3
  188. package/src/tools/interactions/long-press.ts +22 -10
  189. package/src/tools/interactions/screenshot.ts +11 -5
  190. package/src/tools/interactions/set-value.ts +9 -3
  191. package/src/tools/navigations/scroll-to-element.ts +4 -4
  192. package/src/tools/navigations/scroll.ts +25 -10
  193. package/src/tools/navigations/swipe.ts +17 -6
  194. package/src/tools/session/create-session.ts +108 -27
  195. package/src/tools/session/delete-session.ts +10 -1
  196. package/src/tools/session/select-device.ts +11 -4
  197. package/src/tools/session/select-platform.ts +12 -5
  198. package/src/tools/test-generation/generate-tests.ts +1 -1
  199. package/src/tools/test-generation/locators.ts +8 -3
  200. package/tsconfig.json +7 -15
  201. package/tsconfig.tsbuildinfo +1 -0
@@ -1,6 +1,11 @@
1
- import { FastMCP } from 'fastmcp/dist/FastMCP.js';
1
+ import { FastMCP } from 'fastmcp';
2
2
  import { z } from 'zod';
3
- import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
3
+ import {
4
+ getDriver,
5
+ getPlatformName,
6
+ isRemoteDriverSession,
7
+ PLATFORM,
8
+ } from '../../session-store.js';
4
9
 
5
10
  export default function switchContext(server: FastMCP): void {
6
11
  const schema = z.object({
@@ -26,10 +31,16 @@ export default function switchContext(server: FastMCP): void {
26
31
  throw new Error('No driver found. Please create a session first.');
27
32
  }
28
33
 
34
+ if (isRemoteDriverSession(driver)) {
35
+ throw new Error(
36
+ 'Get context is not yet implemented for the remote driver'
37
+ );
38
+ }
39
+
29
40
  try {
30
41
  const [currentContext, availableContexts] = await Promise.all([
31
- driver.getCurrentContext().catch(() => null),
32
- driver.getContexts().catch(() => []),
42
+ (driver as any).getCurrentContext().catch(() => null),
43
+ (driver as any).getContexts().catch(() => []),
33
44
  ]);
34
45
 
35
46
  if (currentContext === args.context) {
@@ -66,10 +77,10 @@ export default function switchContext(server: FastMCP): void {
66
77
  isError: true,
67
78
  };
68
79
  }
69
- await driver.switchContext(args.context);
80
+ await (driver as any).switchContext(args.context);
70
81
 
71
82
  // Verify the switch was successful
72
- const newContext = await driver.getCurrentContext();
83
+ const newContext = await (driver as any).getCurrentContext();
73
84
 
74
85
  return {
75
86
  content: [
@@ -12,7 +12,7 @@
12
12
  * See src/tools/README.md for tool organization.
13
13
  * See src/tools/metadata/README.md for YAML metadata approach.
14
14
  */
15
- import { FastMCP } from 'fastmcp/dist/FastMCP.js';
15
+ import { FastMCP } from 'fastmcp';
16
16
  import log from '../logger.js';
17
17
  import answerAppium from './documentation/answer-appium.js';
18
18
  import createSession from './session/create-session.js';
@@ -1,7 +1,8 @@
1
- import { FastMCP } from 'fastmcp/dist/FastMCP.js';
1
+ import { FastMCP } from 'fastmcp';
2
2
  import { z } from 'zod';
3
- import { getDriver } from '../../session-store.js';
3
+ import { getDriver, isRemoteDriverSession } from '../../session-store.js';
4
4
  import { elementUUIDScheme } from '../../schema.js';
5
+ import type { Client } from 'webdriver';
5
6
 
6
7
  export default function generateTest(server: FastMCP): void {
7
8
  const clickActionSchema = z.object({
@@ -23,7 +24,9 @@ export default function generateTest(server: FastMCP): void {
23
24
  }
24
25
 
25
26
  try {
26
- await driver.click(args.elementUUID);
27
+ const _ok = isRemoteDriverSession(driver)
28
+ ? await (driver as Client).elementClick(args.elementUUID)
29
+ : await (driver as any).click(args.elementUUID);
27
30
  return {
28
31
  content: [
29
32
  {
@@ -1,7 +1,12 @@
1
- import { FastMCP } from 'fastmcp/dist/FastMCP.js';
1
+ import { FastMCP } from 'fastmcp';
2
2
  import { z } from 'zod';
3
- import { getDriver, getPlatformName } from '../../session-store.js';
3
+ import {
4
+ getDriver,
5
+ getPlatformName,
6
+ isRemoteDriverSession,
7
+ } from '../../session-store.js';
4
8
  import { elementUUIDScheme } from '../../schema.js';
9
+ import type { Client } from 'webdriver';
5
10
 
6
11
  export default function doubleTap(server: FastMCP): void {
7
12
  const doubleTapActionSchema = z.object({
@@ -27,7 +32,10 @@ export default function doubleTap(server: FastMCP): void {
27
32
 
28
33
  if (platform === 'Android') {
29
34
  // Get element location for Android double tap
30
- const element = await driver.findElement('id', args.elementUUID);
35
+ const element = await (driver as any).findElement(
36
+ 'id',
37
+ args.elementUUID
38
+ );
31
39
  const location = await element.getLocation();
32
40
  const size = await element.getSize();
33
41
 
@@ -36,7 +44,7 @@ export default function doubleTap(server: FastMCP): void {
36
44
  const y = location.y + size.height / 2;
37
45
 
38
46
  // Perform double tap using performActions
39
- await driver.performActions([
47
+ await (driver as any).performActions([
40
48
  {
41
49
  type: 'pointer',
42
50
  id: 'finger1',
@@ -55,9 +63,13 @@ export default function doubleTap(server: FastMCP): void {
55
63
  ]);
56
64
  } else if (platform === 'iOS') {
57
65
  // Use iOS mobile: doubleTap execute method
58
- await driver.execute('mobile: doubleTap', [
59
- { elementId: args.elementUUID },
60
- ]);
66
+ const _ok = isRemoteDriverSession(driver)
67
+ ? await (driver as Client).executeScript('mobile: doubleTap', [
68
+ { elementId: args.elementUUID },
69
+ ])
70
+ : await (driver as any).execute('mobile: doubleTap', [
71
+ { elementId: args.elementUUID },
72
+ ]);
61
73
  } else {
62
74
  throw new Error(
63
75
  `Unsupported platform: ${platform}. Only Android and iOS are supported.`
@@ -1,7 +1,12 @@
1
- import { FastMCP } from 'fastmcp/dist/FastMCP.js';
1
+ import { FastMCP } from 'fastmcp';
2
2
  import { z } from 'zod';
3
- import { getDriver, getPlatformName } from '../../session-store.js';
3
+ import {
4
+ getDriver,
5
+ getPlatformName,
6
+ isRemoteDriverSession,
7
+ } from '../../session-store.js';
4
8
  import { elementUUIDScheme } from '../../schema.js';
9
+ import type { Client } from 'webdriver';
5
10
 
6
11
  const DROP_PAUSE_DURATION_MS = 150;
7
12
 
@@ -108,13 +113,13 @@ export default function dragAndDrop(server: FastMCP): void {
108
113
  1. Long press (default 600ms, configurable) on the source to initiate drag mode
109
114
  2. While holding, drag to the target location
110
115
  3. Release at the target to complete the drop
111
-
116
+
112
117
  Supports four modes:
113
118
  1. Element to Element: Drag from one element to another element
114
119
  2. Element to Coordinates: Drag from an element to specific coordinates
115
120
  3. Coordinates to Element: Drag from coordinates to an element
116
121
  4. Coordinates to Coordinates: Drag from coordinates to coordinates
117
-
122
+
118
123
  This is useful for reordering lists, moving items, drag-to-delete, and other drag interactions.`,
119
124
  parameters: dragAndDropSchema,
120
125
  annotations: {
@@ -154,7 +159,9 @@ export default function dragAndDrop(server: FastMCP): void {
154
159
  let endX: number, endY: number;
155
160
 
156
161
  if (args.sourceElementUUID) {
157
- const rect = await driver.getElementRect(args.sourceElementUUID);
162
+ const rect = await (driver as any).getElementRect(
163
+ args.sourceElementUUID
164
+ );
158
165
  startX = Math.floor(rect.x + rect.width / 2);
159
166
  startY = Math.floor(rect.y + rect.height / 2);
160
167
  } else {
@@ -163,7 +170,9 @@ export default function dragAndDrop(server: FastMCP): void {
163
170
  }
164
171
 
165
172
  if (args.targetElementUUID) {
166
- const rect = await driver.getElementRect(args.targetElementUUID);
173
+ const rect = await (driver as any).getElementRect(
174
+ args.targetElementUUID
175
+ );
167
176
  endX = Math.floor(rect.x + rect.width / 2);
168
177
  endY = Math.floor(rect.y + rect.height / 2);
169
178
  } else {
@@ -171,7 +180,7 @@ export default function dragAndDrop(server: FastMCP): void {
171
180
  endY = args.targetY;
172
181
  }
173
182
 
174
- const { width, height } = await driver.getWindowSize();
183
+ const { width, height } = await (driver as any).getWindowRect();
175
184
  if (startX < 0 || startX >= width || startY < 0 || startY >= height) {
176
185
  throw new Error(
177
186
  `Source coordinates (${startX}, ${startY}) are out of screen bounds (${width}x${height})`
@@ -1,4 +1,4 @@
1
- import { FastMCP } from 'fastmcp/dist/FastMCP.js';
1
+ import { FastMCP } from 'fastmcp';
2
2
  import { z } from 'zod';
3
3
  import { getDriver } from '../../session-store.js';
4
4
 
@@ -34,7 +34,10 @@ export default function findElement(server: FastMCP): void {
34
34
  }
35
35
 
36
36
  try {
37
- const element = await driver.findElement(args.strategy, args.selector);
37
+ const element = await (driver as any).findElement(
38
+ args.strategy,
39
+ args.selector
40
+ );
38
41
  return {
39
42
  content: [
40
43
  {
@@ -1,4 +1,4 @@
1
- import { FastMCP } from 'fastmcp/dist/FastMCP.js';
1
+ import { FastMCP } from 'fastmcp';
2
2
  import { z } from 'zod';
3
3
  import { getDriver } from '../../session-store.js';
4
4
  import {
@@ -23,7 +23,7 @@ export default function getPageSource(server: FastMCP): void {
23
23
  }
24
24
 
25
25
  try {
26
- const pageSource = await driver.getPageSource();
26
+ const pageSource = await (driver as any).getPageSource();
27
27
 
28
28
  if (!pageSource) {
29
29
  throw new Error('Page source is empty or null');
@@ -1,7 +1,8 @@
1
- import { FastMCP } from 'fastmcp/dist/FastMCP.js';
1
+ import { FastMCP } from 'fastmcp';
2
2
  import { z } from 'zod';
3
- import { getDriver } from '../../session-store.js';
3
+ import { getDriver, isRemoteDriverSession } from '../../session-store.js';
4
4
  import { elementUUIDScheme } from '../../schema.js';
5
+ import type { Client } from 'webdriver';
5
6
 
6
7
  export default function getText(server: FastMCP): void {
7
8
  const getTextSchema = z.object({
@@ -23,7 +24,9 @@ export default function getText(server: FastMCP): void {
23
24
  }
24
25
 
25
26
  try {
26
- const text = await driver.getText(args.elementUUID);
27
+ const text = isRemoteDriverSession(driver)
28
+ ? await (driver as Client).getElementText(args.elementUUID)
29
+ : await (driver as any).getText(args.elementUUID);
27
30
  return {
28
31
  content: [
29
32
  {
@@ -1,7 +1,12 @@
1
- import { FastMCP } from 'fastmcp/dist/FastMCP.js';
1
+ import { FastMCP } from 'fastmcp';
2
2
  import { z } from 'zod';
3
- import { getDriver, getPlatformName } from '../../session-store.js';
3
+ import {
4
+ getDriver,
5
+ getPlatformName,
6
+ isRemoteDriverSession,
7
+ } from '../../session-store.js';
4
8
  import { elementUUIDScheme } from '../../schema.js';
9
+ import type { Client } from 'webdriver';
5
10
 
6
11
  export default function longPress(server: FastMCP): void {
7
12
  const longPressSchema = z.object({
@@ -37,11 +42,11 @@ export default function longPress(server: FastMCP): void {
37
42
  const duration = args.duration || 2000;
38
43
 
39
44
  if (platform === 'Android') {
40
- const rect = await driver.getElementRect(args.elementUUID);
45
+ const rect = await (driver as any).getElementRect(args.elementUUID);
41
46
  const x = Math.floor(rect.x + rect.width / 2);
42
47
  const y = Math.floor(rect.y + rect.height / 2);
43
48
 
44
- await driver.performActions([
49
+ await (driver as any).performActions([
45
50
  {
46
51
  type: 'pointer',
47
52
  id: 'finger1',
@@ -56,16 +61,23 @@ export default function longPress(server: FastMCP): void {
56
61
  ]);
57
62
  } else if (platform === 'iOS') {
58
63
  try {
59
- await driver.execute('mobile: touchAndHold', {
60
- elementId: args.elementUUID,
61
- duration: duration / 1000,
62
- });
64
+ const _ok = isRemoteDriverSession(driver)
65
+ ? await (driver as Client).executeScript('mobile: touchAndHold', [
66
+ {
67
+ elementId: args.elementUUID,
68
+ duration: duration / 1000,
69
+ },
70
+ ])
71
+ : await (driver as any).execute('mobile: touchAndHold', {
72
+ elementId: args.elementUUID,
73
+ duration: duration / 1000,
74
+ });
63
75
  } catch (touchAndHoldError) {
64
- const rect = await driver.getElementRect(args.elementUUID);
76
+ const rect = await (driver as any).getElementRect(args.elementUUID);
65
77
  const x = Math.floor(rect.x + rect.width / 2);
66
78
  const y = Math.floor(rect.y + rect.height / 2);
67
79
 
68
- await driver.performActions([
80
+ await (driver as any).performActions([
69
81
  {
70
82
  type: 'pointer',
71
83
  id: 'finger1',
@@ -1,12 +1,16 @@
1
- import { FastMCP } from 'fastmcp/dist/FastMCP.js';
2
- import { getDriver } from '../../session-store.js';
1
+ import { FastMCP } from 'fastmcp';
2
+ import { getDriver, isRemoteDriverSession } from '../../session-store.js';
3
3
  import { writeFile, mkdir } from 'fs/promises';
4
4
  import { join, isAbsolute } from 'path';
5
+ import * as os from 'node:os';
5
6
  import {
6
7
  createUIResource,
7
8
  createScreenshotViewerUI,
8
9
  addUIResourceToResponse,
9
10
  } from '../../ui/mcp-ui-utils.js';
11
+ import type { Client } from 'webdriver';
12
+ import type { XCUITestDriver } from 'appium-xcuitest-driver';
13
+ import type { AndroidUiautomator2Driver } from 'appium-uiautomator2-driver';
10
14
 
11
15
  /**
12
16
  * Resolves the screenshot directory path.
@@ -18,7 +22,7 @@ export function resolveScreenshotDir(): string {
18
22
  const screenshotDir = process.env.SCREENSHOTS_DIR;
19
23
 
20
24
  if (!screenshotDir) {
21
- return process.cwd();
25
+ return os.tmpdir();
22
26
  }
23
27
 
24
28
  if (isAbsolute(screenshotDir)) {
@@ -29,7 +33,7 @@ export function resolveScreenshotDir(): string {
29
33
  }
30
34
 
31
35
  export interface ScreenshotDeps {
32
- getDriver: () => { getScreenshot: () => Promise<string> } | null;
36
+ getDriver: () => Client | AndroidUiautomator2Driver | XCUITestDriver | null;
33
37
  writeFile: typeof writeFile;
34
38
  mkdir: typeof mkdir;
35
39
  resolveScreenshotDir: typeof resolveScreenshotDir;
@@ -53,7 +57,9 @@ export async function executeScreenshot(
53
57
  }
54
58
 
55
59
  try {
56
- const screenshotBase64 = await driver.getScreenshot();
60
+ const screenshotBase64 = isRemoteDriverSession(driver)
61
+ ? await (driver as Client).takeScreenshot()
62
+ : await (driver as any).getScreenshot();
57
63
 
58
64
  // Convert base64 to buffer
59
65
  const screenshotBuffer = Buffer.from(screenshotBase64, 'base64');
@@ -1,7 +1,8 @@
1
- import { FastMCP } from 'fastmcp/dist/FastMCP.js';
1
+ import { FastMCP } from 'fastmcp';
2
2
  import { z } from 'zod';
3
- import { getDriver } from '../../session-store.js';
3
+ import { getDriver, isRemoteDriverSession } from '../../session-store.js';
4
4
  import { elementUUIDScheme } from '../../schema.js';
5
+ import type { Client } from 'webdriver';
5
6
 
6
7
  export default function setValue(server: FastMCP): void {
7
8
  const setValueSchema = z.object({
@@ -24,7 +25,12 @@ export default function setValue(server: FastMCP): void {
24
25
  }
25
26
 
26
27
  try {
27
- await driver.setValue(args.text, args.elementUUID);
28
+ const _ok = isRemoteDriverSession(driver)
29
+ ? await (driver as Client).elementSendKeys(
30
+ args.elementUUID,
31
+ args.text
32
+ )
33
+ : await (driver as any).setValue(args.text, args.elementUUID);
28
34
  return {
29
35
  content: [
30
36
  {
@@ -84,7 +84,7 @@ async function performAndroidScroll(
84
84
  await driver.findElement('-android uiautomator', scrollCommand);
85
85
  } catch (error) {
86
86
  // If UiScrollable fails, try touch actions
87
- const { width, height } = await driver.getWindowSize();
87
+ const { width, height } = await driver.getWindowRect();
88
88
  const startX = width / 2;
89
89
  const startY = direction === 'up' ? height * 0.3 : height * 0.7;
90
90
  const endY = direction === 'up' ? height * 0.7 : height * 0.3;
@@ -100,7 +100,7 @@ async function performAndroidScroll(
100
100
 
101
101
  async function performiOSScroll(driver: any, direction: string): Promise<void> {
102
102
  // Use iOS mobile commands for scrolling
103
- const { width, height } = await driver.getWindowSize();
103
+ const { width, height } = await driver.getWindowRect();
104
104
 
105
105
  await driver.execute('mobile: scroll', {
106
106
  direction: direction,
@@ -133,7 +133,7 @@ export default function scrollToElement(server: any): void {
133
133
 
134
134
  // First try to find the element directly (it might already be in viewport)
135
135
  try {
136
- const element = await driver.findElement(
136
+ const element = await (driver as any).findElement(
137
137
  args.strategy,
138
138
  args.selector
139
139
  );
@@ -160,7 +160,7 @@ export default function scrollToElement(server: any): void {
160
160
  );
161
161
  }
162
162
 
163
- const element = await driver.findElement(
163
+ const element = await (driver as any).findElement(
164
164
  args.strategy,
165
165
  args.selector
166
166
  );
@@ -1,6 +1,11 @@
1
1
  import { z } from 'zod';
2
- import { getDriver, getPlatformName } from '../../session-store.js';
2
+ import {
3
+ getDriver,
4
+ getPlatformName,
5
+ isRemoteDriverSession,
6
+ } from '../../session-store.js';
3
7
  import log from '../../logger.js';
8
+ import type { Client } from 'webdriver';
4
9
 
5
10
  export default function scroll(server: any): void {
6
11
  server.addTool({
@@ -25,7 +30,7 @@ export default function scroll(server: any): void {
25
30
  }
26
31
 
27
32
  try {
28
- const { width, height } = await driver.getWindowSize();
33
+ const { width, height } = await (driver as any).getWindowRect();
29
34
  log.info('Device screen size:', { width, height });
30
35
  const startX = Math.floor(width / 2);
31
36
  // calculate start and end Y positions for scrolling depending on the direction
@@ -47,7 +52,7 @@ export default function scroll(server: any): void {
47
52
  log.info('Going to scroll to:', { startX, endY });
48
53
 
49
54
  if (getPlatformName(driver) === 'Android') {
50
- await driver.performActions([
55
+ await (driver as any).performActions([
51
56
  {
52
57
  type: 'pointer',
53
58
  id: 'finger1',
@@ -63,13 +68,23 @@ export default function scroll(server: any): void {
63
68
  ]);
64
69
  log.info('Scroll action completed successfully.');
65
70
  } else if (getPlatformName(driver) === 'iOS') {
66
- await driver.execute('mobile: scroll', {
67
- direction: args.direction,
68
- startX: startX,
69
- startY: startY,
70
- endX: startX,
71
- endY: endY,
72
- });
71
+ const _ok = isRemoteDriverSession(driver)
72
+ ? await (driver as Client).executeScript('mobile: scroll', [
73
+ {
74
+ direction: args.direction,
75
+ startX: startX,
76
+ startY: startY,
77
+ endX: startX,
78
+ endY: endY,
79
+ },
80
+ ])
81
+ : await (driver as any).execute('mobile: scroll', {
82
+ direction: args.direction,
83
+ startX: startX,
84
+ startY: startY,
85
+ endX: startX,
86
+ endY: endY,
87
+ });
73
88
  } else {
74
89
  throw new Error(
75
90
  `Unsupported platform: ${getPlatformName(driver)}. Only Android and iOS are supported.`
@@ -1,7 +1,12 @@
1
1
  import { z } from 'zod';
2
- import { getDriver, getPlatformName } from '../../session-store.js';
2
+ import {
3
+ getDriver,
4
+ getPlatformName,
5
+ isRemoteDriverSession,
6
+ } from '../../session-store.js';
3
7
  import log from '../../logger.js';
4
8
  import { elementUUIDScheme } from '../../schema.js';
9
+ import type { Client } from 'webdriver';
5
10
 
6
11
  function calculateSwipeCoordinates(
7
12
  direction: 'left' | 'right' | 'up' | 'down',
@@ -227,7 +232,7 @@ export default function swipe(server: any): void {
227
232
  endY,
228
233
  });
229
234
  } else {
230
- const { width, height } = await driver.getWindowSize();
235
+ const { width, height } = await (driver as any).getWindowRect();
231
236
  log.info('Device screen size:', { width, height });
232
237
  const coords = calculateSwipeCoordinates(
233
238
  args.direction,
@@ -268,7 +273,7 @@ export default function swipe(server: any): void {
268
273
  if (platform === 'Android') {
269
274
  if (startX !== endX && Math.abs(startY - endY) < 50) {
270
275
  const swipeDuration = Math.min(duration, 400);
271
- await driver.performActions([
276
+ await (driver as any).performActions([
272
277
  {
273
278
  type: 'pointer',
274
279
  id: 'finger1',
@@ -303,9 +308,15 @@ export default function swipe(server: any): void {
303
308
  } else if (platform === 'iOS') {
304
309
  if (args.direction) {
305
310
  try {
306
- await driver.execute('mobile: swipe', {
307
- direction: args.direction,
308
- });
311
+ const _ok = isRemoteDriverSession(driver)
312
+ ? await (driver as Client).executeScript('mobile: swipe', [
313
+ {
314
+ direction: args.direction,
315
+ },
316
+ ])
317
+ : await (driver as any).execute('mobile: swipe', {
318
+ direction: args.direction,
319
+ });
309
320
  log.info(
310
321
  `iOS swipe completed using mobile: swipe (${args.direction})`
311
322
  );