252 lines
7.7 KiB
Markdown
252 lines
7.7 KiB
Markdown
# MCP Server Evaluation Guide
|
|
|
|
Evaluate whether models can discover and use an MCP server safely and efficiently. Protocol correctness is necessary, but a technically valid tool can still be difficult for a model to select, call, or interpret.
|
|
|
|
## Layers of verification
|
|
|
|
Use four complementary layers:
|
|
|
|
1. **Unit tests** verify schemas, API-client behavior, response shaping, and errors.
|
|
2. **Protocol tests** verify MCP initialization, tool listing, invocation, transports, and cleanup.
|
|
3. **Deterministic scenarios** verify known tool calls against stable fixtures or test services.
|
|
4. **Harness-native agent review** evaluates discoverability and multi-step model behavior without adding a provider-specific runner to the skill.
|
|
|
|
Do not replace build, lint, typecheck, security checks, or protocol tests with an LLM review.
|
|
|
|
## 1. Unit and integration tests
|
|
|
|
Test each tool at the boundary where it becomes deterministic.
|
|
|
|
### Inputs
|
|
|
|
Cover:
|
|
|
|
- smallest valid input
|
|
- realistic valid input
|
|
- missing required fields
|
|
- wrong types and invalid enum values
|
|
- minimum and maximum lengths or numbers
|
|
- malformed identifiers, dates, and URLs
|
|
- unknown fields when strict schemas are intended
|
|
- attempts to access disallowed hosts or resources
|
|
|
|
### Upstream behavior
|
|
|
|
Cover:
|
|
|
|
- successful responses
|
|
- empty results
|
|
- pagination and continuation tokens
|
|
- rate limits and retry hints
|
|
- authentication and authorization failures
|
|
- upstream validation failures
|
|
- timeouts, cancellation, and partial failures
|
|
- malformed or unexpectedly large upstream payloads
|
|
|
|
### Outputs
|
|
|
|
Assert:
|
|
|
|
- `structuredContent` matches the declared output schema
|
|
- text content is concise and consistent with structured content
|
|
- pagination metadata is sufficient to continue
|
|
- secrets and sensitive fields are absent
|
|
- large results are bounded or truncated explicitly
|
|
- errors tell the model what it can change or try next
|
|
|
|
## 2. Protocol testing with MCP Inspector
|
|
|
|
Use the official Inspector against the server under test:
|
|
|
|
```bash
|
|
npx @modelcontextprotocol/inspector
|
|
```
|
|
|
|
Verify:
|
|
|
|
- initialization completes
|
|
- advertised capabilities are accurate
|
|
- tool names and descriptions are visible
|
|
- input schemas render correctly
|
|
- each tool can be invoked
|
|
- errors remain valid MCP responses
|
|
- cancellation and shutdown release resources
|
|
|
|
For stdio servers, confirm that stdout contains only protocol messages. Logs belong on stderr.
|
|
|
|
For Streamable HTTP, also confirm:
|
|
|
|
- origin and host validation
|
|
- authentication on every request
|
|
- session behavior, if used
|
|
- CORS policy, if browser access is intended
|
|
- request size and timeout limits
|
|
- DNS rebinding protections
|
|
|
|
Record the Inspector version and server command or endpoint with the results.
|
|
|
|
## 3. Scenario specification
|
|
|
|
Store scenarios as JSON so they can be parsed safely by project tests and reused by different harnesses.
|
|
|
|
Example:
|
|
|
|
```json
|
|
{
|
|
"version": 1,
|
|
"scenarios": [
|
|
{
|
|
"id": "find-open-critical-issues",
|
|
"goal": "Find open critical issues assigned to the current user and return their titles in updated order.",
|
|
"fixture": "fixtures/issues.json",
|
|
"expected": {
|
|
"answer": ["Database failover", "Expired signing key"],
|
|
"requiredTools": ["gitea_list_issues"],
|
|
"forbiddenTools": ["gitea_update_issue", "gitea_close_issue"],
|
|
"maxToolCalls": 3
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
A scenario should define:
|
|
|
|
- stable identifier
|
|
- realistic user goal
|
|
- fixed fixture or immutable test environment
|
|
- expected answer or objective assertions
|
|
- tools that should or must not be used
|
|
- maximum reasonable tool-call count
|
|
- safety constraints
|
|
|
|
Avoid answers based on live counts, current popularity, or mutable public data. Prefer frozen fixtures, seeded test accounts, or fixed historical ranges.
|
|
|
|
## 4. Designing useful scenarios
|
|
|
|
Create scenarios that collectively test:
|
|
|
|
- obvious tool selection
|
|
- ambiguous requests where descriptions must disambiguate tools
|
|
- filtering and pagination
|
|
- multi-step lookup and join behavior
|
|
- recovery from a validation or upstream error
|
|
- empty results
|
|
- large-result handling
|
|
- authentication boundaries
|
|
- read-only requests that must never invoke mutating tools
|
|
- intentional mutation with confirmation or explicit user intent
|
|
|
|
Each scenario should resemble a task a real user would delegate. Do not expose internal tool names in the user prompt unless the scenario specifically tests direct tool selection.
|
|
|
|
A good scenario requires reasoning but has objective success criteria. A poor scenario is either trivial (“list tools”) or impossible to grade consistently (“explore the data and tell me something interesting”).
|
|
|
|
## 5. Harness-native agent review
|
|
|
|
Run qualitative scenarios through an isolated agent or harness session configured with only the MCP server and essential filesystem/test tools. This prevents unrelated tools from masking gaps in the server.
|
|
|
|
For each scenario, capture:
|
|
|
|
- final answer
|
|
- ordered tool calls and arguments
|
|
- relevant tool results
|
|
- errors and retries
|
|
- total call count
|
|
- elapsed time when available
|
|
- model feedback about confusing names, schemas, or responses
|
|
|
|
Grade the trace against the scenario's objective assertions. Do not rely only on the model's self-reported success.
|
|
|
|
When comparing revisions, use the same scenario set, fixtures, model route, and tool permissions. Compare:
|
|
|
|
- task success rate
|
|
- median calls per successful task
|
|
- validation-error rate
|
|
- repeated or unnecessary calls
|
|
- unsafe mutation attempts
|
|
- response volume and truncation
|
|
|
|
## 6. Review rubric
|
|
|
|
### Discoverability
|
|
|
|
- Does the model choose the intended tool without being told its name?
|
|
- Are similar tools distinguishable by name and description?
|
|
- Are prerequisites and side effects clear?
|
|
|
|
### Schema usability
|
|
|
|
- Are required fields genuinely required?
|
|
- Do descriptions explain formats and constraints?
|
|
- Do enums and defaults prevent guesswork?
|
|
- Are nested inputs simpler than equivalent orchestration would be?
|
|
|
|
### Response usability
|
|
|
|
- Does the response contain the identifiers needed for the next step?
|
|
- Is structured content stable and bounded?
|
|
- Can the model paginate without reconstructing hidden state?
|
|
- Is irrelevant upstream data removed?
|
|
|
|
### Error recovery
|
|
|
|
- Does an error identify the bad field or failed precondition?
|
|
- Does it distinguish authentication, authorization, validation, rate limits, and upstream failure?
|
|
- Does it suggest a safe corrective action?
|
|
|
|
### Safety
|
|
|
|
- Are read-only and mutating tools clearly separated?
|
|
- Do annotations match real side effects?
|
|
- Can broad inputs escape the intended tenant, repository, filesystem, or host boundary?
|
|
- Are secrets absent from logs and tool results?
|
|
|
|
## 7. Evaluation report
|
|
|
|
Use a concise Markdown report:
|
|
|
|
```markdown
|
|
# MCP evaluation: <server>
|
|
|
|
## Environment
|
|
- Commit:
|
|
- SDK version:
|
|
- Transport:
|
|
- Inspector version:
|
|
- Agent/model route:
|
|
- Fixture version:
|
|
|
|
## Summary
|
|
- Scenarios passed: 8/10
|
|
- Median tool calls: 3
|
|
- Validation errors: 2
|
|
- Unsafe mutation attempts: 0
|
|
|
|
## Findings
|
|
|
|
### Concern: issue search description hides label semantics
|
|
|
|
Evidence: scenarios `find-critical` and `triage-ready` each made two failed calls.
|
|
Action: document whether labels use intersection or union semantics and add an enum for state.
|
|
|
|
## Scenario results
|
|
|
|
| Scenario | Result | Calls | Evidence |
|
|
| --- | --- | ---: | --- |
|
|
| find-critical | Fail | 5 | Used OR semantics; expected AND |
|
|
```
|
|
|
|
Every finding should connect trace evidence to an actionable schema, description, response, implementation, or documentation change.
|
|
|
|
## Completion criteria
|
|
|
|
An MCP server is ready when:
|
|
|
|
- project checks pass
|
|
- Inspector confirms protocol behavior
|
|
- deterministic scenarios pass
|
|
- qualitative scenarios show reliable tool selection
|
|
- no unresolved high-risk security or authorization findings remain
|
|
- failure paths are actionable
|
|
- evaluation evidence and known limitations are documented
|