@yolk-sdk/emulators 0.1.0-canary.96

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 (333) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2135 -0
  3. package/dist/anthropic.d.mts +269 -0
  4. package/dist/anthropic.d.mts.map +1 -0
  5. package/dist/anthropic.mjs +177 -0
  6. package/dist/anthropic.mjs.map +1 -0
  7. package/dist/chat-completions.d.mts +288 -0
  8. package/dist/chat-completions.d.mts.map +1 -0
  9. package/dist/chat-completions.mjs +451 -0
  10. package/dist/chat-completions.mjs.map +1 -0
  11. package/dist/codex.d.mts +265 -0
  12. package/dist/codex.d.mts.map +1 -0
  13. package/dist/codex.mjs +199 -0
  14. package/dist/codex.mjs.map +1 -0
  15. package/dist/dropbox/api.d.mts +63 -0
  16. package/dist/dropbox/api.d.mts.map +1 -0
  17. package/dist/dropbox/api.mjs +565 -0
  18. package/dist/dropbox/api.mjs.map +1 -0
  19. package/dist/dropbox/state.d.mts +136 -0
  20. package/dist/dropbox/state.d.mts.map +1 -0
  21. package/dist/dropbox/state.mjs +209 -0
  22. package/dist/dropbox/state.mjs.map +1 -0
  23. package/dist/dropbox.d.mts +79 -0
  24. package/dist/dropbox.d.mts.map +1 -0
  25. package/dist/dropbox.mjs +124 -0
  26. package/dist/dropbox.mjs.map +1 -0
  27. package/dist/email-fixtures.d.mts +36 -0
  28. package/dist/email-fixtures.d.mts.map +1 -0
  29. package/dist/email-fixtures.mjs +1080 -0
  30. package/dist/email-fixtures.mjs.map +1 -0
  31. package/dist/email.d.mts +160 -0
  32. package/dist/email.d.mts.map +1 -0
  33. package/dist/email.mjs +608 -0
  34. package/dist/email.mjs.map +1 -0
  35. package/dist/emulator-compose.d.mts +40 -0
  36. package/dist/emulator-compose.d.mts.map +1 -0
  37. package/dist/emulator-compose.mjs +91 -0
  38. package/dist/emulator-compose.mjs.map +1 -0
  39. package/dist/emulator-http.d.mts +53 -0
  40. package/dist/emulator-http.d.mts.map +1 -0
  41. package/dist/emulator-http.mjs +117 -0
  42. package/dist/emulator-http.mjs.map +1 -0
  43. package/dist/emulator-kernel.d.mts +176 -0
  44. package/dist/emulator-kernel.d.mts.map +1 -0
  45. package/dist/emulator-kernel.mjs +413 -0
  46. package/dist/emulator-kernel.mjs.map +1 -0
  47. package/dist/fixture-route.d.mts +129 -0
  48. package/dist/fixture-route.d.mts.map +1 -0
  49. package/dist/fixture-route.mjs +257 -0
  50. package/dist/fixture-route.mjs.map +1 -0
  51. package/dist/fortnox/api.d.mts +92 -0
  52. package/dist/fortnox/api.d.mts.map +1 -0
  53. package/dist/fortnox/api.mjs +750 -0
  54. package/dist/fortnox/api.mjs.map +1 -0
  55. package/dist/fortnox/state.d.mts +533 -0
  56. package/dist/fortnox/state.d.mts.map +1 -0
  57. package/dist/fortnox/state.mjs +612 -0
  58. package/dist/fortnox/state.mjs.map +1 -0
  59. package/dist/fortnox.d.mts +128 -0
  60. package/dist/fortnox.d.mts.map +1 -0
  61. package/dist/fortnox.mjs +403 -0
  62. package/dist/fortnox.mjs.map +1 -0
  63. package/dist/gateway-evaluate-recordings.d.mts +12 -0
  64. package/dist/gateway-evaluate-recordings.d.mts.map +1 -0
  65. package/dist/gateway-evaluate-recordings.mjs +128 -0
  66. package/dist/gateway-evaluate-recordings.mjs.map +1 -0
  67. package/dist/gateway.d.mts +272 -0
  68. package/dist/gateway.d.mts.map +1 -0
  69. package/dist/gateway.mjs +400 -0
  70. package/dist/gateway.mjs.map +1 -0
  71. package/dist/github/api.d.mts +63 -0
  72. package/dist/github/api.d.mts.map +1 -0
  73. package/dist/github/api.mjs +527 -0
  74. package/dist/github/api.mjs.map +1 -0
  75. package/dist/github/state.d.mts +272 -0
  76. package/dist/github/state.d.mts.map +1 -0
  77. package/dist/github/state.mjs +303 -0
  78. package/dist/github/state.mjs.map +1 -0
  79. package/dist/github.d.mts +77 -0
  80. package/dist/github.d.mts.map +1 -0
  81. package/dist/github.mjs +180 -0
  82. package/dist/github.mjs.map +1 -0
  83. package/dist/google/calendar.d.mts +10 -0
  84. package/dist/google/calendar.d.mts.map +1 -0
  85. package/dist/google/calendar.mjs +252 -0
  86. package/dist/google/calendar.mjs.map +1 -0
  87. package/dist/google/drive.d.mts +8 -0
  88. package/dist/google/drive.d.mts.map +1 -0
  89. package/dist/google/drive.mjs +252 -0
  90. package/dist/google/drive.mjs.map +1 -0
  91. package/dist/google/gmail.d.mts +10 -0
  92. package/dist/google/gmail.d.mts.map +1 -0
  93. package/dist/google/gmail.mjs +591 -0
  94. package/dist/google/gmail.mjs.map +1 -0
  95. package/dist/google/shared.d.mts +107 -0
  96. package/dist/google/shared.d.mts.map +1 -0
  97. package/dist/google/shared.mjs +146 -0
  98. package/dist/google/shared.mjs.map +1 -0
  99. package/dist/google/state.d.mts +385 -0
  100. package/dist/google/state.d.mts.map +1 -0
  101. package/dist/google/state.mjs +496 -0
  102. package/dist/google/state.mjs.map +1 -0
  103. package/dist/google.d.mts +75 -0
  104. package/dist/google.d.mts.map +1 -0
  105. package/dist/google.mjs +210 -0
  106. package/dist/google.mjs.map +1 -0
  107. package/dist/linkedin-search/api.d.mts +45 -0
  108. package/dist/linkedin-search/api.d.mts.map +1 -0
  109. package/dist/linkedin-search/api.mjs +181 -0
  110. package/dist/linkedin-search/api.mjs.map +1 -0
  111. package/dist/linkedin-search/state.d.mts +123 -0
  112. package/dist/linkedin-search/state.d.mts.map +1 -0
  113. package/dist/linkedin-search/state.mjs +261 -0
  114. package/dist/linkedin-search/state.mjs.map +1 -0
  115. package/dist/linkedin-search.d.mts +69 -0
  116. package/dist/linkedin-search.d.mts.map +1 -0
  117. package/dist/linkedin-search.mjs +158 -0
  118. package/dist/linkedin-search.mjs.map +1 -0
  119. package/dist/mcp/api.d.mts +44 -0
  120. package/dist/mcp/api.d.mts.map +1 -0
  121. package/dist/mcp/api.mjs +557 -0
  122. package/dist/mcp/api.mjs.map +1 -0
  123. package/dist/mcp/recordings.d.mts +40 -0
  124. package/dist/mcp/recordings.d.mts.map +1 -0
  125. package/dist/mcp/recordings.mjs +2390 -0
  126. package/dist/mcp/recordings.mjs.map +1 -0
  127. package/dist/mcp/state.d.mts +71 -0
  128. package/dist/mcp/state.d.mts.map +1 -0
  129. package/dist/mcp/state.mjs +83 -0
  130. package/dist/mcp/state.mjs.map +1 -0
  131. package/dist/mcp.d.mts +84 -0
  132. package/dist/mcp.d.mts.map +1 -0
  133. package/dist/mcp.mjs +241 -0
  134. package/dist/mcp.mjs.map +1 -0
  135. package/dist/messages.d.mts +183 -0
  136. package/dist/messages.d.mts.map +1 -0
  137. package/dist/messages.mjs +532 -0
  138. package/dist/messages.mjs.map +1 -0
  139. package/dist/microsoft/api.d.mts +47 -0
  140. package/dist/microsoft/api.d.mts.map +1 -0
  141. package/dist/microsoft/api.mjs +178 -0
  142. package/dist/microsoft/api.mjs.map +1 -0
  143. package/dist/microsoft/calendar.d.mts +30 -0
  144. package/dist/microsoft/calendar.d.mts.map +1 -0
  145. package/dist/microsoft/calendar.mjs +271 -0
  146. package/dist/microsoft/calendar.mjs.map +1 -0
  147. package/dist/microsoft/drive.d.mts +36 -0
  148. package/dist/microsoft/drive.d.mts.map +1 -0
  149. package/dist/microsoft/drive.mjs +298 -0
  150. package/dist/microsoft/drive.mjs.map +1 -0
  151. package/dist/microsoft/graph.d.mts +198 -0
  152. package/dist/microsoft/graph.d.mts.map +1 -0
  153. package/dist/microsoft/graph.mjs +264 -0
  154. package/dist/microsoft/graph.mjs.map +1 -0
  155. package/dist/microsoft/mail.d.mts +48 -0
  156. package/dist/microsoft/mail.d.mts.map +1 -0
  157. package/dist/microsoft/mail.mjs +488 -0
  158. package/dist/microsoft/mail.mjs.map +1 -0
  159. package/dist/microsoft/state.d.mts +480 -0
  160. package/dist/microsoft/state.d.mts.map +1 -0
  161. package/dist/microsoft/state.mjs +625 -0
  162. package/dist/microsoft/state.mjs.map +1 -0
  163. package/dist/microsoft.d.mts +168 -0
  164. package/dist/microsoft.d.mts.map +1 -0
  165. package/dist/microsoft.mjs +483 -0
  166. package/dist/microsoft.mjs.map +1 -0
  167. package/dist/node.d.mts +47 -0
  168. package/dist/node.d.mts.map +1 -0
  169. package/dist/node.mjs +178 -0
  170. package/dist/node.mjs.map +1 -0
  171. package/dist/notion/api.d.mts +51 -0
  172. package/dist/notion/api.d.mts.map +1 -0
  173. package/dist/notion/api.mjs +507 -0
  174. package/dist/notion/api.mjs.map +1 -0
  175. package/dist/notion/state.d.mts +329 -0
  176. package/dist/notion/state.d.mts.map +1 -0
  177. package/dist/notion/state.mjs +432 -0
  178. package/dist/notion/state.mjs.map +1 -0
  179. package/dist/notion.d.mts +72 -0
  180. package/dist/notion.d.mts.map +1 -0
  181. package/dist/notion.mjs +127 -0
  182. package/dist/notion.mjs.map +1 -0
  183. package/dist/openai.d.mts +165 -0
  184. package/dist/openai.d.mts.map +1 -0
  185. package/dist/openai.mjs +141 -0
  186. package/dist/openai.mjs.map +1 -0
  187. package/dist/opencode-recordings.d.mts +7 -0
  188. package/dist/opencode-recordings.d.mts.map +1 -0
  189. package/dist/opencode-recordings.mjs +222 -0
  190. package/dist/opencode-recordings.mjs.map +1 -0
  191. package/dist/opencode.d.mts +70 -0
  192. package/dist/opencode.d.mts.map +1 -0
  193. package/dist/opencode.mjs +217 -0
  194. package/dist/opencode.mjs.map +1 -0
  195. package/dist/r2-fixtures.d.mts +36 -0
  196. package/dist/r2-fixtures.d.mts.map +1 -0
  197. package/dist/r2-fixtures.mjs +245 -0
  198. package/dist/r2-fixtures.mjs.map +1 -0
  199. package/dist/r2-guard.d.mts +43 -0
  200. package/dist/r2-guard.d.mts.map +1 -0
  201. package/dist/r2-guard.mjs +215 -0
  202. package/dist/r2-guard.mjs.map +1 -0
  203. package/dist/r2.d.mts +166 -0
  204. package/dist/r2.d.mts.map +1 -0
  205. package/dist/r2.mjs +517 -0
  206. package/dist/r2.mjs.map +1 -0
  207. package/dist/responses.d.mts +231 -0
  208. package/dist/responses.d.mts.map +1 -0
  209. package/dist/responses.mjs +556 -0
  210. package/dist/responses.mjs.map +1 -0
  211. package/dist/route-evidence.d.mts +45 -0
  212. package/dist/route-evidence.d.mts.map +1 -0
  213. package/dist/route-evidence.mjs +56 -0
  214. package/dist/route-evidence.mjs.map +1 -0
  215. package/dist/router.d.mts +93 -0
  216. package/dist/router.d.mts.map +1 -0
  217. package/dist/router.mjs +259 -0
  218. package/dist/router.mjs.map +1 -0
  219. package/dist/stateful-core.d.mts +17 -0
  220. package/dist/stateful-core.d.mts.map +1 -0
  221. package/dist/stateful-core.mjs +41 -0
  222. package/dist/stateful-core.mjs.map +1 -0
  223. package/dist/stateful-emulator.d.mts +565 -0
  224. package/dist/stateful-emulator.d.mts.map +1 -0
  225. package/dist/stateful-emulator.mjs +1228 -0
  226. package/dist/stateful-emulator.mjs.map +1 -0
  227. package/dist/stateful-secrets.d.mts +84 -0
  228. package/dist/stateful-secrets.d.mts.map +1 -0
  229. package/dist/stateful-secrets.mjs +216 -0
  230. package/dist/stateful-secrets.mjs.map +1 -0
  231. package/dist/subscription-usage-recordings.d.mts +9 -0
  232. package/dist/subscription-usage-recordings.d.mts.map +1 -0
  233. package/dist/subscription-usage-recordings.mjs +53 -0
  234. package/dist/subscription-usage-recordings.mjs.map +1 -0
  235. package/dist/subscription-usage.d.mts +53 -0
  236. package/dist/subscription-usage.d.mts.map +1 -0
  237. package/dist/subscription-usage.mjs +21 -0
  238. package/dist/subscription-usage.mjs.map +1 -0
  239. package/dist/telegram/api.d.mts +34 -0
  240. package/dist/telegram/api.d.mts.map +1 -0
  241. package/dist/telegram/api.mjs +257 -0
  242. package/dist/telegram/api.mjs.map +1 -0
  243. package/dist/telegram/state.d.mts +128 -0
  244. package/dist/telegram/state.d.mts.map +1 -0
  245. package/dist/telegram/state.mjs +154 -0
  246. package/dist/telegram/state.mjs.map +1 -0
  247. package/dist/telegram.d.mts +62 -0
  248. package/dist/telegram.d.mts.map +1 -0
  249. package/dist/telegram.mjs +127 -0
  250. package/dist/telegram.mjs.map +1 -0
  251. package/dist/todoist/api.d.mts +55 -0
  252. package/dist/todoist/api.d.mts.map +1 -0
  253. package/dist/todoist/api.mjs +415 -0
  254. package/dist/todoist/api.mjs.map +1 -0
  255. package/dist/todoist/state.d.mts +275 -0
  256. package/dist/todoist/state.d.mts.map +1 -0
  257. package/dist/todoist/state.mjs +345 -0
  258. package/dist/todoist/state.mjs.map +1 -0
  259. package/dist/todoist.d.mts +68 -0
  260. package/dist/todoist.d.mts.map +1 -0
  261. package/dist/todoist.mjs +181 -0
  262. package/dist/todoist.mjs.map +1 -0
  263. package/dist/xai.d.mts +267 -0
  264. package/dist/xai.d.mts.map +1 -0
  265. package/dist/xai.mjs +252 -0
  266. package/dist/xai.mjs.map +1 -0
  267. package/package.json +157 -0
  268. package/src/anthropic.ts +289 -0
  269. package/src/chat-completions.ts +924 -0
  270. package/src/codex.ts +296 -0
  271. package/src/dropbox/api.ts +1084 -0
  272. package/src/dropbox/state.ts +364 -0
  273. package/src/dropbox.ts +203 -0
  274. package/src/email-fixtures.ts +1297 -0
  275. package/src/email.ts +1108 -0
  276. package/src/emulator-compose.ts +147 -0
  277. package/src/emulator-http.ts +184 -0
  278. package/src/emulator-kernel.ts +844 -0
  279. package/src/fixture-route.ts +561 -0
  280. package/src/fortnox/api.ts +1352 -0
  281. package/src/fortnox/state.ts +798 -0
  282. package/src/fortnox.ts +801 -0
  283. package/src/gateway-evaluate-recordings.ts +153 -0
  284. package/src/gateway.ts +530 -0
  285. package/src/github/api.ts +986 -0
  286. package/src/github/state.ts +439 -0
  287. package/src/github.ts +271 -0
  288. package/src/google/calendar.ts +486 -0
  289. package/src/google/drive.ts +471 -0
  290. package/src/google/gmail.ts +1011 -0
  291. package/src/google/shared.ts +321 -0
  292. package/src/google/state.ts +686 -0
  293. package/src/google.ts +298 -0
  294. package/src/linkedin-search/api.ts +363 -0
  295. package/src/linkedin-search/state.ts +373 -0
  296. package/src/linkedin-search.ts +241 -0
  297. package/src/mcp/api.ts +995 -0
  298. package/src/mcp/recordings.ts +2665 -0
  299. package/src/mcp/state.ts +125 -0
  300. package/src/mcp.ts +319 -0
  301. package/src/messages.ts +844 -0
  302. package/src/microsoft/api.ts +426 -0
  303. package/src/microsoft/calendar.ts +491 -0
  304. package/src/microsoft/drive.ts +541 -0
  305. package/src/microsoft/graph.ts +550 -0
  306. package/src/microsoft/mail.ts +833 -0
  307. package/src/microsoft/state.ts +822 -0
  308. package/src/microsoft.ts +982 -0
  309. package/src/node.ts +293 -0
  310. package/src/notion/api.ts +976 -0
  311. package/src/notion/state.ts +512 -0
  312. package/src/notion.ts +210 -0
  313. package/src/openai.ts +198 -0
  314. package/src/opencode-recordings.ts +257 -0
  315. package/src/opencode.ts +271 -0
  316. package/src/r2-fixtures.ts +295 -0
  317. package/src/r2-guard.ts +323 -0
  318. package/src/r2.ts +890 -0
  319. package/src/responses.ts +901 -0
  320. package/src/route-evidence.ts +90 -0
  321. package/src/router.ts +490 -0
  322. package/src/stateful-core.ts +70 -0
  323. package/src/stateful-emulator.ts +2571 -0
  324. package/src/stateful-secrets.ts +299 -0
  325. package/src/subscription-usage-recordings.ts +77 -0
  326. package/src/subscription-usage.ts +68 -0
  327. package/src/telegram/api.ts +437 -0
  328. package/src/telegram/state.ts +229 -0
  329. package/src/telegram.ts +227 -0
  330. package/src/todoist/api.ts +736 -0
  331. package/src/todoist/state.ts +456 -0
  332. package/src/todoist.ts +316 -0
  333. package/src/xai.ts +341 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.mjs","names":[],"sources":["../../src/mcp/api.ts"],"sourcesContent":["/**\n * MCP emulator route table (internal): one wire route per recorded HTTP shape (`POST /modern/mcp`,\n * `POST /legacy/mcp`, `GET /legacy/mcp`), each answering only the JSON-RPC methods its profile's\n * fixtures record, as manifest variants (`RPC <origin><path>#<method>`, plus the `GET` row).\n *\n * A request is admitted only when it equals a recorded request (`src/mcp/recordings.ts`) within\n * the latitude: the MCP headers (`accept`, `content-type`, `mcp-method`, `mcp-protocol-version`,\n * `mcp-name`, `last-event-id`) equal the recorded values or are absent where the recording has\n * none; `mcp-session-id` is present exactly where recorded; the body has exactly the recorded\n * keys; the id is any JSON-RPC id of the accepted form where one is recorded; and `params` equal\n * the recorded ones except for JSON key order and the `_meta` client info's name and version\n * (and, on the second page of the paged listing, the cursor, checked by issuance). Everything\n * else is refused with a constant reason. The answer is the recorded one with only the request id\n * substituted where the recording carries the recorded request id (the top-level `id` of a JSON\n * answer, or of the SSE response event's payload), the session id (minted, or the request's) in\n * the `mcp-session-id` header, and the cursor of the current generation in `nextCursor`.\n *\n * @experimental\n */\nimport { Predicate } from 'effect'\nimport type * as Schema from 'effect/Schema'\nimport type { EmulatorRouteEvidence } from '../route-evidence.ts'\nimport {\n isJsonObject,\n isNotEmulated,\n notEmulated,\n parseJsonText,\n streamedCommit,\n type Admission,\n type EmulatedRequest,\n type NotEmulated,\n type Planned,\n type StatefulRoute,\n type StreamedAnswer\n} from '../stateful-emulator.ts'\nimport {\n mcpEmulatorFixtures,\n type McpRecordedExchange,\n type McpRecordedFixture,\n type McpRecordedRequest,\n type McpRecordedResponse\n} from './recordings.ts'\nimport {\n mcpEmulatorLegacyPath,\n mcpEmulatorModernPath,\n mcpEmulatorOrigin,\n mcpEmulatorSessionCap,\n mcpEmulatorSessionPrefix,\n type McpEmulatorState,\n type McpRuntime\n} from './state.ts'\n\n/** Drill knobs (tests only): each makes the emulator disagree with exactly one case's claim. */\nexport type McpEmulatorDrills = {\n /** `mcp.negotiation.era` (modern): the discover answer also carries a JSON-RPC error. */\n readonly discoverCarriesErrorResponse?: boolean\n /** `mcp.modern.stateless`: the modern discover result lacks `resultType`. */\n readonly discoverWithoutResultType?: boolean\n /** `mcp.legacy.session`: minted session ids hold a space (not visible ASCII). */\n readonly sessionIdNotVisibleAscii?: boolean\n /** `mcp.transport.response-encoding` (modern): the discover answer holds its response twice. */\n readonly discoverAnsweredTwice?: boolean\n /** `mcp.tools.list`: the listing marks the write tool `readOnlyHint: true`. */\n readonly writeToolMarkedReadOnly?: boolean\n /** `mcp.tools.call-read`: the read call answers `isError: true`. */\n readonly readCallAnswersToolError?: boolean\n /** `mcp.tools.call-tool-error`: invalid arguments answer a JSON-RPC error. */\n readonly invalidCallAnswersRpcError?: boolean\n /** `mcp.errors.unknown-tool`: the absent tool answers a tool result. */\n readonly absentCallAnswersResult?: boolean\n /** `mcp.auth.rejected`: the 401 carries no `WWW-Authenticate` challenge. */\n readonly unauthorizedWithoutChallenge?: boolean\n}\n\nexport const mcpEmulatorDrillKnobs: ReadonlyArray<keyof McpEmulatorDrills> = [\n 'discoverCarriesErrorResponse',\n 'discoverWithoutResultType',\n 'sessionIdNotVisibleAscii',\n 'discoverAnsweredTwice',\n 'writeToolMarkedReadOnly',\n 'readCallAnswersToolError',\n 'invalidCallAnswersRpcError',\n 'absentCallAnswersResult',\n 'unauthorizedWithoutChallenge'\n]\n\nexport type McpApiEnv = {\n readonly drills: Readonly<Record<keyof McpEmulatorDrills, boolean>>\n /** The digest of the reserved invalid credential on the emulated origin. */\n readonly reservedDigest: string\n /** Runtime data the commits advance (never in the state). */\n readonly runtime: McpRuntime\n}\n\ntype McpRoute = StatefulRoute<McpEmulatorState, McpApiEnv>\n\ntype RpcId = string | number\n\ntype JsonObject = Schema.JsonObject\n\nconst fieldOf = (value: Schema.Json | undefined, key: string): Schema.Json | undefined =>\n isJsonObject(value) ? value[key] : undefined\n\n// The recorded exchanges the routes answer, by fixture id and exchange index.\n\nconst exchangeOf = (fixtureId: string, index: number): McpRecordedExchange => {\n const exchange = mcpEmulatorFixtures\n .find(fixture => fixture.id === fixtureId)\n ?.exchanges.at(index)\n\n if (exchange === undefined) {\n throw new Error(`the MCP recordings have no exchange ${index} in ${fixtureId}`)\n }\n\n return exchange\n}\n\nconst modern = (caseId: string) => `${caseId}.modern.synthetic`\n\nconst legacy = (caseId: string) => `${caseId}.legacy.synthetic`\n\nconst recorded = {\n modernDiscover: exchangeOf(modern('mcp.negotiation.era'), 0),\n modernRejected: exchangeOf(modern('mcp.auth.rejected'), 0),\n modernList: exchangeOf(modern('mcp.negotiation.era'), 1),\n modernFirstPage: exchangeOf(modern('mcp.tools.list'), 1),\n modernSecondPage: exchangeOf(modern('mcp.tools.list'), 2),\n modernCallRead: exchangeOf(modern('mcp.tools.call-read'), -1),\n modernCallToolError: exchangeOf(modern('mcp.tools.call-tool-error'), -1),\n modernCallAbsent: exchangeOf(modern('mcp.errors.unknown-tool'), -1),\n legacyDiscover: exchangeOf(legacy('mcp.negotiation.era'), 0),\n legacyRejected: exchangeOf(legacy('mcp.auth.rejected'), 0),\n legacyInitialize: exchangeOf(legacy('mcp.negotiation.era'), 1),\n legacyInitialized: exchangeOf(legacy('mcp.negotiation.era'), 2),\n legacyGet: exchangeOf(legacy('mcp.negotiation.era'), 3),\n legacyList: exchangeOf(legacy('mcp.negotiation.era'), 4),\n legacyCallRead: exchangeOf(legacy('mcp.tools.call-read'), -1),\n legacyCallToolError: exchangeOf(legacy('mcp.tools.call-tool-error'), -1),\n legacyCallAbsent: exchangeOf(legacy('mcp.errors.unknown-tool'), -1)\n}\n\ntype RecordedKey = keyof typeof recorded\n\n/** The cursor the paged listing records between its two pages. */\nconst recordedCursor = (() => {\n const cursor = fieldOf(fieldOf(recorded.modernSecondPage.request.body, 'params'), 'cursor')\n\n if (!Predicate.isString(cursor)) {\n throw new Error('the paged MCP listing records no cursor')\n }\n\n return cursor\n})()\n\n// The manifest: one row per recorded JSON-RPC method of each profile, plus the GET row.\n\nconst casesSending = (path: string, sends: (request: McpRecordedRequest) => boolean) => [\n ...new Set(\n mcpEmulatorFixtures.flatMap(fixture =>\n fixture.endpoint === `${mcpEmulatorOrigin}${path}` &&\n fixture.exchanges.some(exchange => sends(exchange.request))\n ? [fixture.caseId]\n : []\n )\n )\n]\n\nconst rpcMethodOf = (request: McpRecordedRequest): string | undefined => {\n const method = fieldOf(request.body, 'method')\n\n return Predicate.isString(method) ? method : undefined\n}\n\nconst rpcRow = (path: string, method: string): EmulatorRouteEvidence => ({\n method: 'RPC',\n path: `${mcpEmulatorOrigin}${path}#${method}`,\n kind: 'connector',\n write: false,\n caseIds: casesSending(\n path,\n request => request.method === 'POST' && rpcMethodOf(request) === method\n ),\n evidence: 'unverified'\n})\n\nconst modernMethods = ['server/discover', 'tools/list', 'tools/call'] as const\n\nconst legacyMethods = [\n 'server/discover',\n 'initialize',\n 'notifications/initialized',\n 'tools/list',\n 'tools/call'\n] as const\n\nconst modernRows = modernMethods.map(method => rpcRow(mcpEmulatorModernPath, method))\n\nconst legacyRows = legacyMethods.map(method => rpcRow(mcpEmulatorLegacyPath, method))\n\nconst getRow: EmulatorRouteEvidence = {\n method: 'GET',\n path: `${mcpEmulatorOrigin}${mcpEmulatorLegacyPath}`,\n kind: 'connector',\n write: false,\n caseIds: casesSending(mcpEmulatorLegacyPath, request => request.method === 'GET'),\n evidence: 'unverified'\n}\n\nconst rowOf = (path: string, method: string): string => `${mcpEmulatorOrigin}${path}#${method}`\n\n// Answers: the recorded bytes, with only the request id, session id, and cursor substituted.\n\nconst isEventStream = (headers: Readonly<Record<string, string>>): boolean =>\n headers['content-type'] === 'text/event-stream'\n\n/** A recorded answer as status, headers, and chunks (a JSON body is one chunk; none is none). */\nconst answerOf = (response: McpRecordedResponse): StreamedAnswer => ({\n status: response.status,\n headers: response.headers,\n chunks: 'chunks' in response ? response.chunks : response.body === '' ? [] : [response.body]\n})\n\nconst isResponseTo = (message: Schema.Json | undefined, id: RpcId): message is JsonObject =>\n isJsonObject(message) && message['id'] === id && ('result' in message || 'error' in message)\n\nconst dataPrefix = 'data: '\n\n/**\n * `answer` with the JSON-RPC response to `recordedId` (the top-level message of a JSON answer, or\n * the payload of the SSE event that carries it) replaced by `change` of it; every other chunk,\n * line, and event (notifications, `id:` lines) stays byte for byte.\n */\nconst mapResponse = (\n answer: StreamedAnswer,\n recordedId: RpcId,\n change: (message: JsonObject) => Schema.Json\n): StreamedAnswer => {\n const eventStream = isEventStream(answer.headers)\n\n const chunks = answer.chunks.map(chunk => {\n if (!eventStream) {\n const message = parseJsonText(chunk)\n\n return isResponseTo(message, recordedId) ? JSON.stringify(change(message)) : chunk\n }\n\n return chunk\n .split('\\n')\n .map(line => {\n if (!line.startsWith(dataPrefix)) return line\n\n const message = parseJsonText(line.slice(dataPrefix.length))\n\n return isResponseTo(message, recordedId)\n ? `${dataPrefix}${JSON.stringify(change(message))}`\n : line\n })\n .join('\\n')\n })\n\n return { ...answer, chunks }\n}\n\nconst recordedIdOf = (exchange: McpRecordedExchange): RpcId | undefined => {\n const id = fieldOf(exchange.request.body, 'id')\n\n return Predicate.isString(id) || Predicate.isNumber(id) ? id : undefined\n}\n\n/** The recorded answer of `exchange` with the request's id where it carries the recorded id. */\nconst answerWithId = (exchange: McpRecordedExchange, id: RpcId | undefined): StreamedAnswer => {\n const answer = answerOf(exchange.response)\n const recordedId = recordedIdOf(exchange)\n\n // The recorded request id stays byte for byte; so does an answer that does not carry it.\n if (recordedId === undefined || id === undefined || id === recordedId) return answer\n\n return mapResponse(answer, recordedId, message => ({ ...message, id }))\n}\n\n/** `answer` with its `mcp-session-id` header (recorded on SSE answers) set to `session`. */\nconst withSession = (answer: StreamedAnswer, session: string): StreamedAnswer =>\n answer.headers['mcp-session-id'] === undefined\n ? answer\n : { ...answer, headers: { ...answer.headers, 'mcp-session-id': session } }\n\n/** The response message of an answer to `id` with `change` applied to its `result`. */\nconst mapResult =\n (change: (result: JsonObject) => JsonObject) =>\n (message: JsonObject): JsonObject => {\n const result = message['result']\n\n return isJsonObject(result) ? { ...message, result: change(result) } : message\n }\n\n/**\n * Where a copied recording is not in the canonical form id substitution relies on: every JSON\n * answer body, and every SSE `data:` payload, must equal `JSON.stringify(JSON.parse(text))`, and\n * every SSE data line must start with `data: `. `makeMcpEmulator` throws on any problem, so a\n * recording copied in another form (escapes such as `\\u00e9` or `\\/`, numbers such as `1.0`,\n * spacing) fails loudly instead of answering bytes the substitution would rewrite.\n */\nexport const mcpRecordingProblems = (\n fixtures: ReadonlyArray<McpRecordedFixture>\n): ReadonlyArray<string> =>\n fixtures.flatMap(fixture =>\n fixture.exchanges.flatMap(({ response }, index) => {\n const where = `${fixture.id} exchange ${index}`\n\n const canonical = (text: string) => {\n const parsed = parseJsonText(text)\n\n return parsed !== undefined && JSON.stringify(parsed) === text\n }\n\n if (!('chunks' in response)) {\n return response.body === '' || canonical(response.body)\n ? []\n : [`${where}: the JSON body is not canonical`]\n }\n\n return response.chunks.flatMap((chunk, at) =>\n chunk\n .split('\\n')\n .flatMap(line =>\n !line.startsWith('data') ||\n (line.startsWith(dataPrefix) && canonical(line.slice(dataPrefix.length)))\n ? []\n : [`${where} chunk ${at}: an SSE data line is not canonical`]\n )\n )\n })\n )\n\n// Request checks: constant reasons only (the wrapper ledgers refusals as constant entries).\n\n/** The MCP headers compared with the recording (absent where the recording has none). */\nconst comparedHeaders = [\n 'accept',\n 'content-type',\n 'last-event-id',\n 'mcp-method',\n 'mcp-name',\n 'mcp-protocol-version'\n] as const\n\nconst sessionHeader = 'mcp-session-id'\n\n/** The `mcp-*` headers a recording carries; any other (such as `mcp-param-*`) is refused. */\nconst recordedMcpHeaders: ReadonlySet<string> = new Set([\n 'mcp-method',\n 'mcp-name',\n 'mcp-protocol-version',\n sessionHeader\n])\n\n/** Refuse an `mcp-*` header no recording carries (fail closed when the names are unknown). */\nconst unrecordedMcpHeader = (request: EmulatedRequest): NotEmulated | undefined =>\n request.headerNames === undefined ||\n request.headerNames.some(name => name.startsWith('mcp-') && !recordedMcpHeaders.has(name))\n ? notEmulated('an mcp-* header no recording carries is not emulated')\n : undefined\n\nconst headerProblem = (\n request: EmulatedRequest,\n recordedRequest: McpRecordedRequest,\n names: ReadonlyArray<string>\n): NotEmulated | undefined => {\n for (const name of names) {\n if (request.header(name) !== recordedRequest.headers[name]) {\n return notEmulated(`the ${name} header must be the recorded value, or absent where none is`)\n }\n }\n\n if (\n (request.header(sessionHeader) === undefined) !==\n (recordedRequest.headers[sessionHeader] === undefined)\n ) {\n return notEmulated('mcp-session-id must be sent exactly where the recording sends one')\n }\n\n return undefined\n}\n\n/**\n * A JSON-RPC request id of the emulated form: an integer from 0 to 2^53 - 1, or 1 to 64 printable\n * ASCII characters.\n */\nexport const isMcpEmulatedRequestId = (id: Schema.Json | undefined): id is RpcId =>\n (Predicate.isNumber(id) && Number.isSafeInteger(id) && id >= 0) ||\n (Predicate.isString(id) && /^[\\x20-\\x7E]{1,64}$/.test(id))\n\n/** Structural JSON equality, ignoring object key order. */\nconst jsonEqual = (left: Schema.Json, right: Schema.Json): boolean => {\n if (Array.isArray(left)) {\n return (\n Array.isArray(right) &&\n left.length === right.length &&\n left.every((item, index) => {\n const other = right[index]\n\n return other !== undefined && jsonEqual(item, other)\n })\n )\n }\n\n if (isJsonObject(left)) {\n if (!isJsonObject(right)) return false\n\n const keys = Object.keys(left)\n\n return (\n keys.length === Object.keys(right).length &&\n keys.every(key => {\n const value = left[key]\n const other = right[key]\n\n return (\n Object.hasOwn(right, key) &&\n value !== undefined &&\n other !== undefined &&\n jsonEqual(value, other)\n )\n })\n )\n }\n\n return left === right\n}\n\nconst clientInfoKey = 'io.modelcontextprotocol/clientInfo'\n\nconst isClientInfo = (value: Schema.Json | undefined): boolean =>\n isJsonObject(value) &&\n Object.keys(value).length === 2 &&\n Predicate.isString(value['name']) &&\n value['name'].length > 0 &&\n Predicate.isString(value['version']) &&\n value['version'].length > 0\n\n/**\n * The request params normalised for comparison with `recordedParams`: the `_meta` client info\n * replaced by the recorded one (when it is any non-empty name and version), and with `cursorFree`\n * the cursor replaced by the recorded one (when it is a string; checked by issuance at plan).\n */\nconst normalisedParams = (\n params: Schema.Json | undefined,\n recordedParams: JsonObject,\n cursorFree: boolean\n): JsonObject | NotEmulated => {\n if (!isJsonObject(params)) return notEmulated('params must be the recorded JSON object')\n\n const meta = params['_meta']\n const recordedMeta = recordedParams['_meta']\n let normalised: JsonObject = params\n\n if (isJsonObject(recordedMeta) && recordedMeta[clientInfoKey] !== undefined) {\n if (!isJsonObject(meta) || !isClientInfo(meta[clientInfoKey])) {\n return notEmulated('the _meta client info must be a non-empty name and version only')\n }\n\n normalised = { ...normalised, _meta: { ...meta, [clientInfoKey]: recordedMeta[clientInfoKey] } }\n }\n\n if (cursorFree) {\n if (!Predicate.isString(params['cursor'])) {\n return notEmulated('the second page must send the cursor the first page issued')\n }\n\n normalised = { ...normalised, cursor: recordedCursor }\n }\n\n return normalised\n}\n\ntype Matched = {\n readonly key: RecordedKey\n readonly id: RpcId | undefined\n readonly cursor: string | undefined\n}\n\n/**\n * The first candidate whose recorded request the JSON-RPC POST equals within the latitude, or\n * not emulated. Every candidate records the same method; candidates differ only in their params\n * and `mcp-name` (the recorded tool calls).\n */\nconst matchRpc = (\n request: EmulatedRequest,\n candidates: ReadonlyArray<RecordedKey>,\n options: { readonly cursorFree?: boolean } = {}\n): Matched | NotEmulated => {\n const [first] = candidates\n\n if (first === undefined) return notEmulated('this JSON-RPC method is not emulated here')\n\n const firstRequest = recorded[first].request\n const body = request.json\n const recordedBody = firstRequest.body\n\n if (!isJsonObject(recordedBody)) return notEmulated('this JSON-RPC method is not emulated here')\n\n const common =\n unrecordedMcpHeader(request) ??\n headerProblem(\n request,\n firstRequest,\n comparedHeaders.filter(name => name !== 'mcp-name')\n )\n\n if (common !== undefined) return common\n\n if (!isJsonObject(body)) {\n return notEmulated('JSON-RPC batches and non-object bodies are not emulated')\n }\n\n const keys = Object.keys(body)\n const recordedKeys = Object.keys(recordedBody)\n\n if (keys.length !== recordedKeys.length || keys.some(key => !recordedKeys.includes(key))) {\n return notEmulated('the JSON-RPC message must have exactly the recorded members')\n }\n\n if (body['jsonrpc'] !== '2.0') return notEmulated('jsonrpc must be \"2.0\"')\n\n const id = body['id']\n\n if ('id' in recordedBody && !isMcpEmulatedRequestId(id)) {\n return notEmulated(\n 'the request id must be an integer from 0 to 2^53 - 1 or 1 to 64 printable ASCII characters'\n )\n }\n\n const cursor = options.cursorFree === true ? fieldOf(body['params'], 'cursor') : undefined\n\n for (const key of candidates) {\n const candidate = recorded[key].request\n const candidateBody = candidate.body\n\n if (!isJsonObject(candidateBody)) continue\n\n if (headerProblem(request, candidate, ['mcp-name']) !== undefined) continue\n\n const recordedParams = candidateBody['params']\n\n if (recordedParams !== undefined) {\n const params = isJsonObject(recordedParams)\n ? normalisedParams(body['params'], recordedParams, options.cursorFree === true)\n : notEmulated('params must be the recorded value')\n\n if (isNotEmulated(params)) return params\n\n if (!jsonEqual(params, recordedParams)) continue\n }\n\n return {\n key,\n id: isMcpEmulatedRequestId(id) ? id : undefined,\n cursor: Predicate.isString(cursor) ? cursor : undefined\n }\n }\n\n return notEmulated('params other than the recorded ones are not emulated')\n}\n\n/** Refuse any query parameter (no fixture records one). */\nconst noQuery = (request: EmulatedRequest): NotEmulated | undefined =>\n request.rawQuery === undefined || request.rawQuery === ''\n ? undefined\n : notEmulated('query parameters are not emulated')\n\nconst isReserved = (request: EmulatedRequest, env: McpApiEnv): boolean =>\n request.bearerDigest === env.reservedDigest\n\nconst reservedOnlyOnProbe = 'the reserved invalid credential is answered only on the era probe'\n\n// Plans and commits.\n\ntype Admitted = Matched & {\n /** The request's `mcp-session-id` (legacy non-handshake requests). */\n readonly session: string | undefined\n}\n\ntype Plan = (state: McpEmulatorState, admitted: Admitted, env: McpApiEnv) => Planned\n\nconst admission = (\n variant: string,\n admitted: Admitted,\n plan: Plan\n): Admission<McpEmulatorState, McpApiEnv> => ({\n variant,\n plan: (state, context) => plan(state, admitted, context.env)\n})\n\n/** A commit that answers `answer` and writes nothing. */\nconst answerOnly = (answer: StreamedAnswer): Planned => streamedCommit(answer)\n\nconst sessionOf = (state: McpEmulatorState, admitted: Admitted, phase: 'initializing' | 'ready') =>\n state.sessions.find(session => session.id === admitted.session && session.phase === phase)\n\nconst unknownSession = (phase: 'initializing' | 'ready') =>\n notEmulated(\n phase === 'ready'\n ? 'a request on no ready session of this emulator is not emulated'\n : 'notifications/initialized on no initializing session of this emulator is not emulated'\n )\n\n/** The JSON-RPC error the era drill adds to the discover answer (another id: the SDK skips it). */\nconst drillErrorResponse = JSON.stringify({\n jsonrpc: '2.0',\n id: 'yolk-emu-drill',\n error: { code: -32_603, message: 'Synthetic drill error.' }\n})\n\n/** Drill transforms of an answer, by the recorded exchange it answers. */\nconst drilled = (key: RecordedKey, answer: StreamedAnswer, id: RpcId, env: McpApiEnv) => {\n const drills = env.drills\n\n switch (key) {\n case 'modernDiscover': {\n let next = answer\n\n if (drills.discoverWithoutResultType) {\n next = mapResponse(\n next,\n id,\n mapResult(({ resultType: _resultType, ...result }) => result)\n )\n }\n\n if (drills.discoverCarriesErrorResponse) {\n next = {\n ...next,\n chunks: next.chunks.map(chunk => `[${drillErrorResponse},${chunk}]`)\n }\n }\n\n if (drills.discoverAnsweredTwice) {\n next = {\n ...next,\n headers: { ...next.headers, 'content-type': 'text/event-stream' },\n chunks: next.chunks.flatMap(chunk => [\n `event: message\\ndata: ${chunk}\\n\\n`,\n `event: message\\ndata: ${chunk}\\n\\n`\n ])\n }\n }\n\n return next\n }\n\n case 'modernList':\n case 'modernFirstPage':\n case 'modernSecondPage':\n case 'legacyList':\n return drills.writeToolMarkedReadOnly\n ? mapResponse(\n answer,\n id,\n mapResult(result => {\n const tools = result['tools']\n\n return Array.isArray(tools)\n ? {\n ...result,\n tools: tools.map(tool =>\n isJsonObject(tool) && tool['name'] === 'create_synthetic_note'\n ? { ...tool, annotations: { readOnlyHint: true } }\n : tool\n )\n }\n : result\n })\n )\n : answer\n\n case 'modernCallRead':\n case 'legacyCallRead':\n return drills.readCallAnswersToolError\n ? mapResponse(\n answer,\n id,\n mapResult(result => ({ ...result, isError: true }))\n )\n : answer\n\n case 'modernCallToolError':\n case 'legacyCallToolError':\n return drills.invalidCallAnswersRpcError\n ? mapResponse(answer, id, () => ({\n jsonrpc: '2.0',\n id,\n error: { code: -32_602, message: 'Invalid arguments: noteId must be a string.' }\n }))\n : answer\n\n case 'modernCallAbsent':\n case 'legacyCallAbsent': {\n if (!drills.absentCallAnswersResult) return answer\n\n const result: JsonObject = {\n content: [{ type: 'text', text: 'Synthetic drill result.' }],\n isError: true\n }\n\n return mapResponse({ ...answer, status: 200 }, id, () => ({\n jsonrpc: '2.0',\n id,\n result: key === 'modernCallAbsent' ? { ...result, resultType: 'complete' } : result\n }))\n }\n\n case 'modernRejected':\n case 'legacyRejected': {\n if (!drills.unauthorizedWithoutChallenge) return answer\n\n const { 'www-authenticate': _challenge, ...headers } = answer.headers\n\n return { ...answer, headers }\n }\n\n default:\n return answer\n }\n}\n\n/** The id the answer's response carries: the request's (substituted), else the recorded one. */\nconst responseIdOf = (key: RecordedKey, id: RpcId | undefined): RpcId | undefined =>\n id ?? recordedIdOf(recorded[key])\n\n/** The recorded answer for `key`, with the request id substituted and any drill applied. */\nconst recordedAnswer = (key: RecordedKey, id: RpcId | undefined, env: McpApiEnv) => {\n const answer = answerWithId(recorded[key], id)\n const responseId = responseIdOf(key, id)\n\n return responseId === undefined ? answer : drilled(key, answer, responseId, env)\n}\n\n/** The cursor value issued in the current generation (the recorded one in its first). */\nconst cursorFor = (runtime: McpRuntime): string =>\n (runtime.cursorFirstGeneration ?? runtime.generation) === runtime.generation\n ? recordedCursor\n : `${recordedCursor}.g${runtime.generation}`\n\nconst planModernList: Plan = (state, admitted, env) => {\n if (state.modernListing === 'one-page') {\n return answerOnly(recordedAnswer('modernList', admitted.id, env))\n }\n\n const cursor = cursorFor(env.runtime)\n const recordedPage = recordedAnswer('modernFirstPage', admitted.id, env)\n const responseId = responseIdOf('modernFirstPage', admitted.id)\n\n // The recorded bytes in the generation that first issues the cursor; a minted cursor after it.\n const sent =\n cursor === recordedCursor || responseId === undefined\n ? recordedPage\n : mapResponse(\n recordedPage,\n responseId,\n mapResult(result => ({ ...result, nextCursor: cursor }))\n )\n\n // The cursor is issued only by the commit, so a faulted or truncated first page issues none.\n return streamedCommit(sent, () => {\n env.runtime.cursorFirstGeneration ??= env.runtime.generation\n env.runtime.issuedCursor = cursor\n }, [cursor])\n}\n\nconst planModernSecondPage: Plan = (state, admitted, env) =>\n state.modernListing === 'two-pages' &&\n env.runtime.issuedCursor !== undefined &&\n admitted.cursor === env.runtime.issuedCursor\n ? answerOnly(recordedAnswer('modernSecondPage', admitted.id, env))\n : notEmulated(\n 'a cursor this emulator did not issue since the last reset or seed is not emulated'\n )\n\nconst planInitialize: Plan = (state, admitted, env) => {\n const number = env.runtime.nextSession\n\n if (state.sessions.length >= mcpEmulatorSessionCap || !Number.isSafeInteger(number + 1)) {\n return notEmulated('the emulator holds as many sessions as it takes')\n }\n\n const session = env.drills.sessionIdNotVisibleAscii\n ? `yolk-emu-session ${number}`\n : `${mcpEmulatorSessionPrefix}${number}`\n\n const answer = withSession(recordedAnswer('legacyInitialize', admitted.id, env), session)\n\n // The session is minted only by the commit, so a faulted or truncated `initialize` holds none\n // and leaves the counter where it was.\n return streamedCommit(answer, () => {\n env.runtime.nextSession = number + 1\n state.sessions = [...state.sessions, { id: session, phase: 'initializing' }]\n }, [session])\n}\n\nconst planInitialized: Plan = (state, admitted, env) => {\n const session = sessionOf(state, admitted, 'initializing')\n\n if (session === undefined) return unknownSession('initializing')\n\n const answer = recordedAnswer('legacyInitialized', undefined, env)\n\n return streamedCommit(answer, () => {\n state.sessions = state.sessions.map(held =>\n held.id === session.id ? { id: held.id, phase: 'ready' } : held\n )\n })\n}\n\n/** A legacy answer on a ready session: the recorded answer with the session's id. */\nconst planOnSession =\n (key: RecordedKey): Plan =>\n (state, admitted, env) => {\n const session = sessionOf(state, admitted, 'ready')\n\n return session === undefined\n ? unknownSession('ready')\n : answerOnly(withSession(recordedAnswer(key, admitted.id, env), session.id))\n }\n\nconst planAnswer =\n (key: RecordedKey): Plan =>\n (_state, admitted, env) =>\n answerOnly(recordedAnswer(key, admitted.id, env))\n\n// Routes.\n\nconst routeEvidenceOf = (\n method: string,\n path: string,\n variants: ReadonlyArray<EmulatorRouteEvidence>\n) => ({\n method,\n path,\n kind: 'connector' as const,\n write: false,\n caseIds: [...new Set(variants.flatMap(variant => variant.caseIds))],\n evidence: 'unverified' as const,\n origin: mcpEmulatorOrigin,\n variants\n})\n\nconst admitted = (matched: Matched, request: EmulatedRequest): Admitted => ({\n ...matched,\n session: request.header(sessionHeader)\n})\n\n/** `POST /modern/mcp`: the stateless synthetic server (JSON answers, no session). */\nconst modernRoute: McpRoute = {\n ...routeEvidenceOf('POST', mcpEmulatorModernPath, modernRows),\n body: 'json',\n admit: (request, env) => {\n const query = noQuery(request)\n\n if (query !== undefined) return query\n\n const method = fieldOf(request.json, 'method')\n const variant = (name: string) => rowOf(mcpEmulatorModernPath, name)\n\n if (method === 'server/discover') {\n const matched = matchRpc(request, ['modernDiscover'])\n\n if (isNotEmulated(matched)) return matched\n\n return isReserved(request, env)\n ? admission(variant(method), admitted(matched, request), planAnswer('modernRejected'))\n : admission(variant(method), admitted(matched, request), planAnswer('modernDiscover'))\n }\n\n if (isReserved(request, env)) return notEmulated(reservedOnlyOnProbe)\n\n if (method === 'tools/list') {\n const paged = fieldOf(fieldOf(request.json, 'params'), 'cursor') !== undefined\n\n const matched = paged\n ? matchRpc(request, ['modernSecondPage'], { cursorFree: true })\n : matchRpc(request, ['modernList'])\n\n if (isNotEmulated(matched)) return matched\n\n return admission(\n variant(method),\n admitted(matched, request),\n paged ? planModernSecondPage : planModernList\n )\n }\n\n if (method === 'tools/call') {\n const matched = matchRpc(request, [\n 'modernCallRead',\n 'modernCallToolError',\n 'modernCallAbsent'\n ])\n\n if (isNotEmulated(matched)) return matched\n\n return admission(variant(method), admitted(matched, request), planAnswer(matched.key))\n }\n\n return notEmulated('this JSON-RPC method is not emulated on the modern profile')\n }\n}\n\n/** `POST /legacy/mcp`: the initialize-based synthetic server (SSE answers, sessions). */\nconst legacyRoute: McpRoute = {\n ...routeEvidenceOf('POST', mcpEmulatorLegacyPath, legacyRows),\n body: 'json',\n admit: (request, env) => {\n const query = noQuery(request)\n\n if (query !== undefined) return query\n\n const method = fieldOf(request.json, 'method')\n const variant = (name: string) => rowOf(mcpEmulatorLegacyPath, name)\n\n if (method === 'server/discover') {\n const matched = matchRpc(request, ['legacyDiscover'])\n\n if (isNotEmulated(matched)) return matched\n\n return isReserved(request, env)\n ? admission(variant(method), admitted(matched, request), planAnswer('legacyRejected'))\n : admission(variant(method), admitted(matched, request), planAnswer('legacyDiscover'))\n }\n\n if (isReserved(request, env)) return notEmulated(reservedOnlyOnProbe)\n\n const single = (key: RecordedKey, name: string, plan: Plan) => {\n const matched = matchRpc(request, [key])\n\n return isNotEmulated(matched)\n ? matched\n : admission(variant(name), admitted(matched, request), plan)\n }\n\n if (method === 'initialize') return single('legacyInitialize', method, planInitialize)\n\n if (method === 'notifications/initialized') {\n return single('legacyInitialized', method, planInitialized)\n }\n\n if (method === 'tools/list') return single('legacyList', method, planOnSession('legacyList'))\n\n if (method === 'tools/call') {\n const matched = matchRpc(request, [\n 'legacyCallRead',\n 'legacyCallToolError',\n 'legacyCallAbsent'\n ])\n\n if (isNotEmulated(matched)) return matched\n\n return admission(variant(method), admitted(matched, request), planOnSession(matched.key))\n }\n\n return notEmulated('this JSON-RPC method is not emulated on the legacy profile')\n }\n}\n\n/** `GET /legacy/mcp`: the client's standing event stream, answered the recorded 405. */\nconst legacyGetRoute: McpRoute = {\n ...routeEvidenceOf('GET', mcpEmulatorLegacyPath, [getRow]),\n body: 'none',\n admit: (request, env) => {\n const query = noQuery(request)\n\n if (query !== undefined) return query\n\n if (isReserved(request, env)) return notEmulated(reservedOnlyOnProbe)\n\n const problem =\n unrecordedMcpHeader(request) ??\n headerProblem(request, recorded.legacyGet.request, comparedHeaders)\n\n if (problem !== undefined) return problem\n\n return admission(\n getRow.path,\n {\n key: 'legacyGet',\n id: undefined,\n cursor: undefined,\n session: request.header(sessionHeader)\n },\n planOnSession('legacyGet')\n )\n }\n}\n\n/** The route table: one wire route per recorded HTTP shape, each with its manifest variants. */\nexport const mcpApiRoutes: ReadonlyArray<McpRoute> = [modernRoute, legacyRoute, legacyGetRoute]\n"],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import * as Schema from "effect/Schema";
