@vibesdotdev/mcp 0.0.0-stage → 1.0.0-rc.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 (602) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +96 -2
  3. package/dist/adapters/auth-middleware.d.ts +68 -0
  4. package/dist/adapters/auth-middleware.d.ts.map +1 -0
  5. package/dist/adapters/auth-middleware.js +161 -0
  6. package/dist/adapters/auth-middleware.js.map +1 -0
  7. package/dist/adapters/compatibility.d.ts +20 -0
  8. package/dist/adapters/compatibility.d.ts.map +1 -0
  9. package/dist/adapters/compatibility.js +57 -0
  10. package/dist/adapters/compatibility.js.map +1 -0
  11. package/dist/adapters/host-context.consumer.d.ts +12 -0
  12. package/dist/adapters/host-context.consumer.d.ts.map +1 -0
  13. package/dist/adapters/host-context.consumer.js +10 -0
  14. package/dist/adapters/host-context.consumer.js.map +1 -0
  15. package/dist/adapters/host-context.d.ts +32 -0
  16. package/dist/adapters/host-context.d.ts.map +1 -0
  17. package/dist/adapters/host-context.js +17 -0
  18. package/dist/adapters/host-context.js.map +1 -0
  19. package/dist/adapters/index.d.ts +12 -0
  20. package/dist/adapters/index.d.ts.map +1 -0
  21. package/dist/adapters/index.js +13 -0
  22. package/dist/adapters/index.js.map +1 -0
  23. package/dist/adapters/mcp/ambient-envelope.d.ts +26 -0
  24. package/dist/adapters/mcp/ambient-envelope.d.ts.map +1 -0
  25. package/dist/adapters/mcp/ambient-envelope.js +70 -0
  26. package/dist/adapters/mcp/ambient-envelope.js.map +1 -0
  27. package/dist/adapters/mcp/catalog.d.ts +15 -0
  28. package/dist/adapters/mcp/catalog.d.ts.map +1 -0
  29. package/dist/adapters/mcp/catalog.js +26 -0
  30. package/dist/adapters/mcp/catalog.js.map +1 -0
  31. package/dist/adapters/mcp/connection-identity.d.ts +81 -0
  32. package/dist/adapters/mcp/connection-identity.d.ts.map +1 -0
  33. package/dist/adapters/mcp/connection-identity.js +114 -0
  34. package/dist/adapters/mcp/connection-identity.js.map +1 -0
  35. package/dist/adapters/mcp/context.d.ts +137 -0
  36. package/dist/adapters/mcp/context.d.ts.map +1 -0
  37. package/dist/adapters/mcp/context.js +230 -0
  38. package/dist/adapters/mcp/context.js.map +1 -0
  39. package/dist/adapters/mcp/formatters.d.ts +41 -0
  40. package/dist/adapters/mcp/formatters.d.ts.map +1 -0
  41. package/dist/adapters/mcp/formatters.js +102 -0
  42. package/dist/adapters/mcp/formatters.js.map +1 -0
  43. package/dist/adapters/mcp/from-api-endpoint.d.ts +59 -0
  44. package/dist/adapters/mcp/from-api-endpoint.d.ts.map +1 -0
  45. package/dist/adapters/mcp/from-api-endpoint.js +206 -0
  46. package/dist/adapters/mcp/from-api-endpoint.js.map +1 -0
  47. package/dist/adapters/mcp/generation-contract.d.ts +5 -0
  48. package/dist/adapters/mcp/generation-contract.d.ts.map +1 -0
  49. package/dist/adapters/mcp/generation-contract.js +34 -0
  50. package/dist/adapters/mcp/generation-contract.js.map +1 -0
  51. package/dist/adapters/mcp/host-registry.d.ts +159 -0
  52. package/dist/adapters/mcp/host-registry.d.ts.map +1 -0
  53. package/dist/adapters/mcp/host-registry.js +237 -0
  54. package/dist/adapters/mcp/host-registry.js.map +1 -0
  55. package/dist/adapters/mcp/index.d.ts +12 -0
  56. package/dist/adapters/mcp/index.d.ts.map +1 -0
  57. package/dist/adapters/mcp/index.js +17 -0
  58. package/dist/adapters/mcp/index.js.map +1 -0
  59. package/dist/adapters/mcp/isolated-notice.d.ts +111 -0
  60. package/dist/adapters/mcp/isolated-notice.d.ts.map +1 -0
  61. package/dist/adapters/mcp/isolated-notice.js +217 -0
  62. package/dist/adapters/mcp/isolated-notice.js.map +1 -0
  63. package/dist/adapters/mcp/json-rpc.d.ts +16 -0
  64. package/dist/adapters/mcp/json-rpc.d.ts.map +1 -0
  65. package/dist/adapters/mcp/json-rpc.js +32 -0
  66. package/dist/adapters/mcp/json-rpc.js.map +1 -0
  67. package/dist/adapters/mcp/local-origin.d.ts +18 -0
  68. package/dist/adapters/mcp/local-origin.d.ts.map +1 -0
  69. package/dist/adapters/mcp/local-origin.js +37 -0
  70. package/dist/adapters/mcp/local-origin.js.map +1 -0
  71. package/dist/adapters/mcp/logging/mcp-cloud.descriptor.d.ts +11 -0
  72. package/dist/adapters/mcp/logging/mcp-cloud.descriptor.d.ts.map +1 -0
  73. package/dist/adapters/mcp/logging/mcp-cloud.descriptor.js +21 -0
  74. package/dist/adapters/mcp/logging/mcp-cloud.descriptor.js.map +1 -0
  75. package/dist/adapters/mcp/logging/mcp-http.descriptor.d.ts +10 -0
  76. package/dist/adapters/mcp/logging/mcp-http.descriptor.d.ts.map +1 -0
  77. package/dist/adapters/mcp/logging/mcp-http.descriptor.js +20 -0
  78. package/dist/adapters/mcp/logging/mcp-http.descriptor.js.map +1 -0
  79. package/dist/adapters/mcp/logging/mcp-server.descriptor.d.ts +9 -0
  80. package/dist/adapters/mcp/logging/mcp-server.descriptor.d.ts.map +1 -0
  81. package/dist/adapters/mcp/logging/mcp-server.descriptor.js +25 -0
  82. package/dist/adapters/mcp/logging/mcp-server.descriptor.js.map +1 -0
  83. package/dist/adapters/mcp/logging/mcp-stdio.descriptor.d.ts +10 -0
  84. package/dist/adapters/mcp/logging/mcp-stdio.descriptor.d.ts.map +1 -0
  85. package/dist/adapters/mcp/logging/mcp-stdio.descriptor.js +20 -0
  86. package/dist/adapters/mcp/logging/mcp-stdio.descriptor.js.map +1 -0
  87. package/dist/adapters/mcp/mcp-http-session.d.ts +140 -0
  88. package/dist/adapters/mcp/mcp-http-session.d.ts.map +1 -0
  89. package/dist/adapters/mcp/mcp-http-session.js +797 -0
  90. package/dist/adapters/mcp/mcp-http-session.js.map +1 -0
  91. package/dist/adapters/mcp/mcp-wire-name.d.ts +9 -0
  92. package/dist/adapters/mcp/mcp-wire-name.d.ts.map +1 -0
  93. package/dist/adapters/mcp/mcp-wire-name.js +52 -0
  94. package/dist/adapters/mcp/mcp-wire-name.js.map +1 -0
  95. package/dist/adapters/mcp/projection-doctor.d.ts +101 -0
  96. package/dist/adapters/mcp/projection-doctor.d.ts.map +1 -0
  97. package/dist/adapters/mcp/projection-doctor.js +285 -0
  98. package/dist/adapters/mcp/projection-doctor.js.map +1 -0
  99. package/dist/adapters/mcp/projection.d.ts +36 -0
  100. package/dist/adapters/mcp/projection.d.ts.map +1 -0
  101. package/dist/adapters/mcp/projection.js +136 -0
  102. package/dist/adapters/mcp/projection.js.map +1 -0
  103. package/dist/adapters/mcp/prompts/continuity-wake.prompt.descriptor.d.ts +113 -0
  104. package/dist/adapters/mcp/prompts/continuity-wake.prompt.descriptor.d.ts.map +1 -0
  105. package/dist/adapters/mcp/prompts/continuity-wake.prompt.descriptor.js +15 -0
  106. package/dist/adapters/mcp/prompts/continuity-wake.prompt.descriptor.js.map +1 -0
  107. package/dist/adapters/mcp/prompts/empty-tool-kind.prompt.descriptor.d.ts +113 -0
  108. package/dist/adapters/mcp/prompts/empty-tool-kind.prompt.descriptor.d.ts.map +1 -0
  109. package/dist/adapters/mcp/prompts/empty-tool-kind.prompt.descriptor.js +18 -0
  110. package/dist/adapters/mcp/prompts/empty-tool-kind.prompt.descriptor.js.map +1 -0
  111. package/dist/adapters/mcp/prompts/index.d.ts +113 -0
  112. package/dist/adapters/mcp/prompts/index.d.ts.map +1 -0
  113. package/dist/adapters/mcp/prompts/index.js +24 -0
  114. package/dist/adapters/mcp/prompts/index.js.map +1 -0
  115. package/dist/adapters/mcp/prompts/isolated-runtime.prompt.descriptor.d.ts +114 -0
  116. package/dist/adapters/mcp/prompts/isolated-runtime.prompt.descriptor.d.ts.map +1 -0
  117. package/dist/adapters/mcp/prompts/isolated-runtime.prompt.descriptor.js +37 -0
  118. package/dist/adapters/mcp/prompts/isolated-runtime.prompt.descriptor.js.map +1 -0
  119. package/dist/adapters/mcp/prompts/local-tools.prompt.descriptor.d.ts +113 -0
  120. package/dist/adapters/mcp/prompts/local-tools.prompt.descriptor.d.ts.map +1 -0
  121. package/dist/adapters/mcp/prompts/local-tools.prompt.descriptor.js +20 -0
  122. package/dist/adapters/mcp/prompts/local-tools.prompt.descriptor.js.map +1 -0
  123. package/dist/adapters/mcp/prompts/max-tools.prompt.descriptor.d.ts +113 -0
  124. package/dist/adapters/mcp/prompts/max-tools.prompt.descriptor.d.ts.map +1 -0
  125. package/dist/adapters/mcp/prompts/max-tools.prompt.descriptor.js +20 -0
  126. package/dist/adapters/mcp/prompts/max-tools.prompt.descriptor.js.map +1 -0
  127. package/dist/adapters/mcp/prompts/private-runtime.prompt.descriptor.d.ts +114 -0
  128. package/dist/adapters/mcp/prompts/private-runtime.prompt.descriptor.d.ts.map +1 -0
  129. package/dist/adapters/mcp/prompts/private-runtime.prompt.descriptor.js +21 -0
  130. package/dist/adapters/mcp/prompts/private-runtime.prompt.descriptor.js.map +1 -0
  131. package/dist/adapters/mcp/prompts/registration-failure.prompt.descriptor.d.ts +113 -0
  132. package/dist/adapters/mcp/prompts/registration-failure.prompt.descriptor.d.ts.map +1 -0
  133. package/dist/adapters/mcp/prompts/registration-failure.prompt.descriptor.js +19 -0
  134. package/dist/adapters/mcp/prompts/registration-failure.prompt.descriptor.js.map +1 -0
  135. package/dist/adapters/mcp/prompts/required-checklist.prompt.descriptor.d.ts +113 -0
  136. package/dist/adapters/mcp/prompts/required-checklist.prompt.descriptor.d.ts.map +1 -0
  137. package/dist/adapters/mcp/prompts/required-checklist.prompt.descriptor.js +18 -0
  138. package/dist/adapters/mcp/prompts/required-checklist.prompt.descriptor.js.map +1 -0
  139. package/dist/adapters/mcp/prompts/required-tools-missing.prompt.descriptor.d.ts +113 -0
  140. package/dist/adapters/mcp/prompts/required-tools-missing.prompt.descriptor.d.ts.map +1 -0
  141. package/dist/adapters/mcp/prompts/required-tools-missing.prompt.descriptor.js +19 -0
  142. package/dist/adapters/mcp/prompts/required-tools-missing.prompt.descriptor.js.map +1 -0
  143. package/dist/adapters/mcp/prompts/unknown-client.prompt.descriptor.d.ts +113 -0
  144. package/dist/adapters/mcp/prompts/unknown-client.prompt.descriptor.d.ts.map +1 -0
  145. package/dist/adapters/mcp/prompts/unknown-client.prompt.descriptor.js +18 -0
  146. package/dist/adapters/mcp/prompts/unknown-client.prompt.descriptor.js.map +1 -0
  147. package/dist/adapters/mcp/request-context.d.ts +28 -0
  148. package/dist/adapters/mcp/request-context.d.ts.map +1 -0
  149. package/dist/adapters/mcp/request-context.js +49 -0
  150. package/dist/adapters/mcp/request-context.js.map +1 -0
  151. package/dist/adapters/mcp/roster-announcer.d.ts +3 -0
  152. package/dist/adapters/mcp/roster-announcer.d.ts.map +1 -0
  153. package/dist/adapters/mcp/roster-announcer.js +22 -0
  154. package/dist/adapters/mcp/roster-announcer.js.map +1 -0
  155. package/dist/adapters/mcp/sampling-context.d.ts +12 -0
  156. package/dist/adapters/mcp/sampling-context.d.ts.map +1 -0
  157. package/dist/adapters/mcp/sampling-context.js +30 -0
  158. package/dist/adapters/mcp/sampling-context.js.map +1 -0
  159. package/dist/adapters/mcp/sampling.d.ts +17 -0
  160. package/dist/adapters/mcp/sampling.d.ts.map +1 -0
  161. package/dist/adapters/mcp/sampling.js +43 -0
  162. package/dist/adapters/mcp/sampling.js.map +1 -0
  163. package/dist/adapters/mcp/schemas/index.d.ts +37 -0
  164. package/dist/adapters/mcp/schemas/index.d.ts.map +1 -0
  165. package/dist/adapters/mcp/schemas/index.js +5 -0
  166. package/dist/adapters/mcp/schemas/index.js.map +1 -0
  167. package/dist/adapters/mcp/schemas/tool-selection.d.ts +12 -0
  168. package/dist/adapters/mcp/schemas/tool-selection.d.ts.map +1 -0
  169. package/dist/adapters/mcp/schemas/tool-selection.js +2 -0
  170. package/dist/adapters/mcp/schemas/tool-selection.js.map +1 -0
  171. package/dist/adapters/mcp/serve-identity.d.ts +64 -0
  172. package/dist/adapters/mcp/serve-identity.d.ts.map +1 -0
  173. package/dist/adapters/mcp/serve-identity.js +220 -0
  174. package/dist/adapters/mcp/serve-identity.js.map +1 -0
  175. package/dist/adapters/mcp/server.consumer.d.ts +5 -0
  176. package/dist/adapters/mcp/server.consumer.d.ts.map +1 -0
  177. package/dist/adapters/mcp/server.consumer.js +300 -0
  178. package/dist/adapters/mcp/server.consumer.js.map +1 -0
  179. package/dist/adapters/mcp/server.d.ts +56 -0
  180. package/dist/adapters/mcp/server.d.ts.map +1 -0
  181. package/dist/adapters/mcp/server.js +1423 -0
  182. package/dist/adapters/mcp/server.js.map +1 -0
  183. package/dist/adapters/mcp/stale-body.consumer.d.ts +85 -0
  184. package/dist/adapters/mcp/stale-body.consumer.d.ts.map +1 -0
  185. package/dist/adapters/mcp/stale-body.consumer.js +183 -0
  186. package/dist/adapters/mcp/stale-body.consumer.js.map +1 -0
  187. package/dist/adapters/mcp/startup-refusal.d.ts +8 -0
  188. package/dist/adapters/mcp/startup-refusal.d.ts.map +1 -0
  189. package/dist/adapters/mcp/startup-refusal.js +141 -0
  190. package/dist/adapters/mcp/startup-refusal.js.map +1 -0
  191. package/dist/adapters/mcp/stdio-relay.d.ts +232 -0
  192. package/dist/adapters/mcp/stdio-relay.d.ts.map +1 -0
  193. package/dist/adapters/mcp/stdio-relay.js +1169 -0
  194. package/dist/adapters/mcp/stdio-relay.js.map +1 -0
  195. package/dist/adapters/mcp/tool-audit-live.d.ts +109 -0
  196. package/dist/adapters/mcp/tool-audit-live.d.ts.map +1 -0
  197. package/dist/adapters/mcp/tool-audit-live.js +538 -0
  198. package/dist/adapters/mcp/tool-audit-live.js.map +1 -0
  199. package/dist/adapters/mcp/tool-audit.d.ts +44 -0
  200. package/dist/adapters/mcp/tool-audit.d.ts.map +1 -0
  201. package/dist/adapters/mcp/tool-audit.js +168 -0
  202. package/dist/adapters/mcp/tool-audit.js.map +1 -0
  203. package/dist/adapters/mcp/tool-catalog.d.ts +179 -0
  204. package/dist/adapters/mcp/tool-catalog.d.ts.map +1 -0
  205. package/dist/adapters/mcp/tool-catalog.js +330 -0
  206. package/dist/adapters/mcp/tool-catalog.js.map +1 -0
  207. package/dist/adapters/mcp/tool-selection.d.ts +77 -0
  208. package/dist/adapters/mcp/tool-selection.d.ts.map +1 -0
  209. package/dist/adapters/mcp/tool-selection.js +266 -0
  210. package/dist/adapters/mcp/tool-selection.js.map +1 -0
  211. package/dist/adapters/mcp/transport-registry.d.ts +5 -0
  212. package/dist/adapters/mcp/transport-registry.d.ts.map +1 -0
  213. package/dist/adapters/mcp/transport-registry.js +13 -0
  214. package/dist/adapters/mcp/transport-registry.js.map +1 -0
  215. package/dist/adapters/mcp/trust-tag.d.ts +69 -0
  216. package/dist/adapters/mcp/trust-tag.d.ts.map +1 -0
  217. package/dist/adapters/mcp/trust-tag.js +120 -0
  218. package/dist/adapters/mcp/trust-tag.js.map +1 -0
  219. package/dist/adapters/mcp/vibes-types.d.ts +115 -0
  220. package/dist/adapters/mcp/vibes-types.d.ts.map +1 -0
  221. package/dist/adapters/mcp/vibes-types.js +7 -0
  222. package/dist/adapters/mcp/vibes-types.js.map +1 -0
  223. package/dist/adapters/mcp/web-handler.d.ts +49 -0
  224. package/dist/adapters/mcp/web-handler.d.ts.map +1 -0
  225. package/dist/adapters/mcp/web-handler.js +129 -0
  226. package/dist/adapters/mcp/web-handler.js.map +1 -0
  227. package/dist/adapters/session-id.d.ts +3 -0
  228. package/dist/adapters/session-id.d.ts.map +1 -0
  229. package/dist/adapters/session-id.js +42 -0
  230. package/dist/adapters/session-id.js.map +1 -0
  231. package/dist/adapters/transport-bun-http.d.ts +39 -0
  232. package/dist/adapters/transport-bun-http.d.ts.map +1 -0
  233. package/dist/adapters/transport-bun-http.js +42 -0
  234. package/dist/adapters/transport-bun-http.js.map +1 -0
  235. package/dist/adapters/types.d.ts +135 -0
  236. package/dist/adapters/types.d.ts.map +1 -0
  237. package/dist/adapters/types.js +2 -0
  238. package/dist/adapters/types.js.map +1 -0
  239. package/dist/adapters/web-compatibility.d.ts +6 -0
  240. package/dist/adapters/web-compatibility.d.ts.map +1 -0
  241. package/dist/adapters/web-compatibility.js +13 -0
  242. package/dist/adapters/web-compatibility.js.map +1 -0
  243. package/dist/adapters/zod-mcp.d.ts +139 -0
  244. package/dist/adapters/zod-mcp.d.ts.map +1 -0
  245. package/dist/adapters/zod-mcp.js +617 -0
  246. package/dist/adapters/zod-mcp.js.map +1 -0
  247. package/dist/cli/mcp/audit/dev.audit.tools.descriptor.d.ts +15 -0
  248. package/dist/cli/mcp/audit/dev.audit.tools.descriptor.d.ts.map +1 -0
  249. package/dist/cli/mcp/audit/dev.audit.tools.descriptor.js +58 -0
  250. package/dist/cli/mcp/audit/dev.audit.tools.descriptor.js.map +1 -0
  251. package/dist/cli/mcp/audit/dev.audit.tools.impl.consumer.d.ts +6 -0
  252. package/dist/cli/mcp/audit/dev.audit.tools.impl.consumer.d.ts.map +1 -0
  253. package/dist/cli/mcp/audit/dev.audit.tools.impl.consumer.js +180 -0
  254. package/dist/cli/mcp/audit/dev.audit.tools.impl.consumer.js.map +1 -0
  255. package/dist/cli/mcp/lifecycle/dev.mcp.restart.descriptor.d.ts +22 -0
  256. package/dist/cli/mcp/lifecycle/dev.mcp.restart.descriptor.d.ts.map +1 -0
  257. package/dist/cli/mcp/lifecycle/dev.mcp.restart.descriptor.js +19 -0
  258. package/dist/cli/mcp/lifecycle/dev.mcp.restart.descriptor.js.map +1 -0
  259. package/dist/cli/mcp/lifecycle/dev.mcp.restart.impl.consumer.d.ts +23 -0
  260. package/dist/cli/mcp/lifecycle/dev.mcp.restart.impl.consumer.d.ts.map +1 -0
  261. package/dist/cli/mcp/lifecycle/dev.mcp.restart.impl.consumer.js +41 -0
  262. package/dist/cli/mcp/lifecycle/dev.mcp.restart.impl.consumer.js.map +1 -0
  263. package/dist/cli/mcp/lifecycle/dev.mcp.serve.descriptor.d.ts +75 -0
  264. package/dist/cli/mcp/lifecycle/dev.mcp.serve.descriptor.d.ts.map +1 -0
  265. package/dist/cli/mcp/lifecycle/dev.mcp.serve.descriptor.js +84 -0
  266. package/dist/cli/mcp/lifecycle/dev.mcp.serve.descriptor.js.map +1 -0
  267. package/dist/cli/mcp/lifecycle/dev.mcp.start.descriptor.d.ts +35 -0
  268. package/dist/cli/mcp/lifecycle/dev.mcp.start.descriptor.d.ts.map +1 -0
  269. package/dist/cli/mcp/lifecycle/dev.mcp.start.descriptor.js +28 -0
  270. package/dist/cli/mcp/lifecycle/dev.mcp.start.descriptor.js.map +1 -0
  271. package/dist/cli/mcp/lifecycle/dev.mcp.start.impl.consumer.d.ts +11 -0
  272. package/dist/cli/mcp/lifecycle/dev.mcp.start.impl.consumer.d.ts.map +1 -0
  273. package/dist/cli/mcp/lifecycle/dev.mcp.start.impl.consumer.js +47 -0
  274. package/dist/cli/mcp/lifecycle/dev.mcp.start.impl.consumer.js.map +1 -0
  275. package/dist/cli/mcp/lifecycle/dev.mcp.stop.descriptor.d.ts +18 -0
  276. package/dist/cli/mcp/lifecycle/dev.mcp.stop.descriptor.d.ts.map +1 -0
  277. package/dist/cli/mcp/lifecycle/dev.mcp.stop.descriptor.js +18 -0
  278. package/dist/cli/mcp/lifecycle/dev.mcp.stop.descriptor.js.map +1 -0
  279. package/dist/cli/mcp/lifecycle/dev.mcp.stop.impl.consumer.d.ts +12 -0
  280. package/dist/cli/mcp/lifecycle/dev.mcp.stop.impl.consumer.d.ts.map +1 -0
  281. package/dist/cli/mcp/lifecycle/dev.mcp.stop.impl.consumer.js +17 -0
  282. package/dist/cli/mcp/lifecycle/dev.mcp.stop.impl.consumer.js.map +1 -0
  283. package/dist/cli/mcp/management/dev.mcp.install.descriptor.d.ts +41 -0
  284. package/dist/cli/mcp/management/dev.mcp.install.descriptor.d.ts.map +1 -0
  285. package/dist/cli/mcp/management/dev.mcp.install.descriptor.js +49 -0
  286. package/dist/cli/mcp/management/dev.mcp.install.descriptor.js.map +1 -0
  287. package/dist/cli/mcp/management/dev.mcp.install.impl.consumer.d.ts +16 -0
  288. package/dist/cli/mcp/management/dev.mcp.install.impl.consumer.d.ts.map +1 -0
  289. package/dist/cli/mcp/management/dev.mcp.install.impl.consumer.js +244 -0
  290. package/dist/cli/mcp/management/dev.mcp.install.impl.consumer.js.map +1 -0
  291. package/dist/cli/mcp/management/dev.mcp.list.descriptor.d.ts +22 -0
  292. package/dist/cli/mcp/management/dev.mcp.list.descriptor.d.ts.map +1 -0
  293. package/dist/cli/mcp/management/dev.mcp.list.descriptor.js +24 -0
  294. package/dist/cli/mcp/management/dev.mcp.list.descriptor.js.map +1 -0
  295. package/dist/cli/mcp/management/dev.mcp.list.impl.consumer.d.ts +29 -0
  296. package/dist/cli/mcp/management/dev.mcp.list.impl.consumer.d.ts.map +1 -0
  297. package/dist/cli/mcp/management/dev.mcp.list.impl.consumer.js +127 -0
  298. package/dist/cli/mcp/management/dev.mcp.list.impl.consumer.js.map +1 -0
  299. package/dist/cli/mcp/management/dev.mcp.status.descriptor.d.ts +48 -0
  300. package/dist/cli/mcp/management/dev.mcp.status.descriptor.d.ts.map +1 -0
  301. package/dist/cli/mcp/management/dev.mcp.status.descriptor.js +56 -0
  302. package/dist/cli/mcp/management/dev.mcp.status.descriptor.js.map +1 -0
  303. package/dist/cli/mcp/management/dev.mcp.status.impl.consumer.d.ts +9 -0
  304. package/dist/cli/mcp/management/dev.mcp.status.impl.consumer.d.ts.map +1 -0
  305. package/dist/cli/mcp/management/dev.mcp.status.impl.consumer.js +253 -0
  306. package/dist/cli/mcp/management/dev.mcp.status.impl.consumer.js.map +1 -0
  307. package/dist/cli/mcp/management/install-helpers.d.ts +26 -0
  308. package/dist/cli/mcp/management/install-helpers.d.ts.map +1 -0
  309. package/dist/cli/mcp/management/install-helpers.js +95 -0
  310. package/dist/cli/mcp/management/install-helpers.js.map +1 -0
  311. package/dist/cli/mcp/management/process-audit.impl.consumer.d.ts +38 -0
  312. package/dist/cli/mcp/management/process-audit.impl.consumer.d.ts.map +1 -0
  313. package/dist/cli/mcp/management/process-audit.impl.consumer.js +145 -0
  314. package/dist/cli/mcp/management/process-audit.impl.consumer.js.map +1 -0
  315. package/dist/cli/mcp/management/rules-debt-summary.impl.consumer.d.ts +21 -0
  316. package/dist/cli/mcp/management/rules-debt-summary.impl.consumer.d.ts.map +1 -0
  317. package/dist/cli/mcp/management/rules-debt-summary.impl.consumer.js +82 -0
  318. package/dist/cli/mcp/management/rules-debt-summary.impl.consumer.js.map +1 -0
  319. package/dist/cli/mcp/management/status-doctor.d.ts +22 -0
  320. package/dist/cli/mcp/management/status-doctor.d.ts.map +1 -0
  321. package/dist/cli/mcp/management/status-doctor.js +153 -0
  322. package/dist/cli/mcp/management/status-doctor.js.map +1 -0
  323. package/dist/cli/mcp/schemas/status-doctor.d.ts +75 -0
  324. package/dist/cli/mcp/schemas/status-doctor.d.ts.map +1 -0
  325. package/dist/cli/mcp/schemas/status-doctor.js +2 -0
  326. package/dist/cli/mcp/schemas/status-doctor.js.map +1 -0
  327. package/dist/cli/mcp/support/host-port.d.ts +31 -0
  328. package/dist/cli/mcp/support/host-port.d.ts.map +1 -0
  329. package/dist/cli/mcp/support/host-port.js +31 -0
  330. package/dist/cli/mcp/support/host-port.js.map +1 -0
  331. package/dist/cli/mcp/support/server-process.impl.consumer.d.ts +24 -0
  332. package/dist/cli/mcp/support/server-process.impl.consumer.d.ts.map +1 -0
  333. package/dist/cli/mcp/support/server-process.impl.consumer.js +86 -0
  334. package/dist/cli/mcp/support/server-process.impl.consumer.js.map +1 -0
  335. package/dist/cli/mcp/support/status-doctor.d.ts +33 -0
  336. package/dist/cli/mcp/support/status-doctor.d.ts.map +1 -0
  337. package/dist/cli/mcp/support/status-doctor.js +104 -0
  338. package/dist/cli/mcp/support/status-doctor.js.map +1 -0
  339. package/dist/cli/print.d.ts +12 -0
  340. package/dist/cli/print.d.ts.map +1 -0
  341. package/dist/cli/print.js +25 -0
  342. package/dist/cli/print.js.map +1 -0
  343. package/dist/cli/surface-mcp/client-connection-identity.consumer.d.ts +19 -0
  344. package/dist/cli/surface-mcp/client-connection-identity.consumer.d.ts.map +1 -0
  345. package/dist/cli/surface-mcp/client-connection-identity.consumer.js +53 -0
  346. package/dist/cli/surface-mcp/client-connection-identity.consumer.js.map +1 -0
  347. package/dist/cli/surface-mcp/dev.mcp.serve.impl.cloud.d.ts +7 -0
  348. package/dist/cli/surface-mcp/dev.mcp.serve.impl.cloud.d.ts.map +1 -0
  349. package/dist/cli/surface-mcp/dev.mcp.serve.impl.cloud.js +345 -0
  350. package/dist/cli/surface-mcp/dev.mcp.serve.impl.cloud.js.map +1 -0
  351. package/dist/cli/surface-mcp/dev.mcp.serve.impl.consumer.d.ts +12 -0
  352. package/dist/cli/surface-mcp/dev.mcp.serve.impl.consumer.d.ts.map +1 -0
  353. package/dist/cli/surface-mcp/dev.mcp.serve.impl.consumer.js +657 -0
  354. package/dist/cli/surface-mcp/dev.mcp.serve.impl.consumer.js.map +1 -0
  355. package/dist/cli/surface-mcp/local-dev-flag.d.ts +24 -0
  356. package/dist/cli/surface-mcp/local-dev-flag.d.ts.map +1 -0
  357. package/dist/cli/surface-mcp/local-dev-flag.js +37 -0
  358. package/dist/cli/surface-mcp/local-dev-flag.js.map +1 -0
  359. package/dist/cli/surface-mcp/shared-host-startup.d.ts +14 -0
  360. package/dist/cli/surface-mcp/shared-host-startup.d.ts.map +1 -0
  361. package/dist/cli/surface-mcp/shared-host-startup.js +46 -0
  362. package/dist/cli/surface-mcp/shared-host-startup.js.map +1 -0
  363. package/dist/cli/surface-mcp/stdio-relay-transport.d.ts +2 -0
  364. package/dist/cli/surface-mcp/stdio-relay-transport.d.ts.map +1 -0
  365. package/dist/cli/surface-mcp/stdio-relay-transport.js +21 -0
  366. package/dist/cli/surface-mcp/stdio-relay-transport.js.map +1 -0
  367. package/dist/cli/surface-mcp/teardown.d.ts +17 -0
  368. package/dist/cli/surface-mcp/teardown.d.ts.map +1 -0
  369. package/dist/cli/surface-mcp/teardown.js +28 -0
  370. package/dist/cli/surface-mcp/teardown.js.map +1 -0
  371. package/dist/client.d.ts +49 -0
  372. package/dist/client.d.ts.map +1 -0
  373. package/dist/client.js +131 -0
  374. package/dist/client.js.map +1 -0
  375. package/dist/config/load.d.ts +6 -0
  376. package/dist/config/load.d.ts.map +1 -0
  377. package/dist/config/load.js +18 -0
  378. package/dist/config/load.js.map +1 -0
  379. package/dist/config/mcp.config.descriptor.d.ts +108 -0
  380. package/dist/config/mcp.config.descriptor.d.ts.map +1 -0
  381. package/dist/config/mcp.config.descriptor.js +63 -0
  382. package/dist/config/mcp.config.descriptor.js.map +1 -0
  383. package/dist/docs/mcp.docs.descriptor.d.ts +4 -0
  384. package/dist/docs/mcp.docs.descriptor.d.ts.map +1 -0
  385. package/dist/docs/mcp.docs.descriptor.js +44 -0
  386. package/dist/docs/mcp.docs.descriptor.js.map +1 -0
  387. package/dist/docs/prompts.docs.descriptor.d.ts +4 -0
  388. package/dist/docs/prompts.docs.descriptor.d.ts.map +1 -0
  389. package/dist/docs/prompts.docs.descriptor.js +130 -0
  390. package/dist/docs/prompts.docs.descriptor.js.map +1 -0
  391. package/dist/docs/resources.docs.descriptor.d.ts +4 -0
  392. package/dist/docs/resources.docs.descriptor.d.ts.map +1 -0
  393. package/dist/docs/resources.docs.descriptor.js +390 -0
  394. package/dist/docs/resources.docs.descriptor.js.map +1 -0
  395. package/dist/docs/server.docs.descriptor.d.ts +4 -0
  396. package/dist/docs/server.docs.descriptor.d.ts.map +1 -0
  397. package/dist/docs/server.docs.descriptor.js +383 -0
  398. package/dist/docs/server.docs.descriptor.js.map +1 -0
  399. package/dist/docs/tools.docs.descriptor.d.ts +4 -0
  400. package/dist/docs/tools.docs.descriptor.d.ts.map +1 -0
  401. package/dist/docs/tools.docs.descriptor.js +316 -0
  402. package/dist/docs/tools.docs.descriptor.js.map +1 -0
  403. package/dist/harness-identity.descriptors.d.ts +11 -0
  404. package/dist/harness-identity.descriptors.d.ts.map +1 -0
  405. package/dist/harness-identity.descriptors.js +41 -0
  406. package/dist/harness-identity.descriptors.js.map +1 -0
  407. package/dist/index.d.ts +36 -0
  408. package/dist/index.d.ts.map +1 -0
  409. package/dist/index.js +36 -0
  410. package/dist/index.js.map +1 -0
  411. package/dist/kinds/harness-identity.kind.d.ts +3 -0
  412. package/dist/kinds/harness-identity.kind.d.ts.map +1 -0
  413. package/dist/kinds/harness-identity.kind.js +16 -0
  414. package/dist/kinds/harness-identity.kind.js.map +1 -0
  415. package/dist/kinds/sampling.kind.d.ts +15 -0
  416. package/dist/kinds/sampling.kind.d.ts.map +1 -0
  417. package/dist/kinds/sampling.kind.js +24 -0
  418. package/dist/kinds/sampling.kind.js.map +1 -0
  419. package/dist/lifecycle-repeat.d.ts +23 -0
  420. package/dist/lifecycle-repeat.d.ts.map +1 -0
  421. package/dist/lifecycle-repeat.js +21 -0
  422. package/dist/lifecycle-repeat.js.map +1 -0
  423. package/dist/mcp/dev.mcp.descriptor.d.ts +18 -0
  424. package/dist/mcp/dev.mcp.descriptor.d.ts.map +1 -0
  425. package/dist/mcp/dev.mcp.descriptor.js +18 -0
  426. package/dist/mcp/dev.mcp.descriptor.js.map +1 -0
  427. package/dist/mcp/index.d.ts +20 -0
  428. package/dist/mcp/index.d.ts.map +1 -0
  429. package/dist/mcp/index.js +19 -0
  430. package/dist/mcp/index.js.map +1 -0
  431. package/dist/mcp/mcp.plugin.d.ts +9 -0
  432. package/dist/mcp/mcp.plugin.d.ts.map +1 -0
  433. package/dist/mcp/mcp.plugin.js +59 -0
  434. package/dist/mcp/mcp.plugin.js.map +1 -0
  435. package/dist/mcp-client.plugin.d.ts +4 -0
  436. package/dist/mcp-client.plugin.d.ts.map +1 -0
  437. package/dist/mcp-client.plugin.js +13 -0
  438. package/dist/mcp-client.plugin.js.map +1 -0
  439. package/dist/mcp.client.descriptor.d.ts +27 -0
  440. package/dist/mcp.client.descriptor.d.ts.map +1 -0
  441. package/dist/mcp.client.descriptor.js +7 -0
  442. package/dist/mcp.client.descriptor.js.map +1 -0
  443. package/dist/mcp.consumer.plugin.d.ts +4 -0
  444. package/dist/mcp.consumer.plugin.d.ts.map +1 -0
  445. package/dist/mcp.consumer.plugin.js +19 -0
  446. package/dist/mcp.consumer.plugin.js.map +1 -0
  447. package/dist/mcp.runtime.plugin.d.ts +10 -0
  448. package/dist/mcp.runtime.plugin.d.ts.map +1 -0
  449. package/dist/mcp.runtime.plugin.js +40 -0
  450. package/dist/mcp.runtime.plugin.js.map +1 -0
  451. package/dist/root-state.d.ts +3 -0
  452. package/dist/root-state.d.ts.map +1 -0
  453. package/dist/root-state.js +3 -0
  454. package/dist/root-state.js.map +1 -0
  455. package/dist/schemas/api-endpoint.d.ts +12 -0
  456. package/dist/schemas/api-endpoint.d.ts.map +1 -0
  457. package/dist/schemas/api-endpoint.js +11 -0
  458. package/dist/schemas/api-endpoint.js.map +1 -0
  459. package/dist/schemas/audit.d.ts +172 -0
  460. package/dist/schemas/audit.d.ts.map +1 -0
  461. package/dist/schemas/audit.js +82 -0
  462. package/dist/schemas/audit.js.map +1 -0
  463. package/dist/schemas/harness-identity.d.ts +41 -0
  464. package/dist/schemas/harness-identity.d.ts.map +1 -0
  465. package/dist/schemas/harness-identity.js +19 -0
  466. package/dist/schemas/harness-identity.js.map +1 -0
  467. package/dist/schemas/host-adapters.d.ts +14 -0
  468. package/dist/schemas/host-adapters.d.ts.map +1 -0
  469. package/dist/schemas/host-adapters.js +7 -0
  470. package/dist/schemas/host-adapters.js.map +1 -0
  471. package/dist/schemas/projection.d.ts +10 -0
  472. package/dist/schemas/projection.d.ts.map +1 -0
  473. package/dist/schemas/projection.js +9 -0
  474. package/dist/schemas/projection.js.map +1 -0
  475. package/dist/schemas/tool.d.ts +8 -0
  476. package/dist/schemas/tool.d.ts.map +1 -0
  477. package/dist/schemas/tool.js +8 -0
  478. package/dist/schemas/tool.js.map +1 -0
  479. package/dist/surface-mcp/build-provenance.d.ts +67 -0
  480. package/dist/surface-mcp/build-provenance.d.ts.map +1 -0
  481. package/dist/surface-mcp/build-provenance.js +287 -0
  482. package/dist/surface-mcp/build-provenance.js.map +1 -0
  483. package/dist/surface-mcp/crash-reporting.d.ts +28 -0
  484. package/dist/surface-mcp/crash-reporting.d.ts.map +1 -0
  485. package/dist/surface-mcp/crash-reporting.js +41 -0
  486. package/dist/surface-mcp/crash-reporting.js.map +1 -0
  487. package/dist/surface-mcp/executable-freshness-watch.d.ts +89 -0
  488. package/dist/surface-mcp/executable-freshness-watch.d.ts.map +1 -0
  489. package/dist/surface-mcp/executable-freshness-watch.js +225 -0
  490. package/dist/surface-mcp/executable-freshness-watch.js.map +1 -0
  491. package/dist/surface-mcp/host-provenance-banner.d.ts +49 -0
  492. package/dist/surface-mcp/host-provenance-banner.d.ts.map +1 -0
  493. package/dist/surface-mcp/host-provenance-banner.js +135 -0
  494. package/dist/surface-mcp/host-provenance-banner.js.map +1 -0
  495. package/dist/surface-mcp/index.d.ts +51 -0
  496. package/dist/surface-mcp/index.d.ts.map +1 -0
  497. package/dist/surface-mcp/index.js +92 -0
  498. package/dist/surface-mcp/index.js.map +1 -0
  499. package/dist/surface-mcp/local-tools-bootstrap.d.ts +36 -0
  500. package/dist/surface-mcp/local-tools-bootstrap.d.ts.map +1 -0
  501. package/dist/surface-mcp/local-tools-bootstrap.js +43 -0
  502. package/dist/surface-mcp/local-tools-bootstrap.js.map +1 -0
  503. package/dist/surface-mcp/mcp-serve.plugin.d.ts +9 -0
  504. package/dist/surface-mcp/mcp-serve.plugin.d.ts.map +1 -0
  505. package/dist/surface-mcp/mcp-serve.plugin.js +24 -0
  506. package/dist/surface-mcp/mcp-serve.plugin.js.map +1 -0
  507. package/dist/surface-mcp/project-config.d.ts +35 -0
  508. package/dist/surface-mcp/project-config.d.ts.map +1 -0
  509. package/dist/surface-mcp/project-config.js +74 -0
  510. package/dist/surface-mcp/project-config.js.map +1 -0
  511. package/dist/surface-mcp/serve-lifecycle.d.ts +102 -0
  512. package/dist/surface-mcp/serve-lifecycle.d.ts.map +1 -0
  513. package/dist/surface-mcp/serve-lifecycle.js +343 -0
  514. package/dist/surface-mcp/serve-lifecycle.js.map +1 -0
  515. package/dist/surface-mcp/session-bridge.d.ts +18 -0
  516. package/dist/surface-mcp/session-bridge.d.ts.map +1 -0
  517. package/dist/surface-mcp/session-bridge.js +26 -0
  518. package/dist/surface-mcp/session-bridge.js.map +1 -0
  519. package/dist/surface-mcp/subscriptions/session.bound.workspace.descriptor.d.ts +13 -0
  520. package/dist/surface-mcp/subscriptions/session.bound.workspace.descriptor.d.ts.map +1 -0
  521. package/dist/surface-mcp/subscriptions/session.bound.workspace.descriptor.js +13 -0
  522. package/dist/surface-mcp/subscriptions/session.bound.workspace.descriptor.js.map +1 -0
  523. package/dist/surface-mcp/subscriptions/session.bound.workspace.impl.consumer.d.ts +11 -0
  524. package/dist/surface-mcp/subscriptions/session.bound.workspace.impl.consumer.d.ts.map +1 -0
  525. package/dist/surface-mcp/subscriptions/session.bound.workspace.impl.consumer.js +36 -0
  526. package/dist/surface-mcp/subscriptions/session.bound.workspace.impl.consumer.js.map +1 -0
  527. package/dist/surface-mcp/workspace-warning.d.ts +16 -0
  528. package/dist/surface-mcp/workspace-warning.d.ts.map +1 -0
  529. package/dist/surface-mcp/workspace-warning.js +44 -0
  530. package/dist/surface-mcp/workspace-warning.js.map +1 -0
  531. package/dist/svelte/index.d.ts +12 -0
  532. package/dist/svelte/index.d.ts.map +1 -0
  533. package/dist/svelte/index.js +11 -0
  534. package/dist/svelte/mcp-svelte.plugin.d.ts +10 -0
  535. package/dist/svelte/mcp-svelte.plugin.d.ts.map +1 -0
  536. package/dist/svelte/mcp-svelte.plugin.js +24 -0
  537. package/dist/svelte/tool-widgets/VibesContextToolCard.svelte +91 -0
  538. package/dist/svelte/tool-widgets/VibesContextToolCard.svelte.d.ts +9 -0
  539. package/dist/svelte/tool-widgets/VibesContextToolCard.svelte.d.ts.map +1 -0
  540. package/dist/svelte/tool-widgets/index.d.ts +3 -0
  541. package/dist/svelte/tool-widgets/index.d.ts.map +1 -0
  542. package/dist/svelte/tool-widgets/index.js +2 -0
  543. package/dist/svelte/tool-widgets/summary.d.ts +48 -0
  544. package/dist/svelte/tool-widgets/summary.d.ts.map +1 -0
  545. package/dist/svelte/tool-widgets/summary.js +117 -0
  546. package/dist/tools/vibes-context/schemas.d.ts +85 -0
  547. package/dist/tools/vibes-context/schemas.d.ts.map +1 -0
  548. package/dist/tools/vibes-context/schemas.js +76 -0
  549. package/dist/tools/vibes-context/schemas.js.map +1 -0
  550. package/dist/tools/vibes-context/vibes-context.descriptor.d.ts +4 -0
  551. package/dist/tools/vibes-context/vibes-context.descriptor.d.ts.map +1 -0
  552. package/dist/tools/vibes-context/vibes-context.descriptor.js +30 -0
  553. package/dist/tools/vibes-context/vibes-context.descriptor.js.map +1 -0
  554. package/dist/tools/vibes-context/vibes-context.impl.d.ts +34 -0
  555. package/dist/tools/vibes-context/vibes-context.impl.d.ts.map +1 -0
  556. package/dist/tools/vibes-context/vibes-context.impl.js +207 -0
  557. package/dist/tools/vibes-context/vibes-context.impl.js.map +1 -0
  558. package/dist/tui/index.d.ts +4 -0
  559. package/dist/tui/index.d.ts.map +1 -0
  560. package/dist/tui/index.js +4 -0
  561. package/dist/tui/index.js.map +1 -0
  562. package/dist/tui/mcp-health.d.ts +7 -0
  563. package/dist/tui/mcp-health.d.ts.map +1 -0
  564. package/dist/tui/mcp-health.js +16 -0
  565. package/dist/tui/mcp-health.js.map +1 -0
  566. package/dist/tui/mcp-tui.plugin.d.ts +3 -0
  567. package/dist/tui/mcp-tui.plugin.d.ts.map +1 -0
  568. package/dist/tui/mcp-tui.plugin.js +18 -0
  569. package/dist/tui/mcp-tui.plugin.js.map +1 -0
  570. package/dist/tui/mcp.tui-app.descriptor.d.ts +4 -0
  571. package/dist/tui/mcp.tui-app.descriptor.d.ts.map +1 -0
  572. package/dist/tui/mcp.tui-app.descriptor.js +19 -0
  573. package/dist/tui/mcp.tui-app.descriptor.js.map +1 -0
  574. package/dist/tui/mcp.tui-app.impl.consumer.d.ts +4 -0
  575. package/dist/tui/mcp.tui-app.impl.consumer.d.ts.map +1 -0
  576. package/dist/tui/mcp.tui-app.impl.consumer.js +48 -0
  577. package/dist/tui/mcp.tui-app.impl.consumer.js.map +1 -0
  578. package/dist/tui/mcp.tui-state.descriptor.d.ts +8 -0
  579. package/dist/tui/mcp.tui-state.descriptor.d.ts.map +1 -0
  580. package/dist/tui/mcp.tui-state.descriptor.js +37 -0
  581. package/dist/tui/mcp.tui-state.descriptor.js.map +1 -0
  582. package/dist/tui/mcp.tui-state.impl.consumer.d.ts +5 -0
  583. package/dist/tui/mcp.tui-state.impl.consumer.d.ts.map +1 -0
  584. package/dist/tui/mcp.tui-state.impl.consumer.js +97 -0
  585. package/dist/tui/mcp.tui-state.impl.consumer.js.map +1 -0
  586. package/dist/tui/mcp.tui-state.key.d.ts +45 -0
  587. package/dist/tui/mcp.tui-state.key.d.ts.map +1 -0
  588. package/dist/tui/mcp.tui-state.key.js +25 -0
  589. package/dist/tui/mcp.tui-state.key.js.map +1 -0
  590. package/dist/types.core.d.ts +25 -0
  591. package/dist/types.core.d.ts.map +1 -0
  592. package/dist/types.core.js +8 -0
  593. package/dist/types.core.js.map +1 -0
  594. package/dist/types.d.ts +71 -0
  595. package/dist/types.d.ts.map +1 -0
  596. package/dist/types.js +2 -0
  597. package/dist/types.js.map +1 -0
  598. package/dist/types.registry.d.ts +93 -0
  599. package/dist/types.registry.d.ts.map +1 -0
  600. package/dist/types.registry.js +32 -0
  601. package/dist/types.registry.js.map +1 -0
  602. package/package.json +323 -4
