JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q64088F
  • License MIT

A Node.js testing library for Model Context Protocol (MCP) servers

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (mcp-conductor) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    MCP Conductor

    A comprehensive Node.js testing library for Model Context Protocol (MCP) servers

    Node.js License: MIT

    MCP Conductor provides both YAML-based declarative testing and programmatic testing for MCP servers with advanced pattern matching capabilities, including case-insensitive matching, pattern negation, string length validation, comprehensive numeric comparison patterns (with exact equality, floating-point tolerance, and precision validation), date/timestamp validation patterns, and cross-field relationship validation.

    ๐Ÿ“– Documentation

    ๐Ÿ“š Complete Documentation

    โšก Quick Start

    # Install globally
    npm install -g mcp-conductor
    
    # Initialize in your MCP project
    npx mcp-conductor init
    
    # The init command creates:
    # - conductor.config.json (configured from package.json)
    # - test/mcp/ or tests/mcp/ directory (based on existing project structure)
    # - AGENTS.md (AI agent guide) in the test directory
    # - Installs mcp-conductor as a dev dependency
    
    # Customize your config (optional)
    # Edit conductor.config.json to match your server setup
    
    # Write your first test
    cat > tests/mcp/my-server.test.mcp.yml << 'EOF'  # or test/mcp/ depending on your project
    description: "Basic test"
    tests:
      - it: "should list tools"
        request:
          jsonrpc: "2.0"
          id: "1"
          method: "tools/list"
          params: {}
        expect:
          response:
            jsonrpc: "2.0"
            id: "1"
            result:
              tools: "match:type:array"
    EOF
    
    # Run tests (after init, you can use npx or npm script)
    npx mcp-conductor "test*/mcp/**/*.test.mcp.yml"  # Matches both test/ and tests/
    
    # Or add to package.json scripts:
    # "scripts": { "test:mcp": "mcp-conductor \"./test*/mcp/**/*.test.mcp.yml\"" }
    # Then run: npm run test:mcp

    Manual Setup (Alternative)

    # Create config manually
    echo '{"name":"My Server","command":"node","args":["./server.js"]}' > conductor.config.json
    
    # Write test
    cat > test.yml << 'EOF'
    description: "Basic test"
    tests:
      - it: "should list tools"
        request:
          jsonrpc: "2.0"
          id: "1"
          method: "tools/list"
          params: {}
        expect:
          response:
            jsonrpc: "2.0"
            id: "1"
            result:
              tools: "match:type:array"
    EOF
    
    # Run test
    conductor test.yml --config conductor.config.json

    โœจ Key Features

    • ๐ŸŽฏ Declarative YAML Testing - Simple, readable test definitions
    • ๐Ÿ’ป Programmatic API - JavaScript/TypeScript integration with any test framework
    • ๐Ÿ”„ Automatic MCP Protocol - Handles handshakes and JSON-RPC messaging
    • ๐Ÿงช Advanced Pattern Matching - 40+ verified pattern types including case-insensitive matching, string length validation, exact numeric equality, floating-point tolerance, decimal precision validation, modular arithmetic, comprehensive date/timestamp validation, and cross-field relationship validation
    • ๐Ÿ“Š Rich Reporting - Detailed diffs and colored output
    • ๐Ÿ›ก๏ธ Robust Communication - Reliable stdio transport handling

    ๐Ÿ“– Documentation

    ๐Ÿ“š Complete Documentation

    ๐Ÿš€ Testing Approaches

    YAML Declarative Testing

    description: "Calculator tests"
    tests:
      - it: "should add numbers"
        request:
          jsonrpc: "2.0"
          id: "calc-1"
          method: "tools/call"
          params:
            name: "calculator"
            arguments: { a: 15, b: 27 }
        expect:
          response:
            jsonrpc: "2.0"
            id: "calc-1"
            result:
              content:
                - type: "text"
                  text: "match:Result: \\d+"

    Advanced Pattern Matching Examples

    # Numeric comparisons
    tests:
      - it: "should validate numeric ranges"
        expect:
          response:
            result:
              score: "match:greaterThan:85"          # Score > 85
              count: "match:between:10:100"          # Count between 10-100
              percentage: "match:lessThanOrEqual:95" # Percentage <= 95
    
    # ๐Ÿ†• NEW: Exact numeric matching and precision validation
      - it: "should validate exact numeric values and precision"
        expect:
          response:
            result:
              productCount: "match:equals:42"        # Exact equality: 42 = 42
              categoryId: "match:notEquals:10"       # Inequality: 8 โ‰  10
              price: "match:decimalPlaces:2"         # Currency format: 24.99 (2 decimals)
              rating: "match:decimalPlaces:1"        # Rating format: 4.2 (1 decimal)
              stock: "match:multipleOf:5"            # Inventory rule: multiple of 5
              percentage: "match:divisibleBy:10"     # Business rule: divisible by 10
    
    # ๐Ÿ†• NEW: Floating point tolerance matching  
      - it: "should validate floating point with tolerance"
        expect:
          response:
            result:
              successRate: "match:approximately:95.5:0.1"  # 95.5 ยฑ 0.1 tolerance
              loadAverage: "match:approximately:1.2:0.05"  # Performance metric ยฑ 0.05
              temperature: "match:approximately:20:0.5"    # Sensor reading ยฑ 0.5ยฐC
    
    # Date and timestamp validation
      - it: "should validate dates and timestamps"
        expect:
          response:
            result:
              createdAt: "match:dateValid"               # Valid date/timestamp
              publishDate: "match:dateAfter:2023-01-01"  # After specific date
              expireDate: "match:dateBefore:2025-01-01"  # Before specific date
              lastUpdate: "match:dateAge:1d"             # Within last day
              eventTime: "match:dateBetween:2023-01-01:2024-12-31"  # Date range
              timestamp: "match:dateFormat:iso"          # ISO 8601 format
    
    # ๐Ÿ†• NEW: String length validation
      - it: "should validate string lengths and constraints"
        expect:
          response:
            result:
              title: "match:stringLength:25"                    # Exact length: 25 characters
              shortName: "match:stringLengthLessThan:10"        # Max length: < 10 characters
              description: "match:stringLengthGreaterThan:50"   # Min length: > 50 characters
              username: "match:stringLengthBetween:3:20"        # Length range: 3-20 characters
              nickname: "match:stringLengthGreaterThanOrEqual:2" # Min length: >= 2 characters
              bio: "match:stringLengthLessThanOrEqual:500"      # Max length: <= 500 characters
              emptyField: "match:stringEmpty"                   # Must be empty string
              requiredField: "match:stringNotEmpty"             # Must not be empty
              notShort: "match:not:stringLengthLessThan:5"     # Should NOT be < 5 characters
    
    # ๐Ÿ†• NEW: Cross-field validation for field relationships
      - it: "should validate field relationships and constraints"
        expect:
          response:
            result:
              "match:crossField": "startDate < endDate"     # Event dates relationship
              "match:crossField": "minPrice <= maxPrice"    # Pricing constraints  
              "match:crossField": "currentStock > minStock" # Inventory validation
              "match:crossField": "age >= minAge"           # User validation
              "match:crossField": "amount != fee"           # Financial rules
              
      - it: "should support nested field paths in cross-field validation"
        expect:
          response:
            result:
              "match:crossField": "user.profile.age >= settings.minAge"    # Nested field comparison
              "match:crossField": "order.total > payment.amount"           # Complex object validation
              
      - it: "should validate with pattern negation"
        expect:
          response:
            result:
              value: "match:not:greaterThan:1000"    # Value should NOT be > 1000
              status: "match:not:contains:error"     # Status should NOT contain "error"
              invalidDate: "match:not:dateValid"     # Should NOT be valid date
    
      - it: "should validate case-insensitive patterns"
        expect:
          response:
            result:
              name: "match:containsIgnoreCase:john"    # Matches "John", "JOHN", "johnny" (case-insensitive)
              status: "match:equalsIgnoreCase:SUCCESS" # Matches "success", "Success", "SUCCESS" (case-insensitive)
              message: "match:not:containsIgnoreCase:ERROR" # Should NOT contain "error" (case-insensitive)

    Programmatic Testing

    import { test, describe, before, after, beforeEach } from 'node:test';
    import { strict as assert } from 'node:assert';
    import { connect } from 'mcp-conductor';
    
    describe('MCP Server Tests', () => {
      let client;
      
      before(async () => { 
        client = await connect('./conductor.config.json'); 
      });
      
      after(async () => { 
        await client?.disconnect(); 
      });
      
      beforeEach(() => {
        // CRITICAL: Prevents stderr leaking between tests
        client.clearStderr();
      });
    
      test('should list available tools', async () => {
        const tools = await client.listTools();
        assert.ok(Array.isArray(tools));
        assert.ok(tools.length > 0);
        
        // Verify tool structure
        tools.forEach(tool => {
          assert.ok(tool.name, 'Tool should have name');
          assert.ok(tool.description, 'Tool should have description');
          assert.ok(tool.inputSchema, 'Tool should have input schema');
        });
      });
    
      test('should execute calculator tool', async () => {
        const result = await client.callTool('calculator', { 
          operation: 'add', a: 15, b: 27 
        });
      
        assert.equal(result.isError, false);
        assert.equal(result.content[0].type, 'text');
        assert.equal(result.content[0].text, 'Result: 42');
      });
    
      test('should handle tool errors gracefully', async () => {
        try {
          await client.callTool('nonexistent_tool', {});
          assert.fail('Should have thrown an error');
        } catch (error) {
          assert.ok(error.message.includes('Failed to call tool'));
        }
      });
    });

    ๐Ÿƒโ€โ™‚๏ธ Running Tests

    # YAML tests with various options
    conductor "tests/**/*.test.mcp.yml" --config config.json
    
    # Verbose output with test hierarchy
    conductor "tests/*.yml" --config config.json --verbose
    
    # Debug mode with detailed MCP communication
    conductor "tests/*.yml" --config config.json --debug
    
    # Timing information for performance analysis
    conductor "tests/*.yml" --config config.json --timing
    
    # JSON output for CI/automation systems  
    conductor "tests/*.yml" --config config.json --json
    
    # Quiet mode (minimal output)
    conductor "tests/*.yml" --config config.json --quiet
    
    # Error reporting options
    conductor "tests/*.yml" --config config.json --errors-only
    conductor "tests/*.yml" --config config.json --syntax-only  
    conductor "tests/*.yml" --config config.json --no-analysis
    conductor "tests/*.yml" --config config.json --group-errors
    conductor "tests/*.yml" --config config.json --max-errors 3
    
    # Combine multiple options
    conductor "tests/*.yml" --config config.json --verbose --timing --debug
    
    # Programmatic tests  
    node --test tests/**/*.programmatic.test.js
    
    # Example tests (included)
    npm run test:examples
    
    # Specific example servers
    npm run test:filesystem    # File operations with regex patterns
    npm run test:multitool     # Multi-tool server with comprehensive patterns  
    npm run test:numeric       # Numeric and date pattern matching demonstrations

    ๐ŸŽ›๏ธ CLI Options

    Output & Debugging Options

    • --verbose, -v: Display individual test results with the test suite hierarchy
    • --debug, -d: Enable debug mode with detailed MCP communication logging
    • --timing, -t: Show timing information for tests and operations
    • --json, -j: Output results in JSON format for CI/automation systems
    • --quiet, -q: Suppress non-essential output (opposite of verbose)

    Error Reporting Options

    • --errors-only: Show only failed tests and their errors, hide passing tests

      • Useful for focusing on failures in large test suites
      • Provides clean output for debugging sessions
    • --syntax-only: Show only syntax-related errors and suggestions

      • Highlights pattern syntax issues like missing match: prefixes
      • Recommends corrections for common syntax mistakes
    • --no-analysis: Disable detailed validation analysis, show only basic error messages

      • Provides minimal error output without suggestions or analysis
      • Faster execution when detailed analysis isn't needed
    • --group-errors: Group similar errors together to reduce repetition

      • Consolidates identical validation failures across multiple paths
      • Shows error frequency and affected paths in summary format
    • --concise: Suppress per-test detailed analysis blocks (requires --group-errors)

      • Hides the "๐Ÿ” Detailed Validation Analysis" section for each failing test
      • Keeps high-level failure lines and the aggregated grouped error summary
      • Ideal for very large failing suites where per-test verbosity is noisy
    • --max-errors <number>: Limit the number of validation errors shown per test (default: 5)

      • Prevents overwhelming output when tests have many validation failures
      • Shows "... and X more validation error(s)" for truncated errors

    Example Usage

    # Focus on failures only
    conductor "tests/*.yml" --config config.json --errors-only
    
    # Get syntax suggestions for pattern fixes
    conductor "tests/*.yml" --config config.json --syntax-only
    
    # Minimal error output for scripting
    conductor "tests/*.yml" --config config.json --no-analysis --quiet
    
    # Group similar errors for large test suites
    conductor "tests/*.yml" --config config.json --group-errors
    
    # Concise grouped summary (no per-test analysis blocks)
    conductor "tests/*.yml" --config config.json --group-errors --concise --errors-only
    
    # Limit error details for quick overview
    conductor "tests/*.yml" --config config.json --max-errors 2
    
    # Combine error reporting options
    conductor "tests/*.yml" --config config.json --errors-only --group-errors --max-errors 3

    ๐Ÿค Contributing

    Contributions welcome! See our Contributing Guide for details.

    # Development setup
    git clone https://github.com/taurgis/mcp-conductor.git
    cd mcp-conductor
    npm install
    
    # Run all tests
    npm test

    ๐Ÿ“œ License

    MIT License - see LICENSE file for details.


    ๐Ÿ“š View Complete Documentation | ๐Ÿ› Report Issues | โญ Star on GitHub