xiaohongshu
xiaohongshu
mcp-evaluation-skill
Comprehensive evaluation creation for MCP servers - question generation, answer verification, and XML formatting for agent usability testing
Full skill instructions
This skill provides a systematic approach to creating comprehensive evaluation suites for MCP (Model Context Protocol) servers. Evaluations test whether AI agents can effectively use MCP tools to answer realistic, complex questions - the ultimate measure of MCP server quality.
Core Capabilities:
Use this skill when you need to:
Trigger Phrases:
Don't use this skill for:
MCP Protocol Understanding
Evaluation Theory
Domain Knowledge
# Ensure MCP server is running
npm run build
node dist/index.js &
# Or use evaluation harness (recommended)
# Harness manages server lifecycle automatically
Objective: Understand the complete capability surface of the MCP server
# If using MCP inspector
mcp-inspector --server ./dist/index.js tools list
# Manual inspection via code
grep -r "@tool" src/mcp/tools/
Document Each Tool:
| Tool Name | Purpose | Input Parameters | Output | Complexity |
|---|---|---|---|---|
list_miners | Get all registered miners | { limit?, offset? } | { miners: [...] } | Simple |
get_miner_status | Get detailed miner status | { minerId } | { status, hashrate, temp } | Simple |
update_firmware | Update miner firmware | { minerId, version } | { jobId, status } | Complex |
get_fleet_summary | Aggregated fleet metrics | { tenantId? } | { total, online, hashrate } | Moderate |
Key Insights to Capture:
Pattern: Map Tool Dependencies
list_miners → get_miner_status (requires minerId from list)
↓
update_firmware (requires minerId)
↓
check_job_status (requires jobId from update)
Workflow Chains to Test:
Critical Rule: Never use destructive operations during exploration
Exploration Strategy:
// Example: Explore miner fleet
const miners = await mcpServer.callTool("list_miners", { limit: 100 });
// Identify interesting miners: highest hashrate, highest temp, offline, etc.
const detailedStatus = await mcpServer.callTool("get_miner_status", {
minerId: miners.miners[0].id
});
// Understand status structure: what fields exist? What values?
const fleetSummary = await mcpServer.callTool("get_fleet_summary", {});
// Understand aggregated metrics: total miners, online count, average hashrate
Data Patterns to Identify:
Uniqueness: Which fields uniquely identify entities?
minerId, serialNumber, ipAddressRelationships: How do entities relate?
Ranges: What are typical value ranges?
Edge Cases: Interesting outliers to test
Aggregations: What can be calculated?
Data Classification Matrix:
| Data Type | Change Frequency | Uniqueness | Suitable for Evaluation? |
|---|---|---|---|
| Miner ID | Never | Unique | ✅ Yes (stable reference) |
| Hashrate | Every 1-5s | Non-unique | ❌ No (too volatile) |
| Firmware version | Rarely | Non-unique | ✅ Yes (stable) |
| Temperature | Every 1-5s | Non-unique | ❌ No (too volatile) |
| Pool URL | Rarely | Non-unique | ✅ Yes (stable) |
| Error messages | Varies | Non-unique | ⚠️ Maybe (if persistent) |
Stable vs Volatile Data:
Target Distribution for 10 Questions:
Characteristics:
Examples:
Simple Discovery
<question>How many miners are currently registered in the fleet?</question>
<answer>127</answer>
<!-- Tools: list_miners (count total) -->
Simple Detail Lookup
<question>What firmware version is miner-abc-123 running?</question>
<answer>2.5.1</answer>
<!-- Tools: get_miner_status(miner-abc-123) → firmware_version -->
Characteristics:
Examples:
Find by Characteristic
<question>Which miner in the fleet has the highest hashrate? What is its IP address?</question>
<answer>192.168.1.157</answer>
<!-- Tools:
1. list_miners
2. get_miner_status for each (or use fleet summary)
3. Identify max hashrate
4. Return IP address
-->
Aggregation with Filter
<question>How many miners are currently offline in tenant 'prod-west'?</question>
<answer>3</answer>
<!-- Tools:
1. list_miners({ tenantId: 'prod-west' })
2. Filter by status === 'offline'
3. Count results
-->
Cross-Resource Query
<question>Which pool URL is configured for the miner with serial number SN-7891? Include the pool priority.</question>
<answer>stratum+tcp://pool.example.com:3333 (priority: 0)</answer>
<!-- Tools:
1. list_miners → find miner by serial number
2. get_pool_config(minerId) → get pool configuration
3. Extract URL and priority
-->
Characteristics:
Examples:
Deep Workflow Exploration
<question>Find the miner with the oldest firmware version in the fleet. What is its current hashrate in TH/s?</question>
<answer>87.3</answer>
<!-- Tools:
1. list_miners (get all miners)
2. get_miner_status for each (or batch query)
3. Identify oldest firmware version
4. Get hashrate for that specific miner
-->
Multi-Condition Search
<question>Among miners running firmware 2.5.x, which one has been online the longest? What is its uptime in hours?</question>
<answer>1847</answer>
<!-- Tools:
1. list_miners
2. get_miner_status for each
3. Filter by firmware version (2.5.x regex)
4. Identify max uptime
5. Convert to hours and return
-->
Pattern Discovery
<question>Which firmware version is most commonly deployed across all miners in the 'prod' tenant? How many miners use it?</question>
<answer>2.5.1 (94 miners)</answer>
<!-- Tools:
1. list_miners({ tenantId: 'prod' })
2. get_miner_status for each
3. Group by firmware version
4. Find most common (mode)
5. Return version + count
-->
For each generated question, verify:
Red Flags (Avoid These):
Critical Rule: You must solve every question yourself to verify the answer
Verification Process:
// For each question, document solving process:
// Question: "How many miners are in tenant 'prod-west'?"
// Step 1: Call list_miners
const miners = await mcpServer.callTool("list_miners", {
tenantId: "prod-west"
});
// Result: { miners: [...], total: 47 }
// Step 2: Verify count
console.log(`Total miners: ${miners.total}`);
// Output: Total miners: 47
// Step 3: Document answer
// Answer: 47
// Step 4: Verify stability
// - Tenant membership rarely changes ✅
// - Answer won't be volatile ✅
// - Answer is deterministic ✅
String Comparison Requirements:
| Answer Type | Format | Example |
|---|---|---|
| Number | Plain number | 47 (not "47 miners") |
| String | Exact string | prod-west (not "Tenant: prod-west") |
| IP Address | Standard notation | 192.168.1.100 |
| URL | Full URL | stratum+tcp://pool.example.com:3333 |
| Version | Semantic version | 2.5.1 (not "v2.5.1") |
| Boolean | true or false | true (lowercase) |
| List | Comma-separated | miner-1,miner-2,miner-3 (no spaces) |
Multiple-Part Answers:
If question asks for multiple pieces of information, format as structured answer:
<question>What is the IP address and pool URL for miner-abc-123?</question>
<answer>192.168.1.100, stratum+tcp://pool.example.com:3333</answer>
<!-- Clear delimiter (comma + space) between parts -->
Check Answer Stability:
Stable vs Unstable Examples:
| Question | Stability | Reason |
|---|---|---|
| "How many miners are registered?" | ✅ Stable | Rarely changes |
| "What is miner-123's hashrate?" | ❌ Unstable | Changes every second |
| "Which firmware version is on miner-abc?" | ✅ Stable | Only changes on update |
| "How many miners are currently online?" | ❌ Unstable | Changes frequently |
| "What pool URL is miner-xyz using?" | ✅ Stable | Configuration data |
Complete Evaluation File Structure:
<?xml version="1.0" encoding="UTF-8"?>
<evaluation>
<metadata>
<name>Braiins OS MCP Server Evaluation</name>
<version>1.0</version>
<created>2025-12-29</created>
<author>Engineering Team</author>
<description>Comprehensive evaluation suite testing agent usability of Braiins OS MCP server</description>
</metadata>
<qa_pairs>
<!-- Simple questions (2) -->
<qa_pair>
<id>eval-001</id>
<difficulty>simple</difficulty>
<question>How many miners are currently registered in the fleet?</question>
<answer>127</answer>
<tools_required>list_miners</tools_required>
<expected_call_count>1</expected_call_count>
</qa_pair>
<qa_pair>
<id>eval-002</id>
<difficulty>simple</difficulty>
<question>What firmware version is miner-abc-123 running?</question>
<answer>2.5.1</answer>
<tools_required>get_miner_status</tools_required>
<expected_call_count>1</expected_call_count>
</qa_pair>
<!-- Moderate questions (6) -->
<qa_pair>
<id>eval-003</id>
<difficulty>moderate</difficulty>
<question>Which miner in the fleet has the highest hashrate? What is its IP address?</question>
<answer>192.168.1.157</answer>
<tools_required>list_miners, get_miner_status</tools_required>
<expected_call_count>3-5</expected_call_count>
</qa_pair>
<!-- ... 5 more moderate questions ... -->
<!-- Complex questions (2) -->
<qa_pair>
<id>eval-009</id>
<difficulty>complex</difficulty>
<question>Find the miner with the oldest firmware version in the fleet. What is its current hashrate in TH/s?</question>
<answer>87.3</answer>
<tools_required>list_miners, get_miner_status</tools_required>
<expected_call_count>5+</expected_call_count>
</qa_pair>
<qa_pair>
<id>eval-010</id>
<difficulty>complex</difficulty>
<question>Which firmware version is most commonly deployed across all miners in the 'prod' tenant? How many miners use it?</question>
<answer>2.5.1 (94 miners)</answer>
<tools_required>list_miners, get_miner_status</tools_required>
<expected_call_count>5+</expected_call_count>
</qa_pair>
</qa_pairs>
<statistics>
<total_questions>10</total_questions>
<simple_count>2</simple_count>
<moderate_count>6</moderate_count>
<complex_count>2</complex_count>
<total_tools>4</total_tools>
<avg_tools_per_question>2.3</avg_tools_per_question>
</statistics>
</evaluation>
Required Fields:
<id>: Unique identifier (eval-001, eval-002, ...)<difficulty>: simple | moderate | complex<question>: Clear, unambiguous question text<answer>: Verified answer (string comparison format)Optional but Recommended Fields:
<tools_required>: Comma-separated tool names needed<expected_call_count>: How many tool calls expected (for performance testing)<rationale>: Why this question is valuable (internal documentation)Target: Braiins OS MCP Server with 4 tools
Step 1: Tool Inspection
// Available tools:
1. list_miners({ limit?, offset?, tenantId? })
2. get_miner_status({ minerId })
3. get_fleet_summary({ tenantId? })
4. get_pool_config({ minerId })
Step 2: Data Exploration
// Discover data patterns
const miners = await callTool("list_miners", { limit: 100 });
// Found: 127 miners total, IDs like "miner-abc-123"
const status = await callTool("get_miner_status", {
minerId: miners.miners[0].id
});
// Found: firmware version (stable), hashrate (volatile), temperature (volatile)
const summary = await callTool("get_fleet_summary", {});
// Found: total count, online count, total hashrate
Step 3: Generate 10 Questions
<evaluation>
<!-- 2 Simple -->
<qa_pair>
<question>How many miners are registered?</question>
<answer>127</answer>
</qa_pair>
<qa_pair>
<question>What is miner-abc-123's firmware version?</question>
<answer>2.5.1</answer>
</qa_pair>
<!-- 6 Moderate -->
<qa_pair>
<question>How many miners in tenant 'prod-west' are online?</question>
<answer>44</answer>
</qa_pair>
<!-- ... 5 more moderate ... -->
<!-- 2 Complex -->
<qa_pair>
<question>Which miner has the oldest firmware? What is its pool URL?</question>
<answer>stratum+tcp://old-pool.example.com:3333</answer>
</qa_pair>
<!-- ... 1 more complex ... -->
</evaluation>
Step 4: Verify All Answers
// Manually solve each question and verify answer stability
// Document solving process for future reference
❌ Bad Question (Volatile Answer):
<question>What is the current hashrate of miner-abc-123?</question>
<answer>95.7</answer>
<!-- Problem: Hashrate changes every second - unstable! -->
✅ Good Question (Stable Answer):
<question>What firmware version is miner-abc-123 running?</question>
<answer>2.5.1</answer>
<!-- Good: Firmware version only changes on updates - stable! -->
❌ Bad Question (Dependent):
<question>Using the miner ID from question 3, what is its temperature?</question>
<!-- Problem: Depends on question 3 - not independent! -->
✅ Good Question (Independent):
<question>What is the pool URL for miner-abc-123?</question>
<answer>stratum+tcp://pool.example.com:3333</answer>
<!-- Good: Self-contained, no dependencies -->
Coverage
Complexity Distribution
Question Quality
Answer Quality
XML Format
Agent Success Rates:
Tool Call Efficiency:
Problem: Using real-time metrics that change constantly
<!-- BAD: Temperature changes every second -->
<question>What is miner-123's current temperature?</question>
<answer>65°C</answer>
Solution: Use stable configuration or historical data
<!-- GOOD: Firmware version only changes on updates -->
<question>What firmware version is miner-123 running?</question>
<answer>2.5.1</answer>
Problem: Questions that rely on previous answers
<!-- BAD: Depends on identifying miner in previous question -->
<question>What is the pool URL for the miner from question 5?</question>
Solution: Make every question self-contained
<!-- GOOD: Fully self-contained -->
<question>What is the pool URL for miner-abc-123?</question>
<answer>stratum+tcp://pool.example.com:3333</answer>
Problem: Multiple valid interpretations
<!-- BAD: Ambiguous format -->
<question>How many miners are offline?</question>
<answer>3 miners are offline</answer>
<!-- Agent might return just "3" or "three" or "3 miners" -->
Solution: Specify exact format in question or normalize answer
<!-- GOOD: Clear number format -->
<question>How many miners are offline?</question>
<answer>3</answer>
<!-- Clear: just the number -->
Evaluation Harness Setup:
# Create evaluation harness script
cat > run-evaluation.ts <<'EOF'
import { MCPClient } from '@modelcontextprotocol/client';
import { parseEvaluation } from './eval-parser';
async function runEvaluation(evalPath: string) {
const client = new MCPClient('./dist/index.js');
const evaluation = parseEvaluation(evalPath);
let passed = 0;
let failed = 0;
for (const qa of evaluation.questions) {
try {
const answer = await client.ask(qa.question);
if (answer === qa.answer) {
passed++;
console.log(`✅ ${qa.id}: PASS`);
} else {
failed++;
console.log(`❌ ${qa.id}: FAIL (expected: ${qa.answer}, got: ${answer})`);
}
} catch (error) {
failed++;
console.log(`❌ ${qa.id}: ERROR - ${error.message}`);
}
}
console.log(`\nResults: ${passed}/${passed + failed} passed (${(passed / (passed + failed) * 100).toFixed(1)}%)`);
}
runEvaluation('./evaluations/braiins-os.xml');
EOF
Usage:
npm run build
npm run evaluate
Version History:
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience