appium-mcp 1.71.5 → 1.71.6

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.71.6](https://github.com/appium/appium-mcp/compare/v1.71.5...v1.71.6) (2026-05-01)
2
+
3
+ ### Bug Fixes
4
+
5
+ * add actions api to the java template ([#310](https://github.com/appium/appium-mcp/issues/310)) ([caebdd4](https://github.com/appium/appium-mcp/commit/caebdd41d21a51dbfaaa790952e2fc9ccc1e0c77))
6
+
1
7
  ## [1.71.5](https://github.com/appium/appium-mcp/compare/v1.71.4...v1.71.5) (2026-04-30)
2
8
 
3
9
  ### Bug Fixes
@@ -1 +1 @@
1
- {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../src/resources/java/template.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,MAAM,EAAE,GAAG,QA+ExD"}
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../src/resources/java/template.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,MAAM,EAAE,GAAG,QA6GxD"}
@@ -7,6 +7,7 @@ export default function javaTemplatesResource(server) {
7
7
  name: 'Generate Code With Locators',
8
8
  description: `Generate code for the current page with locators which was retrieved from generate_locators tool.
9
9
  The code should be generated in the same priorty order as the locators were generated.
10
+ Always use the actions API code from the template for the gestures.
10
11
  For iOS the priority order is:
11
12
  'id',
12
13
  'accessibility id',
@@ -73,6 +74,35 @@ public class locators {
73
74
  public locators(AppiumDriver driver) {
74
75
  PageFactory.initElements(new AppiumFieldDecorator(driver, Duration.ofSeconds(10)), this);
75
76
  }
77
+
78
+ @Test
79
+ public void sliderTest() {
80
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
81
+ wait.until(ExpectedConditions.elementToBeClickable(AppiumBy.accessibilityId("login"))).click();
82
+ wait.until(ExpectedConditions.elementToBeClickable(AppiumBy.accessibilityId("slider1"))).click();
83
+
84
+ try { Thread.sleep(1000); } catch (InterruptedException e) {}
85
+
86
+ WebElement slider = wait.until(ExpectedConditions.visibilityOfElementLocated(AppiumBy.accessibilityId("slider")));
87
+
88
+ Point location = slider.getLocation();
89
+ Dimension size = slider.getSize();
90
+
91
+ // Swipe right: from left side of the slider to the right side
92
+ int startX = location.getX() + (int)(size.getWidth() * 0.1);
93
+ int endX = location.getX() + (int)(size.getWidth() * 0.9);
94
+ int y = location.getY() + size.getHeight() / 2;
95
+
96
+ PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
97
+ Sequence swipe = new Sequence(finger, 1);
98
+
99
+ swipe.addAction(finger.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), startX, y));
100
+ swipe.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
101
+ swipe.addAction(finger.createPointerMove(Duration.ofMillis(600), PointerInput.Origin.viewport(), endX, y));
102
+ swipe.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
103
+
104
+ driver.perform(Collections.singletonList(swipe));
105
+ }
76
106
  }
77
107
  `,
78
108
  };
@@ -1 +1 @@
1
- {"version":3,"file":"template.js","sourceRoot":"","sources":["../../../src/resources/java/template.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,MAAW;IACvD,MAAM,CAAC,WAAW,CAAC;QACjB,GAAG,EAAE,+BAA+B;QACpC,IAAI,EAAE,6BAA6B;QACnC,WAAW,EAAE;;;;;;;;;;;;;;;sHAeqG;QAClH,QAAQ,EAAE,YAAY;QACtB,KAAK,CAAC,IAAI;YACR,uDAAuD;YACvD,OAAO;gBACL,OAAO,EACL,uFAAuF;gBACzF,WAAW,EACT,2DAA2D;gBAC7D,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+CT;aACE,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../../src/resources/java/template.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,MAAW;IACvD,MAAM,CAAC,WAAW,CAAC;QACjB,GAAG,EAAE,+BAA+B;QACpC,IAAI,EAAE,6BAA6B;QACnC,WAAW,EAAE;;;;;;;;;;;;;;;;sHAgBqG;QAClH,QAAQ,EAAE,YAAY;QACtB,KAAK,CAAC,IAAI;YACR,uDAAuD;YACvD,OAAO;gBACL,OAAO,EACL,uFAAuF;gBACzF,WAAW,EACT,2DAA2D;gBAC7D,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4ET;aACE,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -1,3 +1,3 @@
1
- import { FastMCP } from 'fastmcp';
1
+ import type { FastMCP } from 'fastmcp';
2
2
  export default function generateTest(server: FastMCP): void;
3
3
  //# sourceMappingURL=generate-tests.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate-tests.d.ts","sourceRoot":"","sources":["../../../src/tools/test-generation/generate-tests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAIlC,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAoC1D"}
1
+ {"version":3,"file":"generate-tests.d.ts","sourceRoot":"","sources":["../../../src/tools/test-generation/generate-tests.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAQtD,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAgD1D"}
@@ -1,30 +1,42 @@
1
1
  import { z } from 'zod';
2
2
  import { textResult } from '../tool-response.js';
3
+ const generateTestSchema = z.object({
4
+ steps: z.array(z.string()).describe('The steps of the test'),
5
+ });
3
6
  export default function generateTest(server) {
4
- const generateTestSchema = z.object({
5
- steps: z.array(z.string()).describe('The steps of the test'),
6
- });
7
7
  const instructions = (params) => [
8
8
  `## Instructions`,
9
9
  `- You are an Appium test generator.`,
10
- `- You are given a scenario and you need to generate a appium test for it.`,
11
- `- Request user to select the platform first using select_device tool and create a session`,
12
- `- Use generate_locators tool to fetch all interactable elements from the current screen and use it to generate the tests`,
13
- `- Element can only be clicked only if it is clickable.`,
14
- `- Text can entered in the element only if it is focusable`,
15
- `- If any interaction on element is failed, retry again with a differnt possible locator in the hierrarchy`,
16
- `- Interact with the app using the tools provided and generate the test`,
17
- '- DO NOT generate test code based on the scenario alone. DO run steps one by one using the tools provided instead.',
18
- '- Only after all steps are completed, emit a Appium test based on message history',
19
- '- Save generated test file in the tests directory',
20
- `- Use generate://code-with-locators resource as reference for code generation`,
21
- `- Always call find_element_tool to retrieve the element UUID before interacting with the element`,
10
+ `- You are given a scenario and you need to generate an Appium test for it.`,
11
+ ``,
12
+ `### Ordered workflow (use these exact MCP tool names)`,
13
+ `1. select_device choose platform/device (local/embedded mode). Skip if the user already connected to a remote Appium URL (then use appium_session_management only).`,
14
+ `2. prepare_ios_simulator or appium_prepare_ios_real_device only when iOS local setup requires it; otherwise skip.`,
15
+ `3. appium_session_management with action=create start a driver session (match platform to select_device unless using remote server mode).`,
16
+ `4. appium_app_lifecycle or other session tools as needed (e.g. activate app, deep link) only if the scenario requires it.`,
17
+ `5. Discover the target element prefer appium_get_active_element when the focused field is enough; otherwise appium_find_element (strategy + selector, or ai_instruction when appropriate). Use generate_locators only for broad inspection/debugging, not for every step.`,
18
+ `6. Interact using the same tool names the server exposes, for example:`,
19
+ ` - appium_gesture with action=tap (or double_tap, long_press, scroll, swipe, scroll_to_element, pinch_zoom) — use the element id from appium_find_element when required`,
20
+ ` - appium_set_value type into an element; optionally appium_mobile_press_key for special keys`,
21
+ ` - appium_get_text / appium_get_element_attribute when assertions need visible state`,
22
+ `- After appium_find_element, the first line of the response is elementId:<uuid> (or an ai-element coordinate token). Pass that value as elementUUID to gestures or appium_set_value as documented in each tool.`,
23
+ ``,
24
+ `- Use generate_locators to fetch interactable elements when you need full-screen locator lists for code generation; pairing with generate://code-with-locators is fine for templates.`,
25
+ `- An element can only be clicked if it is clickable.`,
26
+ `- Text can only be entered into an element if it is focusable (or use appium_set_value with w3cActions when typing into the focused element).`,
27
+ `- If an interaction fails, retry with a different possible locator in the hierarchy.`,
28
+ `- Interact with the app using the tools provided, then generate the test.`,
29
+ `- DO NOT generate test code from the scenario alone. DO run steps one by one with the tools listed above.`,
30
+ `- Only after all steps are completed, emit an Appium/WebdriverIO-style test based on the message history.`,
31
+ `- Save the generated test file in the tests directory.`,
32
+ `- Use the generate://code-with-locators resource as reference for code generation.`,
33
+ `- Always call appium_find_element (or appium_get_active_element when sufficient) to obtain elementId before tapping or setting value on a specific element.`,
22
34
  `Steps:`,
23
35
  ...params.steps.map((step, index) => `- ${index + 1}. ${step}`),
24
36
  ].join('\n');
25
37
  server.addTool({
26
38
  name: 'appium_generate_tests',
27
- description: 'Generate tests for a given mobile app',
39
+ description: 'Generate tests for a mobile app: follow the returned instructions to drive the real session with MCP tools (select_device, appium_session_management, appium_find_element, appium_gesture, appium_set_value, etc.), then emit code. Use generate_locators only when you need a full locator snapshot; prefer appium_find_element for normal steps.',
28
40
  parameters: generateTestSchema,
29
41
  annotations: {
30
42
  readOnlyHint: false,
@@ -1 +1 @@
1
- {"version":3,"file":"generate-tests.js","sourceRoot":"","sources":["../../../src/tools/test-generation/generate-tests.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,MAAe;IAClD,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;QAClC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC;KAC7D,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,CAAC,MAA2B,EAAE,EAAE,CACnD;QACE,iBAAiB;QACjB,qCAAqC;QACrC,2EAA2E;QAC3E,2FAA2F;QAC3F,0HAA0H;QAC1H,wDAAwD;QACxD,2DAA2D;QAC3D,2GAA2G;QAC3G,wEAAwE;QACxE,oHAAoH;QACpH,mFAAmF;QACnF,mDAAmD;QACnD,+EAA+E;QAC/E,kGAAkG;QAClG,QAAQ;QACR,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;KAChE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEf,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,uCAAuC;QACpD,UAAU,EAAE,kBAAkB;QAC9B,WAAW,EAAE;YACX,YAAY,EAAE,KAAK;YACnB,aAAa,EAAE,KAAK;SACrB;QACD,OAAO,EAAE,KAAK,EAAE,IAAS,EAAE,QAAa,EAAgB,EAAE,CACxD,UAAU,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;KAClD,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"generate-tests.js","sourceRoot":"","sources":["../../../src/tools/test-generation/generate-tests.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC;CAC7D,CAAC,CAAC;AAEH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,MAAe;IAClD,MAAM,YAAY,GAAG,CAAC,MAA2B,EAAE,EAAE,CACnD;QACE,iBAAiB;QACjB,qCAAqC;QACrC,4EAA4E;QAC5E,EAAE;QACF,uDAAuD;QACvD,uKAAuK;QACvK,qHAAqH;QACrH,6IAA6I;QAC7I,6HAA6H;QAC7H,6QAA6Q;QAC7Q,wEAAwE;QACxE,2KAA2K;QAC3K,mGAAmG;QACnG,wFAAwF;QACxF,iNAAiN;QACjN,EAAE;QACF,uLAAuL;QACvL,sDAAsD;QACtD,+IAA+I;QAC/I,sFAAsF;QACtF,2EAA2E;QAC3E,2GAA2G;QAC3G,2GAA2G;QAC3G,wDAAwD;QACxD,oFAAoF;QACpF,6JAA6J;QAC7J,QAAQ;QACR,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;KAChE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEf,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EACT,oVAAoV;QACtV,UAAU,EAAE,kBAAkB;QAC9B,WAAW,EAAE;YACX,YAAY,EAAE,KAAK;YACnB,aAAa,EAAE,KAAK;SACrB;QACD,OAAO,EAAE,KAAK,EACZ,IAAwC,EACxC,QAA6C,EACrB,EAAE,CAC1B,UAAU,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;KAClD,CAAC,CAAC;AACL,CAAC"}
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.71.5",
4
+ "version": "1.71.6",
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.71.5",
6
+ "version": "1.71.6",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "identifier": "appium-mcp",
11
- "version": "1.71.5",
11
+ "version": "1.71.6",
12
12
  "transport": {
13
13
  "type": "stdio"
14
14
  }
@@ -7,6 +7,7 @@ export default function javaTemplatesResource(server: any) {
7
7
  name: 'Generate Code With Locators',
8
8
  description: `Generate code for the current page with locators which was retrieved from generate_locators tool.
9
9
  The code should be generated in the same priorty order as the locators were generated.
10
+ Always use the actions API code from the template for the gestures.
10
11
  For iOS the priority order is:
11
12
  'id',
12
13
  'accessibility id',
@@ -75,6 +76,35 @@ public class locators {
75
76
  public locators(AppiumDriver driver) {
76
77
  PageFactory.initElements(new AppiumFieldDecorator(driver, Duration.ofSeconds(10)), this);
77
78
  }
79
+
80
+ @Test
81
+ public void sliderTest() {
82
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
83
+ wait.until(ExpectedConditions.elementToBeClickable(AppiumBy.accessibilityId("login"))).click();
84
+ wait.until(ExpectedConditions.elementToBeClickable(AppiumBy.accessibilityId("slider1"))).click();
85
+
86
+ try { Thread.sleep(1000); } catch (InterruptedException e) {}
87
+
88
+ WebElement slider = wait.until(ExpectedConditions.visibilityOfElementLocated(AppiumBy.accessibilityId("slider")));
89
+
90
+ Point location = slider.getLocation();
91
+ Dimension size = slider.getSize();
92
+
93
+ // Swipe right: from left side of the slider to the right side
94
+ int startX = location.getX() + (int)(size.getWidth() * 0.1);
95
+ int endX = location.getX() + (int)(size.getWidth() * 0.9);
96
+ int y = location.getY() + size.getHeight() / 2;
97
+
98
+ PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
99
+ Sequence swipe = new Sequence(finger, 1);
100
+
101
+ swipe.addAction(finger.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), startX, y));
102
+ swipe.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
103
+ swipe.addAction(finger.createPointerMove(Duration.ofMillis(600), PointerInput.Origin.viewport(), endX, y));
104
+ swipe.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
105
+
106
+ driver.perform(Collections.singletonList(swipe));
107
+ }
78
108
  }
79
109
  `,
80
110
  };
Binary file
@@ -1,41 +1,57 @@
1
- import { FastMCP } from 'fastmcp';
1
+ import type { ContentResult, FastMCP } from 'fastmcp';
2
2
  import { z } from 'zod';
3
3
  import { textResult } from '../tool-response.js';
4
4
 
5
- export default function generateTest(server: FastMCP): void {
6
- const generateTestSchema = z.object({
7
- steps: z.array(z.string()).describe('The steps of the test'),
8
- });
5
+ const generateTestSchema = z.object({
6
+ steps: z.array(z.string()).describe('The steps of the test'),
7
+ });
9
8
 
9
+ export default function generateTest(server: FastMCP): void {
10
10
  const instructions = (params: { steps: string[] }) =>
11
11
  [
12
12
  `## Instructions`,
13
13
  `- You are an Appium test generator.`,
14
- `- You are given a scenario and you need to generate a appium test for it.`,
15
- `- Request user to select the platform first using select_device tool and create a session`,
16
- `- Use generate_locators tool to fetch all interactable elements from the current screen and use it to generate the tests`,
17
- `- Element can only be clicked only if it is clickable.`,
18
- `- Text can entered in the element only if it is focusable`,
19
- `- If any interaction on element is failed, retry again with a differnt possible locator in the hierrarchy`,
20
- `- Interact with the app using the tools provided and generate the test`,
21
- '- DO NOT generate test code based on the scenario alone. DO run steps one by one using the tools provided instead.',
22
- '- Only after all steps are completed, emit a Appium test based on message history',
23
- '- Save generated test file in the tests directory',
24
- `- Use generate://code-with-locators resource as reference for code generation`,
25
- `- Always call find_element_tool to retrieve the element UUID before interacting with the element`,
14
+ `- You are given a scenario and you need to generate an Appium test for it.`,
15
+ ``,
16
+ `### Ordered workflow (use these exact MCP tool names)`,
17
+ `1. select_device choose platform/device (local/embedded mode). Skip if the user already connected to a remote Appium URL (then use appium_session_management only).`,
18
+ `2. prepare_ios_simulator or appium_prepare_ios_real_device only when iOS local setup requires it; otherwise skip.`,
19
+ `3. appium_session_management with action=create start a driver session (match platform to select_device unless using remote server mode).`,
20
+ `4. appium_app_lifecycle or other session tools as needed (e.g. activate app, deep link) only if the scenario requires it.`,
21
+ `5. Discover the target element prefer appium_get_active_element when the focused field is enough; otherwise appium_find_element (strategy + selector, or ai_instruction when appropriate). Use generate_locators only for broad inspection/debugging, not for every step.`,
22
+ `6. Interact using the same tool names the server exposes, for example:`,
23
+ ` - appium_gesture with action=tap (or double_tap, long_press, scroll, swipe, scroll_to_element, pinch_zoom) — use the element id from appium_find_element when required`,
24
+ ` - appium_set_value type into an element; optionally appium_mobile_press_key for special keys`,
25
+ ` - appium_get_text / appium_get_element_attribute when assertions need visible state`,
26
+ `- After appium_find_element, the first line of the response is elementId:<uuid> (or an ai-element coordinate token). Pass that value as elementUUID to gestures or appium_set_value as documented in each tool.`,
27
+ ``,
28
+ `- Use generate_locators to fetch interactable elements when you need full-screen locator lists for code generation; pairing with generate://code-with-locators is fine for templates.`,
29
+ `- An element can only be clicked if it is clickable.`,
30
+ `- Text can only be entered into an element if it is focusable (or use appium_set_value with w3cActions when typing into the focused element).`,
31
+ `- If an interaction fails, retry with a different possible locator in the hierarchy.`,
32
+ `- Interact with the app using the tools provided, then generate the test.`,
33
+ `- DO NOT generate test code from the scenario alone. DO run steps one by one with the tools listed above.`,
34
+ `- Only after all steps are completed, emit an Appium/WebdriverIO-style test based on the message history.`,
35
+ `- Save the generated test file in the tests directory.`,
36
+ `- Use the generate://code-with-locators resource as reference for code generation.`,
37
+ `- Always call appium_find_element (or appium_get_active_element when sufficient) to obtain elementId before tapping or setting value on a specific element.`,
26
38
  `Steps:`,
27
39
  ...params.steps.map((step, index) => `- ${index + 1}. ${step}`),
28
40
  ].join('\n');
29
41
 
30
42
  server.addTool({
31
43
  name: 'appium_generate_tests',
32
- description: 'Generate tests for a given mobile app',
44
+ description:
45
+ 'Generate tests for a mobile app: follow the returned instructions to drive the real session with MCP tools (select_device, appium_session_management, appium_find_element, appium_gesture, appium_set_value, etc.), then emit code. Use generate_locators only when you need a full locator snapshot; prefer appium_find_element for normal steps.',
33
46
  parameters: generateTestSchema,
34
47
  annotations: {
35
48
  readOnlyHint: false,
36
49
  openWorldHint: false,
37
50
  },
38
- execute: async (args: any, _context: any): Promise<any> =>
51
+ execute: async (
52
+ args: z.infer<typeof generateTestSchema>,
53
+ _context: Record<string, unknown> | undefined
54
+ ): Promise<ContentResult> =>
39
55
  textResult(instructions({ steps: args.steps })),
40
56
  });
41
57
  }