mcp-maestro-mobile-ai 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -16,6 +16,104 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
16
 
17
17
  ---
18
18
 
19
+ ## [1.6.0] - 2025-01-07
20
+
21
+ ### Added
22
+
23
+ - **YAML Caching System**: Intelligent caching for faster recurring test execution
24
+
25
+ - `save_to_cache` - Save successful test YAML for future reuse
26
+ - `lookup_cache` - Check if a cached YAML exists for a prompt
27
+ - `list_cache` - List all cached tests with usage statistics
28
+ - `clear_cache` - Clear all cached YAMLs
29
+ - `delete_from_cache` - Delete specific cached test
30
+ - `get_cache_stats` - Get cache statistics (total cached, execution counts)
31
+ - `run_test_with_cache` - Run test with automatic cache lookup
32
+
33
+ - **Prompt-Based Hashing**: Unique identification of test prompts
34
+ - SHA-256 based hashing with normalization
35
+ - Handles minor formatting differences (whitespace, quotes)
36
+ - AppId included in hash for app-specific caching
37
+
38
+ - **Hidden Cache Storage**: Internal cache location (`~/.maestro-mcp/cache/`)
39
+ - Index file for fast lookup
40
+ - YAML files stored with hash-based names
41
+ - Not visible to end users
42
+
43
+ - **Usage Statistics**: Track cache effectiveness
44
+ - Execution count per cached test
45
+ - Last used timestamp
46
+ - Most used tests identification
47
+
48
+ - **Auto-Cache on Success**: After successful test execution
49
+ - Automatically saves YAML to cache (no user prompt needed)
50
+ - Failed tests are NOT cached (fix and re-run to cache)
51
+ - Automatic reuse when same prompt is run again
52
+
53
+ ### Changed
54
+
55
+ - **Server Version**: Updated to v1.6.0
56
+ - **runTest function**: Now includes cache prompt for successful tests
57
+ - **runTestSuiteWithReport**: Offers bulk caching for successful tests
58
+
59
+ ### Benefits
60
+
61
+ | Feature | Benefit |
62
+ |---------|---------|
63
+ | Faster Execution | Skip YAML generation for recurring tests |
64
+ | Reduced AI Calls | Cached YAML reused automatically |
65
+ | Clean Separation | Cache hidden from user-facing directories |
66
+ | Smart Invalidation | New YAML generated if prompt changes |
67
+
68
+ ---
69
+
70
+ ## [1.5.0] - 2025-01-07
71
+
72
+ ### Added
73
+
74
+ - **Prompt Analysis System (Action-Element-Verification Model)**: Intelligent prompt parsing for reliable YAML generation
75
+
76
+ - `validate_prompt` - PRIMARY tool for converting natural language to Maestro YAML
77
+ - `analyze_prompt` - Analyze prompts without generating YAML (debugging/inspection)
78
+ - Extracts: Actions, Elements, Values, Verifications, Sequence
79
+
80
+ - **Tiered Clarification System**: Smart handling of incomplete prompts
81
+
82
+ - **COMPLETE**: All required info present → generates clean YAML
83
+ - **GENERATABLE**: Missing some info → asks clarification OR generates with warnings
84
+ - **NEEDS_CLARIFICATION**: Missing important info → asks specific questions
85
+ - **INSUFFICIENT**: Missing critical info (app ID) → requests minimum required info
86
+
87
+ - **Force Generate with Warnings**: Option to generate YAML with assumptions
88
+ - Automatically adds warning comments for assumed values
89
+ - Lists all assumptions made during generation
90
+ - Placeholder values clearly marked for user to replace
91
+
92
+ - **New Utilities**:
93
+ - `src/mcp-server/utils/promptAnalyzer.js` - Action-Element-Verification parser
94
+ - `src/mcp-server/utils/yamlGenerator.js` - YAML generation with warnings support
95
+ - `validateAndGenerate()` - Orchestrator function in contextTools.js
96
+
97
+ - **Intelligent Clarification Questions**: Context-aware questions based on what's missing
98
+ - Critical questions (blocking): App ID
99
+ - Important questions: Field labels, button text
100
+ - Recommended questions: Verification elements, dropdown options
101
+
102
+ ### Changed
103
+
104
+ - **Server Version**: Updated to v1.5.0
105
+ - **Description**: Updated to highlight prompt analysis and tiered clarification
106
+ - **Keywords**: Added `prompt-analysis`, `natural-language`, `yaml-generator`
107
+
108
+ ### Developer Experience
109
+
110
+ - Generic, framework-agnostic approach works for ANY mobile app
111
+ - No hard-coded app-specific values
112
+ - Interaction patterns automatically applied
113
+ - Comprehensive test script for verification
114
+
115
+ ---
116
+
19
117
  ## [1.4.0] - 2025-01-07
