Your MCP tool returned success. Did it write the right thing?
Regression tests for MCP tool responses and the state they change. Declare file, directory, SQLite, or custom-probe checks in YAML; compare against expectations, a baseline, or another server.
The official filesystem server's edit_file used to replace CRLF line endings with LF while returning the expected edit diff. Upstream fixed it in PR #5011. We reproduced the historical regression using published versions:
MATCH 2026.8.31 response-only actual: c\nb\n
DIVERGE 2026.8.31 state-observed expected: c\r\nb\r\n
MATCH 2.0.0 fixed-control actual: c\r\nb\r\n
Watch the recorded demo · Reproduce it · Read the captured output
A direct SDK test with the same file assertion catches this too. MCP Behavior gives you one contract, verdict, and evidence bundle. It checks the effects you declare; it does not discover every side effect.
Requires uv and Python 3.11+. No API key or existing server needed.
uvx --from git+https://github.com/GWeale/mcp-behavior.git@v0.1.0 mcp-behavior demoThis separate, intentional invoice fixture runs three real checks and removes its temporary files. It writes 109 while returning saved: true for a requested total of 100:
MATCH response only: file total = 109
DIVERGE response + file state: file total = 109
MATCH corrected implementation: file total = 100
uv tool install git+https://github.com/GWeale/mcp-behavior.git@v0.1.0
mcp-behavior initThe starter includes a file assertion. Edit the server command, tool arguments, expected path, and contents in mcp-behavior.yaml, then run:
mcp-behavior verify mcp-behavior.yamlUse mcp-behavior init --template sqlite for database rows, or --template response for tools with no state changes. For semantic JSON comparisons, adapt the working JSON probe. See the complete example, observers, and contract reference.
| Result | Meaning | Exit |
|---|---|---|
MATCH |
The selected checks agree. | 0 |
DIVERGE |
A response or declared effect differs. | 1 |
INCONCLUSIVE |
The run could not establish a result. | 2 |
Each run saves evidence and differences. Export reports as JSON, Markdown, or JUnit, or use the GitHub Action in CI.
Found a response that hides a wrong state change? Open a minimal, sanitized case with server/version, request, expected state, and actual state. Reproducible cases are especially useful.
CLI · Python API · Evidence · Examples · Authenticated HTTP · Contributing
Alpha: install from the pinned GitHub tag or download a wheel from v0.1.0. See compatibility for schema guarantees. Configured servers and probes run as trusted code; see security. No telemetry or model calls.
