MCP Eval Runner
npm mcp-eval-runner package
A standardized testing harness for MCP servers and agent workflows. Define test cases as YAML fixtures (steps → expected tool calls → expected outputs), run regression suites directly from your MCP client, and get pass/fail results with diffs — without leaving Claude Code or Cursor.
Tool reference | Configuration | Fixture format | Contributing | Troubleshooting | Design principles
Key features
- YAML fixtures: Test cases are plain files in version control — diffable, reviewable, and shareable.
- Two execution modes: Live mode spawns a real MCP server and calls tools via stdio; simulation mode runs assertions against
expected_output without a server.
- Composable assertions: Combine
output_contains, output_not_contains, output_equals, output_matches, schema_match, tool_called, and latency_under per step.
- Step output piping: Reference a previous step's output in downstream inputs via
{{steps.<step_id>.output}}.
- Regression reports: Compare the current run to any past run and surface what changed.
- Watch mode: Automatically reruns the affected fixture when files change.
- CI-ready: Includes a GitHub Action for running evals on every config change.
Requirements
- Node.js v22.5.0 or newer.
- npm.
Getting started
Add the following config to your MCP client:
By default, eval fixtures are loaded from ./evals/ in the current working directory. To use a different path:
MCP Client configuration
Amp · Claude Code · Cline · Cursor · VS Code · Windsurf · Zed
Your first prompt
Create a file at evals/smoke.yaml. Use live mode (recommended) by including a server block:
Then enter the following in your MCP client:
Your client should return a pass/fail result for the smoke test.
Fixture format
Fixtures are YAML (or JSON) files placed in the fixtures directory. Each file defines one test case.
Top-level fields
server block (live mode)
When server is present the eval runner spawns the server as a child process, connects via MCP stdio transport, and calls each step's tool against the live server.
steps array
Each step has the following fields:
Execution modes
Live mode — fixture has a server block:
- The server is spawned and each step calls the named tool via MCP stdio.
- Assertions run against the real tool response.
- Errors from the server cause the step (and by default the case) to fail immediately.
Simulation mode — no server block:
- No server is started.
- Each step's output is taken from
expected_output (or empty string if absent).
- Assertions run against that static output.
- Useful for authoring and CI dry-runs, but
output_contains assertions will always fail if expected_output is not set.
Assertion types
All assertions go inside a step's expect block:
Multiple assertions in one expect block are all evaluated; the step fails if any assertion fails.
Step output piping
Reference the output of a previous step in a downstream step's input using {{steps.<step_id>.output}}:
Piping works in both live mode and simulation mode.
Note on create_test_case
Fixtures created with the create_test_case tool do not include a server block. They always run in simulation mode. To use live mode, add a server block manually to the generated YAML file.
Tools
Running
run_suite — execute all fixtures in the fixtures directory; returns a pass/fail summary
run_case — run a single named fixture by name
list_cases — enumerate available fixtures with step counts and descriptions
Authoring
create_test_case — create a new YAML fixture file (simulation mode; no server block)
scaffold_fixture — generate a boilerplate fixture with placeholder steps and pre-filled assertion comments
Reporting
regression_report — compare the current fixture state to the last run; surfaces regressions and fixes
compare_results — diff two specific runs by run ID
generate_html_report — generate a single-file HTML report for a completed run
Operations
evaluate_deployment_gate — CI gate; fails if recent pass rate drops below a configurable threshold
discover_fixtures — discover fixture files across one or more directories (respects FIXTURE_LIBRARY_DIRS)
Configuration
--fixtures / --fixtures-dir
Directory to load YAML/JSON eval fixture files from.
Type: string
Default: ./evals
--db / --db-path
Path to the SQLite database file used to store run history.
Type: string
Default: ~/.mcp/evals.db
--timeout
Maximum time in milliseconds to wait for a single step before marking it as failed.
Type: number
Default: 30000
--watch
Watch the fixtures directory and rerun the affected fixture automatically when files change.
Type: boolean
Default: false
--format
Output format for eval results.
Type: string
Choices: console, json, html
Default: console
--concurrency
Number of test cases to run in parallel.
Type: number
Default: 1
--http-port
Start an HTTP server on this port instead of stdio transport.
Type: number
Default: disabled (uses stdio)
Pass flags via the args property in your JSON config:
Design principles
- No mocking: Live mode evals run against real servers. Correctness is non-negotiable.
- Fixtures are text: YAML/JSON in version control; no proprietary formats or databases.
- Dogfood-first: The eval runner's own smoke fixture tests the eval runner itself.
Verification
Before publishing a new version, verify the server with MCP Inspector to confirm all tools are exposed correctly and the protocol handshake succeeds.
Interactive UI (opens browser):
CLI mode (scripted / CI-friendly):
Run before publishing to catch regressions in tool registration and runtime startup.
Contributing
New assertion types go in src/assertions.ts — implement the Assertion interface and add a test. Integration tests live under tests/ as unit tests and under evals/ as eval fixtures.
MCP Registry & Marketplace
This plugin is available on:
Search for mcp-eval-runner.