@@ -0,0 +1,1423 @@
1
+ import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { CallToolRequestSchema, CallToolResultSchema, TextContentSchema, ResourceLinkSchema, CreateMessageResultSchema, ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
3
+ import z from 'zod/v4';
4
+ import { safeParseAsync } from '@modelcontextprotocol/sdk/server/zod-compat.js';
5
+ const registeredTools = new WeakMap();
6
+ const explicitResumeInputSchema = z.object({
7
+ action: z.literal('resume'),
8
+ sessionId: z.string().trim().min(1)
9
+ });
10
+ const receiptRestoreInputSchema = z.object({
11
+ action: z.literal('status'),
12
+ receiptOnly: z.literal(true),
13
+ sessionId: z.string(),
14
+ participantId: z.string()
15
+ });
16
+ const explicitSessionTargetSchema = z.object({ sessionId: z.string().trim().min(1) });
17
+ import { admitConnectionCaller } from "./connection-identity.js";
18
+ import { PROMPTS_MANIFEST_DESCRIPTOR_PREFIX, PROMPTS_MANIFEST_KIND_ID, promptsManifestDescriptorSchema } from '@vibesdotdev/ai-schemas';
19
+ import { resolvePromptText } from '@vibesdotdev/tools/prompts/manifests';
20
+ import { isDiscriminatedUnion, getDiscriminator, getDiscriminatorOptions, flattenDiscriminatedUnionToObject, isPlainUnion, resolveMcpDescription } from "../zod-mcp.js";
21
+ import { CapabilityError, CaughtFailureSchema, isCapabilityError, settle, settleNow, valueFreeFailure } from '@vibesdotdev/kernel';
22
+ import { JsonObjectSchema } from '@vibesdotdev/kernel/schemas/json';
23
+ import { redactedExcerpt } from '@vibesdotdev/shared/utils';
24
+ import { requireMcpClient } from "../../client.js";
25
+ import { resolveMcpTransportRegistry } from "./transport-registry.js";
26
+ import { ToolError } from '@vibesdotdev/tools/errors/tool-error';
27
+ import { getLogger } from '@vibesdotdev/logging';
28
+ import { invokeTool } from '@vibesdotdev/tools/execution/invoke';
29
+ import { ToolInputValidationError } from '@vibesdotdev/tools/execution/input-validation';
30
+ import { buildDirectToolCallContext } from '@vibesdotdev/tools/execution/direct-context';
31
+ import { DEFAULT_AGENT_CAPABILITY_CEILING, TOOL_AGENT_CONTEXT_METADATA_KEY } from '@vibesdotdev/tools/schemas/runtime/capability-tier';
32
+ import { isLocalToolId, localToolsOf } from '@vibesdotdev/tools/local/node/ensure-local-tools';
33
+ import { detectMcpClientId } from '@vibesdotdev/tools/schemas/presets/registry';
34
+ import { loadMcpConfig } from "../../config/load.js";
35
+ import { formatLocalMcpToolDescription, vibesToolOrigin } from "./local-origin.js";
36
+ import { normalizeHarness } from "./serve-identity.js";
37
+ import { missingRequiredTools, selectMcpTools } from "./tool-selection.js";
38
+ import { deriveTrustTier, wrapToolOutputText } from "./trust-tag.js";
39
+ import { createProjectionBirthResource, PROJECTION_BIRTH_RESOURCE_URI, projectionCatalogHash } from "./projection.js";
40
+ import { createMcpWireNameMap, mcpWireToolName } from "./mcp-wire-name.js";
41
+ import { ambientMeta, formatAmbientPrefix, liftAmbientEnvelope } from "./ambient-envelope.js";
42
+ import { computeMcpToolCatalog, createMcpToolCatalogCache, formatRegistrationFailureInstructions } from "./tool-catalog.js";
43
+ import { runWithMcpSamplingCallback } from "./sampling-context.js";
44
+ /**
45
+ * Resolve the effective capability tier ceiling for an MCP connection from the
46
+ * runtime's `mcp` ConfigManifest (`clientCapabilityCeilings`).
47
+ *
48
+ * Verified transport harness identity (`admitConnectionCaller`) takes
49
+ * precedence over server-level `mcpClientId` and `preset`. Unconfigured
50
+ * profiles fall back to the tools default ceiling (`'1'`).
51
+ */
52
+ export function resolveMcpClientCapabilityCeiling(config, input, source) {
53
+ const ceilings = config.clientCapabilityCeilings;
54
+ const candidates = [];
55
+ const pushCandidate = (raw) => {
56
+ const trimmed = raw?.trim().toLowerCase();
57
+ if (!trimmed)
58
+ return;
59
+ if (!candidates.includes(trimmed))
60
+ candidates.push(trimmed);
61
+ const normalized = (source ? normalizeHarness(source, trimmed) : undefined) ?? detectMcpClientId(trimmed) ?? undefined;
62
+ if (normalized && !candidates.includes(normalized))
63
+ candidates.push(normalized);
64
+ };
65
+ const verifiedHarness = input.admittedCaller?.harness;
66
+ if (verifiedHarness && verifiedHarness !== 'custom') {
67
+ pushCandidate(verifiedHarness);
68
+ }
69
+ pushCandidate(input.mcpClientId);
70
+ if (input.preset) {
71
+ pushCandidate(input.preset.replace(/^mcp:/i, ''));
72
+ }
73
+ if (verifiedHarness === 'custom') {
74
+ pushCandidate(verifiedHarness);
75
+ }
76
+ for (const candidate of candidates) {
77
+ const configured = ceilings[candidate];
78
+ if (configured !== undefined) {
79
+ return { profile: candidate, ceiling: configured };
80
+ }
81
+ }
82
+ return { profile: candidates[0], ceiling: DEFAULT_AGENT_CAPABILITY_CEILING };
83
+ }
84
+ /**
85
+ * Project-local catalog ids (CLI `list --source=local` parity). Explicit
86
+ * options win (tests, serve bootstrap); otherwise the tools this runtime's
87
+ * discovery pass registered from `.vibes/tools`.
88
+ *
89
+ * This is the one node-scoped read in the build path, so it lives here rather
90
+ * than in `tool-catalog.ts`, which stays isomorphic.
91
+ */
92
+ export function resolveLocalToolIds(runtime, options) {
93
+ return options.localToolIds ?? localToolsOf(runtime).toolIds;
94
+ }
95
+ /**
96
+ * The catalog cache a serving surface should hold: one fold of the registry,
97
+ * shared by every connection, re-folded the moment the registry moves.
98
+ *
99
+ * `loaderSettlement` stays `'advisory'` unless the caller can name the
100
+ * registration bound for its serving surface (see {@link McpLoaderSettlement}).
101
+ * A settled cache excludes descriptors whose loader is unresolvable at fold
102
+ * time, and admits them on the next fold if one registers — the revision key
103
+ * is the guarantee.
104
+ */
105
+ export function createMcpServerCatalogCache(runtime, options, logger, loaderSettlement = 'advisory') {
106
+ return createMcpToolCatalogCache(runtime, options, logger, () => resolveLocalToolIds(runtime, options), loaderSettlement);
107
+ }
108
+ function isStringValue(value) {
109
+ return typeof value === 'string';
110
+ }
111
+ function asJsonObject(value) {
112
+ const parsed = JsonObjectSchema.safeParse(value);
113
+ return parsed.success ? parsed.data : undefined;
114
+ }
115
+ const JsonTextSchema = z.string();
116
+ /** Re-admit a JSON text: objects become structuredContent; arrays and null stay text. */
117
+ function wireJsonText(text) {
118
+ const parsed = settleNow(() => JSON.parse(text));
119
+ if (!parsed.ok) {
120
+ throw new CapabilityError('the tool output is not JSON', 'INVALID_INPUT', {
121
+ reason: 'mcp-tool-output-not-json',
122
+ cause: parsed.cause
123
+ });
124
+ }
125
+ const structured = JsonObjectSchema.safeParse(parsed.value);
126
+ return structured.success ? { text, structured: structured.data } : { text };
127
+ }
128
+ const ZodIssueListSchema = z.object({
129
+ issues: z.array(z.object({
130
+ path: z.array(z.union([z.string(), z.number()])).optional(),
131
+ message: z.string().optional(),
132
+ values: z.array(z.union([z.string(), z.number(), z.boolean(), z.null()])).optional()
133
+ }))
134
+ });
135
+ const ToolHookFailureSchema = z.object({
136
+ code: z.string().optional(),
137
+ recoveryHint: z.string().optional(),
138
+ retryable: z.boolean().optional(),
139
+ metadata: JsonObjectSchema.optional(),
140
+ alternatives: z.array(z.string()).optional()
141
+ });
142
+ const SafetyReadOnlySchema = z.object({ readOnly: z.boolean().optional() });
143
+ // SDK metadata and content contracts govern passthrough. Content stays required:
144
+ // the SDK's default empty array must not classify ordinary domain output as MCP.
145
+ const mcpToolResponseSchema = CallToolResultSchema.extend({
146
+ content: z.array(z.union([TextContentSchema, ResourceLinkSchema]))
147
+ });
148
+ function readMcpToolResponse(value) {
149
+ const parsed = mcpToolResponseSchema.safeParse(value);
150
+ return parsed.success ? parsed.data : undefined;
151
+ }
152
+ function formatZodIssues(error) {
153
+ const parsed = ZodIssueListSchema.safeParse(error);
154
+ if (!parsed.success || parsed.data.issues.length === 0)
155
+ return 'Invalid input';
156
+ return parsed.data.issues
157
+ .slice(0, 4)
158
+ .map((issue) => {
159
+ const path = issue.path && issue.path.length > 0 ? issue.path.join('.') : '<root>';
160
+ const allowed = issue.values && issue.values.length > 0
161
+ ? ` (allowed: ${issue.values.map(String).join(', ')})`
162
+ : '';
163
+ const message = issue.message ?? 'Invalid input';
164
+ return `${path}: ${message}${allowed}`;
165
+ })
166
+ .join('; ');
167
+ }
168
+ /** The most characters of a typed failure's text the model sees. */
169
+ const MODEL_FAILURE_TEXT_MAX_CHARS = 4000;
170
+ /**
171
+ * The text a tool failure may put in the model's context. Typed failures
172
+ * (CapabilityError, input validation, ToolError) carry deliberate, value-free
173
+ * messages and pass the shared credential redactor; anything else is a fixed
174
+ * INTERNAL sentence naming only its value-free facts. The raw text goes to the
175
+ * log as a redacted excerpt, never to the model.
176
+ */
177
+ function modelSafeFailureText(error) {
178
+ if (error instanceof ToolInputValidationError || error instanceof ToolError || isCapabilityError(error)) {
179
+ return redactedExcerpt(error.message, { maxChars: MODEL_FAILURE_TEXT_MAX_CHARS });
180
+ }
181
+ const facts = valueFreeFailure(error);
182
+ return `The tool failed with an internal error (${facts.name}${facts.code === undefined ? '' : ` ${facts.code}`}).`;
183
+ }
184
+ function projectMcpToolFailure(thrown) {
185
+ const error = CaughtFailureSchema.parse(thrown);
186
+ if (error instanceof ToolInputValidationError) {
187
+ const message = modelSafeFailureText(error);
188
+ const capability = new CapabilityError(message, 'INVALID_INPUT', {
189
+ recoveryHint: 'Fix the listed input issues and retry.',
190
+ details: { issues: error.issues }
191
+ });
192
+ return { message, code: 'INVALID_INPUT', envelope: { ...capability.toEnvelope() } };
193
+ }
194
+ if (isCapabilityError(error)) {
195
+ return { message: modelSafeFailureText(error), code: error.code, envelope: { ...error.toEnvelope() } };
196
+ }
197
+ const message = modelSafeFailureText(error);
198
+ // A timeout is read from the failure's own text but never copied out of it.
199
+ const timedOut = error instanceof Error && /timed out/i.test(error.message);
200
+ const code = timedOut ? 'TIMEOUT' : 'INTERNAL';
201
+ const failureOptions = { retryable: timedOut };
202
+ if (timedOut)
203
+ failureOptions.details = { timedOut: true };
204
+ const envelope = new CapabilityError(message, code, failureOptions).toEnvelope();
205
+ return { message, code, envelope };
206
+ }
207
+ function getSuggestedToolCallFromErrorMetadata(metadata) {
208
+ if (!metadata)
209
+ return undefined;
210
+ const containmentRequest = metadata.containmentRequest;
211
+ const containment = asJsonObject(containmentRequest);
212
+ if (!containment)
213
+ return undefined;
214
+ return {
215
+ toolId: 'workspace-fs',
216
+ input: {
217
+ action: 'write',
218
+ writeAction: 'request-access',
219
+ ...containment
220
+ }
221
+ };
222
+ }
223
+ function isZodLike(value) {
224
+ return value instanceof z.ZodType;
225
+ }
226
+ function isSafetyCategory(safety) {
227
+ return typeof safety === 'string';
228
+ }
229
+ function deriveMcpAnnotations(safety) {
230
+ if (!safety)
231
+ return undefined;
232
+ const category = isSafetyCategory(safety) ? safety : safety.category;
233
+ const hints = isSafetyCategory(safety) ? undefined : safety;
234
+ // Default values based on category
235
+ const defaults = {
236
+ read: {
237
+ readOnlyHint: true,
238
+ destructiveHint: false,
239
+ idempotentHint: true,
240
+ openWorldHint: false
241
+ },
242
+ write: {
243
+ readOnlyHint: false,
244
+ destructiveHint: true,
245
+ idempotentHint: false,
246
+ openWorldHint: false
247
+ },
248
+ execute: {
249
+ readOnlyHint: false,
250
+ destructiveHint: false,
251
+ idempotentHint: false,
252
+ openWorldHint: true
253
+ }
254
+ }[category] ?? {
255
+ readOnlyHint: false,
256
+ destructiveHint: false,
257
+ idempotentHint: false,
258
+ openWorldHint: false
259
+ };
260
+ // Apply explicit overrides. `readOnly` is read defensively (the
261
+ // SafetyField type does not declare it yet) so a descriptor that declares
262
+ // an explicit readOnly hint is honored instead of silently taking the
263
+ // category default.
264
+ const parsedReadOnly = hints ? SafetyReadOnlySchema.safeParse(hints) : undefined;
265
+ const readOnly = parsedReadOnly?.success ? parsedReadOnly.data.readOnly : undefined;
266
+ return {
267
+ readOnlyHint: readOnly ?? defaults.readOnlyHint,
268
+ destructiveHint: hints?.destructive ?? defaults.destructiveHint,
269
+ idempotentHint: hints?.idempotent ?? defaults.idempotentHint,
270
+ openWorldHint: hints?.openWorld ?? defaults.openWorldHint
271
+ };
272
+ }
273
+ function uniqueName(base, used) {
274
+ if (!used.has(base)) {
275
+ used.add(base);
276
+ return base;
277
+ }
278
+ let index = 2;
279
+ let candidate = `${base}.${index}`;
280
+ while (used.has(candidate)) {
281
+ index += 1;
282
+ candidate = `${base}.${index}`;
283
+ }
284
+ used.add(candidate);
285
+ return candidate;
286
+ }
287
+ function getDescriptorMcpDescription(descriptor) {
288
+ return resolveMcpDescription(descriptor);
289
+ }
290
+ function buildResourceText(descriptor, resourceName, uri, variables) {
291
+ const description = getDescriptorMcpDescription(descriptor);
292
+ return JSON.stringify({
293
+ kind: 'descriptor-metadata',
294
+ note: 'Descriptor metadata payload; not live resource data.',
295
+ tool: {
296
+ id: descriptor.id,
297
+ name: descriptor.name ?? descriptor.id,
298
+ description: description || null
299
+ },
300
+ resource: {
301
+ name: resourceName,
302
+ uri
303
+ },
304
+ variables
305
+ }, null, 2);
306
+ }
307
+ /** MCP prompt arguments arrive as strings; each manifest-declared argument becomes one. */
308
+ function buildPromptArgsSchema(argumentsSchema) {
309
+ if (!argumentsSchema || argumentsSchema.length === 0)
310
+ return undefined;
311
+ const argumentSchemas = {};
312
+ for (const arg of argumentsSchema) {
313
+ // Describe the outer schema: the SDK lists an optional argument's own description.
314
+ const description = arg.description ?? `${arg.name} argument`;
315
+ argumentSchemas[arg.name] = arg.required ? z.string().describe(description) : z.string().optional().describe(description);
316
+ }
317
+ return argumentSchemas;
318
+ }
319
+ function registerDescriptorMcpDefinitions(server, descriptors, runtime, logger, options = { announce: true }) {
320
+ const resourceUris = new Set();
321
+ const resourceNames = new Set();
322
+ const promptNames = new Set();
323
+ const promptIds = new Set();
324
+ const mcpLog = logger.child('mcp-definitions');
325
+ const canResolvePromptIds = runtime.hasKind(PROMPTS_MANIFEST_KIND_ID);
326
+ for (const descriptor of descriptors) {
327
+ const mcp = descriptor.mcp;
328
+ if (!mcp)
329
+ continue;
330
+ const resources = [...(mcp.resource ? [mcp.resource] : []), ...(mcp.resources ?? [])];
331
+ for (const resource of resources) {
332
+ if (resource.uri === PROJECTION_BIRTH_RESOURCE_URI)
333
+ throw new Error('Reserved projection birth resource URI');
334
+ if (resourceUris.has(resource.uri))
335
+ continue;
336
+ resourceUris.add(resource.uri);
337
+ const name = uniqueName(resource.name || `${descriptor.id}.resource`, resourceNames);
338
+ server.registerResource(name, resource.uri, {
339
+ description: resource.description
340
+ ? `${resource.description} (descriptor metadata)`
341
+ : `Descriptor metadata for ${descriptor.id}`,
342
+ mimeType: resource.mimeType,
343
+ _meta: {
344
+ vibes: {
345
+ toolId: descriptor.id,
346
+ cacheable: resource.cacheable,
347
+ subscriptions: resource.subscriptions
348
+ }
349
+ }
350
+ }, (uri) => ({
351
+ contents: [
352
+ {
353
+ uri: uri.href,
354
+ mimeType: resource.mimeType ?? 'application/json',
355
+ text: buildResourceText(descriptor, name, uri.href)
356
+ }
357
+ ]
358
+ }));
359
+ }
360
+ for (const template of mcp.resourceTemplates ?? []) {
361
+ if (template.uriTemplate === PROJECTION_BIRTH_RESOURCE_URI)
362
+ throw new Error('Reserved projection birth resource URI');
363
+ const name = uniqueName(template.name || `${descriptor.id}.resource-template`, resourceNames);
364
+ const uriTemplate = new ResourceTemplate(template.uriTemplate, { list: undefined });
365
+ server.registerResource(name, uriTemplate, {
366
+ description: template.description
367
+ ? `${template.description} (descriptor metadata)`
368
+ : `Descriptor metadata template for ${descriptor.id}`,
369
+ mimeType: template.mimeType,
370
+ _meta: {
371
+ vibes: {
372
+ toolId: descriptor.id,
373
+ cacheable: template.cacheable,
374
+ subscriptions: template.subscriptions
375
+ }
376
+ }
377
+ }, (uri, variables) => ({
378
+ contents: [
379
+ {
380
+ uri: uri.href,
381
+ mimeType: template.mimeType ?? 'application/json',
382
+ text: buildResourceText(descriptor, name, uri.href, variables)
383
+ }
384
+ ]
385
+ }));
386
+ }
387
+ if (canResolvePromptIds) {
388
+ for (const promptId of mcp.promptIds ?? []) {
389
+ if (promptIds.has(promptId))
390
+ continue;
391
+ promptIds.add(promptId);
392
+ const name = uniqueName(`ai.prompt.${promptId}`, promptNames);
393
+ const registered = runtime.query(PROMPTS_MANIFEST_KIND_ID)
394
+ .withId(`${PROMPTS_MANIFEST_DESCRIPTOR_PREFIX}${promptId}`)
395
+ .firstDescriptor();
396
+ const manifest = registered ? promptsManifestDescriptorSchema.parse(registered).manifest : undefined;
397
+ const promptDescription = manifest
398
+ ? resolveMcpDescription({ id: promptId, name: manifest.name, description: manifest.description || undefined })
399
+ : `Prompt descriptor ${promptId}`;
400
+ const argsSchema = buildPromptArgsSchema(manifest?.arguments) ?? {};
401
+ server.registerPrompt(name, {
402
+ description: promptDescription,
403
+ argsSchema
404
+ }, async (args) => {
405
+ // THE prompts kind renders the prompt with its composition, declared defaults and the caller's arguments.
406
+ const text = await resolvePromptText(runtime, promptId, { args });
407
+ return {
408
+ description: promptDescription,
409
+ messages: [
410
+ {
411
+ role: 'user',
412
+ content: {
413
+ type: 'text',
414
+ text: text || `Prompt '${promptId}' has no prompts/manifest content to expose.`
415
+ }
416
+ }
417
+ ]
418
+ };
419
+ });
420
+ }
421
+ }
422
+ }
423
+ // Announced once per catalog fold; identical on every later connection.
424
+ const summary = { resources: resourceUris.size, prompts: promptNames.size };
425
+ if (options.announce) {
426
+ mcpLog.info('Registered MCP descriptor definitions', summary);
427
+ }
428
+ else {
429
+ mcpLog.debug('Registered MCP descriptor definitions', summary);
430
+ }
431
+ }
432
+ /**
433
+ * Construct one `McpServer` for one connection.
434
+ *
435
+ * The catalog fold (discover → enable → select → instructions) is NOT done
436
+ * here: pass a `catalog` from `createMcpToolCatalogCache` so many connections
437
+ * share one fold. When omitted the fold happens inline, which keeps every
438
+ * single-server caller (stdio, tests) working exactly as before.
439
+ */
440
+ export function buildServer(runtime, options, logger, catalog = computeMcpToolCatalog(runtime, options, logger, resolveLocalToolIds(runtime, options))) {
441
+ const buildLog = logger.child('build');
442
+ const serverName = options.serverName ?? 'vibes';
443
+ const serverVersion = options.serverVersion ?? '0.0.0';
444
+ if (catalog.degradedKind) {
445
+ // Constitution rule 13: empty tools/list must not look healthy. The
446
+ // banner was composed (and error-logged) by the catalog fold.
447
+ return new McpServer({ name: serverName, version: serverVersion }, {
448
+ capabilities: catalog.capabilities,
449
+ instructions: catalog.instructions
450
+ });
451
+ }
452
+ const selected = catalog.selected;
453
+ if (!selected) {
454
+ throw new Error('MCP tool catalog is non-degraded but carries no selection');
455
+ }
456
+ const enabledDescriptors = catalog.enabledDescriptors;
457
+ const localToolIds = catalog.localToolIds;
458
+ const descriptors = catalog.descriptors;
459
+ createMcpWireNameMap(descriptors.map(descriptor => descriptor.id), options.mcpClientId, catalog.purposePresets);
460
+ const capabilities = catalog.capabilities;
461
+ const instructions = catalog.instructions;
462
+ const preScanFailedTools = [...catalog.preScanFailedTools];
463
+ const failedTools = [...preScanFailedTools];
464
+ let registeredCount = 0;
465
+ const registeredToolIds = [];
466
+ const server = new McpServer({ name: serverName, version: serverVersion }, {
467
+ capabilities,
468
+ instructions: instructions || undefined
469
+ });
470
+ for (const descriptor of descriptors) {
471
+ if (!descriptor.schemas?.input) {
472
+ // Already counted in preFailed / instructions.
473
+ continue;
474
+ }
475
+ const registered = settleNow(() => registerTool(server, descriptor, runtime, { ...options, customPresets: catalog.purposePresets }, logger, localToolIds));
476
+ if (!registered.ok) {
477
+ const facts = valueFreeFailure(registered.cause);
478
+ failedTools.push(`${descriptor.id}: ${facts.name}`);
479
+ buildLog.error(`Failed to register tool: ${descriptor.id}`, { error: facts });
480
+ continue;
481
+ }
482
+ if (registered.value) {
483
+ registeredCount++;
484
+ registeredToolIds.push(descriptor.id);
485
+ }
486
+ else {
487
+ failedTools.push(`${descriptor.id}: schema conversion failed`);
488
+ buildLog.warn(`Tool registration returned false: ${descriptor.id}`);
489
+ }
490
+ }
491
+ // One INFO per catalog fold, DEBUG for every later connection served from the
492
+ // same fold: the work is identical, so repeating the line per connection is
493
+ // noise that hides real events (7,291 of these in 53 h of uptime).
494
+ const announce = !catalog.announced;
495
+ catalog.announced = true;
496
+ const registrationSummary = `Registered ${registeredCount}/${descriptors.length} tools with MCP server`;
497
+ if (announce) {
498
+ buildLog.info(registrationSummary, { descriptorRevision: catalog.revision });
499
+ }
500
+ else {
501
+ buildLog.debug(registrationSummary, { descriptorRevision: catalog.revision });
502
+ }
503
+ if (failedTools.length > 0) {
504
+ buildLog.error(`MCP tool registration incomplete: ${failedTools.length} tool(s) not advertised to agents`, { failedTools, registeredCount, selectedCount: descriptors.length });
505
+ }
506
+ // Late failures were not known at construct — patch `_instructions` so the
507
+ // host still sees DEGRADED TOOLSET at session start (rule 13).
508
+ const lateFailedTools = failedTools.slice(preScanFailedTools.length);
509
+ if (lateFailedTools.length > 0) {
510
+ appendMcpInstructions(server, formatRegistrationFailureInstructions(lateFailedTools));
511
+ }
512
+ // Continuity contract: required tools that were selected but lack schemas.input
513
+ // (pre-scan) fail closed — same injury class as missingRequired at selection.
514
+ const requiredSet = new Set(selected.preset?.requiredTools ?? []);
515
+ const requiredMissingSchema = descriptors
516
+ .filter((d) => requiredSet.has(d.id) && !d.schemas?.input)
517
+ .map((d) => d.id);
518
+ if (requiredMissingSchema.length > 0) {
519
+ const message = `REQUIRED MCP TOOLS CANNOT BE ADVERTISED for preset ${selected.presetId}: ` +
520
+ `${requiredMissingSchema.join(', ')} (no schemas.input). ` +
521
+ `These continuity tools must not silently vanish from tools/list.`;
522
+ buildLog.error(message, { requiredMissingSchema, failedTools });
523
+ throw new Error(message);
524
+ }
525
+ // Determinism gate (czar D2 / c198b7bc):
526
+ // Serve-time registry hash vs selected policy ids asserted equal every boot.
527
+ const selectedToolIds = descriptors.map((descriptor) => descriptor.id);
528
+ const selectedCatalogHash = projectionCatalogHash(selectedToolIds);
529
+ const registeredCatalogHash = projectionCatalogHash(registeredToolIds);
530
+ if (selectedCatalogHash !== registeredCatalogHash) {
531
+ const unregisteredIds = selectedToolIds.filter((id) => !registeredToolIds.includes(id));
532
+ buildLog.error(`MCP serve catalog indeterminism: registered toolset hash (${registeredCatalogHash}) differs from selected policy ids (${selectedCatalogHash})`, {
533
+ selectedCatalogHash,
534
+ registeredCatalogHash,
535
+ unregisteredIds
536
+ });
537
+ }
538
+ // Snapshot before client detection or generation changes can add served tools.
539
+ if (options.buildProvenance) {
540
+ const birth = createProjectionBirthResource({ provenance: options.buildProvenance, selectedToolIds, registeredToolIds });
541
+ server.registerResource('vibes-projection-birth', PROJECTION_BIRTH_RESOURCE_URI, { description: 'Immutable startup snapshot; not a host-visible catalog attestation.', mimeType: 'application/json' }, () => ({ contents: [{ uri: PROJECTION_BIRTH_RESOURCE_URI, mimeType: 'application/json', text: birth.text }] }));
542
+ const warning = options.buildProvenance.match(/^⚠ (?:EXECUTABLE SOURCE UNKNOWN|DIRTY BUILD|STALE BUILD):/);
543
+ if (warning)
544
+ appendMcpInstructions(server, `${warning[0]} Read ${PROJECTION_BIRTH_RESOURCE_URI} for source identity and recovery guidance.`);
545
+ appendMcpInstructions(server, birth.instructions);
546
+ }
547
+ registerDescriptorMcpDefinitions(server, descriptors, runtime, logger, { announce });
548
+ // Client auto-detection (2025-era scar tissue): when serve was spawned without
549
+ // --client, the base `mcp` preset applies and client-curated tools stay hidden.
550
+ // After initialize, we additive-register the detected preset and emit
551
+ // tools/listChanged.
552
+ //
553
+ // MCP 2026-07-28: tools/list MUST NOT vary per connection. This path mutates
554
+ // the catalog after initialize and is therefore gated behind an explicit
555
+ // opt-in (`allowClientAutoDetectUpgrade`, default OFF). Pass --client (or
556
+ // pack config) so the catalog is fixed at start.
557
+ // See docs/proposals/mcp-2026-07-28/FINDINGS.md.
558
+ if (!options.mcpClientId && options.allowClientAutoDetectUpgrade) {
559
+ const baselineIds = new Set(descriptors.map((descriptor) => descriptor.id));
560
+ server.server.oninitialized = () => {
561
+ const detected = settleNow(() => {
562
+ const clientName = server.server.getClientVersion()?.name;
563
+ const detectedClientId = detectMcpClientId(clientName, catalog.purposePresets);
564
+ if (!detectedClientId)
565
+ return;
566
+ buildLog.warn('MCP catalog mutated after initialize (client auto-detect). ' +
567
+ 'Illegal under protocol 2026-07-28 — pass --client so the preset is fixed at start.', { clientName, detectedClientId });
568
+ // Same registration bound as the construct-time fold: a settled
569
+ // surface must not re-admit an unavailable descriptor through
570
+ // this opt-in mutation path. `zombieCandidates` is exactly the
571
+ // fold's unavailable set.
572
+ const settlementExcluded = catalog.loaderSettlement === 'settled' ? new Set(catalog.zombieCandidates) : null;
573
+ const upgraded = selectMcpTools(settlementExcluded
574
+ ? enabledDescriptors.filter((descriptor) => !settlementExcluded.has(descriptor.id))
575
+ : [...enabledDescriptors], { mcpClientId: detectedClientId, customPresets: catalog.purposePresets });
576
+ const additions = upgraded.descriptors.filter((descriptor) => !baselineIds.has(descriptor.id));
577
+ if (additions.length === 0)
578
+ return;
579
+ let added = 0;
580
+ const upgradeFailures = [];
581
+ for (const descriptor of additions) {
582
+ const registered = settleNow(() => registerTool(server, descriptor, runtime, { ...options, customPresets: catalog.purposePresets }, logger, localToolIds));
583
+ if (!registered.ok) {
584
+ const facts = valueFreeFailure(registered.cause);
585
+ upgradeFailures.push(`${descriptor.id}: ${facts.name}`);
586
+ // Error (not warn): continuity tools often land only via
587
+ // this path when --client was omitted at serve start.
588
+ buildLog.error(`Client-detected tool failed to register: ${descriptor.id}`, { error: facts });
589
+ continue;
590
+ }
591
+ if (registered.value) {
592
+ baselineIds.add(descriptor.id);
593
+ added += 1;
594
+ }
595
+ else {
596
+ upgradeFailures.push(`${descriptor.id}: schema conversion failed`);
597
+ buildLog.error(`Client-detected tool failed to register: ${descriptor.id}`, { error: 'schema conversion failed' });
598
+ }
599
+ }
600
+ // Initialize already returned construct-time instructions; patch
601
+ // so agents that re-read server state / later sessions see the gap.
602
+ // Hosts that only saw initialize may still miss this — error log
603
+ // remains load-bearing until listChanged + instructions re-push.
604
+ if (upgradeFailures.length > 0) {
605
+ appendMcpInstructions(server, formatRegistrationFailureInstructions(upgradeFailures));
606
+ buildLog.error(`Client-detected preset upgrade incomplete: ${upgradeFailures.length} tool(s) not advertised`, { upgradeFailures, added, detectedClientId });
607
+ }
608
+ // Required continuity tools for the detected client must not
609
+ // vanish silently (brain/presence class outage via auto-detect).
610
+ const stillMissingRequired = missingRequiredTools([...baselineIds], upgraded.preset);
611
+ if (stillMissingRequired.length > 0) {
612
+ const section = `⚠ DEGRADED SURFACE: required tools missing after client auto-detect ` +
613
+ `(${detectedClientId}): ${stillMissingRequired.join(', ')}. ` +
614
+ `Report this to the user IMMEDIATELY; do NOT silently work around it.`;
615
+ appendMcpInstructions(server, section);
616
+ buildLog.error('REQUIRED MCP TOOLS MISSING after client auto-detect', {
617
+ detectedClientId,
618
+ stillMissingRequired
619
+ });
620
+ }
621
+ buildLog.info('Client-detected preset upgrade', {
622
+ clientName,
623
+ detectedClientId,
624
+ presetId: upgraded.presetId,
625
+ added,
626
+ addedTools: additions.map((descriptor) => descriptor.id),
627
+ upgradeFailures
628
+ });
629
+ });
630
+ if (!detected.ok) {
631
+ const facts = valueFreeFailure(detected.cause);
632
+ // Whole-path failure (not per-tool): still a rule-13 injury —
633
+ // thin base preset can look healthy without continuity tools.
634
+ appendMcpInstructions(server, '⚠ DEGRADED SURFACE: client preset auto-detection failed after initialize. ' +
635
+ 'Continuity tools for the connected client may be missing. ' +
636
+ 'Report this to the user IMMEDIATELY; do NOT silently work around it. ' +
637
+ 'Diagnose: pass --client explicitly or check MCP initialize clientInfo.name.');
638
+ buildLog.error('Client preset auto-detection failed', { error: facts });
639
+ }
640
+ };
641
+ }
642
+ // Own admission before asynchronous SDK schema parsing. RegisteredTool is
643
+ // a public SDK handle; replacing it leaves admitted calls' schemas intact.
644
+ //
645
+ // Protocol shape: an unknown tool or unsupported task execution is a
646
+ // request error, not a tool-execution error — per MCP spec these are
647
+ // JSON-RPC -32602 responses, not HTTP-200 `isError` results. Validation
648
+ // failures stay tool-result-shaped but stamp `_meta.errorCode`
649
+ // (`INVALID_INPUT`), mirroring the execution path's capability-error
650
+ // projection below.
651
+ server.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
652
+ const invocation = runtime.acquireInvocation();
653
+ try {
654
+ const attempted = await settle(() => invocation.runtime.runInvocation(async () => {
655
+ const tool = registeredTools.get(server)?.get(request.params.name);
656
+ if (!tool?.registration.enabled)
657
+ throw new McpError(ErrorCode.InvalidParams, `Unknown tool: ${request.params.name}`);
658
+ if (request.params.task)
659
+ throw new McpError(ErrorCode.InvalidParams, 'This tool does not support task execution');
660
+ const parsed = tool.registration.inputSchema ? await safeParseAsync(tool.registration.inputSchema, request.params.arguments) : { success: true, data: request.params.arguments };
661
+ if (!parsed.success) {
662
+ const issues = formatZodIssues(parsed.error);
663
+ const text = `Invalid input for '${request.params.name}': ${issues}`;
664
+ // Omit structuredContent on isError: MCP clients that kept
665
+ // outputSchema validate it even on errors, and {ok:false,error}
666
+ // does not match tool output schemas.
667
+ return {
668
+ isError: true,
669
+ content: [{ type: 'text', text }],
670
+ _meta: { errorCode: 'INVALID_INPUT' }
671
+ };
672
+ }
673
+ return await tool.invoke(request.params.arguments, extra, invocation);
674
+ }));
675
+ if (attempted.ok)
676
+ return attempted.value;
677
+ // McpError must escape so the SDK answers with a JSON-RPC error
678
+ // response carrying its code and the request id.
679
+ if (attempted.cause instanceof McpError)
680
+ throw attempted.cause;
681
+ const failure = projectMcpToolFailure(attempted.cause);
682
+ return {
683
+ isError: true,
684
+ content: [{ type: 'text', text: failure.message }],
685
+ _meta: { errorCode: failure.code }
686
+ };
687
+ }
688
+ finally {
689
+ invocation.release();
690
+ }
691
+ });
692
+ const unsubscribe = runtime.onGenerationChange(() => {
693
+ // Same isolation contract as the initial registration loop above: one
694
+ // bad descriptor must not leave the server with its tools removed but
695
+ // not re-registered, skip sendToolListChanged(), or escape into the
696
+ // event subscription.
697
+ const refreshed = settleNow(() => {
698
+ // Same registration bound as the fold this server was built from:
699
+ // the refresh must not widen a settled surface with descriptors a
700
+ // fresh connection would still exclude.
701
+ const next = computeMcpToolCatalog(runtime, options, logger, resolveLocalToolIds(runtime, options), catalog.loaderSettlement);
702
+ // Validate the replacement before retracting the current, unambiguous catalog.
703
+ createMcpWireNameMap(next.descriptors.map(descriptor => descriptor.id), options.mcpClientId, next.purposePresets);
704
+ for (const entry of registeredTools.get(server)?.values() ?? [])
705
+ entry.registration.remove();
706
+ registeredTools.set(server, new Map());
707
+ const refreshFailures = [];
708
+ for (const descriptor of next.descriptors) {
709
+ const registered = settleNow(() => registerTool(server, descriptor, runtime, { ...options, customPresets: next.purposePresets }, logger, next.localToolIds));
710
+ if (!registered.ok) {
711
+ const facts = valueFreeFailure(registered.cause);
712
+ refreshFailures.push(`${descriptor.id}: ${facts.name}`);
713
+ buildLog.error(`Failed to re-register tool on generation change: ${descriptor.id}`, { error: facts });
714
+ continue;
715
+ }
716
+ if (!registered.value)
717
+ refreshFailures.push(`${descriptor.id}: schema conversion failed`);
718
+ }
719
+ if (refreshFailures.length > 0) {
720
+ appendMcpInstructions(server, formatRegistrationFailureInstructions(refreshFailures));
721
+ buildLog.error(`MCP tool re-registration incomplete after generation change: ${refreshFailures.length} tool(s) not advertised`, { refreshFailures });
722
+ }
723
+ server.sendToolListChanged();
724
+ });
725
+ if (!refreshed.ok) {
726
+ const facts = valueFreeFailure(refreshed.cause);
727
+ appendMcpInstructions(server, '⚠ DEGRADED SURFACE: tool catalog refresh after a registry generation change failed. ' +
728
+ 'The previously registered tool list may be stale or empty. ' +
729
+ 'Report this to the user IMMEDIATELY; do NOT silently work around it.');
730
+ buildLog.error('MCP tool catalog refresh on generation change failed', { error: facts });
731
+ }
732
+ });
733
+ const onclose = server.server.onclose;
734
+ server.server.onclose = () => { unsubscribe(); onclose?.(); };
735
+ return server;
736
+ }
737
+ /**
738
+ * SDK keeps instructions on Server as private `_instructions` and reads that
739
+ * field on initialize. Construct-time options cannot list late registerTool
740
+ * failures — mutate the field after registration so rule 13 still holds.
741
+ */
742
+ function appendMcpInstructions(server, section) {
743
+ const inner = server.server;
744
+ // The SDK Server constructor always assigns its own `_instructions`
745
+ // property (possibly undefined). If that own property disappears, the SDK
746
+ // renamed the private field and every degraded-toolset banner written here
747
+ // would be silently dropped — fail loudly instead of rotting.
748
+ if (!('_instructions' in inner) || !Object.prototype.hasOwnProperty.call(inner, '_instructions')) {
749
+ throw new Error('MCP SDK Server no longer declares the private `_instructions` field; ' +
750
+ 'appendMcpInstructions cannot patch degraded-toolset instructions. ' +
751
+ 'Upstream an SDK API for late instructions and update this adapter.');
752
+ }
753
+ const previousInstructions = z.object({ _instructions: z.string().optional() }).safeParse(inner);
754
+ const existing = previousInstructions.success ? previousInstructions.data._instructions ?? '' : '';
755
+ if (!Reflect.set(inner, '_instructions', existing ? `${existing}\n\n${section}` : section)) {
756
+ throw new Error('MCP SDK Server instructions are no longer writable.');
757
+ }
758
+ }
759
+ /**
760
+ * Zod introspection is pure in its schema, so it is cached against the schema
761
+ * OBJECT rather than the descriptor id or the registry revision. A WeakMap
762
+ * cannot go stale: a changed descriptor brings a different schema instance, and
763
+ * an unchanged instance cannot derive differently.
764
+ */
765
+ const derivedInputSchemas = new WeakMap();
766
+ const normalizableOutputSchemas = new WeakMap();
767
+ function requireToolZodSchema(value, toolId) {
768
+ const parsed = z.custom((candidate) => candidate instanceof z.ZodType).safeParse(value);
769
+ if (!parsed.success)
770
+ throw new CapabilityError(`Tool '${toolId}' must supply a Zod schema`, 'INVALID_INPUT');
771
+ return parsed.data;
772
+ }
773
+ function deriveInputSchema(zodSchema) {
774
+ const cached = derivedInputSchemas.get(zodSchema);
775
+ if (cached)
776
+ return cached;
777
+ const isUnion = isDiscriminatedUnion(zodSchema);
778
+ const derived = {
779
+ isUnion,
780
+ discriminator: isUnion ? getDiscriminator(zodSchema) : null,
781
+ unionOptions: isUnion ? getDiscriminatorOptions(zodSchema) : [],
782
+ // The SDK's normalizeObjectSchema only handles z.object() — discriminated
783
+ // unions produce { type: "object", properties: {} } in tools/list.
784
+ // Flatten union variants into a merged z.object() so the SDK serializes all params.
785
+ inputSchema: flattenDiscriminatedUnionToObject(zodSchema)
786
+ };
787
+ derivedInputSchemas.set(zodSchema, derived);
788
+ return derived;
789
+ }
790
+ function normalizableOutputSchema(rawOutputSchema) {
791
+ const cached = normalizableOutputSchemas.get(rawOutputSchema);
792
+ if (cached)
793
+ return cached.schema;
794
+ const schema = !isPlainUnion(rawOutputSchema) && !isDiscriminatedUnion(rawOutputSchema)
795
+ ? rawOutputSchema
796
+ : undefined;
797
+ normalizableOutputSchemas.set(rawOutputSchema, { schema });
798
+ return schema;
799
+ }
800
+ // One fallback identity per server, shared by its tools and preserved across registration refresh.
801
+ const serverConnectionKeys = new WeakMap();
802
+ function registerTool(server, descriptor, runtime, options, logger, localToolIds = []) {
803
+ let serverConnectionKey = serverConnectionKeys.get(server);
804
+ if (!serverConnectionKey) {
805
+ serverConnectionKey = `mcp-server:${crypto.randomUUID()}`;
806
+ serverConnectionKeys.set(server, serverConnectionKey);
807
+ }
808
+ if (!descriptor.schemas?.input) {
809
+ logger.child('schema').error(`No input schema for ${descriptor.id} — skipping tool`);
810
+ return false;
811
+ }
812
+ const zodSchema = requireToolZodSchema(descriptor.schemas.input, descriptor.id);
813
+ // Pre-computed once per schema OBJECT, not once per connection. Every HTTP
814
+ // session builds its own McpServer and re-registers all ~89 tools, and the
815
+ // zod introspection below (union walk + variant merge) was the bulk of that
816
+ // work. Keying a WeakMap on the schema instance needs no invalidation: a
817
+ // re-registered descriptor arrives with a new schema object, and for the
818
+ // same object these are pure functions.
819
+ const derived = deriveInputSchema(zodSchema);
820
+ const inputSchema = derived.inputSchema;
821
+ // Output schema - pass only if it can be normalized by the SDK.
822
+ // The SDK's normalizeObjectSchema() only handles z.object() — unions cause
823
+ // safeParseAsync(undefined, ...) which throws "undefined is not an object (evaluating 's._zod')".
824
+ // Skip output schemas that are plain unions or discriminated unions to avoid this SDK bug.
825
+ const rawOutputSchema = descriptor.schemas.output === undefined ? undefined : requireToolZodSchema(descriptor.schemas.output, descriptor.id);
826
+ const outputSchema = rawOutputSchema ? normalizableOutputSchema(rawOutputSchema) : undefined;
827
+ // Derive MCP annotations from safety field
828
+ const annotations = deriveMcpAnnotations(descriptor.safety);
829
+ // Trust-tag tier is derived from `safety` until `descriptor.capability.tier`
830
+ // lands in the tier-spec PR (AI-SURFACE-2026-05.md §4.3 step 1). Captured
831
+ // once at registration so it composes with cache-stable system prompts.
832
+ const trustTier = deriveTrustTier(descriptor);
833
+ const toolAccessor = runtime.assets('tools/tool');
834
+ const isDiscriminated = toolAccessor.isDiscriminated(descriptor.id);
835
+ let variantSafety;
836
+ if (isDiscriminated) {
837
+ const discriminatedDescriptor = toolAccessor.getDiscriminatedDescriptor(descriptor.id);
838
+ if (discriminatedDescriptor) {
839
+ const entries = discriminatedDescriptor.variantNames
840
+ .map((variantName) => [variantName, discriminatedDescriptor.getVariantSafety(variantName)])
841
+ .filter((entry) => entry[1] !== undefined);
842
+ if (entries.length > 0) {
843
+ variantSafety = Object.fromEntries(entries);
844
+ }
845
+ }
846
+ }
847
+ const isLocal = isLocalToolId(descriptor.id, localToolIds);
848
+ const origin = vibesToolOrigin(isLocal);
849
+ const description = formatLocalMcpToolDescription(getDescriptorMcpDescription(descriptor), isLocal);
850
+ const dispatchRuntime = runtime;
851
+ const vibesRegistrationMeta = {
852
+ origin,
853
+ category: descriptor.category,
854
+ subcategory: descriptor.subcategory,
855
+ tags: descriptor.tags,
856
+ requiresApproval: descriptor.requiresApproval,
857
+ safety: descriptor.safety,
858
+ mcpClientId: options.mcpClientId
859
+ };
860
+ if (variantSafety)
861
+ vibesRegistrationMeta.variants = variantSafety;
862
+ const registrationOptions = {
863
+ title: descriptor.name ?? descriptor.id,
864
+ description,
865
+ inputSchema: inputSchema,
866
+ outputSchema: outputSchema,
867
+ annotations,
868
+ _meta: { vibes: vibesRegistrationMeta }
869
+ };
870
+ const handler = async (args, extra, boundInvocation) => {
871
+ const callId = `mcp_${Date.now()}_${crypto.randomUUID()}`;
872
+ // Per-call nonce for trust-tag wrapper (F4). Shared across all text items
873
+ // and error paths in this tool call so the model can verify boundary integrity.
874
+ const callNonce = crypto.randomUUID();
875
+ // A body whose executable was replaced on disk says so on EVERY result and
876
+ // error until it is respawned (stale-body.consumer.ts, handed in by the
877
+ // consumer serve impl) — the one channel an agent reads on every call.
878
+ // Computed before `try` so the error path shares it.
879
+ const stalePrefix = options.staleBodyBanner?.() ?? null;
880
+ let toolCallCtx;
881
+ const callStarted = Date.now();
882
+ const traceStage = (stage) => logger.info('MCP invocation stage', { callId, tool: descriptor.id, stage, elapsedMs: Date.now() - callStarted });
883
+ traceStage('start');
884
+ const invocation = boundInvocation?.retain() ?? dispatchRuntime.acquireInvocation();
885
+ const runtime = invocation.runtime;
886
+ let callDescriptor = descriptor;
887
+ try {
888
+ const attempted = await settle(async () => {
889
+ // SAFETY: This accessor belongs to the registered tools/tool kind, whose descriptor contract is ToolAssetDescriptor; AssetAccessor erases the descriptor type, not its owner.
890
+ const currentDescriptor = runtime.assets('tools/tool').descriptor(descriptor.id);
891
+ if (!currentDescriptor?.schemas?.input)
892
+ throw new Error(`Tool '${descriptor.id}' is unavailable in this generation`);
893
+ callDescriptor = currentDescriptor;
894
+ const zodSchema = requireToolZodSchema(callDescriptor.schemas.input, callDescriptor.id);
895
+ const { isUnion, discriminator, unionOptions } = deriveInputSchema(zodSchema);
896
+ const defaultAction = callDescriptor.schemas.defaultAction;
897
+ await options.beforeToolCall?.();
898
+ // Tools parses these raw JSON arguments once with the owner schema.
899
+ // This handler does not parse them. A missing union discriminator
900
+ // still defaults only on an admitted object, for the session stamp.
901
+ const wire = JsonObjectSchema.safeParse(args);
902
+ if (isUnion && discriminator && !wire.success) {
903
+ throw new CapabilityError('the tool arguments are invalid', 'INVALID_INPUT', {
904
+ reason: 'mcp-tool-args-invalid'
905
+ });
906
+ }
907
+ let resolvedArgs = wire.success ? wire.data : {};
908
+ if (isUnion && discriminator && wire.success && !(discriminator in resolvedArgs)) {
909
+ if (defaultAction && unionOptions.includes(defaultAction)) {
910
+ resolvedArgs = { [discriminator]: defaultAction, ...resolvedArgs };
911
+ }
912
+ }
913
+ // The SDK callback does not currently populate `extra.sessionId` for
914
+ // WebStandard Streamable HTTP. The HTTP adapter therefore gives each
915
+ // connection a private identity cell when it builds the server. This is
916
+ // call data, never mutable process-global runtime scope.
917
+ const transportSessionId = extra.sessionId ?? options.resolveTransportSessionId?.();
918
+ // A session-family call may name the participant it continues as
919
+ // (the documented bind flow). That is a binding hint the session layer
920
+ // verifies, not identity: agent identity comes only from the connection.
921
+ const callMeta = '_meta' in extra ? asJsonObject(extra._meta) : undefined;
922
+ const metaParticipantId = (isStringValue(callMeta?.participantId) && callMeta.participantId) ||
923
+ (isStringValue(callMeta?.['vibes/participantId']) &&
924
+ callMeta['vibes/participantId']) ||
925
+ undefined;
926
+ const connectionKey = transportSessionId ?? serverConnectionKey;
927
+ // Build context with progress/cancellation support
928
+ const baseToolCallCtx = {
929
+ callId,
930
+ logger: logger.child(callDescriptor.id)
931
+ };
932
+ if (extra.signal)
933
+ baseToolCallCtx.signal = extra.signal;
934
+ if (extra.sendProgress)
935
+ baseToolCallCtx.sendProgress = (progress) => {
936
+ const update = { progress: progress.progress, total: progress.total };
937
+ if (progress.message)
938
+ update.message = progress.message;
939
+ extra.sendProgress?.(update);
940
+ };
941
+ // Stamp trusted identity from the runtime's `auth/identity` (the same
942
+ // builder the tools-cli surface uses). The MCP stdio surface runs as an
943
+ // authenticated local account; without this, owner-scoped tools
944
+ // (applet/knowledge/work) fell back to SYSTEM_OWNER and orphaned the
945
+ // user's artifacts. buildDirectToolCallContext strips any caller-supplied
946
+ // identity keys (anti-laundering) before stamping userId/actorUserId(+org).
947
+ traceStage('direct-auth');
948
+ const directContext = await buildDirectToolCallContext(runtime, baseToolCallCtx);
949
+ const caller = metaParticipantId && !directContext.caller?.participantId
950
+ ? { ...directContext.caller, participantId: metaParticipantId }
951
+ : { ...directContext.caller };
952
+ // Admission (RC08 U7): identity only from what this connection's
953
+ // transport verified, before the hook bus or any observer runs.
954
+ const admittedCaller = admitConnectionCaller({
955
+ verified: options.resolveVerifiedConnectionIdentity?.() ?? options.verifiedConnectionIdentity,
956
+ declared: options.resolveConnectionIdentity?.(),
957
+ call: caller,
958
+ principal: directContext.metadata
959
+ });
960
+ const mcpSettings = await loadMcpConfig(runtime);
961
+ const resolvedCeiling = resolveMcpClientCapabilityCeiling(mcpSettings, {
962
+ admittedCaller,
963
+ mcpClientId: options.mcpClientId,
964
+ preset: options.preset
965
+ }, runtime);
966
+ const agentContext = {
967
+ agentId: admittedCaller?.agentId ?? resolvedCeiling.profile ?? 'mcp-client',
968
+ ceiling: resolvedCeiling.ceiling,
969
+ callChain: []
970
+ };
971
+ const metadata = {
972
+ ...directContext.metadata,
973
+ 'mcp.transportMode': options.mode,
974
+ [TOOL_AGENT_CONTEXT_METADATA_KEY]: agentContext,
975
+ agentCapabilityCeiling: resolvedCeiling.ceiling
976
+ };
977
+ if (transportSessionId)
978
+ metadata['mcp.transportSessionId'] = transportSessionId;
979
+ if (connectionKey)
980
+ metadata['mcp.connectionKey'] = connectionKey;
981
+ const directToolCallCtx = {
982
+ ...directContext,
983
+ caller: admittedCaller,
984
+ metadata
985
+ };
986
+ traceStage('prepare-context');
987
+ const preparation = {
988
+ context: directToolCallCtx, toolId: callDescriptor.id, input: resolvedArgs, descriptor: callDescriptor
989
+ };
990
+ if (transportSessionId)
991
+ preparation.transportSessionId = transportSessionId;
992
+ const preparedToolCallCtx = options.prepareToolCallContext
993
+ ? await options.prepareToolCallContext(preparation)
994
+ : directToolCallCtx;
995
+ traceStage('stamp-session');
996
+ const sessionStampedCtx = await stampMcpSessionCaller(runtime, server, preparedToolCallCtx, transportSessionId ?? connectionKey, options.mode, callDescriptor.id, resolvedArgs, logger);
997
+ const stampedToolCallCtx = {
998
+ ...sessionStampedCtx,
999
+ metadata: {
1000
+ ...sessionStampedCtx.metadata,
1001
+ [TOOL_AGENT_CONTEXT_METADATA_KEY]: agentContext,
1002
+ agentCapabilityCeiling: resolvedCeiling.ceiling
1003
+ }
1004
+ };
1005
+ toolCallCtx = stampedToolCallCtx;
1006
+ // Route through invokeTool so tools/tool hook bus events
1007
+ // (contextBuild / beforeExecute / afterExecute / error) fire
1008
+ // around execution. invokeTool handles discriminated dispatch
1009
+ // internally and propagates hook-enriched error metadata.
1010
+ traceStage('invoke');
1011
+ const execution = {
1012
+ runtime, toolId: callDescriptor.id, input: args, ctx: stampedToolCallCtx
1013
+ };
1014
+ if (options.toolExecutionTimeoutMs !== undefined && options.toolExecutionTimeoutMs > 0) {
1015
+ execution.timeoutMs = options.toolExecutionTimeoutMs;
1016
+ }
1017
+ const detachAgentContextHook = runtime
1018
+ .hooks('tools/tool')
1019
+ .on('contextBuild', (event) => {
1020
+ if (event.callId === stampedToolCallCtx.callId) {
1021
+ event.metadata.set(TOOL_AGENT_CONTEXT_METADATA_KEY, agentContext);
1022
+ }
1023
+ });
1024
+ const rawOutput = await (async () => {
1025
+ try {
1026
+ return await runWithMcpSamplingCallback(options.scopedValues, (request) => server.server.request({ method: 'sampling/createMessage', params: request }, CreateMessageResultSchema, { relatedRequestId: extra.requestId }), () => invokeTool(execution));
1027
+ }
1028
+ finally {
1029
+ detachAgentContextHook();
1030
+ }
1031
+ })();
1032
+ traceStage('result');
1033
+ const outputSchema = callDescriptor.schemas.output;
1034
+ const lifted = liftAmbientEnvelope(rawOutput, isZodLike(outputSchema) ? outputSchema : undefined);
1035
+ const output = lifted.output;
1036
+ const ambientPrefix = formatAmbientPrefix(lifted);
1037
+ const envelopeMeta = ambientMeta(lifted);
1038
+ const unboundNotice = isStringValue(toolCallCtx.metadata?.['mcp.unboundSessionNotice'])
1039
+ ? toolCallCtx.metadata['mcp.unboundSessionNotice']
1040
+ : undefined;
1041
+ if (isZodLike(callDescriptor.schemas.output)) {
1042
+ const res = callDescriptor.schemas.output.safeParse(output);
1043
+ if (!res.success) {
1044
+ const issues = (res.error?.issues ?? [])
1045
+ .slice(0, 4)
1046
+ .map((issue) => `${issue.path.join('.') || '<root>'}: ${issue.message}`)
1047
+ .join('; ');
1048
+ throw new Error(`Invalid output from '${callDescriptor.id}': ${issues}`);
1049
+ }
1050
+ }
1051
+ // Build content array
1052
+ const content = [];
1053
+ // Trust-tag wrapper (F4 / VIBA-34). Every text payload that reaches the
1054
+ // model gets a nonce-randomized <tool_output> envelope so injected
1055
+ // instructions inside tool output can't impersonate system content.
1056
+ // One nonce per call: shared across all text items and error paths.
1057
+ const resultPrefix = [stalePrefix, unboundNotice, ambientPrefix]
1058
+ .filter(Boolean)
1059
+ .join('\n');
1060
+ const wrapText = (text) => wrapToolOutputText({
1061
+ toolId: callDescriptor.id,
1062
+ tier: trustTier,
1063
+ text: resultPrefix ? `${resultPrefix}\n${text}` : text,
1064
+ nonce: callNonce
1065
+ }).text;
1066
+ // Passthrough for tools that return MCP content directly
1067
+ const mcpResponse = readMcpToolResponse(output);
1068
+ if (mcpResponse) {
1069
+ const wrappedContent = mcpResponse.content.map((item) => item.type === 'text' ? { ...item, text: wrapText(item.text) } : item);
1070
+ const result = {
1071
+ ...mcpResponse,
1072
+ content: wrappedContent
1073
+ };
1074
+ if (envelopeMeta)
1075
+ result._meta = { ...mcpResponse._meta, ...envelopeMeta };
1076
+ return result;
1077
+ }
1078
+ // Handle string output
1079
+ if (isStringValue(output)) {
1080
+ const result = {
1081
+ content: [{ type: 'text', text: wrapText(output) }]
1082
+ };
1083
+ if (envelopeMeta)
1084
+ result._meta = envelopeMeta;
1085
+ return result;
1086
+ }
1087
+ // JSON wire form: undefined fields omitted, arrays kept. Never String() an object or array.
1088
+ const serialized = settleNow(() => JSON.stringify(output));
1089
+ if (!serialized.ok) {
1090
+ throw new CapabilityError('the tool output is not JSON', 'INVALID_INPUT', {
1091
+ reason: 'mcp-tool-output-not-json',
1092
+ cause: serialized.cause
1093
+ });
1094
+ }
1095
+ const jsonText = JsonTextSchema.safeParse(serialized.value);
1096
+ if (!jsonText.success) {
1097
+ throw new CapabilityError('the tool output is not JSON', 'INVALID_INPUT', {
1098
+ reason: 'mcp-tool-output-not-json'
1099
+ });
1100
+ }
1101
+ const wired = wireJsonText(jsonText.data);
1102
+ content.push({
1103
+ type: 'text',
1104
+ text: wrapText(wired.text)
1105
+ });
1106
+ // Add resource links if present (must include required 'name' field per MCP ResourceSchema)
1107
+ const resourceLinkValue = wired.structured?.resourceLinks;
1108
+ const resourceLinks = Array.isArray(resourceLinkValue)
1109
+ ? z.array(ResourceLinkSchema.pick({ uri: true, mimeType: true })).parse(resourceLinkValue)
1110
+ : [];
1111
+ if (resourceLinks.length > 0) {
1112
+ for (const link of resourceLinks) {
1113
+ if (link?.uri) {
1114
+ const resourceLink = {
1115
+ type: 'resource_link',
1116
+ name: link.uri.split('/').pop() || link.uri,
1117
+ uri: link.uri
1118
+ };
1119
+ if (link.mimeType)
1120
+ resourceLink.mimeType = link.mimeType;
1121
+ content.push(resourceLink);
1122
+ }
1123
+ }
1124
+ }
1125
+ const result = { content };
1126
+ // Plain object outputs retain typed data without requiring clients to parse text.
1127
+ if (wired.structured)
1128
+ result.structuredContent = wired.structured;
1129
+ if (envelopeMeta)
1130
+ result._meta = envelopeMeta;
1131
+ return result;
1132
+ });
1133
+ if (attempted.ok)
1134
+ return attempted.value;
1135
+ const error = attempted.cause;
1136
+ const caught = error;
1137
+ const message = modelSafeFailureText(caught);
1138
+ logger.child('tool').error(`Execution failed: ${callDescriptor.id}`, {
1139
+ failure: valueFreeFailure(caught),
1140
+ excerpt: caught instanceof Error ? redactedExcerpt(caught.message) : undefined
1141
+ });
1142
+ // Format error with structured metadata for MCP
1143
+ const parsedHookFailure = ToolHookFailureSchema.safeParse(error);
1144
+ const toolError = parsedHookFailure.success ? parsedHookFailure.data : undefined;
1145
+ const suggestedToolCall = getSuggestedToolCallFromErrorMetadata(toolError?.metadata);
1146
+ // invokeTool attaches `recoveryHint` / `retryable` onto the
1147
+ // thrown error after hook-bus `error` subscribers run. Surface
1148
+ // them even when the error isn't a structured ToolError.
1149
+ const hookRecoveryHint = toolError?.recoveryHint;
1150
+ const hookRetryable = toolError?.retryable;
1151
+ // Wrap error text in the same trust-tag envelope: error messages flow
1152
+ // back into model context exactly like success output and so share the
1153
+ // same prompt-injection surface. Uses the same per-call nonce for
1154
+ // boundary integrity across success and error paths.
1155
+ const unboundNotice = isStringValue(toolCallCtx?.metadata?.['mcp.unboundSessionNotice'])
1156
+ ? toolCallCtx.metadata['mcp.unboundSessionNotice']
1157
+ : undefined;
1158
+ const errorPrefix = [stalePrefix, unboundNotice].filter(Boolean).join('\n');
1159
+ const errorContent = {
1160
+ type: 'text',
1161
+ text: wrapToolOutputText({
1162
+ toolId: callDescriptor.id,
1163
+ tier: trustTier,
1164
+ text: errorPrefix ? `${errorPrefix}\n${message}` : message,
1165
+ nonce: callNonce
1166
+ }).text
1167
+ };
1168
+ // CapabilityError is the runtime-owned cross-surface outcome contract
1169
+ // (@vibesdotdev/kernel, outcome/capability-error.ts) — the harvested
1170
+ // generalization of ToolError with the TOOL_ prefix dropped from the
1171
+ // code vocabulary. The explicit naming correspondence between the two
1172
+ // small enums (do NOT re-derive by string surgery):
1173
+ // NOT_FOUND ↔ TOOL_NOT_FOUND, PERMISSION_DENIED ↔ TOOL_PERMISSION_DENIED,
1174
+ // RATE_LIMITED ↔ TOOL_RATE_LIMITED, TIMEOUT ↔ TOOL_TIMEOUT,
1175
+ // CANCELLED ↔ TOOL_CANCELLED, INTERNAL ↔ TOOL_INTERNAL_ERROR,
1176
+ // INVALID_INPUT ↔ TOOL_VALIDATION_FAILED;
1177
+ // AUTH_REQUIRED / CONFLICT / UNAVAILABLE have no ToolError twin.
1178
+ // Per the contract ("MCP → _meta.errorCode + retryable + recoveryHint")
1179
+ // the stable capability code goes on the wire UNTRANSLATED — squashing
1180
+ // the twin-less codes into a generic TOOL_* code would lose exactly the
1181
+ // signal the contract exists to carry. Same _meta shape as ToolError.
1182
+ // This branch runs FIRST: CapabilityError also has a truthy `.code`, so
1183
+ // the ToolError duck-typed branch below would otherwise swallow it and
1184
+ // drop the contract's `retryable`/`details` projection.
1185
+ let structuredMeta;
1186
+ if (error instanceof Error && isCapabilityError(error)) {
1187
+ structuredMeta = {
1188
+ errorCode: error.code,
1189
+ recoveryHint: error.recoveryHint ?? hookRecoveryHint,
1190
+ retryable: error.retryable
1191
+ };
1192
+ if (error.details !== undefined)
1193
+ structuredMeta.errorMetadata = error.details;
1194
+ }
1195
+ else if (toolError?.code) {
1196
+ structuredMeta = {
1197
+ errorCode: toolError.code,
1198
+ recoveryHint: toolError.recoveryHint ?? hookRecoveryHint,
1199
+ alternatives: toolError.alternatives,
1200
+ errorMetadata: toolError.metadata
1201
+ };
1202
+ if (hookRetryable !== undefined)
1203
+ structuredMeta.retryable = hookRetryable;
1204
+ }
1205
+ else if (hookRecoveryHint || hookRetryable !== undefined || suggestedToolCall) {
1206
+ structuredMeta = {};
1207
+ if (hookRecoveryHint)
1208
+ structuredMeta.recoveryHint = hookRecoveryHint;
1209
+ if (hookRetryable !== undefined)
1210
+ structuredMeta.retryable = hookRetryable;
1211
+ }
1212
+ if (structuredMeta && suggestedToolCall)
1213
+ structuredMeta.suggestedToolCall = suggestedToolCall;
1214
+ const failure = projectMcpToolFailure(error);
1215
+ const existingCode = structuredMeta && 'errorCode' in structuredMeta
1216
+ ? structuredMeta.errorCode
1217
+ : undefined;
1218
+ const errorResponse = {
1219
+ content: [errorContent],
1220
+ isError: true,
1221
+ _meta: { ...structuredMeta, errorCode: existingCode ?? failure.code }
1222
+ };
1223
+ return errorResponse;
1224
+ }
1225
+ finally {
1226
+ invocation.release();
1227
+ }
1228
+ };
1229
+ const registration = server.registerTool(mcpWireToolName(descriptor.id, options.mcpClientId, options.customPresets), registrationOptions, handler);
1230
+ const entries = registeredTools.get(server) ?? new Map();
1231
+ entries.set(mcpWireToolName(descriptor.id, options.mcpClientId, options.customPresets), { registration, invoke: handler });
1232
+ registeredTools.set(server, entries);
1233
+ return true;
1234
+ }
1235
+ /**
1236
+ * Stamp MCP client + session-participant identity onto the tool ctx so
1237
+ * session-collaborate send/mark-read can resolve the caller without
1238
+ * fromParticipant / participantId.
1239
+ */
1240
+ /** One unbound-session notice per MCP transport connection, per root (views and generations share it). */
1241
+ function takeUnboundSessionNoticeSlot(runtime, connectionId) {
1242
+ const key = connectionId ?? 'stdio';
1243
+ const issued = requireMcpClient(runtime).unboundSessionNotices;
1244
+ if (issued.has(key))
1245
+ return false;
1246
+ issued.add(key);
1247
+ if (issued.size > 256) {
1248
+ const first = issued.values().next().value;
1249
+ if (first)
1250
+ issued.delete(first);
1251
+ }
1252
+ return true;
1253
+ }
1254
+ async function resolveWorkspacePath(runtime) {
1255
+ const attempted = await settle(() => runtime.context('runtime/workspace-path'));
1256
+ if (!attempted.ok) {
1257
+ // An unbound workspace is a fact, not a failure; anything else is logged with its reason.
1258
+ const error = attempted.cause;
1259
+ if (!(error instanceof Error && isCapabilityError(error) && error.reason === 'workspace-unbound')) {
1260
+ getLogger('mcp', runtime).debug('workspace path unavailable for the tool call', { failure: valueFreeFailure(error) });
1261
+ }
1262
+ return undefined;
1263
+ }
1264
+ return isStringValue(attempted.value) && attempted.value.length > 0 ? attempted.value : undefined;
1265
+ }
1266
+ async function stampMcpSessionCaller(runtime, server, ctx, transportSessionId, mode, toolId, input, logger) {
1267
+ const mcpSessionId = transportSessionId ?? null;
1268
+ let transportParticipantId;
1269
+ let sessionUtils;
1270
+ const stamped = await settle(async () => {
1271
+ sessionUtils = await import('@vibesdotdev/session/mcp/utils/participant');
1272
+ const mcpSessionRegistry = await resolveMcpTransportRegistry(runtime);
1273
+ const clientVersion = server.server.getClientVersion?.();
1274
+ const existing = mcpSessionRegistry.getClientInfo(mcpSessionId);
1275
+ // The connection declares its harness session; a shared host never reads
1276
+ // its own environment for it (that is whichever harness started the host).
1277
+ const harnessSessionId = ctx.caller?.harnessSessionId ?? existing?.harnessSessionId;
1278
+ const agentId = ctx.caller?.agentId ?? existing?.agentId;
1279
+ if (clientVersion?.name || existing || harnessSessionId || agentId) {
1280
+ const clientInfo = {
1281
+ ...existing,
1282
+ name: clientVersion?.name ?? existing?.name ?? 'mcp-client',
1283
+ version: clientVersion?.version ?? existing?.version,
1284
+ transport: mode === 'http' ? 'http' : 'stdio',
1285
+ connectionId: mcpSessionId ?? existing?.connectionId
1286
+ };
1287
+ if (agentId)
1288
+ clientInfo.agentId = agentId;
1289
+ if (harnessSessionId)
1290
+ clientInfo.harnessSessionId = harnessSessionId;
1291
+ mcpSessionRegistry.setClientInfo(mcpSessionId, clientInfo);
1292
+ }
1293
+ if (mcpSessionId) {
1294
+ const previous = mcpSessionRegistry.getConnectionState(mcpSessionId);
1295
+ transportParticipantId =
1296
+ (previous && 'participantId' in previous && isStringValue(previous.participantId) ? previous.participantId : undefined) ??
1297
+ previous?.agentId ??
1298
+ undefined;
1299
+ mcpSessionRegistry.setConnectionState(mcpSessionId, {
1300
+ ...previous,
1301
+ transport: mode === 'http' ? 'http' : 'stdio',
1302
+ connectionId: mcpSessionId,
1303
+ sessionId: previous?.sessionId,
1304
+ agentId: previous?.agentId ?? null,
1305
+ agentSlug: previous?.agentSlug ?? null
1306
+ });
1307
+ }
1308
+ });
1309
+ if (!stamped.ok) {
1310
+ // Session registry is optional for non-session MCP surfaces, but a real
1311
+ // failure still degrades downstream participant resolution — leave a
1312
+ // diagnostic instead of vanishing.
1313
+ logger.warn('MCP session caller stamping failed; participant resolution may degrade', {
1314
+ failure: valueFreeFailure(stamped.cause),
1315
+ toolId
1316
+ });
1317
+ }
1318
+ const isSessionFamilyTool = toolId === 'session' || toolId.startsWith('session-');
1319
+ const { participantId: _hintParticipant, sessionId: _hintSession, ...unboundCaller } = ctx.caller ?? {};
1320
+ if (!runtime.hasContext('session/manager')) {
1321
+ return { ...ctx, caller: unboundCaller };
1322
+ }
1323
+ const receiptRestore = toolId === 'session' ? receiptRestoreInputSchema.safeParse(input) : undefined;
1324
+ const receiptRestoreParticipantId = receiptRestore?.success
1325
+ ? receiptRestore.data.participantId
1326
+ : undefined;
1327
+ let authoritativeParticipantId = ctx.caller?.participantId ?? transportParticipantId ?? receiptRestoreParticipantId;
1328
+ // The session family is the only consumer of caller.sessionId stamping; the
1329
+ // no-durable-session branch below exempted nothing, which gated stateless
1330
+ // tools behind session-authority repair.
1331
+ const reconciled = await settle(async () => {
1332
+ const manager = await runtime.context('session/manager');
1333
+ if (!isSessionFamilyTool) {
1334
+ // Ordinary tools cannot self-identify as another seat through request metadata.
1335
+ authoritativeParticipantId = await manager.resolveMcpParticipant({}, mcpSessionId);
1336
+ }
1337
+ else {
1338
+ authoritativeParticipantId ??= await manager.resolveMcpParticipant({}, mcpSessionId, ctx.caller);
1339
+ }
1340
+ if (!authoritativeParticipantId) {
1341
+ throw new Error('Session manager did not resolve an MCP participant');
1342
+ }
1343
+ const participantSession = await manager.ensureParticipantSession(authoritativeParticipantId);
1344
+ if (!participantSession) {
1345
+ // A brand-new MCP body has no session by definition. Permit discovery
1346
+ // (list/search/status/get) and init so the caller can bind or create,
1347
+ // and strip any stale prepared session so neither can inherit another
1348
+ // body's custody.
1349
+ const workspacePath = await resolveWorkspacePath(runtime);
1350
+ if (!isSessionFamilyTool) {
1351
+ // Tools outside the session family never consume
1352
+ // caller.sessionId; failing them here gated stateless tools
1353
+ // (calculate & co.) behind session-authority repair. Stamp the
1354
+ // participant identity only, and tell the agent once per
1355
+ // connection that it is unbound.
1356
+ const { sessionId: _staleSessionId, ...caller } = ctx.caller ?? {};
1357
+ let notice;
1358
+ if (takeUnboundSessionNoticeSlot(runtime, mcpSessionId) && sessionUtils) {
1359
+ const guidance = await sessionUtils.buildUnboundSessionGuidance(manager, {
1360
+ workspacePath
1361
+ });
1362
+ notice = sessionUtils.renderUnboundSessionGuidance(guidance);
1363
+ }
1364
+ const metadata = { ...ctx.metadata };
1365
+ if (notice)
1366
+ metadata['mcp.unboundSessionNotice'] = notice;
1367
+ return {
1368
+ ...ctx,
1369
+ caller: { ...caller, participantId: authoritativeParticipantId },
1370
+ metadata
1371
+ };
1372
+ }
1373
+ const getNeedsId = toolId === 'session' &&
1374
+ input.action === 'get' &&
1375
+ !explicitSessionTargetSchema.safeParse(input).success;
1376
+ // Resume repairs an inactive binding. It must reach its owner with the
1377
+ // participant identity, but without borrowing the closed session's custody.
1378
+ const explicitResume = toolId === 'session' && explicitResumeInputSchema.safeParse(input).success;
1379
+ if (!getNeedsId &&
1380
+ (explicitResume || sessionUtils?.isSessionDiscoveryCall(toolId, input.action) ||
1381
+ (!sessionUtils &&
1382
+ toolId === 'session' &&
1383
+ (input.action === 'init' || input.action === 'status')))) {
1384
+ const { sessionId: _staleSessionId, ...caller } = ctx.caller ?? {};
1385
+ return {
1386
+ ...ctx,
1387
+ caller: { ...caller, participantId: authoritativeParticipantId }
1388
+ };
1389
+ }
1390
+ if (sessionUtils) {
1391
+ const fields = await sessionUtils.unboundSessionErrorFields(manager, { workspacePath });
1392
+ throw sessionUtils.createSessionToolError('SESSION_NOT_ACTIVE', fields.message, fields.hint, fields.details);
1393
+ }
1394
+ throw new Error(`Participant ${authoritativeParticipantId} has no durable active session (call session { action: "init" } to bind one, or resume the archived session explicitly)`);
1395
+ }
1396
+ if (mcpSessionId) {
1397
+ sessionUtils?.bindRuntimeConnectionReceipt(runtime, mcpSessionId, authoritativeParticipantId, participantSession.id);
1398
+ }
1399
+ return {
1400
+ ...ctx,
1401
+ caller: {
1402
+ ...ctx.caller,
1403
+ participantId: authoritativeParticipantId,
1404
+ sessionId: participantSession.id
1405
+ }
1406
+ };
1407
+ });
1408
+ if (reconciled.ok)
1409
+ return reconciled.value;
1410
+ const error = reconciled.cause;
1411
+ if (!isSessionFamilyTool) {
1412
+ // Session-authority failures (storage unavailable, unreadable routing
1413
+ // rows) must not take down tools that never touch session state. Run
1414
+ // unqualified rather than wedging stateless tools behind identity
1415
+ // repair.
1416
+ logger.warn('MCP participant reconciliation failed; running non-session tool without session identity', { toolId, failure: valueFreeFailure(error) });
1417
+ return { ...ctx, caller: unboundCaller };
1418
+ }
1419
+ if (sessionUtils?.isSessionToolError(error, 'SESSION_NOT_ACTIVE'))
1420
+ throw error;
1421
+ throw new Error(`Cannot reconcile MCP participant ${authoritativeParticipantId ?? 'from the session authority'} to a session`, { cause: error });
1422
+ }
1423
+ //# sourceMappingURL=server.js.map