CI/CD Integration

Integrate MCP Jest into your continuous integration and deployment pipelines for automated testing.

GitHub Actions

Complete GitHub Actions workflow for MCP Jest:

# .github/workflows/mcp-test.yml
name: MCP Server Tests

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [18, 20, 22]
        
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v4
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
        
    - name: Install dependencies
      run: npm ci
      
    - name: Build server
      run: npm run build
      
    - name: Install MCP Jest
      run: npm install -g mcp-jest
      
    - name: Run tests
      run: |
        mcp-jest tests/*.json \
          --reporter junit \
          --output-file test-results.xml \
          --no-colors \
          --timeout 30000
          
    - name: Upload test results
      uses: actions/upload-artifact@v4
      if: always()
      with:
        name: test-results-node-${{ matrix.node-version }}
        path: test-results.xml
        
    - name: Publish test report
      uses: dorny/test-reporter@v1
      if: always()
      with:
        name: MCP Tests (Node ${{ matrix.node-version }})
        path: test-results.xml
        reporter: java-junit

GitLab CI

# .gitlab-ci.yml
stages:
  - test
  - deploy

variables:
  NODE_VERSION: "20"

.test_template: &test_template
  image: node:${NODE_VERSION}
  before_script:
    - npm ci
    - npm run build
    - npm install -g mcp-jest
  artifacts:
    reports:
      junit: test-results.xml
    paths:
      - test-results.xml
      - coverage/
    expire_in: 1 week
    when: always

test:unit:
  <<: *test_template
  stage: test
  script:
    - mcp-jest tests/unit/*.json
      --reporter junit
      --output-file test-results.xml
      --coverage
      --bail
  coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'

test:integration:
  <<: *test_template
  stage: test
  script:
    - mcp-jest tests/integration/*.json
      --timeout 60000
      --retries 2
      --parallel
      --max-workers 2
  services:
    - redis:latest
    - postgres:13
  variables:
    REDIS_URL: redis://redis:6379
    DATABASE_URL: postgres://postgres@postgres:5432/test

test:e2e:
  <<: *test_template
  stage: test
  script:
    - mcp-jest tests/e2e/*.json
      --timeout 120000
      --no-parallel
  only:
    - main
    - develop

Jenkins Pipeline

// Jenkinsfile
pipeline {
  agent any
  
  environment {
    NODE_VERSION = '20'
  }
  
  stages {
    stage('Setup') {
      steps {
        // Use Node.js
        nodejs(nodeJSInstallationName: "Node ${NODE_VERSION}") {
          sh 'npm ci'
          sh 'npm run build'
          sh 'npm install -g mcp-jest'
        }
      }
    }
    
    stage('Unit Tests') {
      steps {
        nodejs(nodeJSInstallationName: "Node ${NODE_VERSION}") {
          sh '''
            mcp-jest tests/unit/*.json \
              --reporter junit \
              --output-file unit-results.xml \
              --coverage \
              --coverage-dir coverage/unit
          '''
        }
      }
      post {
        always {
          junit 'unit-results.xml'
          publishHTML([
            allowMissing: false,
            alwaysLinkToLastBuild: true,
            keepAll: true,
            reportDir: 'coverage/unit',
            reportFiles: 'index.html',
            reportName: 'Unit Test Coverage'
          ])
        }
      }
    }
    
    stage('Integration Tests') {
      steps {
        nodejs(nodeJSInstallationName: "Node ${NODE_VERSION}") {
          sh '''
            mcp-jest tests/integration/*.json \
              --reporter junit \
              --output-file integration-results.xml \
              --timeout 60000 \
              --retries 2
          '''
        }
      }
      post {
        always {
          junit 'integration-results.xml'
        }
      }
    }
    
    stage('Performance Tests') {
      when {
        branch 'main'
      }
      steps {
        nodejs(nodeJSInstallationName: "Node ${NODE_VERSION}") {
          sh '''
            mcp-jest tests/performance/*.json \
              --reporter json \
              --output-file perf-results.json \
              --timeout 300000
          '''
          
          // Process performance results
          script {
            def results = readJSON file: 'perf-results.json'
            if (results.stats.failed > 0) {
              error("Performance tests failed")
            }
          }
        }
      }
    }
  }
  
  post {
    always {
      // Archive test results
      archiveArtifacts artifacts: '*-results.*', fingerprint: true
      
      // Clean workspace
      cleanWs()
    }
    
    failure {
      // Notify on failure
      emailext(
        subject: "MCP Tests Failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
        body: "Test failure in build ${env.BUILD_URL}",
        to: "${env.CHANGE_AUTHOR_EMAIL}"
      )
    }
  }
}

CircleCI

# .circleci/config.yml
version: 2.1

orbs:
  node: circleci/node@5.1.0

executors:
  node-executor:
    docker:
      - image: cimg/node:20.0
      
jobs:
  test:
    executor: node-executor
    steps:
      - checkout
      
      - node/install-packages:
          pkg-manager: npm
          
      - run:
          name: Build application
          command: npm run build
          
      - run:
          name: Install MCP Jest
          command: npm install -g mcp-jest
          
      - run:
          name: Run tests
          command: |
            mcp-jest tests/*.json \
              --reporter junit \
              --output-file test-results.xml \
              --coverage \
              --parallel \
              --max-workers 2
              
      - store_test_results:
          path: test-results.xml
          
      - store_artifacts:
          path: test-results.xml
          destination: test-results
          
      - store_artifacts:
          path: coverage
          destination: coverage
          
  deploy:
    executor: node-executor
    steps:
      - checkout
      - run:
          name: Deploy to production
          command: |
            if [ "${CIRCLE_BRANCH}" == "main" ]; then
              echo "Deploying to production..."
              # Your deployment commands here
            fi
            
workflows:
  test-and-deploy:
    jobs:
      - test
      - deploy:
          requires:
            - test
          filters:
            branches:
              only: main

Azure DevOps

# azure-pipelines.yml
trigger:
  branches:
    include:
      - main
      - develop

pool:
  vmImage: 'ubuntu-latest'

variables:
  nodeVersion: '20.x'

stages:
- stage: Test
  displayName: 'Run Tests'
  jobs:
  - job: UnitTests
    displayName: 'Unit Tests'
    steps:
    - task: NodeTool@0
      inputs:
        versionSpec: '$(nodeVersion)'
      displayName: 'Install Node.js'
      
    - task: Npm@1
      inputs:
        command: 'ci'
      displayName: 'Install dependencies'
      
    - task: Npm@1
      inputs:
        command: 'custom'
        customCommand: 'run build'
      displayName: 'Build application'
      
    - task: Npm@1
      inputs:
        command: 'custom'
        customCommand: 'install -g mcp-jest'
      displayName: 'Install MCP Jest'
      
    - script: |
        mcp-jest tests/unit/*.json \
          --reporter junit \
          --output-file $(Agent.TempDirectory)/unit-results.xml \
          --coverage \
          --coverage-dir $(Agent.TempDirectory)/coverage
      displayName: 'Run unit tests'
      
    - task: PublishTestResults@2
      inputs:
        testResultsFormat: 'JUnit'
        testResultsFiles: '$(Agent.TempDirectory)/unit-results.xml'
        testRunTitle: 'Unit Tests'
      condition: always()
      
    - task: PublishCodeCoverageResults@1
      inputs:
        codeCoverageTool: 'Cobertura'
        summaryFileLocation: '$(Agent.TempDirectory)/coverage/cobertura-coverage.xml'
        reportDirectory: '$(Agent.TempDirectory)/coverage'
      condition: always()

  - job: IntegrationTests
    displayName: 'Integration Tests'
    dependsOn: UnitTests
    steps:
    - task: NodeTool@0
      inputs:
        versionSpec: '$(nodeVersion)'
        
    - task: Npm@1
      inputs:
        command: 'ci'
        
    - task: Npm@1
      inputs:
        command: 'custom'
        customCommand: 'run build'
        
    - task: Npm@1
      inputs:
        command: 'custom'
        customCommand: 'install -g mcp-jest'
        
    - script: |
        mcp-jest tests/integration/*.json \
          --reporter junit \
          --output-file $(Agent.TempDirectory)/integration-results.xml \
          --timeout 60000 \
          --retries 2
      displayName: 'Run integration tests'
      
    - task: PublishTestResults@2
      inputs:
        testResultsFormat: 'JUnit'
        testResultsFiles: '$(Agent.TempDirectory)/integration-results.xml'
        testRunTitle: 'Integration Tests'
      condition: always()

Docker Integration

Test Container

# Dockerfile.test
FROM node:20-slim

WORKDIR /app

# Install MCP Jest globally
RUN npm install -g mcp-jest

# Copy package files
COPY package*.json ./
RUN npm ci --only=production

# Copy application
COPY . .

# Build application
RUN npm run build

# Set up test environment
ENV NODE_ENV=test
ENV LOG_LEVEL=error

# Create test script
RUN echo '#!/bin/bash\n\
set -e\n\
echo "Starting MCP Jest tests..."\n\
mcp-jest tests/*.json \\\n\
  --reporter junit \\\n\
  --output-file /app/results/test-results.xml \\\n\
  --coverage \\\n\
  --coverage-dir /app/results/coverage \\\n\
  --timeout 30000 \\\n\
  --no-colors\n\
echo "Tests completed successfully!"' > /app/run-tests.sh

RUN chmod +x /app/run-tests.sh

# Create results directory
RUN mkdir -p /app/results

CMD ["/app/run-tests.sh"]

Docker Compose for Testing

# docker-compose.test.yml
version: '3.8'

services:
  mcp-test:
    build:
      context: .
      dockerfile: Dockerfile.test
    volumes:
      - ./test-results:/app/results
    environment:
      - NODE_ENV=test
      - DATABASE_URL=postgres://test:test@postgres:5432/testdb
      - REDIS_URL=redis://redis:6379
    depends_on:
      - postgres
      - redis
    networks:
      - test-network

  postgres:
    image: postgres:13
    environment:
      POSTGRES_DB: testdb
      POSTGRES_USER: test
      POSTGRES_PASSWORD: test
    networks:
      - test-network

  redis:
    image: redis:7-alpine
    networks:
      - test-network

networks:
  test-network:
    driver: bridge

# Run with: docker-compose -f docker-compose.test.yml up --abort-on-container-exit

Test Reports and Artifacts

JUnit XML Output

<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="MCP Jest Tests" tests="3" failures="0" time="2.456">
  <testsuite name="My Test Suite" tests="3" failures="0" time="2.456">
    <testcase name="Should test capabilities" time="0.123" />
    <testcase name="Should test tool" time="1.234" />
    <testcase name="Should test resource" time="1.099" />
  </testsuite>
</testsuites>

HTML Reports

# Generate HTML report
mcp-jest tests/*.json \
  --reporter html \
  --output-dir ./reports/html \
  --title "MCP Server Test Results"

Environment-Specific Configuration

// mcp-jest.config.js
module.exports = {
  environments: {
    ci: {
      timeout: 30000,
      retries: 2,
      bail: true,
      parallel: true,
      maxWorkers: 2,
      colors: false,
      reporters: [
        'default',
        {
          name: 'junit',
          outputFile: 'test-results.xml'
        }
      ],
      coverage: {
        enabled: true,
        reporters: ['text', 'cobertura', 'html'],
        thresholds: {
          global: {
            branches: 80,
            functions: 80,
            lines: 80,
            statements: 80
          }
        }
      }
    },
    
    local: {
      timeout: 10000,
      watch: true,
      verbose: true,
      colors: true,
      reporters: ['default']
    }
  }
};

// Usage in CI:
// mcp-jest --env ci tests/*.json

Best Practices

✅ CI/CD Best Practices

  • • Use appropriate timeouts for CI environments
  • • Enable parallel execution to speed up tests
  • • Configure proper test artifacts and reports
  • • Set up coverage thresholds to maintain quality
  • • Use environment-specific configurations
  • • Implement proper cleanup and resource management

❌ Common Pitfalls

  • • Not handling test timeouts properly in CI
  • • Using development configurations in production
  • • Ignoring test failures or flaky tests
  • • Not preserving test artifacts
  • • Running resource-intensive tests in parallel

🚀 CI/CD Ready

With proper CI/CD integration, MCP Jest ensures your servers are tested automatically on every change.

Learn About Custom Matchers →