appium-mcp 1.82.2 → 1.84.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.
Files changed (114) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -0
  3. package/dist/create-server.d.ts.map +1 -1
  4. package/dist/create-server.js +4 -0
  5. package/dist/create-server.js.map +1 -1
  6. package/dist/server.d.ts.map +1 -1
  7. package/dist/server.js +7 -4
  8. package/dist/server.js.map +1 -1
  9. package/dist/tests/create-server.test.js +8 -0
  10. package/dist/tests/create-server.test.js.map +1 -1
  11. package/dist/tests/tools/evidence.test.d.ts +2 -0
  12. package/dist/tests/tools/evidence.test.d.ts.map +1 -0
  13. package/dist/tests/tools/evidence.test.js +158 -0
  14. package/dist/tests/tools/evidence.test.js.map +1 -0
  15. package/dist/tests/utils/paths.test.js +5 -6
  16. package/dist/tests/utils/paths.test.js.map +1 -1
  17. package/dist/tools/evidence.d.ts +82 -0
  18. package/dist/tools/evidence.d.ts.map +1 -0
  19. package/dist/tools/evidence.js +124 -0
  20. package/dist/tools/evidence.js.map +1 -0
  21. package/dist/tools/gestures/gesture.d.ts.map +1 -1
  22. package/dist/tools/gestures/gesture.js +47 -25
  23. package/dist/tools/gestures/gesture.js.map +1 -1
  24. package/dist/tools/interactions/find.d.ts.map +1 -1
  25. package/dist/tools/interactions/find.js +27 -4
  26. package/dist/tools/interactions/find.js.map +1 -1
  27. package/package.json +8 -19
  28. package/server.json +2 -2
  29. package/src/create-server.ts +4 -0
  30. package/src/server.ts +9 -4
  31. package/src/tools/evidence.ts +198 -0
  32. package/src/tools/gestures/gesture.ts +63 -26
  33. package/src/tools/interactions/find.ts +40 -6
  34. package/dist/scripts/eval-documentation-rag.d.ts +0 -50
  35. package/dist/scripts/eval-documentation-rag.d.ts.map +0 -1
  36. package/dist/scripts/eval-documentation-rag.js +0 -287
  37. package/dist/scripts/eval-documentation-rag.js.map +0 -1
  38. package/dist/scripts/generate-embeddings-cache.d.ts +0 -13
  39. package/dist/scripts/generate-embeddings-cache.d.ts.map +0 -1
  40. package/dist/scripts/generate-embeddings-cache.js +0 -24
  41. package/dist/scripts/generate-embeddings-cache.js.map +0 -1
  42. package/dist/scripts/rag-eval-dataset.json +0 -516
  43. package/dist/scripts/simple-index-documentation.d.ts +0 -21
  44. package/dist/scripts/simple-index-documentation.d.ts.map +0 -1
  45. package/dist/scripts/simple-index-documentation.js +0 -77
  46. package/dist/scripts/simple-index-documentation.js.map +0 -1
  47. package/dist/scripts/simple-query-documentation.d.ts +0 -13
  48. package/dist/scripts/simple-query-documentation.d.ts.map +0 -1
  49. package/dist/scripts/simple-query-documentation.js +0 -52
  50. package/dist/scripts/simple-query-documentation.js.map +0 -1
  51. package/dist/tests/tools/documentation/appium-skills.test.d.ts +0 -2
  52. package/dist/tests/tools/documentation/appium-skills.test.d.ts.map +0 -1
  53. package/dist/tests/tools/documentation/appium-skills.test.js +0 -106
  54. package/dist/tests/tools/documentation/appium-skills.test.js.map +0 -1
  55. package/dist/tests/tools/documentation/plugin.test.d.ts +0 -2
  56. package/dist/tests/tools/documentation/plugin.test.d.ts.map +0 -1
  57. package/dist/tests/tools/documentation/plugin.test.js +0 -34
  58. package/dist/tests/tools/documentation/plugin.test.js.map +0 -1
  59. package/dist/tests/tools/documentation/simple-pdf-indexer.test.d.ts +0 -2
  60. package/dist/tests/tools/documentation/simple-pdf-indexer.test.d.ts.map +0 -1
  61. package/dist/tests/tools/documentation/simple-pdf-indexer.test.js +0 -46
  62. package/dist/tests/tools/documentation/simple-pdf-indexer.test.js.map +0 -1
  63. package/dist/tools/documentation/answer-appium.d.ts +0 -8
  64. package/dist/tools/documentation/answer-appium.d.ts.map +0 -1
  65. package/dist/tools/documentation/answer-appium.js +0 -38
  66. package/dist/tools/documentation/answer-appium.js.map +0 -1
  67. package/dist/tools/documentation/appium-skills.d.ts +0 -5
  68. package/dist/tools/documentation/appium-skills.d.ts.map +0 -1
  69. package/dist/tools/documentation/appium-skills.js +0 -168
  70. package/dist/tools/documentation/appium-skills.js.map +0 -1
  71. package/dist/tools/documentation/index.d.ts +0 -29
  72. package/dist/tools/documentation/index.d.ts.map +0 -1
  73. package/dist/tools/documentation/index.js +0 -66
  74. package/dist/tools/documentation/index.js.map +0 -1
  75. package/dist/tools/documentation/markdown-header-splitter.d.ts +0 -32
  76. package/dist/tools/documentation/markdown-header-splitter.d.ts.map +0 -1
  77. package/dist/tools/documentation/markdown-header-splitter.js +0 -180
  78. package/dist/tools/documentation/markdown-header-splitter.js.map +0 -1
  79. package/dist/tools/documentation/plugin.d.ts +0 -14
  80. package/dist/tools/documentation/plugin.d.ts.map +0 -1
  81. package/dist/tools/documentation/plugin.js +0 -19
  82. package/dist/tools/documentation/plugin.js.map +0 -1
  83. package/dist/tools/documentation/reasoning-rag.d.ts +0 -89
  84. package/dist/tools/documentation/reasoning-rag.d.ts.map +0 -1
  85. package/dist/tools/documentation/reasoning-rag.js +0 -282
  86. package/dist/tools/documentation/reasoning-rag.js.map +0 -1
  87. package/dist/tools/documentation/sentence-transformers-embeddings.d.ts +0 -40
  88. package/dist/tools/documentation/sentence-transformers-embeddings.d.ts.map +0 -1
  89. package/dist/tools/documentation/sentence-transformers-embeddings.js +0 -119
  90. package/dist/tools/documentation/sentence-transformers-embeddings.js.map +0 -1
  91. package/dist/tools/documentation/simple-pdf-indexer.d.ts +0 -47
  92. package/dist/tools/documentation/simple-pdf-indexer.d.ts.map +0 -1
  93. package/dist/tools/documentation/simple-pdf-indexer.js +0 -572
  94. package/dist/tools/documentation/simple-pdf-indexer.js.map +0 -1
  95. package/dist/tools/documentation/uploads/documents.json +0 -1
  96. package/dist/tools/documentation/uploads/embeddings-Xenova-bge-small-en-v1.5.json +0 -1
  97. package/scripts/setup-submodules-sparse.sh +0 -53
  98. package/scripts/update-submodules.sh +0 -14
  99. package/scripts/zip-assets.mjs +0 -55
  100. package/src/resources/submodules.zip +0 -0
  101. package/src/scripts/eval-documentation-rag.ts +0 -433
  102. package/src/scripts/generate-embeddings-cache.ts +0 -24
  103. package/src/scripts/rag-eval-dataset.json +0 -516
  104. package/src/scripts/simple-index-documentation.ts +0 -93
  105. package/src/scripts/simple-query-documentation.ts +0 -61
  106. package/src/tools/documentation/answer-appium.ts +0 -47
  107. package/src/tools/documentation/appium-skills.ts +0 -244
  108. package/src/tools/documentation/index.ts +0 -99
  109. package/src/tools/documentation/markdown-header-splitter.ts +0 -209
  110. package/src/tools/documentation/plugin.ts +0 -21
  111. package/src/tools/documentation/reasoning-rag.ts +0 -438
  112. package/src/tools/documentation/sentence-transformers-embeddings.ts +0 -152
  113. package/src/tools/documentation/simple-pdf-indexer.ts +0 -755
  114. package/src/tools/documentation/uploads/documents.json +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../src/tools/evidence.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"gesture.d.ts","sourceRoot":"","sources":["../../../src/tools/gestures/gesture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AActD,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAkDrD"}
