mcprigor 1.0.0-rc.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 (164) hide show
  1. package/LICENSE +17 -0
  2. package/README.md +233 -0
  3. package/dist/assertions.d.ts +4 -0
  4. package/dist/assertions.d.ts.map +1 -0
  5. package/dist/assertions.js +101 -0
  6. package/dist/assertions.js.map +1 -0
  7. package/dist/author.d.ts +57 -0
  8. package/dist/author.d.ts.map +1 -0
  9. package/dist/author.js +134 -0
  10. package/dist/author.js.map +1 -0
  11. package/dist/canonical.d.ts +4 -0
  12. package/dist/canonical.d.ts.map +1 -0
  13. package/dist/canonical.js +17 -0
  14. package/dist/canonical.js.map +1 -0
  15. package/dist/cli.d.ts +3 -0
  16. package/dist/cli.d.ts.map +1 -0
  17. package/dist/cli.js +265 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/contract.d.ts +28 -0
  20. package/dist/contract.d.ts.map +1 -0
  21. package/dist/contract.js +138 -0
  22. package/dist/contract.js.map +1 -0
  23. package/dist/data.d.ts +24 -0
  24. package/dist/data.d.ts.map +1 -0
  25. package/dist/data.js +367 -0
  26. package/dist/data.js.map +1 -0
  27. package/dist/discovery.d.ts +6 -0
  28. package/dist/discovery.d.ts.map +1 -0
  29. package/dist/discovery.js +82 -0
  30. package/dist/discovery.js.map +1 -0
  31. package/dist/errors.d.ts +19 -0
  32. package/dist/errors.d.ts.map +1 -0
  33. package/dist/errors.js +40 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/extension-host.d.ts +20 -0
  36. package/dist/extension-host.d.ts.map +1 -0
  37. package/dist/extension-host.js +52 -0
  38. package/dist/extension-host.js.map +1 -0
  39. package/dist/extension-sdk.d.ts +22 -0
  40. package/dist/extension-sdk.d.ts.map +1 -0
  41. package/dist/extension-sdk.js +3 -0
  42. package/dist/extension-sdk.js.map +1 -0
  43. package/dist/extension-worker.d.ts +2 -0
  44. package/dist/extension-worker.d.ts.map +1 -0
  45. package/dist/extension-worker.js +27 -0
  46. package/dist/extension-worker.js.map +1 -0
  47. package/dist/extensions.d.ts +15 -0
  48. package/dist/extensions.d.ts.map +1 -0
  49. package/dist/extensions.js +60 -0
  50. package/dist/extensions.js.map +1 -0
  51. package/dist/imports.d.ts +7 -0
  52. package/dist/imports.d.ts.map +1 -0
  53. package/dist/imports.js +41 -0
  54. package/dist/imports.js.map +1 -0
  55. package/dist/index.d.ts +29 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +28 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/language.d.ts +34 -0
  60. package/dist/language.d.ts.map +1 -0
  61. package/dist/language.js +102 -0
  62. package/dist/language.js.map +1 -0
  63. package/dist/loader.d.ts +4 -0
  64. package/dist/loader.d.ts.map +1 -0
  65. package/dist/loader.js +51 -0
  66. package/dist/loader.js.map +1 -0
  67. package/dist/parity.d.ts +23 -0
  68. package/dist/parity.d.ts.map +1 -0
  69. package/dist/parity.js +77 -0
  70. package/dist/parity.js.map +1 -0
  71. package/dist/path.d.ts +3 -0
  72. package/dist/path.d.ts.map +1 -0
  73. package/dist/path.js +71 -0
  74. package/dist/path.js.map +1 -0
  75. package/dist/qa-advanced.d.ts +8 -0
  76. package/dist/qa-advanced.d.ts.map +1 -0
  77. package/dist/qa-advanced.js +239 -0
  78. package/dist/qa-advanced.js.map +1 -0
  79. package/dist/qa-language.d.ts +4 -0
  80. package/dist/qa-language.d.ts.map +1 -0
  81. package/dist/qa-language.js +385 -0
  82. package/dist/qa-language.js.map +1 -0
  83. package/dist/qa-loader.d.ts +4 -0
  84. package/dist/qa-loader.d.ts.map +1 -0
  85. package/dist/qa-loader.js +22 -0
  86. package/dist/qa-loader.js.map +1 -0
  87. package/dist/redact.d.ts +7 -0
  88. package/dist/redact.d.ts.map +1 -0
  89. package/dist/redact.js +63 -0
  90. package/dist/redact.js.map +1 -0
  91. package/dist/replay.d.ts +17 -0
  92. package/dist/replay.d.ts.map +1 -0
  93. package/dist/replay.js +48 -0
  94. package/dist/replay.js.map +1 -0
  95. package/dist/reporters.d.ts +6 -0
  96. package/dist/reporters.d.ts.map +1 -0
  97. package/dist/reporters.js +52 -0
  98. package/dist/reporters.js.map +1 -0
  99. package/dist/runner.d.ts +16 -0
  100. package/dist/runner.d.ts.map +1 -0
  101. package/dist/runner.js +304 -0
  102. package/dist/runner.js.map +1 -0
  103. package/dist/schema.d.ts +446 -0
  104. package/dist/schema.d.ts.map +1 -0
  105. package/dist/schema.js +117 -0
  106. package/dist/schema.js.map +1 -0
  107. package/dist/session.d.ts +5 -0
  108. package/dist/session.d.ts.map +1 -0
  109. package/dist/session.js +111 -0
  110. package/dist/session.js.map +1 -0
  111. package/dist/snapshots.d.ts +28 -0
  112. package/dist/snapshots.d.ts.map +1 -0
  113. package/dist/snapshots.js +87 -0
  114. package/dist/snapshots.js.map +1 -0
  115. package/dist/starter.d.ts +3 -0
  116. package/dist/starter.d.ts.map +1 -0
  117. package/dist/starter.js +34 -0
  118. package/dist/starter.js.map +1 -0
  119. package/dist/state.d.ts +13 -0
  120. package/dist/state.d.ts.map +1 -0
  121. package/dist/state.js +29 -0
  122. package/dist/state.js.map +1 -0
  123. package/dist/trace.d.ts +57 -0
  124. package/dist/trace.d.ts.map +1 -0
  125. package/dist/trace.js +94 -0
  126. package/dist/trace.js.map +1 -0
  127. package/dist/types.d.ts +245 -0
  128. package/dist/types.d.ts.map +1 -0
  129. package/dist/types.js +2 -0
  130. package/dist/types.js.map +1 -0
  131. package/dist/workspace.d.ts +10 -0
  132. package/dist/workspace.d.ts.map +1 -0
  133. package/dist/workspace.js +144 -0
  134. package/dist/workspace.js.map +1 -0
  135. package/docs/CLI-REFERENCE.md +167 -0
  136. package/docs/COMPATIBILITY.md +42 -0
  137. package/docs/CONTRACT-DRIFT.md +42 -0
  138. package/docs/DATA-AND-REUSE.md +213 -0
  139. package/docs/DATA-ENGINEERING.md +96 -0
  140. package/docs/ENGINEER-SETUP.md +176 -0
  141. package/docs/ERROR-MODEL.md +24 -0
  142. package/docs/EVIDENCE.md +58 -0
  143. package/docs/EXTENSION-SDK.md +76 -0
  144. package/docs/FILE-EXTENSION.md +52 -0
  145. package/docs/GETTING-STARTED.md +126 -0
  146. package/docs/GUIDED-AUTHORING.md +80 -0
  147. package/docs/LANDSCAPE.md +81 -0
  148. package/docs/LANGUAGE-SPEC.md +317 -0
  149. package/docs/MCP-NATIVE.md +111 -0
  150. package/docs/PLAIN-LANGUAGE-COOKBOOK.md +219 -0
  151. package/docs/QA-GUIDE.md +128 -0
  152. package/docs/QA-WORKSPACE.md +78 -0
  153. package/docs/README.md +55 -0
  154. package/docs/SECURITY-AND-RETENTION.md +37 -0
  155. package/docs/SNAPSHOTS-AND-REPLAY.md +85 -0
  156. package/docs/SPECIFICATION.md +178 -0
  157. package/docs/STATE-AND-DEPENDENCIES.md +106 -0
  158. package/docs/TRANSPORT-PARITY.md +98 -0
  159. package/docs/TROUBLESHOOTING.md +199 -0
  160. package/editors/mcpr-language.json +16 -0
  161. package/package.json +70 -0
  162. package/workspace-assets/app.js +1 -0
  163. package/workspace-assets/index.html +1 -0
  164. package/workspace-assets/style.css +1 -0
