@provartesting/provardx-cli 1.5.0-dev.2 → 1.5.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 (147) hide show
  1. package/README.md +163 -12
  2. package/bin/mcp-start.js +74 -0
  3. package/lib/commands/provar/auth/clear.d.ts +7 -0
  4. package/lib/commands/provar/auth/clear.js +36 -0
  5. package/lib/commands/provar/auth/clear.js.map +1 -0
  6. package/lib/commands/provar/auth/login.d.ts +10 -0
  7. package/lib/commands/provar/auth/login.js +90 -0
  8. package/lib/commands/provar/auth/login.js.map +1 -0
  9. package/lib/commands/provar/auth/rotate.d.ts +7 -0
  10. package/lib/commands/provar/auth/rotate.js +42 -0
  11. package/lib/commands/provar/auth/rotate.js.map +1 -0
  12. package/lib/commands/provar/auth/status.d.ts +7 -0
  13. package/lib/commands/provar/auth/status.js +107 -0
  14. package/lib/commands/provar/auth/status.js.map +1 -0
  15. package/lib/commands/provar/mcp/start.d.ts +2 -0
  16. package/lib/commands/provar/mcp/start.js +14 -1
  17. package/lib/commands/provar/mcp/start.js.map +1 -1
  18. package/lib/mcp/docs/NITROX_CATALOG_SOURCE.json +6 -0
  19. package/lib/mcp/docs/NITROX_COMPONENT_CATALOG.md +2001 -0
  20. package/lib/mcp/docs/PROVAR_TEST_STEP_REFERENCE.md +1430 -0
  21. package/lib/mcp/docs/PROVAR_TOOL_GUIDE.md +187 -0
  22. package/lib/mcp/licensing/algasClient.js +14 -5
  23. package/lib/mcp/licensing/algasClient.js.map +1 -1
  24. package/lib/mcp/licensing/ideDetection.d.ts +0 -12
  25. package/lib/mcp/licensing/ideDetection.js +1 -73
  26. package/lib/mcp/licensing/ideDetection.js.map +1 -1
  27. package/lib/mcp/licensing/licenseCache.js +7 -1
  28. package/lib/mcp/licensing/licenseCache.js.map +1 -1
  29. package/lib/mcp/licensing/licenseValidator.d.ts +3 -3
  30. package/lib/mcp/licensing/licenseValidator.js +11 -4
  31. package/lib/mcp/licensing/licenseValidator.js.map +1 -1
  32. package/lib/mcp/prompts/guidePrompts.d.ts +4 -0
  33. package/lib/mcp/prompts/guidePrompts.js +334 -0
  34. package/lib/mcp/prompts/guidePrompts.js.map +1 -0
  35. package/lib/mcp/prompts/index.d.ts +2 -0
  36. package/lib/mcp/prompts/index.js +23 -0
  37. package/lib/mcp/prompts/index.js.map +1 -0
  38. package/lib/mcp/prompts/loopPrompts.d.ts +6 -0
  39. package/lib/mcp/prompts/loopPrompts.js +435 -0
  40. package/lib/mcp/prompts/loopPrompts.js.map +1 -0
  41. package/lib/mcp/prompts/migrationPrompts.d.ts +4 -0
  42. package/lib/mcp/prompts/migrationPrompts.js +207 -0
  43. package/lib/mcp/prompts/migrationPrompts.js.map +1 -0
  44. package/lib/mcp/rules/provar_best_practices_rules.json +256 -544
  45. package/lib/mcp/security/pathPolicy.d.ts +5 -0
  46. package/lib/mcp/security/pathPolicy.js +58 -3
  47. package/lib/mcp/security/pathPolicy.js.map +1 -1
  48. package/lib/mcp/server.d.ts +18 -0
  49. package/lib/mcp/server.js +232 -19
  50. package/lib/mcp/server.js.map +1 -1
  51. package/lib/mcp/tools/antTools.d.ts +15 -0
  52. package/lib/mcp/tools/antTools.js +369 -170
  53. package/lib/mcp/tools/antTools.js.map +1 -1
  54. package/lib/mcp/tools/automationTools.d.ts +18 -8
  55. package/lib/mcp/tools/automationTools.js +333 -176
  56. package/lib/mcp/tools/automationTools.js.map +1 -1
  57. package/lib/mcp/tools/bestPracticesEngine.js +161 -23
  58. package/lib/mcp/tools/bestPracticesEngine.js.map +1 -1
  59. package/lib/mcp/tools/connectionTools.d.ts +4 -0
  60. package/lib/mcp/tools/connectionTools.js +242 -0
  61. package/lib/mcp/tools/connectionTools.js.map +1 -0
  62. package/lib/mcp/tools/defectTools.d.ts +1 -1
  63. package/lib/mcp/tools/defectTools.js +61 -50
  64. package/lib/mcp/tools/defectTools.js.map +1 -1
  65. package/lib/mcp/tools/descHelper.d.ts +5 -0
  66. package/lib/mcp/tools/descHelper.js +14 -0
  67. package/lib/mcp/tools/descHelper.js.map +1 -0
  68. package/lib/mcp/tools/hierarchyValidate.d.ts +1 -1
  69. package/lib/mcp/tools/hierarchyValidate.js +127 -42
  70. package/lib/mcp/tools/hierarchyValidate.js.map +1 -1
  71. package/lib/mcp/tools/nitroXTools.d.ts +23 -0
  72. package/lib/mcp/tools/nitroXTools.js +863 -0
  73. package/lib/mcp/tools/nitroXTools.js.map +1 -0
  74. package/lib/mcp/tools/pageObjectGenerate.js +150 -57
  75. package/lib/mcp/tools/pageObjectGenerate.js.map +1 -1
  76. package/lib/mcp/tools/pageObjectValidate.js +143 -46
  77. package/lib/mcp/tools/pageObjectValidate.js.map +1 -1
  78. package/lib/mcp/tools/projectInspect.js +79 -32
  79. package/lib/mcp/tools/projectInspect.js.map +1 -1
  80. package/lib/mcp/tools/projectValidateFromPath.js +185 -58
  81. package/lib/mcp/tools/projectValidateFromPath.js.map +1 -1
  82. package/lib/mcp/tools/propertiesTools.d.ts +2 -0
  83. package/lib/mcp/tools/propertiesTools.js +358 -78
  84. package/lib/mcp/tools/propertiesTools.js.map +1 -1
  85. package/lib/mcp/tools/qualityHubApiTools.d.ts +3 -0
  86. package/lib/mcp/tools/qualityHubApiTools.js +139 -0
  87. package/lib/mcp/tools/qualityHubApiTools.js.map +1 -0
  88. package/lib/mcp/tools/qualityHubTools.js +292 -72
  89. package/lib/mcp/tools/qualityHubTools.js.map +1 -1
  90. package/lib/mcp/tools/rcaTools.d.ts +3 -2
  91. package/lib/mcp/tools/rcaTools.js +194 -56
  92. package/lib/mcp/tools/rcaTools.js.map +1 -1
  93. package/lib/mcp/tools/sfSpawn.d.ts +25 -3
  94. package/lib/mcp/tools/sfSpawn.js +154 -6
  95. package/lib/mcp/tools/sfSpawn.js.map +1 -1
  96. package/lib/mcp/tools/testCaseGenerate.js +285 -78
  97. package/lib/mcp/tools/testCaseGenerate.js.map +1 -1
  98. package/lib/mcp/tools/testCaseStepTools.d.ts +4 -0
  99. package/lib/mcp/tools/testCaseStepTools.js +244 -0
  100. package/lib/mcp/tools/testCaseStepTools.js.map +1 -0
  101. package/lib/mcp/tools/testCaseValidate.d.ts +11 -0
  102. package/lib/mcp/tools/testCaseValidate.js +381 -46
  103. package/lib/mcp/tools/testCaseValidate.js.map +1 -1
  104. package/lib/mcp/tools/testPlanTools.d.ts +1 -0
  105. package/lib/mcp/tools/testPlanTools.js +316 -59
  106. package/lib/mcp/tools/testPlanTools.js.map +1 -1
  107. package/lib/mcp/tools/testPlanValidate.js +114 -23
  108. package/lib/mcp/tools/testPlanValidate.js.map +1 -1
  109. package/lib/mcp/tools/testSuiteValidate.js +130 -15
  110. package/lib/mcp/tools/testSuiteValidate.js.map +1 -1
  111. package/lib/mcp/update/updateChecker.d.ts +14 -0
  112. package/lib/mcp/update/updateChecker.js +228 -0
  113. package/lib/mcp/update/updateChecker.js.map +1 -0
  114. package/lib/mcp/utils/detailLevel.d.ts +9 -0
  115. package/lib/mcp/utils/detailLevel.js +20 -0
  116. package/lib/mcp/utils/detailLevel.js.map +1 -0
  117. package/lib/mcp/utils/fieldMask.d.ts +17 -0
  118. package/lib/mcp/utils/fieldMask.js +75 -0
  119. package/lib/mcp/utils/fieldMask.js.map +1 -0
  120. package/lib/mcp/utils/tokenMeta.d.ts +40 -0
  121. package/lib/mcp/utils/tokenMeta.js +90 -0
  122. package/lib/mcp/utils/tokenMeta.js.map +1 -0
  123. package/lib/mcp/utils/validationDiff.d.ts +57 -0
  124. package/lib/mcp/utils/validationDiff.js +191 -0
  125. package/lib/mcp/utils/validationDiff.js.map +1 -0
  126. package/lib/mcp/utils/validationScore.d.ts +15 -0
  127. package/lib/mcp/utils/validationScore.js +31 -0
  128. package/lib/mcp/utils/validationScore.js.map +1 -0
  129. package/lib/services/auth/credentials.d.ts +21 -0
  130. package/lib/services/auth/credentials.js +75 -0
  131. package/lib/services/auth/credentials.js.map +1 -0
  132. package/lib/services/auth/loginFlow.d.ts +68 -0
  133. package/lib/services/auth/loginFlow.js +216 -0
  134. package/lib/services/auth/loginFlow.js.map +1 -0
  135. package/lib/services/projectValidation.d.ts +5 -2
  136. package/lib/services/projectValidation.js +83 -31
  137. package/lib/services/projectValidation.js.map +1 -1
  138. package/lib/services/qualityHub/client.d.ts +161 -0
  139. package/lib/services/qualityHub/client.js +226 -0
  140. package/lib/services/qualityHub/client.js.map +1 -0
  141. package/messages/sf.provar.auth.clear.md +16 -0
  142. package/messages/sf.provar.auth.login.md +31 -0
  143. package/messages/sf.provar.auth.rotate.md +23 -0
  144. package/messages/sf.provar.auth.status.md +16 -0
  145. package/messages/sf.provar.mcp.start.md +83 -48
  146. package/oclif.manifest.json +325 -28
  147. package/package.json +35 -12
