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.
- package/LICENSE +17 -0
- package/README.md +233 -0
- package/dist/assertions.d.ts +4 -0
- package/dist/assertions.d.ts.map +1 -0
- package/dist/assertions.js +101 -0
- package/dist/assertions.js.map +1 -0
- package/dist/author.d.ts +57 -0
- package/dist/author.d.ts.map +1 -0
- package/dist/author.js +134 -0
- package/dist/author.js.map +1 -0
- package/dist/canonical.d.ts +4 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/canonical.js +17 -0
- package/dist/canonical.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +265 -0
- package/dist/cli.js.map +1 -0
- package/dist/contract.d.ts +28 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +138 -0
- package/dist/contract.js.map +1 -0
- package/dist/data.d.ts +24 -0
- package/dist/data.d.ts.map +1 -0
- package/dist/data.js +367 -0
- package/dist/data.js.map +1 -0
- package/dist/discovery.d.ts +6 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +82 -0
- package/dist/discovery.js.map +1 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +40 -0
- package/dist/errors.js.map +1 -0
- package/dist/extension-host.d.ts +20 -0
- package/dist/extension-host.d.ts.map +1 -0
- package/dist/extension-host.js +52 -0
- package/dist/extension-host.js.map +1 -0
- package/dist/extension-sdk.d.ts +22 -0
- package/dist/extension-sdk.d.ts.map +1 -0
- package/dist/extension-sdk.js +3 -0
- package/dist/extension-sdk.js.map +1 -0
- package/dist/extension-worker.d.ts +2 -0
- package/dist/extension-worker.d.ts.map +1 -0
- package/dist/extension-worker.js +27 -0
- package/dist/extension-worker.js.map +1 -0
- package/dist/extensions.d.ts +15 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +60 -0
- package/dist/extensions.js.map +1 -0
- package/dist/imports.d.ts +7 -0
- package/dist/imports.d.ts.map +1 -0
- package/dist/imports.js +41 -0
- package/dist/imports.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/language.d.ts +34 -0
- package/dist/language.d.ts.map +1 -0
- package/dist/language.js +102 -0
- package/dist/language.js.map +1 -0
- package/dist/loader.d.ts +4 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +51 -0
- package/dist/loader.js.map +1 -0
- package/dist/parity.d.ts +23 -0
- package/dist/parity.d.ts.map +1 -0
- package/dist/parity.js +77 -0
- package/dist/parity.js.map +1 -0
- package/dist/path.d.ts +3 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +71 -0
- package/dist/path.js.map +1 -0
- package/dist/qa-advanced.d.ts +8 -0
- package/dist/qa-advanced.d.ts.map +1 -0
- package/dist/qa-advanced.js +239 -0
- package/dist/qa-advanced.js.map +1 -0
- package/dist/qa-language.d.ts +4 -0
- package/dist/qa-language.d.ts.map +1 -0
- package/dist/qa-language.js +385 -0
- package/dist/qa-language.js.map +1 -0
- package/dist/qa-loader.d.ts +4 -0
- package/dist/qa-loader.d.ts.map +1 -0
- package/dist/qa-loader.js +22 -0
- package/dist/qa-loader.js.map +1 -0
- package/dist/redact.d.ts +7 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +63 -0
- package/dist/redact.js.map +1 -0
- package/dist/replay.d.ts +17 -0
- package/dist/replay.d.ts.map +1 -0
- package/dist/replay.js +48 -0
- package/dist/replay.js.map +1 -0
- package/dist/reporters.d.ts +6 -0
- package/dist/reporters.d.ts.map +1 -0
- package/dist/reporters.js +52 -0
- package/dist/reporters.js.map +1 -0
- package/dist/runner.d.ts +16 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +304 -0
- package/dist/runner.js.map +1 -0
- package/dist/schema.d.ts +446 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +117 -0
- package/dist/schema.js.map +1 -0
- package/dist/session.d.ts +5 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +111 -0
- package/dist/session.js.map +1 -0
- package/dist/snapshots.d.ts +28 -0
- package/dist/snapshots.d.ts.map +1 -0
- package/dist/snapshots.js +87 -0
- package/dist/snapshots.js.map +1 -0
- package/dist/starter.d.ts +3 -0
- package/dist/starter.d.ts.map +1 -0
- package/dist/starter.js +34 -0
- package/dist/starter.js.map +1 -0
- package/dist/state.d.ts +13 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +29 -0
- package/dist/state.js.map +1 -0
- package/dist/trace.d.ts +57 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/trace.js +94 -0
- package/dist/trace.js.map +1 -0
- package/dist/types.d.ts +245 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/workspace.d.ts +10 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +144 -0
- package/dist/workspace.js.map +1 -0
- package/docs/CLI-REFERENCE.md +167 -0
- package/docs/COMPATIBILITY.md +42 -0
- package/docs/CONTRACT-DRIFT.md +42 -0
- package/docs/DATA-AND-REUSE.md +213 -0
- package/docs/DATA-ENGINEERING.md +96 -0
- package/docs/ENGINEER-SETUP.md +176 -0
- package/docs/ERROR-MODEL.md +24 -0
- package/docs/EVIDENCE.md +58 -0
- package/docs/EXTENSION-SDK.md +76 -0
- package/docs/FILE-EXTENSION.md +52 -0
- package/docs/GETTING-STARTED.md +126 -0
- package/docs/GUIDED-AUTHORING.md +80 -0
- package/docs/LANDSCAPE.md +81 -0
- package/docs/LANGUAGE-SPEC.md +317 -0
- package/docs/MCP-NATIVE.md +111 -0
- package/docs/PLAIN-LANGUAGE-COOKBOOK.md +219 -0
- package/docs/QA-GUIDE.md +128 -0
- package/docs/QA-WORKSPACE.md +78 -0
- package/docs/README.md +55 -0
- package/docs/SECURITY-AND-RETENTION.md +37 -0
- package/docs/SNAPSHOTS-AND-REPLAY.md +85 -0
- package/docs/SPECIFICATION.md +178 -0
- package/docs/STATE-AND-DEPENDENCIES.md +106 -0
- package/docs/TRANSPORT-PARITY.md +98 -0
- package/docs/TROUBLESHOOTING.md +199 -0
- package/editors/mcpr-language.json +16 -0
- package/package.json +70 -0
- package/workspace-assets/app.js +1 -0
- package/workspace-assets/index.html +1 -0
- package/workspace-assets/style.css +1 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# MCP Rigor file extension
|
|
2
|
+
|
|
3
|
+
MCP Rigor plain-language tests use:
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
.mcpr
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Examples:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
smoke.mcpr
|
|
13
|
+
customer-regression.mcpr
|
|
14
|
+
transport-parity.mcpr
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Why not `.mcp`?
|
|
18
|
+
|
|
19
|
+
The `.mcp` suffix predates Model Context Protocol and is already associated with other software, including Metrowerks CodeWarrior project files. Reusing it would create ambiguous editor, operating-system, MIME, and tooling associations.
|
|
20
|
+
|
|
21
|
+
MCP Rigor therefore uses the product-specific `.mcpr` suffix: **MCP Rigor**.
|
|
22
|
+
|
|
23
|
+
References checked during the decision:
|
|
24
|
+
|
|
25
|
+
- [FileInfo: MCP file extension](https://fileinfo.com/extension/mcp)
|
|
26
|
+
- [ReviverSoft file-extension registry](https://www.reviversoft.com/file-extensions/mcp)
|
|
27
|
+
|
|
28
|
+
File-extension registries are not global standards authorities, but existing use is sufficient reason to avoid the collision.
|
|
29
|
+
|
|
30
|
+
## Migration
|
|
31
|
+
|
|
32
|
+
Rename files without changing their contents:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
mv tests/smoke.mcp tests/smoke.mcpr
|
|
36
|
+
mv tests/shared-flows.mcp tests/shared-flows.mcpr
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Update flow imports:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
Import flows from "./shared-flows.mcpr"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Update scripts and CI:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
mcprigor check tests/smoke.mcpr
|
|
49
|
+
mcprigor test tests/smoke.mcpr
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
MCP Rigor now rejects `.mcp` files with an actionable rename message. YAML and JSON suite support is unchanged.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Getting started
|
|
2
|
+
|
|
3
|
+
This guide takes you from installation to one passing MCP test.
|
|
4
|
+
|
|
5
|
+
## 1. Install MCP Rigor
|
|
6
|
+
|
|
7
|
+
You need Node.js 20 or 22.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
mkdir mcp-acceptance-tests
|
|
11
|
+
cd mcp-acceptance-tests
|
|
12
|
+
npm init -y
|
|
13
|
+
npm install --save-dev mcprigor
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 2. Create a test file
|
|
17
|
+
|
|
18
|
+
Create `calculator.mcpr`:
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
MCP Test 1
|
|
22
|
+
|
|
23
|
+
Suite: "Calculator acceptance tests"
|
|
24
|
+
Server: node ../calculator-server/dist/server.js
|
|
25
|
+
|
|
26
|
+
Test: "Adding 20 and 22 gives 42"
|
|
27
|
+
Call tool "add" with:
|
|
28
|
+
a: 20
|
|
29
|
+
b: 22
|
|
30
|
+
|
|
31
|
+
Expect "structuredContent.sum" equals 42
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Change the `Server` command to the command that starts your MCP server.
|
|
35
|
+
|
|
36
|
+
For a deployed Streamable HTTP server, use:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
MCP URL: https://qa.example.com/mcp
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 3. Check the wording
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx mcprigor check calculator.mcpr
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
A valid file prints:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
✓ calculator.mcpr looks good and is ready to run
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`check` does not connect to the server.
|
|
55
|
+
|
|
56
|
+
## 4. Run the test
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npx mcprigor test calculator.mcpr
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
A passing result looks like:
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
MCP Rigor — Calculator acceptance tests
|
|
66
|
+
✓ Adding 20 and 22 gives 42
|
|
67
|
+
|
|
68
|
+
1 passed, 0 failed, 0 skipped, 0 blocked
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## 5. Create a shareable report
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npx mcprigor test calculator.mcpr --html report.html
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Open `report.html` or attach it to a ticket.
|
|
78
|
+
|
|
79
|
+
## 6. Try the browser workspace
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npx mcprigor workspace .
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Open the printed local URL. Select `calculator.mcpr`, edit it, choose **Validate**, then **Run tests**.
|
|
86
|
+
|
|
87
|
+
## If you do not know tool names
|
|
88
|
+
|
|
89
|
+
Create a small target file such as `server.mcpr`:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
MCP Test 1
|
|
93
|
+
Suite: "Server target"
|
|
94
|
+
Server: node ../calculator-server/dist/server.js
|
|
95
|
+
Test: "Connection"
|
|
96
|
+
Send "ping"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Start guided authoring:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx mcprigor author server.mcpr --out calculator.mcpr
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
MCP Rigor discovers tools, resources, and prompts and asks what you want to verify.
|
|
106
|
+
|
|
107
|
+
## Recommended project layout
|
|
108
|
+
|
|
109
|
+
```text
|
|
110
|
+
mcp-acceptance-tests/
|
|
111
|
+
package.json
|
|
112
|
+
tests/
|
|
113
|
+
smoke.mcpr
|
|
114
|
+
regression.mcpr
|
|
115
|
+
data/
|
|
116
|
+
customers.csv
|
|
117
|
+
.mcprigor/
|
|
118
|
+
# generated evidence; normally ignored or stored as CI artifacts
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Next steps
|
|
122
|
+
|
|
123
|
+
- [Plain-language cookbook](PLAIN-LANGUAGE-COOKBOOK.md)
|
|
124
|
+
- [QA workspace](QA-WORKSPACE.md)
|
|
125
|
+
- [Engineer setup and CI](ENGINEER-SETUP.md)
|
|
126
|
+
- [Troubleshooting](TROUBLESHOOTING.md)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Guided test authoring
|
|
2
|
+
|
|
3
|
+
Use this when you know the behavior to test but do not know the server's tool, resource, prompt, or response field names.
|
|
4
|
+
|
|
5
|
+
The `author` command creates a plain-language test by connecting to a live MCP server and asking QA-friendly questions.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
mcprigor author server.mcpr --out tests/search-customer.mcpr
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`server.mcpr` can be an existing minimal target file:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
MCP Test 1
|
|
15
|
+
Suite: "QA target"
|
|
16
|
+
Server: node dist/server.js
|
|
17
|
+
Test: "placeholder"
|
|
18
|
+
Send "ping"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Authoring flow
|
|
22
|
+
|
|
23
|
+
1. MCP Rigor connects and discovers tools, resources, and prompts.
|
|
24
|
+
2. Choose whether to call a tool, read a resource, or get a prompt.
|
|
25
|
+
3. Select the operation by its name and description.
|
|
26
|
+
4. Enter required inputs derived from the tool JSON Schema or prompt arguments.
|
|
27
|
+
5. Review and run the request.
|
|
28
|
+
6. Select returned fields to verify.
|
|
29
|
+
7. Choose equality, containment, or existence checks.
|
|
30
|
+
8. Name the test and review the generated source.
|
|
31
|
+
9. Confirm the output file.
|
|
32
|
+
10. Run it normally with `mcprigor test`.
|
|
33
|
+
|
|
34
|
+
Generated files are deterministic:
|
|
35
|
+
|
|
36
|
+
- `MCP Test 1` language header
|
|
37
|
+
- sorted input object keys
|
|
38
|
+
- sorted assertions
|
|
39
|
+
- two-space indentation
|
|
40
|
+
- one trailing newline
|
|
41
|
+
- no timestamps or random identifiers
|
|
42
|
+
|
|
43
|
+
The output is an ordinary `.mcpr` file. It can be edited, reviewed in a pull request, copied, and run without the authoring wizard.
|
|
44
|
+
|
|
45
|
+
## Input behavior
|
|
46
|
+
|
|
47
|
+
The wizard understands common JSON Schema input types:
|
|
48
|
+
|
|
49
|
+
- required and optional object properties
|
|
50
|
+
- strings
|
|
51
|
+
- numbers and integers
|
|
52
|
+
- booleans
|
|
53
|
+
- arrays and objects entered as JSON
|
|
54
|
+
- property defaults
|
|
55
|
+
|
|
56
|
+
Unsupported or highly dynamic schemas can still be tested by editing the generated `.mcpr` file afterward. Secret values should be represented through environment variables in the target or generated file; never paste reusable credentials into assertions.
|
|
57
|
+
|
|
58
|
+
## Response field selection
|
|
59
|
+
|
|
60
|
+
Responses are flattened into stable paths such as:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
$.structuredContent.id
|
|
64
|
+
$.content[0].text
|
|
65
|
+
$.messages[0].content.text
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Object keys are sorted and array order is retained. Display previews are capped. Select only stable business fields; prefer `exists` for generated IDs and avoid equality checks on timestamps, tokens, or volatile metadata.
|
|
69
|
+
|
|
70
|
+
## Automation API
|
|
71
|
+
|
|
72
|
+
The authoring engine accepts an injected `PromptAdapter`. The included `ScriptedPromptAdapter` lets CI and framework tests run the entire wizard without terminal input. Programmatic APIs are exported from `mcprigor`:
|
|
73
|
+
|
|
74
|
+
- `authorTest`
|
|
75
|
+
- `renderAuthoredTest`
|
|
76
|
+
- `flattenResponse`
|
|
77
|
+
- `createReadlinePromptAdapter`
|
|
78
|
+
- `ScriptedPromptAdapter`
|
|
79
|
+
|
|
80
|
+
This separation keeps discovery, prompting, execution, rendering, and file writing independently testable.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Background: MCP testing landscape
|
|
2
|
+
|
|
3
|
+
> Non-normative research. This page explains product positioning; it is not needed to use MCP Rigor.
|
|
4
|
+
|
|
5
|
+
## Executive summary
|
|
6
|
+
|
|
7
|
+
MCP testing tools currently fall into five categories: interactive inspectors, scriptable probes, official protocol conformance, SDK/framework-local tests, and semantic or security evaluators. The strongest opening for MCP Rigor is a transport-neutral, deterministic, black-box application test runner: **“Playwright for MCP.”**
|
|
8
|
+
|
|
9
|
+
MCP Rigor should complement the Inspector and official Conformance project rather than suggest it replaces either.
|
|
10
|
+
|
|
11
|
+
## Landscape
|
|
12
|
+
|
|
13
|
+
| Tool | Primary role | What it does well | Gap relative to MCP Rigor |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| [MCP Inspector](https://github.com/modelcontextprotocol/inspector) | Official interactive debugger | Explore connections, capabilities, tools, resources, prompts, notifications, and logs | Primarily manual exploration rather than a scenario/assertion/reporting framework |
|
|
16
|
+
| [MCP Inspector CLI](https://github.com/modelcontextprotocol/inspector#cli-mode) | Scriptable probe | Programmatic one-shot MCP interactions | Tests, fixtures, captures, deterministic assertion semantics, and CI reports remain limited or external |
|
|
17
|
+
| [Official MCP Conformance](https://github.com/modelcontextprotocol/conformance) | Protocol compliance/interoperability | Repeatable client/server protocol checks | Evolving protocol suite rather than application-domain regression testing |
|
|
18
|
+
| [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) | SDK and in-memory testing | Typed clients and in-process transport testing | Language/repository coupled; in-memory tests do not cover deployed transport boundaries |
|
|
19
|
+
| [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) | SDK and in-memory testing | Python integration tests and memory helpers | Language/repository coupled rather than a universal black-box suite |
|
|
20
|
+
| [FastMCP testing](https://gofastmcp.com/patterns/testing) | Python framework testing | Convenient deterministic pytest/in-process testing | Framework-specific and can bypass subprocess, HTTP, auth, proxy, and deployment behavior |
|
|
21
|
+
| [mcptools](https://github.com/f/mcptools) | CLI probing | Shell-friendly list/call/read operations | Assertion model, scenarios, reports, fixtures, and coverage are external |
|
|
22
|
+
| [Promptfoo MCP provider](https://www.promptfoo.dev/docs/providers/mcp/) | Behavioral/agentic evaluation | Tool selection and response-quality evaluation with reports | LLM/model behavior can be probabilistic; not wire or deterministic application testing |
|
|
23
|
+
| [mcp-vibetest](https://github.com/ComposioHQ/mcp-vibetest) | Agentic semantic evaluation | Realistic task-completion checks | Probabilistic and complementary to hard deterministic gates |
|
|
24
|
+
| [mcp-scan](https://github.com/invariantlabs-ai/mcp-scan) | Security scanning | Tool-poisoning and prompt/config risk detection | Specialized security gate, not functional regression testing |
|
|
25
|
+
| [Cisco MCP Scanner](https://github.com/cisco-ai-defense/mcp-scanner) | Security scanning | MCP-focused security analysis | Specialized scanner rather than behavior/protocol test runner |
|
|
26
|
+
| [MCPJam Inspector](https://github.com/MCPJam/inspector) | Interactive workbench | Friendly exploratory MCP development | Primarily interactive; deterministic CI should not be assumed without specific current support |
|
|
27
|
+
|
|
28
|
+
Project details and release status change quickly. Pin versions and verify current primary documentation before making compatibility claims.
|
|
29
|
+
|
|
30
|
+
## Positioning
|
|
31
|
+
|
|
32
|
+
### Category
|
|
33
|
+
|
|
34
|
+
**Deterministic MCP application testing.**
|
|
35
|
+
|
|
36
|
+
### One-line message
|
|
37
|
+
|
|
38
|
+
> MCP Rigor is the open-source test runner for repeatable MCP server behavior across stdio and Streamable HTTP.
|
|
39
|
+
|
|
40
|
+
### Memorable message
|
|
41
|
+
|
|
42
|
+
> Playwright for MCP: author once, run the same scenarios locally and in CI.
|
|
43
|
+
|
|
44
|
+
### Naming rationale
|
|
45
|
+
|
|
46
|
+
“MCP Rigor” uses established developer-tool terminology, clearly describes the project’s scope, and remains independent from any specific MCP server or vendor brand. Registry and trademark availability should still be verified before publication.
|
|
47
|
+
|
|
48
|
+
## Durable differentiation
|
|
49
|
+
|
|
50
|
+
1. **Application workflows, not only probes:** multi-step scenarios, captures, fixtures, setup/teardown, and side-effect verification.
|
|
51
|
+
2. **Real boundaries:** subprocess lifecycle, stdio framing, Streamable HTTP, auth, TLS/proxy, reconnect, and cleanup.
|
|
52
|
+
3. **Stable CI contract:** deterministic exit codes, JSON/JUnit/SARIF, traces, artifacts, filtering, and policy-controlled retries.
|
|
53
|
+
4. **MCP-aware assertions:** tools/resources/prompts, errors, notifications, progress, pagination, cancellation, capability/version matrices, and subscriptions.
|
|
54
|
+
5. **Declarative and programmable:** safe YAML/JSON for most cases plus a typed API and explicit plugin model for advanced projects.
|
|
55
|
+
6. **Layered oracles:** deterministic assertions as hard gates; optional semantic/LLM evaluation as a clearly labeled soft layer.
|
|
56
|
+
7. **Record to regression:** capture an exploratory interaction, sanitize secrets/dynamic values, and generate a checked-in test.
|
|
57
|
+
8. **Evidence, not certification:** run or aggregate exact official conformance profiles without making blanket compliance claims.
|
|
58
|
+
|
|
59
|
+
## What not to become
|
|
60
|
+
|
|
61
|
+
- another generic MCP chat client
|
|
62
|
+
- another Inspector UI as the first product
|
|
63
|
+
- an unofficial certification authority
|
|
64
|
+
- a Python- or TypeScript-framework-specific helper
|
|
65
|
+
- an LLM evaluation platform whose core results are nondeterministic
|
|
66
|
+
- a broad security scanner that dilutes functional testing
|
|
67
|
+
|
|
68
|
+
## Launch wedge
|
|
69
|
+
|
|
70
|
+
Target teams that have one or more MCP servers in CI and currently use shell scripts, Inspector screenshots, ad hoc SDK tests, or manual checks. The first compelling demo should:
|
|
71
|
+
|
|
72
|
+
1. run the same calculator test against stdio and HTTP targets;
|
|
73
|
+
2. show a clear structural diff for a broken tool response;
|
|
74
|
+
3. capture a value and reuse it in a later step;
|
|
75
|
+
4. verify a protocol error and timeout;
|
|
76
|
+
5. export JUnit in GitHub Actions;
|
|
77
|
+
6. prove the child process is cleaned up after failure.
|
|
78
|
+
|
|
79
|
+
## Suggested public narrative
|
|
80
|
+
|
|
81
|
+
“The MCP ecosystem already has excellent tools to inspect a server and increasingly strong official protocol conformance checks. MCP Rigor addresses a different question: does your server still perform the domain behaviors your users depend on? It turns those behaviors into deterministic scenarios that run over real transports on every pull request.”
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# MCP Test Language 1
|
|
2
|
+
|
|
3
|
+
Status: compatibility-stable frontend for MCP Rigor 0.12.
|
|
4
|
+
|
|
5
|
+
The `.mcpr` language and YAML compile to the same `Suite` runtime model. Every user-authored YAML capability has a deterministic plain-language equivalent; YAML remains available for generated files and programmatic integrations rather than being a more powerful test format.
|
|
6
|
+
|
|
7
|
+
## Design goals
|
|
8
|
+
|
|
9
|
+
- Readable by QA professionals without programming experience
|
|
10
|
+
- Deterministic: no LLM or fuzzy interpretation
|
|
11
|
+
- Two-space indentation and precise file/line/column diagnostics
|
|
12
|
+
- Safe data blocks delegated to YAML after the outer statement is recognized
|
|
13
|
+
- Backward-compatible with MCP Rigor 0.5 `.mcpr` files
|
|
14
|
+
|
|
15
|
+
A file may begin with:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
MCP Test 1
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Unknown language versions are rejected.
|
|
22
|
+
|
|
23
|
+
## Lexical rules
|
|
24
|
+
|
|
25
|
+
- UTF-8 text; LF and CRLF accepted
|
|
26
|
+
- Tabs are rejected
|
|
27
|
+
- Indentation must be a multiple of two spaces
|
|
28
|
+
- `#` starts a comment on a standalone line
|
|
29
|
+
- Declaration keywords are case-insensitive for compatibility
|
|
30
|
+
- Tool, flow, test, variable, and ID values retain their case
|
|
31
|
+
- Strings may use single or double quotes
|
|
32
|
+
- Indented `with:` blocks use safe YAML values
|
|
33
|
+
|
|
34
|
+
The formal frontend emits located nodes with UTF-16 offsets, line, column, semantic span, indentation, and declaration kind. Compilation currently lowers this document through the compatibility compiler so runtime behavior remains stable.
|
|
35
|
+
|
|
36
|
+
## Document declarations
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
MCP Test 1
|
|
40
|
+
Suite: "Customer tests"
|
|
41
|
+
Server: node dist/server.js
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
HTTP:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
MCP URL: https://qa.example.com/mcp
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Target options use a readable settings block:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
Server options:
|
|
54
|
+
cwd: ./server
|
|
55
|
+
env:
|
|
56
|
+
MODE: test
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
Server options:
|
|
61
|
+
headers:
|
|
62
|
+
Authorization: "Bearer ${env.QA_TOKEN}"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Parity targets use the same connection grammar:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
Compare target "Local": node server.js
|
|
69
|
+
Compare target "QA": https://qa.example.com/mcp
|
|
70
|
+
|
|
71
|
+
Target options for "QA":
|
|
72
|
+
headers:
|
|
73
|
+
Authorization: "Bearer ${env.QA_TOKEN}"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Suite-level YAML fields have direct equivalents:
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
Default timeout: 10 seconds
|
|
80
|
+
Redact: "secret-value", "token-value"
|
|
81
|
+
Snapshots: snapshots.json
|
|
82
|
+
Ignore snapshot paths: "$.createdAt", "$.requestId"
|
|
83
|
+
|
|
84
|
+
Client behavior:
|
|
85
|
+
roots:
|
|
86
|
+
- uri: file:///workspace
|
|
87
|
+
name: Workspace
|
|
88
|
+
sampling:
|
|
89
|
+
model: fixture
|
|
90
|
+
text: deterministic response
|
|
91
|
+
elicitation:
|
|
92
|
+
action: accept
|
|
93
|
+
content:
|
|
94
|
+
approved: true
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Imports
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
Import flows from "./shared/customer-flows.mcpr"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Only `Flow:` declarations are imported. Imported tests, server declarations, data sources, and top-level configuration never execute. Paths resolve relative to the importer. Canonical path cycles are rejected.
|
|
104
|
+
|
|
105
|
+
## Flows
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
Flow: "Verify addition"
|
|
109
|
+
Inputs: a, b=1, expected
|
|
110
|
+
|
|
111
|
+
Call tool "add" with:
|
|
112
|
+
a: "${a}"
|
|
113
|
+
b: "${b}"
|
|
114
|
+
|
|
115
|
+
Expect "structuredContent.sum" equals "${expected}"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Inputs without `=` are required. Inputs with defaults are optional. Unknown supplied inputs and missing required inputs are compilation errors. Recursive flows are rejected.
|
|
119
|
+
|
|
120
|
+
Use a flow:
|
|
121
|
+
|
|
122
|
+
```text
|
|
123
|
+
Use flow "Verify addition" with:
|
|
124
|
+
a: 4
|
|
125
|
+
expected: 5
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Flow invocations receive isolated prefixed variables. Caller values are available only when passed through declared inputs.
|
|
129
|
+
|
|
130
|
+
## Tests and dependencies
|
|
131
|
+
|
|
132
|
+
```text
|
|
133
|
+
Test: "Create customer"
|
|
134
|
+
Id: create-customer
|
|
135
|
+
Require: tools
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
Test: "Retrieve customer"
|
|
140
|
+
Depends on: create-customer
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Additional test settings:
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
Skip: "Not enabled in this environment"
|
|
147
|
+
|
|
148
|
+
Variables:
|
|
149
|
+
tenant: acme
|
|
150
|
+
retryCount: 3
|
|
151
|
+
|
|
152
|
+
Require protocol: "2025-06-18"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`Skip` without a reason maps to `skip: true`. IDs are unique. Dependencies form an acyclic graph and must pass before the consumer opens a session.
|
|
156
|
+
|
|
157
|
+
## Actions
|
|
158
|
+
|
|
159
|
+
```text
|
|
160
|
+
Call tool "search" with:
|
|
161
|
+
query: "red shoes"
|
|
162
|
+
|
|
163
|
+
Read resource "catalog://status"
|
|
164
|
+
|
|
165
|
+
Get prompt "review" with:
|
|
166
|
+
topic: "release"
|
|
167
|
+
|
|
168
|
+
Send "ping"
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Expectations and values
|
|
172
|
+
|
|
173
|
+
```text
|
|
174
|
+
Expect it succeeds
|
|
175
|
+
Expect an error
|
|
176
|
+
Expect "structuredContent.total" equals 2
|
|
177
|
+
Expect "content[0].text" contains "complete"
|
|
178
|
+
Expect "items" exists
|
|
179
|
+
Expect "items" has 3 items
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Full assertion vocabulary:
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
Expect "status" does not equal "deleted"
|
|
186
|
+
Expect "count" is a number
|
|
187
|
+
Expect "customerId" matches "^C-[0-9]+$"
|
|
188
|
+
Expect error code -32602
|
|
189
|
+
Expect error message matches "invalid input"
|
|
190
|
+
Expect "structuredContent" matches schema:
|
|
191
|
+
type: object
|
|
192
|
+
required: [customerId]
|
|
193
|
+
Expect "structuredContent" matches snapshot "customer" ignoring "$.createdAt"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Equality is type-sensitive. No implicit text/number coercion occurs. Schema blocks use safe YAML only after the deterministic outer statement is recognized.
|
|
197
|
+
|
|
198
|
+
## Variables, exports, and utilities
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
Save "structuredContent.id" as "localId"
|
|
202
|
+
Export "structuredContent.id" as "customerId"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Local values use `${localId}`. Dependency outputs use `${deps.create-customer.customerId}`. Persisted state uses `${state.create-customer.customerId}`.
|
|
206
|
+
|
|
207
|
+
```text
|
|
208
|
+
Set "normalized" using "lowercase" with:
|
|
209
|
+
value: "${row.Email}"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Data iteration
|
|
213
|
+
|
|
214
|
+
```text
|
|
215
|
+
For each row:
|
|
216
|
+
| caseId | input | expected |
|
|
217
|
+
| first | 2 | 4 |
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Plain-language engineered sources:
|
|
221
|
+
|
|
222
|
+
```text
|
|
223
|
+
Data source: "customers"
|
|
224
|
+
From CSV "customers.csv"
|
|
225
|
+
Column "customerId" is string required
|
|
226
|
+
Column "spend" is number required
|
|
227
|
+
Column "tier" is string one of gold, silver, bronze
|
|
228
|
+
Derive "label" as "${customerId}:${tier}"
|
|
229
|
+
Keep rows where "spend" is greater than 100
|
|
230
|
+
Sample 25 rows with seed 2025
|
|
231
|
+
Cache this source
|
|
232
|
+
|
|
233
|
+
Test: "Active customer"
|
|
234
|
+
For each row from "customers"
|
|
235
|
+
Call tool "find_customer" with:
|
|
236
|
+
customerId: "${row.customerId}"
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
File forms are `From CSV`, `From JSON`, `From YAML`, and `From Excel ... sheet ...`. Remote sources use `From REST`. Existing structured settings remain accepted inside a `Data source` block for Google Sheets, SQL, custom plugins, joins, and uncommon provider-specific options, so there is no capability gap with YAML. Remote and custom-code safety flags remain mandatory.
|
|
240
|
+
|
|
241
|
+
See `DATA-AND-REUSE.md` and `DATA-ENGINEERING.md`.
|
|
242
|
+
|
|
243
|
+
## Setup and cleanup
|
|
244
|
+
|
|
245
|
+
```text
|
|
246
|
+
Setup:
|
|
247
|
+
Call tool "prepare"
|
|
248
|
+
|
|
249
|
+
Steps:
|
|
250
|
+
Call tool "execute"
|
|
251
|
+
|
|
252
|
+
Cleanup:
|
|
253
|
+
Call tool "remove"
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Cleanup actions are attempted even after an earlier failure. Cleanup should be idempotent.
|
|
257
|
+
|
|
258
|
+
## MCP-native actions
|
|
259
|
+
|
|
260
|
+
```text
|
|
261
|
+
Subscribe to resource "customer://updates"
|
|
262
|
+
Wait for notification "notifications/resources/updated" within 5 seconds
|
|
263
|
+
Unsubscribe from resource "customer://updates"
|
|
264
|
+
Set log level to "debug"
|
|
265
|
+
List all tools
|
|
266
|
+
List all resources
|
|
267
|
+
List all prompts
|
|
268
|
+
List all resource templates
|
|
269
|
+
Get task "task-1"
|
|
270
|
+
List tasks
|
|
271
|
+
Cancel task "task-1"
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Progress and cancellation:
|
|
275
|
+
|
|
276
|
+
```text
|
|
277
|
+
Call tool "import" with progress and cancel after 500 ms with:
|
|
278
|
+
source: catalog.csv
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
These compile to the same `native` step objects accepted by YAML.
|
|
282
|
+
|
|
283
|
+
## Diagnostics
|
|
284
|
+
|
|
285
|
+
A diagnostic includes a stable code, source location, original line, caret, explanation, and correction:
|
|
286
|
+
|
|
287
|
+
```text
|
|
288
|
+
MCPLANG102 tests/customer.mcpr:8:1
|
|
289
|
+
|
|
290
|
+
Call tool "create"
|
|
291
|
+
^
|
|
292
|
+
|
|
293
|
+
Indentation must use multiples of two spaces.
|
|
294
|
+
Try: use 0, 2, 4, or 6 leading spaces
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Current namespaces:
|
|
298
|
+
|
|
299
|
+
- `MCPLANG1xx`: lexical/version errors
|
|
300
|
+
- `MCPLANG2xx`: structural errors
|
|
301
|
+
- `MCPLANG3xx`: import errors
|
|
302
|
+
- `MCPLANG4xx`: symbol, flow, and reference errors
|
|
303
|
+
- `MCP-DEP-*`: dependency graph errors
|
|
304
|
+
- `QA-DATA-*` / `MCP-DATA-*`: data compilation/provider errors
|
|
305
|
+
|
|
306
|
+
## Grammar summary
|
|
307
|
+
|
|
308
|
+
```ebnf
|
|
309
|
+
document = version? declaration* ;
|
|
310
|
+
declaration = suite | server | import | flow | dataSource | test ;
|
|
311
|
+
flow = "Flow:" name flowProperty* statement* ;
|
|
312
|
+
test = "Test:" name testProperty* statement* ;
|
|
313
|
+
statement = callTool | readResource | getPrompt | send | expect
|
|
314
|
+
| save | export | wait | set | useFlow | forEach | section ;
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The vocabulary is closed. New behavior requires a documented language-version-compatible statement rather than fuzzy natural-language interpretation.
|