@provartesting/provardx-cli 1.5.0 → 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 (64) hide show
  1. package/lib/mcp/docs/PROVAR_TOOL_GUIDE.md +18 -6
  2. package/lib/mcp/prompts/guidePrompts.js +21 -11
  3. package/lib/mcp/prompts/guidePrompts.js.map +1 -1
  4. package/lib/mcp/server.d.ts +1 -0
  5. package/lib/mcp/server.js +89 -21
  6. package/lib/mcp/server.js.map +1 -1
  7. package/lib/mcp/tools/antTools.js +60 -38
  8. package/lib/mcp/tools/antTools.js.map +1 -1
  9. package/lib/mcp/tools/automationTools.js +22 -21
  10. package/lib/mcp/tools/automationTools.js.map +1 -1
  11. package/lib/mcp/tools/connectionTools.js +100 -30
  12. package/lib/mcp/tools/connectionTools.js.map +1 -1
  13. package/lib/mcp/tools/defectTools.js +12 -7
  14. package/lib/mcp/tools/defectTools.js.map +1 -1
  15. package/lib/mcp/tools/descHelper.d.ts +5 -0
  16. package/lib/mcp/tools/descHelper.js +14 -0
  17. package/lib/mcp/tools/descHelper.js.map +1 -0
  18. package/lib/mcp/tools/nitroXTools.js +72 -32
  19. package/lib/mcp/tools/nitroXTools.js.map +1 -1
  20. package/lib/mcp/tools/pageObjectGenerate.js +33 -15
  21. package/lib/mcp/tools/pageObjectGenerate.js.map +1 -1
  22. package/lib/mcp/tools/pageObjectValidate.js +11 -4
  23. package/lib/mcp/tools/pageObjectValidate.js.map +1 -1
  24. package/lib/mcp/tools/projectInspect.js +31 -5
  25. package/lib/mcp/tools/projectInspect.js.map +1 -1
  26. package/lib/mcp/tools/projectValidateFromPath.js +128 -22
  27. package/lib/mcp/tools/projectValidateFromPath.js.map +1 -1
  28. package/lib/mcp/tools/propertiesTools.js +43 -17
  29. package/lib/mcp/tools/propertiesTools.js.map +1 -1
  30. package/lib/mcp/tools/qualityHubApiTools.js +8 -7
  31. package/lib/mcp/tools/qualityHubApiTools.js.map +1 -1
  32. package/lib/mcp/tools/qualityHubTools.js +108 -37
  33. package/lib/mcp/tools/qualityHubTools.js.map +1 -1
  34. package/lib/mcp/tools/rcaTools.js +18 -13
  35. package/lib/mcp/tools/rcaTools.js.map +1 -1
  36. package/lib/mcp/tools/testCaseGenerate.js +71 -12
  37. package/lib/mcp/tools/testCaseGenerate.js.map +1 -1
  38. package/lib/mcp/tools/testCaseStepTools.js +27 -9
  39. package/lib/mcp/tools/testCaseStepTools.js.map +1 -1
  40. package/lib/mcp/tools/testCaseValidate.js +136 -57
  41. package/lib/mcp/tools/testCaseValidate.js.map +1 -1
  42. package/lib/mcp/tools/testPlanTools.js +43 -26
  43. package/lib/mcp/tools/testPlanTools.js.map +1 -1
  44. package/lib/mcp/tools/testPlanValidate.js +64 -11
  45. package/lib/mcp/tools/testPlanValidate.js.map +1 -1
  46. package/lib/mcp/tools/testSuiteValidate.js +99 -10
  47. package/lib/mcp/tools/testSuiteValidate.js.map +1 -1
  48. package/lib/mcp/utils/detailLevel.d.ts +9 -0
  49. package/lib/mcp/utils/detailLevel.js +20 -0
  50. package/lib/mcp/utils/detailLevel.js.map +1 -0
  51. package/lib/mcp/utils/fieldMask.d.ts +17 -0
  52. package/lib/mcp/utils/fieldMask.js +75 -0
  53. package/lib/mcp/utils/fieldMask.js.map +1 -0
  54. package/lib/mcp/utils/tokenMeta.d.ts +40 -0
  55. package/lib/mcp/utils/tokenMeta.js +90 -0
  56. package/lib/mcp/utils/tokenMeta.js.map +1 -0
  57. package/lib/mcp/utils/validationDiff.d.ts +57 -0
  58. package/lib/mcp/utils/validationDiff.js +191 -0
  59. package/lib/mcp/utils/validationDiff.js.map +1 -0
  60. package/lib/mcp/utils/validationScore.d.ts +15 -0
  61. package/lib/mcp/utils/validationScore.js +31 -0
  62. package/lib/mcp/utils/validationScore.js.map +1 -0
  63. package/oclif.manifest.json +1 -1
  64. package/package.json +13 -1