@@ -10,5 +10,10 @@ export declare class PathPolicyError extends Error {
10
10
  * - PATH_NOT_ALLOWED — resolved path is outside all allowed roots
11
11
  *
12
12
  * When allowedPaths is empty, all paths are permitted (unrestricted mode).
13
+ *
14
+ * Symlinks are resolved via fs.realpathSync so that a symlink inside an allowed
15
+ * directory pointing to a location outside it cannot bypass containment.
16
+ * If the path does not yet exist (e.g. an output file to be created), the parent
17
+ * directory is resolved instead and the basename re-attached.
13
18
  */
14
19
  export declare function assertPathAllowed(filePath: string, allowedPaths: string[]): void;
@@ -4,6 +4,7 @@
4
4
  * Licensed under the BSD 3-Clause license.
5
5
  * For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
+ import fs from 'node:fs';
7
8
  import path from 'node:path';
8
9
  export class PathPolicyError extends Error {
9
10
  code;
@@ -21,6 +22,11 @@ export class PathPolicyError extends Error {
21
22
  * - PATH_NOT_ALLOWED — resolved path is outside all allowed roots
22
23
  *
23
24
  * When allowedPaths is empty, all paths are permitted (unrestricted mode).
25
+ *
26
+ * Symlinks are resolved via fs.realpathSync so that a symlink inside an allowed
27
+ * directory pointing to a location outside it cannot bypass containment.
28
+ * If the path does not yet exist (e.g. an output file to be created), the parent
29
+ * directory is resolved instead and the basename re-attached.
24
30
  */
25
31
  export function assertPathAllowed(filePath, allowedPaths) {
26
32
  // Check the original path for `..` segments before any normalization resolves them away
@@ -28,10 +34,59 @@ export function assertPathAllowed(filePath, allowedPaths) {
28
34
  if (rawSegments.some((s) => s === '..')) {
29
35
  throw new PathPolicyError('PATH_TRAVERSAL', `Path traversal detected: ${filePath}`);
30
36
  }
31
- const resolved = path.resolve(filePath);
32
- const resolvedAllowed = allowedPaths.map((p) => path.resolve(path.normalize(p)));
37
+ // Resolve symlinks so a symlink inside an allowed dir that points outside cannot bypass
38
+ // the containment check. Fall back to lexical resolution when the path doesn't exist yet.
39
+ let resolved;
40
+ try {
41
+ resolved = fs.realpathSync(filePath);
42
+ }
43
+ catch {
44
+ // Path doesn't exist — walk up the ancestor hierarchy to find the deepest existing directory,
45
+ // resolve symlinks there, then re-attach the non-existent tail segments. This handles macOS
46
+ // where os.tmpdir() returns /var/... (a symlink to /private/var/...) and intermediate dirs
47
+ // for a new output path may not yet exist.
48
+ const full = path.resolve(filePath);
49
+ let cur = full;
50
+ const tail = [];
51
+ while (!fs.existsSync(cur) && cur !== path.dirname(cur)) {
52
+ tail.unshift(path.basename(cur));
53
+ cur = path.dirname(cur);
54
+ }
55
+ try {
56
+ resolved = path.join(fs.realpathSync(cur), ...tail);
57
+ }
58
+ catch {
59
+ resolved = full;
60
+ }
61
+ }
62
+ const resolvedAllowed = allowedPaths.map((p) => {
63
+ try {
64
+ return fs.realpathSync(p);
65
+ }
66
+ catch {
67
+ return path.resolve(path.normalize(p));
68
+ }
69
+ });
70
+ // Windows file paths are case-insensitive; fs.realpathSync does not always
71
+ // canonicalize drive-letter case (e.g. `c:\` vs `C:\`), so compare case-insensitively.
72
+ const isWindows = process.platform === 'win32';
73
+ const normalizeForCompare = (p) => (isWindows ? p.toLowerCase() : p);
74
+ const resolvedKey = normalizeForCompare(resolved);
33
75
  if (resolvedAllowed.length > 0 &&
34
- !resolvedAllowed.some((base) => resolved === base || resolved.startsWith(base + path.sep))) {
76
+ !resolvedAllowed.some((base) => {
77
+ const rawBaseKey = normalizeForCompare(base);
78
+ // Strip trailing separator unless base is a filesystem root (/ on Unix, C:\ on Windows).
79
+ // A trailing sep from user input like "/tmp/" would otherwise cause double-sep prefix
80
+ // checks ("startsWith('/tmp//')") and equality mismatches ("/tmp" !== "/tmp/").
81
+ const isRoot = rawBaseKey === path.sep || (isWindows && /^[a-z]:[/\\]$/.test(rawBaseKey));
82
+ if (isRoot) {
83
+ // Root path already ends with its own separator (/ or C:\).
84
+ // Appending path.sep would produce // or C:\\, breaking startsWith for all children.
85
+ return resolvedKey.startsWith(rawBaseKey);
86
+ }
87
+ const baseKey = rawBaseKey.endsWith(path.sep) ? rawBaseKey.slice(0, -1) : rawBaseKey;
88
+ return resolvedKey === baseKey || resolvedKey.startsWith(baseKey + path.sep);
89
+ })) {
35
90
  throw new PathPolicyError('PATH_NOT_ALLOWED', `Path "${resolved}" is not within allowed paths: [${resolvedAllowed.join(', ')}]`);
36
91
  }
37
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pathPolicy.js","sourceRoot":"","sources":["../../../src/mcp/security/pathPolicy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxB,IAAI,CAAS;IAC7B,YAAmB,IAAY,EAAE,OAAe;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,YAAsB;IACxE,wFAAwF;IACxF,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzE,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,eAAe,CAAC,gBAAgB,EAAE,4BAA4B,QAAQ,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,eAAe,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjF,IACE,eAAe,CAAC,MAAM,GAAG,CAAC;QAC1B,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAC1F,CAAC;QACD,MAAM,IAAI,eAAe,CACvB,kBAAkB,EAClB,SAAS,QAAQ,mCAAmC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAClF,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"pathPolicy.js","sourceRoot":"","sources":["../../../src/mcp/security/pathPolicy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxB,IAAI,CAAS;IAC7B,YAAmB,IAAY,EAAE,OAAe;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,YAAsB;IACxE,wFAAwF;IACxF,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzE,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,eAAe,CAAC,gBAAgB,EAAE,4BAA4B,QAAQ,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,wFAAwF;IACxF,0FAA0F;IAC1F,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,8FAA8F;QAC9F,4FAA4F;QAC5F,2FAA2F;QAC3F,2CAA2C;QAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,GAAG,GAAG,IAAI,CAAC;QACf,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACxD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YACjC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC;YACH,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;IACH,CAAC;IAED,MAAM,eAAe,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7C,IAAI,CAAC;YACH,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,2EAA2E;IAC3E,uFAAuF;IACvF,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;IAC/C,MAAM,mBAAmB,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrF,MAAM,WAAW,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAElD,IACE,eAAe,CAAC,MAAM,GAAG,CAAC;QAC1B,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YAC7B,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAC7C,yFAAyF;YACzF,sFAAsF;YACtF,gFAAgF;YAChF,MAAM,MAAM,GAAG,UAAU,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,IAAI,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAC1F,IAAI,MAAM,EAAE,CAAC;gBACX,4DAA4D;gBAC5D,qFAAqF;gBACrF,OAAO,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YAC5C,CAAC;YACD,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;YACrF,OAAO,WAAW,KAAK,OAAO,IAAI,WAAW,CAAC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/E,CAAC,CAAC,EACF,CAAC;QACD,MAAM,IAAI,eAAe,CACvB,kBAAkB,EAClB,SAAS,QAAQ,mCAAmC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAClF,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -1,5 +1,23 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  export interface ServerConfig {
3
3
  allowedPaths: string[];
4
+ updateResult?: {
5
+ updateAvailable: boolean;
6
+ latestVersion: string | null;
7
+ updateCommand: string | null;
8
+ };
4
9
  }
10
+ export declare function parseActiveGroups(): Set<string> | null;
5
11
  export declare function createProvarMcpServer(config: ServerConfig): McpServer;
12
+ /**
13
+ * Resolve the docs directory for bundled MCP Markdown resources.
14
+ * In compiled output (lib/mcp/) the sibling docs/ dir exists; in dev/ts-node
15
+ * mode (src/mcp/) it doesn't, so fall back two levels to the repo-root docs/.
16
+ */
17
+ export declare function resolveDocsDir(currentDir: string): string;
18
+ /**
19
+ * Read NITROX_CATALOG_SOURCE.json from the docs directory and return it as
20
+ * a formatted JSON string. Returns a fallback object string if the file is
21
+ * absent or unreadable.
22
+ */
23
+ export declare function readCatalogSource(docsDir: string): string;
package/lib/mcp/server.js CHANGED
@@ -4,9 +4,15 @@
4
4
  * Licensed under the BSD 3-Clause license.
5
5
  * For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
+ import { createRequire } from 'node:module';
8
+ import { existsSync, readFileSync } from 'node:fs';
9
+ import { fileURLToPath } from 'node:url';
10
+ import { dirname, join } from 'node:path';
7
11
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
12
  import { z } from 'zod';
9
13
  import { log } from './logging/logger.js';
14
+ const requireJson = createRequire(import.meta.url);
15
+ const SERVER_VERSION = requireJson('../../package.json').version;
10
16
  import { registerProjectInspect } from './tools/projectInspect.js';
11
17
  import { registerPageObjectGenerate } from './tools/pageObjectGenerate.js';
12
18
  import { registerPageObjectValidate } from './tools/pageObjectValidate.js';
@@ -17,43 +23,250 @@ import { registerTestPlanValidate } from './tools/testPlanValidate.js';
17
23
  import { registerProjectValidateFromPath } from './tools/projectValidateFromPath.js';
18
24
  import { registerAllPropertiesTools } from './tools/propertiesTools.js';
19
25
  import { registerAllQualityHubTools } from './tools/qualityHubTools.js';
26
+ import { registerAllQualityHubApiTools } from './tools/qualityHubApiTools.js';
20
27
  import { registerAllAutomationTools } from './tools/automationTools.js';
21
28
  import { registerAllDefectTools } from './tools/defectTools.js';
22
29
  import { registerAllAntTools } from './tools/antTools.js';
23
30
  import { registerAllRcaTools } from './tools/rcaTools.js';
24
31
  import { registerAllTestPlanTools } from './tools/testPlanTools.js';
32
+ import { registerAllNitroXTools } from './tools/nitroXTools.js';
33
+ import { registerAllTestCaseStepTools } from './tools/testCaseStepTools.js';
34
+ import { registerAllConnectionTools } from './tools/connectionTools.js';
35
+ import { registerAllPrompts } from './prompts/index.js';
36
+ import { createDepthGuardState, wrapWithDepthGuard, } from './utils/tokenMeta.js';
37
+ import { desc } from './tools/descHelper.js';
38
+ // ── Tool group registry ───────────────────────────────────────────────────────
39
+ // Groups are keyed in lowercase so they match the lowercased env var values.
40
+ const TOOL_GROUPS = {
41
+ nitrox: [registerAllNitroXTools],
42
+ automation: [registerAllAutomationTools],
43
+ qualityhub: [registerAllQualityHubTools, registerAllQualityHubApiTools, registerAllDefectTools],
44
+ validation: [
45
+ registerProjectValidateFromPath,
46
+ registerAllAntTools,
47
+ registerAllPropertiesTools,
48
+ registerTestCaseValidate,
49
+ registerTestSuiteValidate,
50
+ registerTestPlanValidate,
51
+ registerPageObjectValidate,
52
+ ],
53
+ authoring: [
54
+ registerTestCaseGenerate,
55
+ registerPageObjectGenerate,
56
+ registerAllTestCaseStepTools,
57
+ registerAllTestPlanTools,
58
+ ],
59
+ inspect: [registerProjectInspect],
60
+ connection: [registerAllConnectionTools],
61
+ rca: [registerAllRcaTools],
62
+ };
63
+ export function parseActiveGroups() {
64
+ const env = process.env['PROVAR_MCP_TOOLS'];
65
+ if (!env?.trim())
66
+ return null;
67
+ const requested = new Set(env
68
+ .split(',')
69
+ .map((g) => g.trim().toLowerCase())
70
+ .filter(Boolean));
71
+ if (requested.size === 0) {
72
+ log('warn', 'PROVAR_MCP_TOOLS was set but contained no valid group names — activating all groups', { raw: env });
73
+ return null;
74
+ }
75
+ const known = new Set(Object.keys(TOOL_GROUPS));
76
+ const matched = new Set();
77
+ const unknown = [];
78
+ for (const g of requested) {
79
+ if (known.has(g))
80
+ matched.add(g);
81
+ else
82
+ unknown.push(g);
83
+ }
84
+ if (unknown.length > 0) {
85
+ log('warn', 'PROVAR_MCP_TOOLS contains unknown group names — they will be ignored', {
86
+ raw: env,
87
+ unknown,
88
+ known: [...known],
89
+ });
90
+ }
91
+ if (matched.size === 0) {
92
+ log('warn', 'PROVAR_MCP_TOOLS matched no known group names — activating all groups', {
93
+ raw: env,
94
+ known: [...known],
95
+ });
96
+ return null;
97
+ }
98
+ return matched;
99
+ }
25
100
  export function createProvarMcpServer(config) {
26
101
  log('info', 'Creating Provar MCP server', { allowedPaths: config.allowedPaths });
27
102
  const server = new McpServer({
28
103
  name: 'provar-mcp',
29
- version: '1.0.0',
104
+ version: SERVER_VERSION,
30
105
  });
31
106
  // ── Sanity-check tool ────────────────────────────────────────────────────────
32
- server.tool('provardx.ping', 'Sanity-check tool. Echoes back a message with a timestamp. Use this to verify the MCP server is reachable before calling other tools.', {
33
- message: z.string().optional().default('ping').describe('Optional message to echo back'),
107
+ server.registerTool('provardx_ping', {
108
+ title: 'Ping MCP Server',
109
+ description: desc('Sanity-check tool. Echoes back a message with a timestamp. Use this to verify the MCP server is reachable before calling other tools.', 'Echo message back with timestamp; verify MCP server is reachable.'),
110
+ inputSchema: {
111
+ message: z
112
+ .string()
113
+ .optional()
114
+ .default('ping')
115
+ .describe(desc('Optional message to echo back', 'message to echo')),
116
+ },
34
117
  }, ({ message }) => {
35
- const result = { pong: message, ts: new Date().toISOString(), server: 'provar-mcp@1.0.0' };
118
+ const result = {
119
+ pong: message,
120
+ ts: new Date().toISOString(),
121
+ server: `provar-mcp@${SERVER_VERSION}`,
122
+ updateAvailable: config.updateResult?.updateAvailable ?? false,
123
+ latestVersion: config.updateResult?.latestVersion ?? null,
124
+ updateCommand: config.updateResult?.updateCommand ?? null,
125
+ };
36
126
  return {
37
127
  content: [{ type: 'text', text: JSON.stringify(result) }],
38
128
  structuredContent: result,
39
129
  };
40
130
  });
131
+ // ── Depth-guard middleware (PDX-474) ─────────────────────────────────────────
132
+ const rawLimit = parseInt(process.env['PROVAR_MCP_MAX_TOOL_DEPTH'] ?? '50', 10);
133
+ const depthLimit = Number.isNaN(rawLimit) || rawLimit <= 0 ? 50 : rawLimit;
134
+ const depthState = createDepthGuardState();
135
+ patchWithMiddleware(server, depthState, depthLimit);
41
136
  // ── Provar tools ─────────────────────────────────────────────────────────────
42
- registerProjectInspect(server, config);
43
- registerPageObjectGenerate(server, config);
44
- registerPageObjectValidate(server, config);
45
- registerTestCaseGenerate(server, config);
46
- registerTestCaseValidate(server, config);
47
- registerTestSuiteValidate(server);
48
- registerTestPlanValidate(server);
49
- registerProjectValidateFromPath(server, config);
50
- registerAllPropertiesTools(server, config);
51
- registerAllQualityHubTools(server);
52
- registerAllAutomationTools(server);
53
- registerAllDefectTools(server);
54
- registerAllAntTools(server, config);
55
- registerAllRcaTools(server);
56
- registerAllTestPlanTools(server, config);
137
+ const activeGroups = parseActiveGroups();
138
+ for (const [group, registrars] of Object.entries(TOOL_GROUPS)) {
139
+ if (activeGroups === null || activeGroups.has(group)) {
140
+ for (const register of registrars) {
141
+ register(server, config);
142
+ }
143
+ }
144
+ }
145
+ // ── Provar prompts ───────────────────────────────────────────────────────────
146
+ registerAllPrompts(server);
147
+ // ── Documentation resources ──────────────────────────────────────────────────
148
+ const docsDir = resolveDocsDir(dirname(fileURLToPath(import.meta.url)));
149
+ server.resource('provar-nitrox-component-catalog', 'provar://nitrox/component-catalog', {
150
+ description: 'Catalog of all shipped NitroX (Hybrid Model) base component packages. Lists every package with its components, types, tagNames, interactions, and attributes. Read this before calling provar_nitrox_generate to understand available component patterns and naming conventions.',
151
+ mimeType: 'text/markdown',
152
+ }, () => {
153
+ try {
154
+ const text = readFileSync(join(docsDir, 'NITROX_COMPONENT_CATALOG.md'), 'utf-8');
155
+ return {
156
+ contents: [{ uri: 'provar://nitrox/component-catalog', mimeType: 'text/markdown', text }],
157
+ };
158
+ }
159
+ catch {
160
+ return {
161
+ contents: [
162
+ {
163
+ uri: 'provar://nitrox/component-catalog',
164
+ mimeType: 'text/markdown',
165
+ text: '# NitroX Component Catalog\n\nCatalog not found. If you are developing from source, rebuild the package. Otherwise, reinstall or upgrade the plugin/package and try again.',
166
+ },
167
+ ],
168
+ };
169
+ }
170
+ });
171
+ server.resource('provar-nitrox-catalog-source', 'provar://nitrox/catalog-source', {
172
+ description: 'Version metadata for the bundled NitroX component catalog. Returns the factPackages commit SHA and fetch timestamp from the last successful release build. Use this to verify which version of the ProvarTesting/factPackages repo is bundled in the running MCP server.',
173
+ mimeType: 'application/json',
174
+ }, () => {
175
+ const text = readCatalogSource(docsDir);
176
+ return {
177
+ contents: [{ uri: 'provar://nitrox/catalog-source', mimeType: 'application/json', text }],
178
+ };
179
+ });
180
+ server.resource('provar-step-reference', 'provar://docs/step-reference', {
181
+ description: 'Canonical reference for all Provar XML test step API IDs, argument formats, validation rules, and corpus-verified examples. Use this to understand correct step structure when generating or reviewing test cases.',
182
+ mimeType: 'text/markdown',
183
+ }, () => {
184
+ try {
185
+ const content = readFileSync(join(docsDir, 'PROVAR_TEST_STEP_REFERENCE.md'), 'utf-8');
186
+ return {
187
+ contents: [
188
+ {
189
+ uri: 'provar://docs/step-reference',
190
+ mimeType: 'text/markdown',
191
+ text: content,
192
+ },
193
+ ],
194
+ };
195
+ }
196
+ catch {
197
+ return {
198
+ contents: [
199
+ {
200
+ uri: 'provar://docs/step-reference',
201
+ mimeType: 'text/markdown',
202
+ text: '# Provar Test Step Reference\n\nReference doc not found. If you are developing from source, rebuild the package. Otherwise, reinstall or upgrade the plugin/package and try again.',
203
+ },
204
+ ],
205
+ };
206
+ }
207
+ });
208
+ server.resource('provar-tool-guide', 'provar://docs/tool-guide', {
209
+ description: 'Tool selection guide for ProvarDX MCP. Organised by what you want to accomplish (run tests, author tests, debug failures, manage config, etc.) rather than by tool name. Read this to choose the right tool and understand correct sequencing before calling tools.',
210
+ mimeType: 'text/markdown',
211
+ }, () => {
212
+ try {
213
+ const text = readFileSync(join(docsDir, 'PROVAR_TOOL_GUIDE.md'), 'utf-8');
214
+ return {
215
+ contents: [{ uri: 'provar://docs/tool-guide', mimeType: 'text/markdown', text }],
216
+ };
217
+ }
218
+ catch {
219
+ return {
220
+ contents: [
221
+ {
222
+ uri: 'provar://docs/tool-guide',
223
+ mimeType: 'text/markdown',
224
+ text: '# ProvarDX Tool Guide\n\nGuide not found. Reinstall or upgrade the plugin and try again.',
225
+ },
226
+ ],
227
+ };
228
+ }
229
+ });
57
230
  return server;
58
231
  }
232
+ function patchWithMiddleware(server, state, limit) {
233
+ const orig = server.registerTool.bind(server);
234
+ // Cast through unknown to patch the overloaded method without triggering no-unsafe-any.
235
+ const patchable = server;
236
+ patchable.registerTool = (name, config, handler) => orig(name, config, wrapWithDepthGuard(name, handler, state, limit));
237
+ }
238
+ /**
239
+ * Resolve the docs directory for bundled MCP Markdown resources.
240
+ * In compiled output (lib/mcp/) the sibling docs/ dir exists; in dev/ts-node
241
+ * mode (src/mcp/) it doesn't, so fall back two levels to the repo-root docs/.
242
+ */
243
+ export function resolveDocsDir(currentDir) {
244
+ const sibling = join(currentDir, 'docs');
245
+ return existsSync(sibling) ? sibling : join(currentDir, '..', '..', 'docs');
246
+ }
247
+ /**
248
+ * Read NITROX_CATALOG_SOURCE.json from the docs directory and return it as
249
+ * a formatted JSON string. Returns a fallback object string if the file is
250
+ * absent or unreadable.
251
+ */
252
+ export function readCatalogSource(docsDir) {
253
+ try {
254
+ const raw = readFileSync(join(docsDir, 'NITROX_CATALOG_SOURCE.json'), 'utf-8');
255
+ const parsed = JSON.parse(raw);
256
+ // Normalise schemasUpdated so older build artifacts (which lack this field)
257
+ // return a stable shape rather than omitting the key entirely.
258
+ if (!('schemasUpdated' in parsed)) {
259
+ parsed['schemasUpdated'] = null;
260
+ }
261
+ return JSON.stringify(parsed, null, 2);
262
+ }
263
+ catch {
264
+ return JSON.stringify({
265
+ branch: 'main',
266
+ commitSha: null,
267
+ fetchedAt: null,
268
+ schemasUpdated: null,
269
+ }, null, 2);
270
+ }
271
+ }
59
272
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,+BAA+B,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAMpE,MAAM,UAAU,qBAAqB,CAAC,MAAoB;IACxD,GAAG,CAAC,MAAM,EAAE,4BAA4B,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IAEjF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,gFAAgF;IAChF,MAAM,CAAC,IAAI,CACT,eAAe,EACf,uIAAuI,EACvI;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,+BAA+B,CAAC;KACzF,EACD,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;QACd,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;QAC3F,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YAClE,iBAAiB,EAAE,MAAM;SAC1B,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,gFAAgF;IAChF,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,0BAA0B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,0BAA0B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,+BAA+B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,0BAA0B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEzC,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -18,4 +18,19 @@ export interface AntValidationResult {
18
18
  }
19
19
  /** Pure function — exported for unit testing */
20
20
  export declare function validateAntXml(xmlContent: string): AntValidationResult;
21
+ export interface JUnitStepResult {
22
+ testItemId: string;
23
+ title: string;
24
+ status: 'pass' | 'fail' | 'skip';
25
+ errorMessage?: string;
26
+ }
27
+ export interface JUnitParseResult {
28
+ steps: JUnitStepResult[];
29
+ warning?: string;
30
+ }
31
+ /**
32
+ * Scan a Provar results directory for JUnit XML files and return structured step results.
33
+ * Returns an empty steps array (+ optional warning) when no XML is found or parsing fails.
34
+ */
35
+ export declare function parseJUnitResults(resultsDir: string): JUnitParseResult;
21
36
  export declare function registerAllAntTools(server: McpServer, config: ServerConfig): void;