mcp-evals
Behavioral evaluation and description linting for Model Context Protocol (MCP) servers.
Status: v0.4 — stdio + HTTP JSON-RPC discovery, description lint (including
name-description-mismatch), and mock/OpenAI-compatible tool-selection evals.
60-second try
docker compose run --rm run-example # mock eval, no API key
docker compose run --rm lint-example # live stdio lint
docker compose run --rm test # pytest
Why this vs alternatives
| Approach | Strength | Gap |
|---|---|---|
| mcp-evals | Lint + YAML evals + mock CI runner | Not a full agent harness |
| MCP Inspector | Interactive debugging | No CI lint/eval suite |
| Protocol conformance tests | JSON-RPC correctness | Do not test tool selection |
| Hand-written LLM mocks | Full control | Drift from real descriptions |
Problem
Protocol conformance tests verify JSON-RPC correctness. They do not verify whether an LLM agent selects the right tool, passes sensible arguments, or completes the task. Tool descriptions are now load-bearing API design, and there is no standard way to test them.
mcp-evals fills the behavioral layer: lint tool descriptions, define eval cases in YAML, and (next) measure tool-selection accuracy in CI.
Key features (v0.4)
- Description linter — missing descriptions, undocumented required params, overlapping tools, ambiguous verbs,
name-description-mismatch - Live discover — handshake a stdio or HTTP JSON-RPC MCP server (or load a catalog fixture)
- Eval runner —
mcp-evals runwith--model mock(CI),--live SERVER.yaml, or an OpenAI-compatible endpoint - CLI + Docker + GitHub Action — lint and optional eval in CI without a cloud key (mock selector)
Architecture
┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ CLI │────▶│ Linter / Runner │────▶│ Models (Pydantic)│
│ mcp-evals │ │ spec_loader │ │ EvalSuite, etc. │
└─────────────┘ └──────────────────┘ └─────────────────┘
│
(next) MCP client + LLM
| Component | Technology | Why |
|---|---|---|
| Language | Python 3.11+ | MCP SDK ecosystem, pytest integration |
| CLI | Click | Mature, composable commands |
| Schemas | Pydantic v2 | Strict validation, good errors |
| Logging | structlog | Structured, JSON-capable |
| Config | pydantic-settings | Env-based, typed |
| Tests | pytest + ruff + mypy | Standard Python OSS stack |
Installation
pip install mcp-tool-evals
# or from source:
pip install -e ".[dev]"
Local development
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
mcp-evals health
mcp-evals lint examples/tools.yaml
mcp-evals discover examples/server.yaml
mcp-evals lint --live examples/server.yaml
mcp-evals validate-spec examples/eval-suite.yaml
mcp-evals run examples/eval-suite.yaml --catalog examples/tools.yaml --model mock
pytest tests/ -v
Docker
# Health check
docker compose run --rm dev
# Run tests
docker compose run --rm test
# Lint a live stdio server (this example passes)
docker compose run --rm lint-example
# Discover tools from the example calc server
docker compose run --rm discover-example
# Mock eval run (no API key)
docker compose run --rm run-example
Configuration
Copy .env.example to .env:
| Variable | Default | Description |
|---|---|---|
MCP_EVALS_LOG_LEVEL |
INFO |
Log level |
MCP_EVALS_LOG_JSON |
false |
JSON log output |
MCP_EVALS_DEFAULT_MODEL |
gpt-4o-mini |
Model for eval runs (future) |
MCP_EVALS_PASS_THRESHOLD |
0.8 |
Minimum selection accuracy |
Usage
Lint tool descriptions
mcp-evals lint examples/tools.yaml
mcp-evals lint --live examples/server.yaml
mcp-evals discover examples/server.yaml
mcp-evals lint examples/tools.yaml --format json
mcp-evals lint examples/tools.yaml --fail-on-warning
Run behavioral evals
mcp-evals run examples/eval-suite.yaml --catalog examples/tools.yaml --model mock
mcp-evals run examples/eval-suite.yaml --catalog examples/tools.yaml \
--model llama3.2 --base-url http://localhost:11434/v1 --pass-threshold 0.8
# or discover tools from a live server that matches the suite:
# mcp-evals run suite.yaml --live server.yaml --model mock
Validate eval suite
mcp-evals validate-spec examples/eval-suite.yaml
Health check
mcp-evals health
Example eval suite
See examples/eval-suite.yaml:
name: document-server-behavior
cases:
- id: search-by-keyword
request: Find documents about quarterly revenue
expected_tool:
name: search_documents
arguments:
query: quarterly revenue
Running tests
pytest tests/ -v
ruff check src tests
mypy src
Development workflow
- Add linter rules in
src/mcp_evals/linter/ - Add runner logic in
src/mcp_evals/runner/ - Add tests in
tests/ - Update examples in
examples/
Roadmap
- MCP client: stdio discover + lint --live
- LLM eval runner (mock + OpenAI-compatible)
- HTTP JSON-RPC MCP transport
-
name-description-mismatchlinter rule - Streamable HTTP/SSE MCP transport
- GitHub Action PR comments and accuracy deltas
Known limitations (v0.4)
- Streamable HTTP/SSE MCP is not implemented — HTTP is JSON-RPC POST only
- Mock selector does not fill tool arguments (accuracy is tool-name only)
- Live Ollama/OpenAI evals need a reachable
--base-url; CI uses--model mock examples/tools.yamlis intentionally dirty somcp-evals lintcan show findings
Contributing
See CONTRIBUTING.md.
License
MIT — see LICENSE.
Release files for mcp-tool-evals 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mcp_tool_evals-0.4.0.tar.gz | 25.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mcp_tool_evals-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:46.6 kB
Release files / mcp_tool_evals-0.4.0.tar.gz
| Download URL | mcp_tool_evals-0.4.0.tar.gz |
|---|---|
| Size | 25.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
089e0628bbf2cd169eb2e265aaca7fe755a3831f73735c8b8e4f1c8cc2f751d4
|
|
BLAKE2b-256 checksum How to use checksums |
2c3cd1117ebb53bfdbbfc2e5d5ff76129460124daa48a208eb6f66786975abcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Release files / mcp_tool_evals-0.4.0-py3-none-any.whl
| Download URL | mcp_tool_evals-0.4.0-py3-none-any.whl |
|---|---|
| Size | 21.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ad7a574e9d4f6c6d8b460ab62fa15af4671adf4c497fdb5d0526423d750a3e0c
|
|
BLAKE2b-256 checksum How to use checksums |
a996f2b9e8730549e683e9e692ea047c57f94945894e9158723bc7ea31e25fd4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|