Skip to content

Commit b749dbd

Browse files
feat(065): D1 retrieval datasets (renamed for clarity) + merged D1/D2 README (#554)
* feat(065): D1 retrieval datasets — frozen corpus, golden set, baseline (A2) Generate and commit the Spec 065 D1 retrieval evaluation artifacts via A1's mcp-eval datasets/retrieval CLI (cb37f84): - corpus_v1.json: frozen 45-tool snapshot over 7 no-auth reference MCP servers (filesystem, git, memory, sqlite, fetch, time, sequential-thinking), via GET /api/v1/tools. Immutable (CN-002); refresh = corpus_v2 (FR-012). - corpus_v1.source.json: secret-free, reproducible mcpproxy source config. - retrieval_golden_v1.json: 47 graded queries (relevance 0|1|2), 11 cross-server hard-negatives (FR-001), R-C compliant (queries never name the tool). Passes schema + INV-1 validation. - baseline_v1.json: reference Recall@k/MRR/nDCG@10/MAP + Recall@5 tolerance 0.05, the CI regression anchor (FR-009). Retrieval metrics top-level (scorer reads them directly); empty security section reserved for D2 (CN-004). - README.md: documented, repeatable regeneration procedure (FR-012). Verified end-to-end against a live BM25 index: validate OK, gate PASS (Recall@5=0.681 >= baseline-0.05). Score reports stay local (CN-003). Related #MCP-740 Co-Authored-By: Paperclip <noreply@paperclip.ing> * fix(065): rename D1 dataset files for clarity + merge D1/D2 README Addresses pre-merge review on #552: corpus_v1.source.json (valid config) vs corpus_v1.json (scored snapshot, NOT a config) invited 'serve --config corpus_v1.json' which fails. Renamed: - corpus_v1.source.json -> snapshot-servers.config.json (the servable config) - corpus_v1.json -> corpus_v1.tools.json (the scored snapshot) Updated baseline_v1.json source_config + corpus note refs; merged the D1 and D2 dataset READMEs into one with an explicit servable-vs-dataset cheat sheet. --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
1 parent 371af22 commit b749dbd

5 files changed

Lines changed: 1299 additions & 3 deletions

File tree

specs/065-evaluation-foundation/datasets/README.md

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,67 @@
11
# Spec 065 — Evaluation datasets
22

3-
## `security_corpus_v1.json` (D2)
3+
Versioned, frozen evaluation artifacts for the tool-retrieval (D1) and security
4+
(D2) benchmarks. **Immutable once committed — a refresh is `*_v2.*`, never an edit
5+
of a `*_v1.*` file** (CN-002, FR-012).
6+
7+
> **File-type cheat sheet — read this before running anything:**
8+
> - **`snapshot-servers.config.json`** is the ONLY servable file — it's a real
9+
> mcpproxy config (`mcpproxy serve --config snapshot-servers.config.json`).
10+
> - **`corpus_v1.tools.json`** is the frozen *tool snapshot* the eval scores
11+
> against — it is **NOT** a mcpproxy config; `serve --config corpus_v1.tools.json`
12+
> will fail. Likewise `security_corpus_v1.json` is a labeled dataset, not a config.
13+
14+
| File | What it is | Servable? | Committed? |
15+
|------|------------|-----------|------------|
16+
| `snapshot-servers.config.json` | mcpproxy config of 7 no-auth reference servers used to freeze the corpus (secret-free, reproducible) | **yes** (`serve --config`) | yes |
17+
| `corpus_v1.tools.json` | Frozen snapshot of 45 tools (`GET /api/v1/tools`) — the D1 universe the eval scores against | no (dataset) | yes |
18+
| `retrieval_golden_v1.json` | 47 graded queries → tool(s), relevance 0\|1\|2, ≥8 hard-negatives (FR-001); R-C (queries never name the tool) | no (dataset) | yes |
19+
| `baseline_v1.json` | Reference Recall@k/MRR/nDCG@10/MAP + Recall@5 tolerance — the CI regression anchor (FR-009). `security` section filled by D2 (CN-004) | no (dataset) | yes |
20+
| `security_corpus_v1.json` | D2 labeled security regression corpus (per-detector P/R/F1/FPR) | no (dataset) | yes |
21+
| score reports (`report.json` / `.html`) | Per-run output | no | **no** (CN-003 — stay local) |
22+
23+
---
24+
25+
## D1 — Tool-retrieval datasets
26+
27+
Generated by A1's harness (`~/repos/mcp-eval`, `mcp-eval datasets` / `mcp-eval retrieval`).
28+
29+
### Regenerate (documented + repeatable — FR-012)
30+
31+
```bash
32+
# 1. Boot a throwaway mcpproxy over the committed SERVABLE config (fresh data-dir).
33+
mcpproxy serve --config specs/065-evaluation-foundation/datasets/snapshot-servers.config.json \
34+
--data-dir /tmp/mcpproxy-corpus-snapshot --listen 127.0.0.1:8092
35+
# (all 7 servers connect via npx/uvx, no tokens; quarantine disabled for a clean index)
36+
37+
# 2. Freeze the corpus snapshot (only when intentionally cutting corpus_v2).
38+
cd ~/repos/mcp-eval && PYTHONPATH=src uv run python -m mcp_eval.cli datasets snapshot \
39+
--out <repo>/specs/065-evaluation-foundation/datasets/corpus_v1.tools.json \
40+
--base-url http://127.0.0.1:8092 --api-key eval-corpus-snapshot
41+
42+
# 3. Validate the golden set (schema + INV-1: every tool_id ∈ corpus).
43+
PYTHONPATH=src uv run python -m mcp_eval.cli datasets validate \
44+
--corpus .../corpus_v1.tools.json --golden .../retrieval_golden_v1.json
45+
46+
# 4. Score + gate against the baseline (deterministic; gate = Recall@5 ≥ baseline−0.05).
47+
PYTHONPATH=src uv run python -m mcp_eval.cli retrieval \
48+
--corpus .../corpus_v1.tools.json --golden .../retrieval_golden_v1.json \
49+
--baseline .../baseline_v1.json --tolerance 0.05 \
50+
--base-url http://127.0.0.1:8092 --api-key eval-corpus-snapshot
51+
```
52+
53+
The golden set was seeded by intent and **hand-curated** for graded relevance and
54+
cross-server hard-negatives (e.g. `filesystem:search_files` vs `memory:search_nodes`;
55+
`sqlite:read_query` vs `filesystem:read_text_file`; `fetch:fetch` vs
56+
`filesystem:read_text_file`), then validated. Invariants: **INV-1** (no dangling
57+
labels), **INV-2** (removing a labeled tool drives that query's Recall→0 — proven by
58+
the harness scorer tests).
59+
60+
---
61+
62+
## D2 — Security regression corpus
63+
64+
### `security_corpus_v1.json`
465

566
Labeled security regression corpus the D2 detection scorer measures against
667
(precision / recall / F1 / FPR per detector). Conforms to
@@ -25,7 +86,7 @@ legitimately says "ignore case"). They exist to expose noisy detectors
2586
(SC-004 / INV-3). Each hard-negative `id` is `hn_<attack_category>_<n>`, encoding
2687
the attack it mimics so false positives map back to a category.
2788