2
+
3
+ //#region src/mcp/recordings.d.ts
4
+ /** One recorded request: method, URL, the MCP routing and session headers, the JSON-RPC body. */
5
+ type McpRecordedRequest = {
6
+ readonly method: string;
7
+ readonly url: string;
8
+ readonly headers: Readonly<Record<string, string>>;
9
+ readonly body?: Schema.Json;
10
+ };
11
+ /** One recorded answer: a whole text body, or SSE chunks (chunk boundaries kept). */
12
+ type McpRecordedResponse = {
13
+ readonly status: number;
14
+ readonly headers: Readonly<Record<string, string>>;
15
+ readonly body: string;
16
+ } | {
17
+ readonly status: number;
18
+ readonly headers: Readonly<Record<string, string>>;
19
+ readonly chunks: ReadonlyArray<string>;
20
+ };
21
+ type McpRecordedExchange = {
22
+ readonly request: McpRecordedRequest;
23
+ readonly response: McpRecordedResponse;
24
+ };
25
+ /** A copied fixture (the `WireFixture` fields, as data). */
26
+ type McpRecordedFixture = {
27
+ readonly id: string;
28
+ readonly caseId: string;
29
+ readonly evidence: 'unverified';
30
+ readonly recordedAt: string;
31
+ readonly account: string;
32
+ readonly endpoint: string;
33
+ readonly note: string;
34
+ readonly exchanges: ReadonlyArray<McpRecordedExchange>;
35
+ };
36
+ /** Every synthetic MCP fixture, in the order of `mcpConformanceFixtures`. */
37
+ declare const mcpEmulatorFixtures: ReadonlyArray<McpRecordedFixture>;
38
+ //#endregion
39
+ export { McpRecordedExchange, McpRecordedFixture, McpRecordedRequest, McpRecordedResponse, mcpEmulatorFixtures };
40
+ //# sourceMappingURL=recordings.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recordings.d.mts","names":[],"sources":["../../src/mcp/recordings.ts"],"mappings":";;;;KAcY,kBAAA;EAAA,SACD,MAAA;EAAA,SACA,GAAA;EAAA,SACA,OAAA,EAAS,QAAA,CAAS,MAAA;EAAA,SAClB,IAAA,GAAO,MAAA,CAAO,IAAA;AAAA;;KAIb,mBAAA;EAAA,SAEG,MAAA;EAAA,SACA,OAAA,EAAS,QAAA,CAAS,MAAA;EAAA,SAClB,IAAA;AAAA;EAAA,SAGA,MAAA;EAAA,SACA,OAAA,EAAS,QAAA,CAAS,MAAA;EAAA,SAClB,MAAA,EAAQ,aAAA;AAAA;AAAA,KAGX,mBAAA;EAAA,SACD,OAAA,EAAS,kBAAA;EAAA,SACT,QAAA,EAAU,mBAAmB;AAAA;;KAI5B,kBAAA;EAAA,SACD,EAAA;EAAA,SACA,MAAA;EAAA,SACA,QAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA;EAAA,SACA,QAAA;EAAA,SACA,IAAA;EAAA,SACA,SAAA,EAAW,aAAa,CAAC,mBAAA;AAAA;AAdpC;AAAA,cAkBa,mBAAA,EAAqB,aAAa,CAAC,kBAAA"}