1
+ {"version":3,"file":"gesture.d.ts","sourceRoot":"","sources":["../../../src/tools/gestures/gesture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AA0BtD,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAwCrD"}
@@ -1,10 +1,12 @@
1
1
  import { errorResult, resolveDriver, textResult, toolErrorMessage, } from '../tool-response.js';
2
- import { GESTURE_ACTIONS, gestureSchema } from './schema.js';
2
+ import { GESTURE_ACTIONS, gestureSchema, } from './schema.js';
3
3
  import { handleTap, handleDoubleTap, handleLongPress } from './handlers/tap.js';
4
4
  import { handleScroll, handleSwipe } from './handlers/swipe-scroll.js';
5
5
  import { handlePinchZoom } from './handlers/pinch.js';
6
6
  import { handleScrollToElement } from './handlers/scroll-to-element.js';
7
7
  import { back } from '../../command.js';
8
+ import { withEvidence, evidenceContext, } from '../evidence.js';
9
+ import { isAiElementUUID } from './handlers/ai-element.js';
8
10
  export default function gesture(server) {
9
11
  server.addTool({
10
12
  name: 'appium_gesture',
@@ -23,31 +25,51 @@ export default function gesture(server) {
23
25
  return resolved.result;
24
26
  }
25
27
  const { driver } = resolved;
26
- switch (args.action) {
27
- case 'back':
28
- try {
29
- await back(driver);
30
- return textResult('Successfully performed back action.');
31
- }
32
- catch (err) {
33
- return errorResult(`Failed to perform back action. ${toolErrorMessage(err)}`);
34
- }
35
- case 'tap':
36
- return handleTap(driver, args);
37
- case 'double_tap':
38
- return handleDoubleTap(driver, args);
39
- case 'long_press':
40
- return handleLongPress(driver, args);
41
- case 'scroll':
42
- return handleScroll(driver, args);
43
- case 'swipe':
44
- return handleSwipe(driver, args);
45
- case 'pinch_zoom':
46
- return handlePinchZoom(driver, args);
47
- case 'scroll_to_element':
48
- return handleScrollToElement(driver, args);
49
- }
28
+ const startedAt = Date.now();
29
+ const context = await evidenceContext(args.sessionId);
30
+ const result = await dispatchGesture(driver, args);
31
+ return withEvidence(result, {
32
+ name: 'appium_gesture',
33
+ stage: gestureStage(args.action),
34
+ startedAt,
35
+ context,
36
+ ...(args.strategy && args.selector
37
+ ? { locator: { strategy: args.strategy, selector: args.selector } }
38
+ : {}),
39
+ ...(args.elementUUID && !isAiElementUUID(args.elementUUID)
40
+ ? { element: { webdriverId: args.elementUUID } }
41
+ : {}),
42
+ });
50
43
  },
51
44
  });
52
45
  }
