mcp-tool-evals 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. mcp_tool_evals-0.4.0/.dockerignore +9 -0
  2. mcp_tool_evals-0.4.0/.env.example +4 -0
  3. mcp_tool_evals-0.4.0/.github/ISSUE_TEMPLATE/bug_report.yml +18 -0
  4. mcp_tool_evals-0.4.0/.github/pull_request_template.md +13 -0
  5. mcp_tool_evals-0.4.0/.github/workflows/ci.yml +19 -0
  6. mcp_tool_evals-0.4.0/.gitignore +16 -0
  7. mcp_tool_evals-0.4.0/.pre-commit-config.yaml +11 -0
  8. mcp_tool_evals-0.4.0/CHANGELOG.md +37 -0
  9. mcp_tool_evals-0.4.0/CODE_OF_CONDUCT.md +22 -0
  10. mcp_tool_evals-0.4.0/CONTRIBUTING.md +51 -0
  11. mcp_tool_evals-0.4.0/LICENSE +21 -0
  12. mcp_tool_evals-0.4.0/PKG-INFO +235 -0
  13. mcp_tool_evals-0.4.0/README.md +199 -0
  14. mcp_tool_evals-0.4.0/SECURITY.md +14 -0
  15. mcp_tool_evals-0.4.0/action.yml +34 -0
  16. mcp_tool_evals-0.4.0/compose.yaml +61 -0
  17. mcp_tool_evals-0.4.0/docker/Dockerfile +18 -0
  18. mcp_tool_evals-0.4.0/docs/architecture.md +25 -0
  19. mcp_tool_evals-0.4.0/examples/calc_server.py +106 -0
  20. mcp_tool_evals-0.4.0/examples/catalog-server.yaml +3 -0
  21. mcp_tool_evals-0.4.0/examples/eval-suite.yaml +18 -0
  22. mcp_tool_evals-0.4.0/examples/http-server.yaml +4 -0
  23. mcp_tool_evals-0.4.0/examples/http_server.py +93 -0
  24. mcp_tool_evals-0.4.0/examples/server.yaml +6 -0
  25. mcp_tool_evals-0.4.0/examples/tools.yaml +28 -0
  26. mcp_tool_evals-0.4.0/plans/README.md +12 -0
  27. mcp_tool_evals-0.4.0/plans/v0.1-completed-foundation.md +154 -0
  28. mcp_tool_evals-0.4.0/plans/v0.2-next-phase-roadmap.md +176 -0
  29. mcp_tool_evals-0.4.0/pyproject.toml +72 -0
  30. mcp_tool_evals-0.4.0/src/mcp_evals/__init__.py +3 -0
  31. mcp_tool_evals-0.4.0/src/mcp_evals/cli.py +246 -0
  32. mcp_tool_evals-0.4.0/src/mcp_evals/config.py +23 -0
  33. mcp_tool_evals-0.4.0/src/mcp_evals/errors.py +21 -0
  34. mcp_tool_evals-0.4.0/src/mcp_evals/linter/__init__.py +3 -0
  35. mcp_tool_evals-0.4.0/src/mcp_evals/linter/descriptions.py +203 -0
  36. mcp_tool_evals-0.4.0/src/mcp_evals/logging.py +35 -0
  37. mcp_tool_evals-0.4.0/src/mcp_evals/mcp_client/__init__.py +5 -0
  38. mcp_tool_evals-0.4.0/src/mcp_evals/mcp_client/discover.py +73 -0
  39. mcp_tool_evals-0.4.0/src/mcp_evals/mcp_client/http.py +59 -0
  40. mcp_tool_evals-0.4.0/src/mcp_evals/mcp_client/stdio.py +121 -0
  41. mcp_tool_evals-0.4.0/src/mcp_evals/models/__init__.py +11 -0
  42. mcp_tool_evals-0.4.0/src/mcp_evals/models/server.py +19 -0
  43. mcp_tool_evals-0.4.0/src/mcp_evals/models/spec.py +42 -0
  44. mcp_tool_evals-0.4.0/src/mcp_evals/runner/__init__.py +17 -0
  45. mcp_tool_evals-0.4.0/src/mcp_evals/runner/eval_runner.py +59 -0
  46. mcp_tool_evals-0.4.0/src/mcp_evals/runner/llm_runner.py +203 -0
  47. mcp_tool_evals-0.4.0/src/mcp_evals/spec_loader.py +34 -0
  48. mcp_tool_evals-0.4.0/tests/test_eval_runner.py +80 -0
  49. mcp_tool_evals-0.4.0/tests/test_linter.py +82 -0
  50. mcp_tool_evals-0.4.0/tests/test_spec_loader.py +33 -0
