MP-301b · Module 3

Automated Test Pipelines

4 min read

An MCP server test pipeline has three stages that should run in order: unit tests (fastest, most numerous), integration tests (medium speed, protocol-level), and e2e tests (slowest, highest confidence). Fail fast: if unit tests fail, skip the rest. This keeps CI feedback under 2 minutes for clean code while still running comprehensive checks on every push. Structure your pipeline as separate CI jobs with dependencies so you get parallel execution where possible and sequential gating where needed.

Beyond the three test stages, add static analysis gates: TypeScript strict compilation (catches type mismatches between schema and handler), linting (catches code quality issues), and schema validation (catches malformed tool definitions). These run in parallel with unit tests since they have no dependencies. A failed type check is often a faster signal than a failed test, so run tsc --noEmit as the very first step.

name: MCP Server Tests
on: [push, pull_request]

jobs:
  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm ci
      - run: npx tsc --noEmit

  unit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm ci
      - run: npx vitest run tests/handlers/ tests/schemas/

  integration:
    needs: [typecheck, unit]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm ci
      - run: npx vitest run tests/integration/

  e2e:
    needs: integration
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm ci
      - run: npx vitest run tests/e2e/
  1. Structure tests by layer Organize into tests/handlers/ (unit), tests/schemas/ (schema validation), tests/integration/ (protocol), and tests/e2e/ (workflows). Each directory runs as a separate CI stage.
  2. Add dependency gates Integration tests depend on unit + typecheck passing. E2e tests depend on integration passing. Use CI `needs` directives for sequencing.
  3. Set a time budget Target: typecheck < 10s, unit < 30s, integration < 60s, e2e < 120s. If any stage exceeds its budget, investigate — slow tests indicate slow tools or missing fixtures.