@@ -8,7 +8,30 @@
8
8
  import { z } from 'zod';
9
9
  import { makeError, makeRequestId } from '../schemas/common.js';
10
10
  import { log } from '../logging/logger.js';
11
- import { validatePlan, buildHierarchySummary } from './hierarchyValidate.js';
11
+ import { applyDetailLevel } from '../utils/detailLevel.js';
12
+ import { calcCompletenessScore, calcNextAction } from '../utils/validationScore.js';
13
+ import { validatePlan, buildHierarchySummary, } from './hierarchyValidate.js';
14
+ import { desc } from './descHelper.js';
15
+ function countSuiteViolations(suite) {
16
+ let total = suite.violations.length;
17
+ for (const tc of suite.test_cases) {
18
+ total += tc.issues.length + tc.best_practices_violations.length;
19
+ }
20
+ for (const child of suite.test_suites) {
21
+ total += countSuiteViolations(child);
22
+ }
23
+ return total;
24
+ }
25
+ function countAllPlanViolations(result) {
26
+ let total = result.violations.length;
27
+ for (const suite of result.test_suites) {
28
+ total += countSuiteViolations(suite);
29
+ }
30
+ for (const tc of result.test_cases) {
31
+ total += tc.issues.length + tc.best_practices_violations.length;
32
+ }
33
+ return total;
34
+ }
12
35
  // ── Zod schemas ───────────────────────────────────────────────────────────────
13
36
  const testCaseSchema = z
14
37
  .object({
@@ -60,29 +83,48 @@ const metadataSchema = z
60
83
  })
61
84
  .optional()
62
85
  .describe('Plan completeness metadata — these fields are configured in the Provar Quality Hub app, not in local project files');
