Troubleshooting Guide
MCP Aegis Issues & Solutions
Common issues and comprehensive solutions when using MCP Aegis for testing Model Context Protocol servers, with debugging tips and best practices.
Installation Issues
NPM Package Not Found
Problem: npm: package 'mcp-aegis' not found
Solution: Make sure you have the latest npm and try installing again:
# Update npm
npm install -g npm@latest
# Install MCP Aegis
npm install -g mcp-aegisGlobal vs Local Installation
Problem: Command not found after installation
Solution:
# For development usage (after cloning repository)
cd mcp-aegis
node bin/aegis.js --help
# Create an alias for convenience
alias aegis="node /path/to/mcp-aegis/bin/aegis.js"Permission Errors
Problem: Permission denied during installation
Solution:
# For development setup (recommended approach)
git clone https://github.com/taurgis/mcp-aegis.git
cd mcp-aegis
npm install # No sudo needed for local development
# Set up proper Node.js permissions if needed
npm config set prefix ~/.npm-global
export PATH=~/.npm-global/bin:$PATHConnection Problems
Server Fails to Start
Problem: Failed to start server: Error: spawn ENOENT
Diagnosis: The command specified in config is not found or executable.
Solution:
{
"name": "My Server",
"command": "/full/path/to/node", // Use absolute path
"args": ["./server.js"]
}Check executable path:
which node
which python3Connection Timeout
Problem: Connection timeout after 5000ms
Diagnosis: Server takes too long to start or ready pattern not matching.
Solutions:
1. Increase timeout:
{
"name": "Slow Server",
"command": "python",
"args": ["./slow_server.py"],
"startupTimeout": 30000 // 30 seconds (default is 5000ms)
}2. Add ready pattern:
{
"name": "Server with Pattern",
"command": "node",
"args": ["./server.js"],
"readyPattern": "Server listening on port \\d+"
}3. Debug server startup:
# Test server manually
node ./server.js
# Debug with MCP Aegis
aegis test.yml --config config.json --debug
# Verbose output with timing
aegis test.yml --config config.json --verbose --timing
# Minimal output for scripts
aegis test.yml --config config.json --quietInteractive Tool Debugging with Query Command
Use the query command to debug individual MCP tools directly without writing test files.
Usage:
aegis query --config aegis.config.json
aegis query tool_name --config aegis.config.json
aegis query tool_name '{"path": "/tmp/file.txt"}' --config aegis.config.json
aegis query tool_name '{"arg": "value"}' --config aegis.config.json --json
aegis query tool_name --config aegis.config.json --quietBenefits:
- Quick testing: Test tools immediately without creating YAML files
- Server validation: Verify your server is responding correctly
- Tool discovery: List all available tools and their parameters
- Debugging: See exact server responses and stderr output
- Development workflow: Test tools as you develop them
Example debugging session:
# 1. First, list available tools
aegis query --config config.json
# Output: Shows all tools with descriptions and parameters
# 2. Test a file reading tool
aegis query read_file '{"path": "test.txt"}' --config config.json
# Output: Shows result content and any stderr
# 3. Test error conditions
aegis query read_file '{"path": "nonexistent.txt"}' --config config.json
# Output: Shows how the tool handles errors
# 4. Examine specific tool parameters
aegis query calculator '{"operation": "add", "a": 5, "b": 3}' --config config.json
# Output: Shows calculation resultHandshake Failures
Problem: MCP handshake failed: Unexpected response
Diagnosis: Server doesn't implement MCP protocol correctly.
Solution: Verify server implements required MCP methods:
// Server must handle these methods:
// - initialize
// - initialized (notification)
// - tools/list
// - tools/call
function handleMessage(message) {
if (message.method === 'initialize') {
sendResponse(message.id, {
protocolVersion: "2025-06-18",
capabilities: { tools: {} },
serverInfo: { name: "my-server", version: "1.0.0" }
});
}
// ... other methods
}Working Directory Issues
Problem: Server can't find files or resources
Solution: Set correct working directory:
{
"name": "Server with CWD",
"command": "node",
"args": ["./src/server.js"],
"cwd": "/absolute/path/to/project"
}Test Failures
Pattern Not Matching
Problem: Pattern did not match: expected "match:regex:..." but got "..."
Diagnosis: Pattern doesn't match actual response format.
Solutions:
1. Check actual response:
# MCP Aegis shows detailed output with debug mode
aegis test.yml --config config.json --debug --verbose2. Test regex separately:
const pattern = /Result: \d+/;
const text = "Result: 42 items found";
console.log(pattern.test(text)); // Should be true3. Fix common escaping issues:
# ❌ Wrong - single backslash
text: "match:regex:\d+"
# ✅ Correct - double backslash in YAML
text: "match:regex:\\d+"
# ✅ Correct - escaped special characters
text: "match:regex:\\$\\d+\\.\\d+" # For $15.99JSON-RPC Format Errors
Problem: Invalid JSON-RPC format
Solution: Verify correct JSON-RPC 2.0 structure:
request:
jsonrpc: "2.0" # Must be exactly "2.0"
id: "unique-id" # Must be unique per test
method: "tools/call" # Must be valid MCP method
params: # Parameters object
name: "tool_name"
arguments: {}Stderr Validation Failures
Problem: Expected empty stderr but got: "Warning: ..."
Solutions:
1. Accept expected stderr:
stderr: "match:contains:Warning"2. Update server to suppress warnings:
{
"env": {
"NODE_ENV": "test",
"SUPPRESS_WARNINGS": "true"
}
}3. Clear stderr before test:
client.clearStderr();
await client.callTool('tool', {});
const stderr = client.getStderr();Pattern Matching Issues
YAML Structure Errors (Most Common)
Problem: duplicated mapping key Error
Symptoms: YAML parser fails with duplicate key errors
Root Cause: YAML fundamentally cannot have duplicate keys in the same object
Solution: Restructure tests to avoid duplicates:
# ❌ CRITICAL ERROR - Duplicate keys
result:
tools: "match:arrayLength:1"
tools: ["read_file"] # This overwrites the previous line!
match:extractField: "tools.*.name"
match:extractField: "isError" # Another duplicate!
# ✅ CORRECT - Separate tests for different validations
# Test 1: Array length
result:
tools: "match:arrayLength:1"
# Test 2: Field extraction (separate test case)
result:
match:extractField: "tools.*.name"
value:
- "read_file"
# Test 3: Error flag (separate test case)
result:
match:extractField: "isError"
value: falsePattern Structure Conflicts
Symptoms: Unexpected validation behavior or structure errors
Solution: Don't mix pattern types inappropriately:
# ❌ WRONG - Can't mix arrayElements with direct array
result:
content:
match:arrayElements:
type: "text"
- type: "text" # This creates a structure conflict!
# ✅ CORRECT - Use one approach consistently
result:
content:
match:arrayElements:
type: "text"
text: "match:contains:data"
# OR use direct array structure:
result:
content:
- type: "text"
text: "match:contains:data"Field Extraction Problems
Problem: Field extraction returns empty array or wrong data
Diagnosis: JSON path is incorrect or data structure changed.
Solutions:
1. Verify JSON path:
const data = {
tools: [
{ name: "tool1", type: "utility" },
{ name: "tool2", type: "processor" }
]
};
// Correct paths:
// "tools.*.name" → ["tool1", "tool2"]
// "tools.*.type" → ["utility", "processor"]2. Debug extraction:
# Test with simpler extraction first
match:extractField: "tools"
value: "match:type:array"
# Then add complexity
match:extractField: "tools.*.name"
value: "match:arrayContains:expected_tool"Performance Issues
Slow Test Execution
Problem: Tests take too long to complete
Solutions:
1. Optimize server startup:
{
"startupTimeout": 5000, // Default is 5000ms, reduce if possible
"readyPattern": "Ready" // Add pattern to detect ready state
}2. Use connection pooling:
// Reuse client for multiple tests (Node.js test runner)
import { describe, test, before, after, beforeEach } from 'node:test';
describe('Test Suite', () => {
let client;
before(async () => {
client = await createClient('./config.json');
await client.connect();
});
after(async () => {
await client.disconnect();
});
beforeEach(() => {
// CRITICAL: Clear stderr to prevent test interference
client.clearStderr();
});
// Tests use same client instance
});Debugging Tips
Enable Verbose Output
# YAML testing with detailed debugging output
aegis tests.yml --config config.json --debug --verbose
# Shows actual vs expected values for failures with MCP communication detailsInspect Raw Responses
// Programmatic testing
const result = await client.sendMessage({
jsonrpc: "2.0",
id: "debug-1",
method: "tools/call",
params: { name: "my_tool", arguments: {} }
});
console.log('Raw response:', JSON.stringify(result, null, 2));Debug Server Directly
# Test server manually
echo '{"jsonrpc":"2.0","id":"1","method":"tools/list","params":{}}' | node server.js
# Check server logs
node server.js 2>server.log &
# Run tests then check server.logUse Debug Configuration
{
"name": "Debug Server",
"command": "node",
"args": ["--inspect", "./server.js"], // Enable debugger
"env": {
"DEBUG": "*", // Enable debug output
"NODE_ENV": "development"
},
"startupTimeout": 30000 // Longer timeout for debugging
}Getting Help
Create Minimal Reproduction
When reporting issues, create minimal reproduction:
1. Minimal server:
#!/usr/bin/env node
const server = { name: "minimal", version: "1.0.0" };
process.stdin.on('data', (data) => {
const message = JSON.parse(data.toString());
console.log(JSON.stringify({
jsonrpc: "2.0",
id: message.id,
result: { tools: [] }
}));
});2. Minimal config:
{
"name": "Minimal Server",
"command": "node",
"args": ["./minimal-server.js"]
}3. Minimal test:
description: "Minimal reproduction"
tests:
- it: "should work"
request:
jsonrpc: "2.0"
id: "1"
method: "tools/list"
params: {}
expect:
response:
jsonrpc: "2.0"
id: "1"
result:
tools: []Report Issues
Include the following information:
- MCP Aegis version:
node bin/aegis.js --version - Node.js version:
node --version - Operating system
- Full error message
- Minimal reproduction case
- Configuration file (sanitized)
Need More Help?
- Examples - Working examples and patterns
- API Reference - Complete API documentation
- GitHub Issues - Report bugs and request features