MCP Test Language 1
Status: compatibility-stable frontend for MCP Rigor 0.12.
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.
Design goals
- Readable by QA professionals without programming experience
- Deterministic: no LLM or fuzzy interpretation
- Two-space indentation and precise file/line/column diagnostics
- Safe data blocks delegated to YAML after the outer statement is recognized
- Backward-compatible with MCP Rigor 0.5
.mcprfiles
A file may begin with:
MCP Test 1
Unknown language versions are rejected.
Lexical rules
- UTF-8 text; LF and CRLF accepted
- Tabs are rejected
- Indentation must be a multiple of two spaces
#starts a comment on a standalone line- Declaration keywords are case-insensitive for compatibility
- Tool, flow, test, variable, and ID values retain their case
- Strings may use single or double quotes
- Indented
with:blocks use safe YAML values
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.
Document declarations
MCP Test 1
Suite: "Customer tests"
Server: node dist/server.js
HTTP:
MCP URL: https://qa.example.com/mcp
Target options use a readable settings block:
Server options:
cwd: ./server
env:
MODE: test
Server options:
headers:
Authorization: "Bearer ${env.QA_TOKEN}"
Parity targets use the same connection grammar:
Compare target "Local": node server.js
Compare target "QA": https://qa.example.com/mcp
Target options for "QA":
headers:
Authorization: "Bearer ${env.QA_TOKEN}"
Suite-level YAML fields have direct equivalents:
Default timeout: 10 seconds
Redact: "secret-value", "token-value"
Snapshots: snapshots.json
Ignore snapshot paths: "$.createdAt", "$.requestId"
Client behavior:
roots:
- uri: file:///workspace
name: Workspace
sampling:
model: fixture
text: deterministic response
elicitation:
action: accept
content:
approved: true
Imports
Import flows from "./shared/customer-flows.mcpr"
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.
Flows
Flow: "Verify addition"
Inputs: a, b=1, expected
Call tool "add" with:
a: "${a}"
b: "${b}"
Expect "structuredContent.sum" equals "${expected}"
Inputs without = are required. Inputs with defaults are optional. Unknown supplied inputs and missing required inputs are compilation errors. Recursive flows are rejected.
Use a flow:
Use flow "Verify addition" with:
a: 4
expected: 5
Flow invocations receive isolated prefixed variables. Caller values are available only when passed through declared inputs.
Tests and dependencies
Test: "Create customer"
Id: create-customer
Require: tools
Test: "Retrieve customer"
Depends on: create-customer
Additional test settings:
Skip: "Not enabled in this environment"
Variables:
tenant: acme
retryCount: 3
Require protocol: "2025-06-18"
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.
Actions
Call tool "search" with:
query: "red shoes"
Read resource "catalog://status"
Get prompt "review" with:
topic: "release"
Send "ping"
Expectations and values
Expect it succeeds
Expect an error
Expect "structuredContent.total" equals 2
Expect "content[0].text" contains "complete"
Expect "items" exists
Expect "items" has 3 items
Full assertion vocabulary:
Expect "status" does not equal "deleted"
Expect "count" is a number
Expect "customerId" matches "^C-[0-9]+$"
Expect error code -32602
Expect error message matches "invalid input"
Expect "structuredContent" matches schema:
type: object
required: [customerId]
Expect "structuredContent" matches snapshot "customer" ignoring "$.createdAt"
Equality is type-sensitive. No implicit text/number coercion occurs. Schema blocks use safe YAML only after the deterministic outer statement is recognized.
Variables, exports, and utilities
Save "structuredContent.id" as "localId"
Export "structuredContent.id" as "customerId"
Local values use ${localId}. Dependency outputs use ${deps.create-customer.customerId}. Persisted state uses ${state.create-customer.customerId}.
Set "normalized" using "lowercase" with:
value: "${row.Email}"
Data iteration
For each row:
| caseId | input | expected |
| first | 2 | 4 |
Plain-language engineered sources:
Data source: "customers"
From CSV "customers.csv"
Column "customerId" is string required
Column "spend" is number required
Column "tier" is string one of gold, silver, bronze
Derive "label" as "${customerId}:${tier}"
Keep rows where "spend" is greater than 100
Sample 25 rows with seed 2025
Cache this source
Test: "Active customer"
For each row from "customers"
Call tool "find_customer" with:
customerId: "${row.customerId}"
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.
See DATA-AND-REUSE.md and DATA-ENGINEERING.md.
Setup and cleanup
Setup:
Call tool "prepare"
Steps:
Call tool "execute"
Cleanup:
Call tool "remove"
Cleanup actions are attempted even after an earlier failure. Cleanup should be idempotent.
MCP-native actions
Subscribe to resource "customer://updates"
Wait for notification "notifications/resources/updated" within 5 seconds
Unsubscribe from resource "customer://updates"
Set log level to "debug"
List all tools
List all resources
List all prompts
List all resource templates
Get task "task-1"
List tasks
Cancel task "task-1"
Progress and cancellation:
Call tool "import" with progress and cancel after 500 ms with:
source: catalog.csv
These compile to the same native step objects accepted by YAML.
Diagnostics
A diagnostic includes a stable code, source location, original line, caret, explanation, and correction:
MCPLANG102 tests/customer.mcpr:8:1
Call tool "create"
^
Indentation must use multiples of two spaces.
Try: use 0, 2, 4, or 6 leading spaces
Current namespaces:
MCPLANG1xx: lexical/version errorsMCPLANG2xx: structural errorsMCPLANG3xx: import errorsMCPLANG4xx: symbol, flow, and reference errorsMCP-DEP-*: dependency graph errorsQA-DATA-/MCP-DATA-: data compilation/provider errors
Grammar summary
document = version? declaration* ;
declaration = suite | server | import | flow | dataSource | test ;
flow = "Flow:" name flowProperty* statement* ;
test = "Test:" name testProperty* statement* ;
statement = callTool | readResource | getPrompt | send | expect
| save | export | wait | set | useFlow | forEach | section ;
The vocabulary is closed. New behavior requires a documented language-version-compatible statement rather than fuzzy natural-language interpretation.