Skip to main content
Glama
README.md
# mock-mcp

![Node CI](https://github.com/mcpland/mock-mcp/workflows/Node%20CI/badge.svg)
[![npm](https://img.shields.io/npm/v/mock-mcp.svg)](https://www.npmjs.com/package/mock-mcp)
![license](https://img.shields.io/npm/l/mock-mcp)

Mock MCP Server - AI-generated mock data based on your **OpenAPI JSON Schema** definitions. The project uses a **Daemon + Adapter** architecture that enables multiple MCP clients (Cursor, Claude Desktop, etc.) to run simultaneously without port conflicts, while providing robust claim-based concurrency control for mock batch processing.

## Table of Contents

- [Quick Start](#quick-start)
- [Why Mock MCP](#why-mock-mcp)
- [What Mock MCP Does](#what-mock-mcp-does)
- [Architecture](#architecture)
- [Configure MCP Server](#configure-mcp-server)
- [Connect From Tests](#connect-from-tests)
- [Describe Requests with Metadata](#describe-requests-with-metadata)
- [MCP Tools](#mcp-tools)
- [CLI Commands](#cli-commands)
- [Available APIs](#available-apis)
- [Environment Variables](#environment-variables)
- [How It Works](#how-it-works)
- [Use the development scripts](#use-the-development-scripts)
- [License](#license)

## Quick Start

1. **Install the package.** Add mock-mcp as a dev dependency inside your project.

```bash
npm install -D mock-mcp
# or
yarn add -D mock-mcp
# or
pnpm add -D mock-mcp
```

2. **Configure the Model Context Protocol server.** Add mock-mcp to your MCP client configuration (Cursor, Claude Desktop, etc.):

```json
{
  "mcpServers": {
    "mock-mcp": {
      "command": "npx",
      "args": ["-y", "mock-mcp@latest", "adapter"]
    }
  }
}
```

> **Note:** The `adapter` command connects to a shared daemon process that is automatically started when needed. This eliminates port conflicts when running multiple MCP clients simultaneously.

3. **Connect from your tests.** Use `connect` to retrieve a mock client and request data for intercepted calls.

```ts
import { render, screen, fireEvent } from "@testing-library/react";
import { connect } from "mock-mcp";

const userSchema = {
  summary: "Fetch the current user",
  response: {
    type: "object",
    required: ["id", "name"],
    properties: {
      id: { type: "number" },
      name: { type: "string" },
    },
  },
};

it("example", async () => {
  const mockClient = await connect();
  const metadata = {
    schemaUrl: "https://example.com/openapi.json#/paths/~1user/get",
    schema: userSchema,
    instructions: "Respond with a single user described by the schema.",
  };

  fetchMock.get("/user", async () => {
    const response = await mockClient.requestMock("/user", "GET", { metadata }) // add mock via mock-mcp
    return response.data
  });

  const result = await fetch("/user");
  const data = await result.json();
  expect(data).toEqual({ id: 1, name: "Jane" });
}, 10 * 60 * 1000); // 10 minute timeout for AI interaction
```

4. **Run with MCP enabled.** Prompt your AI client to run the persistent test command and provide mocks through the tools.

```
Please run the persistent test: `MOCK_MCP=true npm test test/example.test.tsx` and mock fetch data with mock-mcp
```

## Why Mock MCP

### The Problem with Traditional Mock Approaches

Testing modern web applications often feels like preparing for a battle—you need the right weapons (test cases), ammunition (mock data), and strategy (test logic). But creating mock data has always been the most tedious part:

```typescript
// Traditional approach: Manual fixture hell
const mockUsers = [
  { id: 1, name: "Alice", email: "alice@example.com", role: "admin", ... },
  { id: 2, name: "Bob", email: "bob@example.com", role: "user", ... },
  // ... 50 more lines of boring manual data entry
];
```

**Common Pain Points:**

| Challenge                   | Traditional Solutions           | Limitations                                 |
| --------------------------- | ------------------------------- | ------------------------------------------- |
| **Creating Realistic Data** | Manual JSON files or faker.js   | ❌ Time-consuming, lacks business logic     |
| **Complex Scenarios**       | Hardcoded edge cases            | ❌ Difficult to maintain, brittle           |
| **Evolving Requirements**   | Update fixtures manually        | ❌ High maintenance cost                    |
| **Learning Curve**          | New team members write fixtures | ❌ Steep learning curve for complex domains |
| **CI/CD Integration**       | Static fixtures only            | ❌ Can't adapt to new scenarios             |

### The Mock MCP Innovation

Mock MCP introduces a **paradigm shift**: instead of treating mock data as static artifacts, it makes them **AI-generated, interactive, and evolvable**.

```
Traditional:  Write Test → Create Fixtures → Run Test → Maintain Fixtures
                                ↑                          ↓
                                └──────── Pain Loop ───────┘

Mock MCP:     Write Test → AI Generates Data (Schema-Compliant) → Run Test → Solidify Code
                             ↑                                    ↓
                             └───────────── Evolution ────────────┘
```

### Schema-Driven Accuracy

Unlike "hallucinated" mocks, Mock MCP uses your actual **OpenAPI JSON Schema** definitions to ground the AI. This ensures that generated data not only looks real but strictly adheres to your API contracts, catching integration issues early.

## What Mock MCP Does

Mock MCP uses a **Daemon + Adapter** architecture to move intercepted requests from tests to AI helpers and back again.

- **Schema-aware generation** uses your provided metadata (OpenAPI JSON Schema) to ensure mocks match production behavior.
- **Batch-aware test client** collects every network interception inside a single macrotask and waits for the full response set.
- **Claim-based concurrency** prevents multiple AI clients from racing on the same batch through lease-based locking.
- **Multi-run isolation** supports concurrent test processes with distinct run IDs.
- **IPC-based communication** uses Unix Domain Sockets (macOS/Linux) or Named Pipes (Windows) instead of TCP ports, eliminating port conflicts.
- **Timeouts, TTLs, and cleanup** guard the test runner from stale batches or disconnected clients.

## Architecture

The v0.4.0 release introduces a new **Daemon + Adapter** architecture that fundamentally solves the "multiple MCP clients" problem:

```
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   Test Process  │     │     Daemon      │     │    Adapter      │
│  (your tests)   │────▶│  (per-project)  │◀────│  (per MCP client)│
└─────────────────┘     └─────────────────┘     └─────────────────┘
        │                       │                       │
        │  WebSocket/IPC        │  JSON-RPC/IPC         │  MCP stdio
        │                       │                       │
        ▼                       ▼                       ▼
   BatchMockCollector     Mock Bridge Daemon      MCP Tools
   - Auto-discovers       - Manages runs/batches  - claim_next_batch
   - Sends batches        - Claim/lease control   - provide_batch_mock_data
   - Receives mocks       - Multi-client safe     - get_status, list_runs
```

**Key Benefits:**

- Single daemon per project (no per-client server instances)
- IPC communication
- Full multi-client support
- Claim-based concurrency (no race conditions)
- Auto-discovery (no manual configuration)

## Configure MCP Server

Add mock-mcp to your MCP client configuration. The adapter automatically discovers or starts the daemon for your project:

```json
{
  "mcpServers": {
    "mock-mcp": {
      "command": "npx",
      "args": ["-y", "mock-mcp", "adapter"]
    }
  }
}
```

**That's it!** The daemon uses IPC (Unix Domain Sockets on macOS/Linux, Named Pipes on Windows) which:

- Eliminates port conflicts between multiple MCP clients
- Automatically shares state between all adapters in the same project
- Requires no manual coordination or environment variables

Restart your MCP client and confirm that the `mock-mcp` server exposes the tools (`get_status`, `claim_next_batch`, `provide_batch_mock_data`, etc.).

## Connect From Tests

Tests call `connect` to spin up a `BatchMockCollector` that automatically discovers and connects to the daemon:

```ts
// tests/mocks.ts
import { connect } from "mock-mcp";

// Auto-discovers daemon via IPC
const mockClient = await connect({
  timeout: 60000,
});

await page.route("**/api/users", async (route) => {
  const url = new URL(route.request().url());
  const { data } = await mockClient.requestMock(
    url.pathname,
    route.request().method()
  );

  await route.fulfill({
    status: 200,
    contentType: "application/json",
    body: JSON.stringify(data),
  });
});
```

Batch behaviour stays automatic: additional `requestMock` calls issued in the same macrotask are grouped, forwarded, and resolved together.

Need to pause the test until everything in-flight resolves? Call `waitForPendingRequests` to block on the current set of pending requests (anything started after the call is not included):

```ts
// After routing a few requests
await mockClient.waitForPendingRequests();
// Safe to assert on the results produced by the mocked responses
```

**Multiple test processes** can run concurrently - each gets a unique `runId` and their batches are isolated from each other.

## Describe Requests with Metadata

`requestMock` accepts an optional third argument (`RequestMockOptions`) that is forwarded without modification to the MCP server. The most important field in that object is `metadata`, which lets the test process describe each request with the exact OpenAPI JSON Schema fragment, sample payloads, or test context that the AI client needs to build a response.

When an MCP client calls `get_pending_batches`, every `requests[].metadata` entry from the test run is included in the response. That is the channel the LLM uses to understand the requested endpoint before supplying data through `provide_batch_mock_data`. Metadata is also persisted when batch logging is enabled, so you can audit what was sent to the model.

```ts
const listProductsSchema = {
  summary: "List products by popularity",
  response: {
    type: "array",
    items: {
      type: "object",
      required: ["id", "name", "price"],
      properties: {
        id: { type: "string" },
        name: { type: "string" },
        price: { type: "number" },
      },
    },
  },
};

await mockClient.requestMock("/api/products", "GET", {
  metadata: {
    // Link or embed the authoritative contract for the AI to follow.
    schemaUrl:
      "https://shop.example.com/openapi.json#/paths/~1api~1products/get",
    schema: listProductsSchema,
    instructions:
      "Return 3 popular products with stable ids so the UI can snapshot them.",
    testFile: expect.getState().testPath,
  },
});
```

**Tips for useful metadata**

- Embed the OpenAPI/JSON Schema snippet (or a reference URL) that describes the response structure for the intercepted endpoint.
- Include contextual hints such as the test name, scenario, user role, or seed data so the model can mirror your expected fixtures.
- Keep the metadata JSON-serializable and deterministic; large binary blobs or class instances will be dropped.
- Reuse helper functions to centralize schema definitions so each test only supplies the endpoint-specific instructions.

## MCP Tools

The new architecture provides a richer set of tools with claim-based concurrency control:

| Tool                      | Purpose                                         | Input                                      |
| ------------------------- | ----------------------------------------------- | ------------------------------------------ |
| `get_status`              | Get daemon status (runs, pending, claimed)      | None                                       |
| `list_runs`               | List all active test runs                       | None                                       |
| `claim_next_batch`        | Claim the next pending batch (with lease)       | `{ runId?, leaseMs? }`                     |
| `get_batch`               | Get details of a specific batch (read-only)     | `{ batchId }`                              |
| `provide_batch_mock_data` | Provide mock data for a claimed batch           | `{ batchId, claimToken, mocks }`           |
| `release_batch`           | Release a claimed batch without providing mocks | `{ batchId, claimToken, reason? }`         |

### Workflow

The new workflow uses **claim → provide** to prevent race conditions:

1. **Claim a batch** - Call `claim_next_batch` to acquire a lease on a pending batch
2. **Receive batch details** - Get `batchId`, `claimToken`, and `requests` array
3. **Generate mocks** - Create mock responses for each request
4. **Provide mocks** - Call `provide_batch_mock_data` with the claim token

```jsonc
// Step 1: Claim
{
  "name": "claim_next_batch",
  "arguments": { "leaseMs": 30000 }
}
// Returns: { "batchId": "batch:abc:1", "claimToken": "xyz", "requests": [...] }

// Step 2: Provide
{
  "name": "provide_batch_mock_data",
  "arguments": {
    "batchId": "batch:abc:1",
    "claimToken": "xyz",
    "mocks": [
      { "requestId": "req-1", "data": { "id": 1, "name": "Alice" } }
    ]
  }
}
```

**Lease expiration**: If you don't provide mocks within the lease time (default 30s), the batch is automatically released for another adapter to claim.

## CLI Commands

| Command             | Description                                           |
| ------------------- | ----------------------------------------------------- |
| `mock-mcp adapter`  | Start the MCP adapter (default, for MCP clients)      |
| `mock-mcp daemon`   | Start the daemon process (usually auto-started)       |
| `mock-mcp status`   | Show daemon status for current project                |
| `mock-mcp stop`     | Stop the daemon for current project                   |
| `mock-mcp help`     | Show help                                             |
| `mock-mcp version`  | Show version                                          |

Example usage:

```bash
# Check if daemon is running
mock-mcp status

# Manually stop daemon
mock-mcp stop
```

## Available APIs

The library exports primitives so you can embed the workflow inside bespoke runners or scripts:

### Client APIs

- `connect(options?)` - Creates a `BatchMockCollector` and waits for daemon connection.
- `BatchMockCollector` - Low-level batching client for test environments.
- `BatchMockCollector.requestMock(endpoint, method, options?)` - Request mock data for an endpoint.
- `BatchMockCollector.waitForPendingRequests()` - Wait for pending requests to settle.
- `BatchMockCollector.getRunId()` - Get the unique run ID for this collector.

### Server APIs

- `MockMcpDaemon` - The daemon process that manages runs and batches.
- `runAdapter()` - Start the MCP adapter (stdio transport).
- `DaemonClient` - JSON-RPC client for communicating with the daemon.

### Discovery APIs

- `ensureDaemonRunning(options?)` - Ensure daemon is running, start if needed.
- `resolveProjectRoot(startDir?)` - Find project root by searching for `.git` or `package.json`.
- `computeProjectId(projectRoot)` - Compute stable project ID from path.

Each class accepts logger overrides, timeout tweaks, and other ergonomics.

## Environment Variables

| Variable             | Description                                                              | Default            |
| -------------------- | ------------------------------------------------------------------------ | ------------------ |
| `MOCK_MCP`           | Enables the test runner hook so intercepted requests are routed to mock-mcp. | unset              |
| `MOCK_MCP_CACHE_DIR` | Override the cache directory for daemon files (registry, socket, lock). | `~/.cache/mock-mcp`|

## How It Works

The new **Daemon + Adapter** architecture uses four collaborating processes:

| Process          | Responsibility                                        | Technology                               | Communication                   |
| ---------------- | ----------------------------------------------------- | ---------------------------------------- | ------------------------------- |
| **Test Process** | Executes test cases and intercepts HTTP requests      | Playwright/Puppeteer + BatchMockCollector| WebSocket over IPC → Daemon     |
| **Daemon**       | Manages runs, batches, claims with lease control      | Node.js + HTTP/WS on Unix socket         | IPC ↔ Test & Adapter            |
| **Adapter**      | Bridges MCP protocol to daemon RPC                    | Node.js + MCP SDK (stdio)                | stdio ↔ MCP Client, RPC → Daemon|
| **MCP Client**   | Uses AI to produce mock data via MCP tools            | Cursor / Claude Desktop / custom clients | MCP protocol → Adapter          |

### Data flow sequence with claim-based concurrency

```
┌──────────────────┐      ┌──────────────────┐      ┌──────────────────┐      ┌──────────────────┐
│  Test Process    │      │     Daemon       │      │     Adapter      │      │   MCP Client     │
│  (Browser Test)  │      │  (per-project)   │      │ (per MCP client) │      │      (AI)        │
└────────┬─────────┘      └────────┬─────────┘      └────────┬─────────┘      └────────┬─────────┘
         │                         │                         │                         │
         │  1. Connect via IPC     │                         │                         │
         │     HELLO_TEST          │                         │                         │
         ├════════════════════════►│                         │                         │
         │                         │                         │                         │
         │  2. HELLO_ACK           │                         │                         │
         │◄════════════════════════┤                         │                         │
         │                         │                         │                         │
         │  3. BATCH_MOCK_REQUEST  │                         │                         │
         │     [req-1, req-2, ...] │                         │                         │
         ├════════════════════════►│                         │                         │
         │                         │                         │                         │
         │     Test paused...      │  4. Store in pending    │                         │
         │       Awaiting mocks    │     queue               │                         │
         │                         │                         │                         │
         │                         │                         │◄────────────────────────┤
         │                         │                         │  5. claim_next_batch    │
         │                         │                         │                         │
         │                         │◄────────────────────────┤                         │
         │                         │  6. RPC: claimNextBatch │                         │
         │                         │                         │                         │
         │                         ├────────────────────────►│                         │
         │                         │  7. {batch, claimToken} │                         │
         │                         │                         │                         │
         │                         │                         ├────────────────────────►│
         │                         │                         │  8. Return batch info   │
         │                         │                         │                         │
         │                         │                         │        9. AI generates  │
         │                         │                         │           mock data     │
         │                         │                         │                         │
         │                         │                         │◄────────────────────────┤
         │                         │                         │  10. provide_batch_     │
         │                         │                         │      mock_data          │
         │                         │                         │                         │
         │                         │◄────────────────────────┤                         │
         │                         │  11. RPC: provideBatch  │                         │
         │                         │      + claimToken       │                         │
         │                         │                         │                         │
         │  12. BATCH_MOCK_RESULT  │                         │                         │
         │      [mock-1, mock-2]   │                         │                         │
         │◄════════════════════════┤                         │                         │
         │                         │                         │                         │
         │  13. Resolve promises   │                         │                         │
         │      Test continues     │                         │                         │
         ▼                         ▼                         ▼                         ▼

Protocol Summary:
─────────────────
- Test Process ←→ Daemon: WebSocket over IPC (Unix socket / Named pipe)
  Message types: HELLO_TEST, BATCH_MOCK_REQUEST, BATCH_MOCK_RESULT

- Adapter ←→ Daemon: HTTP JSON-RPC over IPC
  Methods: claimNextBatch, provideBatch, getStatus, listRuns

- MCP Client ←→ Adapter: MCP protocol (stdio)
  Tools: claim_next_batch, provide_batch_mock_data, get_status, list_runs

Key Features:
──────────────
✓ uses IPC instead of TCP - No port conflicts
✓ Multi-client support - multiple MCP clients can run simultaneously
✓ Claim-based concurrency - prevents race conditions on batches
✓ Lease expiration - auto-recovery if adapter crashes
✓ Multi-run isolation - concurrent test processes are isolated
✓ Auto-discovery - no manual configuration needed
```

## Use the development scripts

```bash
yarn test              # runs Vitest suites
yarn test:concurrency  # runs concurrency tests specifically
yarn dev               # tsx watch mode for the CLI
yarn dev:adapter       # tsx watch mode for adapter
yarn lint              # eslint --ext .ts
yarn build             # compile TypeScript
```

Tests create isolated daemon instances with temporary cache directories, so they can run safely without affecting your development environment.

## License

MIT

TDQS

A4/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: claiming, getting details, providing data, releasing, and status queries. No overlap or ambiguity.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case, making the API predictable and easy to navigate.

Tool Count5/5

With 6 tools covering the core workflow (claim, provide, release, inspect), the count is well-scoped and each tool serves a necessary function.

Completeness5/5

The tool set fully covers the mock batch lifecycle: claiming, providing data, releasing, plus status and batch details. No obvious gaps for the stated purpose.

Maintenance

ActivityInactive
ResponsivenessNo issues