Skip to main content
Source: examples/mcp_server_fetch/

Overview

This example validates a simple MCP server that exposes a fetch tool to retrieve web content. The tests illustrate three styles (decorators, pytest, and legacy assertions) and demonstrate how to combine structural assertions, path constraints, and LLM judges.

Goals

  • Verify the agent calls the fetch tool when appropriate
  • Check extracted content for known signals (e.g., “Example Domain”)
  • Ensure efficient paths (no unnecessary steps)
  • Evaluate quality with rubric-based judges

What you’ll learn

  • Choosing assertions per outcome type (structural, tool, path, judge)
  • Designing resilient tests using immediate vs deferred checks
  • Reading metrics and span trees to diagnose behavior

Structure

  • datasets/ – YAML and Python datasets
  • tests/ – pytest style, decorators, assertions style
  • golden_paths/ – expected sequences
  • mcpeval.yaml – config for provider, reports

Run

Assertion design and rationale

1) Prove the right tool was used

When a prompt requires reading a URL, we assert the fetch tool was called:
Why: catches regressions where the agent “hallucinates” content without making tool calls, or switches to an unintended tool. Tip: combine with Expect.tools.count("fetch", 1) to detect duplicate calls.

2) Validate output structure rather than brittle text

For tool outputs, prefer structural checks over raw substring matching:
Why: tool responses are often nested structures. Field‑scoped, regex/partial checks are stable across formatting differences and small content changes.

3) Check content cues in the assistant’s final message

After tool use, assert the answer includes expected signals:
Why: validates the final user‑visible output, not just tool logs.

4) Constrain the path and efficiency

For simple fetch tasks, we expect a single fetch and minimal steps:
Why: detects backtracking, repeated tools, or detours. Combats “thrashing” behaviors.

5) Enforce iteration and latency budgets

Why: catches runaway loops and slow paths early. Pairs well with CI budgets.

6) Use judges when “quality” is subjective

Some checks need subjective evaluation (e.g., “good summary”). Use rubric‑based judges:
Why: judges provide a tunable gate (min_score) for non‑deterministic tasks. In CI, keep them few and scoped.

7) Multi‑criteria judges for richer rubrics

Why: breaks down quality into interpretable dimensions, enabling targeted improvements.

Immediate vs deferred: how these fit together

  • Immediate: content/judge checks that rely on response
  • Deferred: tools/path/performance checks that need session metrics
Design tip: make immediate assertions small and concrete; keep most structural checks deferred for stability.

What it demonstrates

  • Fetch tool end‑to‑end scenarios
  • Dataset style configs and generated cases
  • Tool sequence and output matching
  • Judge rubric for quality checks
Placeholder: add screenshots of the HTML report for a passing run and for a failure showing a mismatched tool output.