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
package/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Copyright 2026 LoopMCP contributors
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,233 @@
1
+ # MCP Rigor
2
+
3
+ **Plain-language testing for Model Context Protocol servers.**
4
+
5
+ MCP Rigor lets QA teams test MCP tools, resources, prompts, contracts, and transports without writing test code. Tests are deterministic: no AI model interprets the wording. Plain-language files use `.mcpr` to avoid collision with existing `.mcp` formats.
6
+
7
+ > Status: `1.0.0-rc.1` release candidate. Node.js 20 or 22 is required.
8
+
9
+ ## Install
10
+
11
+ In your test project:
12
+
13
+ ```bash
14
+ npm install --save-dev mcprigor
15
+ ```
16
+
17
+ Use `npx mcprigor` in commands below, or install globally to use `mcprigor` directly.
18
+
19
+ ## Write your first test
20
+
21
+ Create `calculator.mcpr`:
22
+
23
+ ```text
24
+ MCP Test 1
25
+
26
+ Suite: "Calculator acceptance tests"
27
+ Server: node dist/server.js
28
+
29
+ Test: "Adding 20 and 22 gives 42"
30
+ Call tool "add" with:
31
+ a: 20
32
+ b: 22
33
+
34
+ Expect "structuredContent.sum" equals 42
35
+ ```
36
+
37
+ Check the wording, then run it:
38
+
39
+ ```bash
40
+ npx mcprigor check calculator.mcpr
41
+ npx mcprigor test calculator.mcpr
42
+ ```
43
+
44
+ Create a browser report:
45
+
46
+ ```bash
47
+ npx mcprigor test calculator.mcpr --html report.html
48
+ ```
49
+
50
+ Expected summary:
51
+
52
+ ```text
53
+ ✓ Adding 20 and 22 gives 42
54
+
55
+ 1 passed, 0 failed, 0 skipped, 0 blocked
56
+ ```
57
+
58
+ ## Use the QA workspace
59
+
60
+ Start the local browser interface:
61
+
62
+ ```bash
63
+ npx mcprigor workspace .
64
+ ```
65
+
66
+ Open the printed `http://127.0.0.1:...` URL. You can select a suite, edit it, validate the wording, run tests, run transport parity, and review results.
67
+
68
+ The workspace is loopback-only and does not accept arbitrary commands from the browser.
69
+
70
+ ## Connect to an MCP server
71
+
72
+ Local stdio server:
73
+
74
+ ```text
75
+ Server: node dist/server.js
76
+ ```
77
+
78
+ Python server:
79
+
80
+ ```text
81
+ Server: python -m my_mcp_server
82
+ ```
83
+
84
+ Streamable HTTP server:
85
+
86
+ ```text
87
+ MCP URL: https://qa.example.com/mcp
88
+
89
+ Server options:
90
+ headers:
91
+ Authorization: "Bearer ${env.MCP_TOKEN}"
92
+ ```
93
+
94
+ Run with an environment variable:
95
+
96
+ ```bash
97
+ MCP_TOKEN="your-token" npx mcprigor test customer.mcpr
98
+ ```
99
+
100
+ Do not place reusable credentials directly in test files.
101
+
102
+ ## Common test actions
103
+
104
+ ```text
105
+ Call tool "search" with:
106
+ query: "red shoes"
107
+
108
+ Read resource "catalog://status"
109
+
110
+ Get prompt "write_summary" with:
111
+ topic: "Release quality"
112
+
113
+ Expect it succeeds
114
+ Expect an error
115
+ Expect "structuredContent.total" equals 2
116
+ Expect "content[0].text" contains "complete"
117
+ Expect "items" has 3 items
118
+ ```
119
+
120
+ See the [plain-language cookbook](docs/PLAIN-LANGUAGE-COOKBOOK.md) for copy-ready examples.
121
+
122
+ ## Compare local and deployed behavior
123
+
124
+ ```text
125
+ MCP Test 1
126
+ Suite: "Calculator parity"
127
+
128
+ Compare target "Local": node dist/server.js
129
+ Compare target "QA": https://qa.example.com/mcp
130
+
131
+ Test: "Addition is consistent"
132
+ Call tool "add" with:
133
+ a: 20
134
+ b: 22
135
+ Expect "structuredContent.sum" equals 42
136
+ ```
137
+
138
+ ```bash
139
+ npx mcprigor parity calculator-parity.mcpr
140
+ ```
141
+
142
+ MCP Rigor runs every scenario against both targets and reports semantic differences.
143
+
144
+ ## Create a test from a live server
145
+
146
+ Provide a small `.mcpr` file containing the target, then run:
147
+
148
+ ```bash
149
+ npx mcprigor author server.mcpr --out search-customer.mcpr
150
+ ```
151
+
152
+ The guided author discovers operations, asks for inputs, previews a response, and writes a reviewable plain-language test.
153
+
154
+ ## Use data-driven tests
155
+
156
+ ```text
157
+ Test: "Calculator examples"
158
+ For each row:
159
+ | caseId | a | b | expected |
160
+ | basic | 2 | 3 | 5 |
161
+ | larger | 20 | 22 | 42 |
162
+
163
+ Call tool "add" with:
164
+ a: "${row.a}"
165
+ b: "${row.b}"
166
+
167
+ Expect "structuredContent.sum" equals "${row.expected}"
168
+ ```
169
+
170
+ CSV, JSON, YAML, Excel, REST, Google Sheets, SQL adapters, typed columns, filters, joins, and deterministic sampling are also supported.
171
+
172
+ ## Use in CI
173
+
174
+ ```yaml
175
+ - uses: actions/setup-node@v4
176
+ with:
177
+ node-version: 20
178
+ - run: npm ci
179
+ - run: npx mcprigor check tests/acceptance.mcpr
180
+ - run: npx mcprigor test tests/acceptance.mcpr --junit reports/mcp.xml --evidence .mcprigor/ci-run
181
+ ```
182
+
183
+ Exit codes:
184
+
185
+ | Code | Meaning |
186
+ |---:|---|
187
+ | `0` | Tests passed |
188
+ | `1` | A test or comparison failed |
189
+ | `2` | Usage, language, or configuration problem |
190
+ | `3` | Server, transport, or internal failure |
191
+
192
+ ## Main commands
193
+
194
+ ```text
195
+ mcprigor workspace [DIRECTORY] Start the local QA interface
196
+ mcprigor init FILE Create an example test
197
+ mcprigor check FILE Validate without connecting
198
+ mcprigor test FILE Run plain-language or YAML tests
199
+ mcprigor author TARGET --out FILE Build a test interactively
200
+ mcprigor parity FILE Compare named targets
201
+ mcprigor discover FILE Save the live MCP contract
202
+ mcprigor contract-check LOCK --target FILE
203
+ mcprigor evidence-show DIRECTORY
204
+ ```
205
+
206
+ See the [complete CLI reference](docs/CLI-REFERENCE.md).
207
+
208
+ ## Choose your next guide
209
+
210
+ - **New QA user:** [Getting started](docs/GETTING-STARTED.md)
211
+ - **Writing scenarios:** [Plain-language cookbook](docs/PLAIN-LANGUAGE-COOKBOOK.md)
212
+ - **Using the browser UI:** [QA workspace](docs/QA-WORKSPACE.md)
213
+ - **Setting up targets and CI:** [Engineer setup](docs/ENGINEER-SETUP.md)
214
+ - **Fixing failures:** [Troubleshooting](docs/TROUBLESHOOTING.md)
215
+ - **All documentation:** [Documentation index](docs/README.md)
216
+ - **Renaming old files:** [`.mcpr` extension and migration](docs/FILE-EXTENSION.md)
217
+
218
+ ## Scope and safety
219
+
220
+ MCP Rigor performs black-box behavior and contract testing. It complements MCP Inspector and official MCP Conformance; it does not provide certification.
221
+
222
+ Remote data and custom extensions are disabled unless explicitly enabled. Reports and evidence are sanitized, but business response data may still be sensitive. Review [security and retention](docs/SECURITY-AND-RETENTION.md) before storing CI artifacts.
223
+
224
+ ## Contributing
225
+
226
+ See `CONTRIBUTING.md`, then run:
227
+
228
+ ```bash
229
+ npm ci
230
+ npm run check
231
+ ```
232
+
233
+ Apache-2.0 licensed.
@@ -0,0 +1,4 @@
1
+ import type { StepAssertion } from "./types.js";
2
+ export declare function assertResponse(response: unknown, assertion: StepAssertion | undefined): void;
3
+ export declare function assertError(error: unknown, assertion: StepAssertion | undefined): void;
4
+ //# sourceMappingURL=assertions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertions.d.ts","sourceRoot":"","sources":["../src/assertions.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAiB,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI,CAU5F;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI,CAgBtF"}
@@ -0,0 +1,101 @@
1
+ import { isDeepStrictEqual } from "node:util";
2
+ import AjvModule from "ajv";
3
+ const Ajv = AjvModule;
4
+ import { readPath } from "./path.js";
5
+ const ajv = new Ajv({ allErrors: true, strict: false });
6
+ export function assertResponse(response, assertion) {
7
+ if (!assertion)
8
+ return;
9
+ if (assertion.status === "error")
10
+ throw new Error("Expected an MCP error, but the request succeeded");
11
+ const assertions = assertion.json
12
+ ? Array.isArray(assertion.json)
13
+ ? assertion.json
14
+ : [assertion.json]
15
+ : [];
16
+ for (const item of assertions)
17
+ assertJson(response, item);
18
+ }
19
+ export function assertError(error, assertion) {
20
+ if (assertion?.status !== "error")
21
+ throw error;
22
+ const candidate = error;
23
+ const expected = assertion.error;
24
+ if (!expected)
25
+ return;
26
+ if (expected.code !== undefined && candidate.code !== expected.code) {
27
+ throw new Error(`Expected error code ${expected.code}, received ${String(candidate.code)}`);
28
+ }
29
+ const message = String(candidate.message ?? error);
30
+ if (expected.message !== undefined && message !== expected.message) {
31
+ throw new Error(`Expected error message ${JSON.stringify(expected.message)}, received ${JSON.stringify(message)}`);
32
+ }
33
+ if (expected.matches !== undefined && !new RegExp(expected.matches).test(message)) {
34
+ throw new Error(`Expected error message to match /${expected.matches}/, received ${JSON.stringify(message)}`);
35
+ }
36
+ }
37
+ function assertJson(response, assertion) {
38
+ const actual = readPath(response, assertion.path);
39
+ const label = assertion.path ?? "$";
40
+ if (assertion.exists !== undefined) {
41
+ const exists = actual !== undefined;
42
+ if (exists !== assertion.exists)
43
+ fail(label, `existence ${assertion.exists}`, actual);
44
+ }
45
+ if ("equals" in assertion && !isDeepStrictEqual(actual, assertion.equals)) {
46
+ fail(label, JSON.stringify(assertion.equals), actual);
47
+ }
48
+ if ("notEquals" in assertion && isDeepStrictEqual(actual, assertion.notEquals)) {
49
+ throw new Error(`${label}: expected value not to equal ${JSON.stringify(assertion.notEquals)}`);
50
+ }
51
+ if (assertion.type !== undefined && typeOf(actual) !== assertion.type) {
52
+ fail(label, `type ${assertion.type}`, typeOf(actual));
53
+ }
54
+ if (assertion.length !== undefined) {
55
+ const length = typeof actual === "string" || Array.isArray(actual) ? actual.length : undefined;
56
+ if (length !== assertion.length)
57
+ fail(label, `length ${assertion.length}`, length);
58
+ }
59
+ if ("contains" in assertion && !contains(actual, assertion.contains)) {
60
+ throw new Error(`${label}: expected ${JSON.stringify(actual)} to contain ${JSON.stringify(assertion.contains)}`);
61
+ }
62
+ if (assertion.matches !== undefined) {
63
+ if (typeof actual !== "string" || !new RegExp(assertion.matches).test(actual)) {
64
+ fail(label, `a string matching /${assertion.matches}/`, actual);
65
+ }
66
+ }
67
+ if (assertion.schema !== undefined) {
68
+ const validate = ajv.compile(assertion.schema);
69
+ if (!validate(actual)) {
70
+ const detail = (validate.errors ?? []).map((error) => `${error.instancePath || "$"} ${error.message}`).join("; ");
71
+ throw new Error(`${label}: MCP-SCHEMA-001 response does not match schema: ${detail}`);
72
+ }
73
+ }
74
+ }
75
+ function contains(actual, expected) {
76
+ if (typeof actual === "string" && typeof expected === "string")
77
+ return actual.includes(expected);
78
+ if (Array.isArray(actual)) {
79
+ return actual.some((item) => isDeepStrictEqual(item, expected) || isSubset(item, expected));
80
+ }
81
+ return isSubset(actual, expected);
82
+ }
83
+ function isSubset(actual, expected) {
84
+ if (isDeepStrictEqual(actual, expected))
85
+ return true;
86
+ if (typeof actual !== "object" || actual === null || typeof expected !== "object" || expected === null) {
87
+ return false;
88
+ }
89
+ return Object.entries(expected).every(([key, value]) => isSubset(actual[key], value));
90
+ }
91
+ function typeOf(value) {
92
+ if (value === null)
93
+ return "null";
94
+ if (Array.isArray(value))
95
+ return "array";
96
+ return typeof value;
97
+ }
98
+ function fail(path, expected, actual) {
99
+ throw new Error(`${path}: expected ${String(expected)}, received ${JSON.stringify(actual)}`);
100
+ }
101
+ //# sourceMappingURL=assertions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertions.js","sourceRoot":"","sources":["../src/assertions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { Target } from "./types.js";
2
+ export interface Choice<T> {
3
+ label: string;
4
+ value: T;
5
+ description?: string;
6
+ }
7
+ export interface PromptAdapter {
8
+ select<T>(id: string, message: string, choices: Choice<T>[]): Promise<T>;
9
+ multiselect<T>(id: string, message: string, choices: Choice<T>[]): Promise<T[]>;
10
+ input(id: string, message: string, initial?: string): Promise<string>;
11
+ confirm(id: string, message: string, initial?: boolean): Promise<boolean>;
12
+ note(message: string): Promise<void>;
13
+ close(): Promise<void>;
14
+ }
15
+ export interface AuthoredOperation {
16
+ kind: "tool" | "resource" | "prompt";
17
+ name: string;
18
+ input?: Record<string, unknown>;
19
+ response: unknown;
20
+ }
21
+ export interface AuthoredAssertion {
22
+ path: string;
23
+ kind: "equals" | "contains" | "exists";
24
+ expected?: unknown;
25
+ }
26
+ export interface AuthoredTest {
27
+ suiteName: string;
28
+ testName: string;
29
+ target: Target;
30
+ operation: AuthoredOperation;
31
+ assertions: AuthoredAssertion[];
32
+ }
33
+ export declare function authorTest(target: Target, prompts: PromptAdapter, output: string): Promise<AuthoredTest>;
34
+ export declare function renderAuthoredTest(test: AuthoredTest): string;
35
+ export interface FlatField {
36
+ path: string;
37
+ value: unknown;
38
+ preview: string;
39
+ }
40
+ export declare function flattenResponse(value: unknown, path?: string, depth?: number): FlatField[];
41
+ export declare class ScriptedPromptAdapter implements PromptAdapter {
42
+ private readonly answers;
43
+ readonly transcript: Array<{
44
+ id: string;
45
+ answer: unknown;
46
+ }>;
47
+ constructor(answers: Record<string, unknown>);
48
+ select<T>(id: string, _message: string, choices: Choice<T>[]): Promise<T>;
49
+ multiselect<T>(id: string, _message: string, choices: Choice<T>[]): Promise<T[]>;
50
+ input(id: string, _message: string, initial?: string): Promise<string>;
51
+ confirm(id: string, _message: string, initial?: boolean): Promise<boolean>;
52
+ note(_message: string): Promise<void>;
53
+ close(): Promise<void>;
54
+ private answer;
55
+ }
56
+ export declare function createReadlinePromptAdapter(): PromptAdapter;
57
+ //# sourceMappingURL=author.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"author.d.ts","sourceRoot":"","sources":["../src/author.ts"],"names":[],"mappings":"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"}
package/dist/author.js ADDED
@@ -0,0 +1,134 @@
1
+ import { rename, writeFile } from "node:fs/promises";
2
+ import { dirname, basename, resolve } from "node:path";
3
+ import { createInterface } from "node:readline/promises";
4
+ import { stdin, stdout } from "node:process";
5
+ import { discoverTarget } from "./discovery.js";
6
+ import { createSession } from "./session.js";
7
+ export async function authorTest(target, prompts, output) {
8
+ const discovery = await discoverTarget(target);
9
+ const kind = await prompts.select("operation.kind", "What would you like to test?", availableKinds(discovery));
10
+ const selected = await chooseOperation(kind, discovery, prompts);
11
+ const input = await collectInputs(kind, selected, prompts);
12
+ await prompts.note(`Request preview:\n${selectedName(selected)} ${JSON.stringify(input, null, 2)}`);
13
+ if (!await prompts.confirm("request.run", "Run this request now?", true))
14
+ throw new Error("MCP-AUTHOR-001 Authoring cancelled before preview run");
15
+ const session = createSession(target);
16
+ let response;
17
+ try {
18
+ await session.connect();
19
+ response = kind === "tool" ? await session.request("tools/call", { name: selectedName(selected), arguments: input })
20
+ : kind === "resource" ? await session.request("resources/read", { uri: selectedName(selected) })
21
+ : await session.request("prompts/get", { name: selectedName(selected), arguments: input });
22
+ }
23
+ finally {
24
+ await session.close();
25
+ }
26
+ const fields = flattenResponse(response);
27
+ const chosen = await prompts.multiselect("assertions.fields", "Which returned fields should be checked?", fields.map((field) => ({ label: `${field.path} = ${field.preview}`, value: field })));
28
+ const assertions = [];
29
+ for (const field of chosen) {
30
+ const kindOfAssertion = await prompts.select(`assertion.${field.path}`, `How should ${field.path} be checked?`, assertionChoices(field.value));
31
+ assertions.push({ path: field.path, kind: kindOfAssertion, ...(kindOfAssertion === "exists" ? {} : { expected: field.value }) });
32
+ }
33
+ const testName = await prompts.input("test.name", "Name this test", `${kind === "tool" ? "Tool" : kind === "resource" ? "Resource" : "Prompt"} ${selectedName(selected)} works`);
34
+ const authored = { suiteName: "Generated MCP acceptance test", testName, target, operation: { kind, name: selectedName(selected), input, response }, assertions };
35
+ const source = renderAuthoredTest(authored);
36
+ await prompts.note(`Generated test:\n\n${source}`);
37
+ if (!await prompts.confirm("file.write", `Write ${output}?`, true))
38
+ throw new Error("MCP-AUTHOR-002 Authoring cancelled before writing");
39
+ await atomicWrite(output, source);
40
+ return authored;
41
+ }
42
+ export function renderAuthoredTest(test) {
43
+ const lines = [`MCP Test 1`, `Suite: ${JSON.stringify(test.suiteName)}`];
44
+ if (test.target.transport === "stdio")
45
+ lines.push(`Server: ${[test.target.command, ...(test.target.args ?? [])].map(quoteCommand).join(" ")}`);
46
+ else
47
+ lines.push(`MCP URL: ${test.target.url}`);
48
+ lines.push("", `Test: ${JSON.stringify(test.testName)}`);
49
+ if (test.operation.kind === "tool")
50
+ lines.push(` Require: tools`, ` Call tool ${JSON.stringify(test.operation.name)}${Object.keys(test.operation.input ?? {}).length ? " with:" : ""}`);
51
+ else if (test.operation.kind === "resource")
52
+ lines.push(` Require: resources`, ` Read resource ${JSON.stringify(test.operation.name)}`);
53
+ else
54
+ lines.push(` Require: prompts`, ` Get prompt ${JSON.stringify(test.operation.name)}${Object.keys(test.operation.input ?? {}).length ? " with:" : ""}`);
55
+ if (Object.keys(test.operation.input ?? {}).length)
56
+ for (const [key, value] of Object.entries(sortObject(test.operation.input)))
57
+ lines.push(` ${key}: ${JSON.stringify(value)}`);
58
+ lines.push("", " Expect it succeeds");
59
+ for (const assertion of [...test.assertions].sort((a, b) => a.path.localeCompare(b.path))) {
60
+ const path = assertion.path.replace(/^\$\.?/, "");
61
+ lines.push(assertion.kind === "exists" ? ` Expect ${JSON.stringify(path)} exists` : ` Expect ${JSON.stringify(path)} ${assertion.kind} ${JSON.stringify(assertion.expected)}`);
62
+ }
63
+ return `${lines.join("\n")}\n`;
64
+ }
65
+ export function flattenResponse(value, path = "$", depth = 0) {
66
+ if (depth > 8)
67
+ return [];
68
+ if (Array.isArray(value))
69
+ return value.flatMap((item, index) => flattenResponse(item, `${path}[${index}]`, depth + 1));
70
+ if (typeof value === "object" && value !== null)
71
+ return Object.keys(value).sort().flatMap((key) => flattenResponse(value[key], `${path}.${key}`, depth + 1));
72
+ return [{ path, value, preview: JSON.stringify(value)?.slice(0, 100) ?? String(value) }];
73
+ }
74
+ export class ScriptedPromptAdapter {
75
+ answers;
76
+ transcript = [];
77
+ constructor(answers) {
78
+ this.answers = answers;
79
+ }
80
+ async select(id, _message, choices) { const answer = this.answer(id); const found = choices.find((choice) => choice.value === answer || choice.label === answer); if (!found)
81
+ throw new Error(`No scripted choice for ${id}: ${String(answer)}`); return found.value; }
82
+ async multiselect(id, _message, choices) { const answers = this.answer(id); return choices.filter((choice) => answers.includes(choice.value) || answers.includes(choice.label)).map((choice) => choice.value); }
83
+ async input(id, _message, initial) { return String(this.answer(id, initial)); }
84
+ async confirm(id, _message, initial = false) { return Boolean(this.answer(id, initial)); }
85
+ async note(_message) { }
86
+ async close() { }
87
+ answer(id, fallback) { const value = id in this.answers ? this.answers[id] : fallback; if (value === undefined)
88
+ throw new Error(`Missing scripted answer: ${id}`); this.transcript.push({ id, answer: value }); return value; }
89
+ }
90
+ export function createReadlinePromptAdapter() {
91
+ const rl = createInterface({ input: stdin, output: stdout });
92
+ const inputPrompt = async (_id, message, initial) => (await rl.question(`${message}${initial ? ` [${initial}]` : ""}: `)).trim() || initial || "";
93
+ return {
94
+ input: inputPrompt,
95
+ async select(id, message, choices) { await noteChoices(message, choices); const answer = Number(await inputPrompt(id, "Choose a number")); if (!Number.isInteger(answer) || !choices[answer - 1])
96
+ throw new Error("Please run author again and choose a listed number."); return choices[answer - 1].value; },
97
+ async multiselect(id, message, choices) { await noteChoices(message, choices); const answer = await inputPrompt(id, "Choose numbers separated by commas"); return answer.split(",").map(Number).filter((n) => choices[n - 1]).map((n) => choices[n - 1].value); },
98
+ async confirm(id, message, initial = false) { const answer = (await inputPrompt(id, `${message} (y/n)`, initial ? "y" : "n")).toLowerCase(); return answer === "y" || answer === "yes"; },
99
+ async note(message) { stdout.write(`${message}\n`); }, async close() { rl.close(); },
100
+ };
101
+ async function noteChoices(message, choices) { stdout.write(`\n${message}\n${choices.map((choice, index) => ` ${index + 1}. ${choice.label}${choice.description ? ` — ${choice.description}` : ""}`).join("\n")}\n`); }
102
+ }
103
+ function availableKinds(lock) { return [lock.tools.length ? { label: "Call a tool", value: "tool" } : undefined, lock.resources.length ? { label: "Read a resource", value: "resource" } : undefined, lock.prompts.length ? { label: "Get a prompt", value: "prompt" } : undefined].filter((x) => !!x); }
104
+ async function chooseOperation(kind, lock, prompts) { const list = kind === "tool" ? lock.tools : kind === "resource" ? lock.resources : lock.prompts; const choices = list.map((item) => ({ label: String(item.name ?? item.uri), value: item, description: typeof item.description === "string" ? item.description : undefined })); return prompts.select(`${kind}.name`, `Choose a ${kind}`, choices); }
105
+ async function collectInputs(kind, item, prompts) { if (kind === "resource")
106
+ return {}; const result = {}; const schema = kind === "tool" ? item.inputSchema : undefined; const properties = schema?.properties; const required = new Set(Array.isArray(schema?.required) ? schema.required : []); if (properties)
107
+ for (const key of Object.keys(properties).sort()) {
108
+ const field = properties[key];
109
+ if (!required.has(key) && !await prompts.confirm(`input.${key}.set`, `Set optional ${key}?`, false))
110
+ continue;
111
+ const raw = await prompts.input(`input.${key}`, `${key}${required.has(key) ? " (required)" : ""}${field.type ? `, ${String(field.type)}` : ""}`, field.default === undefined ? undefined : String(field.default));
112
+ result[key] = parseInput(raw, field.type);
113
+ }
114
+ else if (kind === "prompt")
115
+ for (const argument of item.arguments ?? []) {
116
+ const key = String(argument.name);
117
+ if (!argument.required && !await prompts.confirm(`input.${key}.set`, `Set optional ${key}?`, false))
118
+ continue;
119
+ result[key] = await prompts.input(`input.${key}`, `${key}${argument.required ? " (required)" : ""}`);
120
+ } return sortObject(result); }
121
+ function parseInput(value, type) { if (type === "integer" || type === "number") {
122
+ const parsed = Number(value);
123
+ if (!Number.isFinite(parsed) || type === "integer" && !Number.isInteger(parsed))
124
+ throw new Error(`Invalid ${String(type)}: ${value}`);
125
+ return parsed;
126
+ } if (type === "boolean")
127
+ return value.toLowerCase() === "true"; if (type === "array" || type === "object")
128
+ return JSON.parse(value); return value; }
129
+ function assertionChoices(value) { return [{ label: "equals current value", value: "equals" }, ...(typeof value === "string" ? [{ label: "contains current text", value: "contains" }] : []), { label: "exists", value: "exists" }]; }
130
+ function selectedName(item) { return String(item.name ?? item.uri); }
131
+ function sortObject(value) { return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b))); }
132
+ function quoteCommand(value) { return /\s/.test(value) ? JSON.stringify(value) : value; }
133
+ async function atomicWrite(file, source) { const absolute = resolve(file); const temporary = `${dirname(absolute)}/.${basename(absolute)}.${process.pid}.tmp`; await writeFile(temporary, source, "utf8"); await rename(temporary, absolute); }
134
+ //# sourceMappingURL=author.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"author.js","sourceRoot":"","sources":["../src/author.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function canonicalize(value: unknown): unknown;
2
+ export declare function canonicalJson(value: unknown): string;
3
+ export declare function fingerprint(value: unknown): string;
4
+ //# sourceMappingURL=canonical.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQpD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAElD"}
@@ -0,0 +1,17 @@
1
+ import { createHash } from "node:crypto";
2
+ export function canonicalize(value) {
3
+ if (Array.isArray(value))
4
+ return value.map(canonicalize);
5
+ if (typeof value !== "object" || value === null)
6
+ return value;
7
+ return Object.fromEntries(Object.entries(value)
8
+ .sort(([a], [b]) => a.localeCompare(b))
9
+ .map(([key, item]) => [key, canonicalize(item)]));
10
+ }
11
+ export function canonicalJson(value) {
12
+ return JSON.stringify(canonicalize(value));
13
+ }
14
+ export function fingerprint(value) {
15
+ return `sha256:${createHash("sha256").update(canonicalJson(value)).digest("hex")}`;
16
+ }
17
+ //# sourceMappingURL=canonical.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.js","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;SAClB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CACnD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,UAAU,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACrF,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}