Home / Function/ createServerFixture() — mcp Function Reference

createServerFixture() — mcp Function Reference

Architecture documentation for the createServerFixture() function in server.integration.test.ts from the mcp codebase.

Entity Profile

Relationship Graph

Source Code

src/server.integration.test.ts lines 19–127

function createServerFixture(extraEnv: Record<string, string> = {}) {
  let server: ChildProcess;
  let requestId = 0;
  let responseQueue: Map<number, { resolve: (value: any) => void; reject: (err: Error) => void }> = new Map();
  let rl: readline.Interface;
  let startupError: Error | null = null;

  function sendRequest(method: string, params: Record<string, unknown> = {}): Promise<any> {
    return new Promise((resolve, reject) => {
      const id = ++requestId;
      const request = {
        jsonrpc: '2.0',
        id,
        method,
        params
      };
      responseQueue.set(id, { resolve, reject });
      server.stdin!.write(JSON.stringify(request) + '\n');

      setTimeout(() => {
        if (responseQueue.has(id)) {
          responseQueue.delete(id);
          reject(new Error(`Request ${method} timed out`));
        }
      }, 5000);
    });
  }

  function setup() {
    beforeAll(async () => {
      const distPath = path.join(__dirname, '..', 'dist', 'index.js');
      if (!existsSync(distPath)) {
        throw new Error(
          `Server build not found at ${distPath}. Run 'npm run build' first.`
        );
      }

      server = spawn('node', [distPath, '--no-api-fallback'], {
        stdio: ['pipe', 'pipe', 'pipe'],
        env: { ...process.env, ...extraEnv }
      });

      server.on('error', (err) => {
        startupError = new Error(`Failed to start MCP server: ${err.message}`);
      });

      rl = readline.createInterface({
        input: server.stdout!,
        crlfDelay: Infinity
      });

      rl.on('line', (line) => {
        try {
          const response = JSON.parse(line);
          if (response.id && responseQueue.has(response.id)) {
            const { resolve, reject } = responseQueue.get(response.id)!;
            responseQueue.delete(response.id);
            if (response.error) {
              reject(new Error(JSON.stringify(response.error)));
            } else {
              resolve(response.result);
            }
          }
        } catch {
          // Not JSON, ignore
        }
      });

      let ready = false;
      const startTime = Date.now();
      while (Date.now() - startTime < SERVER_STARTUP_TIMEOUT_MS) {
        if (startupError) throw startupError;
        if (server.exitCode !== null) {
          throw new Error(`Server exited unexpectedly with code ${server.exitCode}`);
        }
        await new Promise(r => setTimeout(r, STARTUP_POLL_INTERVAL_MS));
        if (server.stdin?.writable) {
          ready = true;
          break;
        }
      }

      if (!ready) {
        throw new Error(`Server not ready after ${SERVER_STARTUP_TIMEOUT_MS}ms`);
      }

      // Initialize the server so all tests have a consistent state
      await sendRequest('initialize', {
        protocolVersion: '2024-11-05',
        capabilities: {},
        clientInfo: { name: 'jest-test', version: '1.0.0' }
      });
    });

    afterAll(async () => {
      responseQueue.clear();
      rl?.close();
      if (server && !server.killed) {
        server.stdin?.end();
        server.stdout?.destroy();
        server.stderr?.destroy();
        server.kill('SIGKILL');
      }
      await new Promise(r => setTimeout(r, 100));
    });
  }

  return { sendRequest, setup };
}

Domain

Subdomains

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free