Mutation Server Protocol Specification

0.4.1 · active · verified Sun Apr 19

The `mutation-server-protocol` package defines the Mutation Server Protocol (MSP), a standardized, language-agnostic specification based on JSON-RPC 2.0. Its purpose is to enable seamless communication between Integrated Development Environments (IDEs) or other tools and mutation testing frameworks. Inspired by the Language Server Protocol, MSP establishes a unified method for initiating mutation tests, reporting their progress, and exchanging structured data like mutation locations and results. The current stable version is 0.4.2, with recent minor updates in March 2026, indicating active maintenance within the Stryker Mutator monorepo. Key differentiators include its explicit focus on mutation testing, support for both Standard Input/Output (stdio) and TCP/IP Socket transport modes, and detailed message formats for operations such as mutant discovery and execution. It emphasizes 1-based indexing for positions and locations, aligning with common text editor conventions.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates defining a basic Mutation Server Protocol handler using its TypeScript types and simulates client-server message exchange for `discover` and `mutationTest` methods.

import type {
  MutationServer,
  DiscoverParams,
  MutationTestParams,
  MutationTestResult,
  FileRange,
  Mutant,
  Location,
} from 'mutation-server-protocol';

// Simulate a basic JSON-RPC message handler implementing the MSP server interface
class MyMutationServer implements MutationServer {
  private requestIdCounter = 0;

  // MSP method: discover mutants in a given scope
  async discover(params: DiscoverParams): Promise<Mutant[]> {
    console.log(`[Server] Received discover request for files: ${params.files?.map(f => f.fileName).join(', ')}`);
    // In a real server, this would analyze code to find potential mutants
    const mutants: Mutant[] = [
      {
        id: 'mutant-1',
        mutatorName: 'BinaryExpression',
        replacement: 'false', // Example replacement
        location: { start: { line: 1, column: 10 }, end: { line: 1, column: 15 } },
        fileName: 'src/example.js',
        status: 'Pending'
      },
    ];
    return mutants;
  }

  // MSP method: run mutation tests for specific mutants
  async mutationTest(params: MutationTestParams): Promise<MutationTestResult> {
    console.log(`[Server] Received mutationTest request for mutants: ${params.mutants?.map(m => m.id).join(', ')}`);
    // In a real server, this would execute tests against mutated code
    const result: MutationTestResult = {
      mutantResults: {
        'mutant-1': { status: 'Killed', coveredBy: ['testA'] },
      },
      // ... other results like files, test results
    };
    return result;
  }

  // Example of how a client might construct and send a request
  async simulateClientRequest() {
    const server = new MyMutationServer();

    const discoverRequest = {
      jsonrpc: '2.0',
      id: ++this.requestIdCounter,
      method: 'discover',
      params: {
        files: [{ fileName: 'src/example.js' } as FileRange],
        // Optional other params like 'testFramework'
      } as DiscoverParams,
    };

    console.log('\n[Client] Sending discover request:', JSON.stringify(discoverRequest, null, 2));
    const discoverResponse = await server.discover(discoverRequest.params);
    console.log('[Client] Received discover response:', JSON.stringify(discoverResponse, null, 2));

    const mutationTestRequest = {
      jsonrpc: '2.0',
      id: ++this.requestIdCounter,
      method: 'mutationTest',
      params: {
        mutants: discoverResponse.slice(0, 1), // Test the first discovered mutant
        // Optional other params
      } as MutationTestParams,
    };

    console.log('\n[Client] Sending mutationTest request:', JSON.stringify(mutationTestRequest, null, 2));
    const mutationTestResponse = await server.mutationTest(mutationTestRequest.params);
    console.log('[Client] Received mutationTest response:', JSON.stringify(mutationTestResponse, null, 2));
  }
}

const simulator = new MyMutationServer();
simulator.simulateClientRequest();

view raw JSON →