@copilotkit/aimock 1.43.0 → 1.44.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 (290) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +15 -0
  4. package/README.md +8 -2
  5. package/dist/agui-handler.d.ts.map +1 -1
  6. package/dist/agui-types.d.ts.map +1 -1
  7. package/dist/bedrock-converse.cjs +32 -4
  8. package/dist/bedrock-converse.cjs.map +1 -1
  9. package/dist/bedrock-converse.d.cts.map +1 -1
  10. package/dist/bedrock-converse.d.ts.map +1 -1
  11. package/dist/bedrock-converse.js +32 -4
  12. package/dist/bedrock-converse.js.map +1 -1
  13. package/dist/chaos.cjs +8 -5
  14. package/dist/chaos.cjs.map +1 -1
  15. package/dist/chaos.d.cts.map +1 -1
  16. package/dist/chaos.d.ts.map +1 -1
  17. package/dist/chaos.js +9 -6
  18. package/dist/chaos.js.map +1 -1
  19. package/dist/cli.cjs +89 -7
  20. package/dist/cli.cjs.map +1 -1
  21. package/dist/cli.js +91 -9
  22. package/dist/cli.js.map +1 -1
  23. package/dist/cohere.cjs +27 -1
  24. package/dist/cohere.cjs.map +1 -1
  25. package/dist/cohere.js +27 -1
  26. package/dist/cohere.js.map +1 -1
  27. package/dist/config-loader.cjs +1 -1
  28. package/dist/config-loader.d.ts.map +1 -1
  29. package/dist/config-loader.js +1 -1
  30. package/dist/constants.cjs +8 -0
  31. package/dist/constants.cjs.map +1 -1
  32. package/dist/constants.d.cts +6 -2
  33. package/dist/constants.d.ts +6 -2
  34. package/dist/constants.js +8 -1
  35. package/dist/constants.js.map +1 -1
  36. package/dist/echo-text.cjs +65 -0
  37. package/dist/echo-text.cjs.map +1 -0
  38. package/dist/echo-text.d.cts +22 -0
  39. package/dist/echo-text.d.cts.map +1 -0
  40. package/dist/echo-text.d.ts +22 -0
  41. package/dist/echo-text.d.ts.map +1 -0
  42. package/dist/echo-text.js +65 -0
  43. package/dist/echo-text.js.map +1 -0
  44. package/dist/embeddings.cjs +18 -1
  45. package/dist/embeddings.cjs.map +1 -1
  46. package/dist/embeddings.d.cts +1 -1
  47. package/dist/embeddings.d.cts.map +1 -1
  48. package/dist/embeddings.d.ts +1 -1
  49. package/dist/embeddings.d.ts.map +1 -1
  50. package/dist/embeddings.js +18 -1
  51. package/dist/embeddings.js.map +1 -1
  52. package/dist/files.cjs +9 -11
  53. package/dist/files.cjs.map +1 -1
  54. package/dist/files.d.cts.map +1 -1
  55. package/dist/files.d.ts.map +1 -1
  56. package/dist/files.js +10 -13
  57. package/dist/files.js.map +1 -1
  58. package/dist/fine-tuning.cjs +1 -19
  59. package/dist/fine-tuning.cjs.map +1 -1
  60. package/dist/fine-tuning.d.cts.map +1 -1
  61. package/dist/fine-tuning.d.ts.map +1 -1
  62. package/dist/fine-tuning.js +2 -20
  63. package/dist/fine-tuning.js.map +1 -1
  64. package/dist/fixture-loader-services.cjs +116 -0
  65. package/dist/fixture-loader-services.cjs.map +1 -0
  66. package/dist/fixture-loader-services.d.cts +48 -0
  67. package/dist/fixture-loader-services.d.cts.map +1 -0
  68. package/dist/fixture-loader-services.d.ts +48 -0
  69. package/dist/fixture-loader-services.d.ts.map +1 -0
  70. package/dist/fixture-loader-services.js +114 -0
  71. package/dist/fixture-loader-services.js.map +1 -0
  72. package/dist/fixture-loader.cjs +172 -11
  73. package/dist/fixture-loader.cjs.map +1 -1
  74. package/dist/fixture-loader.d.cts +95 -1
  75. package/dist/fixture-loader.d.cts.map +1 -1
  76. package/dist/fixture-loader.d.ts +95 -1
  77. package/dist/fixture-loader.d.ts.map +1 -1
  78. package/dist/fixture-loader.js +168 -12
  79. package/dist/fixture-loader.js.map +1 -1
  80. package/dist/gemini-embeddings.cjs +42 -2
  81. package/dist/gemini-embeddings.cjs.map +1 -1
  82. package/dist/gemini-embeddings.js +43 -3
  83. package/dist/gemini-embeddings.js.map +1 -1
  84. package/dist/gemini-interactions.cjs +38 -0
  85. package/dist/gemini-interactions.cjs.map +1 -1
  86. package/dist/gemini-interactions.d.cts.map +1 -1
  87. package/dist/gemini-interactions.d.ts.map +1 -1
  88. package/dist/gemini-interactions.js +38 -0
  89. package/dist/gemini-interactions.js.map +1 -1
  90. package/dist/gemini.cjs +8 -1
  91. package/dist/gemini.cjs.map +1 -1
  92. package/dist/gemini.d.cts.map +1 -1
  93. package/dist/gemini.d.ts.map +1 -1
  94. package/dist/gemini.js +8 -1
  95. package/dist/gemini.js.map +1 -1
  96. package/dist/helpers.cjs +276 -5
  97. package/dist/helpers.cjs.map +1 -1
  98. package/dist/helpers.d.cts.map +1 -1
  99. package/dist/helpers.d.ts.map +1 -1
  100. package/dist/helpers.js +275 -7
  101. package/dist/helpers.js.map +1 -1
  102. package/dist/images.cjs +3 -2
  103. package/dist/images.cjs.map +1 -1
  104. package/dist/images.js +3 -2
  105. package/dist/images.js.map +1 -1
  106. package/dist/index.cjs +30 -1
  107. package/dist/index.d.cts +8 -3
  108. package/dist/index.d.ts +8 -3
  109. package/dist/index.js +9 -3
  110. package/dist/jest.cjs +15 -10
  111. package/dist/jest.cjs.map +1 -1
  112. package/dist/jest.d.cts +4 -2
  113. package/dist/jest.d.cts.map +1 -1
  114. package/dist/jest.d.ts +4 -2
  115. package/dist/jest.d.ts.map +1 -1
  116. package/dist/jest.js +16 -11
  117. package/dist/jest.js.map +1 -1
  118. package/dist/journal.cjs +20 -0
  119. package/dist/journal.cjs.map +1 -1
  120. package/dist/journal.d.cts +16 -0
  121. package/dist/journal.d.cts.map +1 -1
  122. package/dist/journal.d.ts +16 -0
  123. package/dist/journal.d.ts.map +1 -1
  124. package/dist/journal.js +20 -0
  125. package/dist/journal.js.map +1 -1
  126. package/dist/llmock.cjs +82 -10
  127. package/dist/llmock.cjs.map +1 -1
  128. package/dist/llmock.d.cts +35 -0
  129. package/dist/llmock.d.cts.map +1 -1
  130. package/dist/llmock.d.ts +35 -0
  131. package/dist/llmock.d.ts.map +1 -1
  132. package/dist/llmock.js +83 -11
  133. package/dist/llmock.js.map +1 -1
  134. package/dist/mcp-fakes-mount.cjs +216 -0
  135. package/dist/mcp-fakes-mount.cjs.map +1 -0
  136. package/dist/mcp-fakes-mount.js +210 -0
  137. package/dist/mcp-fakes-mount.js.map +1 -0
  138. package/dist/mcp-fakes.cjs +1619 -0
  139. package/dist/mcp-fakes.cjs.map +1 -0
  140. package/dist/mcp-fakes.d.cts +101 -0
  141. package/dist/mcp-fakes.d.cts.map +1 -0
  142. package/dist/mcp-fakes.d.ts +101 -0
  143. package/dist/mcp-fakes.d.ts.map +1 -0
  144. package/dist/mcp-fakes.js +1614 -0
  145. package/dist/mcp-fakes.js.map +1 -0
  146. package/dist/mcp-handler.cjs +331 -17
  147. package/dist/mcp-handler.cjs.map +1 -1
  148. package/dist/mcp-handler.js +330 -18
  149. package/dist/mcp-handler.js.map +1 -1
  150. package/dist/mcp-mock.cjs +217 -49
  151. package/dist/mcp-mock.cjs.map +1 -1
  152. package/dist/mcp-mock.d.cts +66 -1
  153. package/dist/mcp-mock.d.cts.map +1 -1
  154. package/dist/mcp-mock.d.ts +66 -1
  155. package/dist/mcp-mock.d.ts.map +1 -1
  156. package/dist/mcp-mock.js +218 -50
  157. package/dist/mcp-mock.js.map +1 -1
  158. package/dist/mcp-stub.cjs +5 -1
  159. package/dist/mcp-stub.d.cts +3 -1
  160. package/dist/mcp-stub.d.ts +3 -1
  161. package/dist/mcp-stub.js +3 -1
  162. package/dist/mcp-types.d.cts +6 -0
  163. package/dist/mcp-types.d.ts +6 -0
  164. package/dist/message-text.cjs +192 -0
  165. package/dist/message-text.cjs.map +1 -0
  166. package/dist/message-text.d.cts +31 -0
  167. package/dist/message-text.d.cts.map +1 -0
  168. package/dist/message-text.d.ts +31 -0
  169. package/dist/message-text.d.ts.map +1 -0
  170. package/dist/message-text.js +184 -0
  171. package/dist/message-text.js.map +1 -0
  172. package/dist/messages.cjs +38 -0
  173. package/dist/messages.cjs.map +1 -1
  174. package/dist/messages.js +38 -0
  175. package/dist/messages.js.map +1 -1
  176. package/dist/metrics.cjs +46 -66
  177. package/dist/metrics.cjs.map +1 -1
  178. package/dist/metrics.d.cts +14 -6
  179. package/dist/metrics.d.cts.map +1 -1
  180. package/dist/metrics.d.ts +14 -6
  181. package/dist/metrics.d.ts.map +1 -1
  182. package/dist/metrics.js +32 -40
  183. package/dist/metrics.js.map +1 -1
  184. package/dist/ollama.cjs +5 -1
  185. package/dist/ollama.cjs.map +1 -1
  186. package/dist/ollama.d.cts.map +1 -1
  187. package/dist/ollama.d.ts.map +1 -1
  188. package/dist/ollama.js +5 -1
  189. package/dist/ollama.js.map +1 -1
  190. package/dist/openapi.cjs +3405 -0
  191. package/dist/openapi.cjs.map +1 -0
  192. package/dist/openapi.d.cts +30 -0
  193. package/dist/openapi.d.cts.map +1 -0
  194. package/dist/openapi.d.ts +30 -0
  195. package/dist/openapi.d.ts.map +1 -0
  196. package/dist/openapi.js +3404 -0
  197. package/dist/openapi.js.map +1 -0
  198. package/dist/openrouter-video.cjs +4 -4
  199. package/dist/openrouter-video.cjs.map +1 -1
  200. package/dist/openrouter-video.d.cts.map +1 -1
  201. package/dist/openrouter-video.d.ts.map +1 -1
  202. package/dist/openrouter-video.js +4 -4
  203. package/dist/openrouter-video.js.map +1 -1
  204. package/dist/recorder.cjs +9 -1
  205. package/dist/recorder.cjs.map +1 -1
  206. package/dist/recorder.d.cts.map +1 -1
  207. package/dist/recorder.d.ts.map +1 -1
  208. package/dist/recorder.js +9 -1
  209. package/dist/recorder.js.map +1 -1
  210. package/dist/responses.cjs +43 -4
  211. package/dist/responses.cjs.map +1 -1
  212. package/dist/responses.d.cts.map +1 -1
  213. package/dist/responses.d.ts.map +1 -1
  214. package/dist/responses.js +43 -4
  215. package/dist/responses.js.map +1 -1
  216. package/dist/route-registry.cjs +951 -0
  217. package/dist/route-registry.cjs.map +1 -0
  218. package/dist/route-registry.d.cts +33 -0
  219. package/dist/route-registry.d.cts.map +1 -0
  220. package/dist/route-registry.d.ts +33 -0
  221. package/dist/route-registry.d.ts.map +1 -0
  222. package/dist/route-registry.js +866 -0
  223. package/dist/route-registry.js.map +1 -0
  224. package/dist/router.cjs +1 -1
  225. package/dist/router.cjs.map +1 -1
  226. package/dist/router.js +1 -1
  227. package/dist/router.js.map +1 -1
  228. package/dist/server.cjs +590 -191
  229. package/dist/server.cjs.map +1 -1
  230. package/dist/server.d.cts +4 -1
  231. package/dist/server.d.cts.map +1 -1
  232. package/dist/server.d.ts +4 -1
  233. package/dist/server.d.ts.map +1 -1
  234. package/dist/server.js +498 -99
  235. package/dist/server.js.map +1 -1
  236. package/dist/speech.cjs +4 -2
  237. package/dist/speech.cjs.map +1 -1
  238. package/dist/speech.js +4 -2
  239. package/dist/speech.js.map +1 -1
  240. package/dist/suite.cjs +1 -1
  241. package/dist/suite.js +1 -1
  242. package/dist/transcription.cjs +2 -2
  243. package/dist/transcription.cjs.map +1 -1
  244. package/dist/transcription.d.cts.map +1 -1
  245. package/dist/transcription.d.ts.map +1 -1
  246. package/dist/transcription.js +2 -2
  247. package/dist/transcription.js.map +1 -1
  248. package/dist/types.cjs +18 -0
  249. package/dist/types.cjs.map +1 -0
  250. package/dist/types.d.cts +202 -2
  251. package/dist/types.d.cts.map +1 -1
  252. package/dist/types.d.ts +202 -2
  253. package/dist/types.d.ts.map +1 -1
  254. package/dist/types.js +17 -0
  255. package/dist/types.js.map +1 -0
  256. package/dist/validate-cli.cjs +89 -31
  257. package/dist/validate-cli.cjs.map +1 -1
  258. package/dist/validate-cli.js +91 -33
  259. package/dist/validate-cli.js.map +1 -1
  260. package/dist/vector-stores.cjs +1180 -0
  261. package/dist/vector-stores.cjs.map +1 -0
  262. package/dist/vector-stores.d.cts +106 -0
  263. package/dist/vector-stores.d.cts.map +1 -0
  264. package/dist/vector-stores.d.ts +106 -0
  265. package/dist/vector-stores.d.ts.map +1 -0
  266. package/dist/vector-stores.js +1164 -0
  267. package/dist/vector-stores.js.map +1 -0
  268. package/dist/vector-types.d.cts.map +1 -1
  269. package/dist/vector-types.d.ts.map +1 -1
  270. package/dist/video.cjs +19 -0
  271. package/dist/video.cjs.map +1 -1
  272. package/dist/video.d.cts.map +1 -1
  273. package/dist/video.d.ts.map +1 -1
  274. package/dist/video.js +19 -0
  275. package/dist/video.js.map +1 -1
  276. package/dist/vitest.cjs +15 -10
  277. package/dist/vitest.cjs.map +1 -1
  278. package/dist/vitest.d.cts +4 -2
  279. package/dist/vitest.d.cts.map +1 -1
  280. package/dist/vitest.d.ts +4 -2
  281. package/dist/vitest.d.ts.map +1 -1
  282. package/dist/vitest.js +16 -11
  283. package/dist/vitest.js.map +1 -1
  284. package/dist/ws-gemini-live.d.ts +2 -2
  285. package/dist/ws-realtime.d.ts +2 -2
  286. package/dist/ws-responses.cjs +14 -2
  287. package/dist/ws-responses.cjs.map +1 -1
  288. package/dist/ws-responses.js +14 -2
  289. package/dist/ws-responses.js.map +1 -1
  290. package/package.json +4 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-fakes.cjs","names":["DEFAULT_TEST_ID","FixtureLoadError","build","fixed","MCP_FAKES_ECHO_LIMIT","jsonText","fullText","quote","quoteJson"],"sources":["../src/mcp-fakes.ts"],"sourcesContent":["/**\n * MCP fakes: the fake model core.\n *\n * Pure module, no I/O. It owns block validation (the bad-block cases (a)-(j)\n * listed in `MCP_FAKES_LOAD_RULES`), entry ids and the per-mount counters in\n * them, block-id and entry-id uniqueness per mount, scope matching, scope\n * tiers, argument equality, the synchronous claim step with its mismatch and\n * exhausted details (`firstDifference`), consumption state per test id with\n * its FIFO cap, the undeclared-tool policy, and the fake tools for\n * `tools/list`. One `McpFakeStore` serves one MCP mount.\n */\n\nimport { DEFAULT_TEST_ID, MCP_FAKES_ECHO_LIMIT } from \"./constants.js\";\nimport { cutText, type CutUnits } from \"./echo-text.js\";\nimport {\n FixtureLoadError,\n type FixtureLoadErrorJSON,\n type McpFakesLoadRule,\n} from \"./fixture-loader.js\";\nimport {\n Message,\n build,\n fixed,\n fullText,\n jsonText,\n msg,\n plainText,\n quote,\n quoteJson,\n type MessageValue,\n} from \"./message-text.js\";\nimport type {\n McpFakeCallAnswer,\n McpFakeCallMatch,\n McpFakeDeepReadonly,\n McpFakeIdentity,\n McpFakeResult,\n McpFakeScope,\n McpFakeSource,\n McpFakeUndeclaredPolicy,\n} from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n\n/** Default `mount` path of a block. */\nexport const MCP_FAKES_DEFAULT_MOUNT = \"/mcp\";\n\n/**\n * Name of the consumption state shared by requests that supply no test id:\n * the journal's `DEFAULT_TEST_ID`. The store keeps that state apart from an\n * explicitly supplied test id equal to this string;\n * `resetState(MCP_FAKES_DEFAULT_TEST_ID)` resets both.\n */\nexport const MCP_FAKES_DEFAULT_TEST_ID = DEFAULT_TEST_ID;\n\n/**\n * Default FIFO cap on distinct test ids (`McpFakeStoreOptions.maxTestIds`),\n * for a mount with no journal. A mount with a journal mirrors the journal's\n * effective cap (`fixtureCountsMaxTestIdsCap`): 500 under `createServer` unless\n * the option is set, and `0` (unbounded) for a bare `Journal` or an explicit `0`.\n */\nexport const MCP_FAKES_DEFAULT_MAX_TEST_IDS = 500;\n\n/**\n * Longest text an `echo` of one value produces. Defined in constants.ts so\n * that helpers.ts can share it without an import cycle.\n */\nexport { MCP_FAKES_ECHO_LIMIT };\n\n/**\n * Deepest nesting of objects and arrays accepted in an `mcpFakes` value: the\n * value itself (a block, or the array of blocks) is level 1. A container\n * below this level is not copied; the input snapshot holds a \"nested deeper\n * than 64 levels\" value there, which the check of the enclosing field reports\n * as its own bad block.\n */\nexport const MCP_FAKES_MAX_DEPTH = 64;\n\n/** The reason a container below `MCP_FAKES_MAX_DEPTH` levels is not copied. */\nconst DEPTH_REASON = msg`nested deeper than ${MCP_FAKES_MAX_DEPTH} levels`;\n\n/** Longest `firstDifference` text (path plus both values), cut the same way. */\nconst DIFF_LIMIT = 1_000;\n\nconst BLOCK_KEYS = new Set([\"scope\", \"mount\", \"undeclaredTools\", \"tools\"]);\nconst TOOL_KEYS = new Set([\"name\", \"description\", \"inputSchema\", \"calls\"]);\nconst CALL_KEYS = new Set([\"args\", \"anyArgs\", \"result\", \"error\", \"id\"]);\nconst SCOPE_KEYS = new Set([\"testId\", \"context\"]);\n\n// ---------------------------------------------------------------------------\n// Types\n\n/**\n * One validated call entry, with its entry id. Deeply frozen: its `args` /\n * `result` are frozen copies of the caller's values (never the caller's objects).\n */\nexport type ValidatedCall = Readonly<{\n /**\n * Full entry id: `<source><load>[<block>]:<local>`, where `local` is the\n * user `id` or `<tool>#<index>`.\n */\n id: string;\n /** Position in its tool's `calls`. */\n index: number;\n}> &\n McpFakeDeepReadonly<McpFakeCallMatch> &\n McpFakeDeepReadonly<McpFakeCallAnswer>;\n\n/** One validated tool. Deeply frozen; `inputSchema` is a frozen copy. */\nexport interface ValidatedTool {\n readonly name: string;\n readonly description?: string;\n readonly inputSchema?: McpFakeDeepReadonly<Record<string, unknown>>;\n readonly calls: readonly ValidatedCall[];\n}\n\n/**\n * Scope tiers, most specific first. A tool's candidate entries come from the\n * first tier with an applicable block that declares it.\n */\nexport type McpFakeTier = \"testId+context\" | \"testId\" | \"context\" | \"shared\";\n\nconst TIER_ORDER: readonly McpFakeTier[] = [\"testId+context\", \"testId\", \"context\", \"shared\"];\n\n/** One validated block. Deeply frozen: the store hands it out as is. */\nexport interface ValidatedBlock {\n /** Entry-id `source`: the file's source string, or `code#<n>` / `control-api#<n>`. */\n readonly source: string;\n /** Entry-id load suffix: `\"\"` for the first load of a source, `@<k>` for the k-th. */\n readonly load: string;\n /** `null` when `mcpFakes` was a single object. */\n readonly blockIndex: number | null;\n /** `<source><load>[<block>]`. */\n readonly blockId: string;\n readonly scope: McpFakeScope;\n readonly tier: McpFakeTier;\n readonly mount: string;\n readonly undeclaredTools?: McpFakeUndeclaredPolicy;\n readonly tools: readonly ValidatedTool[];\n}\n\n/**\n * A validation warning: an `args` entry shadowed by an earlier `anyArgs` entry\n * of the same tool. Errors are `FixtureLoadError` instances.\n */\nexport interface McpFakeIssue {\n file: string | null;\n blockId: string | null;\n entryId: string | null;\n message: string;\n}\n\nexport interface McpFakesValidation {\n blocks: ValidatedBlock[];\n errors: FixtureLoadError[];\n warnings: McpFakeIssue[];\n}\n\n/** A `tools/call` result. */\nexport type McpFakeCallToolResult = { content: unknown[] } & Record<string, unknown>;\n\n/**\n * One declared entry as named in a mismatch claim or a snapshot. Deeply\n * frozen; `args` is a frozen copy.\n */\nexport type McpFakeDeclaredEntry = Readonly<{ id: string; consumed: boolean }> &\n McpFakeDeepReadonly<McpFakeCallMatch>;\n\n/**\n * What `McpFakeStore.claim` returns. Frozen, as is everything in it that the\n * store owns (`entry`, `block`, `declared`, `matchingIds`); `result` is a\n * fresh mutable copy for the mount to send, and `received` is the caller's\n * `args` value as given (not copied or frozen), or a new `{}` when it was\n * `undefined`.\n */\nexport type McpFakeClaim =\n | Readonly<{\n kind: \"answer\";\n tool: string;\n entry: ValidatedCall;\n block: ValidatedBlock;\n tier: McpFakeTier;\n result: McpFakeCallToolResult;\n }>\n | Readonly<{\n kind: \"mismatch\";\n tool: string;\n received: unknown;\n declared: readonly McpFakeDeclaredEntry[];\n firstDifference: string;\n }>\n | Readonly<{\n kind: \"exhausted\";\n tool: string;\n received: unknown;\n matchingDeclared: number;\n matchingConsumed: number;\n matchingIds: readonly string[];\n }>\n | Readonly<{\n /**\n * The test id's consumption state was dropped by the FIFO cap, so\n * which entries it already used is unknown. Fail loud rather than replay\n * an entry; only `resetState(testId)` (or a full reset) clears this. The\n * mark never ages out.\n */\n kind: \"evicted\";\n tool: string;\n testId: string;\n maxTestIds: number;\n }>\n | Readonly<{ kind: \"none\" }>;\n\nexport interface McpFakeToolListing {\n name: string;\n description?: string;\n inputSchema: Record<string, unknown>;\n}\n\n/** One block of `McpFakeStore.snapshot()`. Deeply frozen. */\nexport interface McpFakeBlockSnapshot {\n readonly blockId: string;\n readonly source: string;\n readonly mount: string;\n readonly scope: McpFakeScope;\n readonly undeclaredTools: McpFakeUndeclaredPolicy;\n /**\n * The requested test id's consumption state was evicted by the FIFO cap. Its\n * entries then show `consumed: false` because which ones it used is unknown,\n * and a claim from it of a tool an applicable block declares fails as\n * `evicted` until it is reset.\n */\n readonly evicted: boolean;\n readonly tools: ReadonlyArray<\n Readonly<{ name: string; entries: readonly McpFakeDeclaredEntry[] }>\n >;\n}\n\nexport interface McpFakeAddOrigin {\n /**\n * `file`: blocks keep their `source` and `blockIndex`, and the per-source\n * load counter (`@<k>`) applies.\n * `code` / `control-api`: one run-time addition; every block gets the source\n * `code#<n>` / `control-api#<n>`, whatever `source` it carried. The\n * input is one `mcpFakes` value of that addition: a single item with a null\n * `blockIndex` is the single-object form (no `[<i>]`); otherwise each block\n * is numbered by its position in the input (`[0]`, `[1]`, ...).\n */\n kind: \"file\" | \"code\" | \"control-api\";\n}\n\n/** What a successful `McpFakeStore.add` / `Mountable.addMcpFakes` returns. */\nexport interface McpFakeAddResult {\n /** Shadowed-entry warnings of the added blocks, with their real entry ids. */\n warnings: McpFakeIssue[];\n}\n\n/**\n * `McpFakesAddError.toJSON()`: the first error's `rule`, `file`, `blockId` and\n * `entryId`, the combined `message`, and every error and warning.\n */\nexport interface McpFakesAddErrorJSON extends FixtureLoadErrorJSON {\n name: \"McpFakesAddError\";\n errors: FixtureLoadErrorJSON[];\n warnings: McpFakeIssue[];\n}\n\n/**\n * The error a failed add throws. It is a `FixtureLoadError` whose `rule`,\n * `file`, `blockId` and `entryId` are those of the first error, and whose\n * `message` is the first error's message plus the count of the others.\n * `errors` holds every error found in the input, in order (the first\n * included; see `validateBlock` for the checks that stop early), and\n * `warnings` the shadowed-entry warnings of the blocks that passed every\n * check. Both are frozen, non-writable arrays; `toJSON()` returns copies.\n */\nexport class McpFakesAddError extends FixtureLoadError {\n override readonly name = \"McpFakesAddError\";\n declare readonly errors: readonly FixtureLoadError[];\n declare readonly warnings: readonly Readonly<McpFakeIssue>[];\n\n constructor(errors: readonly FixtureLoadError[], warnings: readonly McpFakeIssue[]) {\n const first = errors[0];\n if (!first) throw new TypeError(build(msg`McpFakesAddError needs at least one error`));\n super({\n rule: first.rule,\n file: first.file,\n blockId: first.blockId,\n entryId: first.entryId,\n detail: \"\",\n });\n const more = errors.length - 1;\n this.message =\n more > 0\n ? build(\n msg`${fixed(first.message)} (and ${more} more ${fixed(more === 1 ? \"error\" : \"errors\")})`,\n )\n : first.message;\n Object.defineProperty(this, \"errors\", {\n value: Object.freeze([...errors]),\n enumerable: true,\n writable: false,\n });\n Object.defineProperty(this, \"warnings\", {\n value: Object.freeze(warnings.map((w) => Object.freeze({ ...w }))),\n enumerable: true,\n writable: false,\n });\n }\n\n override toJSON(): McpFakesAddErrorJSON {\n return {\n ...super.toJSON(),\n name: this.name,\n errors: this.errors.map((e) => e.toJSON()),\n warnings: this.warnings.map((w) => ({ ...w })),\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Small helpers\n\n/** An object whose prototype is `Object.prototype` or `null` (not an array). */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * The one own-key listing for input data: own, enumerable, string keys.\n * Inherited names (`constructor`, `toString`, `__proto__`) are never listed.\n *\n * @internal\n */\nexport function ownKeys(obj: object): string[] {\n return Object.keys(obj);\n}\n\n/**\n * The one key check: `key` is an own property of `obj`. Unlike `key in obj`,\n * it never sees the prototype chain, so `hasOwnKey({}, \"constructor\")` is\n * false.\n *\n * @internal\n */\nexport function hasOwnKey(obj: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n\n/**\n * `text` cut to at most `limit` chars in all, as the message builder cuts one\n * part: the kept part, then `…` and the count of chars left out. When even\n * that count does not fit in `limit`, the kept part is followed by a bare\n * `…`. Never ends the kept part inside a surrogate pair, and with `units`\n * `\"json\"` never inside a JSON escape. A `limit` below 1 keeps nothing\n * (`\"\"`), as `cutText` does; a `NaN` limit is a `RangeError`. Messages do not\n * use it: they are built by `build` (message-text.ts).\n *\n * @internal\n */\nexport function echoText(\n text: string,\n limit = MCP_FAKES_ECHO_LIMIT,\n units: CutUnits = \"text\",\n): string {\n // Below 1 a user part has no room for its `…`; cut it as `cutText` does.\n if (!(limit >= 1)) return cutText(text, limit, units);\n return build(msg`${units === \"json\" ? jsonText(text, limit) : plainText(text, limit)}`);\n}\n\n/**\n * A user value as one message part: a string is JSON-quoted (quotes and\n * control chars escaped), any other value is rendered as JSON (or as\n * `undefined`, `NaN`, `10n`, ... where JSON cannot at the top level), and a\n * snapshot placeholder, a nested bigint, a cycle, a container too deep, a\n * symbol or function, and a value whose reading throws each as a `<reason>`\n * placeholder whose user text is quoted (see `render`). The builder cuts it\n * once, to its share and to no more than its max, never inside a JSON escape\n * (`\\n`, `\\u0001`). Whatever the caller's code throws is caught; an error of\n * aimock's own is not.\n */\nfunction shown(value: unknown, max = MCP_FAKES_ECHO_LIMIT): MessageValue {\n return jsonText(render(value), max);\n}\n\n/**\n * One user value as message text: `shown`, built alone, so cut to `limit`\n * chars as the builder cuts it. A `limit` below 1 keeps nothing (`\"\"`), as\n * `cutText` does; a `NaN` limit is a `RangeError`.\n *\n * @internal\n */\nexport function echo(value: unknown, limit = MCP_FAKES_ECHO_LIMIT): string {\n if (!(limit >= 1)) return cutText(render(value), limit, \"json\");\n return build(msg`${shown(value, limit)}`);\n}\n\nfunction render(value: unknown): string {\n if (value === undefined) return \"undefined\";\n if (typeof value === \"number\" && !Number.isFinite(value)) return String(value);\n if (typeof value === \"bigint\") return `${value}n`;\n return renderMember(() => value, \"\", []) ?? notJson(value);\n}\n\n/**\n * Thrown by `userCode` when code the caller supplied throws: a `toJSON`, a\n * getter, a `Proxy` trap, a `toString`. The renderer catches only this, so a\n * defect in aimock's own rendering code is never hidden as a placeholder.\n */\nclass UserCodeThrew {\n constructor(readonly error: unknown) {}\n}\n\n/**\n * `run()`, which touches the caller's value and so may run the caller's code;\n * whatever that code throws comes out as a `UserCodeThrew`.\n */\nfunction userCode<T>(run: () => T): T {\n try {\n return run();\n } catch (error) {\n throw new UserCodeThrew(error);\n }\n}\n\n/** A placeholder in a rendered value: `<reason>`, the reason's text whole. */\nfunction placeholder(reason: Message): string {\n return `<${fullText(reason)}>`;\n}\n\n/** The reason a rendered value holds where it reaches one of its own containers. */\nconst CIRCULAR_REASON = msg`a circular reference`;\n\n/**\n * A value that `renderJson` gives no JSON for (a symbol, a function): a\n * placeholder that names its type and, when it has one, quotes its text.\n */\nfunction notJson(value: unknown): string {\n const reason = msg`not a JSON value (got ${fixed(typeof value)})`;\n let text: string;\n try {\n text = userCode(() => String(value));\n } catch (err) {\n if (!(err instanceof UserCodeThrew)) throw err;\n return placeholder(reason);\n }\n return placeholder(msg`${reason}: ${quote(text)}`);\n}\n\n/**\n * One value of a rendered value, read by `read` (which may run the caller's\n * code), rendered by `renderJson`. Where the caller's code throws while it is\n * read or rendered, it renders as an \"unreadable value\" placeholder that\n * quotes what was thrown, and the rest of the value is kept.\n */\nfunction renderMember(read: () => unknown, key: string, stack: object[]): string | undefined {\n try {\n return renderJson(userCode(read), key, stack);\n } catch (err) {\n if (!(err instanceof UserCodeThrew)) throw err;\n return placeholder(msg`an unreadable value (reading it threw ${describeThrown(err.error)})`);\n }\n}\n\n/**\n * `value` as `JSON.stringify` renders it, except that a snapshot placeholder,\n * a bigint below the top level, a cycle (found through `stack`, the\n * containers being rendered) and a container more than `MCP_FAKES_MAX_DEPTH`\n * levels down each render as a `<reason>` placeholder. A placeholder is known\n * by its class, never by its text, so no user value can pose as one.\n * `undefined` where `JSON.stringify` gives `undefined`. Every part it joins\n * is `JSON.stringify` output or placeholder text. Every read of the caller's\n * value goes through `userCode`, so the only error it lets out from the\n * caller's code is a `UserCodeThrew`.\n */\nfunction renderJson(value: unknown, key: string, stack: object[]): string | undefined {\n if (userCode(() => value instanceof NotPlain)) return placeholder((value as NotPlain).reason);\n if (value !== null && (typeof value === \"object\" || typeof value === \"bigint\")) {\n const toJSON: unknown = userCode(() => (value as { toJSON?: unknown }).toJSON);\n if (typeof toJSON === \"function\") value = userCode(() => toJSON.call(value, key) as unknown);\n }\n if (typeof value === \"bigint\") return placeholder(msg`a bigint (${fixed(`${value}n`)})`);\n if (value === null || typeof value !== \"object\") return JSON.stringify(value);\n const container = value;\n const boxed = userCode(\n () =>\n container instanceof Number || container instanceof String || container instanceof Boolean,\n );\n if (boxed) return userCode(() => JSON.stringify(container));\n if (stack.includes(container)) return placeholder(CIRCULAR_REASON);\n if (stack.length >= MCP_FAKES_MAX_DEPTH) return placeholder(DEPTH_REASON);\n stack.push(container);\n try {\n if (userCode(() => Array.isArray(container))) {\n const array = container as readonly unknown[];\n const length = userCode(() => array.length);\n const items: string[] = [];\n for (let i = 0; i < length; i++) {\n items.push(renderMember(() => array[i], String(i), stack) ?? \"null\");\n }\n return `[${items.join(\",\")}]`;\n }\n const record = container as Record<string, unknown>;\n const members: string[] = [];\n for (const k of userCode(() => ownKeys(record))) {\n const item = renderMember(() => record[k], k, stack);\n if (item !== undefined) members.push(`${JSON.stringify(k)}:${item}`);\n }\n return `{${members.join(\",\")}}`;\n } finally {\n stack.pop();\n }\n}\n\n/**\n * A thrown value as a message part: its text (user text: a Proxy trap's or a\n * `toJSON`'s message) JSON-quoted; never throws.\n */\nfunction describeThrown(err: unknown): MessageValue {\n try {\n return quote(err instanceof Error ? `${err.name}: ${err.message}` : String(err));\n } catch {\n return fixed(\"an unprintable value\");\n }\n}\n\n/**\n * A built-in `Object.prototype.toString` tag (`[object Date]`). Any other tag\n * can come from a user `Symbol.toStringTag`, so a message JSON-quotes it: it\n * then cannot pose as JSON structure or a `<...>` placeholder, and holds no\n * backslash that is not a JSON escape.\n */\nconst BUILTIN_TAG = /^\\[object [A-Za-z][A-Za-z0-9]*\\]$/;\n\n/** A `toString` tag as a message part: a built-in one as is, any other quoted. */\nfunction tagPart(tag: string): MessageValue {\n return BUILTIN_TAG.test(tag) ? fixed(tag) : quote(tag);\n}\n\n/**\n * A place in the caller's input that the boundary snapshot could not copy as\n * plain data. It replaces that value in the snapshot, so every later check\n * sees a non-plain value and reports its own rule with `reason`.\n */\nclass NotPlain {\n constructor(readonly reason: Message) {\n Object.freeze(this);\n }\n}\n\n/**\n * The input boundary: one plain-data copy of a caller's value, made once at\n * `McpFakeStore.add` / `validateMcpFakes` entry; every check after it reads\n * only the copy. It reads own, enumerable, string-keyed data properties only:\n * getters are never run and inherited fields never seen. Never throws. Where\n * the value is not plain data, the copy holds a `NotPlain`: a non-plain\n * object or array (`Date`, `Map`, a class instance, an object with a custom\n * prototype), a symbol key, an accessor property, a sparse array, an array\n * with a non-index key, a cycle, a function, symbol or bigint, or a value\n * whose reading throws (a hostile or revoked `Proxy`). Strings, numbers\n * (non-finite ones too), booleans, `null` and `undefined` are kept as is.\n * Copied objects have a `null` prototype.\n *\n * An object or array below `maxDepth` levels (the root is level 1) is not\n * read: the copy holds a \"nested deeper than `MCP_FAKES_MAX_DEPTH` levels\"\n * `NotPlain` there, so the copy never recurses deeper than that. Only the\n * reflective reads of the caller's value (`readShape`) are guarded by a\n * `catch`; a throw from aimock's own copy code is a bug and propagates.\n *\n * Each caller object is read once, and copied once per level it is reached\n * at: an object reached through several paths (shared references) is not\n * copied once per path, so the time is linear in the number of objects, not\n * exponential in the depth. The copy keeps that sharing. An object on a\n * cycle is still never copied without a placeholder somewhere under it.\n */\nfunction snapshotInput(value: unknown, maxDepth = MCP_FAKES_MAX_DEPTH): unknown {\n return snapshotValue(value, { maxDepth, ancestors: [], shapes: new Map(), copies: new Map() });\n}\n\n/** The state of one `snapshotInput` call. */\ninterface SnapshotState {\n maxDepth: number;\n /** The objects on the path from the root to the one being copied. */\n ancestors: object[];\n /** Each caller object's one `readShape`. */\n shapes: Map<object, Shape | NotPlain>;\n /** Each caller object's copy, by the level (`ancestors.length`) it was copied at. */\n copies: Map<object, Map<number, unknown>>;\n}\n\nfunction snapshotValue(value: unknown, state: SnapshotState): unknown {\n if (\n value === null ||\n value === undefined ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return value;\n }\n if (typeof value !== \"object\") {\n return new NotPlain(msg`not a JSON value (got ${fixed(typeof value)})`);\n }\n const { ancestors } = state;\n if (ancestors.includes(value)) return new NotPlain(msg`a circular reference`);\n const level = ancestors.length;\n if (level >= state.maxDepth) {\n return new NotPlain(DEPTH_REASON);\n }\n // A copy depends only on the object and its level (the depth limit). The\n // cycle check above can differ by path, but a copy of an object on a cycle\n // always holds a placeholder, so reusing it never hides the cycle.\n let byLevel = state.copies.get(value);\n if (byLevel?.has(level)) return byLevel.get(level);\n let shape = state.shapes.get(value);\n if (shape === undefined) {\n shape = readShape(value);\n state.shapes.set(value, shape);\n }\n if (shape instanceof NotPlain) return shape;\n ancestors.push(value);\n let copy: unknown;\n try {\n copy = copyShape(shape, state);\n } finally {\n ancestors.pop();\n }\n if (!byLevel) {\n byLevel = new Map();\n state.copies.set(value, byLevel);\n }\n byLevel.set(level, copy);\n return copy;\n}\n\n/** What `readShape` read of one caller object: its own enumerable data, in key order. */\ninterface Shape {\n isArray: boolean;\n /** Own enumerable string keys with their values (`ACCESSOR` for a getter). */\n data: Array<[string, unknown]>;\n /** An array's own `length`. */\n length: number;\n}\n\n/**\n * Every reflective read of one caller object, and nothing else: the only\n * code a hostile or revoked `Proxy` can make throw. A throw here is the\n * caller's value being unreadable, so it becomes a `NotPlain`.\n */\nfunction readShape(value: object): Shape | NotPlain {\n try {\n const isArray = Array.isArray(value);\n const proto: unknown = Object.getPrototypeOf(value);\n if (isArray ? proto !== Array.prototype : proto !== Object.prototype && proto !== null) {\n const tag = Object.prototype.toString.call(value);\n const what = fixed(isArray ? \"array\" : \"object\");\n return new NotPlain(msg`not a plain JSON ${what} (got ${tagPart(tag)})`);\n }\n const data: Array<[string, unknown]> = [];\n for (const key of Reflect.ownKeys(value)) {\n const desc = Reflect.getOwnPropertyDescriptor(value, key);\n if (!desc?.enumerable) continue;\n if (typeof key === \"symbol\") return new NotPlain(msg`an object with a symbol key`);\n data.push([key, hasOwnKey(desc, \"value\") ? desc.value : ACCESSOR]);\n }\n const lengthDesc = isArray ? Reflect.getOwnPropertyDescriptor(value, \"length\") : undefined;\n const length = typeof lengthDesc?.value === \"number\" ? lengthDesc.value : 0;\n return { isArray, data, length };\n } catch (err) {\n return new NotPlain(msg`an unreadable value (reading it threw ${describeThrown(err)})`);\n }\n}\n\n/**\n * Most holes a sparse array may have and still be copied element by element.\n * Its `length` costs the caller nothing, so a longer one is not walked.\n */\nconst SPARSE_HOLE_LIMIT = 10_000;\n\n/**\n * Copy what `readShape` read; recurses through `snapshotValue`. A hole in a\n * sparse array becomes a placeholder in its own place, so the array is still\n * an array and every other element is still checked.\n */\nfunction copyShape(shape: Shape, state: SnapshotState): unknown {\n const { data, length } = shape;\n if (shape.isArray) {\n const own = new Map(data);\n for (const [key] of data) {\n const n = Number(key);\n if (key !== String(n) || !Number.isInteger(n) || n < 0 || n >= length) {\n return new NotPlain(msg`an array with a non-index key ${quote(key)}`);\n }\n }\n const holes = length - own.size;\n if (holes > SPARSE_HOLE_LIMIT) {\n let hole = 0;\n while (own.has(String(hole))) hole += 1;\n return new NotPlain(msg`a sparse array with ${holes} holes (the first at [${hole}])`);\n }\n const out: unknown[] = [];\n for (let i = 0; i < length; i++) {\n const key = String(i);\n out.push(\n own.has(key)\n ? snapshotField(own.get(key), state)\n : new NotPlain(msg`a hole in a sparse array`),\n );\n }\n return out;\n }\n const out = Object.create(null) as Record<string, unknown>;\n for (const [key, item] of data) {\n Object.defineProperty(out, key, {\n value: snapshotField(item, state),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n return out;\n}\n\n/** Marks an accessor property in `readShape` (its getter is never run). */\nconst ACCESSOR: unique symbol = Symbol(\"accessor\");\n\nfunction snapshotField(item: unknown, state: SnapshotState): unknown {\n return item === ACCESSOR\n ? new NotPlain(msg`an accessor property (getters are not read)`)\n : snapshotValue(item, state);\n}\n\n/**\n * A copy of `value`, a snapshot copy, with every container below `levels`\n * levels (the value itself is level 1) replaced by the depth placeholder.\n * Used by `McpFakeStore.add` for a block of an array-form `mcpFakes`, whose\n * array is level 1. It does not change `value`: a snapshot can share one copy\n * between paths at different levels. Each container is copied once per level\n * (`memo`), so shared references stay linear.\n */\nfunction capDepth(\n value: unknown,\n levels: number,\n memo = new Map<object, Map<number, unknown>>(),\n): unknown {\n if (value instanceof NotPlain || typeof value !== \"object\" || value === null) return value;\n if (levels < 1) return new NotPlain(DEPTH_REASON);\n let byLevel = memo.get(value);\n if (byLevel?.has(levels)) return byLevel.get(levels);\n let out: unknown;\n if (Array.isArray(value)) {\n out = value.map((item: unknown) => capDepth(item, levels - 1, memo));\n } else {\n const src = value as Record<string, unknown>;\n const obj = Object.create(null) as Record<string, unknown>;\n for (const key of ownKeys(src)) {\n Object.defineProperty(obj, key, {\n value: capDepth(src[key], levels - 1, memo),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n out = obj;\n }\n if (!byLevel) {\n byLevel = new Map();\n memo.set(value, byLevel);\n }\n byLevel.set(levels, out);\n return out;\n}\n\n/**\n * Freeze `value` and everything under it (plain data only). A frozen object\n * is not walked again: this module freezes children before their parent, and\n * a shared child is then frozen once.\n */\nfunction deepFreeze<T>(value: T): T {\n if (typeof value === \"object\" && value !== null && !Object.isFrozen(value)) {\n const obj = value as Record<string, unknown>;\n for (const key of ownKeys(obj)) deepFreeze(obj[key]);\n Object.freeze(value);\n }\n return value;\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\n/** A field is present when it is an own key whose value is not `undefined`. */\nfunction has(raw: Record<string, unknown>, key: string): boolean {\n return hasOwnKey(raw, key) && raw[key] !== undefined;\n}\n\n/** Own keys whose value is not `undefined` (an `undefined` field is absent). */\nfunction presentKeys(raw: Record<string, unknown>): string[] {\n return ownKeys(raw).filter((key) => raw[key] !== undefined);\n}\n\n/**\n * The first place under `value` that is not plain JSON (as `JSON.parse` could\n * produce it), or `null`. An object field set to `undefined` is absent, as in\n * `JSON.stringify`. Rejects an `undefined` array item, functions, symbols,\n * bigints, non-finite numbers, sparse-array holes and objects whose prototype\n * is not `Object.prototype` or `null` (`Date`, `Map`, class instances). Its\n * input is always the input snapshot, which holds no cycle (`snapshotInput`\n * puts a placeholder there) and no container deeper than\n * `MCP_FAKES_MAX_DEPTH`, so the recursion is bounded. A container found clean\n * is not checked again (`clean`), so a shared one is walked once.\n */\nfunction jsonProblem(\n value: unknown,\n path: string,\n clean: WeakSet<object> = new WeakSet(),\n): Message | null {\n if (value instanceof NotPlain) return msg`${pathPart(path)} is ${value.reason}`;\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return null;\n if (typeof value === \"number\") {\n return Number.isFinite(value)\n ? null\n : msg`${pathPart(path)} must be a finite number, got ${shown(value)}`;\n }\n if (typeof value !== \"object\") {\n return msg`${pathPart(path)} is not a JSON value (got ${fixed(typeof value)})`;\n }\n if (clean.has(value)) return null;\n let problem: Message | null = null;\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length && !problem; i++) {\n problem = hasOwnKey(value, String(i))\n ? jsonProblem(value[i], `${path}[${i}]`, clean)\n : msg`${pathPart(`${path}[${i}]`)} is a hole in a sparse array`;\n }\n } else {\n const proto: unknown = Object.getPrototypeOf(value);\n if (proto !== Object.prototype && proto !== null) {\n const tag = Object.prototype.toString.call(value);\n problem = msg`${pathPart(path)} must be a plain JSON object, got ${tagPart(tag)}`;\n } else {\n const obj = value as Record<string, unknown>;\n for (const key of presentKeys(obj)) {\n problem = jsonProblem(obj[key], pathKey(path, key), clean);\n if (problem) break;\n }\n }\n }\n if (!problem) clean.add(value);\n return problem;\n}\n\n/**\n * Deep copy of a plain JSON value (checked by `jsonProblem`), optionally\n * deep-frozen. Keys are defined, not assigned, so `\"__proto__\"` stays data;\n * a field set to `undefined` is left out. A container reached through several\n * paths is copied once (`memo`), and the copy shares it the same way.\n */\nfunction copyJson(value: unknown, freeze = false, memo = new Map<object, unknown>()): unknown {\n if (typeof value !== \"object\" || value === null) return value;\n if (memo.has(value)) return memo.get(value);\n let out: unknown;\n if (Array.isArray(value)) {\n out = value.map((item: unknown) => copyJson(item, freeze, memo));\n } else {\n const src = value as Record<string, unknown>;\n const obj: Record<string, unknown> = {};\n for (const key of presentKeys(src)) {\n Object.defineProperty(obj, key, {\n value: copyJson(src[key], freeze, memo),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n out = obj;\n }\n if (freeze) Object.freeze(out);\n memo.set(value, out);\n return out;\n}\n\n/** Block id: `<source><load>[<block>]`, with no `[<block>]` for a single-object `mcpFakes`. */\nexport function blockIdOf(source: string, loadSuffix: string, blockIndex: number | null): string {\n return `${source}${loadSuffix}${blockIndex === null ? \"\" : `[${blockIndex}]`}`;\n}\n\nfunction localOf(toolName: string, index: number, userId: unknown): string {\n return isNonEmptyString(userId) ? userId : `${toolName}#${index}`;\n}\n\n/**\n * Entry ids of one block: `<source><load>[<block>]:<local>`, where `local` is\n * the user `id` or `<tool>#<index>`. Flat, in tool order then `calls` order.\n */\nexport function entryIds(\n block: {\n blockIndex: number | null;\n tools: ReadonlyArray<{ name: string; calls: ReadonlyArray<{ id?: unknown }> }>;\n },\n source: string,\n loadSuffix: string,\n): string[] {\n const prefix = blockIdOf(source, loadSuffix, block.blockIndex);\n const ids: string[] = [];\n for (const tool of block.tools) {\n tool.calls.forEach((call, index) => {\n ids.push(`${prefix}:${localOf(tool.name, index, call.id)}`);\n });\n }\n return ids;\n}\n\nfunction tierOf(scope: McpFakeScope): McpFakeTier {\n if (scope === \"shared\") return \"shared\";\n if (scope.testId !== undefined && scope.context !== undefined) return \"testId+context\";\n if (scope.testId !== undefined) return \"testId\";\n return \"context\";\n}\n\n/** Scope match: exact, case-sensitive, no normalization; `\"shared\"` matches every request. */\nfunction scopeMatches(scope: McpFakeScope, identity: McpFakeIdentity): boolean {\n if (scope === \"shared\") return true;\n if (scope.testId !== undefined && identity.testId !== scope.testId) return false;\n if (scope.context !== undefined && identity.context !== scope.context) return false;\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Validation (bad-block cases (a)-(j), shadowed-entry warnings)\n\ninterface BlockContext {\n source: string;\n load: string;\n blockIndex: number | null;\n blockId: string;\n}\n\n/** A bad-block letter, `a` to `j`: one with a `mcp-fakes/bad-block:<letter>` rule. */\ntype BadBlockLetter = McpFakesLoadRule extends infer R\n ? R extends `mcp-fakes/bad-block:${infer L}`\n ? L\n : never\n : never;\n\nfunction badBlock(\n ctx: { source: string | null; blockId: string | null },\n letter: BadBlockLetter,\n detail: Message,\n entryId: string | null = null,\n): FixtureLoadError {\n return new FixtureLoadError({\n rule: `mcp-fakes/bad-block:${letter}`,\n file: ctx.source,\n blockId: ctx.blockId,\n entryId,\n detail,\n });\n}\n\n/** Every scope error goes to `errors`; returns the scope only when it is clean. */\nfunction validateScope(\n raw: unknown,\n ctx: BlockContext,\n errors: FixtureLoadError[],\n): McpFakeScope | null {\n if (raw === undefined) {\n errors.push(badBlock(ctx, \"a\", msg`block has no scope`));\n return null;\n }\n if (raw === \"shared\") return \"shared\";\n if (!isPlainObject(raw)) {\n errors.push(badBlock(ctx, \"b\", msg`scope must be \"shared\" or an object, got ${shown(raw)}`));\n return null;\n }\n const before = errors.length;\n for (const key of presentKeys(raw)) {\n if (!SCOPE_KEYS.has(key))\n errors.push(badBlock(ctx, \"b\", msg`scope has unknown key ${shown(key)}`));\n }\n if (!has(raw, \"testId\") && !has(raw, \"context\")) {\n errors.push(badBlock(ctx, \"b\", msg`scope object has neither testId nor context`));\n }\n for (const key of [\"testId\", \"context\"] as const) {\n if (has(raw, key) && !isNonEmptyString(raw[key])) {\n errors.push(\n badBlock(\n ctx,\n \"b\",\n msg`scope.${fixed(key)} must be a non-empty string, got ${shown(raw[key])}`,\n ),\n );\n }\n }\n if (errors.length > before) return null;\n const testId = raw.testId as string | undefined;\n const context = raw.context as string | undefined;\n if (testId !== undefined && context !== undefined) return Object.freeze({ testId, context });\n if (testId !== undefined) return Object.freeze({ testId });\n return Object.freeze({ context: context as string });\n}\n\n// ---------------------------------------------------------------------------\n// `tools/call` result and tool-definition shapes\n//\n// A fake's `result` must be a `CallToolResult` that the `@modelcontextprotocol/sdk`\n// 1.31 client accepts, and a fake tool a `Tool` its `tools/list` accepts. The\n// checks are the SDK client rules that a bad value breaks: the content array,\n// each item's `type` and required fields, `isError`, `structuredContent`,\n// base64 `data` / `blob`, the `Annotations` and `Icon` value rules, the result\n// `_meta` keys the SDK reads, and `inputSchema.type`. The SDK differential\n// test (mcp-fakes-sdk-differential.test.ts) checks them against the SDK\n// schemas. Two checks are aimock's own and stricter than SDK 1.31:\n// - A full result must have a `content` array. The SDK defaults a missing\n// `content` to `[]`, but here an object with `isError` or\n// `structuredContent` and no `content` is far more likely a mistake (or\n// structured data meant to be served as is) than an empty answer.\n// - Each `inputSchema.properties` value must be a JSON object. The SDK\n// accepts any non-null object, arrays included, but a JSON Schema property\n// schema is an object, and an array there is a fixture mistake.\n// Only the full-result envelope is a closed format (a misspelled `isError`\n// must not reach a client as a success); unknown keys inside a content item\n// pass through, as the SDK client ignores them.\n\n/** A check of one value; returns a problem or `null`. */\ntype FieldCheck = (value: unknown, path: string) => Message | null;\n\nconst mustBeString: FieldCheck = (v, p) =>\n typeof v === \"string\" ? null : msg`${pathPart(p)} must be a string, got ${shown(v)}`;\n\nconst mustBeNumber: FieldCheck = (v, p) =>\n typeof v === \"number\" ? null : msg`${pathPart(p)} must be a number, got ${shown(v)}`;\n\nconst mustBeBoolean: FieldCheck = (v, p) =>\n typeof v === \"boolean\" ? null : msg`${pathPart(p)} must be a boolean, got ${shown(v)}`;\n\nconst mustBeObject: FieldCheck = (v, p) =>\n isPlainObject(v) ? null : msg`${pathPart(p)} must be a JSON object, got ${shown(v)}`;\n\n/** Base64 as the SDK's `Base64Schema` accepts it (`atob` does not throw). */\nconst mustBeBase64: FieldCheck = (v, p) => {\n if (typeof v === \"string\") {\n try {\n atob(v);\n return null;\n } catch {\n // not base64: fall through\n }\n }\n return msg`${pathPart(p)} must be a base64 string, got ${shown(v)}`;\n};\n\nfunction oneOf(values: readonly string[]): FieldCheck {\n const list = values.map((v) => quoteJson(v)).join(\", \");\n return (v, p) =>\n typeof v === \"string\" && values.includes(v)\n ? null\n : msg`${pathPart(p)} must be one of ${fixed(list)}, got ${shown(v)}`;\n}\n\nfunction arrayOf(item: FieldCheck, noun = \"an array\"): FieldCheck {\n return (v, p) => {\n if (!Array.isArray(v)) return msg`${pathPart(p)} must be ${fixed(noun)}, got ${shown(v)}`;\n for (let i = 0; i < v.length; i++) {\n const problem = item(v[i], `${p}[${i}]`);\n if (problem) return problem;\n }\n return null;\n };\n}\n\nconst mustBeStringArray = arrayOf(mustBeString, \"an array of strings\");\n\n/**\n * An object with `required` fields and `optional` ones (an `undefined` field\n * is absent). Other keys are not checked.\n */\nfunction shape(\n required: Readonly<Record<string, FieldCheck>>,\n optional: Readonly<Record<string, FieldCheck>> = {},\n): FieldCheck {\n return (v, p) => {\n if (!isPlainObject(v)) return msg`${pathPart(p)} must be a JSON object, got ${shown(v)}`;\n for (const key of ownKeys(required)) {\n const check = required[key];\n const problem = check(has(v, key) ? v[key] : undefined, pathKey(p, key));\n if (problem) return problem;\n }\n for (const key of ownKeys(optional)) {\n const check = optional[key];\n if (!has(v, key)) continue;\n const problem = check(v[key], pathKey(p, key));\n if (problem) return problem;\n }\n return null;\n };\n}\n\n/**\n * RFC 3339 date-time with seconds and a `Z` or `±hh:mm` offset: the pattern of\n * zod's `z.iso.datetime({ offset: true })`, which the SDK uses for\n * `Annotations.lastModified`.\n */\nconst ISO_DATETIME =\n /^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$/;\n\nconst ANNOTATIONS = shape(\n {},\n {\n audience: arrayOf(oneOf([\"user\", \"assistant\"])),\n priority: (v, p) =>\n typeof v === \"number\" && v >= 0 && v <= 1\n ? null\n : msg`${pathPart(p)} must be a number from 0 to 1, got ${shown(v)}`,\n lastModified: (v, p) =>\n typeof v === \"string\" && ISO_DATETIME.test(v)\n ? null\n : msg`${pathPart(p)} must be an ISO 8601 date-time with seconds and an offset, got ${shown(v)}`,\n },\n);\n\nconst ICON = shape(\n { src: mustBeString },\n { mimeType: mustBeString, sizes: mustBeStringArray, theme: oneOf([\"light\", \"dark\"]) },\n);\n\n/** MCP `TextResourceContents` / `BlobResourceContents`: exactly one of text / blob. */\nconst RESOURCE_CONTENTS: FieldCheck = (v, p) => {\n if (!isPlainObject(v)) {\n return msg`${pathPart(p)} must be a JSON object with uri and text or blob, got ${shown(v)}`;\n }\n if (has(v, \"text\") === has(v, \"blob\"))\n return msg`${pathPart(p)} needs exactly one of text / blob`;\n const body: Record<string, FieldCheck> = has(v, \"text\")\n ? { text: mustBeString }\n : { blob: mustBeBase64 };\n return shape({ uri: mustBeString, ...body }, { mimeType: mustBeString, _meta: mustBeObject })(\n v,\n p,\n );\n};\n\n/** Fields every content block may carry. */\nconst CONTENT_COMMON = { annotations: ANNOTATIONS, _meta: mustBeObject };\n\n/** Each MCP content block type, with its fields. */\nconst CONTENT_TYPES = new Map<string, FieldCheck>([\n [\"text\", shape({ text: mustBeString }, CONTENT_COMMON)],\n [\"image\", shape({ data: mustBeBase64, mimeType: mustBeString }, CONTENT_COMMON)],\n [\"audio\", shape({ data: mustBeBase64, mimeType: mustBeString }, CONTENT_COMMON)],\n [\n \"resource_link\",\n shape(\n { uri: mustBeString, name: mustBeString },\n {\n title: mustBeString,\n description: mustBeString,\n mimeType: mustBeString,\n size: mustBeNumber,\n icons: arrayOf(ICON),\n ...CONTENT_COMMON,\n },\n ),\n ],\n [\"resource\", shape({ resource: RESOURCE_CONTENTS }, CONTENT_COMMON)],\n]);\n\nconst CONTENT_TYPE_LIST = [...CONTENT_TYPES.keys()].map((type) => quoteJson(type)).join(\", \");\n\n/** One MCP content block, checked by its `type`. */\nconst CONTENT_BLOCK: FieldCheck = (v, p) => {\n if (!isPlainObject(v)) return msg`${pathPart(p)} must be a content object, got ${shown(v)}`;\n const check = typeof v.type === \"string\" ? CONTENT_TYPES.get(v.type) : undefined;\n if (!check)\n return msg`${pathPart(p)}.type must be one of ${fixed(CONTENT_TYPE_LIST)}, got ${shown(v.type)}`;\n return check(v, p);\n};\n\nconst CONTENT = arrayOf(CONTENT_BLOCK, \"an array of content blocks\");\n\n/** The SDK client's `RequestMeta` keys on a result's `_meta`; other keys pass through. */\nconst RESULT_META = shape(\n {},\n {\n progressToken: (v, p) =>\n typeof v === \"string\" || Number.isSafeInteger(v)\n ? null\n : msg`${pathPart(p)} must be a string or an integer, got ${shown(v)}`,\n \"io.modelcontextprotocol/related-task\": shape({ taskId: mustBeString }),\n },\n);\n\n/**\n * The keys of a full `CallToolResult`. An object `result` with any of\n * them is that form, and must have a `content` array; any other object is\n * structured data.\n */\nconst FULL_RESULT_KEYS = new Set([\"content\", \"isError\", \"structuredContent\", \"_meta\"]);\n\nconst FULL_RESULT = shape(\n { content: CONTENT },\n { isError: mustBeBoolean, structuredContent: mustBeObject, _meta: RESULT_META },\n);\n\nfunction isFullResult(obj: Record<string, unknown>): boolean {\n return [...FULL_RESULT_KEYS].some((key) => has(obj, key));\n}\n\n/**\n * A valid `result`: a string; a content array; a full `CallToolResult` (`content`\n * array, optional boolean `isError`, optional object `structuredContent` and\n * `_meta`, nothing else); or a JSON object with none of those keys (served as\n * text plus `structuredContent`).\n */\nfunction validateResult(result: unknown): Message | null {\n if (typeof result === \"string\") return null;\n if (!Array.isArray(result) && !isPlainObject(result)) {\n return msg`result must be a string, a content array or an object, got ${shown(result)}`;\n }\n const json = jsonProblem(result, \"result\");\n if (json) return json;\n if (Array.isArray(result)) return CONTENT(result, \"result\");\n if (!isFullResult(result)) return null;\n for (const key of presentKeys(result)) {\n if (!FULL_RESULT_KEYS.has(key)) return msg`result has unknown key ${shown(key)}`;\n }\n return FULL_RESULT(result, \"result\");\n}\n\n/**\n * MCP `Tool.inputSchema`: a JSON Schema object with `type: \"object\"` at the\n * root; `properties`, when present, maps names to schema objects, and\n * `required`, when present, lists names. Any other JSON Schema keyword is\n * allowed.\n */\nconst INPUT_SCHEMA = shape(\n {\n type: (v, p) => (v === \"object\" ? null : msg`${pathPart(p)} must be \"object\", got ${shown(v)}`),\n },\n {\n properties: (v, p) => {\n if (!isPlainObject(v)) return mustBeObject(v, p);\n for (const key of presentKeys(v)) {\n const problem = mustBeObject(v[key], pathKey(p, key));\n if (problem) return problem;\n }\n return null;\n },\n required: mustBeStringArray,\n },\n);\n\nfunction inputSchemaProblem(schema: unknown): Message | null {\n if (!isPlainObject(schema)) return mustBeObject(schema, \"inputSchema\");\n return jsonProblem(schema, \"inputSchema\") ?? INPUT_SCHEMA(schema, \"inputSchema\");\n}\n\n/**\n * Validate one call entry of the input snapshot. Every error goes to\n * `errors`; returns its entry id whether or not it is clean, so that the\n * block's entry-id uniqueness check also sees invalid entries, and the frozen call\n * only when it is clean. `toolName` is the tool's name, or a `tools[<i>]`\n * placeholder when that name is invalid.\n */\nfunction validateCall(\n raw: unknown,\n toolName: string,\n label: Message,\n index: number,\n ctx: BlockContext,\n errors: FixtureLoadError[],\n): { entryId: string; call: ValidatedCall | null } {\n const idRaw = isPlainObject(raw) ? raw.id : undefined;\n const entryId = `${ctx.blockId}:${localOf(toolName, index, idRaw)}`;\n const where = msg`${label} calls[${index}]`;\n const bad = (letter: BadBlockLetter, detail: Message): void => {\n errors.push(badBlock(ctx, letter, msg`${where} ${detail}`, entryId));\n };\n if (!isPlainObject(raw)) {\n bad(\"d\", msg`must be an object, got ${shown(raw)}`);\n return { entryId, call: null };\n }\n const before = errors.length;\n for (const key of presentKeys(raw)) {\n if (!CALL_KEYS.has(key)) bad(\"h\", msg`has unknown key ${shown(key)}`);\n }\n if (has(raw, \"id\") && !isNonEmptyString(raw.id)) {\n bad(\"d\", msg`id must be a non-empty string, got ${shown(raw.id)}`);\n }\n if (has(raw, \"anyArgs\") && raw.anyArgs !== true) {\n bad(\"j\", msg`anyArgs must be true, got ${shown(raw.anyArgs)}`);\n }\n const hasArgs = has(raw, \"args\");\n const hasAnyArgs = has(raw, \"anyArgs\");\n if (hasArgs === hasAnyArgs) bad(\"d\", msg`needs exactly one of args / anyArgs`);\n if (hasArgs) {\n const problem = isPlainObject(raw.args)\n ? jsonProblem(raw.args, \"args\")\n : msg`args must be a JSON object, got ${shown(raw.args)}`;\n if (problem) bad(\"d\", problem);\n }\n const hasResult = has(raw, \"result\");\n const hasError = has(raw, \"error\");\n if (hasResult === hasError) bad(\"d\", msg`needs exactly one of result / error`);\n if (hasError && typeof raw.error !== \"string\") {\n bad(\"d\", msg`error must be a string, got ${shown(raw.error)}`);\n }\n if (hasResult) {\n const problem = validateResult(raw.result);\n if (problem) bad(\"d\", problem);\n }\n if (errors.length > before) return { entryId, call: null };\n // Frozen copies of the snapshot: nothing the store keeps can be changed.\n const match: McpFakeCallMatch = hasArgs\n ? { args: copyJson(raw.args, true) as Record<string, unknown> }\n : { anyArgs: true };\n const answer: McpFakeCallAnswer = hasResult\n ? { result: copyJson(raw.result, true) as McpFakeResult }\n : { error: raw.error as string };\n return { entryId, call: Object.freeze({ id: entryId, index, ...match, ...answer }) };\n}\n\n/**\n * Validate one tool of the input snapshot. Every error goes to `errors`, and\n * the entry ids of all its calls (valid or not; with an invalid tool name,\n * only the user ids) to `entryIds`; returns the frozen tool only when it is\n * clean.\n */\nfunction validateTool(\n raw: unknown,\n index: number,\n ctx: BlockContext,\n errors: FixtureLoadError[],\n entryIds: string[],\n): ValidatedTool | null {\n const where = `tools[${index}]`;\n const place = msg`tools[${index}]`;\n if (!isPlainObject(raw)) {\n errors.push(badBlock(ctx, \"g\", msg`${place} must be an object, got ${shown(raw)}`));\n return null;\n }\n const before = errors.length;\n for (const key of presentKeys(raw)) {\n if (!TOOL_KEYS.has(key)) {\n errors.push(badBlock(ctx, \"h\", msg`${place} has unknown key ${shown(key)}`));\n }\n }\n const name = isNonEmptyString(raw.name) ? raw.name : null;\n if (name === null) {\n errors.push(badBlock(ctx, \"g\", msg`${place} needs a string name, got ${shown(raw.name)}`));\n }\n // Where the tool's problems are: its name, or its place when the name is invalid.\n const tw = name === null ? place : msg`tool ${quote(name)}`;\n if (has(raw, \"description\") && typeof raw.description !== \"string\") {\n errors.push(\n badBlock(ctx, \"g\", msg`${tw} description must be a string, got ${shown(raw.description)}`),\n );\n }\n if (has(raw, \"inputSchema\")) {\n const problem = inputSchemaProblem(raw.inputSchema);\n if (problem) {\n errors.push(badBlock(ctx, \"g\", msg`${tw} ${problem}`));\n }\n }\n const calls: ValidatedCall[] = [];\n if (!Array.isArray(raw.calls) || raw.calls.length === 0) {\n errors.push(\n badBlock(ctx, \"g\", msg`${tw} calls must be a non-empty array, got ${shown(raw.calls)}`),\n );\n } else {\n raw.calls.forEach((rawCall: unknown, i: number) => {\n const { entryId, call } = validateCall(rawCall, name ?? where, tw, i, ctx, errors);\n // With an invalid name, a default id is a stand-in (`tools[<i>]#<n>`)\n // that names the entry in its errors but is not an id the user meant to\n // declare, so it is left out of the uniqueness checks. A user `id` does\n // not depend on the name and is checked.\n if (name !== null || (isPlainObject(rawCall) && isNonEmptyString(rawCall.id))) {\n entryIds.push(entryId);\n }\n if (call) calls.push(call);\n });\n }\n if (errors.length > before || name === null) return null;\n const tool: {\n name: string;\n description?: string;\n inputSchema?: Record<string, unknown>;\n calls: readonly ValidatedCall[];\n } = { name, calls: Object.freeze(calls) };\n if (typeof raw.description === \"string\") tool.description = raw.description;\n if (isPlainObject(raw.inputSchema)) {\n tool.inputSchema = copyJson(raw.inputSchema, true) as Record<string, unknown>;\n }\n return Object.freeze(tool);\n}\n\n/** What `validateBlock` found for one block. */\ninterface BlockOutcome {\n /** The deeply frozen block, or `null` when it has any error. */\n block: ValidatedBlock | null;\n /**\n * Distinct entry ids of every call the block declares, valid or not, for\n * the caller's cross-block uniqueness check.\n */\n entryIds: string[];\n /** Shadowed-entry warnings; only a clean block has any. */\n warnings: McpFakeIssue[];\n}\n\n/**\n * Validate one block of the input snapshot. Every check runs and each problem\n * goes to `errors` (no first-stop), with two limits: a block, tool or call\n * entry that is not an object is not checked further, and one `result` or\n * `inputSchema` value reports only its first problem. Entry-id uniqueness\n * inside the block is checked here over every declared entry, valid or not;\n * uniqueness across blocks is the caller's.\n */\nfunction validateBlock(\n raw: unknown,\n source: string,\n blockIndex: number | null,\n load: string,\n errors: FixtureLoadError[],\n): BlockOutcome {\n const ctx: BlockContext = {\n source,\n load,\n blockIndex,\n blockId: blockIdOf(source, load, blockIndex),\n };\n if (!isPlainObject(raw)) {\n errors.push(badBlock(ctx, \"i\", msg`mcpFakes block must be an object, got ${shown(raw)}`));\n return { block: null, entryIds: [], warnings: [] };\n }\n const before = errors.length;\n for (const key of presentKeys(raw)) {\n if (!BLOCK_KEYS.has(key))\n errors.push(badBlock(ctx, \"h\", msg`block has unknown key ${shown(key)}`));\n }\n const scope = validateScope(raw.scope, ctx, errors);\n\n let undeclared: McpFakeUndeclaredPolicy | undefined;\n if (has(raw, \"undeclaredTools\")) {\n if (raw.undeclaredTools === \"allow\" || raw.undeclaredTools === \"deny\") {\n undeclared = raw.undeclaredTools;\n } else {\n errors.push(\n badBlock(\n ctx,\n \"g\",\n msg`undeclaredTools must be \"allow\" or \"deny\", got ${shown(raw.undeclaredTools)}`,\n ),\n );\n }\n }\n if (scope === \"shared\" && undeclared === \"deny\") {\n errors.push(badBlock(ctx, \"c\", msg`scope \"shared\" cannot have undeclaredTools \"deny\"`));\n }\n let mount = MCP_FAKES_DEFAULT_MOUNT;\n if (has(raw, \"mount\")) {\n if (typeof raw.mount === \"string\" && raw.mount.startsWith(\"/\")) {\n mount = raw.mount;\n } else {\n errors.push(\n badBlock(ctx, \"g\", msg`mount must be a string starting with \"/\", got ${shown(raw.mount)}`),\n );\n }\n }\n\n const tools: ValidatedTool[] = [];\n const declaredIds: string[] = [];\n if (!Array.isArray(raw.tools)) {\n errors.push(badBlock(ctx, \"g\", msg`tools must be an array, got ${shown(raw.tools)}`));\n } else if (raw.tools.length === 0) {\n // Bad block (g): an empty `tools` is allowed only on a scoped `deny` block,\n // where it closes the world. A block with `deny` and a bad scope reports\n // only the scope error; without `deny`, the empty `tools` is reported too.\n if (undeclared !== \"deny\" || scope === \"shared\") {\n errors.push(\n badBlock(\n ctx,\n \"g\",\n msg`tools is empty; an empty tools array (tools: []) is allowed only on a scoped (not \"shared\") block with undeclaredTools \"deny\"`,\n ),\n );\n }\n } else {\n // (e) is keyed on the raw name, so a duplicate is found even when the\n // first declaration is invalid. A duplicate's entries, user ids included,\n // are left out of the id-uniqueness checks (in the block, and across\n // blocks and the mount): its default ids repeat the first declaration's\n // by construction. The block already fails (e), so no load is lost.\n const names = new Set<string>();\n raw.tools.forEach((rawTool: unknown, i: number) => {\n const name = isPlainObject(rawTool) && isNonEmptyString(rawTool.name) ? rawTool.name : null;\n const duplicate = name !== null && names.has(name);\n if (duplicate) {\n errors.push(badBlock(ctx, \"e\", msg`tool ${quote(name)} is declared twice in one block`));\n } else if (name !== null) {\n names.add(name);\n }\n const tool = validateTool(rawTool, i, ctx, errors, duplicate ? [] : declaredIds);\n if (tool && !duplicate) tools.push(tool);\n });\n }\n\n // Entry-id uniqueness inside the block: every later occurrence of an id is an offender.\n const seen = new Set<string>();\n for (const id of declaredIds) {\n if (seen.has(id)) {\n errors.push(badBlock(ctx, \"f\", msg`entry id ${quote(id)} is not unique`, id));\n }\n seen.add(id);\n }\n const entryIds = [...seen];\n if (errors.length > before || scope === null) return { block: null, entryIds, warnings: [] };\n\n // Shadowed-entry warning: an args entry after an anyArgs entry of the same tool.\n const warnings: McpFakeIssue[] = [];\n for (const tool of tools) {\n let lastAny: ValidatedCall | null = null;\n for (const call of tool.calls) {\n if (call.anyArgs) {\n lastAny = call;\n } else if (lastAny) {\n warnings.push({\n file: source,\n blockId: ctx.blockId,\n entryId: call.id,\n message: build(\n msg`entry ${quote(call.id)} is shadowed until the preceding anyArgs entry ${quote(lastAny.id)} is consumed`,\n ),\n });\n }\n }\n }\n\n const block: ValidatedBlock = Object.freeze({\n source,\n load,\n blockIndex,\n blockId: ctx.blockId,\n scope,\n tier: tierOf(scope),\n mount,\n ...(undeclared !== undefined ? { undeclaredTools: undeclared } : {}),\n tools: Object.freeze(tools),\n });\n return { block, entryIds, warnings };\n}\n\n/**\n * Standalone validation of a raw `mcpFakes` value (one object, or an array of\n * blocks) from one `source`. It takes the plain-data snapshot of `raw`\n * (getters are not run, inherited fields not read) and reports every\n * bad-block case (a)-(j) found as a `FixtureLoadError` naming the source and\n * block; entry-id collisions inside a block are (f). Never throws. Ids use the\n * first-load form (empty `load`). The store does not use this function:\n * `McpFakeStore.add` runs the same per-block checks (`validateBlock`) with its\n * own load suffix, and adds the entry-id check across blocks (against the\n * mount and the earlier blocks of the same input). `blocks` holds only the\n * clean blocks (deeply frozen), `warnings` only their shadowed-entry warnings.\n */\nexport function validateMcpFakes(raw: unknown, source: string): McpFakesValidation {\n const errors: FixtureLoadError[] = [];\n const warnings: McpFakeIssue[] = [];\n const blocks: ValidatedBlock[] = [];\n const input = snapshotInput(raw);\n let items: Array<{ raw: unknown; blockIndex: number | null }>;\n if (Array.isArray(input) && input.length === 0) {\n // Bad block (i): an empty array declares nothing, so it fails loud.\n errors.push(badBlock({ source, blockId: null }, \"i\", msg`mcpFakes is an empty array`));\n return { blocks, errors, warnings };\n } else if (Array.isArray(input)) {\n items = input.map((item: unknown, i: number) => ({ raw: item, blockIndex: i }));\n } else if (isPlainObject(input)) {\n items = [{ raw: input, blockIndex: null }];\n } else {\n errors.push(\n badBlock(\n { source, blockId: null },\n \"i\",\n msg`mcpFakes must be an object or an array, got ${shown(input)}`,\n ),\n );\n return { blocks, errors, warnings };\n }\n // Entry ids of different blocks of one source cannot collide: each id\n // starts with its own `<source>[<i>]`. Collisions across sources, or with\n // blocks already loaded, are checked by `McpFakeStore.add`.\n for (const item of items) {\n const outcome = validateBlock(item.raw, source, item.blockIndex, \"\", errors);\n if (outcome.block) {\n blocks.push(outcome.block);\n warnings.push(...outcome.warnings);\n }\n }\n return { blocks, errors, warnings };\n}\n\nfunction blockEntryIds(block: ValidatedBlock): string[] {\n return block.tools.flatMap((t) => t.calls.map((c) => c.id));\n}\n\n// ---------------------------------------------------------------------------\n// `tools/call` result shapes\n\n/**\n * Turn a call entry's `result` or `error` into a `tools/call` result. The\n * returned object is a fresh copy the caller may change. A full\n * `CallToolResult` (validation guarantees any object with one of its keys\n * has a `content` array) is copied unchanged, with no `isError` added;\n * every other shape sets `isError`. Throws when the entry has\n * neither (validation makes that a bad block (d)).\n */\nexport function toCallToolResult(\n call: McpFakeDeepReadonly<McpFakeCallAnswer>,\n): McpFakeCallToolResult {\n if (call.error !== undefined) {\n return { content: [{ type: \"text\", text: call.error }], isError: true };\n }\n const result: unknown = call.result;\n if (result === undefined || result === null) {\n throw new Error(build(msg`toCallToolResult: call entry has neither result nor error`));\n }\n if (typeof result === \"string\") {\n return { content: [{ type: \"text\", text: result }], isError: false };\n }\n if (Array.isArray(result)) {\n return { content: copyJson(result) as unknown[], isError: false };\n }\n const obj = copyJson(result) as Record<string, unknown>;\n if (Array.isArray(obj.content)) {\n return { ...obj, content: obj.content as unknown[] };\n }\n return {\n content: [{ type: \"text\", text: JSON.stringify(obj) }],\n structuredContent: obj,\n isError: false,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Argument equality\n\nfunction jsonEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;\n return a.every((v, i) => jsonEqual(v, b[i]));\n }\n if (isPlainObject(a) && isPlainObject(b)) {\n const ak = ownKeys(a);\n const bk = ownKeys(b);\n if (ak.length !== bk.length) return false;\n return ak.every((k) => hasOwnKey(b, k) && jsonEqual(a[k], b[k]));\n }\n return false;\n}\n\n/**\n * Argument equality: key order ignored, array order matters, no coercion,\n * numbers equal as parsed JSON, absent `arguments` is `{}`, non-object\n * `arguments` never equals an `args` entry (only an `anyArgs` entry matches\n * it).\n */\nexport function mcpArgsEqual(expected: Record<string, unknown>, received: unknown): boolean {\n const actual = received === undefined ? {} : received;\n if (!isPlainObject(actual)) return false;\n return jsonEqual(expected, actual);\n}\n\n/**\n * `path` and one more key: `.key` for a short identifier, else `[<key>]` with\n * the key JSON-quoted whole. The path is cut once, where a message shows it\n * (`pathPart`).\n */\nfunction pathKey(path: string, key: string): string {\n return key.length <= MCP_FAKES_ECHO_LIMIT && /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)\n ? `${path}.${key}`\n : `${path}[${quoteJson(key)}]`;\n}\n\n/**\n * A JSON path (built by `pathKey`) as a message part: user data, cut as JSON\n * text, so the cut never splits an escape of a quoted key.\n */\nfunction pathPart(path: string): MessageValue {\n return jsonText(path);\n}\n\nfunction diffAt(path: string, expected: unknown, received: unknown): Message | null {\n if (Array.isArray(expected)) {\n if (!Array.isArray(received)) {\n return msg`${pathPart(path)}: expected an array, received ${shown(received)}`;\n }\n if (expected.length !== received.length) {\n return msg`${pathPart(path)}: expected an array of length ${expected.length}, received length ${received.length}`;\n }\n for (let i = 0; i < expected.length; i++) {\n const d = diffAt(`${path}[${i}]`, expected[i], received[i]);\n if (d) return d;\n }\n return null;\n }\n if (isPlainObject(expected)) {\n if (!isPlainObject(received)) {\n return msg`${pathPart(path)}: expected an object, received ${shown(received)}`;\n }\n for (const key of ownKeys(expected)) {\n const p = pathKey(path, key);\n if (!hasOwnKey(received, key)) {\n return msg`${pathPart(p)}: expected ${shown(expected[key])}, received nothing (key missing)`;\n }\n const d = diffAt(p, expected[key], received[key]);\n if (d) return d;\n }\n for (const key of ownKeys(received)) {\n if (!hasOwnKey(expected, key)) {\n return msg`${pathPart(pathKey(path, key))}: unexpected key, received ${shown(received[key])}`;\n }\n }\n return null;\n }\n if (expected === received) return null;\n return msg`${pathPart(path)}: expected ${shown(expected)}, received ${shown(received)}`;\n}\n\n/**\n * A JSON path to the first unequal value, with both values (the mismatch\n * detail). Returns `\"\"` when `mcpArgsEqual(expected, received)` holds. The\n * path and each value are cut at `MCP_FAKES_ECHO_LIMIT` chars and the whole\n * text at 1000, each part once.\n */\nexport function firstDifference(expected: Record<string, unknown>, received: unknown): string {\n const diff = diffAt(\"$\", expected, received === undefined ? {} : received);\n return diff ? build(diff, DIFF_LIMIT) : \"\";\n}\n\n/**\n * Approximate count of differences, used to pick the closest declared entry.\n * A key or array element present on one side only counts as 1, whatever its\n * subtree size.\n */\nfunction diffCount(expected: unknown, received: unknown): number {\n if (Array.isArray(expected) && Array.isArray(received)) {\n const n = Math.max(expected.length, received.length);\n let count = 0;\n for (let i = 0; i < n; i++) {\n if (i >= expected.length || i >= received.length) count += 1;\n else count += diffCount(expected[i], received[i]);\n }\n return count;\n }\n if (isPlainObject(expected) && isPlainObject(received)) {\n let count = 0;\n for (const key of new Set([...ownKeys(expected), ...ownKeys(received)])) {\n const inE = hasOwnKey(expected, key);\n const inR = hasOwnKey(received, key);\n count += inE && inR ? diffCount(expected[key], received[key]) : 1;\n }\n return count;\n }\n return jsonEqual(expected, received) ? 0 : 1;\n}\n\nfunction callMatches(call: ValidatedCall, received: unknown): boolean {\n return call.anyArgs === true || (call.args !== undefined && mcpArgsEqual(call.args, received));\n}\n\n// ---------------------------------------------------------------------------\n// The store (one per MCP mount)\n\nexport interface McpFakeStoreOptions {\n /**\n * FIFO cap on distinct test ids that keep consumption state; `0` is\n * unbounded. Default 500. A value that is not a non-negative safe integer\n * throws a `RangeError`.\n */\n maxTestIds?: number;\n}\n\nexport interface McpFakeSelection {\n tier: McpFakeTier;\n entries: Array<{ block: ValidatedBlock; entry: ValidatedCall }>;\n}\n\nexport class McpFakeStore {\n private blocks: ValidatedBlock[] = [];\n /** Entry id → the block id that owns it, for every loaded entry. */\n private ids = new Map<string, string>();\n /** Block id → its `source`, for every loaded block. */\n private blockIds = new Map<string, string>();\n /**\n * Consumption state: supplied test id → consumed entry ids. Map insertion\n * order is the FIFO order of the cap.\n */\n private consumed = new Map<string, Set<string>>();\n /** Consumed entry ids for requests with no test id. Never evicted. */\n private untagged = new Set<string>();\n /**\n * Test ids whose state the cap evicted. A claim from one of them, of a tool\n * an applicable block declares, is `evicted` until the test id is reset; a\n * mark never ages out, because a forgotten mark would silently replay\n * entries the test id already consumed. Memory stays bounded per evicted\n * test id: one id string, against the entry-id set the cap dropped. The set only grows with distinct test ids, and every\n * reset door clears it (`resetState`, `clear`). A cap of `0` evicts\n * nothing, so marks made under an earlier cap stay until reset.\n */\n private evicted = new Set<string>();\n /**\n * The last `<n>` of `code#<n>` / `control-api#<n>` used by a run-time\n * addition (see `nextRuntimeNumber`). Never rewound.\n */\n private runtimeAdds = 0;\n /**\n * The `<k>` of `@<k>`: loads per source string, skipping a `@<k>` that a\n * loaded block id already starts (see `add`). Never rewound.\n */\n private loadCounts = new Map<string, number>();\n private maxTestIds: number;\n\n constructor(options: McpFakeStoreOptions = {}) {\n this.maxTestIds = checkCap(options.maxTestIds ?? MCP_FAKES_DEFAULT_MAX_TEST_IDS);\n }\n\n /**\n * Set the FIFO cap on distinct test ids; an MCP mount can pass the\n * journal's `fixtureCountsMaxTestIdsCap`. A lower cap evicts the oldest test\n * ids at once. `0` is unbounded: nothing is evicted, and test ids already\n * marked evicted stay marked until reset. An invalid cap throws a\n * `RangeError` and leaves the cap unchanged.\n */\n setMaxTestIds(cap: number): void {\n this.maxTestIds = checkCap(cap);\n this.enforceCap();\n }\n\n /**\n * Take one plain-data snapshot of `sources` and `origin` (getters are not\n * run, inherited fields not read, holes, symbol keys, proxies that throw and\n * non-plain objects are errors), validate the whole snapshot, derive entry\n * ids and their counters, check that every block id and every entry id is\n * unique against the mount and inside the input (bad block (f), naming the\n * block that already owns the id and, for a block id, that block's source),\n * then append. Every block is checked,\n * valid or not (no first-stop; `validateBlock` says which checks stop\n * early). On any error, throws one `McpFakesAddError` carrying every error\n * found, and the warnings of the blocks that passed every check, and adds\n * nothing (no counter is consumed); it never throws anything else for a bad\n * input (a throw from a defect in aimock itself is not caught). An empty\n * input, an invalid `origin` or an invalid source item (not an object, an\n * empty `source`, a `blockIndex` that is not `null` or a non-negative\n * integer) is a bad block (i).\n *\n * With `kind: \"file\"`, consecutive sources with the same `source` string\n * and increasing `blockIndex` form one load (one `@<k>`). A load whose\n * derived block ids a loaded block already has (a file named `\"a@2\"`\n * starts the ids of `@2`; a file named `\"a[0]\"` has the id of block 0 of\n * the first load) takes the next free `@<k>`, so a file name never blocks\n * later loads of another source. A file loaded after the block whose id\n * its name spells is still the bad block (f). With a run-time origin,\n * blocks are numbered per `McpFakeAddOrigin`; a block given with a null\n * `blockIndex` keeps the single-object depth limit.\n */\n add(sources: readonly McpFakeSource[], origin: McpFakeAddOrigin): McpFakeAddResult {\n const originData = snapshotInput(origin);\n const kind = isPlainObject(originData) ? originData.kind : undefined;\n if (kind !== \"file\" && kind !== \"code\" && kind !== \"control-api\") {\n const detail = isPlainObject(originData)\n ? msg`origin.kind must be \"file\", \"code\" or \"control-api\", got ${shown(kind)}`\n : msg`origin must be an object { kind }, got ${shown(originData)}`;\n throw new McpFakesAddError([badBlock({ source: null, blockId: null }, \"i\", detail)], []);\n }\n const runtimeNumber = kind === \"file\" ? null : this.nextRuntimeNumber(kind);\n const runtimeSource = runtimeNumber === null ? null : `${kind}#${runtimeNumber}`;\n // The blocks sit two levels down (the array, then `{ source, blockIndex, raw }`),\n // so the snapshot counts the depth limit from each `raw`. A block of an\n // array-form `mcpFakes` (a non-null block index) is level 2, as in\n // `validateMcpFakes`; `capDepth` takes the one level more off it below.\n const input = snapshotInput(sources, MCP_FAKES_MAX_DEPTH + 2);\n if (!Array.isArray(input) || input.length === 0) {\n const detail = Array.isArray(input)\n ? msg`mcpFakes holds no blocks`\n : msg`the blocks to add must be an array, got ${shown(input)}`;\n throw new McpFakesAddError(\n [badBlock({ source: runtimeSource, blockId: null }, \"i\", detail)],\n [],\n );\n }\n\n const errors: FixtureLoadError[] = [];\n const warnings: McpFakeIssue[] = [];\n const accepted: ValidatedBlock[] = [];\n /** Entry id → owning block id, for this input. */\n const newIds = new Map<string, string>();\n /** Block id → source, for this input. */\n const newBlockIds = new Map<string, string>();\n const pendingLoads = new Map<string, number>();\n const items: Array<{\n position: number;\n source: string;\n blockIndex: number | null;\n raw: unknown;\n }> = [];\n input.forEach((item: unknown, position: number) => {\n const fail = (detail: Message, file: string | null = runtimeSource): void => {\n errors.push(\n badBlock({ source: file, blockId: null }, \"i\", msg`blocks[${position}] ${detail}`),\n );\n };\n if (!isPlainObject(item)) {\n fail(msg`must be an object { source, blockIndex, raw }, got ${shown(item)}`);\n return;\n }\n const { source, blockIndex } = item;\n // A run-time origin replaces `source`, so only a file source is checked.\n if (runtimeSource === null && !isNonEmptyString(source)) {\n fail(msg`source must be a non-empty string, got ${shown(source)}`);\n return;\n }\n const sourceText = typeof source === \"string\" ? source : \"\";\n const index =\n blockIndex === null ||\n (typeof blockIndex === \"number\" && Number.isSafeInteger(blockIndex) && blockIndex >= 0)\n ? blockIndex\n : undefined;\n if (index === undefined) {\n fail(\n msg`blockIndex must be null or a non-negative integer, got ${shown(blockIndex)}`,\n runtimeSource ?? sourceText,\n );\n return;\n }\n items.push({ position, source: sourceText, blockIndex: index, raw: item.raw });\n });\n const singleObject = input.length === 1 && items.length === 1 && items[0].blockIndex === null;\n\n /** Two consecutive file items with one source and a rising block index are one load. */\n const sameLoad = (\n prev: (typeof items)[number] | undefined,\n item: (typeof items)[number],\n ): boolean =>\n prev !== undefined &&\n prev.source === item.source &&\n prev.blockIndex !== null &&\n item.blockIndex !== null &&\n item.blockIndex > prev.blockIndex;\n let load = \"\";\n for (const [at, item] of items.entries()) {\n const source = runtimeSource ?? item.source;\n let blockIndex = item.blockIndex;\n if (runtimeSource === null) {\n if (!sameLoad(items[at - 1], item)) {\n // The block indices of this load, to check its derived block ids below.\n const indices: number[] = [];\n for (\n let j = at;\n j < items.length && (j === at || sameLoad(items[j - 1], items[j]));\n j++\n ) {\n const index = items[j].blockIndex;\n if (index !== null) indices.push(index);\n }\n let k = (pendingLoads.get(source) ?? this.loadCounts.get(source) ?? 0) + 1;\n // A file source can spell a block id this load derives: `\"a@2\"` (a\n // load suffix) or `\"a[0]\"` (a block index). Skip a taken `@<k>` as\n // `nextRuntimeNumber` skips a taken `<n>`: otherwise every later load\n // of `source` would collide, and fail, on the same block id.\n while (\n k > 1\n ? this.blockIdPrefixTaken(blockIdOf(source, `@${k}`, null), newBlockIds)\n : indices.some((index) => {\n const derived = blockIdOf(source, \"\", index);\n // Taken by a file whose name is that id (its first,\n // single-object load), not by a block that derives it.\n return (this.blockIds.get(derived) ?? newBlockIds.get(derived)) === derived;\n })\n )\n k += 1;\n pendingLoads.set(source, k);\n load = k === 1 ? \"\" : `@${k}`;\n }\n } else {\n blockIndex = singleObject ? null : item.position;\n }\n // The depth limit follows the form the block was given in: a block given\n // with a null block index is a single-object block (level 1), even when a\n // run-time add numbers it.\n const raw = item.blockIndex === null ? item.raw : capDepth(item.raw, MCP_FAKES_MAX_DEPTH - 1);\n const outcome = validateBlock(raw, source, blockIndex, load, errors);\n // Id uniqueness on the mount, for invalid blocks too: their ids are what the\n // user meant to declare, so a collision with them is reported now. A\n // `source` can spell another load's suffix (`\"a@2\"`), so block ids are\n // checked as well as entry ids. A block whose id is taken reports that\n // one collision, not one per entry: every entry id starts with it.\n const blockId = blockIdOf(source, load, blockIndex);\n const blockOwner = this.blockIds.get(blockId) ?? newBlockIds.get(blockId);\n let collided = blockOwner !== undefined;\n if (blockOwner !== undefined) {\n errors.push(\n badBlock(\n { source, blockId },\n \"f\",\n blockCollisionDetail(source, blockOwner, this.blockIds.has(blockId)),\n ),\n );\n } else {\n newBlockIds.set(blockId, source);\n }\n for (const id of outcome.entryIds) {\n const loaded = this.ids.get(id);\n const earlier = newIds.get(id);\n if (!newIds.has(id)) newIds.set(id, blockId);\n if (blockOwner !== undefined) continue;\n const where =\n loaded !== undefined\n ? msg`is already loaded on this mount, in block ${quote(loaded)}`\n : earlier !== undefined\n ? msg`collides with an entry of block ${quote(earlier)} earlier in the same input`\n : null;\n if (where === null) continue;\n errors.push(badBlock({ source, blockId }, \"f\", msg`entry id ${quote(id)} ${where}`, id));\n collided = true;\n }\n if (outcome.block && !collided) {\n accepted.push(outcome.block);\n warnings.push(...outcome.warnings);\n }\n }\n if (errors.length > 0) throw new McpFakesAddError(errors, warnings);\n\n for (const [source, k] of pendingLoads) this.loadCounts.set(source, k);\n if (runtimeNumber !== null) this.runtimeAdds = runtimeNumber;\n for (const [id, owner] of newIds) this.ids.set(id, owner);\n for (const [blockId, source] of newBlockIds) this.blockIds.set(blockId, source);\n this.blocks.push(...accepted);\n return { warnings };\n }\n\n /**\n * The `<n>` for the next run-time add of `kind`: one more than the last one\n * used, skipping any number whose `<kind>#<n>` already starts a loaded block\n * id (and so every entry id of that block). A file source may be spelled\n * `code#1`; without the skip, every later run-time add would collide with it\n * and fail, and a failed add does not advance `<n>`. Blocks loaded after a\n * run-time add still collide with it as usual (the later block fails).\n */\n private nextRuntimeNumber(kind: \"code\" | \"control-api\"): number {\n let n = this.runtimeAdds + 1;\n while (this.blockIdPrefixTaken(`${kind}#${n}`)) n += 1;\n return n;\n }\n\n /**\n * A loaded block id (or one in `pending`, the blocks earlier in the same\n * input) starts with `prefix` and does not go on with a digit, so `prefix`\n * would start a colliding block or entry id (`a@2` is taken by `a@2` and\n * `a@2[0]`, not by `a@23`).\n */\n private blockIdPrefixTaken(prefix: string, pending?: ReadonlyMap<string, string>): boolean {\n for (const ids of [this.blockIds, pending ?? new Map<string, string>()]) {\n for (const blockId of ids.keys()) {\n if (blockId.startsWith(prefix) && !/^[0-9]/.test(blockId.slice(prefix.length))) {\n return true;\n }\n }\n }\n return false;\n }\n\n /** Unload every fake and its state. The id counters (`<n>`, `<k>`) are kept. */\n clear(): void {\n this.blocks = [];\n this.ids.clear();\n this.blockIds.clear();\n this.resetState();\n }\n\n /**\n * Reset consumption state for one test id, or all. Also clears an\n * `evicted` mark. `MCP_FAKES_DEFAULT_TEST_ID` resets the untagged state as\n * well as an explicit test id of that name. That matches\n * `Journal.clearMatchCounts` (which `LLMock.resetMatchCounts` calls), where\n * untagged requests and an explicit `__default__` share one key.\n */\n resetState(testId?: string): void {\n if (testId === undefined) {\n this.consumed.clear();\n this.untagged.clear();\n this.evicted.clear();\n return;\n }\n this.consumed.delete(testId);\n this.evicted.delete(testId);\n if (testId === MCP_FAKES_DEFAULT_TEST_ID) this.untagged.clear();\n }\n\n /** Every entry id on this mount, in load order. */\n allEntryIds(): string[] {\n return this.blocks.flatMap(blockEntryIds);\n }\n\n /** The blocks whose scope matches `identity`, in load order. A frozen list of frozen blocks. */\n applicable(identity: McpFakeIdentity): readonly ValidatedBlock[] {\n return Object.freeze(this.blocks.filter((b) => scopeMatches(b.scope, identity)));\n }\n\n /** The candidate entries for `tool` from the most specific tier declaring it. */\n selectTier(tool: string, identity: McpFakeIdentity): McpFakeSelection | null {\n const blocks = this.applicable(identity);\n for (const tier of TIER_ORDER) {\n const entries: McpFakeSelection[\"entries\"] = [];\n for (const block of blocks) {\n if (block.tier !== tier) continue;\n const t = block.tools.find((x) => x.name === tool);\n if (t) for (const entry of t.calls) entries.push({ block, entry });\n }\n if (entries.length > 0) return { tier, entries };\n }\n return null;\n }\n\n /**\n * Find the first unconsumed matching entry of the selected tier (load order,\n * then `calls` order) and mark it consumed, synchronously (no `await`\n * between find and mark), so concurrent calls never share an entry. The\n * result is built and checked to serialize as JSON before the entry is\n * marked, so a result that cannot be sent throws and leaves the entry\n * unconsumed. An `anyArgs` entry answers any `arguments`, a non-object\n * value included; only an `args` entry needs an object.\n */\n claim(tool: string, args: unknown, identity: McpFakeIdentity): McpFakeClaim {\n const selection = this.selectTier(tool, identity);\n if (!selection) return Object.freeze({ kind: \"none\" });\n const testId = identity.testId;\n if (testId !== null && this.evicted.has(testId)) {\n return Object.freeze({ kind: \"evicted\", tool, testId, maxTestIds: this.maxTestIds });\n }\n const used = this.stateOf(testId);\n const received = args === undefined ? {} : args;\n\n for (const { block, entry } of selection.entries) {\n if (used?.has(entry.id)) continue;\n if (!callMatches(entry, received)) continue;\n let result: McpFakeCallToolResult;\n try {\n result = toCallToolResult(entry);\n } catch (err) {\n throw new Error(\n build(\n msg`MCP fake entry ${quote(entry.id)}: its tools/call result cannot be built: ${describeThrown(err)}`,\n ),\n { cause: err },\n );\n }\n try {\n JSON.stringify(result);\n } catch (err) {\n throw new Error(\n build(\n msg`MCP fake entry ${quote(entry.id)}: result cannot be serialized as JSON: ${describeThrown(err)}`,\n ),\n { cause: err },\n );\n }\n this.stateFor(testId).add(entry.id);\n return Object.freeze({ kind: \"answer\", tool, entry, block, tier: selection.tier, result });\n }\n\n const matching = selection.entries.filter(({ entry }) => callMatches(entry, received));\n if (matching.length > 0) {\n return Object.freeze({\n kind: \"exhausted\",\n tool,\n received,\n matchingDeclared: matching.length,\n matchingConsumed: matching.filter(({ entry }) => used?.has(entry.id)).length,\n matchingIds: Object.freeze(matching.map(({ entry }) => entry.id)),\n });\n }\n\n // Closest = lowest `diffCount`; a tie goes to the first candidate in\n // load/declaration order (the order claims use), hence the strict `<`.\n let closest: ValidatedCall | null = null;\n let best = Infinity;\n for (const { entry } of selection.entries) {\n if (!entry.args) continue;\n const score = diffCount(entry.args, received);\n if (score < best) {\n best = score;\n closest = entry;\n }\n }\n return Object.freeze({\n kind: \"mismatch\",\n tool,\n received,\n declared: deepFreeze(selection.entries.map(({ entry }) => declaredEntry(entry, used))),\n firstDifference: closest?.args ? firstDifference(closest.args, received) : \"\",\n });\n }\n\n /**\n * The undeclared-tool policy, first of: `override` (`null` or omitted falls\n * back to `identity.undeclared`, the request's or session's\n * `X-AIMock-MCP-Undeclared` / `?undeclared=` value) → `deny` when any\n * applicable scoped block says `deny` → `allow`.\n */\n policy(\n identity: McpFakeIdentity,\n override: McpFakeUndeclaredPolicy | null = null,\n ): McpFakeUndeclaredPolicy {\n const effective = override ?? identity.undeclared;\n if (effective) return effective;\n for (const block of this.applicable(identity)) {\n if (block.scope !== \"shared\" && block.undeclaredTools === \"deny\") return \"deny\";\n }\n return \"allow\";\n }\n\n /** Tool names any applicable block (any tier) declares, in load order. */\n declaredTools(identity: McpFakeIdentity): string[] {\n const names = new Set<string>();\n for (const block of this.applicable(identity)) for (const t of block.tools) names.add(t.name);\n return [...names];\n }\n\n /**\n * Fake tools for `tools/list`, metadata from the most specific\n * tier declaring each tool; inside that tier, the first block in load order\n * that declares it. A tool with no `inputSchema` lists `{ type: \"object\" }`.\n * Merging with registered tools is the mount's job.\n */\n listTools(identity: McpFakeIdentity): McpFakeToolListing[] {\n return this.declaredTools(identity).map((name) => {\n const selection = this.selectTier(name, identity);\n const tool = selection?.entries[0].block.tools.find((t) => t.name === name);\n const listing: McpFakeToolListing = {\n name,\n inputSchema: tool?.inputSchema\n ? (copyJson(tool.inputSchema) as Record<string, unknown>)\n : { type: \"object\" },\n };\n if (tool?.description !== undefined) listing.description = tool.description;\n return listing;\n });\n }\n\n /**\n * For `GET /__aimock/mcp/fakes`: applicable blocks with consumed state for\n * `testId`. For a test id the cap evicted, every block says `evicted: true`.\n * Deeply frozen.\n */\n snapshot(testId: string | null, context: string | null): readonly McpFakeBlockSnapshot[] {\n const used = this.stateOf(testId);\n const evicted = testId !== null && this.evicted.has(testId);\n const blocks = this.applicable({ testId, context, undeclared: null }).map((block) => ({\n blockId: block.blockId,\n source: block.source,\n mount: block.mount,\n scope: block.scope,\n undeclaredTools: block.undeclaredTools ?? \"allow\",\n evicted,\n tools: block.tools.map((t) => ({\n name: t.name,\n entries: t.calls.map((c) => declaredEntry(c, used)),\n })),\n }));\n return deepFreeze(blocks);\n }\n\n /** The consumed ids for `testId` (`null`: untagged), without creating state. */\n private stateOf(testId: string | null): ReadonlySet<string> | undefined {\n return testId === null ? this.untagged : this.consumed.get(testId);\n }\n\n private stateFor(testId: string | null): Set<string> {\n if (testId === null) return this.untagged;\n let set = this.consumed.get(testId);\n if (!set) {\n set = new Set();\n this.consumed.set(testId, set);\n this.enforceCap();\n }\n return set;\n }\n\n /**\n * FIFO cap: evict the oldest test ids until the cap holds, marking each\n * evicted. A cap of `0` evicts nothing. The marks are not capped (see\n * `evicted`).\n */\n private enforceCap(): void {\n if (this.maxTestIds === 0) return;\n for (const oldest of this.consumed.keys()) {\n if (this.consumed.size <= this.maxTestIds) break;\n this.consumed.delete(oldest);\n this.evicted.add(oldest);\n }\n }\n}\n\n/**\n * The detail of a block-id collision (bad block (f)). The message prefix\n * already names the block id, so the detail names the two sources.\n */\nfunction blockCollisionDetail(source: string, owner: string, loaded: boolean): Message {\n return loaded\n ? msg`block id (this block's source: ${quote(source)}) is already loaded on this mount by source ${quote(owner)}`\n : msg`block id (this block's source: ${quote(source)}) collides with a block earlier in the same input, from source ${quote(owner)}`;\n}\n\n/** The test-id cap: a non-negative safe integer, `0` meaning unbounded. Anything else throws. */\nfunction checkCap(cap: number): number {\n if (!Number.isSafeInteger(cap) || cap < 0) {\n throw new RangeError(\n build(\n msg`MCP fakes maxTestIds must be a non-negative integer (0 = unbounded), got ${shown(cap)}`,\n ),\n );\n }\n return cap;\n}\n\nfunction declaredEntry(\n entry: ValidatedCall,\n used: ReadonlySet<string> | undefined,\n): McpFakeDeclaredEntry {\n const consumed = used?.has(entry.id) ?? false;\n return entry.args\n ? { id: entry.id, args: copyJson(entry.args) as Record<string, unknown>, consumed }\n : { id: entry.id, anyArgs: true, consumed };\n}\n"],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ import { FixtureLoadError, FixtureLoadErrorJSON } from "./fixture-loader.cjs";
