Setup
One install connects a coding agent to the runs in your repository. The server is a .NET tool. It reads .prototrace archives and answers questions about them over the Model Context Protocol.
Install
dotnet tool install --global ProtoTest.Mcp
The tool command is prototest-mcp. The package targets .NET 8, 9 and 10, so the install picks the framework your SDK has.
Register it
An MCP client starts the server and talks to it over stdio. Add the server to the client's configuration file. The shape is the same everywhere; only the file and the root key change.
{"mcpServers": {"prototest": {"command": "prototest-mcp","args": ["--project", "."]}}}
The server resolves . against its working directory. Keep the file at the repository root. If the client starts the server elsewhere, pass an absolute --project path.
Check it
Three steps, none of which needs a suite of your own.
-
Read a committed failing run with the CLI. Download l0-environment-drill.prototrace from the Learn track, then:
dotnet tool install --global ProtoTest.Cliprototest summary l0-environment-drill.prototraceProtoTest trace 2.0 · run bb2dd8b330924038894c161efda1e5f4 · 2026-09-29 18:36:55Z - 2026-09-29 18:36:58Z1 tests · 1 failedFAILED Northstar.ProtoTest.FailureDrills.TheAddressWasHardcodedForOneMachine (2.60 s)ConnectionError reaching http://127.0.0.1:5099: connection refused.test.execution Test execution · failedcause: runner-reported failureThat is the drill file's own output, so it matches what you just downloaded; your own runs print different ids and times.
prototest summaryprints the same diagnosis the MCP tools return, which makes it the quickest way to check that the file an agent would read says what you expect. The CLI reference documents all four verbs, their arguments and their exit codes. -
Point the server at one file with
--trace, or at a folder of runs with--project. For one archive,--traceworks wherever the file was written. -
Run your own suite once so a
.prototraceexists, and ask the agent to list the runs. It should answer with a run id and a trace file from your machine.
Where it reads
"Newest" is the run's recorded start time, never a file timestamp. An archive the reader cannot open is skipped with a reason in list_runs and never guessed at.
The default trace lands below the test project's build output, and the walk skips bin, so the server cannot see it from the repository root. Give the suite a results folder the server can see. The continuous integration page sets that up with one environment variable, so CI and local runs write to the same place:
var results = Environment.GetEnvironmentVariable("PROTOTEST_RESULTS")
?? Path.Combine("TestResults", "ProtoTest");
builder.ConfigureTracing(trace =>
trace.OutputPath = Path.Combine(results, "run.prototrace"));
Set PROTOTEST_RESULTS to an absolute path such as <repository>/TestResults when you run locally.
Give the agent the skill
The repository carries one skill that teaches the evidence loop and the four tools: skills/prototest-evidence-loop/SKILL.md. It is copy-in, not an install.
A client that reads skills folders (Claude Code, for example) loads it from its skills directory. From a checkout of the ProtoTest repository:
mkdir -p .claude/skills
cp -r skills/prototest-evidence-loop .claude/skills/
Otherwise download the file from the repository and place it in the same layout. A client without a skills folder reads the file as an instruction instead: paste its body into the client's rules or instructions file.
The skill is optional. The MCP server's tool descriptions are the contract, so an agent without the bundle can still list the tools and work from them.
What the agent can see
The tools read your traces and return their content, including expected and actual values, to the connected agent, so run the server as an identity that may see them.
Every tool is read-only and returns a compact JSON document. list_runs over a folder holding one failing run:
{
"root": "C:/dev/your-repo",
"runs": [
{
"runId": "761778e6dc82498a9f9965fa1e6b5a24",
"traceFile": "C:/dev/your-repo/TestResults/run.prototrace",
"startedAtUtc": "2026-09-29T06:19:01Z",
"completedAtUtc": "2026-09-29T06:19:05Z",
"outcomes": { "failed": 1 },
"failingTests": [ { "testId": "00001", "name": "TheAddressWasHardcodedForOneMachine" } ],
"failingTestsTruncated": false
}
],
"truncated": false,
"skipped": null
}
The run id, file paths and timestamps above stand in for any run; a real call returns your machine's.
| Tool | Input | Returns | Cap |
|---|---|---|---|
list_runs | optional folder, limit (default 10) | the newest runs first: run id, trace file, start and completion, outcome counts, failing test ids, and the archives it had to skip | 50 runs |
get_failure | optional runId, testId | the failure entry: outcome, error, source location, the selected failing operation, the shape mismatches and the test's artifacts | 10 failed operations, 25 mismatches |
get_diagnosis | optional runId, testId, detail (summary or context) | the run's diagnosis, or one failing test's context package | the diagnosis caps |
get_coverage | optional runId, target, category, includeUncovered, offset, limit | coverage totals and uncovered units from the report the run embedded | 200 uncovered units |
Diagnosis explains what get_failure and get_diagnosis return and what the agent can do with it.
Limits
- Read-only: no trace is written, no suite is rerun, the stdio host binds no port, and nothing on disk is modified.
- Nothing leaves the machine by default: no telemetry, no uploads, no accounts. The stdio host reads local archives, stdout carries the protocol only, and logs go to stderr.
- Hard caps bound every payload.
list_runsreturns at most 50 runs,get_coverageat most 200 uncovered units, andget_diagnosisapplies the diagnosis caps. - The server reads evidence that already exists. A run with no
.prototraceis not visible to it; write the trace first. - One external dependency: the official
ModelContextProtocolSDK (Apache-2.0). - The demo endpoint is a local sample. See Coding agents.