86
+ const PLAN_VALIDATE_SUMMARY_FIELDS = [
87
+ 'requestId',
88
+ 'name',
89
+ 'quality_score',
90
+ 'summary',
91
+ 'completeness_score',
92
+ 'recommended_next_action',
93
+ ];
63
94
  export function registerTestPlanValidate(server) {
64
95
  server.registerTool('provar_testplan_validate', {
65
96
  title: 'Validate Test Plan',
66
- description: 'Validate a Provar test plan: checks for empty plans, duplicate suite names, oversized plans (>20 suites), plan completeness (objectives, scope, methodology, environments, acceptance criteria, test data strategy, risk assessment), and naming consistency. Recursively validates child suites and test cases. Returns quality score, plan-level violations, and full hierarchy results.',
97
+ description: desc('Validate a Provar test plan: checks for empty plans, duplicate suite names, oversized plans (>20 suites), plan completeness (objectives, scope, methodology, environments, acceptance criteria, test data strategy, risk assessment), and naming consistency. Recursively validates child suites and test cases. Returns quality score, plan-level violations, and full hierarchy results. Use completeness_score and recommended_next_action to determine whether to continue iterating.', 'Validate a Provar test plan: naming, size, completeness, per-suite quality; stop signal via completeness_score.'),
67
98
  inputSchema: {
68
- plan_name: z.string().describe('Name of the test plan'),
69
- test_suites: z.array(suiteSchema).optional().describe('Test suites belonging to this plan'),
70
- test_cases: z.array(testCaseSchema).optional().describe('Test cases directly in this plan (not in a suite)'),
99
+ plan_name: z.string().describe(desc('Name of the test plan', 'string')),
100
+ test_suites: z
101
+ .array(suiteSchema)
102
+ .optional()
103
+ .describe(desc('Test suites belonging to this plan', 'object[], optional')),
104
+ test_cases: z
105
+ .array(testCaseSchema)
106
+ .optional()
107
+ .describe(desc('Test cases directly in this plan (not in a suite)', 'object[], optional')),
71
108
  test_suite_count: z
72
109
  .number()
73
110
  .int()
74
111
  .min(0)
75
112
  .optional()
76
- .describe('Explicit suite count for size check (overrides counting test_suites)'),
113
+ .describe(desc('Explicit suite count for size check (overrides counting test_suites)', 'int ≥0, optional')),
77
114
  metadata: metadataSchema,
78
115
  quality_threshold: z
79
116
  .number()
80
117
  .min(0)
81
118
  .max(100)
82
119
  .optional()
83
- .describe('Minimum quality score for a test case to be considered valid (default: 80)'),
120
+ .describe(desc('Minimum quality score for a test case to be considered valid (default: 80)', 'number 0–100, optional')),
121
+ detail: z
122
+ .enum(['summary', 'standard', 'full'])
123
+ .optional()
124
+ .default('standard')
125
+ .describe(desc('Response verbosity. "summary": name, scores, and stop signal only. "standard"/"full": full violations and hierarchy results (default).', 'enum summary|standard|full, optional; default standard')),
84
126
  },
85
- }, ({ plan_name, test_suites, test_cases, test_suite_count, metadata, quality_threshold }) => {
127
+ }, ({ plan_name, test_suites, test_cases, test_suite_count, metadata, quality_threshold, detail }) => {
86
128
  const requestId = makeRequestId();
87
129
  log('info', 'provar_testplan_validate', { requestId, plan_name });
88
130
  try {
@@ -96,10 +138,21 @@ export function registerTestPlanValidate(server) {
96
138
  };
97
139
  const result = validatePlan(input, threshold);
98
140
  const summary = buildHierarchySummary(result);
99
- const response = { requestId, ...result, summary };
141
+ const completeness_score = calcCompletenessScore(summary.test_cases_valid, summary.total_test_cases);
142
+ const remainingViolations = countAllPlanViolations(result);
143
+ const recommended_next_action = calcNextAction(completeness_score, false, remainingViolations);
144
+ const response = {
145
+ requestId,
146
+ completeness_score,
147
+ recommended_next_action,
148
+ ...result,
149
+ summary,
150
+ };
151
+ const detailLevel = (detail ?? 'standard');
152
+ const finalResponse = applyDetailLevel(response, detailLevel, PLAN_VALIDATE_SUMMARY_FIELDS);
100
153
  return {
101
- content: [{ type: 'text', text: JSON.stringify(response) }],
102
- structuredContent: response,
154
+ content: [{ type: 'text', text: JSON.stringify(finalResponse) }],
155
+ structuredContent: finalResponse,
103
156
  };
104
157
  }
105
158
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"testPlanValidate.js","sourceRoot":"","sources":["../../../src/mcp/tools/testPlanValidate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"testPlanValidate.js","sourceRoot":"","sources":["../../../src/mcp/tools/testPlanValidate.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,22 @@
8
8
  import { z } from 'zod';
9
9
  import { makeError, makeRequestId } from '../schemas/common.js';
10
10
  import { log } from '../logging/logger.js';
11
+ import { applyDetailLevel } from '../utils/detailLevel.js';
12
+ import { calcCompletenessScore, calcNextAction } from '../utils/validationScore.js';
13
+ import { generateRunId, saveRun, hasAnyRun, loadBaselineViolations, computeDiff, computeContextHash, resolveValidationDir, } from '../utils/validationDiff.js';
11
14
  import { validateSuite, buildHierarchySummary } from './hierarchyValidate.js';
15
+ import { desc } from './descHelper.js';
16
+ function collectAllViolations(result) {
17
+ const all = [...result.violations];
18
+ for (const tc of result.test_cases) {
19
+ all.push(...tc.issues);
20
+ all.push(...tc.best_practices_violations);
21
+ }
22
+ for (const child of result.test_suites) {
23
+ all.push(...collectAllViolations(child));
24
+ }
25
+ return all;
26
+ }
12
27
  // ── Zod schemas ───────────────────────────────────────────────────────────────
13
28
  const testCaseSchema = z
14
29
  .object({
@@ -35,31 +50,55 @@ const childSuiteSchema = z.object({
35
50
  test_suites: z.array(innerSuiteSchema).optional().describe('Nested child suites (one level deep)'),
36
51
  test_case_count: z.number().int().min(0).optional().describe('Explicit test case count for size check'),
37
52
  });
53
+ const SUITE_VALIDATE_SUMMARY_FIELDS = [
54
+ 'requestId',
55
+ 'name',
56
+ 'quality_score',
57
+ 'summary',
58
+ 'run_id',
59
+ 'completeness_score',
60
+ 'recommended_next_action',
61
+ ];
62
+ function suiteStorageDir() {
63
+ return resolveValidationDir('testsuite');
64
+ }
38
65
  export function registerTestSuiteValidate(server) {
39
66
  server.registerTool('provar_testsuite_validate', {
40
67
  title: 'Validate Test Suite',
41
- description: 'Validate a Provar test suite: checks for empty suites, duplicate names, oversized suites (>75 tests), and naming convention consistency. Recursively validates child suites and individual test case XML. Returns quality score, suite-level violations, and per-test-case results.',
68
+ description: desc('Validate a Provar test suite: checks for empty suites, duplicate names, oversized suites (>75 tests), and naming convention consistency. Recursively validates child suites and individual test case XML. Returns quality score, suite-level violations, and per-test-case results. Every response includes run_id — pass it as baseline_run_id in the next call to receive only new/resolved violations.', 'Validate a Provar test suite: naming, size, duplicates, per-test-case quality; run_id for diff.'),
42
69
  inputSchema: {
43
- suite_name: z.string().describe('Name of the test suite'),
44
- test_cases: z.array(testCaseSchema).optional().describe('Test cases directly in this suite'),
70
+ suite_name: z.string().describe(desc('Name of the test suite', 'string')),
71
+ test_cases: z
72
+ .array(testCaseSchema)
73
+ .optional()
74
+ .describe(desc('Test cases directly in this suite', 'object[], optional')),
45
75
  child_suites: z
46
76
  .array(childSuiteSchema)
47
77
  .optional()
48
- .describe('Child test suites (supports up to 2 levels of nesting)'),
78
+ .describe(desc('Child test suites (supports up to 2 levels of nesting)', 'object[], optional')),
49
79
  test_case_count: z
50
80
  .number()
51
81
  .int()
52
82
  .min(0)
53
83
  .optional()
54
- .describe('Explicit total test case count for size check (overrides counting test_cases)'),
84
+ .describe(desc('Explicit total test case count for size check (overrides counting test_cases)', 'int ≥0, optional')),
55
85
  quality_threshold: z
56
86
  .number()
57
87
  .min(0)
58
88
  .max(100)
59
89
  .optional()
60
- .describe('Minimum quality score for a test case to be considered valid (default: 80)'),
90
+ .describe(desc('Minimum quality score for a test case to be considered valid (default: 80)', 'number 0–100, optional')),
91
+ detail: z
92
+ .enum(['summary', 'standard', 'full'])
93
+ .optional()
94
+ .default('standard')
95
+ .describe(desc('Response verbosity. "summary": name, scores, and stop signal only. "standard"/"full": full violations and per-test-case results (default).', 'enum summary|standard|full, optional; default standard')),
96
+ baseline_run_id: z
97
+ .string()
98
+ .optional()
99
+ .describe(desc('run_id from a previous call. When provided, returns only violations that are new or resolved since that run: { added, resolved, unchanged_count, run_id }. If not found, returns error BASELINE_NOT_FOUND.', 'string, optional; prev run_id for diff response')),
61
100
  },
62
- }, ({ suite_name, test_cases, child_suites, test_case_count, quality_threshold }) => {
101
+ }, ({ suite_name, test_cases, child_suites, test_case_count, quality_threshold, detail, baseline_run_id }) => {
63
102
  const requestId = makeRequestId();
64
103
  log('info', 'provar_testsuite_validate', { requestId, suite_name });
65
104
  try {
@@ -72,10 +111,60 @@ export function registerTestSuiteValidate(server) {
72
111
  };
73
112
  const result = validateSuite(input, threshold);
74
113
  const summary = buildHierarchySummary(result);
75
- const response = { requestId, ...result, summary };
114
+ const storageDir = suiteStorageDir();
115
+ const contextHash = computeContextHash('suite', suite_name);
116
+ const runId = generateRunId(suite_name);
117
+ const currentViolations = collectAllViolations(result);
118
+ // Load baseline BEFORE saving to prevent eviction of the requested baseline
119
+ const baseline = baseline_run_id !== undefined && baseline_run_id !== ''
120
+ ? loadBaselineViolations(storageDir, baseline_run_id, contextHash)
121
+ : null;
122
+ const hasBaseline = hasAnyRun(storageDir);
123
+ try {
124
+ saveRun(storageDir, runId, currentViolations, contextHash);
125
+ }
126
+ catch (saveErr) {
127
+ log('warn', 'provar_testsuite_validate: could not save run for diff', {
128
+ requestId,
129
+ error: saveErr.message,
130
+ });
131
+ }
132
+ // Diff mode
133
+ if (baseline_run_id !== undefined && baseline_run_id !== '') {
134
+ if (!baseline) {
135
+ const errResult = makeError('BASELINE_NOT_FOUND', 'Baseline run not found. Run validation without baseline_run_id first to establish a baseline.', requestId, false, { suggestion: 'Run provar_testsuite_validate without baseline_run_id first to establish a baseline.' });
136
+ return { isError: true, content: [{ type: 'text', text: JSON.stringify(errResult) }] };
137
+ }
138
+ const diff = computeDiff(baseline, currentViolations);
139
+ const completeness_score = calcCompletenessScore(summary.test_cases_valid, summary.total_test_cases);
140
+ const recommended_next_action = calcNextAction(completeness_score, true, currentViolations.length);
141
+ const diffResponse = {
142
+ requestId,
143
+ run_id: runId,
144
+ ...diff,
145
+ completeness_score,
146
+ recommended_next_action,
147
+ };
148
+ return {
149
+ content: [{ type: 'text', text: JSON.stringify(diffResponse) }],
150
+ structuredContent: diffResponse,
151
+ };
152
+ }
153
+ const completeness_score = calcCompletenessScore(summary.test_cases_valid, summary.total_test_cases);
154
+ const recommended_next_action = calcNextAction(completeness_score, hasBaseline, currentViolations.length);
155
+ const response = {
156
+ requestId,
157
+ run_id: runId,
158
+ completeness_score,
159
+ recommended_next_action,
160
+ ...result,
161
+ summary,
162
+ };
163
+ const detailLevel = (detail ?? 'standard');
164
+ const finalResponse = applyDetailLevel(response, detailLevel, SUITE_VALIDATE_SUMMARY_FIELDS);
76
165
  return {
77
- content: [{ type: 'text', text: JSON.stringify(response) }],
78
- structuredContent: response,
166
+ content: [{ type: 'text', text: JSON.stringify(finalResponse) }],
167
+ structuredContent: finalResponse,
79
168
  };
80
169
  }
81
170
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"testSuiteValidate.js","sourceRoot":"","sources":["../../../src/mcp/tools/testSuiteValidate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"testSuiteValidate.js","sourceRoot":"","sources":["../../../src/mcp/tools/testSuiteValidate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export type DetailLevel = 'summary' | 'standard' | 'full';
2
+ /**
3
+ * Shape a structured response object according to the requested detail level.
4
+ *
5
+ * - `summary` — retain only the keys listed in summaryFields
6
+ * - `standard` — return data unchanged (the existing default response shape)
7
+ * - `full` — return data unchanged (callers expand gated fields before calling)
8
+ */
9
+ export declare function applyDetailLevel(data: Record<string, unknown>, level: DetailLevel, summaryFields: string[]): Record<string, unknown>;
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Copyright (c) 2024 Provar Limited.
3
+ * All rights reserved.
4
+ * Licensed under the BSD 3-Clause license.
5
+ * For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+ /**
8
+ * Shape a structured response object according to the requested detail level.
9
+ *
10
+ * - `summary` — retain only the keys listed in summaryFields
11
+ * - `standard` — return data unchanged (the existing default response shape)
12
+ * - `full` — return data unchanged (callers expand gated fields before calling)
13
+ */
14
+ export function applyDetailLevel(data, level, summaryFields) {
15
+ if (level === 'summary') {
16
+ return Object.fromEntries(Object.entries(data).filter(([k]) => summaryFields.includes(k)));
17
+ }
18
+ return data;
19
+ }
20
+ //# sourceMappingURL=detailLevel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detailLevel.js","sourceRoot":"","sources":["../../../src/mcp/utils/detailLevel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAA6B,EAC7B,KAAkB,EAClB,aAAuB;IAEvB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7F,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Mask an object (or array of objects) to retain only the specified fields.
3
+ *
4
+ * - Top-level keys: `"name"` keeps only the `name` property
5
+ * - Dot notation: `"steps.action"` keeps the `steps` array but only `action` within each element
6
+ * - Unknown field names are silently ignored — never an error
7
+ * - Arrays: masking is applied to every element
8
+ *
9
+ * @param obj Source object or array (typed as unknown; cast internally, never through any)
10
+ * @param fields Parsed field list — each entry is a dot-path string
11
+ */
12
+ export declare function maskFields(obj: unknown, fields: string[]): unknown;
13
+ /**
14
+ * Parse a comma-separated fields string into a trimmed, non-empty field list.
15
+ * Returns null when the string is absent or blank (caller should skip masking).
16
+ */
17
+ export declare function parseFieldsParam(fields: string | undefined): string[] | null;
@@ -0,0 +1,75 @@
1
+ /*
2
+ * Copyright (c) 2024 Provar Limited.
3
+ * All rights reserved.
4
+ * Licensed under the BSD 3-Clause license.
5
+ * For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+ /**
8
+ * Mask an object (or array of objects) to retain only the specified fields.
9
+ *
10
+ * - Top-level keys: `"name"` keeps only the `name` property
11
+ * - Dot notation: `"steps.action"` keeps the `steps` array but only `action` within each element
12
+ * - Unknown field names are silently ignored — never an error
13
+ * - Arrays: masking is applied to every element
14
+ *
15
+ * @param obj Source object or array (typed as unknown; cast internally, never through any)
16
+ * @param fields Parsed field list — each entry is a dot-path string
17
+ */
18
+ export function maskFields(obj, fields) {
19
+ if (Array.isArray(obj)) {
20
+ return obj.map((item) => maskFields(item, fields));
21
+ }
22
+ if (obj === null || typeof obj !== 'object') {
23
+ return obj;
24
+ }
25
+ const source = obj;
26
+ // Group fields: topLevelKeys contains every key to retain.
27
+ // dotFields[key] holds the sub-paths to drill into for that key.
28
+ const topLevelKeys = new Set();
29
+ const dotFields = {};
30
+ for (const field of fields) {
31
+ const dotIdx = field.indexOf('.');
32
+ if (dotIdx === -1) {
33
+ topLevelKeys.add(field);
34
+ }
35
+ else {
36
+ const top = field.slice(0, dotIdx);
37
+ const rest = field.slice(dotIdx + 1);
38
+ topLevelKeys.add(top);
39
+ if (!dotFields[top])
40
+ dotFields[top] = [];
41
+ dotFields[top].push(rest);
42
+ }
43
+ }
44
+ const result = {};
45
+ for (const key of topLevelKeys) {
46
+ if (!(key in source))
47
+ continue; // silently ignore unknown fields
48
+ const subPaths = dotFields[key];
49
+ if (subPaths) {
50
+ const val = source[key];
51
+ // Dot-path into a primitive can't be narrowed; omit rather than leak the whole value.
52
+ if (Array.isArray(val) || (val !== null && typeof val === 'object')) {
53
+ result[key] = maskFields(val, subPaths);
54
+ }
55
+ }
56
+ else {
57
+ result[key] = source[key];
58
+ }
59
+ }
60
+ return result;
61
+ }
62
+ /**
63
+ * Parse a comma-separated fields string into a trimmed, non-empty field list.
64
+ * Returns null when the string is absent or blank (caller should skip masking).
65
+ */
66
+ export function parseFieldsParam(fields) {
67
+ if (!fields)
68
+ return null;
69
+ const parsed = fields
70
+ .split(',')
71
+ .map((f) => f.trim())
72
+ .filter(Boolean);
73
+ return parsed.length > 0 ? parsed : null;
74
+ }
75
+ //# sourceMappingURL=fieldMask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldMask.js","sourceRoot":"","sources":["../../../src/mcp/utils/fieldMask.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,GAAY,EAAE,MAAgB;IACvD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,GAAG,CAAC;IACb,CAAC;IAED,MAAM,MAAM,GAAG,GAA8B,CAAC;IAE9C,2DAA2D;IAC3D,iEAAiE;IACjE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,MAAM,SAAS,GAA6B,EAAE,CAAC;IAE/C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YAClB,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YACnC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACrC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACtB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;gBAAE,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YACzC,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,IAAI,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC;YAAE,SAAS,CAAC,iCAAiC;QACjE,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YACxB,sFAAsF;YACtF,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,CAAC,EAAE,CAAC;gBACpE,MAAM,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAA0B;IACzD,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,MAAM,GAAG,MAAM;SAClB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,40 @@
1
+ type ContentItem = {
2
+ type: 'text';
3
+ text: string;
4
+ };
5
+ export interface ToolResult {
6
+ content: ContentItem[];
7
+ structuredContent?: Record<string, unknown>;
8
+ isError?: boolean;
9
+ }
10
+ interface ToolExtra {
11
+ sessionId?: string;
12
+ }
13
+ export type AnyToolCallback = (args: Record<string, unknown>, extra: ToolExtra) => ToolResult | Promise<ToolResult>;
14
+ interface SessionEntry {
15
+ calls: number;
16
+ totalEstimatedTokens: number;
17
+ }
18
+ export type DepthGuardState = Map<string, SessionEntry>;
19
+ export declare function createDepthGuardState(): DepthGuardState;
20
+ /**
21
+ * Wraps a tool handler to enforce a per-session call budget.
22
+ * Once `limit` calls have been made for a session, every further call returns
23
+ * TOOL_BUDGET_EXCEEDED without invoking the underlying handler.
24
+ * Callers without a sessionId (stdio transports — Claude Desktop, Cursor, etc.)
25
+ * share a single 'anon' bucket so the budget actually limits runaway tool use;
26
+ * giving each anon call a fresh UUID would defeat the purpose of the guard.
27
+ * `provardx_ping` is excluded from wrapping at the call site in server.ts.
28
+ */
29
+ export declare function wrapWithDepthGuard(toolName: string, handler: AnyToolCallback, state: DepthGuardState, limit: number): AnyToolCallback;
30
+ export declare function estimateTokens(payload: unknown): number;
31
+ /**
32
+ * Appends a `_meta` key to `structuredContent` when PROVAR_MCP_EMIT_TOKEN_META=true.
33
+ * The `content[0].text` string is intentionally left unchanged — LLMs read that
34
+ * field, so including meta there would waste tokens on observability data.
35
+ *
36
+ * @param sessionTotalTokens - Cumulative estimated tokens for the session,
37
+ * included only on TOOL_BUDGET_EXCEEDED errors.
38
+ */
39
+ export declare function attachMeta(response: ToolResult, toolName: string, detailLevel: string, sessionTotalTokens?: number): ToolResult;
40
+ export {};
@@ -0,0 +1,90 @@
1
+ /*
2
+ * Copyright (c) 2024 Provar Limited.
3
+ * All rights reserved.
4
+ * Licensed under the BSD 3-Clause license.
5
+ * For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+ const MAX_SESSIONS = 1000;
8
+ export function createDepthGuardState() {
9
+ return new Map();
10
+ }
11
+ function getOrCreateEntry(state, sessionId) {
12
+ if (!state.has(sessionId)) {
13
+ if (state.size >= MAX_SESSIONS) {
14
+ const oldest = state.keys().next().value;
15
+ if (oldest !== undefined)
16
+ state.delete(oldest);
17
+ }
18
+ state.set(sessionId, { calls: 0, totalEstimatedTokens: 0 });
19
+ }
20
+ // Non-null guaranteed by the set above or pre-existing entry.
21
+ return state.get(sessionId);
22
+ }
23
+ /**
24
+ * Wraps a tool handler to enforce a per-session call budget.
25
+ * Once `limit` calls have been made for a session, every further call returns
26
+ * TOOL_BUDGET_EXCEEDED without invoking the underlying handler.
27
+ * Callers without a sessionId (stdio transports — Claude Desktop, Cursor, etc.)
28
+ * share a single 'anon' bucket so the budget actually limits runaway tool use;
29
+ * giving each anon call a fresh UUID would defeat the purpose of the guard.
30
+ * `provardx_ping` is excluded from wrapping at the call site in server.ts.
31
+ */
32
+ export function wrapWithDepthGuard(toolName, handler, state, limit) {
33
+ return async (args, extra) => {
34
+ const sessionId = extra.sessionId ?? 'anon';
35
+ const entry = getOrCreateEntry(state, sessionId);
36
+ if (entry.calls >= limit) {
37
+ const payload = {
38
+ error: 'TOOL_BUDGET_EXCEEDED',
39
+ callsMade: entry.calls,
40
+ limit,
41
+ suggestion: 'Summarize progress and return control to the user.',
42
+ };
43
+ const response = {
44
+ isError: true,
45
+ content: [{ type: 'text', text: JSON.stringify(payload) }],
46
+ structuredContent: payload,
47
+ };
48
+ return attachMeta(response, toolName, 'standard', entry.totalEstimatedTokens);
49
+ }
50
+ entry.calls++;
51
+ const result = await handler(args, extra);
52
+ if (process.env['PROVAR_MCP_EMIT_TOKEN_META'] === 'true') {
53
+ entry.totalEstimatedTokens += estimateTokens(result);
54
+ }
55
+ const detailLevel = typeof args['detail'] === 'string' ? args['detail'] : 'standard';
56
+ return attachMeta(result, toolName, detailLevel);
57
+ };
58
+ }
59
+ // --------------------------------------------------------------------------- //
60
+ // PDX-475 — Token meta attachment (PROVAR_MCP_EMIT_TOKEN_META)
61
+ // --------------------------------------------------------------------------- //
62
+ export function estimateTokens(payload) {
63
+ return Math.ceil(JSON.stringify(payload).length / 4);
64
+ }
65
+ /**
66
+ * Appends a `_meta` key to `structuredContent` when PROVAR_MCP_EMIT_TOKEN_META=true.
67
+ * The `content[0].text` string is intentionally left unchanged — LLMs read that
68
+ * field, so including meta there would waste tokens on observability data.
69
+ *
70
+ * @param sessionTotalTokens - Cumulative estimated tokens for the session,
71
+ * included only on TOOL_BUDGET_EXCEEDED errors.
72
+ */
73
+ export function attachMeta(response, toolName, detailLevel, sessionTotalTokens) {
74
+ if (process.env['PROVAR_MCP_EMIT_TOKEN_META'] !== 'true')
75
+ return response;
76
+ const meta = {
77
+ tool: toolName,
78
+ detailLevel,
79
+ estimatedTokens: estimateTokens(response),
80
+ };
81
+ if (sessionTotalTokens !== undefined) {
82
+ meta['sessionTotalEstimatedTokens'] = sessionTotalTokens;
83
+ }
84
+ const existing = response.structuredContent ?? {};
85
+ return {
86
+ ...response,
87
+ structuredContent: { ...existing, _meta: meta },
88
+ };
89
+ }
90
+ //# sourceMappingURL=tokenMeta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenMeta.js","sourceRoot":"","sources":["../../../src/mcp/utils/tokenMeta.ts"],"names":[],"mappings":"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"}