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 →