Programmatic API

Use MCP Jest programmatically in your Node.js applications and build custom testing workflows.

Installation

npm install mcp-jest

Basic Usage

import { mcpTest } from 'mcp-jest';

const config = {
  name: 'My Test Suite',
  server: {
    command: 'node',
    args: ['my-server.js']
  },
  tests: [
    {
      name: 'Test greeting',
      type: 'tool',
      tool: 'greet',
      arguments: { name: 'World' },
      expect: {
        content: [
          {
            type: 'text',
            text: 'Hello, World!'
          }
        ]
      }
    }
  ]
};

// Run tests
const results = await mcpTest(config);

if (results.success) {
  console.log('All tests passed!');
} else {
  console.error('Tests failed:', results.failures);
  process.exit(1);
}

Core API

mcpTest(config, options?)

Main function to run MCP tests:

interface mcpTest {
  (config: MCPTestConfig, options?: TestOptions): Promise<TestResults>
}

interface TestOptions {
  timeout?: number           // Global timeout override
  verbose?: boolean         // Enable verbose output
  bail?: boolean           // Stop on first failure
  updateSnapshots?: boolean // Update snapshots
  grep?: string           // Filter tests by pattern
  parallel?: boolean      // Run tests in parallel
  maxWorkers?: number     // Number of workers
  reporter?: string       // Reporter type
  outputFile?: string     // Output file path
}

interface TestResults {
  success: boolean         // Overall success
  stats: TestStats        // Test statistics
  results: TestResult[]   // Individual test results
  failures: TestFailure[] // Failed tests
  snapshots?: SnapshotResults
  coverage?: CoverageResults
  duration: number        // Total time in ms
}

Test Results

interface TestStats {
  total: number           // Total tests
  passed: number         // Passed tests
  failed: number         // Failed tests
  skipped: number        // Skipped tests
  pending: number        // Pending tests
}

interface TestResult {
  name: string           // Test name
  status: 'passed' | 'failed' | 'skipped' | 'pending'
  duration: number       // Test duration in ms
  error?: TestError     // Error if failed
  output?: any          // Test output
  snapshot?: boolean    // Has snapshot
}

interface TestFailure {
  name: string          // Test name
  error: TestError     // Error details
  duration: number     // Test duration
  output?: any         // Actual output
  expected?: any       // Expected output
}

interface TestError {
  message: string      // Error message
  stack?: string      // Stack trace
  code?: string       // Error code
  details?: any       // Additional details
}

Advanced Usage

Custom Test Runner

import { MCPTestRunner, MCPTestClient } from 'mcp-jest';

// Create custom test runner
const runner = new MCPTestRunner({
  timeout: 30000,
  retries: 2,
  parallel: true,
  maxWorkers: 4
});

// Add custom hooks
runner.beforeAll(async () => {
  console.log('Setting up test environment...');
});

runner.afterAll(async () => {
  console.log('Cleaning up test environment...');
});

runner.beforeEach(async (test) => {
  console.log(`Running test: ${test.name}`);
});

runner.afterEach(async (test, result) => {
  console.log(`Test ${test.name} ${result.status}`);
});

// Run tests
const results = await runner.run(config);

Direct Server Communication

import { MCPTestClient } from 'mcp-jest';

// Create client
const client = new MCPTestClient({
  command: 'node',
  args: ['my-server.js'],
  timeout: 10000
});

try {
  // Start server
  await client.connect();
  
  // Test capabilities
  const capabilities = await client.getCapabilities();
  console.log('Server capabilities:', capabilities);
  
  // List tools
  const tools = await client.listTools();
  console.log('Available tools:', tools);
  
  // Call tool
  const result = await client.callTool('greet', { name: 'Alice' });
  console.log('Tool result:', result);
  
  // List resources
  const resources = await client.listResources();
  console.log('Available resources:', resources);
  
  // Read resource
  const content = await client.readResource('file://config.json');
  console.log('Resource content:', content);
  
} finally {
  // Clean up
  await client.disconnect();
}

Snapshot Testing API

import { SnapshotManager } from 'mcp-jest';