20
118
 
21
119
  ### Security
@@ -234,7 +332,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
234
332
 
235
333
  ---
236
334
 
237
- [Unreleased]: https://github.com/krunal-mahera/mcp-maestro-mobile-ai/compare/v1.4.0...HEAD
335
+ [Unreleased]: https://github.com/krunal-mahera/mcp-maestro-mobile-ai/compare/v1.6.0...HEAD
336
+ [1.6.0]: https://github.com/krunal-mahera/mcp-maestro-mobile-ai/releases/tag/v1.6.0
337
+ [1.5.0]: https://github.com/krunal-mahera/mcp-maestro-mobile-ai/releases/tag/v1.5.0
238
338
  [1.4.0]: https://github.com/krunal-mahera/mcp-maestro-mobile-ai/releases/tag/v1.4.0
239
339
  [1.3.1]: https://github.com/krunal-mahera/mcp-maestro-mobile-ai/releases/tag/v1.3.1
240
340
  [1.2.0]: https://github.com/krunal-mahera/mcp-maestro-mobile-ai/releases/tag/v1.2.0
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "mcp-maestro-mobile-ai",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "private": false,
5
- "description": "MCP Server for AI-Assisted Mobile Automation using Maestro - Run mobile tests with natural language prompts. Features enterprise-grade security with Safe Mode and input validation.",
5
+ "description": "MCP Server for AI-Assisted Mobile Automation using Maestro - Run mobile tests with natural language prompts. Features prompt analysis, tiered clarification, and enterprise-grade security.",
6
6
  "main": "src/mcp-server/index.js",
7
7
  "type": "module",
8
8
  "bin": {
@@ -54,7 +54,10 @@
54
54
  "ai",
55
55
  "security",
56
56
  "validation",
57
- "zod"
57
+ "zod",
58
+ "prompt-analysis",
59
+ "natural-language",
60
+ "yaml-generator"
58
61
  ],
59
62
  "author": "Krunal Mahera <krunal.mahera@gmail.com>",
60
63
  "license": "MIT",
@@ -32,6 +32,14 @@ import {
32
32
  generateTestReport,
33
33
  listTestReports,
34
34
  runTestSuiteWithReport,
35
+ // Cache management
36
+ runTestWithCache,
37
+ saveTestToCache,
38
+ listCachedTests,
39
+ clearTestCache,
40
+ deleteCachedTest,
41
+ getTestCacheStats,
42
+ lookupCachedTest,
35
43
  } from "./tools/runTools.js";
