stitchkit 0.93.0 → 0.94.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 (791) hide show
  1. package/CHANGELOG.md +134 -0
  2. package/README.md +5 -2
  3. package/dist/agent-runtime/children-control.d.ts +6 -0
  4. package/dist/agent-runtime/children-control.d.ts.map +1 -0
  5. package/dist/agent-runtime/children-spawn.d.ts +6 -0
  6. package/dist/agent-runtime/children-spawn.d.ts.map +1 -0
  7. package/dist/agent-runtime/children-state.d.ts +46 -0
  8. package/dist/agent-runtime/children-state.d.ts.map +1 -0
  9. package/dist/agent-runtime/children-usage.d.ts +8 -0
  10. package/dist/agent-runtime/children-usage.d.ts.map +1 -0
  11. package/dist/agent-runtime/children.d.ts +11 -14
  12. package/dist/agent-runtime/children.d.ts.map +1 -1
  13. package/dist/agent-runtime/coding-tool-contract.d.ts +2 -1
  14. package/dist/agent-runtime/coding-tool-contract.d.ts.map +1 -1
  15. package/dist/agent-runtime/deferred-tool-types.d.ts +2 -2
  16. package/dist/agent-runtime/deferred-tool-types.d.ts.map +1 -1
  17. package/dist/agent-runtime/events.d.ts +1 -1
  18. package/dist/agent-runtime/events.d.ts.map +1 -1
  19. package/dist/agent-runtime/managed-tools.d.ts +1 -1
  20. package/dist/agent-runtime/managed-tools.d.ts.map +1 -1
  21. package/dist/agent-runtime/observability.d.ts +1 -1
  22. package/dist/agent-runtime/observability.d.ts.map +1 -1
  23. package/dist/{agent-runtime-openrouter.d.ts → agent-runtime/openrouter.d.ts} +3 -3
  24. package/dist/agent-runtime/openrouter.d.ts.map +1 -0
  25. package/dist/agent-runtime/projections.d.ts +1 -1
  26. package/dist/agent-runtime/projections.d.ts.map +1 -1
  27. package/dist/agent-runtime/run-acquisition.d.ts +17 -0
  28. package/dist/agent-runtime/run-acquisition.d.ts.map +1 -0
  29. package/dist/agent-runtime/run-execution-state.d.ts +133 -0
  30. package/dist/agent-runtime/run-execution-state.d.ts.map +1 -0
  31. package/dist/agent-runtime/run-execution.d.ts +17 -33
  32. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  33. package/dist/agent-runtime/run-failure.d.ts +18 -0
  34. package/dist/agent-runtime/run-failure.d.ts.map +1 -0
  35. package/dist/agent-runtime/run-model-attempts.d.ts +6 -0
  36. package/dist/agent-runtime/run-model-attempts.d.ts.map +1 -0
  37. package/dist/agent-runtime/run-prompt-history.d.ts +58 -0
  38. package/dist/agent-runtime/run-prompt-history.d.ts.map +1 -0
  39. package/dist/agent-runtime/run-provider-ledger.d.ts +26 -0
  40. package/dist/agent-runtime/run-provider-ledger.d.ts.map +1 -0
  41. package/dist/agent-runtime/run-stream-parts.d.ts +17 -0
  42. package/dist/agent-runtime/run-stream-parts.d.ts.map +1 -0
  43. package/dist/agent-runtime/run-terminal.d.ts +11 -0
  44. package/dist/agent-runtime/run-terminal.d.ts.map +1 -0
  45. package/dist/agent-runtime/run-turn-preparation.d.ts +22 -0
  46. package/dist/agent-runtime/run-turn-preparation.d.ts.map +1 -0
  47. package/dist/agent-runtime/runtime-admission-gate.d.ts +29 -0
  48. package/dist/agent-runtime/runtime-admission-gate.d.ts.map +1 -0
  49. package/dist/agent-runtime/runtime-control.d.ts +9 -0
  50. package/dist/agent-runtime/runtime-control.d.ts.map +1 -0
  51. package/dist/agent-runtime/runtime-recovery.d.ts +10 -0
  52. package/dist/agent-runtime/runtime-recovery.d.ts.map +1 -0
  53. package/dist/agent-runtime/runtime-state.d.ts +36 -0
  54. package/dist/agent-runtime/runtime-state.d.ts.map +1 -0
  55. package/dist/agent-runtime/runtime-submit.d.ts +5 -0
  56. package/dist/agent-runtime/runtime-submit.d.ts.map +1 -0
  57. package/dist/agent-runtime/runtime.d.ts +9 -4
  58. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  59. package/dist/{agent-runtime-sqlite-bun.d.ts → agent-runtime/sqlite-bun.d.ts} +5 -4
  60. package/dist/agent-runtime/sqlite-bun.d.ts.map +1 -0
  61. package/dist/agent-runtime/sqlite-events.d.ts +5 -0
  62. package/dist/agent-runtime/sqlite-events.d.ts.map +1 -0
  63. package/dist/agent-runtime/sqlite-history.d.ts +7 -0
  64. package/dist/agent-runtime/sqlite-history.d.ts.map +1 -0
  65. package/dist/agent-runtime/sqlite-ledger.d.ts +7 -0
  66. package/dist/agent-runtime/sqlite-ledger.d.ts.map +1 -0
  67. package/dist/{agent-runtime-sqlite-node.d.ts → agent-runtime/sqlite-node.d.ts} +5 -4
  68. package/dist/agent-runtime/sqlite-node.d.ts.map +1 -0
  69. package/dist/agent-runtime/sqlite-reads.d.ts +14 -0
  70. package/dist/agent-runtime/sqlite-reads.d.ts.map +1 -0
  71. package/dist/agent-runtime/sqlite-rows.d.ts +178 -0
  72. package/dist/agent-runtime/sqlite-rows.d.ts.map +1 -0
  73. package/dist/agent-runtime/sqlite-schema.d.ts +7 -0
  74. package/dist/agent-runtime/sqlite-schema.d.ts.map +1 -0
  75. package/dist/agent-runtime/sqlite-transactions.d.ts +25 -0
  76. package/dist/agent-runtime/sqlite-transactions.d.ts.map +1 -0
  77. package/dist/agent-runtime/sqlite.d.ts +10 -6
  78. package/dist/agent-runtime/sqlite.d.ts.map +1 -1
  79. package/dist/agent-runtime/store-archive.d.ts +16 -0
  80. package/dist/agent-runtime/store-archive.d.ts.map +1 -0
  81. package/dist/{testing/agent-store-conformance.d.ts → agent-runtime/store-conformance.d.ts} +2 -2
  82. package/dist/agent-runtime/store-conformance.d.ts.map +1 -0
  83. package/dist/agent-runtime/store-create.d.ts +11 -0
  84. package/dist/agent-runtime/store-create.d.ts.map +1 -0
  85. package/dist/agent-runtime/{store-driver.d.ts → store-driver-contract.d.ts} +7 -7
  86. package/dist/agent-runtime/store-driver-contract.d.ts.map +1 -0
  87. package/dist/agent-runtime/store-events.d.ts +7 -89
  88. package/dist/agent-runtime/store-events.d.ts.map +1 -1
  89. package/dist/agent-runtime/store-memory.d.ts +4 -0
  90. package/dist/agent-runtime/store-memory.d.ts.map +1 -0
  91. package/dist/agent-runtime/store-mutate.d.ts +13 -0
  92. package/dist/agent-runtime/store-mutate.d.ts.map +1 -0
  93. package/dist/agent-runtime/store-purge.d.ts +1 -1
  94. package/dist/agent-runtime/store-purge.d.ts.map +1 -1
  95. package/dist/agent-runtime/store-reads.d.ts +29 -0
  96. package/dist/agent-runtime/store-reads.d.ts.map +1 -0
  97. package/dist/agent-runtime/store-reduce-history.d.ts +10 -0
  98. package/dist/agent-runtime/store-reduce-history.d.ts.map +1 -0
  99. package/dist/agent-runtime/store-reduce-run.d.ts +14 -0
  100. package/dist/agent-runtime/store-reduce-run.d.ts.map +1 -0
  101. package/dist/agent-runtime/store-reduce-shared.d.ts +76 -0
  102. package/dist/agent-runtime/store-reduce-shared.d.ts.map +1 -0
  103. package/dist/agent-runtime/store-reduce-terminal.d.ts +6 -0
  104. package/dist/agent-runtime/store-reduce-terminal.d.ts.map +1 -0
  105. package/dist/agent-runtime/store-reducer.d.ts +24 -0
  106. package/dist/agent-runtime/store-reducer.d.ts.map +1 -0
  107. package/dist/agent-runtime/store-snapshot.d.ts +19 -0
  108. package/dist/agent-runtime/store-snapshot.d.ts.map +1 -0
  109. package/dist/agent-runtime/store.d.ts +1 -1
  110. package/dist/agent-runtime/store.d.ts.map +1 -1
  111. package/dist/application/admission.d.ts +1 -1
  112. package/dist/application/admission.d.ts.map +1 -1
  113. package/dist/application/events.d.ts +1 -1
  114. package/dist/application/events.d.ts.map +1 -1
  115. package/dist/{server → application}/file-state-store.d.ts +1 -1
  116. package/dist/application/file-state-store.d.ts.map +1 -0
  117. package/dist/application/health.d.ts +1 -1
  118. package/dist/application/health.d.ts.map +1 -1
  119. package/dist/application/kernel-admission.d.ts +8 -0
  120. package/dist/application/kernel-admission.d.ts.map +1 -0
  121. package/dist/application/kernel-contract.d.ts +142 -0
  122. package/dist/application/kernel-contract.d.ts.map +1 -0
  123. package/dist/application/kernel-resource-context.d.ts +24 -0
  124. package/dist/application/kernel-resource-context.d.ts.map +1 -0
  125. package/dist/application/kernel-restart.d.ts +5 -0
  126. package/dist/application/kernel-restart.d.ts.map +1 -0
  127. package/dist/application/kernel-rollback.d.ts +4 -0
  128. package/dist/application/kernel-rollback.d.ts.map +1 -0
  129. package/dist/application/kernel-shutdown.d.ts +6 -0
  130. package/dist/application/kernel-shutdown.d.ts.map +1 -0
  131. package/dist/application/kernel-start.d.ts +20 -0
  132. package/dist/application/kernel-start.d.ts.map +1 -0
  133. package/dist/application/kernel-state.d.ts +116 -0
  134. package/dist/application/kernel-state.d.ts.map +1 -0
  135. package/dist/application/kernel.d.ts +9 -140
  136. package/dist/application/kernel.d.ts.map +1 -1
  137. package/dist/application/latest-sink.d.ts +1 -1
  138. package/dist/application/latest-sink.d.ts.map +1 -1
  139. package/dist/application/opentelemetry.d.ts +1 -1
  140. package/dist/application/opentelemetry.d.ts.map +1 -1
  141. package/dist/application/watch-hub.d.ts +2 -2
  142. package/dist/application/watch-hub.d.ts.map +1 -1
  143. package/dist/browser/client-multipart.d.ts +1 -1
  144. package/dist/browser/client-multipart.d.ts.map +1 -1
  145. package/dist/browser/client-url.d.ts +1 -1
  146. package/dist/browser/client-url.d.ts.map +1 -1
  147. package/dist/browser/client.d.ts +1 -1
  148. package/dist/browser/client.d.ts.map +1 -1
  149. package/dist/browser/contract-stream.d.ts +1 -1
  150. package/dist/browser/contract-stream.d.ts.map +1 -1
  151. package/dist/browser/http.d.ts +1 -1
  152. package/dist/browser/http.d.ts.map +1 -1
  153. package/dist/browser/resumable.d.ts +1 -28
  154. package/dist/browser/resumable.d.ts.map +1 -1
  155. package/dist/browser/retained.d.ts.map +1 -0
  156. package/dist/browser/socket-io.d.ts +23 -1
  157. package/dist/browser/socket-io.d.ts.map +1 -1
  158. package/dist/browser/stream.d.ts +14 -2
  159. package/dist/browser/stream.d.ts.map +1 -1
  160. package/dist/contract/define.d.ts +72 -65
  161. package/dist/contract/define.d.ts.map +1 -1
  162. package/dist/{internal/errors.d.ts → contract/normalize.d.ts} +3 -39
  163. package/dist/contract/normalize.d.ts.map +1 -0
  164. package/dist/contract/tool-view.d.ts +135 -0
  165. package/dist/contract/tool-view.d.ts.map +1 -0
  166. package/dist/declaration/declaration.d.ts.map +1 -0
  167. package/dist/{agent-runtime/durability-contract.d.ts → durability/contract.d.ts} +2 -2
  168. package/dist/durability/contract.d.ts.map +1 -0
  169. package/dist/{agent-runtime/durability.d.ts → durability/engine.d.ts} +4 -4
  170. package/dist/durability/engine.d.ts.map +1 -0
  171. package/dist/durability/events.d.ts +101 -0
  172. package/dist/durability/events.d.ts.map +1 -0
  173. package/dist/{agent-runtime/durability-json.d.ts → durability/json.d.ts} +1 -1
  174. package/dist/durability/json.d.ts.map +1 -0
  175. package/dist/{agent-runtime/durability-ledger.d.ts → durability/ledger.d.ts} +2 -2
  176. package/dist/durability/ledger.d.ts.map +1 -0
  177. package/dist/{agent-runtime/durability-scheduler.d.ts → durability/scheduler.d.ts} +2 -2
  178. package/dist/durability/scheduler.d.ts.map +1 -0
  179. package/dist/entrypoints/agent-runtime/browser.d.ts +5 -0
  180. package/dist/entrypoints/agent-runtime/browser.d.ts.map +1 -0
  181. package/dist/{agent-runtime-browser.js → entrypoints/agent-runtime/browser.js} +3 -3
  182. package/dist/{agent-runtime-coding-tools.d.ts → entrypoints/agent-runtime/coding-tools.d.ts} +2 -2
  183. package/dist/entrypoints/agent-runtime/coding-tools.d.ts.map +1 -0
  184. package/dist/entrypoints/agent-runtime/coding-tools.js +22 -0
  185. package/dist/{agent-runtime-harness.d.ts → entrypoints/agent-runtime/harness.d.ts} +2 -2
  186. package/dist/entrypoints/agent-runtime/harness.d.ts.map +1 -0
  187. package/dist/{agent-runtime-harness.js → entrypoints/agent-runtime/harness.js} +24 -25
  188. package/dist/entrypoints/agent-runtime/openrouter.d.ts +2 -0
  189. package/dist/entrypoints/agent-runtime/openrouter.d.ts.map +1 -0
  190. package/dist/{agent-runtime-openrouter.js → entrypoints/agent-runtime/openrouter.js} +3 -3
  191. package/dist/{agent-runtime-sandbox.d.ts → entrypoints/agent-runtime/sandbox.d.ts} +5 -5
  192. package/dist/entrypoints/agent-runtime/sandbox.d.ts.map +1 -0
  193. package/dist/{agent-runtime-sandbox.js → entrypoints/agent-runtime/sandbox.js} +11 -12
  194. package/dist/entrypoints/agent-runtime/sqlite/bun.d.ts +2 -0
  195. package/dist/entrypoints/agent-runtime/sqlite/bun.d.ts.map +1 -0
  196. package/dist/{agent-runtime-sqlite-bun.js → entrypoints/agent-runtime/sqlite/bun.js} +8 -6
  197. package/dist/entrypoints/agent-runtime/sqlite/node.d.ts +2 -0
  198. package/dist/entrypoints/agent-runtime/sqlite/node.d.ts.map +1 -0
  199. package/dist/{agent-runtime-sqlite-node.js → entrypoints/agent-runtime/sqlite/node.js} +8 -6
  200. package/dist/entrypoints/agent-runtime/testing.d.ts +4 -0
  201. package/dist/entrypoints/agent-runtime/testing.d.ts.map +1 -0
  202. package/dist/entrypoints/agent-runtime/testing.js +1084 -0
  203. package/dist/{agent-runtime.d.ts → entrypoints/agent-runtime.d.ts} +41 -37
  204. package/dist/entrypoints/agent-runtime.d.ts.map +1 -0
  205. package/dist/{agent-runtime.js → entrypoints/agent-runtime.js} +408 -366
  206. package/dist/{application-diagnostic-journal.d.ts → entrypoints/application/diagnostic-journal.d.ts} +2 -2
  207. package/dist/entrypoints/application/diagnostic-journal.d.ts.map +1 -0
  208. package/dist/{application-diagnostic-journal.js → entrypoints/application/diagnostic-journal.js} +3 -3
  209. package/dist/{application-grammy.d.ts → entrypoints/application/grammy.d.ts} +2 -2
  210. package/dist/entrypoints/application/grammy.d.ts.map +1 -0
  211. package/dist/{application-grammy.js → entrypoints/application/grammy.js} +2 -2
  212. package/dist/{application-opentelemetry.d.ts → entrypoints/application/opentelemetry.d.ts} +2 -2
  213. package/dist/entrypoints/application/opentelemetry.d.ts.map +1 -0
  214. package/dist/{application-opentelemetry.js → entrypoints/application/opentelemetry.js} +4 -4
  215. package/dist/{application-schemas.d.ts → entrypoints/application/schemas.d.ts} +2 -2
  216. package/dist/entrypoints/application/schemas.d.ts.map +1 -0
  217. package/dist/{application-schemas.js → entrypoints/application/schemas.js} +2 -2
  218. package/dist/{application.d.ts → entrypoints/application.d.ts} +22 -21
  219. package/dist/entrypoints/application.d.ts.map +1 -0
  220. package/dist/{application.js → entrypoints/application.js} +24 -22
  221. package/dist/entrypoints/bin/upgrade-cli.d.ts.map +1 -0
  222. package/dist/{upgrade-cli.js → entrypoints/bin/upgrade-cli.js} +3 -3
  223. package/dist/{cli.d.ts → entrypoints/cli.d.ts} +15 -15
  224. package/dist/entrypoints/cli.d.ts.map +1 -0
  225. package/dist/{cli.js → entrypoints/cli.js} +30 -32
  226. package/dist/entrypoints/contract.d.ts +9 -0
  227. package/dist/entrypoints/contract.d.ts.map +1 -0
  228. package/dist/{contract/index.js → entrypoints/contract.js} +14 -6
  229. package/dist/entrypoints/declaration.d.ts +2 -0
  230. package/dist/entrypoints/declaration.d.ts.map +1 -0
  231. package/dist/{declaration.js → entrypoints/declaration.js} +1 -1
  232. package/dist/{files.d.ts → entrypoints/files.d.ts} +2 -2
  233. package/dist/entrypoints/files.d.ts.map +1 -0
  234. package/dist/{files.js → entrypoints/files.js} +3 -3
  235. package/dist/{geo.d.ts → entrypoints/geo.d.ts} +1 -1
  236. package/dist/entrypoints/geo.d.ts.map +1 -0
  237. package/dist/{geo.js → entrypoints/geo.js} +4 -4
  238. package/dist/entrypoints/google.d.ts +2 -0
  239. package/dist/entrypoints/google.d.ts.map +1 -0
  240. package/dist/{google.js → entrypoints/google.js} +1 -1
  241. package/dist/{index.d.ts → entrypoints/index.d.ts} +14 -13
  242. package/dist/entrypoints/index.d.ts.map +1 -0
  243. package/dist/{index.js → entrypoints/index.js} +99 -33
  244. package/dist/{live.d.ts → entrypoints/live.d.ts} +4 -4
  245. package/dist/entrypoints/live.d.ts.map +1 -0
  246. package/dist/{live.js → entrypoints/live.js} +6 -4
  247. package/dist/{node.d.ts → entrypoints/node.d.ts} +11 -11
  248. package/dist/entrypoints/node.d.ts.map +1 -0
  249. package/dist/{node.js → entrypoints/node.js} +20 -16
  250. package/dist/entrypoints/oauth.d.ts +2 -0
  251. package/dist/entrypoints/oauth.d.ts.map +1 -0
  252. package/dist/{oauth.js → entrypoints/oauth.js} +3 -3
  253. package/dist/{observability/index.d.ts → entrypoints/observability.d.ts} +11 -11
  254. package/dist/entrypoints/observability.d.ts.map +1 -0
  255. package/dist/{observability/index.js → entrypoints/observability.js} +9 -11
  256. package/dist/entrypoints/primitives.d.ts +3 -0
  257. package/dist/entrypoints/primitives.d.ts.map +1 -0
  258. package/dist/{primitives.js → entrypoints/primitives.js} +1 -6
  259. package/dist/{react.d.ts → entrypoints/react.d.ts} +4 -4
  260. package/dist/entrypoints/react.d.ts.map +1 -0
  261. package/dist/{react.js → entrypoints/react.js} +3 -3
  262. package/dist/{release.d.ts → entrypoints/release.d.ts} +4 -4
  263. package/dist/entrypoints/release.d.ts.map +1 -0
  264. package/dist/{release.js → entrypoints/release.js} +1 -1
  265. package/dist/{remote.d.ts → entrypoints/remote.d.ts} +1 -1
  266. package/dist/entrypoints/remote.d.ts.map +1 -0
  267. package/dist/entrypoints/remote.js +66 -0
  268. package/dist/{server/index.d.ts → entrypoints/server.d.ts} +35 -34
  269. package/dist/entrypoints/server.d.ts.map +1 -0
  270. package/dist/{server/index.js → entrypoints/server.js} +294 -244
  271. package/dist/{telegram.d.ts → entrypoints/telegram.d.ts} +2 -2
  272. package/dist/entrypoints/telegram.d.ts.map +1 -0
  273. package/dist/{telegram.js → entrypoints/telegram.js} +1 -1
  274. package/dist/entrypoints/testing.d.ts +9 -0
  275. package/dist/entrypoints/testing.d.ts.map +1 -0
  276. package/dist/{testing.js → entrypoints/testing.js} +80 -919
  277. package/dist/{tools/connections/index.d.ts → entrypoints/tools/connections.d.ts} +6 -7
  278. package/dist/entrypoints/tools/connections.d.ts.map +1 -0
  279. package/dist/{tools/connections/index.js → entrypoints/tools/connections.js} +7 -4
  280. package/dist/{tools-contract.d.ts → entrypoints/tools/contract.d.ts} +5 -5
  281. package/dist/entrypoints/tools/contract.d.ts.map +1 -0
  282. package/dist/{tools-contract.js → entrypoints/tools/contract.js} +4 -4
  283. package/dist/{tool-invoker.d.ts → entrypoints/tools/invoker.d.ts} +2 -2
  284. package/dist/entrypoints/tools/invoker.d.ts.map +1 -0
  285. package/dist/entrypoints/tools/invoker.js +20 -0
  286. package/dist/entrypoints/tools.d.ts +51 -0
  287. package/dist/entrypoints/tools.d.ts.map +1 -0
  288. package/dist/{tools.js → entrypoints/tools.js} +1787 -1751
  289. package/dist/{tracking-server.d.ts → entrypoints/tracking/server.d.ts} +8 -8
  290. package/dist/entrypoints/tracking/server.d.ts.map +1 -0
  291. package/dist/{tracking.d.ts → entrypoints/tracking.d.ts} +15 -15
  292. package/dist/entrypoints/tracking.d.ts.map +1 -0
  293. package/dist/{tracking.js → entrypoints/tracking.js} +5 -8
  294. package/dist/google/google.d.ts.map +1 -0
  295. package/dist/{index-a916km3r.js → index-0b1ess5e.js} +6 -13
  296. package/dist/{index-zwkgfq1s.js → index-1nd48tm9.js} +113 -118
  297. package/dist/{index-7zbps32p.js → index-1zbbzgfh.js} +2 -2
  298. package/dist/{index-mzvgxp0n.js → index-2cr1cqhn.js} +16 -4
  299. package/dist/{index-f9mb610r.js → index-35mh5bhj.js} +2 -2
  300. package/dist/index-48ffdxgk.js +6 -0
  301. package/dist/index-58k4fp34.js +1023 -0
  302. package/dist/{index-p13mwz16.js → index-83bdg97s.js} +1 -1
  303. package/dist/index-97ac4gph.js +3618 -0
  304. package/dist/{index-kw9t5ayn.js → index-cq4qfycf.js} +5 -5
  305. package/dist/{index-7gnkny4z.js → index-d9pk3td4.js} +1 -1
  306. package/dist/{index-e42wzzz5.js → index-dcpdvjsc.js} +7 -7
  307. package/dist/{index-h9etkkyk.js → index-dydjcp8z.js} +102 -25
  308. package/dist/{index-sr93cwf9.js → index-e2z3ahw9.js} +2 -2
  309. package/dist/{index-yewwh1w4.js → index-e87kakm4.js} +96 -11
  310. package/dist/{index-cby4ar3v.js → index-eqqvgdb3.js} +1 -1
  311. package/dist/index-fdp6hdxn.js +942 -0
  312. package/dist/{index-0a349c33.js → index-gyr48nzg.js} +125 -198
  313. package/dist/{index-wnfk50r0.js → index-h6eeys1v.js} +1 -1
  314. package/dist/{index-77fekveh.js → index-hffjpmq9.js} +1 -15
  315. package/dist/{index-yn8remb1.js → index-j05z5gn4.js} +50 -14
  316. package/dist/index-k5hsfc3j.js +31 -0
  317. package/dist/{index-fq77yfzc.js → index-kj2wbeta.js} +1 -1
  318. package/dist/index-kvj7f4hq.js +39 -0
  319. package/dist/{index-4fpa9dy2.js → index-m9zn6cpq.js} +2 -2
  320. package/dist/{index-2na0qrfn.js → index-mdzh02yc.js} +7 -7
  321. package/dist/{index-ywd0y6m1.js → index-mkm15s49.js} +1 -1
  322. package/dist/index-mp5sn43f.js +1084 -0
  323. package/dist/{index-3bmnp41g.js → index-n6hxg8as.js} +507 -419
  324. package/dist/index-ngfhvfpd.js +30 -0
  325. package/dist/{index-e0znv5gn.js → index-p5r7qpdd.js} +2 -93
  326. package/dist/{index-n0f51dfn.js → index-p81267c2.js} +608 -549
  327. package/dist/{index-wc4x00bn.js → index-qwhynv6x.js} +1 -1
  328. package/dist/index-r7nmqpsg.js +154 -0
  329. package/dist/{index-bx75zwt7.js → index-rewkc2hj.js} +5 -4
  330. package/dist/{index-9f8ztey6.js → index-sees8yf8.js} +2 -2
  331. package/dist/{index-vjpvjqpn.js → index-v38qyerb.js} +16 -2
  332. package/dist/{index-2c2bjw3s.js → index-vcvkq30w.js} +3 -3
  333. package/dist/index-wqgjfstn.js +18 -0
  334. package/dist/{index-f477k430.js → index-x4799c19.js} +1 -1
  335. package/dist/{index-cxqhvq21.js → index-xnj9bgxe.js} +142 -129
  336. package/dist/index-xsqjkha9.js +281 -0
  337. package/dist/{index-6kyksz9y.js → index-yw4fzmdz.js} +1 -1
  338. package/dist/{index-3xwxfj4z.js → index-zeemqhqx.js} +1 -1
  339. package/dist/{index-tmwcrptx.js → index-zfrhfn82.js} +1 -1
  340. package/dist/index-znfs20ss.js +98 -0
  341. package/dist/internal/backoff.d.ts +29 -0
  342. package/dist/internal/backoff.d.ts.map +1 -0
  343. package/dist/internal/canonical-json.d.ts +21 -11
  344. package/dist/internal/canonical-json.d.ts.map +1 -1
  345. package/dist/internal/channel.d.ts.map +1 -0
  346. package/dist/internal/logger.d.ts.map +1 -0
  347. package/dist/internal/request.d.ts.map +1 -0
  348. package/dist/internal/stable-digest.d.ts +0 -43
  349. package/dist/internal/stable-digest.d.ts.map +1 -1
  350. package/dist/internal/typed.d.ts +0 -8
  351. package/dist/internal/typed.d.ts.map +1 -1
  352. package/dist/internal/zod-issues.d.ts +38 -0
  353. package/dist/internal/zod-issues.d.ts.map +1 -0
  354. package/dist/{tools/json-schema-dialect.d.ts → json-schema/dialect.d.ts} +1 -1
  355. package/dist/json-schema/dialect.d.ts.map +1 -0
  356. package/dist/json-schema/json-schema.d.ts.map +1 -0
  357. package/dist/live/watch-delta.d.ts.map +1 -1
  358. package/dist/{oauth.d.ts → oauth/authorization-code.d.ts} +1 -1
  359. package/dist/oauth/authorization-code.d.ts.map +1 -0
  360. package/dist/observability/audit.d.ts +2 -2
  361. package/dist/observability/audit.d.ts.map +1 -1
  362. package/dist/observability/bounded-logger.d.ts +1 -1
  363. package/dist/observability/bounded-logger.d.ts.map +1 -1
  364. package/dist/{internal/observability-sink.d.ts → observability/bounded-sink.d.ts} +2 -2
  365. package/dist/observability/bounded-sink.d.ts.map +1 -0
  366. package/dist/observability/context.d.ts +1 -1
  367. package/dist/observability/context.d.ts.map +1 -1
  368. package/dist/observability/event.d.ts +1 -1
  369. package/dist/observability/event.d.ts.map +1 -1
  370. package/dist/observability/work.d.ts +1 -1
  371. package/dist/observability/work.d.ts.map +1 -1
  372. package/dist/primitives/audit.d.ts +1 -1
  373. package/dist/primitives/audit.d.ts.map +1 -1
  374. package/dist/primitives/export-operation.d.ts +4 -2
  375. package/dist/primitives/export-operation.d.ts.map +1 -1
  376. package/dist/realtime/socket.d.ts +1 -1
  377. package/dist/realtime/socket.d.ts.map +1 -1
  378. package/dist/server/context-contribution.d.ts +1 -1
  379. package/dist/server/context-contribution.d.ts.map +1 -1
  380. package/dist/server/context.d.ts +2 -2
  381. package/dist/server/context.d.ts.map +1 -1
  382. package/dist/server/contract-method.d.ts +15 -0
  383. package/dist/server/contract-method.d.ts.map +1 -0
  384. package/dist/server/contract-stream.d.ts +1 -1
  385. package/dist/server/contract-stream.d.ts.map +1 -1
  386. package/dist/server/create.d.ts +8 -0
  387. package/dist/server/create.d.ts.map +1 -1
  388. package/dist/server/endpoint-dispatch.d.ts +10 -0
  389. package/dist/server/endpoint-dispatch.d.ts.map +1 -0
  390. package/dist/server/endpoint-response.d.ts +18 -0
  391. package/dist/server/endpoint-response.d.ts.map +1 -0
  392. package/dist/server/error-dispatch.d.ts +17 -1
  393. package/dist/server/error-dispatch.d.ts.map +1 -1
  394. package/dist/server/error-hook.d.ts +2 -2
  395. package/dist/server/error-hook.d.ts.map +1 -1
  396. package/dist/server/handler-state.d.ts +44 -0
  397. package/dist/server/handler-state.d.ts.map +1 -0
  398. package/dist/server/implement.d.ts +1 -1
  399. package/dist/server/implement.d.ts.map +1 -1
  400. package/dist/server/middleware/auth.d.ts +1 -1
  401. package/dist/server/middleware/auth.d.ts.map +1 -1
  402. package/dist/server/middleware/cors.d.ts +17 -0
  403. package/dist/server/middleware/cors.d.ts.map +1 -1
  404. package/dist/server/middleware/trust-fence.d.ts +1 -1
  405. package/dist/server/middleware/trust-fence.d.ts.map +1 -1
  406. package/dist/server/multipart.d.ts +1 -1
  407. package/dist/server/multipart.d.ts.map +1 -1
  408. package/dist/{tools/oauth-metadata.d.ts → server/oauth/metadata.d.ts} +2 -2
  409. package/dist/server/oauth/metadata.d.ts.map +1 -0
  410. package/dist/{tools/oauth-provider.d.ts → server/oauth/provider.d.ts} +2 -2
  411. package/dist/server/oauth/provider.d.ts.map +1 -0
  412. package/dist/server/realtime.d.ts +1 -1
  413. package/dist/server/realtime.d.ts.map +1 -1
  414. package/dist/server/request-completion.d.ts +16 -0
  415. package/dist/server/request-completion.d.ts.map +1 -0
  416. package/dist/server/response-metadata.d.ts +1 -1
  417. package/dist/server/response-metadata.d.ts.map +1 -1
  418. package/dist/server/route-table.d.ts +9 -0
  419. package/dist/server/route-table.d.ts.map +1 -0
  420. package/dist/server/stream.d.ts +0 -13
  421. package/dist/server/stream.d.ts.map +1 -1
  422. package/dist/server/types.d.ts +7 -4
  423. package/dist/server/types.d.ts.map +1 -1
  424. package/dist/testing/handler-clients.d.ts +31 -0
  425. package/dist/testing/handler-clients.d.ts.map +1 -0
  426. package/dist/testing/managed-resource-conformance-scenarios.d.ts.map +1 -1
  427. package/dist/testing/surface-conformance.d.ts +2 -1
  428. package/dist/testing/surface-conformance.d.ts.map +1 -1
  429. package/dist/testing/surface-manifest.d.ts +30 -4
  430. package/dist/testing/surface-manifest.d.ts.map +1 -1
  431. package/dist/tools/{cli-args.d.ts → cli/args.d.ts} +1 -1
  432. package/dist/tools/cli/args.d.ts.map +1 -0
  433. package/dist/tools/{cli-checkpoint.d.ts → cli/checkpoint.d.ts} +1 -1
  434. package/dist/tools/cli/checkpoint.d.ts.map +1 -0
  435. package/dist/tools/{cli-command.d.ts → cli/command.d.ts} +4 -4
  436. package/dist/tools/cli/command.d.ts.map +1 -0
  437. package/dist/tools/{cli.d.ts → cli/config.d.ts} +5 -9
  438. package/dist/tools/cli/config.d.ts.map +1 -0
  439. package/dist/tools/cli/create-cli.d.ts +36 -0
  440. package/dist/tools/cli/create-cli.d.ts.map +1 -0
  441. package/dist/tools/cli/download.d.ts +8 -0
  442. package/dist/tools/cli/download.d.ts.map +1 -0
  443. package/dist/tools/{cli-format.d.ts → cli/format.d.ts} +2 -2
  444. package/dist/tools/cli/format.d.ts.map +1 -0
  445. package/dist/tools/cli/help.d.ts +24 -0
  446. package/dist/tools/cli/help.d.ts.map +1 -0
  447. package/dist/tools/{cli-installer.d.ts → cli/installer.d.ts} +2 -2
  448. package/dist/tools/cli/installer.d.ts.map +1 -0
  449. package/dist/tools/{cli-invoke.d.ts → cli/invoke.d.ts} +8 -8
  450. package/dist/tools/cli/invoke.d.ts.map +1 -0
  451. package/dist/tools/cli/io.d.ts +10 -0
  452. package/dist/tools/cli/io.d.ts.map +1 -0
  453. package/dist/tools/cli/managed-surface.d.ts +30 -0
  454. package/dist/tools/cli/managed-surface.d.ts.map +1 -0
  455. package/dist/tools/{cli-manifest.d.ts → cli/manifest.d.ts} +1 -1
  456. package/dist/tools/cli/manifest.d.ts.map +1 -0
  457. package/dist/tools/{cli-policy.d.ts → cli/policy.d.ts} +2 -2
  458. package/dist/tools/cli/policy.d.ts.map +1 -0
  459. package/dist/tools/cli/prepare.d.ts +14 -0
  460. package/dist/tools/cli/prepare.d.ts.map +1 -0
  461. package/dist/tools/{cli-profile.d.ts → cli/profile.d.ts} +2 -2
  462. package/dist/tools/cli/profile.d.ts.map +1 -0
  463. package/dist/tools/cli/run-managed.d.ts +5 -0
  464. package/dist/tools/cli/run-managed.d.ts.map +1 -0
  465. package/dist/tools/cli/run-native.d.ts +9 -0
  466. package/dist/tools/cli/run-native.d.ts.map +1 -0
  467. package/dist/tools/cli/session.d.ts +40 -0
  468. package/dist/tools/cli/session.d.ts.map +1 -0
  469. package/dist/tools/{cli-signature.d.ts → cli/signature.d.ts} +2 -2
  470. package/dist/tools/cli/signature.d.ts.map +1 -0
  471. package/dist/tools/{cli-stream.d.ts → cli/stream.d.ts} +4 -4
  472. package/dist/tools/cli/stream.d.ts.map +1 -0
  473. package/dist/tools/{cli-update.d.ts → cli/update.d.ts} +3 -3
  474. package/dist/tools/cli/update.d.ts.map +1 -0
  475. package/dist/tools/{cli-view.d.ts → cli/view.d.ts} +2 -2
  476. package/dist/tools/cli/view.d.ts.map +1 -0
  477. package/dist/tools/{cli-wait.d.ts → cli/wait.d.ts} +2 -2
  478. package/dist/tools/cli/wait.d.ts.map +1 -0
  479. package/dist/tools/connections/runtime.d.ts +1 -1
  480. package/dist/tools/connections/runtime.d.ts.map +1 -1
  481. package/dist/tools/connections/types.d.ts +3 -3
  482. package/dist/tools/connections/types.d.ts.map +1 -1
  483. package/dist/tools/durability-context.d.ts +1 -1
  484. package/dist/tools/durability-context.d.ts.map +1 -1
  485. package/dist/tools/execute.d.ts +30 -3
  486. package/dist/tools/execute.d.ts.map +1 -1
  487. package/dist/tools/internal/surface-projector.d.ts +8 -6
  488. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  489. package/dist/tools/internal/tool-view.d.ts +41 -0
  490. package/dist/tools/internal/tool-view.d.ts.map +1 -0
  491. package/dist/tools/invoker.d.ts +11 -3
  492. package/dist/tools/invoker.d.ts.map +1 -1
  493. package/dist/tools/list-names.d.ts +3 -3
  494. package/dist/tools/list-names.d.ts.map +1 -1
  495. package/dist/tools/manifest.d.ts +2 -2
  496. package/dist/tools/manifest.d.ts.map +1 -1
  497. package/dist/tools/{mcp-app.d.ts → mcp/app.d.ts} +1 -1
  498. package/dist/tools/mcp/app.d.ts.map +1 -0
  499. package/dist/tools/{mcp-catalog.d.ts → mcp/catalog.d.ts} +2 -2
  500. package/dist/tools/mcp/catalog.d.ts.map +1 -0
  501. package/dist/tools/{mcp-handler.d.ts → mcp/handler.d.ts} +5 -5
  502. package/dist/tools/mcp/handler.d.ts.map +1 -0
  503. package/dist/tools/{mcp.d.ts → mcp/mount.d.ts} +9 -9
  504. package/dist/tools/mcp/mount.d.ts.map +1 -0
  505. package/dist/tools/{mcp-prepare.d.ts → mcp/prepare.d.ts} +9 -9
  506. package/dist/tools/mcp/prepare.d.ts.map +1 -0
  507. package/dist/tools/{mcp-progress.d.ts → mcp/progress.d.ts} +2 -2
  508. package/dist/tools/mcp/progress.d.ts.map +1 -0
  509. package/dist/tools/mcp/register.d.ts +35 -0
  510. package/dist/tools/mcp/register.d.ts.map +1 -0
  511. package/dist/tools/{mcp-round-policy.d.ts → mcp/round-policy.d.ts} +2 -2
  512. package/dist/tools/mcp/round-policy.d.ts.map +1 -0
  513. package/dist/tools/{mcp-round.d.ts → mcp/round.d.ts} +4 -4
  514. package/dist/tools/mcp/round.d.ts.map +1 -0
  515. package/dist/tools/mcp/runtime-tools.d.ts +24 -0
  516. package/dist/tools/mcp/runtime-tools.d.ts.map +1 -0
  517. package/dist/tools/{mcp-stdio-signals.d.ts → mcp/stdio-signals.d.ts} +3 -3
  518. package/dist/tools/mcp/stdio-signals.d.ts.map +1 -0
  519. package/dist/tools/{mcp-stdio.d.ts → mcp/stdio.d.ts} +4 -4
  520. package/dist/tools/mcp/stdio.d.ts.map +1 -0
  521. package/dist/tools/{mcp-trace.d.ts → mcp/trace.d.ts} +1 -1
  522. package/dist/tools/mcp/trace.d.ts.map +1 -0
  523. package/dist/tools/mount.d.ts +12 -7
  524. package/dist/tools/mount.d.ts.map +1 -1
  525. package/dist/tools/native-definition.d.ts +3 -3
  526. package/dist/tools/native-definition.d.ts.map +1 -1
  527. package/dist/tools/operations/async-operation-binding-types.d.ts +127 -0
  528. package/dist/tools/operations/async-operation-binding-types.d.ts.map +1 -0
  529. package/dist/tools/operations/async-operation-binding.d.ts +28 -0
  530. package/dist/tools/operations/async-operation-binding.d.ts.map +1 -0
  531. package/dist/tools/operations/async-operation-canonical-types.d.ts +110 -0
  532. package/dist/tools/operations/async-operation-canonical-types.d.ts.map +1 -0
  533. package/dist/tools/operations/async-operation-canonical.d.ts +7 -0
  534. package/dist/tools/operations/async-operation-canonical.d.ts.map +1 -0
  535. package/dist/tools/operations/async-operation-contract.d.ts.map +1 -0
  536. package/dist/tools/operations/async-operation-id.d.ts +23 -0
  537. package/dist/tools/operations/async-operation-id.d.ts.map +1 -0
  538. package/dist/tools/operations/async-operation-runtime-tools.d.ts +40 -0
  539. package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -0
  540. package/dist/tools/operations/async-operation-runtime-types.d.ts +68 -0
  541. package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -0
  542. package/dist/tools/operations/async-operation-runtime.d.ts +5 -0
  543. package/dist/tools/operations/async-operation-runtime.d.ts.map +1 -0
  544. package/dist/tools/{define-wait-tool.d.ts → operations/define-wait-tool.d.ts} +2 -2
  545. package/dist/tools/operations/define-wait-tool.d.ts.map +1 -0
  546. package/dist/tools/operations/mount-wait.d.ts.map +1 -0
  547. package/dist/tools/operations/wait-core.d.ts.map +1 -0
  548. package/dist/tools/remote.d.ts +1 -1
  549. package/dist/tools/remote.d.ts.map +1 -1
  550. package/dist/tools/runtime-tool.d.ts +11 -4
  551. package/dist/tools/runtime-tool.d.ts.map +1 -1
  552. package/dist/tools/schema/coerce.d.ts.map +1 -0
  553. package/dist/tools/schema/flatten-join.d.ts.map +1 -0
  554. package/dist/tools/schema/flatten.d.ts.map +1 -0
  555. package/dist/tools/schema/portable-formats.d.ts.map +1 -0
  556. package/dist/tools/{presentation.d.ts → schema/presentation.d.ts} +2 -0
  557. package/dist/tools/schema/presentation.d.ts.map +1 -0
  558. package/dist/tools/schema/schema.d.ts.map +1 -0
  559. package/dist/tools/schema/untyped-properties.d.ts.map +1 -0
  560. package/dist/tools/surface.d.ts +2 -3
  561. package/dist/tools/surface.d.ts.map +1 -1
  562. package/dist/tools/toolkit.d.ts +4 -4
  563. package/dist/tools/toolkit.d.ts.map +1 -1
  564. package/dist/tools/{define-download-tool.d.ts → transfer/define-download-tool.d.ts} +4 -4
  565. package/dist/tools/transfer/define-download-tool.d.ts.map +1 -0
  566. package/dist/tools/{define-upload-tool.d.ts → transfer/define-upload-tool.d.ts} +3 -3
  567. package/dist/tools/transfer/define-upload-tool.d.ts.map +1 -0
  568. package/dist/tools/{define-view-file-tool.d.ts → transfer/define-view-file-tool.d.ts} +2 -2
  569. package/dist/tools/transfer/define-view-file-tool.d.ts.map +1 -0
  570. package/dist/tools/{download-core.d.ts → transfer/download-core.d.ts} +2 -2
  571. package/dist/tools/transfer/download-core.d.ts.map +1 -0
  572. package/dist/tools/{managed-file-error.d.ts → transfer/managed-file-error.d.ts} +1 -1
  573. package/dist/tools/transfer/managed-file-error.d.ts.map +1 -0
  574. package/dist/tools/{mount-download.d.ts → transfer/mount-download.d.ts} +1 -1
  575. package/dist/tools/transfer/mount-download.d.ts.map +1 -0
  576. package/dist/tools/{mount-upload.d.ts → transfer/mount-upload.d.ts} +1 -1
  577. package/dist/tools/transfer/mount-upload.d.ts.map +1 -0
  578. package/dist/tools/transfer/native-result.d.ts.map +1 -0
  579. package/dist/tools/{upload-core.d.ts → transfer/upload-core.d.ts} +1 -1
  580. package/dist/tools/transfer/upload-core.d.ts.map +1 -0
  581. package/dist/tools/transfer/view-file-contract.d.ts.map +1 -0
  582. package/dist/tools/{view-file.d.ts → transfer/view-file.d.ts} +1 -1
  583. package/dist/tools/transfer/view-file.d.ts.map +1 -0
  584. package/dist/tools/transports.d.ts +1 -1
  585. package/dist/tools/transports.d.ts.map +1 -1
  586. package/dist/tracking/contract.d.ts +1 -1
  587. package/dist/tracking/contract.d.ts.map +1 -1
  588. package/llms/agent-runtime-browser.txt +33 -0
  589. package/llms/agent-runtime-coding-tools.txt +58 -0
  590. package/llms/agent-runtime-harness.txt +45 -0
  591. package/llms/agent-runtime-openrouter.txt +22 -0
  592. package/llms/agent-runtime-sandbox.txt +159 -0
  593. package/llms/agent-runtime-sqlite-bun.txt +29 -0
  594. package/llms/agent-runtime-sqlite-node.txt +26 -0
  595. package/llms/agent-runtime-testing.txt +30 -0
  596. package/llms/agent-runtime.2.txt +550 -0
  597. package/llms/agent-runtime.3.txt +311 -0
  598. package/llms/agent-runtime.txt +893 -0
  599. package/llms/application-diagnostic-journal.txt +30 -0
  600. package/llms/application-grammy.txt +27 -0
  601. package/llms/application-opentelemetry.txt +27 -0
  602. package/llms/application-schemas.txt +42 -0
  603. package/llms/application.2.txt +223 -0
  604. package/llms/application.txt +1144 -0
  605. package/llms/cli.txt +977 -0
  606. package/llms/contract.txt +606 -0
  607. package/llms/declaration.txt +286 -0
  608. package/llms/files.txt +30 -0
  609. package/llms/geo.txt +114 -0
  610. package/llms/google.txt +27 -0
  611. package/llms/live.txt +471 -0
  612. package/llms/node.txt +43 -0
  613. package/llms/oauth.txt +136 -0
  614. package/llms/observability.txt +893 -0
  615. package/llms/primitives.txt +158 -0
  616. package/llms/react.txt +184 -0
  617. package/llms/release.txt +176 -0
  618. package/llms/remote.txt +25 -0
  619. package/llms/server.2.txt +361 -0
  620. package/llms/server.3.txt +1031 -0
  621. package/llms/server.4.txt +905 -0
  622. package/llms/server.5.txt +250 -0
  623. package/llms/server.txt +996 -0
  624. package/llms/stitchkit.2.txt +836 -0
  625. package/llms/stitchkit.3.txt +147 -0
  626. package/llms/stitchkit.txt +260 -0
  627. package/llms/telegram.txt +30 -0
  628. package/llms/testing.txt +676 -0
  629. package/llms/tools-connections.txt +45 -0
  630. package/llms/tools-contract.txt +9 -0
  631. package/llms/tools-invoker.txt +9 -0
  632. package/llms/tools.2.txt +838 -0
  633. package/llms/tools.txt +1004 -0
  634. package/llms/tracking-server.txt +32 -0
  635. package/llms/tracking.txt +263 -0
  636. package/llms/upgrading-0.37.0-0.50.0.txt +947 -0
  637. package/llms/upgrading-0.53.0-0.67.0.txt +1174 -0
  638. package/llms/upgrading-0.68.0-0.94.0.txt +1159 -0
  639. package/llms/upgrading.txt +215 -0
  640. package/llms-full.txt +214 -75
  641. package/llms.txt +54 -5
  642. package/package.json +84 -83
  643. package/dist/agent-runtime/durability-contract.d.ts.map +0 -1
  644. package/dist/agent-runtime/durability-json.d.ts.map +0 -1
  645. package/dist/agent-runtime/durability-ledger.d.ts.map +0 -1
  646. package/dist/agent-runtime/durability-scheduler.d.ts.map +0 -1
  647. package/dist/agent-runtime/durability.d.ts.map +0 -1
  648. package/dist/agent-runtime/store-driver.d.ts.map +0 -1
  649. package/dist/agent-runtime-browser.d.ts +0 -5
  650. package/dist/agent-runtime-browser.d.ts.map +0 -1
  651. package/dist/agent-runtime-coding-tools.d.ts.map +0 -1
  652. package/dist/agent-runtime-coding-tools.js +0 -23
  653. package/dist/agent-runtime-harness.d.ts.map +0 -1
  654. package/dist/agent-runtime-openrouter.d.ts.map +0 -1
  655. package/dist/agent-runtime-sandbox.d.ts.map +0 -1
  656. package/dist/agent-runtime-sqlite-bun.d.ts.map +0 -1
  657. package/dist/agent-runtime-sqlite-node.d.ts.map +0 -1
  658. package/dist/agent-runtime-testing.d.ts +0 -3
  659. package/dist/agent-runtime-testing.d.ts.map +0 -1
  660. package/dist/agent-runtime-testing.js +0 -156
  661. package/dist/agent-runtime.d.ts.map +0 -1
  662. package/dist/application/channel.d.ts.map +0 -1
  663. package/dist/application-diagnostic-journal.d.ts.map +0 -1
  664. package/dist/application-grammy.d.ts.map +0 -1
  665. package/dist/application-opentelemetry.d.ts.map +0 -1
  666. package/dist/application-schemas.d.ts.map +0 -1
  667. package/dist/application.d.ts.map +0 -1
  668. package/dist/cli.d.ts.map +0 -1
  669. package/dist/contract/index.d.ts +0 -8
  670. package/dist/contract/index.d.ts.map +0 -1
  671. package/dist/declaration.d.ts.map +0 -1
  672. package/dist/files.d.ts.map +0 -1
  673. package/dist/geo.d.ts.map +0 -1
  674. package/dist/google.d.ts.map +0 -1
  675. package/dist/index-0j3vcp5m.js +0 -28
  676. package/dist/index-a11g2kry.js +0 -866
  677. package/dist/index-cnyk6te3.js +0 -77
  678. package/dist/index-fadnxwna.js +0 -1046
  679. package/dist/index-hrbajay7.js +0 -1196
  680. package/dist/index-s8cnx02s.js +0 -90
  681. package/dist/index-v5573g1k.js +0 -142
  682. package/dist/index-vk3kq9sb.js +0 -3344
  683. package/dist/index.d.ts.map +0 -1
  684. package/dist/internal/errors.d.ts.map +0 -1
  685. package/dist/internal/observability-sink.d.ts.map +0 -1
  686. package/dist/live.d.ts.map +0 -1
  687. package/dist/logger.d.ts.map +0 -1
  688. package/dist/node.d.ts.map +0 -1
  689. package/dist/oauth.d.ts.map +0 -1
  690. package/dist/observability/index.d.ts.map +0 -1
  691. package/dist/primitives.d.ts +0 -3
  692. package/dist/primitives.d.ts.map +0 -1
  693. package/dist/react.d.ts.map +0 -1
  694. package/dist/release.d.ts.map +0 -1
  695. package/dist/remote.d.ts.map +0 -1
  696. package/dist/remote.js +0 -88
  697. package/dist/retained.d.ts.map +0 -1
  698. package/dist/server/file-state-store.d.ts.map +0 -1
  699. package/dist/server/index.d.ts.map +0 -1
  700. package/dist/server/request.d.ts.map +0 -1
  701. package/dist/telegram.d.ts.map +0 -1
  702. package/dist/testing/agent-store-conformance.d.ts.map +0 -1
  703. package/dist/testing.d.ts +0 -39
  704. package/dist/testing.d.ts.map +0 -1
  705. package/dist/tool-invoker.d.ts.map +0 -1
  706. package/dist/tool-invoker.js +0 -21
  707. package/dist/tools/async-operation-contract.d.ts.map +0 -1
  708. package/dist/tools/async-operation.d.ts +0 -332
  709. package/dist/tools/async-operation.d.ts.map +0 -1
  710. package/dist/tools/cli-args.d.ts.map +0 -1
  711. package/dist/tools/cli-checkpoint.d.ts.map +0 -1
  712. package/dist/tools/cli-command.d.ts.map +0 -1
  713. package/dist/tools/cli-format.d.ts.map +0 -1
  714. package/dist/tools/cli-installer.d.ts.map +0 -1
  715. package/dist/tools/cli-invoke.d.ts.map +0 -1
  716. package/dist/tools/cli-manifest.d.ts.map +0 -1
  717. package/dist/tools/cli-policy.d.ts.map +0 -1
  718. package/dist/tools/cli-profile.d.ts.map +0 -1
  719. package/dist/tools/cli-signature.d.ts.map +0 -1
  720. package/dist/tools/cli-stream.d.ts.map +0 -1
  721. package/dist/tools/cli-update.d.ts.map +0 -1
  722. package/dist/tools/cli-view.d.ts.map +0 -1
  723. package/dist/tools/cli-wait.d.ts.map +0 -1
  724. package/dist/tools/cli.d.ts.map +0 -1
  725. package/dist/tools/coerce.d.ts.map +0 -1
  726. package/dist/tools/connections/index.d.ts.map +0 -1
  727. package/dist/tools/define-download-tool.d.ts.map +0 -1
  728. package/dist/tools/define-upload-tool.d.ts.map +0 -1
  729. package/dist/tools/define-view-file-tool.d.ts.map +0 -1
  730. package/dist/tools/define-wait-tool.d.ts.map +0 -1
  731. package/dist/tools/download-core.d.ts.map +0 -1
  732. package/dist/tools/flatten-join.d.ts.map +0 -1
  733. package/dist/tools/flatten.d.ts.map +0 -1
  734. package/dist/tools/json-schema-dialect.d.ts.map +0 -1
  735. package/dist/tools/json-schema.d.ts.map +0 -1
  736. package/dist/tools/managed-file-error.d.ts.map +0 -1
  737. package/dist/tools/mcp-app.d.ts.map +0 -1
  738. package/dist/tools/mcp-catalog.d.ts.map +0 -1
  739. package/dist/tools/mcp-handler.d.ts.map +0 -1
  740. package/dist/tools/mcp-prepare.d.ts.map +0 -1
  741. package/dist/tools/mcp-progress.d.ts.map +0 -1
  742. package/dist/tools/mcp-round-policy.d.ts.map +0 -1
  743. package/dist/tools/mcp-round.d.ts.map +0 -1
  744. package/dist/tools/mcp-stdio-signals.d.ts.map +0 -1
  745. package/dist/tools/mcp-stdio.d.ts.map +0 -1
  746. package/dist/tools/mcp-trace.d.ts.map +0 -1
  747. package/dist/tools/mcp.d.ts.map +0 -1
  748. package/dist/tools/mount-download.d.ts.map +0 -1
  749. package/dist/tools/mount-upload.d.ts.map +0 -1
  750. package/dist/tools/mount-wait.d.ts.map +0 -1
  751. package/dist/tools/native-mcp.d.ts +0 -20
  752. package/dist/tools/native-mcp.d.ts.map +0 -1
  753. package/dist/tools/native-result.d.ts.map +0 -1
  754. package/dist/tools/oauth-metadata.d.ts.map +0 -1
  755. package/dist/tools/oauth-provider.d.ts.map +0 -1
  756. package/dist/tools/portable-formats.d.ts.map +0 -1
  757. package/dist/tools/presentation.d.ts.map +0 -1
  758. package/dist/tools/schema.d.ts.map +0 -1
  759. package/dist/tools/untyped-properties.d.ts.map +0 -1
  760. package/dist/tools/upload-core.d.ts.map +0 -1
  761. package/dist/tools/view-file-contract.d.ts.map +0 -1
  762. package/dist/tools/view-file.d.ts.map +0 -1
  763. package/dist/tools/wait-core.d.ts.map +0 -1
  764. package/dist/tools-contract.d.ts.map +0 -1
  765. package/dist/tools.d.ts +0 -50
  766. package/dist/tools.d.ts.map +0 -1
  767. package/dist/tracking-server.d.ts.map +0 -1
  768. package/dist/tracking.d.ts.map +0 -1
  769. package/dist/upgrade-cli.d.ts.map +0 -1
  770. package/dist/{retained.d.ts → browser/retained.d.ts} +0 -0
  771. package/dist/{declaration.d.ts → declaration/declaration.d.ts} +0 -0
  772. package/dist/{upgrade-cli.d.ts → entrypoints/bin/upgrade-cli.d.ts} +0 -0
  773. package/dist/{tracking-server.js → entrypoints/tracking/server.js} +0 -0
  774. package/dist/{google.d.ts → google/google.d.ts} +0 -0
  775. package/dist/{index-pq95qkbf.js → index-5jm36zv1.js} +0 -0
  776. package/dist/{index-actkayzn.js → index-70yj2ebz.js} +3 -3
  777. /package/dist/{application → internal}/channel.d.ts +0 -0
  778. /package/dist/{logger.d.ts → internal/logger.d.ts} +0 -0
  779. /package/dist/{server → internal}/request.d.ts +0 -0
  780. /package/dist/{tools → json-schema}/json-schema.d.ts +0 -0
  781. /package/dist/tools/{async-operation-contract.d.ts → operations/async-operation-contract.d.ts} +0 -0
  782. /package/dist/tools/{mount-wait.d.ts → operations/mount-wait.d.ts} +0 -0
  783. /package/dist/tools/{wait-core.d.ts → operations/wait-core.d.ts} +0 -0
  784. /package/dist/tools/{coerce.d.ts → schema/coerce.d.ts} +0 -0
  785. /package/dist/tools/{flatten-join.d.ts → schema/flatten-join.d.ts} +0 -0
  786. /package/dist/tools/{flatten.d.ts → schema/flatten.d.ts} +0 -0
  787. /package/dist/tools/{portable-formats.d.ts → schema/portable-formats.d.ts} +0 -0
  788. /package/dist/tools/{schema.d.ts → schema/schema.d.ts} +0 -0
  789. /package/dist/tools/{untyped-properties.d.ts → schema/untyped-properties.d.ts} +0 -0
  790. /package/dist/tools/{native-result.d.ts → transfer/native-result.d.ts} +0 -0
  791. /package/dist/tools/{view-file-contract.d.ts → transfer/view-file-contract.d.ts} +0 -0