46
+ async function dispatchGesture(driver, args) {
47
+ switch (args.action) {
48
+ case 'back':
49
+ try {
50
+ await back(driver);
51
+ return textResult('Successfully performed back action.');
52
+ }
53
+ catch (err) {
54
+ return errorResult(`Failed to perform back action. ${toolErrorMessage(err)}`);
55
+ }
56
+ case 'tap':
57
+ return handleTap(driver, args);
58
+ case 'double_tap':
59
+ return handleDoubleTap(driver, args);
60
+ case 'long_press':
61
+ return handleLongPress(driver, args);
62
+ case 'scroll':
63
+ return handleScroll(driver, args);
64
+ case 'swipe':
65
+ return handleSwipe(driver, args);
66
+ case 'pinch_zoom':
67
+ return handlePinchZoom(driver, args);
68
+ case 'scroll_to_element':
69
+ return handleScrollToElement(driver, args);
70
+ }
71
+ }
72
+ function gestureStage(action) {
73
+ return action === 'scroll_to_element' ? 'locate' : 'interact';
74
+ }
53
75
  //# sourceMappingURL=gesture.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gesture.js","sourceRoot":"","sources":["../../../src/tools/gestures/gesture.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,aAAa,EACb,UAAU,EACV,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,aAAa,EAAoB,MAAM,aAAa,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,MAAe;IAC7C,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,gBAAgB;QACtB,WAAW,EACT,oDAAoD,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YAClF,gFAAgF;YAChF,yFAAyF;YACzF,gGAAgG;QAClG,UAAU,EAAE,aAAa;QACzB,WAAW,EAAE;YACX,YAAY,EAAE,KAAK;YACnB,aAAa,EAAE,KAAK;SACrB;QACD,OAAO,EAAE,KAAK,EACZ,IAAiB,EACjB,QAA6C,EACrB,EAAE;YAC1B,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACrD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,QAAQ,CAAC,MAAM,CAAC;YACzB,CAAC;YACD,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;YAE5B,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;gBACpB,KAAK,MAAM;oBACT,IAAI,CAAC;wBACH,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;wBACnB,OAAO,UAAU,CAAC,qCAAqC,CAAC,CAAC;oBAC3D,CAAC;oBAAC,OAAO,GAAY,EAAE,CAAC;wBACtB,OAAO,WAAW,CAChB,kCAAkC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAC1D,CAAC;oBACJ,CAAC;gBACH,KAAK,KAAK;oBACR,OAAO,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACjC,KAAK,YAAY;oBACf,OAAO,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACvC,KAAK,YAAY;oBACf,OAAO,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACvC,KAAK,QAAQ;oBACX,OAAO,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACpC,KAAK,OAAO;oBACV,OAAO,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACnC,KAAK,YAAY;oBACf,OAAO,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACvC,KAAK,mBAAmB;oBACtB,OAAO,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"gesture.js","sourceRoot":"","sources":["../../../src/tools/gestures/gesture.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../../src/tools/interactions/find.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;iBAqC5B,CAAC;AAEH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CA2CzD"}