36
44
  import {
37
45
  getAppConfig,
@@ -58,6 +66,13 @@ import {
58
66
  validateYamlBeforeRun,
59
67
  getTestPattern,
60
68
  getScreenAnalysis,
69
+ // Known Issues Tools
70
+ getKnownIssues,
71
+ getPlatformRules,
72
+ getGenerationRules,
73
+ // Prompt Analysis & Generation
74
+ validateAndGenerate,
75
+ analyzeTestPrompt,
61
76
  } from "./tools/contextTools.js";
62
77
  import { logger } from "./utils/logger.js";
63
78
  import { validatePrerequisites } from "./utils/prerequisites.js";
@@ -76,8 +91,8 @@ const __filename = fileURLToPath(import.meta.url);
76
91
  const __dirname = dirname(__filename);
77
92
  config({ path: join(__dirname, "../../.env") });
78
93
 
79
- // Server version - updated for security features
80
- const SERVER_VERSION = "1.4.0";
94
+ // Server version - updated for YAML caching features
95
+ const SERVER_VERSION = "1.6.0";
81
96
 
82
97
  // Create MCP Server
83
98
  const server = new Server(
@@ -633,14 +648,14 @@ appId: com.example.app
633
648
  {
634
649
  name: "get_test_pattern",
635
650
  description:
636
- "Get a standard test pattern template. Available: login, form, search, navigation, list, settings, logout. Use these as starting points.",
651
+ "Get a standard test pattern template. Available: login, form, search, navigation, list, settings, logout, dropdown, flutter_login_with_dropdown, flutter_multi_dropdown. Use these as starting points.",
637
652
  inputSchema: {
638
653
  type: "object",
639
654
  properties: {
640
655
  patternName: {
641
656
  type: "string",
642
657
  description:
643
- "Pattern name: login, form, search, navigation, list, settings, or logout",
658
+ "Pattern name: login, form, search, navigation, list, settings, logout, dropdown, flutter_login_with_dropdown, or flutter_multi_dropdown",
644
659
  enum: [
645
660
  "login",
646
661
  "form",
@@ -649,6 +664,9 @@ appId: com.example.app
649
664
  "list",
650
665
  "settings",
651
666
  "logout",
667
+ "dropdown",
668
+ "flutter_login_with_dropdown",
669
+ "flutter_multi_dropdown",
652
670
  ],
653
671
  },
654
672
  },
@@ -664,6 +682,247 @@ appId: com.example.app
664
682
  properties: {},
665
683
  },
666
684
  },
685
+
686
+ // === Interaction Patterns & Generation Rules ===
687
+ {
688
+ name: "get_known_issues",
689
+ description:
690
+ "Get generic interaction patterns for reliable mobile test automation. These patterns are framework-agnostic and improve test reliability across all mobile apps. Optionally filter by category.",
691
+ inputSchema: {
692
+ type: "object",
693
+ properties: {
694
+ category: {
695
+ type: "string",
696
+ description:
697
+ "Filter by category: keyboard_handling, element_interaction, timing_synchronization, input_handling, dropdown_picker, navigation, scroll_visibility, fallback_strategies",
698
+ enum: [
699
+ "keyboard_handling",
700
+ "element_interaction",
701
+ "timing_synchronization",
702
+ "input_handling",
703
+ "dropdown_picker",
704
+ "navigation",
705
+ "scroll_visibility",
706
+ "fallback_strategies",
707
+ ],
708
+ },
709
+ },
710
+ },
711
+ },
712
+ {
713
+ name: "get_platform_rules",
714
+ description:
715
+ "Get interaction patterns for a specific category. Use this to understand how to handle specific interaction types (keyboard, dropdowns, timing, etc.).",
716
+ inputSchema: {
717
+ type: "object",
718
+ properties: {
719
+ category: {
720
+ type: "string",
721
+ description:
722
+ "Pattern category: keyboard_handling, element_interaction, timing_synchronization, input_handling, dropdown_picker, navigation, scroll_visibility, fallback_strategies",
723
+ enum: [
724
+ "keyboard_handling",
725
+ "element_interaction",
726
+ "timing_synchronization",
727
+ "input_handling",
728
+ "dropdown_picker",
729
+ "navigation",
730
+ "scroll_visibility",
731
+ "fallback_strategies",
732
+ ],
733
+ },
734
+ },
735
+ required: ["category"],
736
+ },
737
+ },
738
+ {
739
+ name: "get_generation_rules",
740
+ description:
741
+ "Get all YAML generation rules and best practices. These are framework-agnostic rules that improve test reliability across any mobile application.",
742
+ inputSchema: {
743
+ type: "object",
744
+ properties: {},
745
+ },
746
+ },
747
+
748
+ // === Prompt Analysis & YAML Generation ===
749
+ {
750
+ name: "validate_prompt",
751
+ description: `Analyze a user's test description using the Action-Element-Verification model and generate Maestro YAML.
752
+
753
+ This tool:
754
+ 1. Extracts ACTIONS (tap, input, scroll, select, verify...)
755
+ 2. Identifies ELEMENTS (button, field, dropdown, list, chart...)
756
+ 3. Finds VALUES (credentials, search terms, selections...)
757
+ 4. Detects VERIFICATIONS (visible, contains, success...)
758
+ 5. Assesses completeness and either:
759
+ - Generates clean YAML (if complete)
760
+ - Asks clarifying questions (if incomplete)
761
+ - Generates YAML with warnings (if forceGenerate=true)
762
+
763
+ Use this as the PRIMARY tool for converting natural language test descriptions to Maestro YAML.`,
764
+ inputSchema: {
765
+ type: "object",
766
+ properties: {
767
+ userPrompt: {
768
+ type: "string",
769
+ description:
770
+ "Natural language test description. Example: 'Test login with username abc and password 1234 on com.example.app'",
771
+ },
772
+ appId: {
773
+ type: "string",
774
+ description:
775
+ "Optional app package ID. Provide if not included in the prompt.",
776
+ },
777
+ forceGenerate: {
778
+ type: "boolean",
779
+ description:
780
+ "If true, generate YAML with assumptions even if information is incomplete. Default: false",
781
+ },
782
+ },
783
+ required: ["userPrompt"],
784
+ },
785
+ },
786
+ {
787
+ name: "analyze_prompt",
788
+ description:
789
+ "Analyze a test prompt WITHOUT generating YAML. Returns detailed breakdown of detected actions, elements, values, and verifications. Use this to understand what the system can extract from a prompt.",
790
+ inputSchema: {
791
+ type: "object",
792
+ properties: {
793
+ userPrompt: {
794
+ type: "string",
795
+ description: "The test description to analyze",
796
+ },
797
+ appId: {
798
+ type: "string",
799
+ description: "Optional app package ID for context",
800
+ },
801
+ },
802
+ required: ["userPrompt"],
803
+ },
804
+ },
805
+
806
+ // === YAML Cache Tools ===
807
+ {
808
+ name: "save_to_cache",
809
+ description:
810
+ "Save a successful test's YAML to cache for faster future execution. After a test passes, call this to store the YAML. When the same prompt is used again, the cached YAML will be reused automatically.",
811
+ inputSchema: {
812
+ type: "object",
813
+ properties: {
814
+ prompt: {
815
+ type: "string",
816
+ description: "The original test prompt/description",
817
+ },
818
+ yaml: {
819
+ type: "string",
820
+ description: "The YAML content to cache",
821
+ },
822
+ testName: {
823
+ type: "string",
824
+ description: "Name of the test",
825
+ },
826
+ appId: {
827
+ type: "string",
828
+ description: "Optional app package ID",
829
+ },
830
+ },
831
+ required: ["prompt", "yaml", "testName"],
832
+ },
833
+ },
834
+ {
835
+ name: "lookup_cache",
836
+ description:
837
+ "Check if a YAML is cached for a given prompt. Returns the cached YAML if found, or indicates no cache exists.",
838
+ inputSchema: {
839
+ type: "object",
840
+ properties: {
841
+ prompt: {
842
+ type: "string",
843
+ description: "The test prompt to look up",
844
+ },
845
+ appId: {
846
+ type: "string",
847
+ description: "Optional app package ID",
848
+ },
849
+ },
850
+ required: ["prompt"],
851
+ },
852
+ },
853
+ {
854
+ name: "list_cache",
855
+ description:
856
+ "List all cached test YAMLs. Shows test names, prompts, and usage statistics.",
857
+ inputSchema: {
858
+ type: "object",
859
+ properties: {},
860
+ },
861
+ },
862
+ {
863
+ name: "clear_cache",
864
+ description:
865
+ "Clear all cached test YAMLs. After clearing, all tests will generate fresh YAML.",
866
+ inputSchema: {
867
+ type: "object",
868
+ properties: {},
869
+ },
870
+ },
871
+ {
872
+ name: "delete_from_cache",
873
+ description:
874
+ "Delete a specific cached test by its hash. Use list_cache to find the hash.",
875
+ inputSchema: {
876
+ type: "object",
877
+ properties: {
878
+ hash: {
879
+ type: "string",
880
+ description: "The cache hash to delete (from list_cache output)",
881
+ },
882
+ },
883
+ required: ["hash"],
884
+ },
885
+ },
886
+ {
887
+ name: "get_cache_stats",
888
+ description:
889
+ "Get cache statistics including total cached tests, execution counts, and most used tests.",
890
+ inputSchema: {
891
+ type: "object",
892
+ properties: {},
893
+ },
894
+ },
895
+ {
896
+ name: "run_test_with_cache",
897
+ description:
898
+ "Run a test with automatic cache lookup. If a cached YAML exists for the prompt, it will be used. Otherwise, the provided YAML will be executed.",
899
+ inputSchema: {
900
+ type: "object",
901
+ properties: {
902
+ prompt: {
903
+ type: "string",
904
+ description: "The original test prompt - used for cache lookup",
905
+ },
906
+ yaml: {
907
+ type: "string",
908
+ description: "The YAML to use if not cached",
909
+ },
910
+ name: {
911
+ type: "string",
912
+ description: "Test name",
913
+ },
914
+ appId: {
915
+ type: "string",
916
+ description: "Optional app package ID",
917
+ },
918
+ retries: {
919
+ type: "number",
920
+ description: "Number of retries if test fails",
921
+ },
922
+ },
923
+ required: ["prompt", "yaml", "name"],
924
+ },
925
+ },
667
926
  ];
668
927
 
669
928
  // ============================================
@@ -917,6 +1176,82 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
917
1176
  result = await getScreenAnalysis();
918
1177
  break;
919
1178
 
1179
+ // Known Issues & Platform Rules
1180
+ case "get_known_issues":
1181
+ result = await getKnownIssues(
1182
+ validatedArgs.platform,
1183
+ validatedArgs.category
1184
+ );
1185
+ break;
1186
+
1187
+ case "get_platform_rules":
1188
+ result = await getPlatformRules(validatedArgs.category);
1189
+ break;
1190
+
1191
+ case "get_generation_rules":
1192
+ result = await getGenerationRules();
1193
+ break;
1194
+
1195
+ // Prompt Analysis & YAML Generation
1196
+ case "validate_prompt":
1197
+ result = await validateAndGenerate(validatedArgs.userPrompt, {
1198
+ appId: validatedArgs.appId,
1199
+ forceGenerate: validatedArgs.forceGenerate,
1200
+ });
1201
+ break;
1202
+
1203
+ case "analyze_prompt":
1204
+ result = await analyzeTestPrompt(
1205
+ validatedArgs.userPrompt,
1206
+ validatedArgs.appId
1207
+ );
1208
+ break;
1209
+
1210
+ // YAML Cache tools
1211
+ case "save_to_cache":
1212
+ result = await saveTestToCache(
1213
+ validatedArgs.prompt,
1214
+ validatedArgs.yaml,
1215
+ validatedArgs.testName,
1216
+ validatedArgs.appId
1217
+ );
1218
+ break;
1219
+
1220
+ case "lookup_cache":
1221
+ result = await lookupCachedTest(
1222
+ validatedArgs.prompt,
1223
+ validatedArgs.appId
1224
+ );
1225
+ break;
1226
+
1227
+ case "list_cache":
1228
+ result = await listCachedTests();
1229
+ break;
1230
+
1231
+ case "clear_cache":
1232
+ result = await clearTestCache();
1233
+ break;
1234
+
1235
+ case "delete_from_cache":
1236
+ result = await deleteCachedTest(validatedArgs.hash);
1237
+ break;
1238
+
1239
+ case "get_cache_stats":
1240
+ result = await getTestCacheStats();
1241
+ break;
1242
+
1243
+ case "run_test_with_cache":
1244
+ result = await runTestWithCache(
1245
+ validatedArgs.prompt,
1246
+ validatedArgs.yaml,
1247
+ validatedArgs.name,
1248
+ {
1249
+ appId: validatedArgs.appId,
1250
+ retries: validatedArgs.retries,
1251
+ }
1252
+ );
1253
+ break;
1254
+
920
1255
  default:
921
1256
  throw new Error(`Unknown tool: ${name}`);
922
1257
  }