@@ -0,0 +1,9 @@
1
+ .venv
2
+ .git
3
+ __pycache__
4
+ *.pyc
5
+ .mypy_cache
6
+ .ruff_cache
7
+ htmlcov
8
+ .pytest_cache
9
+ dist
@@ -0,0 +1,4 @@
1
+ MCP_EVALS_LOG_LEVEL=INFO
2
+ MCP_EVALS_LOG_JSON=false
3
+ MCP_EVALS_DEFAULT_MODEL=gpt-4o-mini
4
+ MCP_EVALS_PASS_THRESHOLD=0.8
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: Bug report
3
+ about: Report a problem
4
+ title: "[bug] "
5
+ labels: bug
6
+ body:
7
+ - type: textarea
8
+ id: description
9
+ attributes:
10
+ label: What happened?
11
+ validations:
12
+ required: true
13
+ - type: textarea
14
+ id: reproduce
15
+ attributes:
16
+ label: Steps to reproduce
17
+ validations:
18
+ required: true
@@ -0,0 +1,13 @@
1
+ ## Summary
2
+
3
+ <!-- What does this PR change and why? -->
4
+
5
+ ## Test plan
6
+
7
+ - [ ] `pytest tests/ -v`
8
+ - [ ] `ruff check src tests`
9
+
10
+ ## Checklist
11
+
12
+ - [ ] Tests added or updated
13
+ - [ ] README/CHANGELOG updated if needed
@@ -0,0 +1,19 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ branches: [main]
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: "3.12"
16
+ - run: pip install -e ".[dev]"
17
+ - run: ruff check src tests
18
+ - run: mypy src
19
+ - run: pytest tests/ -v --cov=mcp_evals
@@ -0,0 +1,16 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ .venv/
5
+ .pytest_cache/
6
+ .env
7
+ .coverage
8
+ htmlcov/
9
+ .mypy_cache/
10
+ .ruff_cache/
11
+ dist/
12
+ *.egg-info/
13
+
14
+ # IDE
15
+ .idea/
16
+ .vscode/
@@ -0,0 +1,11 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.4.4
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - repo: https://github.com/pre-commit/mirrors-mypy
8
+ rev: v1.9.0
9
+ hooks:
10
+ - id: mypy
11
+ additional_dependencies: [types-PyYAML, pydantic-settings]
@@ -0,0 +1,37 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.4.0] - 2026-09-14
6
+
7
+ ### Added
8
+ - `name-description-mismatch` linter rule — warns when distinctive tool-name tokens never appear in the description
9
+
10
+ ## [0.3.0] - 2026-08-19
11
+
12
+ ### Added
13
+ - HTTP JSON-RPC MCP discovery (`transport: http` + `mcp_evals.mcp_client.http`)
14
+ - Example HTTP calculator server in `examples/http_server.py`
15
+
16
+ ## [0.2.0] - 2026-08-19
17
+
18
+ ### Added
19
+ - `mcp-evals discover` for stdio MCP servers and catalog fixtures
20
+ - `mcp-evals lint --live` against a server config
21
+ - Behavioral `mcp-evals run` with mock keyword selector or OpenAI-compatible models
22
+ - `--samples` and `--pass-threshold` for CI
23
+ - Extra linter rules: `required-params-undocumented`, `ambiguous-verbs`
24
+ - Example stdio calculator server and GitHub Action (`action.yml`)
25
+
26
+ ### Notes
27
+ - HTTP/Streamable MCP transport is not implemented yet
28
+
29
+ ## [0.1.0] - 2026-08-18
30
+
31
+ ### Added
32
+ - Initial project foundation
33
+ - `mcp-evals lint` — static tool description linter
34
+ - `mcp-evals validate-spec` — eval suite structure validation (dry-run)
35
+ - `mcp-evals health` — installation check
36
+ - Example tool catalog and eval suite fixtures
37
+ - Docker development and test environment
@@ -0,0 +1,22 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our pledge
4
+
5
+ We pledge to make participation in our community a harassment-free experience for everyone.
6
+
7
+ ## Our standards
8
+
9
+ Examples of behavior that contributes to a positive environment:
10
+
11
+ - Using welcoming and inclusive language
12
+ - Being respectful of differing viewpoints
13
+ - Gracefully accepting constructive criticism
14
+ - Focusing on what is best for the community
15
+
16
+ ## Enforcement
17
+
18
+ Project maintainers may remove, edit, or reject contributions that violate this Code of Conduct.
19
+
20
+ ## Attribution
21
+
22
+ Adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.
@@ -0,0 +1,51 @@
1
+ # Contributing to mcp-evals
2
+
3
+ Thank you for your interest in contributing.
4
+
5
+ ## Development setup
6
+
7
+ ```bash
8
+ python -m venv .venv && source .venv/bin/activate
9
+ pip install -e ".[dev]"
10
+ pre-commit install # optional
11
+ ```
12
+
13
+ ## Running tests
14
+
15
+ Prefer Docker Compose so the environment matches CI:
16
+
17
+ ```bash
18
+ docker compose run --rm test
19
+ ```
20
+
21
+ Locally:
22
+
23
+ ```bash
24
+ pytest tests/ -v
25
+ ruff check src tests
26
+ mypy src
27
+ ```
28
+
29
+ Other useful compose services: `dev`, `lint-example`, `discover-example`, `run-example`.
30
+
31
+ ## Project layout
32
+
33
+ | Path | Purpose |
34
+ |------|---------|
35
+ | `src/mcp_evals/cli.py` | CLI entry point |
36
+ | `src/mcp_evals/linter/` | Static description analysis |
37
+ | `src/mcp_evals/runner/` | Eval execution |
38
+ | `src/mcp_evals/models/` | Pydantic schemas |
39
+ | `examples/` | Sample catalogs and eval suites |
40
+
41
+ ## Pull requests
42
+
43
+ - Keep changes focused and tested
44
+ - Update README/CHANGELOG for user-facing changes
45
+ - Follow existing code style (ruff + mypy strict)
46
+ - Prefer small PRs with a clear test plan in the description
47
+
48
+ ## Commit style
49
+
50
+ - Imperative subject line; mention the user-facing why when relevant
51
+ - Do not add AI co-author trailers (e.g. Co-authored-by: Cursor) to commits.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mcp-evals contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,235 @@
1
+ Metadata-Version: 2.5
2
+ Name: mcp-tool-evals
3
+ Version: 0.4.0
4
+ Summary: Behavioral evaluation and description linting for MCP servers
5
+ Project-URL: Homepage, https://github.com/yashshah9/mcp-evals
6
+ Project-URL: Repository, https://github.com/yashshah9/mcp-evals
7
+ Project-URL: Issues, https://github.com/yashshah9/mcp-evals/issues
8
+ Project-URL: Documentation, https://github.com/yashshah9/mcp-evals#readme
9
+ Author-email: Yash Shah <yash376351@gmail.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: agents,llm,mcp,model-context-protocol,testing
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Testing
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: click>=8.1
21
+ Requires-Dist: pydantic-settings>=2.2
22
+ Requires-Dist: pydantic>=2.6
23
+ Requires-Dist: pyyaml>=6.0
24
+ Requires-Dist: rich>=13.7
25
+ Requires-Dist: structlog>=24.1
26
+ Provides-Extra: dev
27
+ Requires-Dist: mypy>=1.9; extra == 'dev'
28
+ Requires-Dist: pre-commit>=3.7; extra == 'dev'
29
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
30
+ Requires-Dist: pytest>=8.0; extra == 'dev'
31
+ Requires-Dist: ruff>=0.4; extra == 'dev'
32
+ Requires-Dist: types-pyyaml>=6.0; extra == 'dev'
33
+ Provides-Extra: mcp
34
+ Requires-Dist: mcp>=1.0; extra == 'mcp'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # mcp-evals
38
+
39
+ Behavioral evaluation and description linting for [Model Context Protocol](https://modelcontextprotocol.io) (MCP) servers.
40
+
41
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
42
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
43
+ [![CI](https://github.com/yashshah9/mcp-evals/actions/workflows/ci.yml/badge.svg)](https://github.com/yashshah9/mcp-evals/actions/workflows/ci.yml)
44
+
45
+ > **Status:** v0.4 — stdio + HTTP JSON-RPC discovery, description lint (including `name-description-mismatch`), and mock/OpenAI-compatible tool-selection evals.
46
+
47
+ ## 60-second try
48
+
49
+ ```bash
50
+ docker compose run --rm run-example # mock eval, no API key
51
+ docker compose run --rm lint-example # live stdio lint
52
+ docker compose run --rm test # pytest
53
+ ```
54
+
55
+ ## Why this vs alternatives
56
+
57
+ | Approach | Strength | Gap |
58
+ |----------|----------|-----|
59
+ | **mcp-evals** | Lint + YAML evals + mock CI runner | Not a full agent harness |
60
+ | MCP Inspector | Interactive debugging | No CI lint/eval suite |
61
+ | Protocol conformance tests | JSON-RPC correctness | Do not test tool selection |
62
+ | Hand-written LLM mocks | Full control | Drift from real descriptions |
63
+
64
+ ## Problem
65
+
66
+ 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.
67
+
68
+ **mcp-evals** fills the behavioral layer: lint tool descriptions, define eval cases in YAML, and (next) measure tool-selection accuracy in CI.
69
+
70
+ ## Key features (v0.4)
71
+
72
+ - **Description linter** — missing descriptions, undocumented required params, overlapping tools, ambiguous verbs, `name-description-mismatch`
73
+ - **Live discover** — handshake a stdio or HTTP JSON-RPC MCP server (or load a catalog fixture)
74
+ - **Eval runner** — `mcp-evals run` with `--model mock` (CI), `--live SERVER.yaml`, or an OpenAI-compatible endpoint
75
+ - **CLI + Docker + GitHub Action** — lint and optional eval in CI without a cloud key (mock selector)
76
+
77
+ ## Architecture
78
+
79
+ ```
80
+ ┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐
81
+ │ CLI │────▶│ Linter / Runner │────▶│ Models (Pydantic)│
82
+ │ mcp-evals │ │ spec_loader │ │ EvalSuite, etc. │
83
+ └─────────────┘ └──────────────────┘ └─────────────────┘
84
+
85
+ (next) MCP client + LLM
86
+ ```
87
+
88
+ | Component | Technology | Why |
89
+ |-----------|------------|-----|
90
+ | Language | Python 3.11+ | MCP SDK ecosystem, pytest integration |
91
+ | CLI | Click | Mature, composable commands |
92
+ | Schemas | Pydantic v2 | Strict validation, good errors |
93
+ | Logging | structlog | Structured, JSON-capable |
94
+ | Config | pydantic-settings | Env-based, typed |
95
+ | Tests | pytest + ruff + mypy | Standard Python OSS stack |
96
+
97
+ ## Installation
98
+
99
+ ```bash
100
+ pip install mcp-tool-evals
101
+ # or from source:
102
+ pip install -e ".[dev]"
103
+ ```
104
+
105
+ ## Local development
106
+
107
+ ```bash
108
+ python -m venv .venv && source .venv/bin/activate
109
+ pip install -e ".[dev]"
110
+ mcp-evals health
111
+ mcp-evals lint examples/tools.yaml
112
+ mcp-evals discover examples/server.yaml
113
+ mcp-evals lint --live examples/server.yaml
114
+ mcp-evals validate-spec examples/eval-suite.yaml
115
+ mcp-evals run examples/eval-suite.yaml --catalog examples/tools.yaml --model mock
116
+ pytest tests/ -v
117
+ ```
118
+
119
+ ## Docker
120
+
121
+ ```bash
122
+ # Health check
123
+ docker compose run --rm dev
124
+
125
+ # Run tests
126
+ docker compose run --rm test
127
+
128
+ # Lint a live stdio server (this example passes)
129
+ docker compose run --rm lint-example
130
+
131
+ # Discover tools from the example calc server
132
+ docker compose run --rm discover-example
133
+
134
+ # Mock eval run (no API key)
135
+ docker compose run --rm run-example
136
+ ```
137
+
138
+ ## Configuration
139
+
140
+ Copy `.env.example` to `.env`:
141
+
142
+ | Variable | Default | Description |
143
+ |----------|---------|-------------|
144
+ | `MCP_EVALS_LOG_LEVEL` | `INFO` | Log level |
145
+ | `MCP_EVALS_LOG_JSON` | `false` | JSON log output |
146
+ | `MCP_EVALS_DEFAULT_MODEL` | `gpt-4o-mini` | Model for eval runs (future) |
147
+ | `MCP_EVALS_PASS_THRESHOLD` | `0.8` | Minimum selection accuracy |
148
+
149
+ ## Usage
150
+
151
+ ### Lint tool descriptions
152
+
153
+ ```bash
154
+ mcp-evals lint examples/tools.yaml
155
+ mcp-evals lint --live examples/server.yaml
156
+ mcp-evals discover examples/server.yaml
157
+ mcp-evals lint examples/tools.yaml --format json
158
+ mcp-evals lint examples/tools.yaml --fail-on-warning
159
+ ```
160
+
161
+ ### Run behavioral evals
162
+
163
+ ```bash
164
+ mcp-evals run examples/eval-suite.yaml --catalog examples/tools.yaml --model mock
165
+ mcp-evals run examples/eval-suite.yaml --catalog examples/tools.yaml \
166
+ --model llama3.2 --base-url http://localhost:11434/v1 --pass-threshold 0.8
167
+ # or discover tools from a live server that matches the suite:
168
+ # mcp-evals run suite.yaml --live server.yaml --model mock
169
+ ```
170
+
171
+ ### Validate eval suite
172
+
173
+ ```bash
174
+ mcp-evals validate-spec examples/eval-suite.yaml
175
+ ```
176
+
177
+ ### Health check
178
+
179
+ ```bash
180
+ mcp-evals health
181
+ ```
182
+
183
+ ## Example eval suite
184
+
185
+ See `examples/eval-suite.yaml`:
186
+
187
+ ```yaml
188
+ name: document-server-behavior
189
+ cases:
190
+ - id: search-by-keyword
191
+ request: Find documents about quarterly revenue
192
+ expected_tool:
193
+ name: search_documents
194
+ arguments:
195
+ query: quarterly revenue
196
+ ```
197
+
198
+ ## Running tests
199
+
200
+ ```bash
201
+ pytest tests/ -v
202
+ ruff check src tests
203
+ mypy src
204
+ ```
205
+
206
+ ## Development workflow
207
+
208
+ 1. Add linter rules in `src/mcp_evals/linter/`
209
+ 2. Add runner logic in `src/mcp_evals/runner/`
210
+ 3. Add tests in `tests/`
211
+ 4. Update examples in `examples/`
212
+
213
+ ## Roadmap
214
+
215
+ - [x] MCP client: stdio discover + lint --live
216
+ - [x] LLM eval runner (mock + OpenAI-compatible)
217
+ - [x] HTTP JSON-RPC MCP transport
218
+ - [x] `name-description-mismatch` linter rule
219
+ - [ ] Streamable HTTP/SSE MCP transport
220
+ - [ ] GitHub Action PR comments and accuracy deltas
221
+
222
+ ## Known limitations (v0.4)
223
+
224
+ - Streamable HTTP/SSE MCP is not implemented — HTTP is JSON-RPC POST only
225
+ - Mock selector does not fill tool arguments (accuracy is tool-name only)
226
+ - Live Ollama/OpenAI evals need a reachable `--base-url`; CI uses `--model mock`
227
+ - `examples/tools.yaml` is intentionally dirty so `mcp-evals lint` can show findings
228
+
229
+ ## Contributing
230
+
231
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
232
+
233
+ ## License
234
+
235
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,199 @@
1
+ # mcp-evals
2
+
3
+ Behavioral evaluation and description linting for [Model Context Protocol](https://modelcontextprotocol.io) (MCP) servers.
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
7
+ [![CI](https://github.com/yashshah9/mcp-evals/actions/workflows/ci.yml/badge.svg)](https://github.com/yashshah9/mcp-evals/actions/workflows/ci.yml)
8
+
9
+ > **Status:** v0.4 — stdio + HTTP JSON-RPC discovery, description lint (including `name-description-mismatch`), and mock/OpenAI-compatible tool-selection evals.
10
+
11
+ ## 60-second try
12
+
13
+ ```bash
14
+ docker compose run --rm run-example # mock eval, no API key
15
+ docker compose run --rm lint-example # live stdio lint
16
+ docker compose run --rm test # pytest
17
+ ```
18
+
19
+ ## Why this vs alternatives
20
+
21
+ | Approach | Strength | Gap |
22
+ |----------|----------|-----|
23
+ | **mcp-evals** | Lint + YAML evals + mock CI runner | Not a full agent harness |
24
+ | MCP Inspector | Interactive debugging | No CI lint/eval suite |
25
+ | Protocol conformance tests | JSON-RPC correctness | Do not test tool selection |
26
+ | Hand-written LLM mocks | Full control | Drift from real descriptions |
27
+
28
+ ## Problem
29
+
30
+ 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.
31
+
32
+ **mcp-evals** fills the behavioral layer: lint tool descriptions, define eval cases in YAML, and (next) measure tool-selection accuracy in CI.
33
+
34
+ ## Key features (v0.4)
35
+
36
+ - **Description linter** — missing descriptions, undocumented required params, overlapping tools, ambiguous verbs, `name-description-mismatch`
37
+ - **Live discover** — handshake a stdio or HTTP JSON-RPC MCP server (or load a catalog fixture)
38
+ - **Eval runner** — `mcp-evals run` with `--model mock` (CI), `--live SERVER.yaml`, or an OpenAI-compatible endpoint
39
+ - **CLI + Docker + GitHub Action** — lint and optional eval in CI without a cloud key (mock selector)
40
+
41
+ ## Architecture
42
+
43
+ ```
44
+ ┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐
45
+ │ CLI │────▶│ Linter / Runner │────▶│ Models (Pydantic)│
46
+ │ mcp-evals │ │ spec_loader │ │ EvalSuite, etc. │
47
+ └─────────────┘ └──────────────────┘ └─────────────────┘
48
+
49
+ (next) MCP client + LLM
50
+ ```
51
+
52
+ | Component | Technology | Why |
53
+ |-----------|------------|-----|
54
+ | Language | Python 3.11+ | MCP SDK ecosystem, pytest integration |
55
+ | CLI | Click | Mature, composable commands |
56
+ | Schemas | Pydantic v2 | Strict validation, good errors |
57
+ | Logging | structlog | Structured, JSON-capable |
58
+ | Config | pydantic-settings | Env-based, typed |
59
+ | Tests | pytest + ruff + mypy | Standard Python OSS stack |
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ pip install mcp-tool-evals
65
+ # or from source:
66
+ pip install -e ".[dev]"
67
+ ```
68
+
69
+ ## Local development
70
+
71
+ ```bash
72
+ python -m venv .venv && source .venv/bin/activate
73
+ pip install -e ".[dev]"
74
+ mcp-evals health
75
+ mcp-evals lint examples/tools.yaml
76
+ mcp-evals discover examples/server.yaml
77
+ mcp-evals lint --live examples/server.yaml
78
+ mcp-evals validate-spec examples/eval-suite.yaml
79
+ mcp-evals run examples/eval-suite.yaml --catalog examples/tools.yaml --model mock
80
+ pytest tests/ -v
81
+ ```
82
+
83
+ ## Docker
84
+
85
+ ```bash
86
+ # Health check
87
+ docker compose run --rm dev
88
+
89
+ # Run tests
90
+ docker compose run --rm test
91
+
92
+ # Lint a live stdio server (this example passes)
93
+ docker compose run --rm lint-example
94
+
95
+ # Discover tools from the example calc server
96
+ docker compose run --rm discover-example
97
+
98
+ # Mock eval run (no API key)
99
+ docker compose run --rm run-example
100
+ ```
101
+
102
+ ## Configuration
103
+
104
+ Copy `.env.example` to `.env`:
105
+
106
+ | Variable | Default | Description |
107
+ |----------|---------|-------------|
108
+ | `MCP_EVALS_LOG_LEVEL` | `INFO` | Log level |
109
+ | `MCP_EVALS_LOG_JSON` | `false` | JSON log output |
110
+ | `MCP_EVALS_DEFAULT_MODEL` | `gpt-4o-mini` | Model for eval runs (future) |
111
+ | `MCP_EVALS_PASS_THRESHOLD` | `0.8` | Minimum selection accuracy |
112
+
113
+ ## Usage
114
+
115
+ ### Lint tool descriptions
116
+
117
+ ```bash
118
+ mcp-evals lint examples/tools.yaml
119
+ mcp-evals lint --live examples/server.yaml
120
+ mcp-evals discover examples/server.yaml
121
+ mcp-evals lint examples/tools.yaml --format json
122
+ mcp-evals lint examples/tools.yaml --fail-on-warning
123
+ ```
124
+
125
+ ### Run behavioral evals
126
+
127
+ ```bash
128
+ mcp-evals run examples/eval-suite.yaml --catalog examples/tools.yaml --model mock
129
+ mcp-evals run examples/eval-suite.yaml --catalog examples/tools.yaml \
130
+ --model llama3.2 --base-url http://localhost:11434/v1 --pass-threshold 0.8
131
+ # or discover tools from a live server that matches the suite:
132
+ # mcp-evals run suite.yaml --live server.yaml --model mock
133
+ ```
134
+
135
+ ### Validate eval suite
136
+
137
+ ```bash
138
+ mcp-evals validate-spec examples/eval-suite.yaml
139
+ ```
140
+
141
+ ### Health check
142
+
143
+ ```bash
144
+ mcp-evals health
145
+ ```
146
+
147
+ ## Example eval suite
148
+
149
+ See `examples/eval-suite.yaml`:
150
+
151
+ ```yaml
152
+ name: document-server-behavior
153
+ cases:
154
+ - id: search-by-keyword
155
+ request: Find documents about quarterly revenue
156
+ expected_tool:
157
+ name: search_documents
158
+ arguments:
159
+ query: quarterly revenue
160
+ ```
161
+
162
+ ## Running tests
163
+
164
+ ```bash
165
+ pytest tests/ -v
166
+ ruff check src tests
167
+ mypy src
168
+ ```
169
+
170
+ ## Development workflow
171
+
172
+ 1. Add linter rules in `src/mcp_evals/linter/`
173
+ 2. Add runner logic in `src/mcp_evals/runner/`
174
+ 3. Add tests in `tests/`
175
+ 4. Update examples in `examples/`
176
+
177
+ ## Roadmap
178
+
179
+ - [x] MCP client: stdio discover + lint --live
180
+ - [x] LLM eval runner (mock + OpenAI-compatible)
181
+ - [x] HTTP JSON-RPC MCP transport
182
+ - [x] `name-description-mismatch` linter rule
183
+ - [ ] Streamable HTTP/SSE MCP transport
184
+ - [ ] GitHub Action PR comments and accuracy deltas
185
+
186
+ ## Known limitations (v0.4)
187
+
188
+ - Streamable HTTP/SSE MCP is not implemented — HTTP is JSON-RPC POST only
189
+ - Mock selector does not fill tool arguments (accuracy is tool-name only)
190
+ - Live Ollama/OpenAI evals need a reachable `--base-url`; CI uses `--model mock`
191
+ - `examples/tools.yaml` is intentionally dirty so `mcp-evals lint` can show findings
192
+
193
+ ## Contributing
194
+
195
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
196
+
197
+ ## License
198
+
199
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,14 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a vulnerability
4
+
5
+ Email **yash376351@gmail.com** with the repo name, a short description, and steps to reproduce. Please do not open a public issue for exploitable findings until we have had a reasonable chance to respond.
6
+
7
+ ## Threat model (honest)
8
+
9
+ mcp-evals is a **developer/CI tool**. It talks to MCP servers and optional LLM endpoints you configure.
10
+
11
+ - It is **not** a sandbox for untrusted MCP servers or model output.
12
+ - Treat tool catalogs, eval fixtures, and live-server configs as trusted inputs for your environment.
13
+ - Do not pass production secrets into eval suites or commit them to cassettes/logs.
14
+ - Mock mode (`--model mock`) never calls a network model; live modes inherit whatever network and credential access your process already has.