mock-mcp 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -35
- package/dist/{src/index.js → index.js} +2 -2
- package/dist/{src/server → server}/test-mock-mcp-server.js +9 -9
- package/package.json +1 -1
- package/dist/package.json +0 -73
- /package/dist/{src/client → client}/batch-mock-collector.d.ts +0 -0
- /package/dist/{src/client → client}/batch-mock-collector.js +0 -0
- /package/dist/{src/client → client}/connect.d.ts +0 -0
- /package/dist/{src/client → client}/connect.js +0 -0
- /package/dist/{src/client → client}/index.d.ts +0 -0
- /package/dist/{src/client → client}/index.js +0 -0
- /package/dist/{src/index.d.ts → index.d.ts} +0 -0
- /package/dist/{src/server → server}/index.d.ts +0 -0
- /package/dist/{src/server → server}/index.js +0 -0
- /package/dist/{src/server → server}/test-mock-mcp-server.d.ts +0 -0
- /package/dist/{src/types.d.ts → types.d.ts} +0 -0
- /package/dist/{src/types.js → types.js} +0 -0
package/README.md
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/mock-mcp)
|
|
5
5
|

|
|
6
6
|
|
|
7
|
-
Mock MCP
|
|
7
|
+
Mock MCP Server - AI-generated mock data. The project pairs a WebSocket batch bridge with MCP tooling so Cursor, Claude Desktop, or any compatible client can fulfill intercepted requests in real time.
|
|
8
8
|
|
|
9
9
|
## Table of Contents
|
|
10
|
+
|
|
10
11
|
- [Quick Start](#quick-start)
|
|
11
12
|
- [Why Mock MCP](#why-mock-mcp)
|
|
12
13
|
- [What Mock MCP Does](#what-mock-mcp-does)
|
|
@@ -44,7 +45,7 @@ Mock MCP orchestrates AI-generated mock data via the Model Context Protocol (MCP
|
|
|
44
45
|
```ts
|
|
45
46
|
import { render, screen, fireEvent } from "@testing-library/react";
|
|
46
47
|
import { connect } from "mock-mcp";
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
const userSchema = {
|
|
49
50
|
summary: "Fetch the current user",
|
|
50
51
|
response: {
|
|
@@ -52,23 +53,23 @@ Mock MCP orchestrates AI-generated mock data via the Model Context Protocol (MCP
|
|
|
52
53
|
required: ["id", "name"],
|
|
53
54
|
properties: {
|
|
54
55
|
id: { type: "number" },
|
|
55
|
-
name: { type: "string" }
|
|
56
|
-
}
|
|
57
|
-
}
|
|
56
|
+
name: { type: "string" },
|
|
57
|
+
},
|
|
58
|
+
},
|
|
58
59
|
};
|
|
59
|
-
|
|
60
|
+
|
|
60
61
|
it("example", async () => {
|
|
61
62
|
const mockClient = await connect();
|
|
62
63
|
const metadata = {
|
|
63
64
|
schemaUrl: "https://example.com/openapi.json#/paths/~1user/get",
|
|
64
65
|
schema: userSchema,
|
|
65
|
-
instructions: "Respond with a single user described by the schema."
|
|
66
|
+
instructions: "Respond with a single user described by the schema.",
|
|
66
67
|
};
|
|
67
|
-
|
|
68
|
+
|
|
68
69
|
fetchMock.get("/user", () =>
|
|
69
70
|
mockClient.requestMock("/user", "GET", { metadata })
|
|
70
71
|
);
|
|
71
|
-
|
|
72
|
+
|
|
72
73
|
const result = await fetch("/user");
|
|
73
74
|
const data = await result.json();
|
|
74
75
|
expect(data).toEqual({ id: 1, name: "Jane" });
|
|
@@ -98,13 +99,13 @@ const mockUsers = [
|
|
|
98
99
|
|
|
99
100
|
**Common Pain Points:**
|
|
100
101
|
|
|
101
|
-
| Challenge
|
|
102
|
-
|
|
103
|
-
| **Creating Realistic Data** | Manual JSON files or faker.js
|
|
104
|
-
| **Complex Scenarios**
|
|
105
|
-
| **Evolving Requirements**
|
|
106
|
-
| **Learning Curve**
|
|
107
|
-
| **CI/CD Integration**
|
|
102
|
+
| Challenge | Traditional Solutions | Limitations |
|
|
103
|
+
| --------------------------- | ------------------------------- | ------------------------------------------- |
|
|
104
|
+
| **Creating Realistic Data** | Manual JSON files or faker.js | ❌ Time-consuming, lacks business logic |
|
|
105
|
+
| **Complex Scenarios** | Hardcoded edge cases | ❌ Difficult to maintain, brittle |
|
|
106
|
+
| **Evolving Requirements** | Update fixtures manually | ❌ High maintenance cost |
|
|
107
|
+
| **Learning Curve** | New team members write fixtures | ❌ Steep learning curve for complex domains |
|
|
108
|
+
| **CI/CD Integration** | Static fixtures only | ❌ Can't adapt to new scenarios |
|
|
108
109
|
|
|
109
110
|
### The Mock MCP Innovation
|
|
110
111
|
|
|
@@ -133,10 +134,10 @@ Mock MCP pairs a WebSocket batch bridge with MCP tooling to move intercepted req
|
|
|
133
134
|
|
|
134
135
|
CLI flags keep the WebSocket bridge and the MCP transports aligned. Use them to adapt the server to your local ports while the Environment Variables section covers per-process overrides:
|
|
135
136
|
|
|
136
|
-
| Option
|
|
137
|
-
|
|
|
138
|
-
| `--port`, `-p`
|
|
139
|
-
| `--no-stdio`
|
|
137
|
+
| Option | Description | Default |
|
|
138
|
+
| -------------- | ------------------------------------------------------------------ | ------- |
|
|
139
|
+
| `--port`, `-p` | WebSocket port for test runners | `3002` |
|
|
140
|
+
| `--no-stdio` | Disable the MCP stdio transport (useful for local debugging/tests) | enabled |
|
|
140
141
|
|
|
141
142
|
The CLI installs a SIGINT/SIGTERM handler so `Ctrl+C` shuts everything down cleanly.
|
|
142
143
|
|
|
@@ -205,21 +206,22 @@ const listProductsSchema = {
|
|
|
205
206
|
properties: {
|
|
206
207
|
id: { type: "string" },
|
|
207
208
|
name: { type: "string" },
|
|
208
|
-
price: { type: "number" }
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
209
|
+
price: { type: "number" },
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
},
|
|
212
213
|
};
|
|
213
214
|
|
|
214
215
|
await mockClient.requestMock("/api/products", "GET", {
|
|
215
216
|
metadata: {
|
|
216
217
|
// Link or embed the authoritative contract for the AI to follow.
|
|
217
|
-
schemaUrl:
|
|
218
|
+
schemaUrl:
|
|
219
|
+
"https://shop.example.com/openapi.json#/paths/~1api~1products/get",
|
|
218
220
|
schema: listProductsSchema,
|
|
219
221
|
instructions:
|
|
220
222
|
"Return 3 popular products with stable ids so the UI can snapshot them.",
|
|
221
|
-
testFile: expect.getState().testPath
|
|
222
|
-
}
|
|
223
|
+
testFile: expect.getState().testPath,
|
|
224
|
+
},
|
|
223
225
|
});
|
|
224
226
|
```
|
|
225
227
|
|
|
@@ -265,20 +267,20 @@ Each class accepts logger overrides, timeout tweaks, and other ergonomics surfac
|
|
|
265
267
|
|
|
266
268
|
## Environment Variables
|
|
267
269
|
|
|
268
|
-
| Variable | Description
|
|
269
|
-
| ----------------- |
|
|
270
|
-
| `MCP_SERVER_PORT` | Overrides the WebSocket port used by both the CLI and any spawned MCP host.
|
|
270
|
+
| Variable | Description | Default |
|
|
271
|
+
| ----------------- | ---------------------------------------------------------------------------- | ------- |
|
|
272
|
+
| `MCP_SERVER_PORT` | Overrides the WebSocket port used by both the CLI and any spawned MCP host. | `3002` |
|
|
271
273
|
| `MOCK_MCP` | Enables the test runner hook so intercepted requests are routed to mock-mcp. | unset |
|
|
272
274
|
|
|
273
275
|
## How It Works
|
|
274
276
|
|
|
275
277
|
Three collaborating processes share responsibilities while staying loosely coupled:
|
|
276
278
|
|
|
277
|
-
| Process | Responsibility
|
|
278
|
-
| ---------------- |
|
|
279
|
-
| **Test Process** | Executes test cases and intercepts HTTP requests
|
|
280
|
-
| **MCP Server** | Coordinates batches and forwards data between parties
|
|
281
|
-
| **MCP Client** | Uses AI to produce mock data via MCP tools
|
|
279
|
+
| Process | Responsibility | Technology | Communication |
|
|
280
|
+
| ---------------- | ----------------------------------------------------- | ---------------------------------------- | ------------------------------------------ |
|
|
281
|
+
| **Test Process** | Executes test cases and intercepts HTTP requests | Playwright/Puppeteer + WebSocket client | WebSocket → MCP Server |
|
|
282
|
+
| **MCP Server** | Coordinates batches and forwards data between parties | Node.js + WebSocket server + MCP SDK | stdio ↔ MCP Client · WebSocket ↔ Test Flow |
|
|
283
|
+
| **MCP Client** | Uses AI to produce mock data via MCP tools | Cursor / Claude Desktop / custom clients | MCP protocol → MCP Server |
|
|
282
284
|
|
|
283
285
|
### Data flow sequence clarifies message order
|
|
284
286
|
|
|
@@ -27,9 +27,9 @@ async function runCli() {
|
|
|
27
27
|
enableMcpTransport,
|
|
28
28
|
});
|
|
29
29
|
await server.start();
|
|
30
|
-
console.
|
|
30
|
+
console.error(`🎯 Test Mock MCP server ready on ws://localhost:${server.port ?? port}`);
|
|
31
31
|
const shutdown = async () => {
|
|
32
|
-
console.
|
|
32
|
+
console.error("👋 Shutting down Test Mock MCP server...");
|
|
33
33
|
await server.stop();
|
|
34
34
|
process.exit(0);
|
|
35
35
|
};
|
|
@@ -130,7 +130,7 @@ export class TestMockMCPServer {
|
|
|
130
130
|
};
|
|
131
131
|
batch.ws.send(JSON.stringify(payload));
|
|
132
132
|
this.pendingBatches.delete(batchId);
|
|
133
|
-
this.logger.
|
|
133
|
+
this.logger.error(`✅ Delivered ${mocks.length} mock(s) to test process for ${batchId}`);
|
|
134
134
|
return this.buildToolResponse(JSON.stringify({
|
|
135
135
|
success: true,
|
|
136
136
|
message: `Provided mock data for ${batchId}`,
|
|
@@ -147,7 +147,7 @@ export class TestMockMCPServer {
|
|
|
147
147
|
wss.once("listening", () => {
|
|
148
148
|
const address = wss.address();
|
|
149
149
|
this.actualPort = address?.port ?? desiredPort;
|
|
150
|
-
this.logger.
|
|
150
|
+
this.logger.error(`🚀 WebSocket server listening on ws://localhost:${this.actualPort}`);
|
|
151
151
|
resolve();
|
|
152
152
|
});
|
|
153
153
|
wss.once("error", (error) => {
|
|
@@ -228,7 +228,7 @@ export class TestMockMCPServer {
|
|
|
228
228
|
this.mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
229
229
|
const toolName = request.params.name;
|
|
230
230
|
if (toolName === "get_pending_batches") {
|
|
231
|
-
this.logger.
|
|
231
|
+
this.logger.error("📋 MCP client inspected pending batches");
|
|
232
232
|
return this.buildToolResponse(JSON.stringify(this.getPendingBatches(), null, 2));
|
|
233
233
|
}
|
|
234
234
|
if (toolName === "provide_batch_mock_data") {
|
|
@@ -243,14 +243,14 @@ export class TestMockMCPServer {
|
|
|
243
243
|
this.transport =
|
|
244
244
|
this.options.transportFactory?.() ?? new StdioServerTransport();
|
|
245
245
|
await this.mcpServer.connect(this.transport);
|
|
246
|
-
this.logger.
|
|
246
|
+
this.logger.error("✅ MCP server is ready (stdio transport)");
|
|
247
247
|
}
|
|
248
248
|
handleConnection(ws) {
|
|
249
|
-
this.logger.
|
|
249
|
+
this.logger.error("🔌 Test process connected");
|
|
250
250
|
this.clients.add(ws);
|
|
251
251
|
ws.on("message", (data) => this.handleClientMessage(ws, data));
|
|
252
252
|
ws.on("close", () => {
|
|
253
|
-
this.logger.
|
|
253
|
+
this.logger.error("🔌 Test process disconnected");
|
|
254
254
|
this.clients.delete(ws);
|
|
255
255
|
this.dropBatchesForClient(ws);
|
|
256
256
|
});
|
|
@@ -292,11 +292,11 @@ export class TestMockMCPServer {
|
|
|
292
292
|
ws,
|
|
293
293
|
expiresAt,
|
|
294
294
|
});
|
|
295
|
-
this.logger.
|
|
295
|
+
this.logger.error([
|
|
296
296
|
`📥 Received ${requests.length} request(s) (${batchId})`,
|
|
297
297
|
...requests.map((req, index) => ` ${index + 1}. ${req.method} ${req.endpoint} (${req.requestId})`),
|
|
298
298
|
].join("\n"));
|
|
299
|
-
this.logger.
|
|
299
|
+
this.logger.error("⏳ Awaiting mock data from MCP client...");
|
|
300
300
|
}
|
|
301
301
|
dropBatchesForClient(ws) {
|
|
302
302
|
for (const [batchId, batch] of this.pendingBatches) {
|
|
@@ -325,7 +325,7 @@ export class TestMockMCPServer {
|
|
|
325
325
|
const entry = this.buildLogEntry(batch, mocks);
|
|
326
326
|
const filePath = path.join(directory, `mock-${batch.batchId}.json`);
|
|
327
327
|
await writeFile(filePath, JSON.stringify(entry, null, 2), "utf8");
|
|
328
|
-
this.logger.
|
|
328
|
+
this.logger.error(`📝 Saved mock batch ${batch.batchId} to ${filePath}`);
|
|
329
329
|
}
|
|
330
330
|
buildLogEntry(batch, mocks) {
|
|
331
331
|
const mockMap = new Map(mocks.map((mock) => [mock.requestId, mock]));
|
package/package.json
CHANGED
package/dist/package.json
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "mock-mcp",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"description": "An MCP server enabling LLMs to write integration tests through live test environment interaction",
|
|
5
|
-
"main": "./dist/connect.cjs",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"bin": {
|
|
8
|
-
"mock-mcp": "dist/index.js"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"dist"
|
|
12
|
-
],
|
|
13
|
-
"publishConfig": {
|
|
14
|
-
"access": "public"
|
|
15
|
-
},
|
|
16
|
-
"engines": {
|
|
17
|
-
"node": ">=18.0.0"
|
|
18
|
-
},
|
|
19
|
-
"scripts": {
|
|
20
|
-
"build": "tsc && tsup src/client/connect.ts --dts",
|
|
21
|
-
"start": "node dist/index.js",
|
|
22
|
-
"dev": "tsx src/index.ts",
|
|
23
|
-
"lint": "eslint . --ext .ts",
|
|
24
|
-
"test": "vitest run",
|
|
25
|
-
"test:watch": "vitest --watch",
|
|
26
|
-
"prepublishOnly": "npm run build",
|
|
27
|
-
"link": "npm link",
|
|
28
|
-
"unlink": "npm unlink",
|
|
29
|
-
"commit": "yarn git-cz"
|
|
30
|
-
},
|
|
31
|
-
"keywords": [
|
|
32
|
-
"mcp",
|
|
33
|
-
"model-context-protocol",
|
|
34
|
-
"mock",
|
|
35
|
-
"mock-mcp"
|
|
36
|
-
],
|
|
37
|
-
"repository": {
|
|
38
|
-
"type": "git",
|
|
39
|
-
"url": "git+https://github.com/mcpland/mock-mcp.git"
|
|
40
|
-
},
|
|
41
|
-
"author": "unadlib",
|
|
42
|
-
"license": "MIT",
|
|
43
|
-
"dependencies": {
|
|
44
|
-
"@cfworker/json-schema": "^4.1.1",
|
|
45
|
-
"@modelcontextprotocol/sdk": "^1.20.2",
|
|
46
|
-
"ts-morph": "^27.0.2",
|
|
47
|
-
"ws": "^8.18.3",
|
|
48
|
-
"zod": "^4.1.12"
|
|
49
|
-
},
|
|
50
|
-
"devDependencies": {
|
|
51
|
-
"@types/node": "^24.0.15",
|
|
52
|
-
"@types/ws": "^8.18.1",
|
|
53
|
-
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
|
54
|
-
"@typescript-eslint/parser": "^8.38.0",
|
|
55
|
-
"@vitest/coverage-v8": "^3.2.4",
|
|
56
|
-
"commitizen": "^4.3.1",
|
|
57
|
-
"eslint": "^9.31.0",
|
|
58
|
-
"node-fetch": "^3.3.2",
|
|
59
|
-
"tsup": "^8.5.0",
|
|
60
|
-
"tsx": "^4.20.3",
|
|
61
|
-
"typescript": "^5.8.3",
|
|
62
|
-
"vite": "^7.0.5",
|
|
63
|
-
"vitest": "^3.2.4"
|
|
64
|
-
},
|
|
65
|
-
"resolutions": {
|
|
66
|
-
"rollup": "4.52.5"
|
|
67
|
-
},
|
|
68
|
-
"config": {
|
|
69
|
-
"commitizen": {
|
|
70
|
-
"path": "cz-conventional-changelog"
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|