28-
## Provenance & licensing (FR-007 / CN-005 / R-07 / R-A)
89+
### Provenance & licensing (FR-007 / CN-005 / R-07 / R-A)
2990

3091
Every entry carries `provenance.{source,license}`, and the test fails the build
3192
if any license is outside the redistributable allowlist (CN-005 / INV-4).
@@ -37,7 +98,7 @@ if any license is outside the redistributable allowlist (CN-005 / INV-4).
3798
[Damn Vulnerable MCP](https://github.com/harishsg993010/damn-vulnerable-MCP-server)
3899
project.
39100

40-
### External benchmarks (referenced, NOT vendored)
101+
#### External benchmarks (referenced, NOT vendored)
41102

42103
Per CN-005 and risk R-A, the following are **referenced externally only** and no
43104
text from them is vendored into this repo:
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"__doc__": "Spec 065 D1+D2 regression baseline. Retrieval metrics are TOP-LEVEL because mcp-eval RetrievalScorer reads baseline[\"recall_at\"][\"5\"] etc. directly (quickstart \u00a74: --baseline datasets/baseline_v1.json). The CI gate (FR-009/MCP-742) fails if a fresh Recall@5 < baseline.recall_at[5] - tolerance.recall_at_5. The \"security\" section is appended by the D2 issue (CN-004); it is intentionally empty here.",
3+
"corpus_version": "corpus_v1",
4+
"golden_version": "retrieval_golden_v1",
5+
"generated_from": {
6+
"harness": "mcp-eval retrieval @ cb37f84",
7+
"source_config": "datasets/snapshot-servers.config.json",
8+
"mcpproxy": "BM25 index over corpus_v1 (45 tools, 7 no-auth reference servers)",
9+
"runs": 1,
10+
"note": "Reference = current BM25 behavior, a regression anchor (NOT a quality target). Refresh requires re-freezing corpus + re-review."
11+
},
12+
"recall_at": {
13+
"1": 0.4184397163120567,
14+
"3": 0.5602836879432624,
15+
"5": 0.6808510638297872,
16+
"10": 0.7907801418439717
17+
},
18+
"mrr": 0.5684903748733535,
19+
"ndcg_at_10": 0.6094872517781414,
20+
"map": 0.5435916919959473,
21+
"tolerance": {
22+
"recall_at_5": 0.05
23+
},
24+
"runs_averaged": 1,
25+
"security": {}
26+
}

0 commit comments

Comments
 (0)