MCP

Aegisv1

Development Guide

Contributing to MCP Aegis

Contributing to MCP Aegis development and extending the Model Context Protocol testing framework. Learn the architecture, setup development environment, and contribute new features.

Development Setup

Prerequisites

  • Node.js 18+ with npm
  • Git for version control

Clone and Install

bash
git clone https://github.com/taurgis/mcp-aegis.git
cd mcp-aegis

# Install dependencies
npm install

# Run tests to verify setup
npm test

Project Architecture

Key directories and modules in the project:

bash
mcp-aegis/
├── bin/                    # CLI entrypoint
│   └── aegis.js
├── src/                    # Source code
│   ├── cli/               # CLI modules
│   │   ├── commands/      # CLI commands (init, run)
│   │   └── output.js      # Output formatting
│   ├── core/              # Core engine
│   │   ├── configParser.js        # Configuration loading
│   │   ├── MCPCommunicator.js     # MCP protocol communication
│   │   └── ConfigValidator.js     # Config validation
│   ├── programmatic/      # Programmatic API
│   │   └── MCPClient.js   # Main client class
│   ├── protocol/          # MCP protocol handlers
│   └── test-engine/       # Testing engine
│       ├── runner.js      # Test execution
│       ├── executor.js    # Individual test execution
│       └── matchers/      # Pattern matching system
├── test/                  # Unit and integration tests
└── examples/              # Example servers and tests

Core Modules

MCP Communicator (src/core/MCPCommunicator.js)

Low-level stdio communication with MCP servers:

  • Child process spawning and management
  • JSON-RPC message framing over stdio
  • Stderr capture and buffering
  • Graceful shutdown handling

Test Engine (src/test-engine/)

Core test execution engine with modular pattern matching:

  • runner.js: Orchestrates test execution
  • executor.js: Executes individual test cases
  • matchers/: 11+ pattern matching types
  • protocol: MCP handshake and protocol handling

Programmatic API (src/programmatic/MCPClient.js)

JavaScript/TypeScript API for integration with test frameworks:

  • High-level MCP operations
  • Promise-based async API
  • Error handling and validation
  • Framework-agnostic design

Contributing Guidelines

Code Standards

  • ES2020+ JavaScript with async/await
  • JSDoc comments for public APIs
  • 2-space indentation, semicolons required

Commit Convention

Follow the conventional commits format: type(scope): description

bash
# Example commits
git commit -m "feat(runner): add regex pattern matching"
git commit -m "fix(client): handle connection timeout properly"
git commit -m "docs(readme): update installation instructions"

Pull Request Process

  1. Fork the repository
  2. Create feature branch from main
  3. Implement changes with tests
  4. Run test suite: npm test
  5. Update documentation as needed
  6. Submit pull request with clear description

Adding Features

Adding New Pattern Matchers

Extend the pattern matching system in src/test-engine/matchers/patterns.js:

javascript
// Add new pattern type
function matchPattern(pattern, actual) {
  if (pattern.startsWith('custom_pattern:')) {
    return matchCustomPattern(actual, pattern.substring(15));
  }
  // ... existing patterns
}

function matchCustomPattern(actual, value) {
  // Implement custom pattern logic
  return { matches: boolean, reason: string };
}

Add tests in test/testRunner.test.js:

javascript
describe('Custom Pattern Matching', () => {
  test('should match custom pattern', async () => {
    const testCase = {
      request: { /* JSON-RPC request */ },
      expect: {
        response: {
          result: {
            data: "match:custom_pattern:expected_value"
          }
        }
      }
    };
    
    // Test implementation
  });
});

Adding CLI Options

Add new options in bin/aegis.js:

javascript
program
  .option('--new-option <value>', 'Description of new option')
  .action(async (testPattern, options) => {
    // Parse options using the standardized parser
    const parsedOptions = parseOptions(options);
    
    if (parsedOptions.newOption) {
      // Handle new option logic
    }
  });

Adding Programmatic API Methods

Extend MCPClient in src/programmatic/MCPClient.js:

