mock-mcp 0.3.0 → 0.5.0

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.
Files changed (44) hide show
  1. package/README.md +217 -128
  2. package/dist/adapter/index.cjs +712 -0
  3. package/dist/adapter/index.d.cts +55 -0
  4. package/dist/adapter/index.d.ts +55 -0
  5. package/dist/adapter/index.js +672 -0
  6. package/dist/client/connect.cjs +913 -0
  7. package/dist/client/connect.d.cts +211 -0
  8. package/dist/client/connect.d.ts +209 -6
  9. package/dist/client/connect.js +867 -10
  10. package/dist/client/index.cjs +914 -0
  11. package/dist/client/index.d.cts +4 -0
  12. package/dist/client/index.d.ts +4 -2
  13. package/dist/client/index.js +873 -2
  14. package/dist/daemon/index.cjs +667 -0
  15. package/dist/daemon/index.d.cts +62 -0
  16. package/dist/daemon/index.d.ts +62 -0
  17. package/dist/daemon/index.js +628 -0
  18. package/dist/discovery-Dc2LdF8q.d.cts +105 -0
  19. package/dist/discovery-Dc2LdF8q.d.ts +105 -0
  20. package/dist/index.cjs +2238 -0
  21. package/dist/index.d.cts +472 -0
  22. package/dist/index.d.ts +472 -10
  23. package/dist/index.js +2185 -53
  24. package/dist/protocol-CiwaQFOt.d.ts +239 -0
  25. package/dist/protocol-xZu-wb0n.d.cts +239 -0
  26. package/dist/shared/index.cjs +386 -0
  27. package/dist/shared/index.d.cts +4 -0
  28. package/dist/shared/index.d.ts +4 -0
  29. package/dist/shared/index.js +310 -0
  30. package/dist/types-BKREdsyr.d.cts +32 -0
  31. package/dist/types-BKREdsyr.d.ts +32 -0
  32. package/package.json +44 -4
  33. package/dist/client/batch-mock-collector.d.ts +0 -87
  34. package/dist/client/batch-mock-collector.js +0 -223
  35. package/dist/client/util.d.ts +0 -1
  36. package/dist/client/util.js +0 -3
  37. package/dist/connect.cjs +0 -299
  38. package/dist/connect.d.cts +0 -95
  39. package/dist/server/index.d.ts +0 -1
  40. package/dist/server/index.js +0 -1
  41. package/dist/server/test-mock-mcp-server.d.ts +0 -73
  42. package/dist/server/test-mock-mcp-server.js +0 -392
  43. package/dist/types.d.ts +0 -42
  44. package/dist/types.js +0 -2