package/llms/tools.txt ADDED
@@ -0,0 +1,1004 @@
1
+ # stitchkit/tools — stitchkit docs slice, part 1 of 2
2
+
3
+ > Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
4
+ > `llms.txt` in this package.
5
+ > Continues in `llms/tools.2.txt`.
6
+
7
+ Parts of this slice:
8
+ - `llms/tools.txt`: Guide: MCP & agents (docs/guide/mcp-and-agents.md)
9
+ - `llms/tools.2.txt`: Guide: MCP & agents (docs/guide/mcp-and-agents.md) · API reference: `stitchkit/tools` (docs/api/reference.md)
10
+
11
+ ==============================================================================
12
+ # Guide: MCP & agents (docs/guide/mcp-and-agents.md)
13
+ ==============================================================================
14
+
15
+ # MCP & AI agents
16
+
17
+ The application generated by `bun create stitchkit` includes a working
18
+ stateless MCP endpoint and a separate `bun run tools` manifest command. Both
19
+ are assembled from the same implemented project contracts as HTTP and CLI, so
20
+ the generated project is the canonical end-to-end example for this chapter.
21
+
22
+ The same contract that drives the HTTP API also drives AI tooling. An endpoint
23
+ exposed on `MCP` becomes a [Model Context Protocol](https://modelcontextprotocol.io)
24
+ tool — callable from Claude, Cursor and other MCP clients. An endpoint exposed on
25
+ `AGENT` becomes a [Vercel AI SDK](https://sdk.vercel.ai) tool — callable from an
26
+ agent loop. Contract operations are never re-described by hand; pathless
27
+ runtime operations use one framework definition shared by both tool transports.
28
+
29
+ ## Which endpoints become tools
30
+
31
+ By default every endpoint is a tool on every transport. `expose` narrows it:
32
+
33
+ ```ts
34
+ { method: 'GET', path: '/search', desc: 'Search the catalog' } // HTTP + MCP + AGENT
35
+ { method: 'POST', path: '/sync', desc: 'Internal sync', expose: ['HTTP'] } // HTTP only
36
+ { method: 'GET', path: '/lookup', desc: 'Look up a price', expose: ['MCP'] } // MCP tool only
37
+ ```
38
+
39
+ Four kinds of endpoint are **never** tools, whatever `expose` says: a
40
+ `multipart` upload (not a tool call), a `rawBody` endpoint (HTTP-only by
41
+ construction), a [`responseMeta`](./server.md#typed-json-response-metadata)
42
+ endpoint (outbound HTTP headers mean nothing on a tool call), and a
43
+ [`rawResponse`](./server.md#raw-response-endpoints) endpoint (its answer is
44
+ bytes — a tool result cannot carry them, and it would reach the model as `{}`).
45
+ Pin the full list with `listToolNames` in a snapshot test.
46
+
47
+ `desc` is the tool description the model reads — write it for the model, not
48
+ just for a human. The tool name defaults
49
+ to a verb-aware name from the method + prefix (`list` → `list_widgets`, `get` →
50
+ `get_widget`); set `tool.name` for an explicit one. Derivation normalises **per half**
51
+ (→ ADR 0035): the service half turns everything outside `[a-zA-Z0-9_]` into `_`,
52
+ hyphen included (`bot-status` ⇒ `get_bot_status`), while the method half keeps
53
+ its hyphen (`get-user` ⇒ `get-user_notes`) because such a name has always been
54
+ legal and may already be pinned in a client config. A name is *accepted* if it
55
+ matches `[a-zA-Z0-9_-]`. A name that
56
+ still cannot be delivered (illegal explicit `tool.name`, over 64 characters, or a
57
+ prefix with no usable character) throws at mount rather than at the first model
58
+ call —
59
+ → [ADR 0035](../decisions/0035-tool-name-derivation-and-validation.md). See
60
+ [Contracts → transports](./contracts.md#transports).
61
+
62
+ ### Pinning tool names — `listToolNames`
63
+
64
+ Derived tool names are part of your public surface — an MCP client config or an
65
+ agent prompt refers to them by string. `listToolNames({ services, runtimeTools })`
66
+ resolves the complete mixed surface (the exact resolver the mounts use), with
67
+ its origin, `(service, method)` identity and transports, sorted — a stable shape
68
+ to snapshot:
69
+
70
+ ```ts
71
+ import { listToolNames } from 'stitchkit/tools'
72
+
73
+ test('tool names have not drifted', () => {
74
+ expect(listToolNames({ services, runtimeTools })).toMatchSnapshot()
75
+ })
76
+ ```
77
+
78
+ A stitchkit upgrade (or a contract refactor) that would shift a derived name
79
+ now fails this test instead of silently breaking the clients that call the
80
+ tool. It is also the mechanical diff when migrating a service: run it before
81
+ and after, compare.
82
+
83
+ > **This is also the guard against a forgotten `expose`.** An endpoint that
84
+ > declares none is a tool on MCP **and** AGENT — the default is fail-open, and
85
+ > there is no contract-level `expose` to set once (→
86
+ > [ADR 0036](../decisions/0036-contract-level-meta.md)). A snapshot of
87
+ > `listToolNames` fails the build the moment an endpoint you meant to keep
88
+ > HTTP-only shows up in the list, which is the one check that catches it however
89
+ > many places the line was forgotten.
90
+
91
+ ## In-process calls — `createToolInvoker`
92
+
93
+ When one application operation dispatches to a contract tool, do not mount an
94
+ AI SDK `ToolSet` and call its transport adapter manually. Compile an in-process
95
+ invoker once and call the shared framework runner directly:
96
+
97
+ ```ts
98
+ import { createToolInvoker } from 'stitchkit/tools/invoker'
99
+
100
+ const invoker = createToolInvoker(services, {
101
+ transport: 'AGENT', // required exposure policy
102
+ })
103
+
104
+ const result = await invoker.invoke('update_entity', args, {
105
+ source: 'internal', // default; audit names the real call source
106
+ context: { identity },
107
+ lifecycle,
108
+ hooks,
109
+ })
110
+
111
+ // Composition path: validated data or the exact normalized AppError.
112
+ const data = await invoker.invokeOrThrow('update_entity', args, {
113
+ context: { identity },
114
+ lifecycle,
115
+ hooks,
116
+ })
117
+ ```
118
+
119
+ `transport` is required and uses the exact existing `MCP`, `AGENT` or `CLI`
120
+ exposure rules; there is no internal bypass mode. The immutable name lookup is
121
+ compiled once. Call-specific identity, context, lifecycle and hooks are passed
122
+ to `invoke` / `invokeOrThrow`, so one registry can safely serve parallel and
123
+ recursive calls without retaining request state. Every invocation gets a fresh
124
+ tool-call context and runs the same extension resolution, input/output
125
+ validation, lifecycle, hooks and output-strip reporter as mounted tools.
126
+
127
+ The dedicated entrypoint needs only the normal `stitchkit`/`zod` install. Use
128
+ the broader `stitchkit/tools` barrel when the same program also mounts MCP or AI
129
+ adapters and has installed their optional peers. Both imports reach the same
130
+ runner; this is dependency isolation, not a second execution implementation.
131
+
132
+ `invoke` returns the canonical discriminated `ToolResult`, not an AI SDK or MCP
133
+ presentation envelope. `invokeOrThrow` returns validated data and throws the
134
+ runner's normalized `AppError` on failure, preserving an application error's
135
+ code, status, message, details and hint without reconstructing it from the
136
+ model-safe envelope. Unexpected throws remain scrubbed. An unknown name throws
137
+ `AppError('NOT_FOUND')` before the runner because there is no operation identity
138
+ against which hooks could run. Duplicate and provider-invalid names fail when
139
+ the invoker is created.
140
+
141
+ The invoker's caller is code, so it gets an endpoint's full answer even where a
142
+ [tool view](#a-different-answer-for-tools--withtoolview) is declared. When the
143
+ invoker backs a transport a model reads, pass `toolSurface: true`: calls then
144
+ get the view's defaults and projected answer, which is what `collectTools` and
145
+ `buildToolManifest` advertise.
146
+
147
+ ## MCP — `createMcpHandler`
148
+
149
+ `createMcpHandler` builds a complete stateless Streamable-HTTP MCP endpoint on
150
+ the official TypeScript SDK v2 server package. It owns server creation,
151
+ protocol-era negotiation and shutdown; application code does not import the SDK
152
+ to mount a normal endpoint.
153
+
154
+ ```ts
155
+ import { createMcpHandler, createMcpHttpRoute } from 'stitchkit/tools'
156
+ import { createServer } from 'stitchkit/server'
157
+
158
+ const mcp = createMcpHandler({
159
+ serverInfo: { name: 'my-app', version: '1.0.0' },
160
+ auth: (req) => resolveApiKey(req), // → an identity, or null for 401
161
+ services: [usersService, catalogService],
162
+ })
163
+
164
+ createServer({
165
+ services,
166
+ rawRoutes: [createMcpHttpRoute({ path: '/mcp', handler: mcp })],
167
+ })
168
+
169
+ // During graceful shutdown:
170
+ await mcp.close()
171
+ ```
172
+
173
+ ### `McpHandlerConfig`
174
+
175
+ | Field | Purpose |
176
+ |-------|---------|
177
+ | `serverInfo` | MCP server identity — `{ name, version }` |
178
+ | `auth` | `(req) => identity \| null` — `null` rejects with 401 |
179
+ | `services` | the services to expose — an array, or `(auth) => ServiceDef[]` |
180
+ | `runtimeTools` | managed pathless operations — an array, or `(auth) => RuntimeToolDefinition[]` |
181
+ | `surfaces` | finite `{ key: { services, runtimeTools } }` registry prepared eagerly |
182
+ | `selectSurface` | `(auth) => declaredKey` — required with `surfaces` |
183
+ | `context` | `(auth) => {…}` — values merged into every tool handler's `ctx` |
184
+ | `lifecycle` | `beforeHandle` / `afterHandle` — the tool-side auth gate (see below) |
185
+ | `multiRound` | Typed MRTR state policy for guarded multi-round tool calls |
186
+ | `hooks` | tool-call observability hooks — `afterToolCall` fires on every result |
187
+ | `extend` | extra advertised arguments resolved into handler context |
188
+ | `schemaValidation` | compatibility policy, typed-property guard and portable-format guard |
189
+ | `logger` | a `StitchLogger` for the `'warn'` policy |
190
+ | `rawTools` | `(server, auth) => …` — explicit SDK registration without framework guarantees |
191
+ | `resources` | MCP Apps `ui://` resources mounted on every server |
192
+ | `instructions` | a short host-facing usage hint, surfaced to MCP tool-search |
193
+ | `coerceJsonArgs` | coerce JSON-stringified object/array arguments (default `true`) |
194
+ | `flattenUnionInput` | advertise discriminated unions as one object (default `false`) |
195
+ | `errorHint` | add a project-owned hint to failed tool results |
196
+ | `onOutputStrip` | observe output keys removed by contract validation |
197
+ | `protectedResource` | RFC 9728 metadata used by HTTP `401` responses |
198
+ | `legacy` | `'serve'` (default) or `'reject'` for pre-2026 clients |
199
+ | `security` | optional Host/Origin allowlists at the Fetch boundary |
200
+ | `onTransportRejected` | observe HTTP/protocol rejections without entering lifecycle or tool hooks |
201
+ | `cache` | explicit operation cache hints; omitted means zero/private |
202
+
203
+ Direct `services` / `runtimeTools` factories, `context`, `selectSurface` and
204
+ `rawTools` receive the resolved identity, so a tenant can be shown only its own
205
+ tools and every handler can read `ctx.tenantId`.
206
+
207
+ Use direct factories only when the definitions are genuinely arbitrary per
208
+ identity. For a bounded role/plan set, declare a finite registry instead:
209
+
210
+ ```ts
211
+ const handleMcp = createMcpHandler({
212
+ serverInfo,
213
+ auth,
214
+ surfaces: {
215
+ admin: { services: allServices, runtimeTools: [renderPreview] },
216
+ member: { services: memberServices, runtimeTools: [renderPreview] },
217
+ },
218
+ selectSurface: (identity) => identity.isAdmin ? 'admin' : 'member',
219
+ context: (identity) => ({ identity }),
220
+ })
221
+ ```
222
+
223
+ Every declared entry is schema-validated and prepared once when the handler is
224
+ constructed. The selected immutable descriptors are shared; the SDK server,
225
+ transport, auth-derived context, lifecycle runner and tool-call context are
226
+ fresh for every request. Unknown keys
227
+ fail before the server connects. The registry never retains auth values.
228
+
229
+ ### Stateless transport and protocol eras
230
+
231
+ Every request gets a fresh SDK server, resolved auth/context and tool-call
232
+ runner. Static direct and finite registry schemas are still prepared once when
233
+ the handler is constructed. There is no session map, event store,
234
+ `Mcp-Session-Id` or resumable cross-request SSE state. Process replacement and
235
+ load balancing therefore cannot strand a client on an in-memory session.
236
+
237
+ The default `legacy: 'serve'` lets the official SDK negotiate either modern
238
+ `2026-07-28` or the supported legacy stateless opening on this same endpoint.
239
+ Set `legacy: 'reject'` when every host is modern. Legacy support is protocol
240
+ translation inside the SDK, not a second Stitchkit transport or compatibility
241
+ API. Stateful MCP and subscriptions are intentionally outside this layer.
242
+
243
+ `createMcpHttpRoute` is the framework-owned raw-route adapter. It registers
244
+ `ALL` because Streamable HTTP uses multiple HTTP methods, delegates only to
245
+ `handler.fetch`, and leaves lifecycle ownership with the returned handler.
246
+
247
+ By default, a present `Host` header must match the request URL and a present
248
+ browser `Origin` must be same-origin. Non-browser hosts may omit `Origin`. Behind
249
+ a trusted reverse proxy, reconstruct the public request URL before calling the
250
+ handler or configure exact `security.allowedHosts` / `allowedOrigins`; never
251
+ copy arbitrary forwarded headers into the trusted URL. If a browser calls MCP
252
+ cross-origin, its HTTP server or gateway must also answer CORS preflight and
253
+ expose the protocol headers. `onTransportRejected` is the audit boundary for
254
+ HTTP/security rejections; it is deliberately separate from tool lifecycle and
255
+ must not be used as authorization input.
256
+
257
+ ### Modern discovery, routing and cache hints
258
+
259
+ Stitchkit forwards the negotiated protocol era and validated MCP request data
260
+ to both `RequestEvent.mcp` and the current managed call's typed `context.mcp`;
261
+ untrusted routing headers never become application identity. The SDK validates
262
+ `MCP-Protocol-Version`, JSON-RPC shape and routing
263
+ metadata before lifecycle or tool handlers run. Framework-owned tool and
264
+ resource registration preserves declaration order across HTTP and stdio. Tool
265
+ manifests preserve mount order; `listToolNames` is a sorted diagnostics view.
266
+ Consumer-owned raw SDK registrations are outside this guarantee.
267
+
268
+ Caching is opt-in. `cache.operations` maps directly to SDK v2 operation cache
269
+ hints, while each `McpResourceDef` may declare its own `cacheHint`. Omission
270
+ means zero/private: neither a prepared surface nor a deterministic response is
271
+ silently treated as public. Unbounded auth-selected surface factories are
272
+ always forced to zero/private even when an operation policy is present; use a
273
+ finite `surfaces` registry when identities share a provably immutable surface.
274
+ Stitchkit never advertises list-change or subscription capabilities
275
+ without an implementation.
276
+
277
+ ### Knowing your catalog is stale — the catalog stamp
278
+
279
+ A client lists the tools once and keeps that list. If the server's contract
280
+ moves afterwards, the client's copy is wrong and *nothing tells it so*: calls
281
+ are refused, and from inside the client a refusal looks like a broken server.
282
+ This is the most expensive shape a contract disagreement takes, because the
283
+ party able to fix it is the one with no evidence.
284
+
285
+ Every advertised tool and every tool result therefore carries the fingerprint of
286
+ the catalog it came from:
287
+
288
+ ```ts
289
+ import { readMcpCatalogStamp } from 'stitchkit/tools';
290
+
291
+ const listed = await client.listTools();
292
+ let known = readMcpCatalogStamp(listed.tools[0]?._meta); // { digest, tools }
293
+
294
+ const result = await client.callTool({ name: 'record_journal', arguments });
295
+ const live = readMcpCatalogStamp(result._meta);
296
+ if (live && known && live.digest !== known.digest) {
297
+ // The catalog moved under us. Re-list before blaming the result.
298
+ known = readMcpCatalogStamp((await client.listTools()).tools[0]?._meta);
299
+ }
300
+ ```
301
+
302
+ The comparison costs nothing and runs on a response you were already receiving —
303
+ including a refusal, which is exactly when a stale catalog is the likeliest
304
+ explanation. `notifications/tools/list_changed` is the push-shaped answer to the
305
+ same problem and `createMcpHandler` cannot send it: it is stateless by
306
+ construction, so there is no retained session to push down.
307
+
308
+ The digest covers each advertised tool's name, description, input schema, output
309
+ schema and annotations, and nothing else — it moves when the contract moves and
310
+ not when a handler does. Raw SDK registrations stay consumer-owned and are
311
+ outside it.
312
+
313
+ ### Shaping arguments before validation — `beforeToolCall`
314
+
315
+ `beforeToolCall` sees the arguments as they arrived and may **replace** them:
316
+
317
+ ```ts
318
+ hooks: {
319
+ beforeToolCall: async ({ args }) =>
320
+ typeof args.id === 'string' && args.id.startsWith('@')
321
+ ? { ...args, id: await resolveReference(args.id) }
322
+ : undefined, // undefined / null / nothing → unchanged
323
+ }
324
+ ```
325
+
326
+ The replacement is validated by the contract schema like any other input, so this
327
+ shapes a call and never bypasses the schema — a hook returning something the
328
+ contract refuses produces an ordinary `VALIDATION_ERROR`. It runs before the
329
+ params/input split, before argument coercion and before both schemas, which is
330
+ why a field declared `z.string()` can receive a reference and still be a string by
331
+ the time it is checked. `lifecycle.beforeHandle` is too late for this: the schemas
332
+ have already answered.
333
+
334
+ The audit trail is unaffected. `afterToolCall` reports what the caller sent as
335
+ `args` and the replacement separately as `effectiveArgs`, so a rewrite is visible
336
+ as a rewrite rather than by overwriting the evidence.
337
+
338
+ ### Knowing the outcome of a call — `afterToolCall` and `toolCallId`
339
+
340
+ `afterToolCall` receives the whole `ToolResult` — `{ok: true, data}` or
341
+ `{ok: false, code, …}` — on every exit, including a validation failure that never
342
+ reached the handler, and on all three transports. It is the answer to "did this
343
+ call fail"; deriving that from the serialized error text instead is the mistake
344
+ this section exists to prevent, and it is a mistake that does not announce itself:
345
+ one consumer had five places asking the question and getting five answers.
346
+
347
+ To correlate an outcome with the call the model made, read `context.toolCallId`:
348
+
349
+ ```ts
350
+ hooks: {
351
+ afterToolCall: ({ context, result }) => {
352
+ loop.record(context.toolCallId, result.ok ? 'ok' : result.code);
353
+ },
354
+ }
355
+ ```
356
+
357
+ Two exits are deliberately **not** reported: a runtime tool presenter that throws
358
+ on the agent surface (the AI SDK calls it after `execute` has already returned)
359
+ and `ToolExecutionControlError`, which is a run being stopped rather than a tool
360
+ failing — check it with `isToolExecutionControlError`.
361
+
362
+ ### Restartable tool bodies — `durability`
363
+
364
+ A tool that starts slow work and must report exactly once, including after a host
365
+ restart, can keep that bookkeeping **inside** the tool:
366
+
367
+ ```ts
368
+ mountAgent(services, {
369
+ durability: (toolCallId, signal) => myLedgerFor(toolCallId, signal),
370
+ });
371
+
372
+ // in the handler
373
+ const asset = await ctx.step('render', () => renderAsset(ctx.input));
374
+ await ctx.waitFor({ event: 'render-done', id: assetId });
375
+ ```
376
+
377
+ `ToolDurability` is the port a tool body sees — `step`, `sleep`, `waitFor`. You
378
+ do not have to implement it: the engine ships from `stitchkit/tools`, and it needs
379
+ a ledger of two methods over storage you already have:
380
+
381
+ ```ts
382
+ import { createLocalStepDurability, type StepDurabilityLedger } from 'stitchkit/tools';
383
+
384
+ const ledger: StepDurabilityLedger = {
385
+ appendEvent: (event) => db.durabilityEvents.insert(event), // returns the row with `seq`
386
+ readEvents: ({ conversationId, fromSeq, toSeq }) => db.durabilityEvents.page(…),
387
+ };
388
+
389
+ mountAgent(services, {
390
+ durability: (toolCallId, signal) =>
391
+ createLocalStepDurability({ store: ledger, conversationId, runId: toolCallId, signal }),
392
+ });
393
+ ```
394
+
395
+ That gives replay, absolute deadlines and decode refusal without writing them.
396
+ The port is there for an application that already has its own ledger engine.
397
+
398
+ One thing the port deliberately leaves out: **delivery**. `waitFor` parks until
399
+ `{ event, id }` arrives, and a tool body has no business delivering to itself —
400
+ so `deliver` lives on the engine object you constructed, not in the handler
401
+ context. Whatever produces the event (a webhook, a queue consumer, a cron) calls
402
+ `engine.deliver({ event, id, payload })` against the same ledger; the parked
403
+ `waitFor` resolves, and a `waitFor` that starts after the delivery returns at
404
+ once. Taking `agent-runtime` is not required and nothing of the runtime proper
405
+ enters the `stitchkit/tools` graph. An application that *does* run on
406
+ `agent-runtime` gets durability through the run context and needs no option;
407
+ where both exist the runtime's wins, because the run is recorded in its ledger.
408
+
409
+ ### Typed MCP call metadata
410
+
411
+ Contract handlers, runtime-tool handlers/factories, lifecycle and tool hooks all
412
+ see the same optional `McpCallContext` for the current invocation:
413
+
414
+ ```ts
415
+ const sourceLabel = context.mcp?.clientInfo?.name ?? context.source
416
+
417
+ context.mcp?.era // 'modern' | 'legacy'
418
+ context.mcp?.method // validated MCP method
419
+ context.mcp?.toolName // resolved framework tool name
420
+ context.mcp?.protocolVersion // when supplied by a modern host
421
+ context.mcp?.clientInfo // { name, version } when validated
422
+ context.mcp?.outcome // multi-round attempt outcome
423
+ context.mcp?.round // multi-round attempt number
424
+ ```
425
+
426
+ The field is absent on HTTP, Agent, CLI and bring-your-own transports. A legacy
427
+ MCP call exposes `era: 'legacy'` but does not invent modern client information.
428
+ `clientInfo` is the host's self-description: use it for labels or analytics,
429
+ never for authentication, RBAC, tenant selection or rate limiting. Verified
430
+ identity still comes from `auth`; the `context(auth)` callback remains the
431
+ application-context factory and receives no protocol metadata.
432
+
433
+ ### Telling the host what a long call is doing — `ctx.reportProgress`
434
+
435
+ A tool that takes ten minutes tells a text host nothing: the call is made, and
436
+ the next thing the host shows is the answer. The protocol has a channel for
437
+ this — the host sends a `progressToken` with the call, the server relates
438
+ progress notifications to it — and a handler reaches it through
439
+ `ctx.reportProgress`:
440
+
441
+ ```ts
442
+ render: async (ctx) => {
443
+ await ctx.reportProgress?.({ message: 'queued' })
444
+ const job = await jobs.start(ctx.input)
445
+ await ctx.reportProgress?.({ message: 'rendering', progress: 1, total: 3 })
446
+ return await jobs.finish(job)
447
+ }
448
+ ```
449
+
450
+ `reportProgress` is present on every **tool** call — MCP, agent and CLI — so a
451
+ handler never branches on transport, and it does nothing wherever nobody is
452
+ listening. It is absent on the HTTP transport, which has no channel for it, so a
453
+ handler that also serves HTTP writes `ctx.reportProgress?.(…)`. It never throws and never
454
+ rejects: a message about work must not be able to kill the work it describes, so
455
+ a refused notification leaves the host exactly where a host that never asked for
456
+ progress already is.
457
+
458
+ `progress` is a number the protocol requires and a handler often does not have —
459
+ there is a stage to name and no scale to name it on. Omit it and the ordinal of
460
+ the update is sent, with no `total`, so the host shows a counter rather than a
461
+ bar stuck at 3%. That is a fact about what happened; a synthesised percentage
462
+ would be a claim nobody measured.
463
+
464
+ The framework sends nothing on its own. Progress is meaningful only where an
465
+ operation has observable stages, and manufacturing one per call would be
466
+ inventing a second transport beside the one the protocol already provides. The
467
+ one exception is the managed wait tool (`mountWait`), which already polls and
468
+ therefore already knows: when the host asked for progress it reports each poll
469
+ and the phase it last saw, which is the tool whose silence raised the question
470
+ in the first place.
471
+
472
+ The token itself is on `ctx.mcp.progressToken` when a caller wants to know
473
+ whether anyone is listening.
474
+
475
+ ### Multi-round tool input (`input_required`)
476
+
477
+ An MCP-only operation can require typed user input before its final side effect:
478
+
479
+ ```ts
480
+ const DeleteConfirmationSchema = z.object({ confirmed: z.boolean() })
481
+
482
+ deleteProject: {
483
+ method: 'DELETE',
484
+ path: '/projects/:id',
485
+ expose: ['MCP'],
486
+ input: DeleteProjectSchema,
487
+ output: DeleteProjectResultSchema,
488
+ tool: {
489
+ mcp: {
490
+ inputRequired: [
491
+ {
492
+ key: 'confirmation',
493
+ schema: DeleteConfirmationSchema,
494
+ message: 'Confirm permanent deletion',
495
+ },
496
+ {
497
+ key: 'reason',
498
+ schema: z.object({ value: z.string().min(3) }),
499
+ message: 'Record the reason',
500
+ },
501
+ ],
502
+ },
503
+ },
504
+ }
505
+ ```
506
+
507
+ Each continuation accepts exactly the currently requested item. Only after the
508
+ ordered sequence completes does the handler receive the exact aggregate as
509
+ `ctx.mcpInput.confirmation` and `ctx.mcpInput.reason`; before then the framework
510
+ returns `input_required` without calling it. Set
511
+ `multiRound.serving.maxRounds` to the maximum declaration size you accept
512
+ (default `10`); empty sequences, duplicate keys and overflow fail first. State
513
+ is bound to principal, full operation identity, current round, accepted
514
+ aggregate and canonical original-argument digest and is
515
+ expiry-checked. Tampered, expired, cross-user or cross-tool state fails before
516
+ the side effect. Output validation applies only to the final result.
517
+
518
+ Every attempt re-runs auth/lifecycle and emits its own tool hooks; audit metadata
519
+ contains the attempt's `mcp.outcome` and `mcp.round`. Stitchkit does not merge
520
+ separate HTTP attempts into one logical trace. Parallel
521
+ rounds have isolated context. HTTP/stdio modern hosts and the supported legacy
522
+ stdio bridge may use this declaration; Agent, CLI and ordinary HTTP invocation
523
+ remain single-round and unchanged. Hosts without the capability receive an
524
+ ordinary unsupported result rather than a falsely advertised round. Signed
525
+ state is tamper-resistant, not an exactly-once replay store; destructive
526
+ handlers must still be idempotent where retries matter.
527
+
528
+ #### Questions chosen from the arguments
529
+
530
+ The list above is fixed when the contract is written, which is right when the
531
+ questions belong to the operation. It is not enough when they belong to the
532
+ **arguments** — one model takes `aspect_ratio`, another `duration`, a third an
533
+ input image — and there a declared list can only be empty. `inputRequired` also
534
+ accepts a function of the parsed call:
535
+
536
+ ```ts
537
+ tool: {
538
+ mcp: {
539
+ inputRequired: async ({ input }) => {
540
+ const model = await catalog.get(input.model)
541
+ return model.needsRatio
542
+ ? [{ key: 'ratio', schema: RatioSchema, message: 'Which aspect ratio?' }]
543
+ : []
544
+ },
545
+ },
546
+ }
547
+ ```
548
+
549
+ It receives the same `params` / `input` the handler receives — parsed, so
550
+ defaults and coercions are already applied. Returning an empty array means this
551
+ call needs nothing and runs straight through. Everything else is unchanged: the
552
+ state is still signed and bound to principal, operation and argument digest, the
553
+ rounds are still counted against `maxRounds`, and a resolved list with duplicate
554
+ keys or more rounds than allowed is refused.
555
+
556
+ **The plan is fingerprinted, and that matters more than it looks.** Between two
557
+ rounds there is a full round trip to the host, and a resolver that reads
558
+ anything outside its arguments — a model catalog, a feature flag — can answer
559
+ differently the second time. Every other check would still pass: same principal,
560
+ same operation, same arguments, round still in range. Round 2's question would
561
+ be asked under round 1's key, and if the schemas happened to be compatible the
562
+ user's answer would be accepted for a question nobody asked. So the resolved
563
+ list is fingerprinted into the signed state and re-checked every round; a plan
564
+ that moved is refused, not asked. A resolver that reads only its arguments never
565
+ sees this.
566
+
567
+ **What a dynamic declaration costs.** One extra pass through the contract
568
+ pipeline per round — `lifecycle.beforeHandle` runs once more and one more
569
+ `toolPhase: 'input-round'` audit row is written. That is the price of ordering:
570
+ the resolver is your code and may reach a network, so it runs **after**
571
+ authorisation, never before, and the only thing that can authorise is a pipeline
572
+ pass. Resolving itself is free — the arguments are parsed by the same pure
573
+ function the call parses with, not by a second run of anything. A fixed list
574
+ pays none of this; its call sequence is unchanged.
575
+
576
+ One thing does change for a fixed list: the signed round state now carries a
577
+ fingerprint of the question plan, and it is checked on every round. A
578
+ conversation already in flight when you deploy this has no fingerprint in its
579
+ state and is refused once with `INVALID_REQUEST_STATE`; the host re-asks and the
580
+ retry succeeds.
581
+
582
+ ### Guarding tools — `lifecycle`
583
+
584
+ A tool call runs the same handler an HTTP request would. `lifecycle` makes it
585
+ run the same gate: a `beforeHandle` (throw to reject) and an `afterHandle`
586
+ (transform the result). Pass the **same**
587
+ [`createAuthHook`](./auth-and-errors.md#createauthhook) result used as the HTTP
588
+ server's `authorize` hook and tool calls are scope-checked by identical rules:
589
+
590
+ ```ts
591
+ createMcpHandler({ serverInfo, auth, services, lifecycle: { beforeHandle: authHook } })
592
+ ```
593
+
594
+ Without it, a tool call bypasses the HTTP `authorize` gate — the contract's
595
+ `scope` is not enforced on the MCP / agent surface. `mountMcp`, `mountAgent` and
596
+ `buildMcpServer` take `lifecycle` too.
597
+
598
+ The observability `hooks` are symmetric with the HTTP side too: `beforeToolCall`
599
+ and `afterToolCall` receive the resolved **`MethodDef`** as `endpoint` —
600
+ the tool-side twin of `afterHandle(ctx, result, endpoint)`. Read
601
+ `endpoint.serviceName` / `.key` / `.meta` directly for an audit row; you do not
602
+ need to rebuild a `toolName → identity` map:
603
+
604
+ ```ts
605
+ hooks: {
606
+ afterToolCall: ({ result, durationMs, endpoint }) => {
607
+ audit({
608
+ service: endpoint.serviceName,
609
+ action: endpoint.key,
610
+ ok: result.ok,
611
+ ms: durationMs,
612
+ })
613
+ },
614
+ }
615
+ ```
616
+
617
+ > **Tool-path identity.** A tool call has no `req`, so `createAuthHook` resolves
618
+ > identity through `resolveFromContext`, not `resolve`. Set it (read the
619
+ > identity your `auth` / `context` injected) — without it a scoped tool call
620
+ > has no identity and **fails closed**. See
621
+ > [Auth on the tool surface](./auth-and-errors.md#auth-on-the-tool-surface--resolvefromcontext).
622
+
623
+ ### MCP schema validation profile
624
+
625
+ A contract schema that JSON Schema cannot represent (a `z.date()`, a `z.map()`)
626
+ cannot become a tool. `schemaValidation.policy` decides what happens:
627
+
628
+ - `'throw'` (default) — fail the build, listing every offending tool. A static
629
+ `services` array is checked when `createMcpHandler` is constructed, so a bad
630
+ schema fails the deploy, not the first request. Better than a tool that
631
+ silently vanishes from the surface.
632
+ - `'warn'` — log through `logger` and drop the tool.
633
+ - `'skip'` — drop the tool silently.
634
+
635
+ `validateMcpSchemas({ services })` runs the same check on its own — useful in a
636
+ startup assertion or a test.
637
+
638
+ For a static `services` array, collection, schema conversion and every enabled
639
+ validation guard run once when the handler is created. Each HTTP request still
640
+ receives a fresh `McpServer`, runner, context and native registration over that
641
+ immutable prepared surface. A `services(auth)` factory
642
+ is deliberately prepared after resolving each identity because its tool set may
643
+ change by tenant.
644
+
645
+ #### Is every property actually usable by a model?
646
+
647
+ A tool schema is the only instruction a model gets about the shape of its
648
+ arguments. A property that carries a `description` and no `type` / `enum` /
649
+ `anyOf` / `$ref` tells it nothing — and nothing fails: the schema converts, the
650
+ mount succeeds, the tool is advertised, and the model then guesses, retrying the
651
+ same wrong guess because the error does not say what the right one would be.
652
+
653
+ ```ts
654
+ validateMcpSchemas({
655
+ services,
656
+ policy: 'throw',
657
+ logger,
658
+ extend,
659
+ flattenUnionInput: true,
660
+ requireTypedProperties: true,
661
+ requirePortableFormats: true,
662
+ allowFormats: [],
663
+ })
664
+ ```
665
+
666
+ For an arbitrary **JSON value**, declare `z.json()`: its recursive JSON Schema
667
+ describes strings, numbers, booleans, null, arrays and objects, so strict schema
668
+ validation needs no exception. `z.unknown()` means an unknown runtime value —
669
+ including values JSON cannot represent — and therefore gives a model no usable
670
+ shape. The guard is off by default for existing contracts. `allowUntyped` takes
671
+ dotted `tool.property` paths and is reserved for a presentation value that is
672
+ genuinely impossible to represent as JSON Schema. On `createMcpHandler`, put the policy under
673
+ `schemaValidation`; the handler supplies its real `extend` and
674
+ `flattenUnionInput`, so the check cannot vet a different document from the one
675
+ advertised.
676
+
677
+ `requirePortableFormats` rejects custom `format` values common MCP/AJV clients
678
+ do not know, such as the `cuid2` emitted by `z.cuid2()`. Use a portable
679
+ schema/pattern, or list it in `allowFormats` only when every client supports it.
680
+ stitchkit never removes or rewrites the keyword.
681
+
682
+ `findUntypedProperties(jsonSchema)` is the same walk, exported on its own if you
683
+ want to assert on a schema you built elsewhere.
684
+
685
+ ### Discriminated unions for weaker models — `flattenUnionInput`
686
+
687
+ A discriminated union in a tool's input becomes a JSON Schema `oneOf` / `anyOf`.
688
+ Capable models (Claude, Gemini, GPT) handle that; weaker / cheaper ones can drop
689
+ the field or mangle its strings. Set `flattenUnionInput: true` (on
690
+ `createMcpHandler` / `mountMcp` / `mountAgent`) to advertise each discriminated
691
+ union as a **single flat object** instead — the discriminator becomes an enum and
692
+ each variant's fields become optional with a `Required if <disc> = …` hint.
693
+
694
+ **A field several variants declare keeps its type.** Flattening puts every
695
+ variant's fields side by side, so a key two variants share has to be advertised
696
+ as one thing. Where they agree, that is what you get; where they disagree — a
697
+ `.refine()` only one of them carries, two different bounds on the same number, an
698
+ enum against a free string — the *constraint* is dropped and the **type** is not.
699
+ A field that is a number in every variant is advertised as a number, not as a
700
+ bare description. When the kinds genuinely differ, the flat projection keeps
701
+ every provable kind in a deterministic JSON Schema type array — for example
702
+ `type: ['string', 'array']` — while dropping constraints that are not sound for
703
+ all branches. Nested `oneOf` / `anyOf` values still contribute their provable
704
+ base kinds without reintroducing union keywords. Only a branch whose kind is
705
+ actually unknowable, such as a free-form schema or unresolved reference, leaves
706
+ the collision unconstrained. → ADRs [0044](../decisions/0044-a-collided-field-keeps-its-type.md)
707
+ and [0065](../decisions/0065-flat-collisions-preserve-every-known-kind.md)
708
+
709
+ It is **deep** because the projection walks the generated JSON Schema document,
710
+ including objects, arrays, tuples and schema-definition nodes. Structurally
711
+ identifiable discriminated object unions are flattened wherever they occur.
712
+ Plain unions and unions hidden behind unresolved external references remain
713
+ unions because Stitchkit cannot soundly invent a discriminator.
714
+
715
+ Use the default `flattenUnionInput: false` when the model must see the exact
716
+ relationship between a discriminator and each branch. The flat type array is a
717
+ sound set of possible JSON kinds, not a reconstruction of those correlations.
718
+
719
+ The flattened form is **lossy but never executable**. Per-variant refinements
720
+ and incompatible constraints are widened in the presentation document; the
721
+ original Zod contract enforces them exactly once inside `executeToolMethod`.
722
+ MCP and AI adapters forward the raw argument object unchanged, so defaults,
723
+ coercions and transforms cannot run before Stitchkit. Strict violations return
724
+ the normal `VALIDATION_ERROR` tool envelope and fire `beforeToolCall` /
725
+ `afterToolCall`. → [ADR 0050](../decisions/0050-presentation-schema-is-not-a-parser.md).
726
+
727
+ ## `mountMcp`
728
+
729
+ If you already run an `McpServer` from the SDK, `mountMcp` adds contract tools
730
+ to it instead of owning the lifecycle:
731
+
732
+ ```ts
733
+ import { mountMcp } from 'stitchkit/tools'
734
+
735
+ mountMcp(mcpServer, [usersService], { context: { source: 'mcp' } })
736
+ ```
737
+
738
+ `createMcpHandler` is the batteries-included path; `mountMcp` is the building
739
+ block under it.
740
+
741
+ ## MCP over stdio — `createStdioMcpServer`
742
+
743
+ `createMcpHandler` serves MCP over HTTP. `createStdioMcpServer` serves the same
744
+ contract tools over **stdio** — the server runs as a subprocess of the MCP
745
+ client (Claude Desktop, Claude Code, Cursor, Codex), on the user's machine, so
746
+ it can reach the local filesystem.
747
+
748
+ ```ts
749
+ import { bindStdioProcessSignals, createStdioMcpServer } from 'stitchkit/tools'
750
+
751
+ const stdio = await createStdioMcpServer({
752
+ serverInfo: { name: 'my-app', version: '1.0.0' },
753
+ auth: resolveIdentity(), // resolved once at startup, not per request
754
+ services: [usersService],
755
+ })
756
+
757
+ const signals = bindStdioProcessSignals(stdio, {
758
+ onClose: () => stopWorkers(),
759
+ onComplete: () => { process.exitCode = 0 },
760
+ onError: (_phase, error) => {
761
+ console.error(error) // stderr only — stdout is JSON-RPC
762
+ process.exitCode = 1
763
+ },
764
+ })
765
+
766
+ await signals.promise
767
+ ```
768
+
769
+ A stdio server is a single process serving one client, so `auth` is a value (or
770
+ a promise of one) resolved once at startup — typically from an env var — rather
771
+ than a per-request `(req) => …`. Keep all logging on **stderr**: stdout is the
772
+ JSON-RPC channel.
773
+
774
+ The default `legacy: 'serve'` negotiates the modern or supported legacy opening
775
+ through the official stdio adapter. Use `legacy: 'reject'` for a modern-only
776
+ binary. Each invocation builds a fresh server; the returned handle owns
777
+ transport shutdown.
778
+
779
+ Signal binding is explicit: `createStdioMcpServer` installs no global process
780
+ listeners by itself. The first `SIGINT`/`SIGTERM` starts exactly one official
781
+ `close()` chain. Stdio has no force primitive, so a later signal restores the
782
+ OS default disposition instead of reporting a fictional forced result.
783
+ `signals.close()` removes an idle binding; the framework never calls
784
+ `process.exit()` or chooses the exit code. See
785
+ [deployment lifecycle](./testing-and-deployment.md#stdio-process-signals).
786
+
787
+ Both transports build the server through the shared `buildMcpServer` — same
788
+ contract/runtime pipeline, same surface selection, context, hooks, raw escape
789
+ hatch and instructions.
790
+
791
+ ## OAuth 2.1 — a native remote connector
792
+
793
+ A remote MCP server is connectable from Claude (Desktop / web "custom
794
+ connector") only through the MCP authorization spec: OAuth 2.1 with PKCE, plus
795
+ the discovery documents (RFC 9728 / 8414), Client ID Metadata Documents (CIMD)
796
+ and resource indicators (RFC 8707). A Bearer-only server returns a
797
+ bare `401` and the connector never establishes.
798
+
799
+ stitchkit ships the OAuth **protocol mechanics**; the app supplies only
800
+ **identity and storage**. Three pieces wire it together:
801
+
802
+ ```ts
803
+ import { createMcpHandler, createMcpHttpRoute, mountOAuthProvider, oauthProtectedResourceRoute } from 'stitchkit/tools'
804
+ import { createServer } from 'stitchkit/server'
805
+
806
+ const resource = 'https://api.example.com/mcp'
807
+ const issuer = 'https://api.example.com'
808
+
809
+ // 1. Resource server — the 401 now points at the metadata.
810
+ const mcp = createMcpHandler({
811
+ serverInfo: { name: 'my-app', version: '1.0.0' },
812
+ auth: resolveOAuthToken, // validate the Bearer JWT (verifyJwt + audience)
813
+ services,
814
+ protectedResource: { resource, authorizationServers: [issuer] },
815
+ })
816
+
817
+ // 2. Authorization server — CIMD, /authorize (PKCE), /token.
818
+ const oauthRoutes = mountOAuthProvider({
819
+ issuer,
820
+ resource,
821
+ signingSecret: env.OAUTH_SECRET,
822
+ clientRegistration: {
823
+ preRegistered: { get: getFirstPartyClient },
824
+ // CIMD is enabled with secure defaults; DCR remains disabled.
825
+ },
826
+ codes, refreshTokens, // your stores (DB or in-memory)
827
+ authorizeUser, // → { userId, approvedScopes } | Response
828
+ })
829
+
830
+ createServer({
831
+ services,
832
+ rawRoutes: [
833
+ createMcpHttpRoute({ path: '/mcp', handler: mcp }),
834
+ oauthProtectedResourceRoute({ resource, authorizationServers: [issuer] }),
835
+ ...oauthRoutes,
836
+ ],
837
+ })
838
+ ```
839
+
840
+ Access tokens are signed HS256 JWTs (`signJwt`) whose `aud` is the resource and
841
+ whose `iss` is the issuer — validate both in `auth` with
842
+ `verifyJwt(token, secret, { audience: resource, issuer })`. `authorizeUser` is
843
+ where the app authenticates the user (reuse an existing session) and records
844
+ consent; return `{ userId, approvedScopes }`, where approved scopes are a subset
845
+ of the requested/supported values, or a `Response` to redirect the browser to a
846
+ login page first. The AS and resource server can co-locate or live
847
+ on separate origins. See
848
+ [ADR 0015](../decisions/0015-oauth-resource-server.md).
849
+
850
+ Client resolution is deterministic: exact pre-registered client, then an HTTPS
851
+ URL client id resolved as CIMD, then explicitly enabled DCR. CIMD is on by
852
+ default; DCR is off unless `clientRegistration.dcr` supplies both `register` and
853
+ `get`. A CIMD-only deployment therefore exposes neither `/register` nor a
854
+ `registration_endpoint`. The metadata document must declare a `client_id` that
855
+ exactly equals its URL, explicit redirect URIs and
856
+ `token_endpoint_auth_method: 'none'`.
857
+
858
+ The production fetcher rejects credentials, fragments, non-HTTPS URLs and
859
+ private/reserved targets. Every redirect is DNS-resolved and IP-pinned again;
860
+ timeouts, redirect count and body size are bounded. Its bounded cache respects
861
+ `Cache-Control` (including `no-store`/`no-cache`), `Age`, `Expires`, `ETag` and
862
+ `Last-Modified`, coalesces concurrent misses and reports sanitized cache events;
863
+ invalid or unavailable identity receives only a short fail-closed cache entry.
864
+
865
+ Resolution itself is rate-limited on two levels (`CimdCachePolicy`):
866
+ `maxResolutionsPerClient` (default 10) bounds ONE `client_id` per
867
+ `resolutionWindowMs` window (default 60 s) — a client whose document disables
868
+ caching burns its own budget, not the server's — while `maxResolutions`
869
+ (default 120) caps the server-wide outbound rate as the flood backstop.
870
+ Positive and negative cache entries keep separate pools of `maxEntries` each,
871
+ so a flood of unresolvable ids cannot evict warmed clients and a burst of
872
+ successes cannot reset a failing client's backoff.
873
+
874
+ ### Authorization hardening (MCP 2026-07-28)
875
+
876
+ - **`iss` on every authorization response (RFC 9207, SEP-2468).** Success *and*
877
+ error redirects carry `iss`, and the AS metadata advertises
878
+ `authorization_response_iss_parameter_supported: true`. A client that talks to
879
+ several authorization servers validates `iss` before redeeming the code, which
880
+ closes the **mix-up attack** — an attacker's server cannot pass its response
881
+ off as this issuer's. Additive on the wire: a client that ignores `iss` is
882
+ unaffected.
883
+ - **`application_type` on registration (SEP-837).** A client may declare
884
+ `"native"` (desktop / CLI) or `"web"` in its DCR body. A **native** client may
885
+ register an `http` loopback redirect (`http://127.0.0.1:…`, RFC 8252 §7.3); a
886
+ **web** client is held to `https` only — that mismatch is the usual cause of
887
+ the `redirect_uri` rejection CLI clients hit. Omit the field and registration
888
+ behaves exactly as before (loopback allowed); an unknown value is rejected
889
+ rather than silently defaulted.
890
+
891
+ > Dynamic Client Registration is an explicit interoperability mode, not the
892
+ > default. Enabling it changes public discovery and adds `/register`; keep it off
893
+ > unless a client that cannot publish CIMD requires it.
894
+
895
+ ## Proxying a remote API — `implementRemote`
896
+
897
+ `implement` binds a contract to local handlers. `implementRemote` binds it to a
898
+ remote HTTP API instead — every handler forwards the call to a deployed server
899
+ through the contract's typed client:
900
+
901
+ ```ts
902
+ import { createHttpClient } from 'stitchkit'
903
+ import { implementRemote } from 'stitchkit/remote'
904
+ import { createStdioMcpServer } from 'stitchkit/tools'
905
+
906
+ const http = createHttpClient({
907
+ baseUrl: 'https://api.example.com',
908
+ headers: () => ({ Authorization: `Bearer ${apiKey}` }),
909
+ })
910
+
911
+ const stdio = await createStdioMcpServer({
912
+ serverInfo: { name: 'my-app', version: '1.0.0' },
913
+ auth: null,
914
+ services: contracts.map((c) => implementRemote(c, http)),
915
+ })
916
+
917
+ // During graceful shutdown:
918
+ await stdio.close()
919
+ ```
920
+
921
+ This is how you ship a thin **local** MCP server for an API that already runs in
922
+ the cloud: the local process owns only the transport and any filesystem-facing
923
+ native tools, while every contract tool proxies to the remote API. One contract,
924
+ no duplicated business logic.
925
+
926
+ `implementRemote(contract, http, { transformArgs })` takes an optional
927
+ `transformArgs` hook that rewrites a call's arguments before they are forwarded
928
+ — e.g. to upload a local file referenced in the args and swap in its URL.
929
+
930
+ ## Structured output
931
+
932
+ When a contract endpoint or runtime tool declares `output`, its MCP tool
933
+ registers that exact schema as `outputSchema` and returns the validated value as
934
+ `structuredContent` alongside a JSON text block. Every JSON root type is kept
935
+ unchanged: object, array, string, number, boolean and `null`. Stitchkit does not
936
+ wrap non-object values in `{ result }`; protocol-era adaptation belongs to the
937
+ official SDK.
938
+
939
+ A tool without an output contract advertises no `outputSchema` and returns no
940
+ invented structured value. Its successful MCP result has an empty `content`
941
+ list.
942
+
943
+ ## A different answer for tools — `withToolView`
944
+
945
+ An admin page wants the full record; a model wants a card. Every byte of a
946
+ tool result enters the model's context and stays in its history, and personal
947
+ fields a task does not need are better never shown to it. Two endpoints on one
948
+ path (one `expose: ['HTTP']`, one for the tools) duplicate the description, the
949
+ schemas and the handler; branching on `ctx.source` teaches every handler about
950
+ transports and still advertises the full output schema.
951
+
952
+ A **tool view** declares the difference on the endpoint instead:
953
+
954
+ ```ts
955
+ import { defineContract, withToolView } from 'stitchkit';
956
+
957
+ export const users = defineContract({ prefix: 'users' }, {
958
+ list: withToolView(
959
+ {
960
+ method: 'GET', path: '/', desc: 'List users', tool: { name: 'user_list' },
961
+ input: UserListQuery, // include: z.array(...).default(['profile', 'stats'])
962
+ output: UserListResponse, // HTTP, OpenAPI and the typed client — unchanged
963
+ },
964
+ {
965
+ defaults: { include: [] }, // what a tool call gets when it passes nothing
966
+ output: UserCardList, // the tool answer and its schema
967
+ project: (full, { input }) => ({ items: full.items.map(toCard) }), // optional: without it, `output` slices
968
+ },
969
+ ),
970
+ });
971
+ ```
972
+
973
+ - **One handler, one parser.** `defaults` joins the tool call's arguments
974
+ *before* the endpoint's own `input` parses them, so the handler receives an
975
+ ordinary `input` — `include: []` from a tool, the HTTP default from HTTP — and
976
+ loads only what was asked for. An explicit argument wins over the default.
977
+ - **The answer is derived, then checked.** The handler's result is validated
978
+ against the full `output` first, as always; then `project` (a pure,
979
+ synchronous function of the full result and the parsed input) or a slice by
980
+ the view's `output`, then validation against the view's schema. A projection
981
+ that throws, returns a Promise or breaks its schema is `INTERNAL_SERVER_ERROR`
982
+ — a server fault, like any output mismatch.
983
+ - **Where it applies.** The MCP, agent and CLI mounts answer with the view;
984
+ `outputSchema`, `structuredContent`, the advertised input `default`, the
985
+ catalog stamp and the surface snapshot follow it. HTTP, OpenAPI, the typed
986
+ client and the in-process [`createToolInvoker`](#in-process-calls--createtoolinvoker)
987
+ keep the full answer — code, not a model, is calling there.
988
+ - **Three forms, one helper.** With `output` and `project` the answer has its
989
+ own schema. With `project` alone it reshapes values inside the full schema.
990
+ With `output` alone it is a slice, and the full result must fit that schema —
991
+ `withToolView` refuses the endpoint at compile time when it does not.
992
+ - **Exposure.** A view needs a tool transport. With `createContractFactory({
993
+ toolExposure: 'explicit' })` an endpoint without `expose` is HTTP-only, so an
994
+ endpoint with a view names its tool transports in `expose`.
995
+ - **What it refuses.** `defineContract` rejects a view on an endpoint with no
996
+ tool transport or no full `output`, on a raw, `rawBody`, multipart,
997
+ `responseMeta` or streaming endpoint, a view that declares neither `output`
998
+ nor `project`, and a default for a key the input does not have, for a path
999
+ param, or with a value the input would reject.
1000
+
1001
+ A projection adds nothing the full result does not carry: a field the tool
1002
+ answer needs belongs in the full answer, loaded by the handler. Keys a
1003
+ projection returns beyond its schema are reported by `onOutputStrip`; a slice
1004
+ removes keys on purpose and is not reported. → [ADR 0196](../decisions/0196-a-tool-answer-is-a-declared-view.md)