Quick Start Guide
MCP Testing in 5 Minutes
Get up and running with MCP Aegis Model Context Protocol testing in 5 minutes with this step-by-step guide.
๐ Choose Your Path
โก Method 1: Quick Setup (Recommended)
Navigate and Initialize
# Navigate to your MCP project directory
cd my-mcp-project
# Initialize MCP Aegis (automatically installs as dev dependency)
npx mcp-aegis initThis creates: aegis.config.json, a test directory structure, and installs the package.
๐ Project Structure After InitAuto-generated
project/
โโโ aegis.config.json # โ Server configuration
โโโ package.json # โ Updated with mcp-aegis dev dependency
โโโ test/ # โ Uses 'test/' if exists, otherwise creates 'tests/'
โ โโโ mcp/
โ โโโ AGENTS.md # โ AI assistant guide
โ โโโ yaml/ # โ YAML test files (.test.mcp.yml)
โ โ โโโ AGENTS.md # โ YAML-specific guidance
โ โโโ node/ # โ Programmatic tests (.programmatic.test.js)
โ โโโ AGENTS.md # โ Node.js-specific guidance
โโโ server.js # โ Your MCP server (update aegis.config.json if different)๐กThe init command detects existing 'test/' or 'tests/' directories and uses whichever exists, or creates 'test/' by default.Skip to Step 3 if using this method.
โ Quick Setup Complete!
Your project is now ready for MCP testing. You can either:
๐ง Method 2: Manual Setup
Install MCP Aegis
You can install MCP Aegis globally for system-wide access or locally in your project:
# Option A: Global installation (recommended for CLI usage)
npm install -g mcp-aegis
# Option B: Local installation (if you prefer local dependencies)
npm install --save-dev mcp-aegis
# Then use: npx mcp-aegis instead of just aegisCreate a Simple MCP Server
Create a basic MCP server for testing (server.js):
#!/usr/bin/env node
const serverInfo = { name: "demo-server", version: "1.0.0" };
const tools = [
{
name: "hello",
description: "Says hello with a friendly greeting",
inputSchema: {
type: "object",
properties: {
name: { type: "string", description: "Name to greet" }
},
required: ["name"]
}
}
];
let initialized = false;
process.stdin.on('data', (data) => {
try {
const message = JSON.parse(data.toString().trim());
if (message.method === 'initialize') {
sendResponse(message.id, {
protocolVersion: "2025-06-18",
capabilities: { tools: {} },
serverInfo
});
} else if (message.method === 'initialized') {
initialized = true;
// Notifications don't get responses
} else if (message.method === 'tools/list') {
if (!initialized) {
sendError(message.id, -32002, "Server not initialized");
return;
}
sendResponse(message.id, { tools });
} else if (message.method === 'tools/call' && message.params?.name === 'hello') {
if (!initialized) {
sendError(message.id, -32002, "Server not initialized");
return;
}
const name = message.params.arguments?.name;
if (!name) {
sendResponse(message.id, {
isError: true,
content: [{ type: "text", text: "Missing required parameter: name" }]
});
return;
}
sendResponse(message.id, {
content: [{ type: "text", text: `Hello, ${name}! ๐ Welcome to MCP!` }],
isError: false
});
} else {
sendError(message.id, -32601, "Method not found");
}
} catch (error) {
sendError(null, -32700, "Parse error");
}
});
function sendResponse(id, result) {
console.log(JSON.stringify({ jsonrpc: "2.0", id, result }));
}
function sendError(id, code, message) {
console.log(JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } }));
}
// Signal server is ready
setTimeout(() => console.error("Server ready"), 100);Create Configuration (Manual Setup Only)
Create aegis.config.json:
๐ Config File Naming
Standard: Use aegis.config.json (default, auto-detected)
Custom: Use any name like server.config.json or config.json and specify with --config flag
Examples: You'll see both patterns in the repository - the examples use short names like config.json for brevity, but aegis.config.json is recommended for clarity in real projects.
{
"name": "Demo MCP Server",
"command": "node",
"args": ["./server.js"],
"startupTimeout": 5000,
"readyPattern": "Server ready"
}๐ Step 3: Write Your First Test
Create demo.test.mcp.yml:
๐ก Working Example AvailableVerified
You can find this complete working example in examples/demo-server/ in the MCP Aegis repository. All the code below has been tested and verified to work.
๐ Beginner Approach (Recommended)Auto-handshake
Let MCP Aegis handle the handshake automatically. MCP Aegis will send the initialize request and initialized notification before your first test runs. This approach ensures your tools work correctly without needing to understand the handshake protocol details. This covers 90% of use cases.
description: "Demo MCP Server Tests"
tests:
- it: "should list available tools"
request:
jsonrpc: "2.0"
id: "tools-test"
method: "tools/list"
params: {}
expect:
response:
jsonrpc: "2.0"
id: "tools-test"
result:
tools:
- name: "hello"
description: "match:contains:hello"
inputSchema:
type: "object"
properties: "match:type:object"
required: ["name"]
stderr: "toBeEmpty"
- it: "should execute hello tool"
request:
jsonrpc: "2.0"
id: "hello-test"
method: "tools/call"
params:
name: "hello"
arguments:
name: "World"
expect:
response:
jsonrpc: "2.0"
id: "hello-test"
result:
content:
- type: "text"
text: "match:contains:Hello, World"
isError: false
stderr: "toBeEmpty"
- it: "should handle invalid tool"
request:
jsonrpc: "2.0"
id: "error-test"
method: "tools/call"
params:
name: "nonexistent"
arguments: {}
expect:
response:
jsonrpc: "2.0"
id: "error-test"
error:
code: -32601
message: "Method not found"
stderr: "toBeEmpty"โ๏ธ Advanced: Manual Handshake Testing
Include an initialize test if you want to verify handshake behavior or test specific protocol versions. This runs as an additional test alongside MCP Aegis's automatic handshake.
# Add this as the FIRST test if you want manual control:
- it: "should initialize successfully"
request:
jsonrpc: "2.0"
id: "init-test"
method: "initialize"
params:
protocolVersion: "2025-06-18"
capabilities: { tools: {} }
clientInfo: { name: "test-client", version: "1.0.0" }
expect:
response:
jsonrpc: "2.0"
id: "init-test"
result:
protocolVersion: "match:regex:20\\d{2}-\\d{2}-\\d{2}"
capabilities: "match:type:object"
serverInfo:
name: "demo-server"
version: "1.0.0"
stderr: "toBeEmpty"๐ Note: Both automatic handshake (for setup) and manual initialize test (for validation) will occur, giving you the best of both worlds - working tools plus handshake verification.
Error Handling Models
Two patterns exist for representing failures:
- JSON-RPC transport / protocol error: Use the top-level
errorobject (method not found, invalid request). - Tool-level logical failure: Return a normal
resultwithisError: trueand explanatorycontent.
Pick one per response; do not mix both for the same request.
Step 4: Run Your Tests
For Quick Setup (Method 1):
# Universal pattern that works for both test/ and tests/ directories:
npx mcp-aegis "test*/mcp/yaml/**/*.test.mcp.yml"
# Or add to package.json scripts for convenience:
# "scripts": {
# "test:mcp:yaml": "mcp-aegis \"test*/mcp/yaml/**/*.test.mcp.yml\"",
# "test:mcp:node": "node --test \"test*/mcp/node/**/*.programmatic.test.js\""
# }
# Then run:
npm run test:mcp:yaml
# Specific directory examples (if you know your structure):
# npx mcp-aegis "test/mcp/yaml/**/*.test.mcp.yml" # if test/ directory
# npx mcp-aegis "tests/mcp/yaml/**/*.test.mcp.yml" # if tests/ directoryFor Manual Setup (Method 2):
# If installed globally, use 'aegis':
aegis demo.test.mcp.yml --config aegis.config.json
# If installed locally, use 'npx mcp-aegis':
npx mcp-aegis demo.test.mcp.yml --config aegis.config.json
# With verbose output for detailed results
aegis demo.test.mcp.yml --config aegis.config.json --verbose
# With debug mode for MCP communication details
aegis demo.test.mcp.yml --config aegis.config.json --debug
# With timing information for performance analysis
aegis demo.test.mcp.yml --config aegis.config.json --timing
# Combine options for maximum debugging
aegis demo.test.mcp.yml --config aegis.config.json --verbose --debug --timing
# Error reporting options for focused debugging
aegis demo.test.mcp.yml --config aegis.config.json --errors-only
aegis demo.test.mcp.yml --config aegis.config.json --syntax-only
aegis demo.test.mcp.yml --config aegis.config.json --group-errors
aegis demo.test.mcp.yml --config aegis.config.json --max-errors 3๐ Understanding the Test Output
โ Success Output ExampleAll tests passed
When your tests run successfully, you should see output like this:
๐ Loaded configuration for: Demo MCP Server
๐งช Found 1 test suite(s)
โน๏ธ Starting MCP server...
โน๏ธ Server started successfully
โน๏ธ Performing MCP handshake...
โน๏ธ Handshake completed successfully
๐ Demo MCP Server Tests
demo.test.mcp.yml
โ should initialize successfully ... โ PASS
โ should list available tools ... โ PASS
โ should execute hello tool ... โ PASS
โ should handle invalid tool ... โ PASS
โน๏ธ Shutting down server...
โน๏ธ Server shut down successfully
๐ Test Results:
โ 4 passed
๐ Total: 4
๐ All tests passed!๐๏ธ Understanding the Test Structure
๐ YAML Test Anatomy
Each MCP Aegis YAML test follows this structure:
๐ description
Human-readable test suite description
๐งช tests
Array of individual test cases
โ it
Description of what the test should do
๐ค request
JSON-RPC request to send to server
๐ฅ expect
Expected response structure
๐ข stderr
Expected stderr output (optional)
Next Steps
Now that you have a basic test running, explore these advanced features:
๐ฏ Essential Next Steps
- Testing Fundamentals
Master core concepts, YAML vs programmatic approaches, and validation strategies
- Pattern Matching Overview
Learn 50+ pattern types for flexible validation - the core power of MCP Aegis
- Basic Patterns
String matching, type validation, length checks, and negation patterns
๐ Advanced Features
- YAML Testing Guide
Advanced YAML testing patterns and best practices
- AI Agent Testing
Advanced patterns for enterprise AI agent scenarios
- Examples
Real-world testing scenarios and reference implementations
๐ฏ Recommended Learning Path
- Master Testing Fundamentals to understand core concepts
- Start with Basic Patterns for core validation techniques
- Explore Array Patterns for validating tool lists and response arrays
- Learn Query Command for interactive debugging
- Graduate to AI Agent Testing for enterprise scenarios
Quick Debugging with Query Command
Use the query command to test tools directly without writing test files:
# List all available tools from your server (if globally installed)
aegis query --config aegis.config.json
# If locally installed, use npx:
npx mcp-aegis query --config aegis.config.json
# Test the hello tool with arguments
aegis query hello '{"name": "World"}' --config aegis.config.json
# Using the method-based approach (newer interface)
aegis query --config aegis.config.json --method tools/list
aegis query --config aegis.config.json --method tools/call --params '{"name": "hello", "arguments": {"name": "World"}}'
# Get JSON output (useful for scripting)
aegis query hello '{"name": "World"}' --config aegis.config.json --json
# If using custom config file names (e.g., examples use config.json):
aegis query --config examples/demo-server/config.json --method tools/listThis is perfect for:
- Verifying your server is working before writing tests
- Exploring what tools your server provides
- Testing tool arguments and responses quickly
- Debugging issues during development
- Learning MCP responses before writing pattern matching assertions
๐จ Common Quick Start Issues
๐ด Server Won't StartCommon Issue
chmod +x server.js#!/usr/bin/env nodeaegis.config.json command/args match your setup"startupTimeout": 10000๐ Tests Fail ImmediatelySetup Issue
readyPattern, ensure your server outputs it to stderrinitialize method--debug flag to see MCP communication๐ก Permission IssuesSystem Config
# Make server executable
chmod +x server.js
# If using npm scripts, ensure proper escaping:
"test:mcp": "mcp-aegis \"test*/mcp/yaml/**/*.test.mcp.yml\""๐ฃ Pattern Matching IssuesSyntax Help
\\\\d+ instead of \\d+ in YAML regex patternsmatch:contains:text for partial matches--verbose to see detailed comparison outputCommon Patterns
Here are some useful patterns you'll use frequently:
Pattern Matching Basics
# Type validation
result: "match:type:object"
tools: "match:type:array"
count: "match:type:number"
# String patterns
message: "match:contains:success"
filename: "match:startsWith:data_"
extension: "match:endsWith:.json"
# Array patterns
tools: "match:arrayLength:3" # Exactly 3 elements
# To assert presence of a specific tool name (use in a separate assertion, not together):
# tools: "match:arrayContains:name:hello"
# Negation & extraction examples
tools: "match:not:arrayLength:0" # Array must NOT be empty
match:extractField: "tools.*.name" # (Use in separate test: extract all tool names)Error Handling
- it: "should handle errors gracefully"
request:
method: "tools/call"
params:
name: "invalid_tool"
arguments: {}
expect:
response:
result:
isError: true
content:
- type: "text"
text: "match:contains:Unknown tool"
# Alternative: JSON-RPC error response (for protocol-level errors)
- it: "should return JSON-RPC error for invalid method"
request:
method: "invalid/method"
params: {}
expect:
response:
error:
code: -32601
message: "Method not found"