@cyanheads/mcp-ts-core 0.11.0 → 0.11.2

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 (177) hide show
  1. package/AGENTS.md +9 -5
  2. package/CLAUDE.md +9 -5
  3. package/README.md +4 -2
  4. package/biome.json +2 -2
  5. package/changelog/0.11.x/0.11.0.md +0 -2
  6. package/changelog/0.11.x/0.11.1.md +74 -0
  7. package/changelog/0.11.x/0.11.2.md +98 -0
  8. package/dist/config/index.d.ts +10 -0
  9. package/dist/config/index.d.ts.map +1 -1
  10. package/dist/config/index.js +27 -13
  11. package/dist/config/index.js.map +1 -1
  12. package/dist/core/app.d.ts +37 -14
  13. package/dist/core/app.d.ts.map +1 -1
  14. package/dist/core/app.js +56 -23
  15. package/dist/core/app.js.map +1 -1
  16. package/dist/core/index.d.ts +1 -1
  17. package/dist/core/index.d.ts.map +1 -1
  18. package/dist/core/index.js.map +1 -1
  19. package/dist/core/worker.d.ts.map +1 -1
  20. package/dist/core/worker.js +35 -18
  21. package/dist/core/worker.js.map +1 -1
  22. package/dist/mcp-server/elicitation.d.ts +64 -0
  23. package/dist/mcp-server/elicitation.d.ts.map +1 -0
  24. package/dist/mcp-server/elicitation.js +81 -0
  25. package/dist/mcp-server/elicitation.js.map +1 -0
  26. package/dist/mcp-server/protocolSession.d.ts +34 -0
  27. package/dist/mcp-server/protocolSession.d.ts.map +1 -0
  28. package/dist/mcp-server/protocolSession.js +13 -0
  29. package/dist/mcp-server/protocolSession.js.map +1 -0
  30. package/dist/mcp-server/resources/resource-registration.d.ts +2 -1
  31. package/dist/mcp-server/resources/resource-registration.d.ts.map +1 -1
  32. package/dist/mcp-server/resources/resource-registration.js +6 -2
  33. package/dist/mcp-server/resources/resource-registration.js.map +1 -1
  34. package/dist/mcp-server/resources/utils/resourceHandlerFactory.d.ts +7 -12
  35. package/dist/mcp-server/resources/utils/resourceHandlerFactory.d.ts.map +1 -1
  36. package/dist/mcp-server/resources/utils/resourceHandlerFactory.js +24 -31
  37. package/dist/mcp-server/resources/utils/resourceHandlerFactory.js.map +1 -1
  38. package/dist/mcp-server/server.d.ts +3 -0
  39. package/dist/mcp-server/server.d.ts.map +1 -1
  40. package/dist/mcp-server/server.js +12 -2
  41. package/dist/mcp-server/server.js.map +1 -1
  42. package/dist/mcp-server/tools/tool-registration.d.ts +2 -1
  43. package/dist/mcp-server/tools/tool-registration.d.ts.map +1 -1
  44. package/dist/mcp-server/tools/tool-registration.js +6 -2
  45. package/dist/mcp-server/tools/tool-registration.js.map +1 -1
  46. package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts +7 -13
  47. package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts.map +1 -1
  48. package/dist/mcp-server/tools/utils/toolHandlerFactory.js +11 -44
  49. package/dist/mcp-server/tools/utils/toolHandlerFactory.js.map +1 -1
  50. package/dist/mcp-server/transports/http/httpErrorHandler.js +1 -1
  51. package/dist/mcp-server/transports/http/httpErrorHandler.js.map +1 -1
  52. package/dist/mcp-server/transports/http/httpServer.d.ts +2 -2
  53. package/dist/mcp-server/transports/http/httpServer.d.ts.map +1 -1
  54. package/dist/mcp-server/transports/http/httpServer.js.map +1 -1
  55. package/dist/mcp-server/transports/http/httpTransport.d.ts +2 -2
  56. package/dist/mcp-server/transports/http/httpTransport.d.ts.map +1 -1
  57. package/dist/mcp-server/transports/http/httpTransport.js +113 -55
  58. package/dist/mcp-server/transports/http/httpTransport.js.map +1 -1
  59. package/dist/mcp-server/transports/http/sessionStore.d.ts +17 -0
  60. package/dist/mcp-server/transports/http/sessionStore.d.ts.map +1 -1
  61. package/dist/mcp-server/transports/http/sessionStore.js +71 -0
  62. package/dist/mcp-server/transports/http/sessionStore.js.map +1 -1
  63. package/dist/mcp-server/transports/manager.d.ts +2 -6
  64. package/dist/mcp-server/transports/manager.d.ts.map +1 -1
  65. package/dist/mcp-server/transports/manager.js +4 -0
  66. package/dist/mcp-server/transports/manager.js.map +1 -1
  67. package/dist/services/canvas/core/CanvasRegistry.d.ts +2 -2
  68. package/dist/services/canvas/core/CanvasRegistry.d.ts.map +1 -1
  69. package/dist/services/canvas/core/CanvasRegistry.js +14 -3
  70. package/dist/services/canvas/core/CanvasRegistry.js.map +1 -1
  71. package/dist/services/canvas/core/DataCanvas.d.ts +1 -1
  72. package/dist/services/canvas/core/DataCanvas.d.ts.map +1 -1
  73. package/dist/services/canvas/core/DataCanvas.js +2 -2
  74. package/dist/services/canvas/core/DataCanvas.js.map +1 -1
  75. package/dist/services/canvas/providers/duckdb/DuckdbProvider.d.ts.map +1 -1
  76. package/dist/services/canvas/providers/duckdb/DuckdbProvider.js +11 -3
  77. package/dist/services/canvas/providers/duckdb/DuckdbProvider.js.map +1 -1
  78. package/dist/services/canvas/providers/duckdb/exportWriter.d.ts.map +1 -1
  79. package/dist/services/canvas/providers/duckdb/exportWriter.js +23 -2
  80. package/dist/services/canvas/providers/duckdb/exportWriter.js.map +1 -1
  81. package/dist/services/mirror/core/defineMirror.d.ts.map +1 -1
  82. package/dist/services/mirror/core/defineMirror.js +18 -7
  83. package/dist/services/mirror/core/defineMirror.js.map +1 -1
  84. package/dist/services/mirror/core/runner.d.ts.map +1 -1
  85. package/dist/services/mirror/core/runner.js +3 -0
  86. package/dist/services/mirror/core/runner.js.map +1 -1
  87. package/dist/services/mirror/index.d.ts +1 -1
  88. package/dist/services/mirror/index.d.ts.map +1 -1
  89. package/dist/services/mirror/index.js.map +1 -1
  90. package/dist/services/mirror/sqlite/sqliteMirrorStore.d.ts +20 -0
  91. package/dist/services/mirror/sqlite/sqliteMirrorStore.d.ts.map +1 -1
  92. package/dist/services/mirror/sqlite/sqliteMirrorStore.js +87 -8
  93. package/dist/services/mirror/sqlite/sqliteMirrorStore.js.map +1 -1
  94. package/dist/storage/core/StorageService.d.ts.map +1 -1
  95. package/dist/storage/core/StorageService.js +4 -1
  96. package/dist/storage/core/StorageService.js.map +1 -1
  97. package/dist/storage/core/storageValidation.d.ts +8 -0
  98. package/dist/storage/core/storageValidation.d.ts.map +1 -1
  99. package/dist/storage/core/storageValidation.js +38 -0
  100. package/dist/storage/core/storageValidation.js.map +1 -1
  101. package/dist/storage/providers/inMemory/inMemoryProvider.d.ts +1 -1
  102. package/dist/storage/providers/inMemory/inMemoryProvider.d.ts.map +1 -1
  103. package/dist/storage/providers/inMemory/inMemoryProvider.js +67 -25
  104. package/dist/storage/providers/inMemory/inMemoryProvider.js.map +1 -1
  105. package/dist/testing/fuzz.d.ts +5 -1
  106. package/dist/testing/fuzz.d.ts.map +1 -1
  107. package/dist/testing/fuzz.js +147 -37
  108. package/dist/testing/fuzz.js.map +1 -1
  109. package/dist/testing/index.d.ts +111 -1
  110. package/dist/testing/index.d.ts.map +1 -1
  111. package/dist/testing/index.js +139 -0
  112. package/dist/testing/index.js.map +1 -1
  113. package/dist/testing/vitest.d.ts +86 -12
  114. package/dist/testing/vitest.d.ts.map +1 -1
  115. package/dist/testing/vitest.js +91 -11
  116. package/dist/testing/vitest.js.map +1 -1
  117. package/dist/utils/index.d.ts +1 -1
  118. package/dist/utils/index.d.ts.map +1 -1
  119. package/dist/utils/index.js +1 -1
  120. package/dist/utils/index.js.map +1 -1
  121. package/dist/utils/network/fetchWithTimeout.d.ts +7 -6
  122. package/dist/utils/network/fetchWithTimeout.d.ts.map +1 -1
  123. package/dist/utils/network/fetchWithTimeout.js +141 -51
  124. package/dist/utils/network/fetchWithTimeout.js.map +1 -1
  125. package/dist/utils/network/httpError.d.ts.map +1 -1
  126. package/dist/utils/network/httpError.js +3 -2
  127. package/dist/utils/network/httpError.js.map +1 -1
  128. package/dist/utils/network/responseBody.d.ts +15 -0
  129. package/dist/utils/network/responseBody.d.ts.map +1 -0
  130. package/dist/utils/network/responseBody.js +63 -0
  131. package/dist/utils/network/responseBody.js.map +1 -0
  132. package/dist/utils/parsing/frontmatterParser.d.ts +3 -1
  133. package/dist/utils/parsing/frontmatterParser.d.ts.map +1 -1
  134. package/dist/utils/parsing/frontmatterParser.js +6 -7
  135. package/dist/utils/parsing/frontmatterParser.js.map +1 -1
  136. package/dist/utils/parsing/htmlExtractor.d.ts +4 -0
  137. package/dist/utils/parsing/htmlExtractor.d.ts.map +1 -1
  138. package/dist/utils/parsing/htmlExtractor.js +4 -5
  139. package/dist/utils/parsing/htmlExtractor.js.map +1 -1
  140. package/dist/utils/parsing/index.d.ts +1 -0
  141. package/dist/utils/parsing/index.d.ts.map +1 -1
  142. package/dist/utils/parsing/index.js +1 -0
  143. package/dist/utils/parsing/index.js.map +1 -1
  144. package/dist/utils/parsing/inputBudget.d.ts +28 -0
  145. package/dist/utils/parsing/inputBudget.d.ts.map +1 -0
  146. package/dist/utils/parsing/inputBudget.js +76 -0
  147. package/dist/utils/parsing/inputBudget.js.map +1 -0
  148. package/dist/utils/parsing/jsonParser.d.ts +3 -1
  149. package/dist/utils/parsing/jsonParser.d.ts.map +1 -1
  150. package/dist/utils/parsing/jsonParser.js +5 -6
  151. package/dist/utils/parsing/jsonParser.js.map +1 -1
  152. package/dist/utils/parsing/pdfParser.d.ts +11 -3
  153. package/dist/utils/parsing/pdfParser.d.ts.map +1 -1
  154. package/dist/utils/parsing/pdfParser.js +65 -50
  155. package/dist/utils/parsing/pdfParser.js.map +1 -1
  156. package/dist/utils/parsing/xmlParser.d.ts +3 -1
  157. package/dist/utils/parsing/xmlParser.d.ts.map +1 -1
  158. package/dist/utils/parsing/xmlParser.js +8 -6
  159. package/dist/utils/parsing/xmlParser.js.map +1 -1
  160. package/dist/utils/parsing/yamlParser.d.ts +3 -1
  161. package/dist/utils/parsing/yamlParser.d.ts.map +1 -1
  162. package/dist/utils/parsing/yamlParser.js +5 -6
  163. package/dist/utils/parsing/yamlParser.js.map +1 -1
  164. package/package.json +28 -26
  165. package/skills/api-testing/SKILL.md +65 -4
  166. package/skills/git-wrapup/SKILL.md +22 -1
  167. package/skills/security-pass/SKILL.md +2 -2
  168. package/templates/devcheck.config.json +1 -1
  169. package/templates/package.json +2 -0
  170. package/templates/tests/fuzz/echo-tool.fuzz.test.ts +20 -0
  171. package/templates/tests/integration/echo-contract.int.test.ts +25 -0
  172. package/templates/tests/smoke/definitions.smoke.test.ts +46 -0
  173. package/templates/vitest.config.ts +24 -27
  174. package/vitest.config.base.mjs +6 -0
  175. package/dist/logs/combined.log +0 -8
  176. package/dist/logs/error.log +0 -4
  177. package/dist/logs/interactions.log +0 -0
