https://github.com/mcpland/mock-mcp
Mock MCP Server - AI-driven mock data orchestration with OpenAPI JSON Schema for testing
https://github.com/mcpland/mock-mcp
mcp-server mock mock-data openapi openapi-spec
Last synced: 9 days ago
JSON representation
Mock MCP Server - AI-driven mock data orchestration with OpenAPI JSON Schema for testing
- Host: GitHub
- URL: https://github.com/mcpland/mock-mcp
- Owner: mcpland
- License: mit
- Created: 2025-11-04T18:40:03.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2026-03-08T18:03:15.000Z (4 months ago)
- Last Synced: 2026-03-08T22:10:16.174Z (4 months ago)
- Topics: mcp-server, mock, mock-data, openapi, openapi-spec
- Language: TypeScript
- Homepage:
- Size: 313 KB
- Stars: 5
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# mock-mcp

[](https://www.npmjs.com/package/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