@@ -0,0 +1,42 @@
1
+ # Contract Drift Analysis
2
+
3
+ MCP Rigor explains how a live MCP surface changed instead of only reporting a different fingerprint.
4
+
5
+ ## Check a lock against a live server
6
+
7
+ ```bash
8
+ mcprigor contract-check mcp.lock.yaml --target server.mcpr
9
+ ```
10
+
11
+ This is read-only. It discovers the server, compares it with the lock, and exits with status `1` when breaking changes exist.
12
+
13
+ Markdown for a pull-request comment:
14
+
15
+ ```bash
16
+ mcprigor contract-check mcp.lock.yaml --target server.mcpr --markdown --out contract-drift.md
17
+ ```
18
+
19
+ ## Offline comparison
20
+
21
+ ```bash
22
+ mcprigor contract-diff old.lock.yaml new.lock.yaml
23
+ mcprigor contract-diff old.lock.yaml new.lock.yaml --markdown
24
+ ```
25
+
26
+ ## Explicit update
27
+
28
+ ```bash
29
+ mcprigor contract-update mcp.lock.yaml --target server.mcpr
30
+ ```
31
+
32
+ The diff is displayed before the newly discovered contract replaces the lock. Review breaking changes before committing it.
33
+
34
+ ## Classifications
35
+
36
+ **Breaking:** an operation or capability was removed; a required input was added; a known property was removed; a type changed; an enum option was removed; or a required prompt argument was added.
37
+
38
+ **Potentially breaking:** protocol version, description, or ambiguous output/schema behavior changed.
39
+
40
+ **Non-breaking:** an operation/capability was added; an optional input was added; a required input became optional; or an enum option was added.
41
+
42
+ Findings use stable `MCP-DRIFT-*` codes and deterministic ordering. Complex JSON Schema implication is classified conservatively rather than overstating compatibility. Contract drift is application compatibility evidence, not formal MCP certification.
@@ -0,0 +1,213 @@
1
+ # Reuse, Utility Functions, and Data-Driven Testing
2
+
3
+ This guide is for QA authors first and extension developers second.
4
+
5
+ ## Reusable flows
6
+
7
+ A flow is a named group of ordinary test actions:
8
+
9
+ ```text
10
+ Flow: "Verify addition"
11
+ Inputs: a, b, expected
12
+
13
+ Call tool "add" with:
14
+ a: "${a}"
15
+ b: "${b}"
16
+
17
+ Expect "structuredContent.sum" equals "${expected}"
18
+ ```
19
+
20
+ Use it from any test:
21
+
22
+ ```text
23
+ Use flow "Verify addition" with:
24
+ a: 2
25
+ b: 3
26
+ expected: 5
27
+ ```
28
+
29
+ Flows can use other flows. Recursive flow calls are rejected before execution. Each invocation has its own prefixed variables, so reused actions do not overwrite another invocation's inputs.
30
+
31
+ Flows may contain section markers:
32
+
33
+ ```text
34
+ Flow: "Create and remove customer"
35
+ Inputs: email
36
+
37
+ Setup:
38
+ Call tool "prepare_tenant"
39
+
40
+ Steps:
41
+ Call tool "create_customer" with:
42
+ email: "${email}"
43
+
44
+ Cleanup:
45
+ Call tool "remove_customer" with:
46
+ email: "${email}"
47
+ ```
48
+
49
+ Cleanup actions are marked as guaranteed and are attempted after a preceding action fails. Keep cleanup idempotent.
50
+
51
+ ## Deterministic built-in utilities
52
+
53
+ ```text
54
+ Set "email" using "lowercase" with:
55
+ value: "${row.Email}"
56
+ ```
57
+
58
+ Built-ins:
59
+
60
+ - `lowercase`, `uppercase`, `trim`
61
+ - `join`, `replace`, `length`
62
+ - `number`, `text`, `json`, `round`
63
+ - `urlEncode`, `base64`, `hash`
64
+
65
+ They have no network or file access and do not use random values or the current time.
66
+
67
+ ## Custom utility functions
68
+
69
+ Declare a reviewed module:
70
+
71
+ ```text
72
+ Functions: tests/qa-functions.mjs
73
+ ```
74
+
75
+ ```javascript
76
+ export function calculateTax({ amount, rate }) {
77
+ return Math.round(amount * rate * 100) / 100;
78
+ }
79
+ ```
80
+
81
+ Use it exactly like a built-in:
82
+
83
+ ```text
84
+ Set "expectedTax" using "calculateTax" with:
85
+ amount: "${row.amount}"
86
+ rate: 0.08
87
+ ```
88
+
89
+ Custom code is disabled by default:
90
+
91
+ ```bash
92
+ mcprigor test tax.mcpr --allow-custom-code
93
+ ```
94
+
95
+ Enabled modules run in constrained workers by default, with manifest checks, explicit permissions, JSON-only boundaries, memory limits, and timeouts. Worker isolation reduces risk but is not a hard sandbox for hostile code. Review, pin, and allowlist every extension before CI use. See [Extension SDK](EXTENSION-SDK.md).
96
+
97
+ ## Inline examples
98
+
99
+ ```text
100
+ Test: "Calculator examples"
101
+ For each row:
102
+ | caseId | a | b | expected |
103
+ | basic | 2 | 3 | 5 |
104
+ | larger | 20 | 22 | 42 |
105
+
106
+ Use flow "Verify addition" with:
107
+ a: "${row.a}"
108
+ b: "${row.b}"
109
+ expected: "${row.expected}"
110
+ ```
111
+
112
+ Each row becomes an isolated test and report entry. `caseId` or `id` provides its display ID.
113
+
114
+ ## Files
115
+
116
+ ```text
117
+ For each row in "data/cases.csv"
118
+ For each row in "data/cases.json"
119
+ For each row in "data/cases.yaml"
120
+ For each row in "data/cases.xlsx" from sheet "Regression"
121
+ ```
122
+
123
+ JSON/YAML files must contain an array of objects. Named source configuration can select a nested `path`.
124
+
125
+ ## Named data sources
126
+
127
+ ```text
128
+ Data source: "regression cases"
129
+ provider: json
130
+ file: data/cases.json
131
+ path: cases
132
+
133
+ Test: "Regression matrix"
134
+ For each row from "regression cases"
135
+ # actions using ${row.column}
136
+ ```
137
+
138
+ Providers:
139
+
140
+ - `inline`
141
+ - `csv`
142
+ - `json`
143
+ - `yaml`
144
+ - `excel`
145
+ - `rest`
146
+ - `google-sheets`
147
+ - `sql` through a reviewed provider module
148
+ - `plugin` for other systems
149
+
150
+ ## REST
151
+
152
+ ```text
153
+ Data source: "API cases"
154
+ provider: rest
155
+ url: https://qa.example.com/cases
156
+ path: cases
157
+ headers:
158
+ Authorization: "Bearer ${env.CASES_TOKEN}"
159
+ ```
160
+
161
+ Remote sources require explicit permission:
162
+
163
+ ```bash
164
+ mcprigor test api.mcpr --allow-remote-data
165
+ ```
166
+
167
+ Requests have a ten-second deadline. Responses must be JSON row arrays. Credential-shaped fields are redacted from reports.
168
+
169
+ ## Google Sheets
170
+
171
+ ```text
172
+ Data source: "Sheet cases"
173
+ provider: google-sheets
174
+ spreadsheetId: "${env.SHEET_ID}"
175
+ range: Regression!A1:F100
176
+ accessToken: "${env.GOOGLE_ACCESS_TOKEN}"
177
+ ```
178
+
179
+ Or provide `apiKey` for a public sheet. Google Sheets is fetched through the Values REST API and requires `--allow-remote-data`.
180
+
181
+ ## SQL and custom providers
182
+
183
+ Database drivers are intentionally not bundled. Register a reviewed provider module:
184
+
185
+ ```text
186
+ Data source: "Database cases"
187
+ provider: sql
188
+ module: test/providers/postgres-cases.mjs
189
+ query: SELECT case_id, input, expected FROM qa_cases
190
+ ```
191
+
192
+ The module implements:
193
+
194
+ ```javascript
195
+ export default {
196
+ async load(config, context) {
197
+ // Use parameterized, read-only queries and return object rows.
198
+ return rows;
199
+ }
200
+ }
201
+ ```
202
+
203
+ Run with `--allow-custom-code`. The same plugin interface can connect Jira, Xray, TestRail, or internal systems.
204
+
205
+ ## Safety and reproducibility
206
+
207
+ - Default maximum: 1,000 rows; set a lower ceiling with `--max-rows`.
208
+ - Local data files have a 10 MiB limit.
209
+ - Every source gets a SHA-256 fingerprint.
210
+ - Every expanded row stores its source, row number, row ID, and source fingerprint.
211
+ - One MCP session is created per row by default.
212
+ - Remote and executable providers are off by default.
213
+ - Data values can contain sensitive business information; avoid placing secrets in `caseId` because IDs appear in reports.
@@ -0,0 +1,96 @@
1
+ # Better Data Engineering
2
+
3
+ Data providers can now feed a deterministic transformation pipeline before rows become isolated tests:
4
+
5
+ ```text
6
+ provider → cache → typed coercion → join → derived columns → filter → sample → row limit
7
+ ```
8
+
9
+ ## Typed columns and validation
10
+
11
+ ```yaml
12
+ provider: csv
13
+ file: customers.csv
14
+ columns:
15
+ customerId:
16
+ type: string
17
+ required: true
18
+ spend:
19
+ type: number
20
+ required: true
21
+ active: boolean
22
+ joinedAt: date
23
+ tier:
24
+ type: string
25
+ enum: [gold, silver, bronze]
26
+ ```
27
+
28
+ Types are `string`, `number`, `boolean`, `date`, and `json`. Errors include the row number and column name. Dates normalize to ISO 8601. Numbers must be finite.
29
+
30
+ ## Derived columns
31
+
32
+ ```yaml
33
+ derive:
34
+ fullName: "${firstName} ${lastName}"
35
+ caseLabel: "${customerId}:${tier}"
36
+ ```
37
+
38
+ Derivation is deterministic template substitution; it does not execute code.
39
+
40
+ ## Filtering
41
+
42
+ ```yaml
43
+ where:
44
+ active: true
45
+ spend:
46
+ greaterThan: 100
47
+ tier:
48
+ in: [gold, silver]
49
+ ```
50
+
51
+ Available predicates: `equals`, `notEquals`, `in`, `matches`, `greaterThan`, and `lessThan`. Multiple columns and predicates are ANDed.
52
+
53
+ ## Deterministic sampling
54
+
55
+ ```yaml
56
+ sample:
57
+ count: 25
58
+ seed: 2025
59
+ ```
60
+
61
+ Other modes:
62
+
63
+ ```yaml
64
+ sample: { first: 10 }
65
+ sample: { last: 10 }
66
+ sample: { every: 5 }
67
+ ```
68
+
69
+ Seeded sampling preserves original source order after selection so test order is stable.
70
+
71
+ ## Joins
72
+
73
+ ```yaml
74
+ provider: csv
75
+ file: orders.csv
76
+ join:
77
+ provider: json
78
+ file: customers.json
79
+ on: customerId
80
+ kind: left
81
+ prefix: customer_
82
+ ```
83
+
84
+ `inner` and `left` joins are supported. The join key must be named by `on`. Prefixing avoids column collisions. Base-row values win on collision.
85
+
86
+ ## Explicit provider caching
87
+
88
+ ```yaml
89
+ provider: rest
90
+ url: https://qa.example.com/cases
91
+ cache: true
92
+ ```
93
+
94
+ Caching is opt-in, process-local, and keyed by provider configuration. Cached rows are defensively cloned. It does not persist credentials or data to disk.
95
+
96
+ Existing safety gates remain: remote sources need `--allow-remote-data`, SQL/custom providers need `--allow-custom-code`, and `--max-rows` caps the transformed dataset.
@@ -0,0 +1,176 @@
1
+ # Engineer setup and CI
2
+
3
+ This guide covers the configuration engineers normally prepare once so QA authors can focus on scenarios.
4
+
5
+ ## Recommended repository layout
6
+
7
+ ```text
8
+ acceptance-tests/
9
+ package.json
10
+ tests/
11
+ smoke.mcpr
12
+ regression.mcpr
13
+ parity.mcpr
14
+ shared-flows.mcpr
15
+ data/
16
+ reports/
17
+ .mcprigor/
18
+ ```
19
+
20
+ Add generated evidence and local reports to `.gitignore` unless your policy requires versioning them:
21
+
22
+ ```gitignore
23
+ .mcprigor/
24
+ reports/
25
+ *.snap.actual.json
26
+ ```
27
+
28
+ Commit contract locks and approved snapshot expectations when they are part of review.
29
+
30
+ ## Configure a stdio target
31
+
32
+ ```text
33
+ MCP Test 1
34
+ Suite: "Customer acceptance tests"
35
+ Server: node ../customer-server/dist/server.js
36
+
37
+ Server options:
38
+ cwd: ../customer-server
39
+ env:
40
+ NODE_ENV: test
41
+ ```
42
+
43
+ MCP Rigor starts the command without a shell. Keep server shutdown deterministic and ensure descendants exit when stdin closes or the parent terminates.
44
+
45
+ ## Configure Streamable HTTP
46
+
47
+ ```text
48
+ MCP URL: https://qa.example.com/mcp
49
+
50
+ Server options:
51
+ headers:
52
+ Authorization: "Bearer ${env.MCP_TOKEN}"
53
+ ```
54
+
55
+ Provide secrets through CI variables:
56
+
57
+ ```bash
58
+ MCP_TOKEN="$QA_MCP_TOKEN" npx mcprigor test tests/smoke.mcpr
59
+ ```
60
+
61
+ ## Give QA authors stable operations
62
+
63
+ Prefer:
64
+
65
+ - clear tool and argument descriptions;
66
+ - structured output for business assertions;
67
+ - stable resource URIs;
68
+ - deterministic fixture data;
69
+ - test-only cleanup operations;
70
+ - generated IDs returned in explicit fields;
71
+ - server errors with actionable MCP messages.
72
+
73
+ Avoid requiring QA users to assert entire text blobs or volatile metadata.
74
+
75
+ ## Add package scripts
76
+
77
+ ```json
78
+ {
79
+ "scripts": {
80
+ "mcp:check": "mcprigor check tests/smoke.mcpr",
81
+ "mcp:test": "mcprigor test tests/smoke.mcpr",
82
+ "mcp:report": "mcprigor test tests/regression.mcpr --html reports/mcp.html",
83
+ "mcp:parity": "mcprigor parity tests/parity.mcpr"
84
+ }
85
+ }
86
+ ```
87
+
88
+ ## GitHub Actions
89
+
90
+ ```yaml
91
+ name: MCP acceptance tests
92
+
93
+ on:
94
+ pull_request:
95
+ push:
96
+ branches: [main]
97
+
98
+ jobs:
99
+ mcp-tests:
100
+ runs-on: ubuntu-latest
101
+ timeout-minutes: 10
102
+ steps:
103
+ - uses: actions/checkout@v4
104
+ - uses: actions/setup-node@v4
105
+ with:
106
+ node-version: 20
107
+ cache: npm
108
+ - run: npm ci
109
+ - run: npm run mcp:check
110
+ - run: >-
111
+ npx mcprigor test tests/regression.mcpr
112
+ --junit reports/mcp.xml
113
+ --evidence .mcprigor/ci-${{ github.run_id }}
114
+ env:
115
+ MCP_TOKEN: ${{ secrets.QA_MCP_TOKEN }}
116
+ - uses: actions/upload-artifact@v4
117
+ if: always()
118
+ with:
119
+ name: mcp-evidence
120
+ path: |
121
+ reports/
122
+ .mcprigor/
123
+ retention-days: 7
124
+ ```
125
+
126
+ ## Contract drift in pull requests
127
+
128
+ Create a baseline once:
129
+
130
+ ```bash
131
+ mcprigor discover tests/server.mcpr --out mcp.lock.yaml
132
+ ```
133
+
134
+ Then check it in CI:
135
+
136
+ ```bash
137
+ mcprigor contract-check mcp.lock.yaml \
138
+ --target tests/server.mcpr \
139
+ --markdown \
140
+ --out reports/contract-drift.md
141
+ ```
142
+
143
+ Update a baseline only after review:
144
+
145
+ ```bash
146
+ mcprigor contract-update mcp.lock.yaml --target tests/server.mcpr
147
+ ```
148
+
149
+ ## Transport parity
150
+
151
+ Engineers configure connections once:
152
+
153
+ ```text
154
+ Compare target "Local": node ../server/dist/server.js
155
+ Compare target "QA": https://qa.example.com/mcp
156
+ ```
157
+
158
+ QA authors then add ordinary tests. CI runs:
159
+
160
+ ```bash
161
+ mcprigor parity tests/parity.mcpr --markdown --out reports/parity.md
162
+ ```
163
+
164
+ ## Production adoption checklist
165
+
166
+ - Pin MCP Rigor and the MCP SDK through the lockfile.
167
+ - Run `check` before server execution.
168
+ - Use dedicated nonproduction accounts and data.
169
+ - Set explicit CI timeouts and row limits.
170
+ - Keep remote data and extensions disabled unless required.
171
+ - Define contract-drift approval ownership.
172
+ - Set evidence access, retention, and deletion rules.
173
+ - Verify each required Node, OS, protocol, and transport combination.
174
+ - Test one intentional failure and server-shutdown path.
175
+
176
+ See [compatibility](COMPATIBILITY.md) and [security and retention](SECURITY-AND-RETENTION.md).
@@ -0,0 +1,24 @@
1
+ # Stable Error Model
2
+
3
+ MCP Rigor failures carry a stable code, category, sanitized message, and QA-facing action.
4
+
5
+ | Category | Baseline code | QA action |
6
+ |---|---|---|
7
+ | configuration | `MCP-CONFIG-000` | Check suite target and settings. |
8
+ | language compilation | `MCP-LANG-000` | Correct the highlighted statement. |
9
+ | data loading | `MCP-DATA-000` | Check the named source, row, and column. |
10
+ | extension | `MCP-EXT-000` | Review manifest, permission, and export. |
11
+ | server spawn | `MCP-SPAWN-000` | Check command and working directory. |
12
+ | initialization | `MCP-INIT-000` | Inspect why MCP initialization did not finish. |
13
+ | transport | `MCP-TRANSPORT-000` | Check process/HTTP connection and server logs. |
14
+ | MCP error | `MCP-REMOTE-000` | Review the server's MCP code and message. |
15
+ | schema | `MCP-SCHEMA-000` | Compare the result with the required schema. |
16
+ | assertion | `MCP-ASSERT-000` | Compare expected path/value with response. |
17
+ | timeout | `MCP-TIMEOUT-000` | Inspect server performance or explicit timeout. |
18
+ | cancellation | `MCP-CANCEL-000` | The operation was stopped before completion. |
19
+ | cleanup | `MCP-CLEANUP-000` | Inspect cleanup steps and server shutdown. |
20
+ | internal | `MCP-INTERNAL-000` | Preserve sanitized evidence and report the bug. |
21
+
22
+ Specific existing codes remain stable within these categories. APIs expose `classifyFailure()`, `formatFailure()`, `RigorError`, and `FAILURE_CODES`. New codes may be added, but released codes are not repurposed.
23
+
24
+ Terminal formatting removes control sequences before display. Private causes and stacks are not part of the stable user-facing contract.
@@ -0,0 +1,58 @@
1
+ # Protocol Traces and Failure Evidence
2
+
3
+ MCP Rigor can retain a sanitized, correlated account of a test run:
4
+
5
+ ```bash
6
+ mcprigor test tests.mcpr --evidence .mcprigor/run-001
7
+ ```
8
+
9
+ This is currently an **MCP SDK/API-boundary trace**, not a raw byte capture. It records what MCP Rigor sends to and receives from the official SDK transport boundary.
10
+
11
+ ## Bundle contents
12
+
13
+ ```text
14
+ .mcprigor/run-001/
15
+ manifest.json
16
+ result.json
17
+ trace.jsonl
18
+ trace.normalized.jsonl
19
+ ```
20
+
21
+ `trace.jsonl` contains ordered lifecycle, request, response, error, close, and bounded diagnostic events. Each event includes a toolkit-owned sequence, request correlation ID, test ID, step name, method, and sanitized data.
22
+
23
+ `trace.normalized.jsonl` removes elapsed timing and known volatile values while preserving semantic ordering. Its SHA-256 fingerprint appears in `manifest.json`.
24
+
25
+ ## Inspect and compare
26
+
27
+ ```bash
28
+ mcprigor evidence-show .mcprigor/run-001
29
+ mcprigor evidence-compare .mcprigor/run-001 .mcprigor/run-002
30
+ ```
31
+
32
+ Comparison checks the result and normalized trace fingerprints. Matching fingerprints indicate semantically identical evidence under the current normalization policy.
33
+
34
+ ## Events
35
+
36
+ - `session.connect.start`
37
+ - `session.connect.success`
38
+ - `request`
39
+ - `response`
40
+ - `error`
41
+ - `session.close`
42
+ - `diagnostic`
43
+
44
+ Request and terminal response/error events share `requestId`. Test and step fields tie protocol activity back to readable acceptance tests.
45
+
46
+ ## Security
47
+
48
+ Redaction happens before events enter the recorder. MCP Rigor removes configured secrets, values under credential-shaped keys, and bearer tokens. Reports should still be handled as potentially sensitive because ordinary business data may remain.
49
+
50
+ Recommended practices:
51
+
52
+ - store evidence as short-lived CI artifacts;
53
+ - do not put tokens or regulated data in assertions/test names;
54
+ - review custom function and provider output;
55
+ - limit artifact access;
56
+ - delete bundles after the investigation or retention period.
57
+
58
+ The evidence hash is an integrity aid, not a digital signature or legal attestation.
@@ -0,0 +1,76 @@
1
+ # Isolated Extension SDK
2
+
3
+ MCP Rigor 0.13 changes custom functions and data providers from direct host imports to worker-isolated extensions.
4
+
5
+ ```js
6
+ export const manifest = {
7
+ schemaVersion: 1,
8
+ name: "customer-utilities",
9
+ version: "1.0.0",
10
+ permissions: [],
11
+ functions: ["normalizeCustomer"],
12
+ provider: true
13
+ };
14
+
15
+ export function normalizeCustomer({ value }) {
16
+ return String(value).trim().toUpperCase();
17
+ }
18
+
19
+ export const provider = {
20
+ async load(config) {
21
+ return [{ id: "case-1", expected: config.expected }];
22
+ }
23
+ };
24
+ ```
25
+
26
+ Enable reviewed extensions as before:
27
+
28
+ ```bash
29
+ mcprigor test suite.mcpr --allow-custom-code
30
+ ```
31
+
32
+ Execution now occurs in a dedicated Node worker with:
33
+
34
+ - a reviewed versioned manifest;
35
+ - explicit permissions;
36
+ - wall-clock timeout and forced termination;
37
+ - a 64 MiB default V8 old-generation limit;
38
+ - JSON-compatible inputs and outputs only;
39
+ - stable `MCP-EXT-1xx` diagnostics;
40
+ - no automatic fallback to direct host import.
41
+
42
+ Manifest permissions currently recognized:
43
+
44
+ - `environment`
45
+ - `filesystem-read`
46
+ - `network`
47
+
48
+ A requested permission must be granted by suite configuration. Permissions describe review intent in the current worker backend; they are not yet a complete host-brokered filesystem/network sandbox.
49
+
50
+ ## Public SDK
51
+
52
+ ```js
53
+ import { defineExtension, defineManifest } from "mcprigor";
54
+
55
+ export const manifest = defineManifest({
56
+ schemaVersion: 1,
57
+ name: "example",
58
+ version: "1.0.0",
59
+ permissions: [],
60
+ functions: ["decorate"]
61
+ });
62
+
63
+ export default defineExtension({ manifest });
64
+ ```
65
+
66
+ Programmatic host APIs:
67
+
68
+ - `inspectExtension()`
69
+ - `callIsolatedFunction()`
70
+ - `callIsolatedProvider()`
71
+
72
+ ## Legacy compatibility
73
+
74
+ Existing modules can still execute directly only when the suite explicitly selects `extensions.unsafeLegacy: true` or a provider uses `unsafeLegacy: true`. This mode has the full authority of the MCP Rigor process and should only be used temporarily while migrating.
75
+
76
+ Worker threads improve failure and capability isolation, but they are not a hard hostile-code security boundary. Truly untrusted extensions should run in a separately secured process or container.