@@ -1,5 +1,5 @@
1
1
  import { decodeCursor, encodeCursor } from '../../../storage/core/storageValidation.js';
2
- import { JsonRpcErrorCode, McpError } from '../../../types-global/errors.js';
2
+ import { configurationError, JsonRpcErrorCode, McpError } from '../../../types-global/errors.js';
3
3
  import { logger } from '../../../utils/internal/logger.js';
4
4
  const DEFAULT_LIST_LIMIT = 1000;
5
5
  const DEFAULT_MAX_ENTRIES = 10_000;
@@ -8,19 +8,23 @@ export class InMemoryProvider {
8
8
  maxEntries;
9
9
  entryCount = 0;
10
10
  constructor(options) {
11
- this.maxEntries = options?.maxEntries ?? DEFAULT_MAX_ENTRIES;
11
+ const maxEntries = options?.maxEntries ?? DEFAULT_MAX_ENTRIES;
12
+ if (!Number.isSafeInteger(maxEntries) || maxEntries < 0) {
13
+ throw configurationError('InMemoryProvider maxEntries must be a non-negative safe integer.');
14
+ }
15
+ this.maxEntries = maxEntries;
12
16
  }
13
17
  /** Returns the total number of entries across all tenants. */
14
18
  get size() {
15
19
  return this.entryCount;
16
20
  }
17
- getTenantStore(tenantId) {
18
- let tenantStore = this.store.get(tenantId);
19
- if (!tenantStore) {
20
- tenantStore = new Map();
21
- this.store.set(tenantId, tenantStore);
22
- }
23
- return tenantStore;
21
+ getOrCreateTenantStore(tenantId) {
22
+ const existing = this.store.get(tenantId);
23
+ if (existing)
24
+ return existing;
25
+ const created = new Map();
26
+ this.store.set(tenantId, created);
27
+ return created;
24
28
  }
25
29
  /** Sweeps all tenant stores and removes expired entries, returning the count reclaimed. */
26
30
  sweepExpired() {
@@ -44,21 +48,24 @@ export class InMemoryProvider {
44
48
  * Ensures capacity for a new entry. If at limit, runs a TTL sweep first.
45
49
  * If still at capacity after sweep, throws.
46
50
  */
47
- ensureCapacity() {
48
- if (this.entryCount < this.maxEntries)
51
+ ensureCapacity(additionalEntries = 1) {
52
+ if (this.entryCount + additionalEntries <= this.maxEntries)
49
53
  return;
50
54
  const reclaimed = this.sweepExpired();
51
55
  if (reclaimed > 0) {
52
56
  logger.debug(`[InMemoryProvider] TTL sweep reclaimed ${reclaimed} expired entries`);
53
57
  }
54
- if (this.entryCount >= this.maxEntries) {
58
+ if (this.entryCount + additionalEntries > this.maxEntries) {
55
59
  throw new McpError(JsonRpcErrorCode.InternalError, `In-memory storage capacity exceeded (max: ${this.maxEntries}). ` +
56
60
  'Consider increasing maxEntries, adding TTLs to entries, or switching to a persistent provider.');
57
61
  }
58
62
  }
59
63
  get(tenantId, key, context) {
60
64
  logger.debug(`[InMemoryProvider] Getting key: ${key} for tenant: ${tenantId}`, context);
61
- const tenantStore = this.getTenantStore(tenantId);
65
+ const tenantStore = this.store.get(tenantId);
66
+ if (!tenantStore) {
67
+ return Promise.resolve(null);
68
+ }
62
69
  const entry = tenantStore.get(key);
63
70
  if (!entry) {
64
71
  return Promise.resolve(null);
@@ -66,6 +73,8 @@ export class InMemoryProvider {
66
73
  if (entry.expiresAt && Date.now() > entry.expiresAt) {
67
74
  tenantStore.delete(key);
68
75
  this.entryCount--;
76
+ if (tenantStore.size === 0)
77
+ this.store.delete(tenantId);
69
78
  logger.debug(`[InMemoryProvider] Key expired and removed: ${key} for tenant: ${tenantId}`, context);
70
79
  return Promise.resolve(null);
71
80
  }
@@ -73,11 +82,12 @@ export class InMemoryProvider {
73
82
  }
74
83
  set(tenantId, key, value, context, options) {
75
84
  logger.debug(`[InMemoryProvider] Setting key: ${key} for tenant: ${tenantId}`, context);
76
- const tenantStore = this.getTenantStore(tenantId);
77
- const isNew = !tenantStore.has(key);
85
+ let tenantStore = this.store.get(tenantId);
86
+ const isNew = !tenantStore?.has(key);
78
87
  if (isNew) {
79
88
  this.ensureCapacity();
80
89
  }
90
+ tenantStore ??= this.getOrCreateTenantStore(tenantId);
81
91
  // Fix: Check for undefined instead of truthy to handle ttl=0 correctly
82
92
  const expiresAt = options?.ttl !== undefined ? Date.now() + options.ttl * 1000 : undefined;
83
93
  tenantStore.set(key, {
@@ -91,10 +101,14 @@ export class InMemoryProvider {
91
101
  }
92
102
  delete(tenantId, key, context) {
93
103
  logger.debug(`[InMemoryProvider] Deleting key: ${key} for tenant: ${tenantId}`, context);
94
- const tenantStore = this.getTenantStore(tenantId);
104
+ const tenantStore = this.store.get(tenantId);
105
+ if (!tenantStore)
106
+ return Promise.resolve(false);
95
107
  const deleted = tenantStore.delete(key);
96
108
  if (deleted) {
97
109
  this.entryCount--;
110
+ if (tenantStore.size === 0)
111
+ this.store.delete(tenantId);
98
112
  }
99
113
  return Promise.resolve(deleted);
100
114
  }
@@ -103,7 +117,14 @@ export class InMemoryProvider {
103
117
  ...context,
104
118
  options,
105
119
  });
106
- const tenantStore = this.getTenantStore(tenantId);
120
+ // Authenticate tenant-bound cursors before an empty-namespace fast path.
121
+ // Otherwise a cursor issued to another tenant is silently accepted whenever
122
+ // the requested tenant has no entries.
123
+ const lastKey = options?.cursor ? decodeCursor(options.cursor, tenantId, context) : undefined;
124
+ const tenantStore = this.store.get(tenantId);
125
+ if (!tenantStore) {
126
+ return Promise.resolve({ keys: [], nextCursor: undefined });
127
+ }
107
128
  const now = Date.now();
108
129
  const allKeys = [];
109
130
  // Collect all matching non-expired keys
@@ -118,14 +139,14 @@ export class InMemoryProvider {
118
139
  }
119
140
  }
120
141
  }
142
+ if (tenantStore.size === 0)
143
+ this.store.delete(tenantId);
121
144
  // Sort for consistent pagination
122
145
  allKeys.sort();
123
146
  // Apply pagination with opaque cursors
124
147
  const limit = options?.limit ?? DEFAULT_LIST_LIMIT;
125
148
  let startIndex = 0;
126
- if (options?.cursor) {
127
- // Decode and validate cursor
128
- const lastKey = decodeCursor(options.cursor, tenantId, context);
149
+ if (lastKey) {
129
150
  const cursorIndex = allKeys.indexOf(lastKey);
130
151
  if (cursorIndex !== -1) {
131
152
  startIndex = cursorIndex + 1;
@@ -163,14 +184,33 @@ export class InMemoryProvider {
163
184
  logger.debug(`[InMemoryProvider] Retrieved ${results.size}/${keys.length} keys for tenant: ${tenantId}`, context);
164
185
  return results;
165
186
  }
187
+ // biome-ignore lint/suspicious/useAwait: async is required by IStorageProvider; the in-memory batch write is synchronous.
166
188
  async setMany(tenantId, entries, context, options) {
167
189
  if (entries.size === 0) {
168
190
  return;
169
191
  }
170
192
  logger.debug(`[InMemoryProvider] Setting ${entries.size} keys for tenant: ${tenantId}`, context);
171
- // Parallel set for better performance
172
- const promises = Array.from(entries.entries()).map(([key, value]) => this.set(tenantId, key, value, context, options));
173
- await Promise.all(promises);
193
+ // Expired entries must be removed before computing the batch delta. If an
194
+ // expired key is present in this batch, counting it as an overwrite and
195
+ // sweeping it later can undercount additions and exceed maxEntries.
196
+ this.sweepExpired();
197
+ let tenantStore = this.store.get(tenantId);
198
+ let newEntryCount = 0;
199
+ for (const key of entries.keys()) {
200
+ if (!tenantStore?.has(key))
201
+ newEntryCount++;
202
+ }
203
+ // Preflight the complete batch so capacity failures cannot partially commit.
204
+ this.ensureCapacity(newEntryCount);
205
+ tenantStore ??= this.getOrCreateTenantStore(tenantId);
206
+ const expiresAt = options?.ttl !== undefined ? Date.now() + options.ttl * 1000 : undefined;
207
+ for (const [key, value] of entries) {
208
+ tenantStore.set(key, {
209
+ value,
210
+ ...(expiresAt !== undefined && { expiresAt }),
211
+ });
212
+ }
213
+ this.entryCount += newEntryCount;
174
214
  logger.debug(`[InMemoryProvider] Successfully set ${entries.size} keys for tenant: ${tenantId}`, context);
175
215
  }
176
216
  async deleteMany(tenantId, keys, context) {
@@ -187,9 +227,11 @@ export class InMemoryProvider {
187
227
  }
188
228
  clear(tenantId, context) {
189
229
  logger.debug(`[InMemoryProvider] Clearing all keys for tenant: ${tenantId}`, context);
190
- const tenantStore = this.getTenantStore(tenantId);
230
+ const tenantStore = this.store.get(tenantId);
231
+ if (!tenantStore)
232
+ return Promise.resolve(0);
191
233
  const count = tenantStore.size;
192
- tenantStore.clear();
234
+ this.store.delete(tenantId);
193
235
  this.entryCount -= count;
194
236
  logger.info(`[InMemoryProvider] Cleared ${count} keys for tenant: ${tenantId}`, context);
195
237
  return Promise.resolve(count);
@@ -1 +1 @@
1
- {"version":3,"file":"inMemoryProvider.js","sourceRoot":"","sources":["../../../../src/storage/providers/inMemory/inMemoryProvider.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAGpD,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAoBnC,MAAM,OAAO,gBAAgB;IACV,KAAK,GAAG,IAAI,GAAG,EAA2C,CAAC;IAC3D,UAAU,CAAS;IAC5B,UAAU,GAAG,CAAC,CAAC;IAEvB,YAAY,OAAiC;QAC3C,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,mBAAmB,CAAC;IAC/D,CAAC;IAED,8DAA8D;IAC9D,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAEO,cAAc,CAAC,QAAgB;QACrC,IAAI,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,WAAW,GAAG,IAAI,GAAG,EAA8B,CAAC;YACpD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,2FAA2F;IACnF,YAAY;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,KAAK,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACjD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC;gBACvC,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;oBAC7C,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBACxB,SAAS,EAAE,CAAC;gBACd,CAAC;YACH,CAAC;YACD,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;QACD,IAAI,CAAC,UAAU,IAAI,SAAS,CAAC;QAC7B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;OAGG;IACK,cAAc;QACpB,IAAI,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU;YAAE,OAAO;QAE9C,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACtC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,CAAC,KAAK,CAAC,0CAA0C,SAAS,kBAAkB,CAAC,CAAC;QACtF,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACvC,MAAM,IAAI,QAAQ,CAChB,gBAAgB,CAAC,aAAa,EAC9B,6CAA6C,IAAI,CAAC,UAAU,KAAK;gBAC/D,gGAAgG,CACnG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,GAAG,CAAI,QAAgB,EAAE,GAAW,EAAE,OAAuB;QAC3D,MAAM,CAAC,KAAK,CAAC,mCAAmC,GAAG,gBAAgB,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC;QACxF,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QAED,IAAI,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YACpD,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACxB,IAAI,CAAC,UAAU,EAAE,CAAC;YAClB,MAAM,CAAC,KAAK,CACV,+CAA+C,GAAG,gBAAgB,QAAQ,EAAE,EAC5E,OAAO,CACR,CAAC;YACF,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAU,CAAC,CAAC;IAC3C,CAAC;IAED,GAAG,CACD,QAAgB,EAChB,GAAW,EACX,KAAc,EACd,OAAuB,EACvB,OAAwB;QAExB,MAAM,CAAC,KAAK,CAAC,mCAAmC,GAAG,gBAAgB,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC;QACxF,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC;QACD,uEAAuE;QACvE,MAAM,SAAS,GAAG,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3F,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE;YACnB,KAAK;YACL,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,CAAC;SAC9C,CAAC,CAAC;QACH,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,QAAgB,EAAE,GAAW,EAAE,OAAuB;QAC3D,MAAM,CAAC,KAAK,CAAC,oCAAoC,GAAG,gBAAgB,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC;QACzF,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,CACF,QAAgB,EAChB,MAAc,EACd,OAAuB,EACvB,OAAqB;QAErB,MAAM,CAAC,KAAK,CAAC,gDAAgD,MAAM,gBAAgB,QAAQ,EAAE,EAAE;YAC7F,GAAG,OAAO;YACV,OAAO;SACR,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,wCAAwC;QACxC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;YACjD,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;oBAC7C,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe;oBACxC,IAAI,CAAC,UAAU,EAAE,CAAC;gBACpB,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,OAAO,CAAC,IAAI,EAAE,CAAC;QAEf,uCAAuC;QACvC,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,kBAAkB,CAAC;QACnD,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;YACpB,6BAA6B;YAC7B,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChE,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC;gBACvB,UAAU,GAAG,WAAW,GAAG,CAAC,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,mEAAmE;gBACnE,MAAM,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;gBAC7D,UAAU,GAAG,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC;YACvE,CAAC;QACH,CAAC;QAED,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,UAAU,GAAG,KAAK,CAAC,CAAC;QACpE,MAAM,UAAU,GACd,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC;YAC7D,CAAC,CAAC,YAAY,CAAC,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAW,EAAE,QAAQ,CAAC;YAC3E,CAAC,CAAC,SAAS,CAAC;QAEhB,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,aAAa;YACnB,UAAU;SACX,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CACX,QAAgB,EAChB,IAAc,EACd,OAAuB;QAEvB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,IAAI,GAAG,EAAa,CAAC;QAC9B,CAAC;QAED,MAAM,CAAC,KAAK,CAAC,8BAA8B,IAAI,CAAC,MAAM,qBAAqB,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC;QAEhG,wCAAwC;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAI,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QACxE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAa,CAAC;QACrC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YACtB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAU,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CACV,gCAAgC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,qBAAqB,QAAQ,EAAE,EAC1F,OAAO,CACR,CAAC;QACF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,OAAO,CACX,QAAgB,EAChB,OAA6B,EAC7B,OAAuB,EACvB,OAAwB;QAExB,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,MAAM,CAAC,KAAK,CACV,8BAA8B,OAAO,CAAC,IAAI,qBAAqB,QAAQ,EAAE,EACzE,OAAO,CACR,CAAC;QAEF,sCAAsC;QACtC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAClE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CACjD,CAAC;QACF,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE5B,MAAM,CAAC,KAAK,CACV,uCAAuC,OAAO,CAAC,IAAI,qBAAqB,QAAQ,EAAE,EAClF,OAAO,CACR,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,IAAc,EAAE,OAAuB;QACxE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,CAAC,KAAK,CACV,+BAA+B,IAAI,CAAC,MAAM,qBAAqB,QAAQ,EAAE,EACzE,OAAO,CACR,CAAC;QAEF,yCAAyC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QACxE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QAEjE,MAAM,CAAC,KAAK,CACV,8BAA8B,YAAY,IAAI,IAAI,CAAC,MAAM,qBAAqB,QAAQ,EAAE,EACxF,OAAO,CACR,CAAC;QACF,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,QAAgB,EAAE,OAAuB;QAC7C,MAAM,CAAC,KAAK,CAAC,oDAAoD,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC;QACtF,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC;QAC/B,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,8BAA8B,KAAK,qBAAqB,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC;QACzF,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;CACF"}
1
+ {"version":3,"file":"inMemoryProvider.js","sourceRoot":"","sources":["../../../../src/storage/providers/inMemory/inMemoryProvider.ts"],"names":[],"mappings":"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"}
@@ -33,6 +33,10 @@ export interface FuzzOptions {
33
33
  * Converts a Zod schema to a fast-check `Arbitrary` that produces valid values.
34
34
  * Supports the JSON-Schema-serializable subset used by MCP tool/resource schemas.
35
35
  *
36
+ * Finite nesting is expanded in full, however deep. A self-referential schema —
37
+ * Zod 4's getter pattern, where reading `.shape` re-enters the same node —
38
+ * terminates at the point of recursion with an absence the schema accepts.
39
+ *
36
40
  * Requires `fast-check` to be loaded first — call from within a `fuzzTool()`/
37
41
  * `fuzzResource()`/`fuzzPrompt()` run, or call `loadFc()` before standalone use.
38
42
  */
@@ -68,7 +72,7 @@ export interface FuzzReport {
68
72
  * Designed to be called inside a `describe()` / `it()` block.
69
73
  *
70
74
  * Checks:
71
- * 1. Valid inputs -> handler runs without crash, output matches schema
75
+ * 1. Valid inputs -> handler returns schema-valid output or a well-formed MCP error
72
76
  * 2. Adversarial inputs -> Zod rejects or handler errors gracefully
73
77
  * 3. No prototype pollution on Object.prototype
74
78
  * 4. No stack trace / path leaks in error messages
@@ -1 +1 @@
1
- {"version":3,"file":"fuzz.d.ts","sourceRoot":"","sources":["../../src/testing/fuzz.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAalD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gDAAgD,CAAC;AAC1F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAC;AAChG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AACpF,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAQxE,wMAAwM;AACxM,wBAAsB,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAGjD;AAiBD,qCAAqC;AACrC,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,GAAG,CAAC,EAAE,kBAAkB,CAAC;IACzB,oDAAoD;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAwBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAErE;AA2HD,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAwDvC,CAAC;AAEX,6EAA6E;AAC7E,wBAAgB,oBAAoB,IAAI,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CA6B5D;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,CAAC,WAAW,CAAC,GAC7B,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAUvC;AA2DD,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,gFAAgF;IAChF,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACnD,4DAA4D;IAC5D,KAAK,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,sDAAsD;IACtD,kBAAkB,EAAE,OAAO,CAAC;IAC5B,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,iBAAiB,EACtB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAkGrB;AAMD;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,qBAAqB,EAC1B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CA+ErB;AAMD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,mBAAmB,EACxB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAsErB"}
1
+ {"version":3,"file":"fuzz.d.ts","sourceRoot":"","sources":["../../src/testing/fuzz.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAalD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gDAAgD,CAAC;AAC1F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAC;AAChG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAEpF,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAQxE,wMAAwM;AACxM,wBAAsB,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAGjD;AAiBD,qCAAqC;AACrC,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,GAAG,CAAC,EAAE,kBAAkB,CAAC;IACzB,oDAAoD;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAmCD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAErE;AA6LD,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAwDvC,CAAC;AAEX,6EAA6E;AAC7E,wBAAgB,oBAAoB,IAAI,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CA6B5D;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,CAAC,WAAW,CAAC,GAC7B,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAUvC;AAiHD,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,gFAAgF;IAChF,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACnD,4DAA4D;IAC5D,KAAK,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,sDAAsD;IACtD,kBAAkB,EAAE,OAAO,CAAC;IAC5B,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,iBAAiB,EACtB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CA8FrB;AAMD;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,qBAAqB,EAC1B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CA2ErB;AAMD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,mBAAmB,EACxB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAsErB"}
@@ -9,6 +9,7 @@
9
9
  * @module src/testing/fuzz
10
10
  */
11
11
  import { ZodArray, ZodBoolean, ZodDefault, ZodEnum, ZodLiteral, ZodNullable, ZodNumber, ZodOptional, ZodString, ZodUnion, } from 'zod';
12
+ import { McpError } from '../types-global/errors.js';
12
13
  import { createMockContext } from './index.js';
13
14
  // ---------------------------------------------------------------------------
14
15
  // Lazy-loaded peer dependency
@@ -46,32 +47,69 @@ function zodTypeName(schema) {
46
47
  // ---------------------------------------------------------------------------
47
48
  // Zod → fast-check arbitrary generation
48
49
  // ---------------------------------------------------------------------------
50
+ /** Elements generated for an array with no declared upper bound. */
51
+ const DEFAULT_ARRAY_MAX = 5;
52
+ /**
53
+ * Nesting levels expanded before a node is treated as non-terminating. Cycle
54
+ * detection catches self-referential schemas by identity; this is the backstop
55
+ * for a schema whose getters mint a fresh node on every access, where there is
56
+ * no repeated identity to detect.
57
+ */
58
+ const MAX_SCHEMA_DEPTH = 32;
49
59
  /**
50
60
  * Converts a Zod schema to a fast-check `Arbitrary` that produces valid values.
51
61
  * Supports the JSON-Schema-serializable subset used by MCP tool/resource schemas.
52
62
  *
63
+ * Finite nesting is expanded in full, however deep. A self-referential schema —
64
+ * Zod 4's getter pattern, where reading `.shape` re-enters the same node —
65
+ * terminates at the point of recursion with an absence the schema accepts.
66
+ *
53
67
  * Requires `fast-check` to be loaded first — call from within a `fuzzTool()`/
54
68
  * `fuzzResource()`/`fuzzPrompt()` run, or call `loadFc()` before standalone use.
55
69
  */
56
70
  export function zodToArbitrary(schema) {
57
- return zodNodeToArbitrary(schema, 0);
71
+ return zodNodeToArbitrary(schema, new Set(), 0) ?? getFc().constant(null);
72
+ }
73
+ /**
74
+ * Expands one schema node, tracking the nodes on the current path so recursion
75
+ * is distinguished from finite nesting.
76
+ *
77
+ * Returns `undefined` when the node cannot yield a finite value — it re-enters
78
+ * itself, or nesting passed `MAX_SCHEMA_DEPTH`. Callers turn that into a
79
+ * schema-valid absence where one exists (`[]`, omitted optional, `null`), and
80
+ * propagate it otherwise, so a generated sample never carries an invalid value
81
+ * at an arbitrary position.
82
+ */
83
+ function zodNodeToArbitrary(schema, path, depth) {
84
+ if (depth > MAX_SCHEMA_DEPTH)
85
+ return;
86
+ if (typeof schema !== 'object' || schema === null)
87
+ return expandNode(schema, path, depth);
88
+ if (path.has(schema))
89
+ return;
90
+ path.add(schema);
91
+ try {
92
+ return expandNode(schema, path, depth);
93
+ }
94
+ finally {
95
+ path.delete(schema);
96
+ }
58
97
  }
59
- function zodNodeToArbitrary(schema, depth) {
98
+ function expandNode(schema, path, depth) {
60
99
  const f = getFc();
61
- if (depth > 6)
62
- return f.constant(null);
63
- // Unwrap wrappers — cast through any to avoid Zod 4 $ZodType vs ZodType mismatch
100
+ // Unwrap wrappers — cast through any to avoid Zod 4 $ZodType vs ZodType mismatch.
101
+ // A wrapper whose inner node cannot terminate collapses to the absence it permits.
64
102
  if (schema instanceof ZodOptional) {
65
- return f.option(zodNodeToArbitrary(schema.unwrap(), depth), { nil: undefined });
103
+ const inner = zodNodeToArbitrary(schema.unwrap(), path, depth);
104
+ return inner ? f.option(inner, { nil: undefined }) : f.constant(undefined);
66
105
  }
67
106
  if (schema instanceof ZodNullable) {
68
- return f.option(zodNodeToArbitrary(schema.unwrap(), depth), { nil: null });
107
+ const inner = zodNodeToArbitrary(schema.unwrap(), path, depth);
108
+ return inner ? f.option(inner, { nil: null }) : f.constant(null);
69
109
  }
70
110
  if (schema instanceof ZodDefault) {
71
- return f.option(zodNodeToArbitrary(schema.removeDefault(), depth), {
72
- nil: undefined,
73
- freq: 5,
74
- });
111
+ const inner = zodNodeToArbitrary(schema.removeDefault(), path, depth);
112
+ return inner ? f.option(inner, { nil: undefined, freq: 5 }) : f.constant(undefined);
75
113
  }
76
114
  // Primitives
77
115
  if (schema instanceof ZodString || zodTypeName(schema) === 'string') {
@@ -93,17 +131,20 @@ function zodNodeToArbitrary(schema, depth) {
93
131
  }
94
132
  // Array
95
133
  if (schema instanceof ZodArray) {
96
- const s = schema;
97
- const minLen = typeof s.minLength === 'number' ? s.minLength : 0;
98
- return f.array(zodNodeToArbitrary(s.element, depth + 1), {
99
- minLength: minLen,
100
- maxLength: Math.max(minLen, 5),
101
- });
134
+ const { minLength, maxLength } = arrayLengthBounds(schema);
135
+ const element = zodNodeToArbitrary(schema.element, path, depth + 1);
136
+ // A recursive element type terminates here — an empty array is the finite value.
137
+ if (!element)
138
+ return f.constant([]);
139
+ return f.array(element, { minLength, maxLength });
102
140
  }
103
141
  // Union
104
142
  if (schema instanceof ZodUnion) {
105
143
  const options = schema._def.options;
106
- return f.oneof(...options.map((o) => zodNodeToArbitrary(o, depth + 1)));
144
+ const arbs = options
145
+ .map((o) => zodNodeToArbitrary(o, path, depth + 1))
146
+ .filter((arb) => arb !== undefined);
147
+ return arbs.length > 0 ? f.oneof(...arbs) : undefined;
107
148
  }
108
149
  // Object — check by _def.type since instanceof ZodObject may have type issues
109
150
  if (zodTypeName(schema) === 'object') {
@@ -115,13 +156,46 @@ function zodNodeToArbitrary(schema, depth) {
115
156
  return f.constant({});
116
157
  const arbs = {};
117
158
  for (const [key, fieldSchema] of entries) {
118
- arbs[key] = zodNodeToArbitrary(fieldSchema, depth + 1);
159
+ const field = zodNodeToArbitrary(fieldSchema, path, depth + 1);
160
+ // An optional or nullable field already collapsed to its permitted absence,
161
+ // so reaching here means a required field cannot terminate.
162
+ if (!field)
163
+ return;
164
+ arbs[key] = field;
119
165
  }
120
166
  return f.record(arbs);
121
167
  }
122
168
  // Fallback: generate JSON-safe primitives
123
169
  return f.oneof(f.string(), f.integer(), f.boolean(), f.constant(null));
124
170
  }
171
+ /**
172
+ * Resolves an array's declared length bounds.
173
+ *
174
+ * Unlike ZodString, Zod 4's ZodArray exposes no `.minLength`/`.maxLength`
175
+ * accessors — `.min()`, `.max()`, `.length()`, and `.nonempty()` all land in
176
+ * `_def.checks`. Reading the absent accessor silently drops every one of them.
177
+ */
178
+ function arrayLengthBounds(schema) {
179
+ const checks = (schema?._def?.checks ?? []);
180
+ let min = 0;
181
+ let max;
182
+ for (const check of checks) {
183
+ const def = check?._zod?.def;
184
+ if (def?.check === 'min_length' && typeof def.minimum === 'number') {
185
+ min = Math.max(min, def.minimum);
186
+ }
187
+ else if (def?.check === 'max_length' && typeof def.maximum === 'number') {
188
+ max = max === undefined ? def.maximum : Math.min(max, def.maximum);
189
+ }
190
+ else if (def?.check === 'length_equals' && typeof def.length === 'number') {
191
+ min = Math.max(min, def.length);
192
+ max = max === undefined ? def.length : Math.min(max, def.length);
193
+ }
194
+ }
195
+ // An unsatisfiable schema (min above max) still has to yield an arbitrary
196
+ // rather than throw out of the generator; the sample is rejected at parse.
197
+ return { minLength: min, maxLength: Math.max(min, max ?? DEFAULT_ARRAY_MAX) };
198
+ }
125
199
  /**
126
200
  * Zod 4 exposes `.minLength`, `.maxLength`, `.format` as direct accessors on ZodString.
127
201
  */
@@ -275,6 +349,50 @@ function checkErrorLeaks(errorText) {
275
349
  /[A-Za-z]:\\/.test(errorText);
276
350
  return { leakedStack, leakedInternals };
277
351
  }
352
+ /** Serialize the fields an MCP client can observe, excluding the local Error stack itself. */
353
+ function publicErrorText(error) {
354
+ if (!(error instanceof McpError)) {
355
+ return error instanceof Error ? error.message : String(error);
356
+ }
357
+ const seen = new WeakSet();
358
+ try {
359
+ return JSON.stringify({ code: error.code, message: error.message, data: error.data }, (_key, value) => {
360
+ if (typeof value === 'bigint')
361
+ return value.toString();
362
+ if (typeof value === 'object' && value !== null) {
363
+ if (seen.has(value))
364
+ return '[Circular]';
365
+ seen.add(value);
366
+ }
367
+ return value;
368
+ });
369
+ }
370
+ catch {
371
+ return error.message;
372
+ }
373
+ }
374
+ /** Records a leak entry when an error's client-visible text exposes a stack or internal path. */
375
+ function recordLeak(report, input, error) {
376
+ const errorText = publicErrorText(error);
377
+ const { leakedStack, leakedInternals } = checkErrorLeaks(errorText);
378
+ if (leakedStack || leakedInternals) {
379
+ report.leaks.push({ input, errorText });
380
+ }
381
+ }
382
+ function recordHandlerError(report, input, error) {
383
+ if (!(error instanceof McpError)) {
384
+ report.crashes.push({ input, error });
385
+ return;
386
+ }
387
+ recordLeak(report, input, error);
388
+ }
389
+ function createToolFuzzContext(def, options, overrides = {}) {
390
+ return createMockContext({
391
+ ...options.ctx,
392
+ ...(def.errors !== undefined && { errors: def.errors }),
393
+ ...overrides,
394
+ });
395
+ }
278
396
  // ---------------------------------------------------------------------------
279
397
  // Prototype pollution detection
280
398
  // ---------------------------------------------------------------------------
@@ -301,7 +419,7 @@ function createProtoPollutionGuard() {
301
419
  * Designed to be called inside a `describe()` / `it()` block.
302
420
  *
303
421
  * Checks:
304
- * 1. Valid inputs -> handler runs without crash, output matches schema
422
+ * 1. Valid inputs -> handler returns schema-valid output or a well-formed MCP error
305
423
  * 2. Adversarial inputs -> Zod rejects or handler errors gracefully
306
424
  * 3. No prototype pollution on Object.prototype
307
425
  * 4. No stack trace / path leaks in error messages
@@ -346,20 +464,20 @@ export async function fuzzTool(def, options = {}) {
346
464
  const parsed = def.input.safeParse(raw);
347
465
  if (!parsed.success)
348
466
  return;
349
- const ctx = createMockContext(options.ctx);
467
+ const ctx = createToolFuzzContext(def, options);
350
468
  try {
351
469
  const result = await withTimeout(def.handler(parsed.data, ctx), timeout);
352
470
  def.output.parse(result);
353
471
  }
354
472
  catch (err) {
355
- report.crashes.push({ input: parsed.data, error: err });
473
+ recordHandlerError(report, parsed.data, err);
356
474
  }
357
475
  }), fcParams);
358
476
  // Phase 2: Adversarial inputs (should be caught by Zod or handler, never crash)
359
477
  const advArb = adversarialObjectArbitrary(def.input);
360
478
  await f.assert(f.asyncProperty(advArb, async (input) => {
361
479
  report.totalRuns++;
362
- const ctx = createMockContext(options.ctx);
480
+ const ctx = createToolFuzzContext(def, options);
363
481
  try {
364
482
  const validated = def.input.safeParse(input);
365
483
  if (!validated.success)
@@ -368,11 +486,7 @@ export async function fuzzTool(def, options = {}) {
368
486
  def.output.parse(result);
369
487
  }
370
488
  catch (err) {
371
- const msg = err instanceof Error ? err.message : String(err);
372
- const leakCheck = checkErrorLeaks(msg);
373
- if (leakCheck.leakedStack || leakCheck.leakedInternals) {
374
- report.leaks.push({ input, errorText: msg });
375
- }
489
+ recordLeak(report, input, err);
376
490
  }
377
491
  }), { ...fcParams, numRuns: numAdversarial });
378
492
  // Phase 3: Raw adversarial (completely wrong types at the top level)
@@ -392,7 +506,7 @@ export async function fuzzTool(def, options = {}) {
392
506
  const validated = def.input.safeParse(input);
393
507
  if (!validated.success)
394
508
  continue;
395
- const ctx = createMockContext(options.ctx);
509
+ const ctx = createToolFuzzContext(def, options);
396
510
  await withTimeout(def.handler(validated.data, ctx), timeout);
397
511
  }
398
512
  catch {
@@ -404,7 +518,7 @@ export async function fuzzTool(def, options = {}) {
404
518
  try {
405
519
  const controller = new AbortController();
406
520
  controller.abort();
407
- const ctx = createMockContext({ ...options.ctx, signal: controller.signal });
521
+ const ctx = createToolFuzzContext(def, options, { signal: controller.signal });
408
522
  const rawSample = generateOne(validArb);
409
523
  const parsedSample = def.input.parse(rawSample);
410
524
  await withTimeout(def.handler(parsedSample, ctx), timeout);
@@ -460,7 +574,7 @@ export async function fuzzResource(def, options = {}) {
460
574
  await withTimeout(def.handler(parsed.data, ctx), timeout);
461
575
  }
462
576
  catch (err) {
463
- report.crashes.push({ input: parsed.data, error: err });
577
+ recordHandlerError(report, parsed.data, err);
464
578
  }
465
579
  }), fcParams);
466
580
  // Phase 2: Adversarial params
@@ -478,11 +592,7 @@ export async function fuzzResource(def, options = {}) {
478
592
  await withTimeout(def.handler(validated.data, ctx), timeout);
479
593
  }
480
594
  catch (err) {
481
- const msg = err instanceof Error ? err.message : String(err);
482
- const leakCheck = checkErrorLeaks(msg);
483
- if (leakCheck.leakedStack || leakCheck.leakedInternals) {
484
- report.leaks.push({ input: params, errorText: msg });
485
- }
595
+ recordLeak(report, params, err);
486
596
  }
487
597
  }), { ...fcParams, numRuns: numAdversarial });
488
598
  }
@@ -496,7 +606,7 @@ export async function fuzzResource(def, options = {}) {
496
606
  await withTimeout(def.handler({}, ctx), timeout);
497
607
  }
498
608
  catch (err) {
499
- report.crashes.push({ input: {}, error: err });
609
+ recordHandlerError(report, {}, err);
500
610
  }
501
611
  }
502
612
  protoGuard.check(report);