1
+ {"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../../src/tools/interactions/find.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;iBAqC5B,CAAC;AAEH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CA4EzD"}
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { resolveDriver, textResultWithPrimaryElementId, errorResult, toolErrorMessage, readWebElementId, } from '../tool-response.js';
3
+ import { withEvidence, evidenceContext } from '../evidence.js';
3
4
  export const findElementSchema = z.object({
4
5
  strategy: z
5
6
  .enum([
@@ -57,17 +58,39 @@ export default function findElement(server) {
57
58
  return resolved.result;
58
59
  }
59
60
  const { driver } = resolved;
61
+ const startedAt = Date.now();
62
+ const locator = { strategy: args.strategy, selector: args.selector };
63
+ const context = await evidenceContext(args.sessionId);
60
64
  try {
61
65
  const element = await driver.findElement(args.strategy, args.selector);
62
66
  const elementId = readWebElementId(element);
63
67
  if (!elementId) {
64
- return errorResult('Element was returned without a valid element ID');
68
+ return withEvidence(errorResult('Element was returned without a valid element ID'), {
69
+ name: 'appium_find_element',
70
+ stage: 'locate',
71
+ startedAt,
72
+ locator,
73
+ context,
74
+ });
65
75
  }
66
- return textResultWithPrimaryElementId(elementId, `Successfully found element ${args.selector} with strategy ${args.strategy}.`);
76
+ return withEvidence(textResultWithPrimaryElementId(elementId, `Successfully found element ${args.selector} with strategy ${args.strategy}.`), {
77
+ name: 'appium_find_element',
78
+ stage: 'locate',
79
+ startedAt,
80
+ locator,
81
+ element: { webdriverId: elementId },
82
+ context,
83
+ });
67
84
  }
68
85
  catch (err) {
69
- const errorMessage = toolErrorMessage(err);
70
- return errorResult(`Failed to find element. Error: ${errorMessage}`);
86
+ return withEvidence(errorResult(`Failed to find element. Error: ${toolErrorMessage(err)}`), {
87
+ name: 'appium_find_element',
88
+ stage: 'locate',
89
+ startedAt,
90
+ locator,
91
+ context,
92
+ error: err,
93
+ });
71
94
  }
72
95
  },
73
96
  });
@@ -1 +1 @@
1
- {"version":3,"file":"find.js","sourceRoot":"","sources":["../../../src/tools/interactions/find.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,aAAa,EACb,8BAA8B,EAC9B,WAAW,EACX,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,QAAQ,EAAE,CAAC;SACR,IAAI,CAAC;QACJ,kBAAkB;QAClB,IAAI;QACJ,uBAAuB;QACvB,kBAAkB;QAClB,sBAAsB;QACtB,OAAO;QACP,MAAM;QACN,YAAY;QACZ,cAAc;KACf,CAAC;SACD,QAAQ,CACP,2CAA2C;QACzC,+DAA+D;QAC/D,8DAA8D;QAC9D,gDAAgD;QAChD,wDAAwD;QACxD,oEAAoE;QACpE,6EAA6E;QAC7E,2CAA2C;QAC3C,qDAAqD;QACrD,mDAAmD;QACnD,yFAAyF;QACzF,uGAAuG,CAC1G;IACH,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,CACP,2CAA2C;QACzC,6GAA6G,CAChH;IACH,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,4DAA4D,CAAC;CAC1E,CAAC,CAAC;AAEH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,MAAe;IACjD,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE;;;;;;;;mGAQkF;QAC/F,UAAU,EAAE,iBAAiB;QAC7B,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,aAAa,EAAE,KAAK;SACrB;QACD,OAAO,EAAE,KAAK,EACZ,IAAuC,EACvC,QAA6C,EACrB,EAAE;YAC1B,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACrD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,QAAQ,CAAC,MAAM,CAAC;YACzB,CAAC;YACD,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;YAE5B,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvE,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;gBAC5C,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,OAAO,WAAW,CAAC,iDAAiD,CAAC,CAAC;gBACxE,CAAC;gBACD,OAAO,8BAA8B,CACnC,SAAS,EACT,8BAA8B,IAAI,CAAC,QAAQ,kBAAkB,IAAI,CAAC,QAAQ,GAAG,CAC9E,CAAC;YACJ,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;gBAC3C,OAAO,WAAW,CAAC,kCAAkC,YAAY,EAAE,CAAC,CAAC;YACvE,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"find.js","sourceRoot":"","sources":["../../../src/tools/interactions/find.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "appium-mcp",
3
3
  "mcpName": "io.github.appium/appium-mcp",
4
- "version": "1.82.2",
4
+ "version": "1.84.0",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -27,8 +27,7 @@
27
27
  "appium-mcp": "dist/index.js"
28
28
  },
29
29
  "scripts": {
30
- "build": "rimraf dist tsconfig.tsbuildinfo && tsc -b && chmod +x dist/index.js && npm run copy-docs",
31
- "copy-docs": "mkdir -p dist/tools/documentation/uploads dist/scripts && cp -f src/tools/documentation/uploads/documents.json dist/tools/documentation/uploads/documents.json 2>/dev/null || true && cp -f src/tools/documentation/uploads/embeddings-*.json dist/tools/documentation/uploads/ 2>/dev/null || true && cp -f src/scripts/rag-eval-dataset.json dist/scripts/rag-eval-dataset.json 2>/dev/null || true",
30
+ "build": "rimraf dist tsconfig.tsbuildinfo && tsc -b && chmod +x dist/index.js",
32
31
  "start": "node dist/index.js",
33
32
  "start:stdio": "node dist/index.js",
34
33
  "start:httpStream": "node dist/index.js --httpStream",
@@ -45,27 +44,17 @@
45
44
  "format": "prettier --write \"src/**/*.{ts,js,json}\"",
46
45
  "format:check": "prettier --check \"src/**/*.{ts,js,json}\"",
47
46
  "check": "npm run lint && npm run format:check",
48
- "index-docs": "node dist/scripts/simple-index-documentation.js",
49
- "query-docs": "node dist/scripts/simple-query-documentation.js",
50
- "eval-docs": "node dist/scripts/eval-documentation-rag.js",
51
- "generate-cache": "node dist/scripts/generate-embeddings-cache.js",
52
- "prepublishOnly": "npm run build && npm run generate-cache",
47
+ "prepublishOnly": "npm run build",
53
48
  "sync-version": "node scripts/sync-version.mjs",
54
- "version": "npm run sync-version",
55
- "zip-assets": "node scripts/zip-assets.mjs zip",
56
- "unzip-assets": "node scripts/zip-assets.mjs unzip",
57
- "preinstall": "node scripts/zip-assets.mjs unzip"
49
+ "version": "npm run sync-version"
58
50
  },
59
51
  "author": "",
60
52
  "license": "Apache-2.0",
61
53
  "description": "Intelligent MCP server providing AI assistants with powerful tools and resources for Appium mobile automation",
62
54
  "dependencies": {
55
+ "@appium/mcp-documentation": "^1.0.1",
63
56
  "@appium/support": "^7.0.2",
64
- "@langchain/classic": "^1.0.10",
65
- "@langchain/core": "^1.1.17",
66
- "@langchain/textsplitters": "^1.0.1",
67
57
  "@modelcontextprotocol/sdk": "^1.22.0",
68
- "@xenova/transformers": "^2.17.2",
69
58
  "@xmldom/xmldom": "^0.9.8",
70
59
  "appium-adb": "^15.0.0",
71
60
  "appium-ios-device": "^3.1.0",
@@ -73,18 +62,17 @@
73
62
  "appium-webdriveragent": "^12.1.1",
74
63
  "appium-xcuitest-driver": "^11.0.0",
75
64
  "applesign": "^5.0.0",
76
- "fast-xml-parser": "^5.2.3",
77
65
  "fastmcp": "^4.0.0",
78
66
  "ios-mobileprovision-finder": "^1.2.1",
79
- "langchain": "^1.1.6",
80
67
  "node-simctl": "^8.0.4",
81
- "rimraf": "^6.0.1",
68
+ "lru-cache": "^11.5.0",
82
69
  "webdriver": "^9.23.0",
83
70
  "xpath": "^0.0.34",
84
71
  "zod": "^4.3.6"
85
72
  },
86
73
  "devDependencies": {
87
74
  "@appium/eslint-config-appium-ts": "^3.0.0",
75
+ "@appium/tsconfig": "^1.1.2",
88
76
  "@jest/globals": "^30.2.0",
89
77
  "@semantic-release/changelog": "^6.0.3",
90
78
  "@semantic-release/git": "^10.0.1",
@@ -95,6 +83,7 @@
95
83
  "jest": "^30.2.0",
96
84
  "lint-staged": "^17.0.2",
97
85
  "prettier": "^3.5.3",
86
+ "rimraf": "^6.0.1",
98
87
  "semantic-release": "^25.0.2",
99
88
  "ts-node": "^10.9.2",
100
89
  "typescript": "^6.0.2"
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.82.2",
6
+ "version": "1.84.0",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "identifier": "appium-mcp",
11
- "version": "1.82.2",
11
+ "version": "1.84.0",
12
12
  "transport": {
13
13
  "type": "stdio"
14
14
  }
@@ -103,6 +103,10 @@ export function createAppiumMcpServer(
103
103
  name: serverName,
104
104
  version: serverVersion,
105
105
  instructions,
106
+ // Appium MCP will not allow client to ask the local workspace/project folders.
107
+ roots: {
108
+ enabled: false,
109
+ },
106
110
  });
107
111
 
108
112
  installPolicy(server, policy);
package/src/server.ts CHANGED
@@ -1,7 +1,12 @@
1
+ import type { AppiumMcpPlugin } from './core.js';
1
2
  import { createAppiumMcpServer } from './create-server.js';
2
- import { AppiumDocumentation } from './tools/documentation/plugin.js';
3
3
 
4
- const server = createAppiumMcpServer({
5
- plugins: [new AppiumDocumentation()],
6
- });
4
+ const plugins: AppiumMcpPlugin[] = [];
5
+
6
+ try {
7
+ const { AppiumDocumentation } = await import('@appium/mcp-documentation');
8
+ plugins.push(new AppiumDocumentation());
9
+ } catch (_err) {}
10
+
11
+ const server = createAppiumMcpServer({ plugins });
7
12
  export default server;
@@ -0,0 +1,198 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import type { ContentResult } from 'fastmcp';
3
+ import pkg from '../../package.json' with { type: 'json' };
4
+
5
+ /**
6
+ * Structured, machine-readable trace of a single tool action, so CI and agents
7
+ * can diagnose failures without parsing prose.
8
+ *
9
+ * This is an *action* record. A future run-level bundle may reference many of
10
+ * these plus heavier artifacts (screenshots, page source).
11
+ */
12
+ export interface ActionEvidenceRecord {
13
+ schemaVersion: 1;
14
+ producer: { name: 'appium-mcp'; version: string };
15
+ evidenceId: string;
16
+ status: 'success' | 'error';
17
+ /**
18
+ * Action-specific details. `stage`/`locator`/`element` are optional because
19
+ * they only apply to tools that resolve or interact with elements (find,
20
+ * gesture); tools like screenshot carry just `name`.
21
+ */
22
+ action: {
23
+ name: string;
24
+ stage?: EvidenceStage;
25
+ locator?: { strategy: string; selector: string };
26
+ element?: { webdriverId: string };
27
+ };
28
+ context?: {
29
+ platform?: string;
30
+ contextName?: string;
31
+ };
32
+ timing: { startedAt: string; finishedAt: string; durationMs: number };
33
+ error?: { code: EvidenceErrorCode; message: string };
34
+ }
35
+
36
+ export type EvidenceStage = 'locate' | 'interact' | 'capture';
37
+
38
+ export type EvidenceErrorCode =
39
+ | 'ELEMENT_NOT_FOUND'
40
+ | 'TIMEOUT'
41
+ | 'STALE_ELEMENT'
42
+ | 'CONTEXT_NOT_AVAILABLE'
43
+ | 'INVALID_SELECTOR'
44
+ | 'ACTION_FAILED';
45
+
46
+ const EVIDENCE_MIME_TYPE = 'application/vnd.appium.evidence+json';
47
+
48
+ /** Inputs a handler supplies to describe the action it performed. */
49
+ export interface EvidenceInput {
50
+ name: string;
51
+ startedAt: number;
52
+ stage?: EvidenceStage;
53
+ locator?: ActionEvidenceRecord['action']['locator'];
54
+ element?: ActionEvidenceRecord['action']['element'];
55
+ context?: ActionEvidenceRecord['context'];
56
+ error?: unknown;
57
+ }
58
+
59
+ /**
60
+ * When disabled, evidence is never built or attached and tool
61
+ * responses are byte-for-byte unchanged.
62
+ */
63
+ export function isEvidenceEnabled(): boolean {
64
+ const raw = process.env.APPIUM_MCP_EVIDENCE?.trim().toLowerCase();
65
+ return raw === '1' || raw === 'true';
66
+ }
67
+
68
+ /**
69
+ * Attach an evidence record to an existing tool result as a `resource` content
70
+ * block, leaving the original text untouched. No-op when evidence is disabled.
71
+ */
72
+ export function withEvidence(
73
+ result: ContentResult,
74
+ input: EvidenceInput
75
+ ): ContentResult {
76
+ if (!isEvidenceEnabled()) {
77
+ return result;
78
+ }
79
+ const record = buildRecord(result, input);
80
+ return {
81
+ ...result,
82
+ content: [
83
+ ...result.content,
84
+ {
85
+ type: 'resource',
86
+ resource: {
87
+ uri: `evidence://${record.evidenceId}`,
88
+ mimeType: EVIDENCE_MIME_TYPE,
89
+ text: JSON.stringify(record),
90
+ },
91
+ },
92
+ ],
93
+ };
94
+ }
95
+
96
+ /**
97
+ * Snapshot the active session's platform and current context for the evidence
98
+ * record. Returns undefined when there is no session to read, so the field is
99
+ * simply omitted. The session-store import is deferred until evidence is
100
+ * enabled so the disabled path pulls in no driver dependencies.
101
+ */
102
+ export async function evidenceContext(
103
+ sessionId?: string
104
+ ): Promise<ActionEvidenceRecord['context'] | undefined> {
105
+ if (!isEvidenceEnabled()) {
106
+ return undefined;
107
+ }
108
+ const { getSessionInfo } = await import('../session-store.js');
109
+ const info = getSessionInfo(sessionId);
110
+ if (!info) {
111
+ return undefined;
112
+ }
113
+ return {
114
+ ...(info.metadata.platform ? { platform: info.metadata.platform } : {}),
115
+ ...(info.currentContext ? { contextName: info.currentContext } : {}),
116
+ };
117
+ }
118
+
119
+ /**
120
+ * Map a raw Appium/WebDriver error to a stable, normalized code. The codes are
121
+ * also the foundation for failure-reason hypotheses. Inspects the error name
122
+ * first, then the message, falling back to ACTION_FAILED.
123
+ */
124
+ export function classifyError(err: unknown): EvidenceErrorCode {
125
+ const name = err instanceof Error ? err.name : '';
126
+ const message = (err instanceof Error ? err.message : String(err)) ?? '';
127
+ const haystack = `${name} ${message}`.toLowerCase();
128
+
129
+ if (/no such element|could not be located|element not found/.test(haystack)) {
130
+ return 'ELEMENT_NOT_FOUND';
131
+ }
132
+ if (/stale element/.test(haystack)) {
133
+ return 'STALE_ELEMENT';
134
+ }
135
+ if (/timed? ?out|timeout/.test(haystack)) {
136
+ return 'TIMEOUT';
137
+ }
138
+ if (/no such context|context.*not.*(found|available)/.test(haystack)) {
139
+ return 'CONTEXT_NOT_AVAILABLE';
140
+ }
141
+ if (/invalid selector|invalid.*(locator|xpath)/.test(haystack)) {
142
+ return 'INVALID_SELECTOR';
143
+ }
144
+ return 'ACTION_FAILED';
145
+ }
146
+
147
+ function buildRecord(
148
+ result: ContentResult,
149
+ input: EvidenceInput
150
+ ): ActionEvidenceRecord {
151
+ const finished = Date.now();
152
+ const status: ActionEvidenceRecord['status'] =
153
+ result.isError || input.error !== undefined ? 'error' : 'success';
154
+
155
+ return {
156
+ schemaVersion: 1,
157
+ producer: { name: 'appium-mcp', version: pkg.version },
158
+ evidenceId: randomUUID(),
159
+ status,
160
+ action: {
161
+ name: input.name,
162
+ ...(input.stage ? { stage: input.stage } : {}),
163
+ ...(input.locator ? { locator: input.locator } : {}),
164
+ ...(input.element ? { element: input.element } : {}),
165
+ },
166
+ ...(input.context ? { context: input.context } : {}),
167
+ timing: {
168
+ startedAt: new Date(input.startedAt).toISOString(),
169
+ finishedAt: new Date(finished).toISOString(),
170
+ durationMs: finished - input.startedAt,
171
+ },
172
+ ...(status === 'error' ? { error: buildError(input.error, result) } : {}),
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Resolve the error message, then classify from the same source so the code
178
+ * and message always agree — handlers that swallow errors only expose the
179
+ * result text, so fall back to that when no error object is passed.
180
+ */
181
+ function buildError(
182
+ err: unknown,
183
+ result: ContentResult
184
+ ): NonNullable<ActionEvidenceRecord['error']> {
185
+ const message = errorMessage(err, result);
186
+ return { code: classifyError(err ?? message), message };
187
+ }
188
+
189
+ function errorMessage(err: unknown, result: ContentResult): string {
190
+ if (err instanceof Error) {
191
+ return err.message;
192
+ }
193
+ if (err !== undefined) {
194
+ return String(err);
195
+ }
196
+ const text = result.content.find((c) => c.type === 'text');
197
+ return text && 'text' in text ? text.text : 'Unknown error';
198
+ }
@@ -1,16 +1,28 @@
1
1
  import type { ContentResult, FastMCP } from 'fastmcp';
2
+ import type { DriverInstance } from '../../session-store.js';
2
3
  import {
3
4
  errorResult,
4
5
  resolveDriver,
5
6
  textResult,
6
7
  toolErrorMessage,
7
8
  } from '../tool-response.js';
8
- import { GESTURE_ACTIONS, gestureSchema, type GestureArgs } from './schema.js';
9
+ import {
10
+ GESTURE_ACTIONS,
11
+ gestureSchema,
12
+ type GestureAction,
13
+ type GestureArgs,
14
+ } from './schema.js';
9
15
  import { handleTap, handleDoubleTap, handleLongPress } from './handlers/tap.js';
10
16
  import { handleScroll, handleSwipe } from './handlers/swipe-scroll.js';
11
17
  import { handlePinchZoom } from './handlers/pinch.js';
12
18
  import { handleScrollToElement } from './handlers/scroll-to-element.js';
13
19
  import { back } from '../../command.js';
20
+ import {
21
+ withEvidence,
22
+ evidenceContext,
23
+ type EvidenceStage,
24
+ } from '../evidence.js';
25
+ import { isAiElementUUID } from './handlers/ai-element.js';
14
26
 
15
27
  export default function gesture(server: FastMCP): void {
16
28
  server.addTool({
@@ -35,31 +47,56 @@ export default function gesture(server: FastMCP): void {
35
47
  }
36
48
  const { driver } = resolved;
37
49
 
38
- switch (args.action) {
39
- case 'back':
40
- try {
41
- await back(driver);
42
- return textResult('Successfully performed back action.');
43
- } catch (err: unknown) {
44
- return errorResult(
45
- `Failed to perform back action. ${toolErrorMessage(err)}`
46
- );
47
- }
48
- case 'tap':
49
- return handleTap(driver, args);
50
- case 'double_tap':
51
- return handleDoubleTap(driver, args);
52
- case 'long_press':
53
- return handleLongPress(driver, args);
54
- case 'scroll':
55
- return handleScroll(driver, args);
56
- case 'swipe':
57
- return handleSwipe(driver, args);
58
- case 'pinch_zoom':
59
- return handlePinchZoom(driver, args);
60
- case 'scroll_to_element':
61
- return handleScrollToElement(driver, args);
62
- }
50
+ const startedAt = Date.now();
51
+ const context = await evidenceContext(args.sessionId);
52
+ const result = await dispatchGesture(driver, args);
53
+ return withEvidence(result, {
54
+ name: 'appium_gesture',
55
+ stage: gestureStage(args.action),
56
+ startedAt,
57
+ context,
58
+ ...(args.strategy && args.selector
59
+ ? { locator: { strategy: args.strategy, selector: args.selector } }
60
+ : {}),
61
+ ...(args.elementUUID && !isAiElementUUID(args.elementUUID)
62
+ ? { element: { webdriverId: args.elementUUID } }
63
+ : {}),
64
+ });
63
65
  },
64
66
  });
65
67
  }
68
+
69
+ async function dispatchGesture(
70
+ driver: DriverInstance,
71
+ args: GestureArgs
72
+ ): Promise<ContentResult> {
73
+ switch (args.action) {
74
+ case 'back':
75
+ try {
76
+ await back(driver);
77
+ return textResult('Successfully performed back action.');
78
+ } catch (err: unknown) {
79
+ return errorResult(
80
+ `Failed to perform back action. ${toolErrorMessage(err)}`
81
+ );
82
+ }
83
+ case 'tap':
84
+ return handleTap(driver, args);
85
+ case 'double_tap':
86
+ return handleDoubleTap(driver, args);
87
+ case 'long_press':
88
+ return handleLongPress(driver, args);
89
+ case 'scroll':
90
+ return handleScroll(driver, args);
91
+ case 'swipe':
92
+ return handleSwipe(driver, args);
93
+ case 'pinch_zoom':
94
+ return handlePinchZoom(driver, args);
95
+ case 'scroll_to_element':
96
+ return handleScrollToElement(driver, args);
97
+ }
98
+ }
99
+
100
+ function gestureStage(action: GestureAction): EvidenceStage {
101
+ return action === 'scroll_to_element' ? 'locate' : 'interact';
102
+ }