package/dist/index.d.ts CHANGED
@@ -1,10 +1,472 @@
1
- #!/usr/bin/env node
2
- import { TestMockMCPServer, type TestMockMCPServerOptions } from "./server/test-mock-mcp-server.js";
3
- import { BatchMockCollector, type BatchMockCollectorOptions, type RequestMockOptions } from "./client/batch-mock-collector.js";
4
- import { connect, type ConnectOptions } from "./client/connect.js";
5
- export { TestMockMCPServer };
6
- export type { TestMockMCPServerOptions };
7
- export { BatchMockCollector };
8
- export type { BatchMockCollectorOptions, RequestMockOptions };
9
- export { connect };
10
- export type { ConnectOptions };
1
+ /**
2
+ * Mock Bridge Daemon - The core singleton process for mock-mcp.
3
+ *
4
+ * Responsibilities:
5
+ * - Listen on IPC (Unix Domain Socket / Windows Named Pipe)
6
+ * - Accept test process connections via WebSocket /test
7
+ * - Accept adapter connections via HTTP /control (JSON-RPC)
8
+ * - Manage runs, batches, claims with lease-based concurrency control
9
+ * - Clean up expired claims and disconnected runs
10
+ */
11
+ type Logger$2 = Pick<Console, "log" | "warn" | "error"> & {
12
+ debug?: (...args: unknown[]) => void;
13
+ };
14
+ interface MockMcpDaemonOptions {
15
+ projectRoot: string;
16
+ token: string;
17
+ version: string;
18
+ cacheDir?: string;
19
+ logger?: Logger$2;
20
+ /** Default lease time for batch claims (ms). Default: 30000 */
21
+ defaultLeaseMs?: number;
22
+ /** Interval for sweeping expired claims (ms). Default: 5000 */
23
+ sweepIntervalMs?: number;
24
+ /** Auto-shutdown after this many ms of inactivity (no runs/adapters). Default: 600000 (10min) */
25
+ idleShutdownMs?: number;
26
+ }
27
+ declare class MockMcpDaemon {
28
+ private readonly logger;
29
+ private readonly opts;
30
+ private server?;
31
+ private wss?;
32
+ private sweepTimer?;
33
+ private idleTimer?;
34
+ private startedAt?;
35
+ private readonly runs;
36
+ private readonly batches;
37
+ private readonly pendingQueue;
38
+ private batchSeq;
39
+ constructor(options: MockMcpDaemonOptions);
40
+ start(): Promise<void>;
41
+ stop(): Promise<void>;
42
+ private handleHttp;
43
+ private readBody;
44
+ private handleWsConnection;
45
+ private handleBatchRequest;
46
+ private cleanupRun;
47
+ private handleRpc;
48
+ private getErrorCode;
49
+ private rpcSuccess;
50
+ private rpcError;
51
+ private getStatus;
52
+ private listRuns;
53
+ private claimNextBatch;
54
+ private provideBatch;
55
+ private validateMocks;
56
+ private releaseBatch;
57
+ private getBatch;
58
+ private sweepExpiredClaims;
59
+ private resetIdleTimer;
60
+ }
61
+
62
+ /**
63
+ * MCP Adapter - The MCP stdio server that bridges AI clients to the Daemon.
64
+ *
65
+ * Each MCP client (Cursor, Claude Desktop, etc.) spawns one Adapter process.
66
+ * The Adapter:
67
+ * - Exposes MCP tools (claim_next_batch, provide_batch_mock_data, get_status)
68
+ * - Connects to the Daemon via IPC
69
+ * - Does NOT bind any ports (avoids conflicts)
70
+ */
71
+ type Logger$1 = Pick<Console, "log" | "warn" | "error"> & {
72
+ debug?: (...args: unknown[]) => void;
73
+ };
74
+ interface AdapterOptions {
75
+ logger?: Logger$1;
76
+ version?: string;
77
+ }
78
+ declare function runAdapter(opts?: AdapterOptions): Promise<void>;
79
+
80
+ /**
81
+ * Core types for mock-mcp.
82
+ */
83
+ /**
84
+ * Shape of a mock request emitted by the test process.
85
+ */
86
+ interface MockRequestDescriptor {
87
+ requestId: string;
88
+ endpoint: string;
89
+ method: string;
90
+ body?: unknown;
91
+ headers?: Record<string, string>;
92
+ metadata?: Record<string, unknown>;
93
+ }
94
+ /**
95
+ * Shape of the mock data that needs to be returned for a request.
96
+ */
97
+ interface MockResponseDescriptor {
98
+ requestId: string;
99
+ data: unknown;
100
+ status?: number;
101
+ headers?: Record<string, string>;
102
+ delayMs?: number;
103
+ }
104
+ /**
105
+ * Resolved mock with typed data.
106
+ */
107
+ interface ResolvedMock<T = unknown> extends Omit<MockResponseDescriptor, "data"> {
108
+ data: T;
109
+ }
110
+
111
+ /**
112
+ * Protocol definitions for mock-mcp Daemon communication.
113
+ *
114
+ * Defines message types for:
115
+ * - Test channel (WebSocket /test): Test process ↔ Daemon
116
+ * - Control channel (HTTP /control): Adapter ↔ Daemon (JSON-RPC)
117
+ */
118
+
119
+ /**
120
+ * Result of claimNextBatch RPC.
121
+ */
122
+ interface ClaimNextBatchResult {
123
+ batchId: string;
124
+ runId: string;
125
+ requests: MockRequestDescriptor[];
126
+ claimToken: string;
127
+ leaseUntil: number;
128
+ }
129
+ /**
130
+ * Result of provideBatch RPC.
131
+ */
132
+ interface ProvideBatchResult {
133
+ ok: boolean;
134
+ message?: string;
135
+ }
136
+ /**
137
+ * Result of getStatus RPC.
138
+ */
139
+ interface GetStatusResult {
140
+ version: string;
141
+ projectId: string;
142
+ projectRoot: string;
143
+ pid: number;
144
+ uptime: number;
145
+ runs: number;
146
+ pending: number;
147
+ claimed: number;
148
+ totalBatches: number;
149
+ }
150
+ /**
151
+ * Result of listRuns RPC.
152
+ */
153
+ interface ListRunsResult {
154
+ runs: RunInfo[];
155
+ }
156
+ interface RunInfo {
157
+ runId: string;
158
+ pid: number;
159
+ cwd: string;
160
+ startedAt: string;
161
+ lastSeen: number;
162
+ pendingBatches: number;
163
+ testMeta?: {
164
+ testFile?: string;
165
+ testName?: string;
166
+ };
167
+ }
168
+ /**
169
+ * Result of getBatch RPC.
170
+ */
171
+ interface GetBatchResult {
172
+ batchId: string;
173
+ runId: string;
174
+ requests: MockRequestDescriptor[];
175
+ status: BatchStatus;
176
+ createdAt: number;
177
+ claim?: {
178
+ adapterId: string;
179
+ leaseUntil: number;
180
+ };
181
+ }
182
+ type BatchStatus = "pending" | "claimed" | "fulfilled" | "expired";
183
+
184
+ /**
185
+ * Daemon Client - HTTP/JSON-RPC client for communicating with the Daemon.
186
+ *
187
+ * Used by the MCP Adapter to call daemon RPC methods.
188
+ */
189
+
190
+ declare class DaemonClient {
191
+ private readonly ipcPath;
192
+ private readonly token;
193
+ private readonly adapterId;
194
+ constructor(ipcPath: string, token: string, adapterId: string);
195
+ getStatus(): Promise<GetStatusResult>;
196
+ listRuns(): Promise<ListRunsResult>;
197
+ claimNextBatch(args: {
198
+ runId?: string;
199
+ leaseMs?: number;
200
+ }): Promise<ClaimNextBatchResult | null>;
201
+ provideBatch(args: {
202
+ batchId: string;
203
+ claimToken: string;
204
+ mocks: MockResponseDescriptor[];
205
+ }): Promise<ProvideBatchResult>;
206
+ releaseBatch(args: {
207
+ batchId: string;
208
+ claimToken: string;
209
+ reason?: string;
210
+ }): Promise<{
211
+ ok: boolean;
212
+ }>;
213
+ getBatch(batchId: string): Promise<GetBatchResult>;
214
+ private rpc;
215
+ }
216
+
217
+ /**
218
+ * Discovery module for mock-mcp Daemon + Adapter architecture.
219
+ *
220
+ * Provides:
221
+ * - Project root resolution (up-search for .git / package.json)
222
+ * - Project ID computation (sha256 of realpath)
223
+ * - Registry/lock file path management
224
+ * - IPC path (Unix Domain Socket / Windows Named Pipe)
225
+ * - ensureDaemonRunning() - atomic daemon startup with lock
226
+ */
227
+
228
+ interface DaemonRegistry {
229
+ projectId: string;
230
+ projectRoot: string;
231
+ ipcPath: string;
232
+ token: string;
233
+ pid: number;
234
+ startedAt: string;
235
+ version: string;
236
+ }
237
+ interface EnsureDaemonOptions {
238
+ projectRoot?: string;
239
+ timeoutMs?: number;
240
+ /** For testing: override cache directory */
241
+ cacheDir?: string;
242
+ }
243
+ /**
244
+ * Resolve the project root by searching upward for .git or package.json.
245
+ * Falls back to the starting directory if nothing is found.
246
+ */
247
+ declare function resolveProjectRoot(startDir?: string): string;
248
+ /**
249
+ * Compute a stable project ID from the project root path.
250
+ * Uses sha256 of the realpath, truncated to 16 characters.
251
+ */
252
+ declare function computeProjectId(projectRoot: string): string;
253
+ /**
254
+ * Ensure the daemon is running for the given project.
255
+ *
256
+ * This function:
257
+ * 1. Checks if a daemon is already running (via registry + health check)
258
+ * 2. If not, acquires a lock and spawns a new daemon
259
+ * 3. Waits for the daemon to become healthy
260
+ * 4. Returns the registry information
261
+ *
262
+ * Thread-safe: multiple processes calling this concurrently will only start one daemon.
263
+ */
264
+ declare function ensureDaemonRunning(opts?: EnsureDaemonOptions): Promise<DaemonRegistry>;
265
+
266
+ /**
267
+ * BatchMockCollector - Collects HTTP requests and sends them to the daemon for mock generation.
268
+ *
269
+ * Features:
270
+ * - Connects to daemon via IPC (Unix Domain Socket / Named Pipe)
271
+ * - Automatically discovers and starts daemon if needed
272
+ * - Uses runId for multi-run isolation
273
+ * - Sends HELLO handshake on connection
274
+ * - Batches concurrent requests for efficient processing
275
+ */
276
+
277
+ type Logger = Pick<Console, "log" | "warn" | "error"> & {
278
+ debug?: (...args: unknown[]) => void;
279
+ };
280
+ interface BatchMockCollectorOptions {
281
+ /**
282
+ * Timeout for individual mock requests in milliseconds.
283
+ * @default 60000
284
+ */
285
+ timeout?: number;
286
+ /**
287
+ * Delay (in milliseconds) before flushing the current batch.
288
+ * Setting to 0 flushes on the next macrotask.
289
+ * @default 0
290
+ */
291
+ batchDebounceMs?: number;
292
+ /**
293
+ * Maximum number of requests that may be included in a single batch.
294
+ * @default 50
295
+ */
296
+ maxBatchSize?: number;
297
+ /**
298
+ * Optional custom logger. Defaults to console.
299
+ */
300
+ logger?: Logger;
301
+ /**
302
+ * Interval for WebSocket heartbeats in milliseconds. Set to 0 to disable.
303
+ * @default 15000
304
+ */
305
+ heartbeatIntervalMs?: number;
306
+ /**
307
+ * Automatically attempt to reconnect when the WebSocket closes unexpectedly.
308
+ * @default true
309
+ */
310
+ enableReconnect?: boolean;
311
+ /**
312
+ * Optional project root override. By default, auto-detected from process.cwd().
313
+ * Use this when you want to explicitly specify the project root directory.
314
+ */
315
+ projectRoot?: string;
316
+ /**
317
+ * Path to the current test file. The project root will be auto-detected
318
+ * by searching upward for .git or package.json from this file's directory.
319
+ *
320
+ * This is useful in test frameworks like Jest/Vitest:
321
+ * @example
322
+ * ```typescript
323
+ * // Jest
324
+ * const mockMcpClient = await connect({
325
+ * filePath: expect.getState().testPath,
326
+ * });
327
+ *
328
+ * // Vitest
329
+ * const mockMcpClient = await connect({
330
+ * filePath: import.meta.url,
331
+ * });
332
+ * ```
333
+ *
334
+ * Note: If both `filePath` and `projectRoot` are provided, `projectRoot` takes precedence.
335
+ */
336
+ filePath?: string;
337
+ /**
338
+ * Optional test metadata to include in the HELLO message.
339
+ */
340
+ testMeta?: {
341
+ testFile?: string;
342
+ testName?: string;
343
+ };
344
+ }
345
+ interface RequestMockOptions {
346
+ body?: unknown;
347
+ headers?: Record<string, string>;
348
+ metadata?: Record<string, unknown>;
349
+ }
350
+ /**
351
+ * Collects HTTP requests and forwards them to the daemon for AI-assisted mock generation.
352
+ *
353
+ * New architecture:
354
+ * - Connects to daemon via IPC (not TCP port)
355
+ * - Sends HELLO handshake with runId
356
+ * - Uses the new protocol (BATCH_MOCK_REQUEST → BATCH_MOCK_RESULT)
357
+ */
358
+ declare class BatchMockCollector {
359
+ private ws?;
360
+ private registry?;
361
+ private readonly runId;
362
+ private readonly pendingRequests;
363
+ private readonly queuedRequestIds;
364
+ private readonly timeout;
365
+ private readonly batchDebounceMs;
366
+ private readonly maxBatchSize;
367
+ private readonly logger;
368
+ private readonly heartbeatIntervalMs;
369
+ private readonly enableReconnect;
370
+ private readonly projectRoot?;
371
+ private readonly testMeta?;
372
+ private batchTimer;
373
+ private heartbeatTimer;
374
+ private reconnectTimer;
375
+ private requestIdCounter;
376
+ private closed;
377
+ private authed;
378
+ private readyResolve?;
379
+ private readyReject?;
380
+ private readyPromise;
381
+ constructor(options?: BatchMockCollectorOptions);
382
+ /**
383
+ * Resolve projectRoot from options.
384
+ * Priority: projectRoot > filePath > undefined (auto-detect)
385
+ */
386
+ private resolveProjectRootFromOptions;
387
+ /**
388
+ * Ensures the underlying connection is ready for use.
389
+ */
390
+ waitUntilReady(): Promise<void>;
391
+ /**
392
+ * Request mock data for a specific endpoint/method pair.
393
+ */
394
+ requestMock<T = unknown>(endpoint: string, method: string, options?: RequestMockOptions): Promise<ResolvedMock<T>>;
395
+ /**
396
+ * Wait for all currently pending requests to settle.
397
+ */
398
+ waitForPendingRequests(): Promise<void>;
399
+ /**
400
+ * Close the connection and fail all pending requests.
401
+ */
402
+ close(code?: number): Promise<void>;
403
+ private initConnection;
404
+ private createWebSocket;
405
+ private setupWebSocket;
406
+ private sendHello;
407
+ private handleMessage;
408
+ private isHelloAck;
409
+ private isBatchMockResult;
410
+ private resolveRequest;
411
+ private rejectRequest;
412
+ private failAllPending;
413
+ private enqueueRequest;
414
+ private flushQueue;
415
+ private sendBatch;
416
+ private startHeartbeat;
417
+ private stopHeartbeat;
418
+ private scheduleReconnect;
419
+ private resetReadyPromise;
420
+ private buildResolvedMock;
421
+ /**
422
+ * Get the run ID for this collector instance.
423
+ */
424
+ getRunId(): string;
425
+ /**
426
+ * Get the daemon registry information (after connection).
427
+ */
428
+ getRegistry(): DaemonRegistry | undefined;
429
+ }
430
+
431
+ /**
432
+ * Options for connecting to the mock-mcp daemon.
433
+ */
434
+ type ConnectOptions = BatchMockCollectorOptions | undefined;
435
+ /**
436
+ * Interface for the mock client returned by connect().
437
+ */
438
+ interface MockClient {
439
+ waitUntilReady(): Promise<void>;
440
+ requestMock<T = unknown>(endpoint: string, method: string, options?: RequestMockOptions): Promise<ResolvedMock<T>>;
441
+ waitForPendingRequests(): Promise<void>;
442
+ close(code?: number): Promise<void>;
443
+ /** Get the unique run ID for this connection */
444
+ getRunId(): string;
445
+ }
446
+ /**
447
+ * Connect to the mock-mcp daemon for AI-assisted mock generation.
448
+ *
449
+ * This function:
450
+ * 1. Automatically discovers or starts the daemon for your project
451
+ * 2. Establishes a WebSocket connection via IPC
452
+ * 3. Returns a MockClient for requesting mocks
453
+ *
454
+ * The daemon uses Unix Domain Sockets (macOS/Linux) or Named Pipes (Windows)
455
+ * instead of TCP ports, eliminating port conflicts when multiple MCP clients
456
+ * are running simultaneously.
457
+ *
458
+ * @example
459
+ * ```typescript
460
+ * import { connect } from 'mock-mcp';
461
+ *
462
+ * const client = await connect();
463
+ *
464
+ * const mock = await client.requestMock<User>('/api/users/1', 'GET');
465
+ * console.log(mock.data); // AI-generated mock data
466
+ *
467
+ * await client.close();
468
+ * ```
469
+ */
470
+ declare const connect: (options?: ConnectOptions) => Promise<MockClient>;
471
+
472
+ export { type AdapterOptions, BatchMockCollector, type BatchMockCollectorOptions, type ConnectOptions, DaemonClient, type DaemonRegistry, type MockClient, MockMcpDaemon, type MockMcpDaemonOptions, type MockRequestDescriptor, type MockResponseDescriptor, type RequestMockOptions, type ResolvedMock, computeProjectId, connect, ensureDaemonRunning, resolveProjectRoot, runAdapter };