// Create snapshot manager
const snapshots = new SnapshotManager({
  snapshotDir: '__snapshots__',
  updateSnapshots: false,
  prettify: true
});

// Test with snapshot
const testResult = await client.callTool('generate-report', {
  type: 'monthly'
});

// Compare with snapshot
const snapshotResult = await snapshots.compare(
  'monthly-report-test',
  testResult,
  {
    exclude: ['generatedAt', 'reportId'],
    replacements: [
      {
        pattern: '\\d{4}-\\d{2}-\\d{2}',
        replacement: 'DATE'
      }
    ]
  }
);

if (!snapshotResult.matches) {
  console.log('Snapshot mismatch!');
  console.log('Diff:', snapshotResult.diff);
}

Custom Matchers

import { addMatcher } from 'mcp-jest';

// Add custom email matcher
addMatcher('email', (value: any) => {
  if (typeof value !== 'string') {
    return { matches: false, message: 'Value must be a string' };
  }
  
  const emailRegex = /^[\w.-]+@[\w.-]+\.[a-zA-Z]{2,}$/;
  const matches = emailRegex.test(value);
  
  return {
    matches,
    message: matches ? 'Valid email' : 'Invalid email format'
  };
});

// Use in tests
const config = {
  name: 'Email validation test',
  server: { ... },
  tests: [
    {
      name: 'Should return valid email',
      type: 'tool',
      tool: 'get-user-email',
      expect: {
        email: { matcher: 'email' }
      }
    }
  ]
};

Plugin Development

// Create a custom plugin
class PerformancePlugin {
  constructor(config) {
    this.thresholds = config.thresholds || {};
  }

  // Plugin hooks
  beforeTest(test) {
    this.startTime = Date.now();
  }

  afterTest(test, result) {
    const duration = Date.now() - this.startTime;
    const threshold = this.thresholds[test.name] || 1000;
    
    if (duration > threshold) {
      console.warn(
        `⚠️  Test "${test.name}" took ${duration}ms (threshold: ${threshold}ms)`
      );
    }
  }

  // Result processing
  processResults(results) {
    const slowTests = results.results.filter(
      result => result.duration > 1000
    );
    
    if (slowTests.length > 0) {
      console.log(`🐌 ${slowTests.length} slow tests detected`);
    }
  }
}

// Register plugin
import { registerPlugin } from 'mcp-jest';

registerPlugin('performance', PerformancePlugin);

// Use plugin in config
const config = {
  plugins: [
    {
      name: 'performance',
      config: {
        thresholds: {
          'slow-operation': 5000,
          'fast-operation': 100
        }
      }
    }
  ],
  // ... rest of config
};

Integration Examples

Express.js Middleware

import express from 'express';
import { mcpTest } from 'mcp-jest';

const app = express();

app.get('/test', async (req, res) => {
  try {
    const results = await mcpTest({
      name: 'Health Check',
      server: {
        command: 'node',
        args: ['server.js']
      },
      tests: [
        {
          name: 'Server health',
          type: 'capabilities'
        }
      ]
    });
    
    res.json({
      healthy: results.success,
      stats: results.stats,
      timestamp: new Date().toISOString()
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

GitHub Actions Integration

// test-action.js
import { mcpTest } from 'mcp-jest';
import { setFailed, setOutput } from '@actions/core';

async function main() {
  try {
    const results = await mcpTest({
      name: 'CI Test Suite',
      server: {
        command: process.env.SERVER_COMMAND,
        args: JSON.parse(process.env.SERVER_ARGS || '[]')
      },
      tests: JSON.parse(process.env.TEST_CONFIG)
    }, {
      reporter: 'junit',
      outputFile: 'test-results.xml',
      bail: true
    });
    
    setOutput('test-results', JSON.stringify(results.stats));
    
    if (!results.success) {
      setFailed(`${results.stats.failed} tests failed`);
    }
  } catch (error) {
    setFailed(error.message);
  }
}

main();

🔧 Programmatic Power

The programmatic API gives you full control over MCP Jest. Build custom workflows, integrate with CI/CD, or create specialized testing tools.

Learn CI/CD Integration →