javascript
async newMethod(parameters) {
  this.validateConnection();
  
  const response = await this.sendMessage({
    jsonrpc: "2.0",
    id: `new-method-${Date.now()}`,
    method: "new/method",
    params: parameters
  });
  
  return response.result;
}

Testing

Test Structure

bash
test/
├── configParser.test.js       # Configuration validation tests
├── testParser.test.js         # YAML parsing tests  
├── MCPCommunicator.test.js    # Protocol communication tests
├── testRunner.test.js         # Test execution tests
├── reporter.test.js           # Output formatting tests
├── cli.test.js               # CLI integration tests
└── fixtures/                 # Test data and mock servers
    ├── runner/               # Test runner fixtures
    ├── servers/             # Mock MCP servers
    └── yaml/                # YAML test files

Running Tests

bash
# Run all tests
npm test

# Run only unit tests
npm run test:unit

# Run example server tests
npm run test:examples

# Run programmatic API tests
npm run test:programmatic

# Run with coverage
npm run test:coverage

Writing Tests

Unit Tests

javascript
import { describe, test } from 'node:test';
import assert from 'node:assert';
import { loadConfig } from '../src/core/configParser.js';

describe('Configuration Parser', () => {
  test('should validate required fields', async () => {
    const config = {
      name: 'Test Server',
      command: 'node',
      args: ['./server.js']
    };
    
    const result = await loadConfig('./test-config.json');
    assert.ok(result.name);
    assert.ok(result.command);
    assert.ok(Array.isArray(result.args));
  });
  
  test('should reject invalid configuration', async () => {
    await assert.rejects(
      async () => await loadConfig('./invalid-config.json'),
      /Missing required configuration fields/
    );
  });
});

Integration Tests

javascript
import { describe, test } from 'node:test';
import assert from 'node:assert';
import { runTests } from '../src/test-engine/runner.js';

describe('Integration Tests', () => {
  test('should run complete test suite', async () => {
    const config = { /* valid config */ };
    const testSuite = { /* valid test suite */ };
    
    const results = await runTests(config, testSuite);
    
    assert.ok(results.totalTests > 0);
    assert.equal(results.passedTests, results.totalTests);
  });
});

Mock Servers for Testing

Create mock MCP servers in test/fixtures/:

javascript
// test/fixtures/mock-server.js
#!/usr/bin/env node

const responses = {
  'tools/list': { tools: [{ name: 'mock_tool', description: 'Mock tool' }] },
  'tools/call': { content: [{ type: 'text', text: 'Mock response' }] }
};

process.stdin.on('data', (data) => {
  const message = JSON.parse(data.toString());
  const response = {
    jsonrpc: "2.0",
    id: message.id,
    result: responses[message.method] || { error: 'Unknown method' }
  };
  console.log(JSON.stringify(response));
});

Release Process

1. Update Version

bash
# For patch release
npm version patch

# For minor release  
npm version minor

# For major release
npm version major

2. Update Changelog

markdown
## [1.2.3] - 2024-01-15

### Added
- New pattern matching type: `arrayContains`
- Support for custom timeout configurations

### Fixed
- Handle edge case in regex pattern escaping
- Improve error messages for connection failures

### Changed
- Improved performance for large test suites

3. Run Full Test Suite

bash
npm run test:all
npm run test:integration
npm run test:examples

4. Pre-release Testing

bash
# Test installation
npm pack
npm install -g mcp-aegis-*.tgz

# Verify CLI works
aegis --help
aegis examples/filesystem.test.mcp.yml --config examples/config.json --verbose --debug

# Test programmatic API
node -e "
const { createClient } = require('mcp-aegis');
console.log('API imports successfully');
"

5. Build and Publish

bash
npm run build
npm publish

# Create GitHub Release
git tag v1.2.3
git push origin v1.2.3

Development Best Practices

  • Test-Driven Development: Write tests before implementing features
  • Small, Focused Commits: Make atomic commits with clear messages
  • Documentation Updates: Keep docs in sync with code changes
  • Performance Monitoring: Benchmark critical paths
  • Error Handling: Provide clear, actionable error messages
  • Backward Compatibility: Maintain API stability
  • Security Reviews: Validate input and sanitize output
  • Code Reviews: All changes require review