mock-mcp 0.3.1 → 0.5.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 +212 -124
- package/dist/adapter/index.cjs +875 -0
- package/dist/adapter/index.d.cts +142 -0
- package/dist/adapter/index.d.ts +142 -0
- package/dist/adapter/index.js +835 -0
- package/dist/client/connect.cjs +991 -0
- package/dist/client/connect.d.cts +218 -0
- package/dist/client/connect.d.ts +211 -7
- package/dist/client/connect.js +941 -20
- package/dist/client/index.cjs +992 -0
- package/dist/client/index.d.cts +3 -0
- package/dist/client/index.d.ts +3 -2
- package/dist/client/index.js +951 -2
- package/dist/daemon/index.cjs +717 -0
- package/dist/daemon/index.d.cts +62 -0
- package/dist/daemon/index.d.ts +62 -0
- package/dist/daemon/index.js +678 -0
- package/dist/index.cjs +2708 -0
- package/dist/index.d.cts +602 -0
- package/dist/index.d.ts +602 -11
- package/dist/index.js +2651 -53
- package/dist/shared/index.cjs +506 -0
- package/dist/shared/index.d.cts +241 -0
- package/dist/shared/index.d.ts +241 -0
- package/dist/shared/index.js +423 -0
- package/dist/types-bEGXLBF0.d.cts +190 -0
- package/dist/types-bEGXLBF0.d.ts +190 -0
- package/package.json +45 -4
- package/dist/client/batch-mock-collector.d.ts +0 -111
- package/dist/client/batch-mock-collector.js +0 -308
- package/dist/client/util.d.ts +0 -1
- package/dist/client/util.js +0 -3
- package/dist/connect.cjs +0 -400
- package/dist/connect.d.cts +0 -82
- package/dist/server/index.d.ts +0 -1
- package/dist/server/index.js +0 -1
- package/dist/server/test-mock-mcp-server.d.ts +0 -73
- package/dist/server/test-mock-mcp-server.js +0 -419
- package/dist/types.d.ts +0 -45
- package/dist/types.js +0 -2
package/dist/connect.cjs
DELETED
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// src/client/connect.ts
|
|
31
|
-
var connect_exports = {};
|
|
32
|
-
__export(connect_exports, {
|
|
33
|
-
connect: () => connect
|
|
34
|
-
});
|
|
35
|
-
module.exports = __toCommonJS(connect_exports);
|
|
36
|
-
|
|
37
|
-
// src/client/batch-mock-collector.ts
|
|
38
|
-
var import_ws = __toESM(require("ws"), 1);
|
|
39
|
-
|
|
40
|
-
// src/types.ts
|
|
41
|
-
var BATCH_MOCK_REQUEST = "BATCH_MOCK_REQUEST";
|
|
42
|
-
var BATCH_MOCK_RESPONSE = "BATCH_MOCK_RESPONSE";
|
|
43
|
-
|
|
44
|
-
// src/client/util.ts
|
|
45
|
-
var isEnabled = () => {
|
|
46
|
-
return process.env.MOCK_MCP !== void 0 && process.env.MOCK_MCP !== "0";
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// src/client/batch-mock-collector.ts
|
|
50
|
-
var DEFAULT_TIMEOUT = 6e4;
|
|
51
|
-
var DEFAULT_BATCH_DEBOUNCE_MS = 0;
|
|
52
|
-
var DEFAULT_MAX_BATCH_SIZE = 50;
|
|
53
|
-
var DEFAULT_PORT = 3002;
|
|
54
|
-
var DEFAULT_HEARTBEAT_INTERVAL_MS = 15e3;
|
|
55
|
-
var BatchMockCollector = class {
|
|
56
|
-
ws;
|
|
57
|
-
pendingRequests = /* @__PURE__ */ new Map();
|
|
58
|
-
queuedRequestIds = /* @__PURE__ */ new Set();
|
|
59
|
-
timeout;
|
|
60
|
-
batchDebounceMs;
|
|
61
|
-
maxBatchSize;
|
|
62
|
-
logger;
|
|
63
|
-
heartbeatIntervalMs;
|
|
64
|
-
enableReconnect;
|
|
65
|
-
port;
|
|
66
|
-
batchTimer = null;
|
|
67
|
-
heartbeatTimer = null;
|
|
68
|
-
reconnectTimer = null;
|
|
69
|
-
requestIdCounter = 0;
|
|
70
|
-
closed = false;
|
|
71
|
-
readyResolve;
|
|
72
|
-
readyReject;
|
|
73
|
-
readyPromise = Promise.resolve();
|
|
74
|
-
constructor(options = {}) {
|
|
75
|
-
this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
|
|
76
|
-
this.batchDebounceMs = options.batchDebounceMs ?? DEFAULT_BATCH_DEBOUNCE_MS;
|
|
77
|
-
this.maxBatchSize = options.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE;
|
|
78
|
-
this.logger = options.logger ?? console;
|
|
79
|
-
this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;
|
|
80
|
-
this.enableReconnect = options.enableReconnect ?? true;
|
|
81
|
-
this.port = options.port ?? DEFAULT_PORT;
|
|
82
|
-
this.resetReadyPromise();
|
|
83
|
-
this.ws = this.createWebSocket();
|
|
84
|
-
this.setupWebSocket();
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Ensures the underlying WebSocket connection is ready for use.
|
|
88
|
-
*/
|
|
89
|
-
async waitUntilReady() {
|
|
90
|
-
return this.readyPromise;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Request mock data for a specific endpoint/method pair.
|
|
94
|
-
*/
|
|
95
|
-
async requestMock(endpoint, method, options = {}) {
|
|
96
|
-
if (this.closed) {
|
|
97
|
-
throw new Error("BatchMockCollector has been closed");
|
|
98
|
-
}
|
|
99
|
-
await this.waitUntilReady();
|
|
100
|
-
const requestId = `req-${++this.requestIdCounter}`;
|
|
101
|
-
const request = {
|
|
102
|
-
requestId,
|
|
103
|
-
endpoint,
|
|
104
|
-
method,
|
|
105
|
-
body: options.body,
|
|
106
|
-
headers: options.headers,
|
|
107
|
-
metadata: options.metadata
|
|
108
|
-
};
|
|
109
|
-
let settleCompletion;
|
|
110
|
-
const completion = new Promise((resolve) => {
|
|
111
|
-
settleCompletion = resolve;
|
|
112
|
-
});
|
|
113
|
-
return new Promise((resolve, reject) => {
|
|
114
|
-
const timeoutId = setTimeout(() => {
|
|
115
|
-
this.rejectRequest(
|
|
116
|
-
requestId,
|
|
117
|
-
new Error(
|
|
118
|
-
`Mock request timed out after ${this.timeout}ms: ${method} ${endpoint}`
|
|
119
|
-
)
|
|
120
|
-
);
|
|
121
|
-
}, this.timeout);
|
|
122
|
-
this.pendingRequests.set(requestId, {
|
|
123
|
-
request,
|
|
124
|
-
resolve: (mock) => {
|
|
125
|
-
settleCompletion({ status: "fulfilled", value: void 0 });
|
|
126
|
-
resolve(this.buildResolvedMock(mock));
|
|
127
|
-
},
|
|
128
|
-
reject: (error) => {
|
|
129
|
-
settleCompletion({ status: "rejected", reason: error });
|
|
130
|
-
reject(error);
|
|
131
|
-
},
|
|
132
|
-
timeoutId,
|
|
133
|
-
completion
|
|
134
|
-
});
|
|
135
|
-
this.enqueueRequest(requestId);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Wait for all requests that are currently pending to settle. Requests
|
|
140
|
-
* created after this method is called are not included.
|
|
141
|
-
*/
|
|
142
|
-
async waitForPendingRequests() {
|
|
143
|
-
if (!isEnabled()) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
const pendingCompletions = Array.from(this.pendingRequests.values()).map(
|
|
147
|
-
(pending) => pending.completion
|
|
148
|
-
);
|
|
149
|
-
const results = await Promise.all(pendingCompletions);
|
|
150
|
-
const rejected = results.find(
|
|
151
|
-
(result) => result.status === "rejected"
|
|
152
|
-
);
|
|
153
|
-
if (rejected) {
|
|
154
|
-
throw rejected.reason;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Close the underlying connection and fail all pending requests.
|
|
159
|
-
*/
|
|
160
|
-
async close(code) {
|
|
161
|
-
if (this.closed) {
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
this.closed = true;
|
|
165
|
-
if (this.batchTimer) {
|
|
166
|
-
clearTimeout(this.batchTimer);
|
|
167
|
-
this.batchTimer = null;
|
|
168
|
-
}
|
|
169
|
-
if (this.heartbeatTimer) {
|
|
170
|
-
clearInterval(this.heartbeatTimer);
|
|
171
|
-
this.heartbeatTimer = null;
|
|
172
|
-
}
|
|
173
|
-
if (this.reconnectTimer) {
|
|
174
|
-
clearTimeout(this.reconnectTimer);
|
|
175
|
-
this.reconnectTimer = null;
|
|
176
|
-
}
|
|
177
|
-
this.queuedRequestIds.clear();
|
|
178
|
-
const closePromise = new Promise((resolve) => {
|
|
179
|
-
this.ws.once("close", () => resolve());
|
|
180
|
-
});
|
|
181
|
-
this.ws.close(code);
|
|
182
|
-
this.failAllPending(new Error("BatchMockCollector has been closed"));
|
|
183
|
-
await closePromise;
|
|
184
|
-
}
|
|
185
|
-
setupWebSocket() {
|
|
186
|
-
this.ws.on("open", () => {
|
|
187
|
-
this.logger.log("\u{1F50C} Connected to mock MCP WebSocket endpoint");
|
|
188
|
-
this.readyResolve?.();
|
|
189
|
-
this.startHeartbeat();
|
|
190
|
-
});
|
|
191
|
-
this.ws.on("message", (data) => this.handleMessage(data));
|
|
192
|
-
this.ws.on("error", (error) => {
|
|
193
|
-
this.logger.error("\u274C WebSocket error:", error);
|
|
194
|
-
this.readyReject?.(
|
|
195
|
-
error instanceof Error ? error : new Error(String(error))
|
|
196
|
-
);
|
|
197
|
-
this.failAllPending(
|
|
198
|
-
error instanceof Error ? error : new Error(String(error))
|
|
199
|
-
);
|
|
200
|
-
});
|
|
201
|
-
this.ws.on("close", () => {
|
|
202
|
-
this.logger.warn("\u{1F50C} WebSocket connection closed");
|
|
203
|
-
this.stopHeartbeat();
|
|
204
|
-
this.failAllPending(new Error("WebSocket connection closed"));
|
|
205
|
-
if (!this.closed && this.enableReconnect) {
|
|
206
|
-
this.scheduleReconnect();
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
createWebSocket() {
|
|
211
|
-
const wsUrl = `ws://localhost:${this.port}`;
|
|
212
|
-
return new import_ws.default(wsUrl);
|
|
213
|
-
}
|
|
214
|
-
resetReadyPromise() {
|
|
215
|
-
this.readyPromise = new Promise((resolve, reject) => {
|
|
216
|
-
this.readyResolve = resolve;
|
|
217
|
-
this.readyReject = reject;
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
startHeartbeat() {
|
|
221
|
-
if (this.heartbeatIntervalMs <= 0 || this.heartbeatTimer) {
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
let lastPong = Date.now();
|
|
225
|
-
this.ws.on("pong", () => {
|
|
226
|
-
lastPong = Date.now();
|
|
227
|
-
});
|
|
228
|
-
this.heartbeatTimer = setInterval(() => {
|
|
229
|
-
if (this.ws.readyState !== import_ws.default.OPEN) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
const now = Date.now();
|
|
233
|
-
if (now - lastPong > this.heartbeatIntervalMs * 2) {
|
|
234
|
-
this.logger.warn(
|
|
235
|
-
"Heartbeat missed; closing socket to trigger reconnect..."
|
|
236
|
-
);
|
|
237
|
-
this.ws.close();
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
this.ws.ping();
|
|
241
|
-
}, this.heartbeatIntervalMs);
|
|
242
|
-
this.heartbeatTimer.unref?.();
|
|
243
|
-
}
|
|
244
|
-
stopHeartbeat() {
|
|
245
|
-
if (this.heartbeatTimer) {
|
|
246
|
-
clearInterval(this.heartbeatTimer);
|
|
247
|
-
this.heartbeatTimer = null;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
scheduleReconnect() {
|
|
251
|
-
if (this.reconnectTimer || this.closed) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
this.reconnectTimer = setTimeout(() => {
|
|
255
|
-
this.reconnectTimer = null;
|
|
256
|
-
this.logger.warn("\u{1F504} Reconnecting to mock MCP WebSocket endpoint...");
|
|
257
|
-
this.stopHeartbeat();
|
|
258
|
-
this.resetReadyPromise();
|
|
259
|
-
this.ws = this.createWebSocket();
|
|
260
|
-
this.setupWebSocket();
|
|
261
|
-
}, 1e3);
|
|
262
|
-
this.reconnectTimer.unref?.();
|
|
263
|
-
}
|
|
264
|
-
handleMessage(data) {
|
|
265
|
-
let parsed;
|
|
266
|
-
try {
|
|
267
|
-
parsed = JSON.parse(data.toString());
|
|
268
|
-
} catch (error) {
|
|
269
|
-
this.logger.error("Failed to parse server message:", error);
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
if (parsed.type !== BATCH_MOCK_RESPONSE) {
|
|
273
|
-
this.logger.warn("Received unsupported message type", parsed.type);
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
this.logger.debug?.(
|
|
277
|
-
`\u{1F4E6} Received mock data for ${parsed.mocks.length} requests (batch ${parsed.batchId})`
|
|
278
|
-
);
|
|
279
|
-
for (const mock of parsed.mocks) {
|
|
280
|
-
this.resolveRequest(mock);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
resolveRequest(mock) {
|
|
284
|
-
const pending = this.pendingRequests.get(mock.requestId);
|
|
285
|
-
if (!pending) {
|
|
286
|
-
this.logger.warn(`Received mock for unknown request: ${mock.requestId}`);
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
clearTimeout(pending.timeoutId);
|
|
290
|
-
this.pendingRequests.delete(mock.requestId);
|
|
291
|
-
const resolve = () => pending.resolve(mock);
|
|
292
|
-
if (mock.delayMs && mock.delayMs > 0) {
|
|
293
|
-
setTimeout(resolve, mock.delayMs);
|
|
294
|
-
} else {
|
|
295
|
-
resolve();
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
enqueueRequest(requestId) {
|
|
299
|
-
this.queuedRequestIds.add(requestId);
|
|
300
|
-
if (this.batchTimer) {
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
this.batchTimer = setTimeout(() => {
|
|
304
|
-
this.batchTimer = null;
|
|
305
|
-
this.flushQueue();
|
|
306
|
-
}, this.batchDebounceMs);
|
|
307
|
-
}
|
|
308
|
-
flushQueue() {
|
|
309
|
-
const queuedIds = Array.from(this.queuedRequestIds);
|
|
310
|
-
this.queuedRequestIds.clear();
|
|
311
|
-
if (queuedIds.length === 0) {
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
for (let i = 0; i < queuedIds.length; i += this.maxBatchSize) {
|
|
315
|
-
const chunkIds = queuedIds.slice(i, i + this.maxBatchSize);
|
|
316
|
-
const requests = [];
|
|
317
|
-
for (const id of chunkIds) {
|
|
318
|
-
const pending = this.pendingRequests.get(id);
|
|
319
|
-
if (pending) {
|
|
320
|
-
requests.push(pending.request);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
if (requests.length > 0) {
|
|
324
|
-
this.sendBatch(requests);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
sendBatch(requests) {
|
|
329
|
-
if (this.ws.readyState !== import_ws.default.OPEN) {
|
|
330
|
-
const error = new Error("WebSocket is not open");
|
|
331
|
-
requests.forEach(
|
|
332
|
-
(request) => this.rejectRequest(request.requestId, error)
|
|
333
|
-
);
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
const payload = {
|
|
337
|
-
type: BATCH_MOCK_REQUEST,
|
|
338
|
-
requests
|
|
339
|
-
};
|
|
340
|
-
this.logger.debug?.(
|
|
341
|
-
`\u{1F4E4} Sending batch with ${requests.length} request(s) to MCP server`
|
|
342
|
-
);
|
|
343
|
-
this.ws.send(JSON.stringify(payload));
|
|
344
|
-
}
|
|
345
|
-
buildResolvedMock(mock) {
|
|
346
|
-
return {
|
|
347
|
-
requestId: mock.requestId,
|
|
348
|
-
data: mock.data,
|
|
349
|
-
status: mock.status,
|
|
350
|
-
headers: mock.headers,
|
|
351
|
-
delayMs: mock.delayMs
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
rejectRequest(requestId, error) {
|
|
355
|
-
const pending = this.pendingRequests.get(requestId);
|
|
356
|
-
if (!pending) {
|
|
357
|
-
return;
|
|
358
|
-
}
|
|
359
|
-
clearTimeout(pending.timeoutId);
|
|
360
|
-
this.pendingRequests.delete(requestId);
|
|
361
|
-
pending.reject(error);
|
|
362
|
-
}
|
|
363
|
-
failAllPending(error) {
|
|
364
|
-
for (const requestId of Array.from(this.pendingRequests.keys())) {
|
|
365
|
-
this.rejectRequest(requestId, error);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
// src/client/connect.ts
|
|
371
|
-
var DisabledMockClient = class {
|
|
372
|
-
async waitUntilReady() {
|
|
373
|
-
return;
|
|
374
|
-
}
|
|
375
|
-
async requestMock() {
|
|
376
|
-
throw new Error(
|
|
377
|
-
"[mock-mcp] MOCK_MCP is not enabled. Set MOCK_MCP=1 to enable mock generation."
|
|
378
|
-
);
|
|
379
|
-
}
|
|
380
|
-
async waitForPendingRequests() {
|
|
381
|
-
return;
|
|
382
|
-
}
|
|
383
|
-
async close() {
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
};
|
|
387
|
-
var connect = async (options) => {
|
|
388
|
-
const resolvedOptions = typeof options === "number" ? { port: options } : options ?? {};
|
|
389
|
-
if (!isEnabled()) {
|
|
390
|
-
console.log("[mock-mcp] Skipping (set MOCK_MCP=1 to enable)");
|
|
391
|
-
return new DisabledMockClient();
|
|
392
|
-
}
|
|
393
|
-
const collector = new BatchMockCollector(resolvedOptions);
|
|
394
|
-
await collector.waitUntilReady();
|
|
395
|
-
return collector;
|
|
396
|
-
};
|
|
397
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
398
|
-
0 && (module.exports = {
|
|
399
|
-
connect
|
|
400
|
-
});
|
package/dist/connect.d.cts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shape of the mock data that needs to be returned for a request.
|
|
3
|
-
*/
|
|
4
|
-
interface MockResponseDescriptor {
|
|
5
|
-
requestId: string;
|
|
6
|
-
data: unknown;
|
|
7
|
-
status?: number;
|
|
8
|
-
headers?: Record<string, string>;
|
|
9
|
-
delayMs?: number;
|
|
10
|
-
}
|
|
11
|
-
interface ResolvedMock<T = unknown> extends Omit<MockResponseDescriptor, "data"> {
|
|
12
|
-
data: T;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
type Logger = Pick<Console, "log" | "warn" | "error"> & {
|
|
16
|
-
debug?: (...args: unknown[]) => void;
|
|
17
|
-
};
|
|
18
|
-
interface BatchMockCollectorOptions {
|
|
19
|
-
/**
|
|
20
|
-
* TCP port exposed by {@link TestMockMCPServer}.
|
|
21
|
-
*
|
|
22
|
-
* @default 3002
|
|
23
|
-
*/
|
|
24
|
-
port?: number;
|
|
25
|
-
/**
|
|
26
|
-
* Timeout for individual mock requests in milliseconds.
|
|
27
|
-
*
|
|
28
|
-
* @default 60000
|
|
29
|
-
*/
|
|
30
|
-
timeout?: number;
|
|
31
|
-
/**
|
|
32
|
-
* Delay (in milliseconds) that determines how long the collector waits before
|
|
33
|
-
* flushing the current batch. Setting this to 0 mirrors the "flush on the next
|
|
34
|
-
* macrotask" approach described in the technical design document.
|
|
35
|
-
*
|
|
36
|
-
* @default 0
|
|
37
|
-
*/
|
|
38
|
-
batchDebounceMs?: number;
|
|
39
|
-
/**
|
|
40
|
-
* Maximum number of requests that may be included in a single batch payload.
|
|
41
|
-
* Requests that exceed this limit will be split into multiple batches.
|
|
42
|
-
*
|
|
43
|
-
* @default 50
|
|
44
|
-
*/
|
|
45
|
-
maxBatchSize?: number;
|
|
46
|
-
/**
|
|
47
|
-
* Optional custom logger. Defaults to `console`.
|
|
48
|
-
*/
|
|
49
|
-
logger?: Logger;
|
|
50
|
-
/**
|
|
51
|
-
* Interval for WebSocket heartbeats in milliseconds. Set to 0 to disable.
|
|
52
|
-
*
|
|
53
|
-
* @default 15000
|
|
54
|
-
*/
|
|
55
|
-
heartbeatIntervalMs?: number;
|
|
56
|
-
/**
|
|
57
|
-
* Automatically attempt to reconnect when the WebSocket closes unexpectedly.
|
|
58
|
-
*
|
|
59
|
-
* @default true
|
|
60
|
-
*/
|
|
61
|
-
enableReconnect?: boolean;
|
|
62
|
-
}
|
|
63
|
-
interface RequestMockOptions {
|
|
64
|
-
body?: unknown;
|
|
65
|
-
headers?: Record<string, string>;
|
|
66
|
-
metadata?: Record<string, unknown>;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
type ConnectOptions = number | BatchMockCollectorOptions | undefined;
|
|
70
|
-
interface MockClient {
|
|
71
|
-
waitUntilReady(): Promise<void>;
|
|
72
|
-
requestMock<T = unknown>(endpoint: string, method: string, options?: RequestMockOptions): Promise<ResolvedMock<T>>;
|
|
73
|
-
waitForPendingRequests(): Promise<void>;
|
|
74
|
-
close(code?: number): Promise<void>;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Convenience helper that creates a {@link BatchMockCollector} and waits for the
|
|
78
|
-
* underlying WebSocket connection to become ready before resolving.
|
|
79
|
-
*/
|
|
80
|
-
declare const connect: (options?: ConnectOptions) => Promise<MockClient>;
|
|
81
|
-
|
|
82
|
-
export { type ConnectOptions, type MockClient, connect };
|
package/dist/server/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { TestMockMCPServer, type TestMockMCPServerOptions, } from "./test-mock-mcp-server.js";
|
package/dist/server/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { TestMockMCPServer, } from "./test-mock-mcp-server.js";
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
2
|
-
import { type CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
-
import { type PendingBatchSummary, type ProvideBatchMockDataArgs } from "../types.js";
|
|
4
|
-
type Logger = Pick<Console, "log" | "warn" | "error"> & {
|
|
5
|
-
debug?: (...args: unknown[]) => void;
|
|
6
|
-
};
|
|
7
|
-
export interface TestMockMCPServerOptions {
|
|
8
|
-
port?: number;
|
|
9
|
-
logger?: Logger;
|
|
10
|
-
batchTtlMs?: number;
|
|
11
|
-
sweepIntervalMs?: number;
|
|
12
|
-
enableMcpTransport?: boolean;
|
|
13
|
-
transportFactory?: () => Transport;
|
|
14
|
-
serverName?: string;
|
|
15
|
-
serverVersion?: string;
|
|
16
|
-
mockLogOptions?: MockLogOptions;
|
|
17
|
-
}
|
|
18
|
-
export interface MockLogOptions {
|
|
19
|
-
enabled?: boolean;
|
|
20
|
-
directory?: string;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Bridges the integration-test process and the MCP client, making it possible
|
|
24
|
-
* to generate realistic mock data on demand.
|
|
25
|
-
*/
|
|
26
|
-
export declare class TestMockMCPServer {
|
|
27
|
-
private readonly logger;
|
|
28
|
-
private readonly options;
|
|
29
|
-
private wss?;
|
|
30
|
-
private cleanupTimer?;
|
|
31
|
-
private mcpServer?;
|
|
32
|
-
private transport?;
|
|
33
|
-
private started;
|
|
34
|
-
private actualPort?;
|
|
35
|
-
private readonly pendingBatches;
|
|
36
|
-
private readonly clients;
|
|
37
|
-
private batchCounter;
|
|
38
|
-
constructor(options?: TestMockMCPServerOptions);
|
|
39
|
-
/**
|
|
40
|
-
* Start both the WebSocket server (for the test runner) and the MCP server
|
|
41
|
-
* (for the AI client).
|
|
42
|
-
*/
|
|
43
|
-
start(): Promise<void>;
|
|
44
|
-
/**
|
|
45
|
-
* Shut down all transports and clear pending batches.
|
|
46
|
-
*/
|
|
47
|
-
stop(): Promise<void>;
|
|
48
|
-
/**
|
|
49
|
-
* Expose the TCP port that the WebSocket server is listening on. Useful when
|
|
50
|
-
* `port=0` is supplied for ephemeral environments or tests.
|
|
51
|
-
*/
|
|
52
|
-
get port(): number | undefined;
|
|
53
|
-
/**
|
|
54
|
-
* Return summaries of all batches that are awaiting AI-provided mock data.
|
|
55
|
-
*/
|
|
56
|
-
getPendingBatches(): PendingBatchSummary[];
|
|
57
|
-
/**
|
|
58
|
-
* Send AI-generated mock data back to the corresponding test process.
|
|
59
|
-
*/
|
|
60
|
-
provideMockData(args: ProvideBatchMockDataArgs): Promise<CallToolResult>;
|
|
61
|
-
private startWebSocketServer;
|
|
62
|
-
private startMcpServer;
|
|
63
|
-
private handleConnection;
|
|
64
|
-
private handleClientMessage;
|
|
65
|
-
private handleBatchRequest;
|
|
66
|
-
private dropBatchesForClient;
|
|
67
|
-
private sweepExpiredBatches;
|
|
68
|
-
private persistMockBatch;
|
|
69
|
-
private buildLogEntry;
|
|
70
|
-
private extractBatchContext;
|
|
71
|
-
private buildToolResponse;
|
|
72
|
-
}
|
|
73
|
-
export {};
|