2
+ import { McpFakeCallMatch, McpFakeDeepReadonly, McpFakeScope, McpFakeUndeclaredPolicy } from "./types.cjs";
3
+
4
+ //#region src/mcp-fakes.d.ts
5
+
6
+ /**
7
+ * A validation warning: an `args` entry shadowed by an earlier `anyArgs` entry
8
+ * of the same tool. Errors are `FixtureLoadError` instances.
9
+ */
10
+ interface McpFakeIssue {
11
+ file: string | null;
12
+ blockId: string | null;
13
+ entryId: string | null;
14
+ message: string;
15
+ }
16
+ /**
17
+ * One declared entry as named in a mismatch claim or a snapshot. Deeply
18
+ * frozen; `args` is a frozen copy.
19
+ */
20
+ type McpFakeDeclaredEntry = Readonly<{
21
+ id: string;
22
+ consumed: boolean;
23
+ }> & McpFakeDeepReadonly<McpFakeCallMatch>;
24
+ /**
25
+ * What `McpFakeStore.claim` returns. Frozen, as is everything in it that the
26
+ * store owns (`entry`, `block`, `declared`, `matchingIds`); `result` is a
27
+ * fresh mutable copy for the mount to send, and `received` is the caller's
28
+ * `args` value as given (not copied or frozen), or a new `{}` when it was
29
+ * `undefined`.
30
+ */
31
+
32
+ /** One block of `McpFakeStore.snapshot()`. Deeply frozen. */
33
+ interface McpFakeBlockSnapshot {
34
+ readonly blockId: string;
35
+ readonly source: string;
36
+ readonly mount: string;
37
+ readonly scope: McpFakeScope;
38
+ readonly undeclaredTools: McpFakeUndeclaredPolicy;
39
+ /**
40
+ * The requested test id's consumption state was evicted by the FIFO cap. Its
41
+ * entries then show `consumed: false` because which ones it used is unknown,
42
+ * and a claim from it of a tool an applicable block declares fails as
43
+ * `evicted` until it is reset.
44
+ */
45
+ readonly evicted: boolean;
46
+ readonly tools: ReadonlyArray<Readonly<{
47
+ name: string;
48
+ entries: readonly McpFakeDeclaredEntry[];
49
+ }>>;
50
+ }
51
+ interface McpFakeAddOrigin {
52
+ /**
53
+ * `file`: blocks keep their `source` and `blockIndex`, and the per-source
54
+ * load counter (`@<k>`) applies.
55
+ * `code` / `control-api`: one run-time addition; every block gets the source
56
+ * `code#<n>` / `control-api#<n>`, whatever `source` it carried. The
57
+ * input is one `mcpFakes` value of that addition: a single item with a null
58
+ * `blockIndex` is the single-object form (no `[<i>]`); otherwise each block
59
+ * is numbered by its position in the input (`[0]`, `[1]`, ...).
60
+ */
61
+ kind: "file" | "code" | "control-api";
62
+ }
63
+ /** What a successful `McpFakeStore.add` / `Mountable.addMcpFakes` returns. */
64
+ interface McpFakeAddResult {
65
+ /** Shadowed-entry warnings of the added blocks, with their real entry ids. */
66
+ warnings: McpFakeIssue[];
67
+ }
68
+ /**
69
+ * `McpFakesAddError.toJSON()`: the first error's `rule`, `file`, `blockId` and
70
+ * `entryId`, the combined `message`, and every error and warning.
71
+ */
72
+ interface McpFakesAddErrorJSON extends FixtureLoadErrorJSON {
73
+ name: "McpFakesAddError";
74
+ errors: FixtureLoadErrorJSON[];
75
+ warnings: McpFakeIssue[];
76
+ }
77
+ /**
78
+ * The error a failed add throws. It is a `FixtureLoadError` whose `rule`,
79
+ * `file`, `blockId` and `entryId` are those of the first error, and whose
80
+ * `message` is the first error's message plus the count of the others.
81
+ * `errors` holds every error found in the input, in order (the first
82
+ * included; see `validateBlock` for the checks that stop early), and
83
+ * `warnings` the shadowed-entry warnings of the blocks that passed every
84
+ * check. Both are frozen, non-writable arrays; `toJSON()` returns copies.
85
+ */
86
+ declare class McpFakesAddError extends FixtureLoadError {
87
+ readonly name = "McpFakesAddError";
88
+ readonly errors: readonly FixtureLoadError[];
89
+ readonly warnings: readonly Readonly<McpFakeIssue>[];
90
+ constructor(errors: readonly FixtureLoadError[], warnings: readonly McpFakeIssue[]);
91
+ toJSON(): McpFakesAddErrorJSON;
92
+ }
93
+ /**
94
+ * The one own-key listing for input data: own, enumerable, string keys.
95
+ * Inherited names (`constructor`, `toString`, `__proto__`) are never listed.
96
+ *
97
+ * @internal
98
+ */
99
+ //#endregion
100
+ export { McpFakeAddOrigin, McpFakeAddResult, McpFakeBlockSnapshot, McpFakeDeclaredEntry, McpFakeIssue, McpFakesAddError, McpFakesAddErrorJSON };
101
+ //# sourceMappingURL=mcp-fakes.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-fakes.d.cts","names":[],"sources":["../src/mcp-fakes.ts"],"sourcesContent":[],"mappings":";;;;;;;;;UAkJiB,YAAA;;;;;;;;;;KAoBL,oBAAA,GAAuB;;;KACjC,oBAAoB;;;;;;;;;;UAsDL,oBAAA;;;;kBAIC;4BACU;;;;;;;;kBAQV,cACd;;sBAA2C;;;UAI9B,gBAAA;;;;;;;;;;;;;UAcA,gBAAA;;YAEL;;;;;;UAOK,oBAAA,SAA6B;;UAEpC;YACE;;;;;;;;;;;cAYC,gBAAA,SAAyB,gBAAA;;4BAEF;8BACE,SAAS;+BAEhB,uCAAuC;YA6BjD"}
@@ -0,0 +1,101 @@
1
+ import { FixtureLoadError, FixtureLoadErrorJSON } from "./fixture-loader.js";
2
+ import { McpFakeCallMatch, McpFakeDeepReadonly, McpFakeScope, McpFakeUndeclaredPolicy } from "./types.js";
3
+
4
+ //#region src/mcp-fakes.d.ts
5
+
6
+ /**
7
+ * A validation warning: an `args` entry shadowed by an earlier `anyArgs` entry
8
+ * of the same tool. Errors are `FixtureLoadError` instances.
9
+ */
10
+ interface McpFakeIssue {
11
+ file: string | null;
12
+ blockId: string | null;
13
+ entryId: string | null;
14
+ message: string;
15
+ }
16
+ /**
17
+ * One declared entry as named in a mismatch claim or a snapshot. Deeply
18
+ * frozen; `args` is a frozen copy.
19
+ */
20
+ type McpFakeDeclaredEntry = Readonly<{
21
+ id: string;
22
+ consumed: boolean;
23
+ }> & McpFakeDeepReadonly<McpFakeCallMatch>;
24
+ /**
25
+ * What `McpFakeStore.claim` returns. Frozen, as is everything in it that the
26
+ * store owns (`entry`, `block`, `declared`, `matchingIds`); `result` is a
27
+ * fresh mutable copy for the mount to send, and `received` is the caller's
28
+ * `args` value as given (not copied or frozen), or a new `{}` when it was
29
+ * `undefined`.
30
+ */
31
+
32
+ /** One block of `McpFakeStore.snapshot()`. Deeply frozen. */
33
+ interface McpFakeBlockSnapshot {
34
+ readonly blockId: string;
35
+ readonly source: string;
36
+ readonly mount: string;
37
+ readonly scope: McpFakeScope;
38
+ readonly undeclaredTools: McpFakeUndeclaredPolicy;
39
+ /**
40
+ * The requested test id's consumption state was evicted by the FIFO cap. Its
41
+ * entries then show `consumed: false` because which ones it used is unknown,
42
+ * and a claim from it of a tool an applicable block declares fails as
43
+ * `evicted` until it is reset.
44
+ */
45
+ readonly evicted: boolean;
46
+ readonly tools: ReadonlyArray<Readonly<{
47
+ name: string;
48
+ entries: readonly McpFakeDeclaredEntry[];
49
+ }>>;
50
+ }
51
+ interface McpFakeAddOrigin {
52
+ /**
53
+ * `file`: blocks keep their `source` and `blockIndex`, and the per-source
54
+ * load counter (`@<k>`) applies.
55
+ * `code` / `control-api`: one run-time addition; every block gets the source
56
+ * `code#<n>` / `control-api#<n>`, whatever `source` it carried. The
57
+ * input is one `mcpFakes` value of that addition: a single item with a null
58
+ * `blockIndex` is the single-object form (no `[<i>]`); otherwise each block
59
+ * is numbered by its position in the input (`[0]`, `[1]`, ...).
60
+ */
61
+ kind: "file" | "code" | "control-api";
62
+ }
63
+ /** What a successful `McpFakeStore.add` / `Mountable.addMcpFakes` returns. */
64
+ interface McpFakeAddResult {
65
+ /** Shadowed-entry warnings of the added blocks, with their real entry ids. */
66
+ warnings: McpFakeIssue[];
67
+ }
68
+ /**
69
+ * `McpFakesAddError.toJSON()`: the first error's `rule`, `file`, `blockId` and
70
+ * `entryId`, the combined `message`, and every error and warning.
71
+ */
72
+ interface McpFakesAddErrorJSON extends FixtureLoadErrorJSON {
73
+ name: "McpFakesAddError";
74
+ errors: FixtureLoadErrorJSON[];
75
+ warnings: McpFakeIssue[];
76
+ }
77
+ /**
78
+ * The error a failed add throws. It is a `FixtureLoadError` whose `rule`,
79
+ * `file`, `blockId` and `entryId` are those of the first error, and whose
80
+ * `message` is the first error's message plus the count of the others.
81
+ * `errors` holds every error found in the input, in order (the first
82
+ * included; see `validateBlock` for the checks that stop early), and
83
+ * `warnings` the shadowed-entry warnings of the blocks that passed every
84
+ * check. Both are frozen, non-writable arrays; `toJSON()` returns copies.
85
+ */
86
+ declare class McpFakesAddError extends FixtureLoadError {
87
+ readonly name = "McpFakesAddError";
88
+ readonly errors: readonly FixtureLoadError[];
89
+ readonly warnings: readonly Readonly<McpFakeIssue>[];
90
+ constructor(errors: readonly FixtureLoadError[], warnings: readonly McpFakeIssue[]);
91
+ toJSON(): McpFakesAddErrorJSON;
92
+ }
93
+ /**
94
+ * The one own-key listing for input data: own, enumerable, string keys.
95
+ * Inherited names (`constructor`, `toString`, `__proto__`) are never listed.
96
+ *
97
+ * @internal
98
+ */
99
+ //#endregion
100
+ export { McpFakeAddOrigin, McpFakeAddResult, McpFakeBlockSnapshot, McpFakeDeclaredEntry, McpFakeIssue, McpFakesAddError, McpFakesAddErrorJSON };
101
+ //# sourceMappingURL=mcp-fakes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-fakes.d.ts","names":[],"sources":["../src/mcp-fakes.ts"],"sourcesContent":[],"mappings":";;;;;;;;;UAkJiB,YAAA;;;;;;;;;;KAoBL,oBAAA,GAAuB;;;KACjC,oBAAoB;;;;;;;;;;UAsDL,oBAAA;;;;kBAIC;4BACU;;;;;;;;kBAQV,cACd;;sBAA2C;;;UAI9B,gBAAA;;;;;;;;;;;;;UAcA,gBAAA;;YAEL;;;;;;UAOK,oBAAA,SAA6B;;UAEpC;YACE;;;;;;;;;;;cAYC,gBAAA,SAAyB,gBAAA;;4BAEF;8BACE,SAAS;+BAEhB,uCAAuC;YA6BjD"}