@provartesting/provardx-cli 1.5.0-beta.14 → 1.5.0-beta.16
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/lib/mcp/docs/PROVAR_TEST_STEP_REFERENCE.md +2 -2
- package/lib/mcp/prompts/loopPrompts.js +18 -18
- package/lib/mcp/prompts/migrationPrompts.js +10 -10
- package/lib/mcp/security/pathPolicy.js +32 -5
- package/lib/mcp/security/pathPolicy.js.map +1 -1
- package/lib/mcp/server.js +6 -2
- package/lib/mcp/server.js.map +1 -1
- package/lib/mcp/tools/antTools.js +140 -129
- package/lib/mcp/tools/antTools.js.map +1 -1
- package/lib/mcp/tools/automationTools.js +125 -105
- package/lib/mcp/tools/automationTools.js.map +1 -1
- package/lib/mcp/tools/connectionTools.js +17 -13
- package/lib/mcp/tools/connectionTools.js.map +1 -1
- package/lib/mcp/tools/defectTools.js +35 -28
- package/lib/mcp/tools/defectTools.js.map +1 -1
- package/lib/mcp/tools/hierarchyValidate.d.ts +1 -1
- package/lib/mcp/tools/hierarchyValidate.js +127 -42
- package/lib/mcp/tools/hierarchyValidate.js.map +1 -1
- package/lib/mcp/tools/nitroXTools.js +161 -142
- package/lib/mcp/tools/nitroXTools.js.map +1 -1
- package/lib/mcp/tools/pageObjectGenerate.js +47 -40
- package/lib/mcp/tools/pageObjectGenerate.js.map +1 -1
- package/lib/mcp/tools/pageObjectValidate.js +136 -46
- package/lib/mcp/tools/pageObjectValidate.js.map +1 -1
- package/lib/mcp/tools/projectInspect.js +51 -30
- package/lib/mcp/tools/projectInspect.js.map +1 -1
- package/lib/mcp/tools/projectValidateFromPath.js +63 -59
- package/lib/mcp/tools/projectValidateFromPath.js.map +1 -1
- package/lib/mcp/tools/propertiesTools.js +64 -48
- package/lib/mcp/tools/propertiesTools.js.map +1 -1
- package/lib/mcp/tools/qualityHubApiTools.js +48 -44
- package/lib/mcp/tools/qualityHubApiTools.js.map +1 -1
- package/lib/mcp/tools/qualityHubTools.js +76 -52
- package/lib/mcp/tools/qualityHubTools.js.map +1 -1
- package/lib/mcp/tools/rcaTools.js +63 -55
- package/lib/mcp/tools/rcaTools.js.map +1 -1
- package/lib/mcp/tools/testCaseGenerate.js +59 -27
- package/lib/mcp/tools/testCaseGenerate.js.map +1 -1
- package/lib/mcp/tools/testCaseStepTools.js +39 -34
- package/lib/mcp/tools/testCaseStepTools.js.map +1 -1
- package/lib/mcp/tools/testCaseValidate.js +51 -28
- package/lib/mcp/tools/testCaseValidate.js.map +1 -1
- package/lib/mcp/tools/testPlanTools.js +220 -81
- package/lib/mcp/tools/testPlanTools.js.map +1 -1
- package/lib/mcp/tools/testPlanValidate.js +56 -18
- package/lib/mcp/tools/testPlanValidate.js.map +1 -1
- package/lib/mcp/tools/testSuiteValidate.js +37 -11
- package/lib/mcp/tools/testSuiteValidate.js.map +1 -1
- package/lib/services/projectValidation.js +8 -2
- package/lib/services/projectValidation.js.map +1 -1
- package/messages/sf.provar.auth.clear.md +1 -1
- package/messages/sf.provar.mcp.start.md +41 -42
- package/oclif.manifest.json +3 -3
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Provar Test Step Reference
|
|
2
2
|
|
|
3
3
|
> **Source of truth** for AI-assisted test generation in the provardx-cli / Quality Hub MCP toolchain.
|
|
4
|
-
> All examples are sourced from the SalesCloud corpus. The `
|
|
5
|
-
> examples for additional grounding; `
|
|
4
|
+
> All examples are sourced from the SalesCloud corpus. The `provar_qualityhub_examples_retrieve` tool returns real
|
|
5
|
+
> examples for additional grounding; `provar_testcase_validate` enforces all rules documented here.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -13,7 +13,7 @@ function projectHint(projectPath) {
|
|
|
13
13
|
}
|
|
14
14
|
// ── Prompt: provar.loop.generate ─────────────────────────────────────────────
|
|
15
15
|
export function registerLoopGeneratePrompt(server) {
|
|
16
|
-
server.prompt('provar.loop.generate', 'Generate a Provar XML test case from a user story or acceptance criteria. Retrieves corpus examples for grounding, generates the test, writes it to the project, then validates it with
|
|
16
|
+
server.prompt('provar.loop.generate', 'Generate a Provar XML test case from a user story or acceptance criteria. Retrieves corpus examples for grounding, generates the test, writes it to the project, then validates it with provar_testcase_validate.', {
|
|
17
17
|
story: z
|
|
18
18
|
.string()
|
|
19
19
|
.describe('The user story or acceptance criteria to test. Paste the full story text, or a numbered list of acceptance criteria. Include the Salesforce object name and the action being tested (e.g. "As a sales rep, I want to close an opportunity so that revenue is recorded").'),
|
|
@@ -44,7 +44,7 @@ Follow these steps in order:
|
|
|
44
44
|
1. **Extract keywords** — identify the Salesforce object, the action (create/update/close/delete/view), and key
|
|
45
45
|
scenario details from the story. Use these as the query for step 2.
|
|
46
46
|
|
|
47
|
-
2. **Get corpus examples** — call \`
|
|
47
|
+
2. **Get corpus examples** — call \`provar_qualityhub_examples_retrieve\` with the keywords you extracted
|
|
48
48
|
(e.g. "close opportunity" or "create lead"). Use the returned XML examples as the sole reference for
|
|
49
49
|
Provar step structure and argument patterns. Do not invent XML structure from prior knowledge.
|
|
50
50
|
If the response has \`"count": 0\` with a \`"warning"\` field (API unavailable or not configured),
|
|
@@ -67,7 +67,7 @@ Follow these steps in order:
|
|
|
67
67
|
${projectHint(projectPath)}
|
|
68
68
|
${testName ? `Target file name: ${testName}.testcase` : 'Infer the file name from the story (snake_case).'}
|
|
69
69
|
|
|
70
|
-
6. **Validate** — call \`
|
|
70
|
+
6. **Validate** — call \`provar_testcase_validate\` on the saved file. If it reports errors, fix them
|
|
71
71
|
and re-validate until the file passes clean.
|
|
72
72
|
|
|
73
73
|
7. **Report** — summarise:
|
|
@@ -81,7 +81,7 @@ ${story}
|
|
|
81
81
|
|
|
82
82
|
${objectName ? `Primary object: ${objectName}` : ''}
|
|
83
83
|
|
|
84
|
-
Begin with step 1: extract keywords, then call
|
|
84
|
+
Begin with step 1: extract keywords, then call provar_qualityhub_examples_retrieve.`,
|
|
85
85
|
},
|
|
86
86
|
},
|
|
87
87
|
],
|
|
@@ -89,13 +89,13 @@ Begin with step 1: extract keywords, then call provar.qualityhub.examples.retrie
|
|
|
89
89
|
}
|
|
90
90
|
// ── Prompt: provar.loop.fix ───────────────────────────────────────────────────
|
|
91
91
|
export function registerLoopFixPrompt(server) {
|
|
92
|
-
server.prompt('provar.loop.fix', 'Fix a failing Provar test case using the output from
|
|
92
|
+
server.prompt('provar.loop.fix', 'Fix a failing Provar test case using the output from provar_testrun_rca. Reads the current XML, retrieves corpus examples for the failing step type, applies targeted fixes, then re-validates.', {
|
|
93
93
|
testcasePath: z
|
|
94
94
|
.string()
|
|
95
95
|
.describe('Absolute path to the failing .testcase XML file. The file must be readable and within the --allowed-paths configured for this MCP server.'),
|
|
96
96
|
rcaOutput: z
|
|
97
97
|
.string()
|
|
98
|
-
.describe('The RCA report text from
|
|
98
|
+
.describe('The RCA report text from provar_testrun_rca, or a raw failure message from a test run. Include the full error text — step name, error type, and message. The more detail, the better the fix.'),
|
|
99
99
|
projectPath: z
|
|
100
100
|
.string()
|
|
101
101
|
.optional()
|
|
@@ -131,7 +131,7 @@ Follow these steps in order:
|
|
|
131
131
|
- The failure category (e.g. element not found, assertion mismatch, connection error, XML structure error)
|
|
132
132
|
- The specific error message
|
|
133
133
|
|
|
134
|
-
3. **Get corpus examples** — call \`
|
|
134
|
+
3. **Get corpus examples** — call \`provar_qualityhub_examples_retrieve\` with keywords describing the
|
|
135
135
|
failing step's scenario (e.g. "close opportunity UiDoAction" or "assert field value UiAssert").
|
|
136
136
|
Use the returned examples to verify the correct structure for the failing step type.
|
|
137
137
|
If the response has \`"count": 0\` with a \`"warning"\` field, fall back: read the
|
|
@@ -150,7 +150,7 @@ Follow these steps in order:
|
|
|
150
150
|
5. **Apply the fix** — rewrite only the failing step(s). Preserve all other steps unchanged. Write the
|
|
151
151
|
updated XML back to the same file path.
|
|
152
152
|
|
|
153
|
-
6. **Validate** — call \`
|
|
153
|
+
6. **Validate** — call \`provar_testcase_validate\` on the updated file. If new errors appear, fix them
|
|
154
154
|
and re-validate until the file passes clean.
|
|
155
155
|
|
|
156
156
|
7. **Report** — summarise:
|
|
@@ -188,13 +188,13 @@ ${projectPath ? `Provar project root: ${projectPath}` : ''}
|
|
|
188
188
|
|
|
189
189
|
Follow these steps in order:
|
|
190
190
|
|
|
191
|
-
1. **Validate** — call \`
|
|
191
|
+
1. **Validate** — call \`provar_testcase_validate\` on the file. Note all errors and warnings. Do not stop
|
|
192
192
|
here even if the file is valid — continue the review.
|
|
193
193
|
|
|
194
194
|
2. **Read the file** — read the XML to understand the test structure: what object is being tested, what
|
|
195
195
|
actions are performed, and what is being asserted.
|
|
196
196
|
|
|
197
|
-
3. **Get corpus examples** — call \`
|
|
197
|
+
3. **Get corpus examples** — call \`provar_qualityhub_examples_retrieve\` with keywords describing the
|
|
198
198
|
test scenario (e.g. "create opportunity", "close opportunity"). Use the returned examples as a
|
|
199
199
|
quality baseline. If the response has \`"count": 0\` with a \`"warning"\` field, fall back: read
|
|
200
200
|
the \`provar://docs/step-reference\` MCP resource for step type schemas, then continue the review
|
|
@@ -238,7 +238,7 @@ Follow these steps in order:
|
|
|
238
238
|
### Suggested improvements
|
|
239
239
|
Any non-blocking suggestions (e.g. parameterising a hardcoded value that appears more than once).
|
|
240
240
|
|
|
241
|
-
Begin with step 1: call
|
|
241
|
+
Begin with step 1: call provar_testcase_validate on the file at: ${testcasePath}`,
|
|
242
242
|
},
|
|
243
243
|
},
|
|
244
244
|
],
|
|
@@ -256,7 +256,7 @@ export function registerLoopCoveragePrompt(server) {
|
|
|
256
256
|
targetOrg: z
|
|
257
257
|
.string()
|
|
258
258
|
.optional()
|
|
259
|
-
.describe('SF org alias or username. If provided, also queries
|
|
259
|
+
.describe('SF org alias or username. If provided, also queries provar_qualityhub_testcase_retrieve to include Quality Hub tests in the coverage analysis.'),
|
|
260
260
|
}, ({ objectName, projectPath, targetOrg }) => ({
|
|
261
261
|
messages: [
|
|
262
262
|
{
|
|
@@ -283,15 +283,15 @@ Follow these steps in order:
|
|
|
283
283
|
- Which fields are set or asserted
|
|
284
284
|
|
|
285
285
|
${targetOrg
|
|
286
|
-
? `2. **Query Quality Hub** — call \`
|
|
286
|
+
? `2. **Query Quality Hub** — call \`provar_qualityhub_testcase_retrieve\` with target_org="${targetOrg}"
|
|
287
287
|
to retrieve test cases linked to the "${objectName}" object from Quality Hub. Add these to the
|
|
288
288
|
coverage inventory.
|
|
289
289
|
|
|
290
|
-
3. **Get corpus examples** — call \`
|
|
290
|
+
3. **Get corpus examples** — call \`provar_qualityhub_examples_retrieve\` with "${objectName.toLowerCase()}"
|
|
291
291
|
as the query to understand what test patterns exist in the corpus for this object.
|
|
292
292
|
If the response has \`"count": 0\` with a \`"warning"\` field, fall back: read the
|
|
293
293
|
\`provar://docs/step-reference\` MCP resource for step type schemas, then continue.`
|
|
294
|
-
: `2. **Get corpus examples** — call \`
|
|
294
|
+
: `2. **Get corpus examples** — call \`provar_qualityhub_examples_retrieve\` with "${objectName.toLowerCase()}"
|
|
295
295
|
as the query to understand what test patterns exist in the corpus for this object.
|
|
296
296
|
If the response has \`"count": 0\` with a \`"warning"\` field, fall back: read the
|
|
297
297
|
\`provar://docs/step-reference\` MCP resource for step type schemas, then continue.`}
|
|
@@ -372,7 +372,7 @@ This is a **database test**, NOT a Salesforce UI or Apex test. Do not use UiConn
|
|
|
372
372
|
|
|
373
373
|
Follow these steps in order:
|
|
374
374
|
|
|
375
|
-
1. **Get corpus examples** — call \`
|
|
375
|
+
1. **Get corpus examples** — call \`provar_qualityhub_examples_retrieve\` with a query that includes "database DbConnect SqlQuery" plus keywords from the story (e.g. "database SQL Server verify record count"). Use the returned XML examples as the reference for correct step structure.
|
|
376
376
|
If the response has \`"count": 0\` with a \`"warning"\` field (API unavailable or not configured), fall back: read the \`provar://docs/step-reference\` MCP resource — specifically the Database Steps section — for the correct attribute schema, then continue.
|
|
377
377
|
|
|
378
378
|
2. **Generate the test case** — produce valid Provar XML. Apply these database-specific rules:
|
|
@@ -414,7 +414,7 @@ Follow these steps in order:
|
|
|
414
414
|
${projectHint(projectPath)}
|
|
415
415
|
${testName ? `Target file name: ${testName}.testcase` : 'Infer the file name from the story (snake_case).'}
|
|
416
416
|
|
|
417
|
-
4. **Validate** — call \`
|
|
417
|
+
4. **Validate** — call \`provar_testcase_validate\` on the saved file. If it reports errors, fix them and re-validate until the file passes clean.
|
|
418
418
|
|
|
419
419
|
5. **Report** — summarise:
|
|
420
420
|
- Which query/assertion was implemented
|
|
@@ -426,7 +426,7 @@ Follow these steps in order:
|
|
|
426
426
|
|
|
427
427
|
${story}
|
|
428
428
|
|
|
429
|
-
Begin with step 1: call
|
|
429
|
+
Begin with step 1: call provar_qualityhub_examples_retrieve with "database DbConnect SqlQuery" plus keywords from the story above.`,
|
|
430
430
|
},
|
|
431
431
|
},
|
|
432
432
|
],
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
// Source-framework context injected into each migration prompt.
|
|
9
9
|
// Lightweight: just enough to interpret the source. Format knowledge lives
|
|
10
|
-
// in the corpus (
|
|
11
|
-
// (
|
|
10
|
+
// in the corpus (provar_qualityhub_examples_retrieve) and the validator
|
|
11
|
+
// (provar_testcase_validate) — not hardcoded here.
|
|
12
12
|
const CRT_CONTEXT = `
|
|
13
13
|
CRT (Copado Robotic Testing) is a keyword-driven framework built on Robot Framework.
|
|
14
14
|
Tests are authored in QEditor using QWords:
|
|
@@ -56,7 +56,7 @@ function migrationOrchestration(projectPath) {
|
|
|
56
56
|
|
|
57
57
|
Follow these steps in order:
|
|
58
58
|
|
|
59
|
-
1. **Get corpus examples** — call \`
|
|
59
|
+
1. **Get corpus examples** — call \`provar_qualityhub_examples_retrieve\` with keywords that
|
|
60
60
|
describe the source test's main scenario (e.g. "create opportunity", "close case", "convert lead").
|
|
61
61
|
Use the returned examples as few-shot grounding for the Provar XML format and step patterns.
|
|
62
62
|
If the response has \`"count": 0\` with a \`"warning"\` field (API unavailable or not configured),
|
|
@@ -71,7 +71,7 @@ Follow these steps in order:
|
|
|
71
71
|
3. **Write the file** — save the generated XML to the appropriate \`tests/\` subdirectory
|
|
72
72
|
inside the Provar project. ${projectHint}
|
|
73
73
|
|
|
74
|
-
4. **Validate** — call \`
|
|
74
|
+
4. **Validate** — call \`provar_testcase_validate\` on the saved file. If it reports errors,
|
|
75
75
|
fix them and re-validate until the file passes clean.
|
|
76
76
|
|
|
77
77
|
5. **Report** — summarise what was migrated, any steps that could not be mapped (add them
|
|
@@ -80,7 +80,7 @@ Follow these steps in order:
|
|
|
80
80
|
}
|
|
81
81
|
// ── Prompt: provar.migrate.crt ────────────────────────────────────────────────
|
|
82
82
|
export function registerCrtMigrationPrompt(server) {
|
|
83
|
-
server.prompt('provar.migrate.crt', 'Convert a Copado Robotic Testing (CRT) test — either a QWord step sequence or a Robot Framework .robot file — into a Provar XML test case. Retrieves corpus examples for grounding, generates the test case, then validates it with
|
|
83
|
+
server.prompt('provar.migrate.crt', 'Convert a Copado Robotic Testing (CRT) test — either a QWord step sequence or a Robot Framework .robot file — into a Provar XML test case. Retrieves corpus examples for grounding, generates the test case, then validates it with provar_testcase_validate.', {
|
|
84
84
|
source: z
|
|
85
85
|
.string()
|
|
86
86
|
.describe('The CRT test content to migrate. Accepts either: (1) a numbered QWord step sequence (e.g. "Step 1: ClickText Accounts"), or (2) a Robot Framework .robot file with *** Settings ***, *** Keywords ***, and *** Test Cases *** sections.'),
|
|
@@ -114,7 +114,7 @@ ${source}
|
|
|
114
114
|
|
|
115
115
|
${testName ? `Target test case name: ${testName}` : 'Infer the test case name from the source content.'}
|
|
116
116
|
|
|
117
|
-
Begin with step 1: call
|
|
117
|
+
Begin with step 1: call provar_qualityhub_examples_retrieve.`,
|
|
118
118
|
},
|
|
119
119
|
},
|
|
120
120
|
],
|
|
@@ -122,7 +122,7 @@ Begin with step 1: call provar.qualityhub.examples.retrieve.`,
|
|
|
122
122
|
}
|
|
123
123
|
// ── Prompt: provar.migrate.selenium ──────────────────────────────────────────
|
|
124
124
|
export function registerSeleniumMigrationPrompt(server) {
|
|
125
|
-
server.prompt('provar.migrate.selenium', 'Convert a Selenium WebDriver test (Java, Python, or JavaScript) that tests a Salesforce org into a Provar XML test case. Retrieves corpus examples for grounding, generates the test case, then validates it with
|
|
125
|
+
server.prompt('provar.migrate.selenium', 'Convert a Selenium WebDriver test (Java, Python, or JavaScript) that tests a Salesforce org into a Provar XML test case. Retrieves corpus examples for grounding, generates the test case, then validates it with provar_testcase_validate.', {
|
|
126
126
|
source: z
|
|
127
127
|
.string()
|
|
128
128
|
.describe('The Selenium test file content to migrate. Accepts Java (JUnit/TestNG), Python (unittest/pytest), or JavaScript (Jest/Mocha) with selenium-webdriver. Include the full file or the relevant test method(s).'),
|
|
@@ -156,7 +156,7 @@ ${source}
|
|
|
156
156
|
|
|
157
157
|
${testName ? `Target test case name: ${testName}` : 'Infer the test case name from the class and method name.'}
|
|
158
158
|
|
|
159
|
-
Begin with step 1: call
|
|
159
|
+
Begin with step 1: call provar_qualityhub_examples_retrieve.`,
|
|
160
160
|
},
|
|
161
161
|
},
|
|
162
162
|
],
|
|
@@ -164,7 +164,7 @@ Begin with step 1: call provar.qualityhub.examples.retrieve.`,
|
|
|
164
164
|
}
|
|
165
165
|
// ── Prompt: provar.migrate.playwright ────────────────────────────────────────
|
|
166
166
|
export function registerPlaywrightMigrationPrompt(server) {
|
|
167
|
-
server.prompt('provar.migrate.playwright', 'Convert a Playwright test (TypeScript or JavaScript) that tests a Salesforce org into a Provar XML test case. Retrieves corpus examples for grounding, generates the test case, then validates it with
|
|
167
|
+
server.prompt('provar.migrate.playwright', 'Convert a Playwright test (TypeScript or JavaScript) that tests a Salesforce org into a Provar XML test case. Retrieves corpus examples for grounding, generates the test case, then validates it with provar_testcase_validate.', {
|
|
168
168
|
source: z
|
|
169
169
|
.string()
|
|
170
170
|
.describe('The Playwright test file content to migrate. Accepts TypeScript or JavaScript using @playwright/test or the playwright library. Include the full file or the relevant test block(s).'),
|
|
@@ -198,7 +198,7 @@ ${source}
|
|
|
198
198
|
|
|
199
199
|
${testName ? `Target test case name: ${testName}` : 'Infer the test case name from the test() block description.'}
|
|
200
200
|
|
|
201
|
-
Begin with step 1: call
|
|
201
|
+
Begin with step 1: call provar_qualityhub_examples_retrieve.`,
|
|
202
202
|
},
|
|
203
203
|
},
|
|
204
204
|
],
|
|
@@ -41,13 +41,22 @@ export function assertPathAllowed(filePath, allowedPaths) {
|
|
|
41
41
|
resolved = fs.realpathSync(filePath);
|
|
42
42
|
}
|
|
43
43
|
catch {
|
|
44
|
-
// Path doesn't exist —
|
|
45
|
-
|
|
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
|
+
}
|
|
46
55
|
try {
|
|
47
|
-
resolved = path.join(fs.realpathSync(
|
|
56
|
+
resolved = path.join(fs.realpathSync(cur), ...tail);
|
|
48
57
|
}
|
|
49
58
|
catch {
|
|
50
|
-
resolved =
|
|
59
|
+
resolved = full;
|
|
51
60
|
}
|
|
52
61
|
}
|
|
53
62
|
const resolvedAllowed = allowedPaths.map((p) => {
|
|
@@ -58,8 +67,26 @@ export function assertPathAllowed(filePath, allowedPaths) {
|
|
|
58
67
|
return path.resolve(path.normalize(p));
|
|
59
68
|
}
|
|
60
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);
|
|
61
75
|
if (resolvedAllowed.length > 0 &&
|
|
62
|
-
!resolvedAllowed.some((base) =>
|
|
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
|
+
})) {
|
|
63
90
|
throw new PathPolicyError('PATH_NOT_ALLOWED', `Path "${resolved}" is not within allowed paths: [${resolvedAllowed.join(', ')}]`);
|
|
64
91
|
}
|
|
65
92
|
}
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
1
|
+
{"version":3,"file":"pathPolicy.js","sourceRoot":"","sources":["../../../src/mcp/security/pathPolicy.ts"],"names":[],"mappings":"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"}
|
package/lib/mcp/server.js
CHANGED
|
@@ -40,8 +40,12 @@ export function createProvarMcpServer(config) {
|
|
|
40
40
|
version: SERVER_VERSION,
|
|
41
41
|
});
|
|
42
42
|
// ── Sanity-check tool ────────────────────────────────────────────────────────
|
|
43
|
-
server.
|
|
44
|
-
|
|
43
|
+
server.registerTool('provardx_ping', {
|
|
44
|
+
title: 'Ping MCP Server',
|
|
45
|
+
description: 'Sanity-check tool. Echoes back a message with a timestamp. Use this to verify the MCP server is reachable before calling other tools.',
|
|
46
|
+
inputSchema: {
|
|
47
|
+
message: z.string().optional().default('ping').describe('Optional message to echo back'),
|
|
48
|
+
},
|
|
45
49
|
}, ({ message }) => {
|
|
46
50
|
const result = {
|
|
47
51
|
pong: message,
|
package/lib/mcp/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAE1C,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnD,MAAM,cAAc,GAAY,WAAW,CAAC,oBAAoB,CAAyB,CAAC,OAAO,CAAC;AAClG,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,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAC9E,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;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAWxD,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,cAAc;KACxB,CAAC,CAAC;IAEH,gFAAgF;IAChF,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAE1C,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnD,MAAM,cAAc,GAAY,WAAW,CAAC,oBAAoB,CAAyB,CAAC,OAAO,CAAC;AAClG,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,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAC9E,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;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAWxD,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,cAAc;KACxB,CAAC,CAAC;IAEH,gFAAgF;IAChF,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EACT,uIAAuI;QACzI,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,+BAA+B,CAAC;SACzF;KACF,EACD,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;QACd,MAAM,MAAM,GAAG;YACb,IAAI,EAAE,OAAO;YACb,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,MAAM,EAAE,cAAc,cAAc,EAAE;YACtC,eAAe,EAAE,MAAM,CAAC,YAAY,EAAE,eAAe,IAAI,KAAK;YAC9D,aAAa,EAAE,MAAM,CAAC,YAAY,EAAE,aAAa,IAAI,IAAI;YACzD,aAAa,EAAE,MAAM,CAAC,YAAY,EAAE,aAAa,IAAI,IAAI;SAC1D,CAAC;QACF,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,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtC,0BAA0B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,4BAA4B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,0BAA0B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE3C,gFAAgF;IAChF,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE3B,gFAAgF;IAChF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACtE,MAAM,CAAC,QAAQ,CACb,uBAAuB,EACvB,8BAA8B,EAC9B;QACE,WAAW,EACT,oNAAoN;QACtN,QAAQ,EAAE,eAAe;KAC1B,EACD,GAAG,EAAE;QACH,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,+BAA+B,CAAC,EAAE,OAAO,CAAC,CAAC;YACtF,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,8BAA8B;wBACnC,QAAQ,EAAE,eAAe;wBACzB,IAAI,EAAE,OAAO;qBACd;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,8BAA8B;wBACnC,QAAQ,EAAE,eAAe;wBACzB,IAAI,EAAE,oLAAoL;qBAC3L;iBACF;aACF,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
|