@kindgi/api 0.0.0-bootstrap.0 → 0.1.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 (505) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +216 -1
  3. package/dist/adapter-binding.d.ts +177 -0
  4. package/dist/adapter-binding.d.ts.map +1 -0
  5. package/dist/adapter-binding.js +12 -0
  6. package/dist/adapter-binding.js.map +1 -0
  7. package/dist/agent-binding.d.ts +207 -0
  8. package/dist/agent-binding.d.ts.map +1 -0
  9. package/dist/agent-binding.js +4 -0
  10. package/dist/agent-binding.js.map +1 -0
  11. package/dist/app.d.ts +770 -0
  12. package/dist/app.d.ts.map +1 -0
  13. package/dist/app.js +396 -0
  14. package/dist/app.js.map +1 -0
  15. package/dist/capability-binding.d.ts +76 -0
  16. package/dist/capability-binding.d.ts.map +1 -0
  17. package/dist/capability-binding.js +4 -0
  18. package/dist/capability-binding.js.map +1 -0
  19. package/dist/cost-binding.d.ts +175 -0
  20. package/dist/cost-binding.d.ts.map +1 -0
  21. package/dist/cost-binding.js +13 -0
  22. package/dist/cost-binding.js.map +1 -0
  23. package/dist/deployment-binding.d.ts +201 -0
  24. package/dist/deployment-binding.d.ts.map +1 -0
  25. package/dist/deployment-binding.js +4 -0
  26. package/dist/deployment-binding.js.map +1 -0
  27. package/dist/env-binding.d.ts +132 -0
  28. package/dist/env-binding.d.ts.map +1 -0
  29. package/dist/env-binding.js +4 -0
  30. package/dist/env-binding.js.map +1 -0
  31. package/dist/errors.d.ts +37 -0
  32. package/dist/errors.d.ts.map +1 -0
  33. package/dist/errors.js +264 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/eval-run-binding.d.ts +196 -0
  36. package/dist/eval-run-binding.d.ts.map +1 -0
  37. package/dist/eval-run-binding.js +16 -0
  38. package/dist/eval-run-binding.js.map +1 -0
  39. package/dist/eval-run-dispatcher.d.ts +131 -0
  40. package/dist/eval-run-dispatcher.d.ts.map +1 -0
  41. package/dist/eval-run-dispatcher.js +368 -0
  42. package/dist/eval-run-dispatcher.js.map +1 -0
  43. package/dist/eval-suite-binding.d.ts +227 -0
  44. package/dist/eval-suite-binding.d.ts.map +1 -0
  45. package/dist/eval-suite-binding.js +24 -0
  46. package/dist/eval-suite-binding.js.map +1 -0
  47. package/dist/event-bus-binding.d.ts +107 -0
  48. package/dist/event-bus-binding.d.ts.map +1 -0
  49. package/dist/event-bus-binding.js +5 -0
  50. package/dist/event-bus-binding.js.map +1 -0
  51. package/dist/flow-binding.d.ts +194 -0
  52. package/dist/flow-binding.d.ts.map +1 -0
  53. package/dist/flow-binding.js +4 -0
  54. package/dist/flow-binding.js.map +1 -0
  55. package/dist/guardrail-binding.d.ts +138 -0
  56. package/dist/guardrail-binding.d.ts.map +1 -0
  57. package/dist/guardrail-binding.js +4 -0
  58. package/dist/guardrail-binding.js.map +1 -0
  59. package/dist/handler-binding.d.ts +126 -0
  60. package/dist/handler-binding.d.ts.map +1 -0
  61. package/dist/handler-binding.js +4 -0
  62. package/dist/handler-binding.js.map +1 -0
  63. package/dist/hitl-binding.d.ts +115 -0
  64. package/dist/hitl-binding.d.ts.map +1 -0
  65. package/dist/hitl-binding.js +4 -0
  66. package/dist/hitl-binding.js.map +1 -0
  67. package/dist/identity-directory-binding.d.ts +116 -0
  68. package/dist/identity-directory-binding.d.ts.map +1 -0
  69. package/dist/identity-directory-binding.js +4 -0
  70. package/dist/identity-directory-binding.js.map +1 -0
  71. package/dist/identity-provider-binding.d.ts +184 -0
  72. package/dist/identity-provider-binding.d.ts.map +1 -0
  73. package/dist/identity-provider-binding.js +4 -0
  74. package/dist/identity-provider-binding.js.map +1 -0
  75. package/dist/image-registry-binding.d.ts +165 -0
  76. package/dist/image-registry-binding.d.ts.map +1 -0
  77. package/dist/image-registry-binding.js +4 -0
  78. package/dist/image-registry-binding.js.map +1 -0
  79. package/dist/index.d.ts +72 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +26 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/key-management-binding.d.ts +101 -0
  84. package/dist/key-management-binding.d.ts.map +1 -0
  85. package/dist/key-management-binding.js +4 -0
  86. package/dist/key-management-binding.js.map +1 -0
  87. package/dist/mcp-endpoint-binding.d.ts +312 -0
  88. package/dist/mcp-endpoint-binding.d.ts.map +1 -0
  89. package/dist/mcp-endpoint-binding.js +12 -0
  90. package/dist/mcp-endpoint-binding.js.map +1 -0
  91. package/dist/memory-binding.d.ts +209 -0
  92. package/dist/memory-binding.d.ts.map +1 -0
  93. package/dist/memory-binding.js +4 -0
  94. package/dist/memory-binding.js.map +1 -0
  95. package/dist/middleware/auth.d.ts +168 -0
  96. package/dist/middleware/auth.d.ts.map +1 -0
  97. package/dist/middleware/auth.js +247 -0
  98. package/dist/middleware/auth.js.map +1 -0
  99. package/dist/middleware/authorize.d.ts +26 -0
  100. package/dist/middleware/authorize.d.ts.map +1 -0
  101. package/dist/middleware/authorize.js +65 -0
  102. package/dist/middleware/authorize.js.map +1 -0
  103. package/dist/middleware/error-mapper.d.ts +13 -0
  104. package/dist/middleware/error-mapper.d.ts.map +1 -0
  105. package/dist/middleware/error-mapper.js +32 -0
  106. package/dist/middleware/error-mapper.js.map +1 -0
  107. package/dist/middleware/idempotency.d.ts +43 -0
  108. package/dist/middleware/idempotency.d.ts.map +1 -0
  109. package/dist/middleware/idempotency.js +118 -0
  110. package/dist/middleware/idempotency.js.map +1 -0
  111. package/dist/middleware/principal.d.ts +4 -0
  112. package/dist/middleware/principal.d.ts.map +1 -0
  113. package/dist/middleware/principal.js +42 -0
  114. package/dist/middleware/principal.js.map +1 -0
  115. package/dist/middleware/public-run-routes.d.ts +16 -0
  116. package/dist/middleware/public-run-routes.d.ts.map +1 -0
  117. package/dist/middleware/public-run-routes.js +43 -0
  118. package/dist/middleware/public-run-routes.js.map +1 -0
  119. package/dist/middleware/request-id.d.ts +14 -0
  120. package/dist/middleware/request-id.d.ts.map +1 -0
  121. package/dist/middleware/request-id.js +24 -0
  122. package/dist/middleware/request-id.js.map +1 -0
  123. package/dist/middleware/sigv4-verify.d.ts +64 -0
  124. package/dist/middleware/sigv4-verify.d.ts.map +1 -0
  125. package/dist/middleware/sigv4-verify.js +286 -0
  126. package/dist/middleware/sigv4-verify.js.map +1 -0
  127. package/dist/middleware/sigv4.d.ts +25 -0
  128. package/dist/middleware/sigv4.d.ts.map +1 -0
  129. package/dist/middleware/sigv4.js +120 -0
  130. package/dist/middleware/sigv4.js.map +1 -0
  131. package/dist/openapi/generate.d.ts +15 -0
  132. package/dist/openapi/generate.d.ts.map +1 -0
  133. package/dist/openapi/generate.js +241 -0
  134. package/dist/openapi/generate.js.map +1 -0
  135. package/dist/openapi/operations.d.ts +70 -0
  136. package/dist/openapi/operations.d.ts.map +1 -0
  137. package/dist/openapi/operations.js +5051 -0
  138. package/dist/openapi/operations.js.map +1 -0
  139. package/dist/openapi/schemas.d.ts +590 -0
  140. package/dist/openapi/schemas.d.ts.map +1 -0
  141. package/dist/openapi/schemas.js +5820 -0
  142. package/dist/openapi/schemas.js.map +1 -0
  143. package/dist/provenance-binding.d.ts +116 -0
  144. package/dist/provenance-binding.d.ts.map +1 -0
  145. package/dist/provenance-binding.js +31 -0
  146. package/dist/provenance-binding.js.map +1 -0
  147. package/dist/provider-binding.d.ts +174 -0
  148. package/dist/provider-binding.d.ts.map +1 -0
  149. package/dist/provider-binding.js +4 -0
  150. package/dist/provider-binding.js.map +1 -0
  151. package/dist/public-run-token.d.ts +97 -0
  152. package/dist/public-run-token.d.ts.map +1 -0
  153. package/dist/public-run-token.js +167 -0
  154. package/dist/public-run-token.js.map +1 -0
  155. package/dist/retention-binding.d.ts +69 -0
  156. package/dist/retention-binding.d.ts.map +1 -0
  157. package/dist/retention-binding.js +4 -0
  158. package/dist/retention-binding.js.map +1 -0
  159. package/dist/reviewer-binding.d.ts +84 -0
  160. package/dist/reviewer-binding.d.ts.map +1 -0
  161. package/dist/reviewer-binding.js +4 -0
  162. package/dist/reviewer-binding.js.map +1 -0
  163. package/dist/rotation-status-store.d.ts +96 -0
  164. package/dist/rotation-status-store.d.ts.map +1 -0
  165. package/dist/rotation-status-store.js +106 -0
  166. package/dist/rotation-status-store.js.map +1 -0
  167. package/dist/routes/adapters.d.ts +29 -0
  168. package/dist/routes/adapters.d.ts.map +1 -0
  169. package/dist/routes/adapters.js +230 -0
  170. package/dist/routes/adapters.js.map +1 -0
  171. package/dist/routes/agents.d.ts +17 -0
  172. package/dist/routes/agents.d.ts.map +1 -0
  173. package/dist/routes/agents.js +342 -0
  174. package/dist/routes/agents.js.map +1 -0
  175. package/dist/routes/approvals.d.ts +37 -0
  176. package/dist/routes/approvals.d.ts.map +1 -0
  177. package/dist/routes/approvals.js +551 -0
  178. package/dist/routes/approvals.js.map +1 -0
  179. package/dist/routes/artifacts.d.ts +25 -0
  180. package/dist/routes/artifacts.d.ts.map +1 -0
  181. package/dist/routes/artifacts.js +265 -0
  182. package/dist/routes/artifacts.js.map +1 -0
  183. package/dist/routes/audit.d.ts +6 -0
  184. package/dist/routes/audit.d.ts.map +1 -0
  185. package/dist/routes/audit.js +162 -0
  186. package/dist/routes/audit.js.map +1 -0
  187. package/dist/routes/auth.d.ts +47 -0
  188. package/dist/routes/auth.d.ts.map +1 -0
  189. package/dist/routes/auth.js +630 -0
  190. package/dist/routes/auth.js.map +1 -0
  191. package/dist/routes/capabilities.d.ts +14 -0
  192. package/dist/routes/capabilities.d.ts.map +1 -0
  193. package/dist/routes/capabilities.js +62 -0
  194. package/dist/routes/capabilities.js.map +1 -0
  195. package/dist/routes/compliance.d.ts +37 -0
  196. package/dist/routes/compliance.d.ts.map +1 -0
  197. package/dist/routes/compliance.js +321 -0
  198. package/dist/routes/compliance.js.map +1 -0
  199. package/dist/routes/conversations.d.ts +13 -0
  200. package/dist/routes/conversations.d.ts.map +1 -0
  201. package/dist/routes/conversations.js +295 -0
  202. package/dist/routes/conversations.js.map +1 -0
  203. package/dist/routes/cost.d.ts +24 -0
  204. package/dist/routes/cost.d.ts.map +1 -0
  205. package/dist/routes/cost.js +243 -0
  206. package/dist/routes/cost.js.map +1 -0
  207. package/dist/routes/deployments.d.ts +122 -0
  208. package/dist/routes/deployments.d.ts.map +1 -0
  209. package/dist/routes/deployments.js +1036 -0
  210. package/dist/routes/deployments.js.map +1 -0
  211. package/dist/routes/env.d.ts +62 -0
  212. package/dist/routes/env.d.ts.map +1 -0
  213. package/dist/routes/env.js +311 -0
  214. package/dist/routes/env.js.map +1 -0
  215. package/dist/routes/eval-runs.d.ts +28 -0
  216. package/dist/routes/eval-runs.d.ts.map +1 -0
  217. package/dist/routes/eval-runs.js +479 -0
  218. package/dist/routes/eval-runs.js.map +1 -0
  219. package/dist/routes/eval-suites.d.ts +24 -0
  220. package/dist/routes/eval-suites.d.ts.map +1 -0
  221. package/dist/routes/eval-suites.js +381 -0
  222. package/dist/routes/eval-suites.js.map +1 -0
  223. package/dist/routes/event-triggers.d.ts +12 -0
  224. package/dist/routes/event-triggers.d.ts.map +1 -0
  225. package/dist/routes/event-triggers.js +218 -0
  226. package/dist/routes/event-triggers.js.map +1 -0
  227. package/dist/routes/flows.d.ts +23 -0
  228. package/dist/routes/flows.d.ts.map +1 -0
  229. package/dist/routes/flows.js +344 -0
  230. package/dist/routes/flows.js.map +1 -0
  231. package/dist/routes/guardrails.d.ts +33 -0
  232. package/dist/routes/guardrails.d.ts.map +1 -0
  233. package/dist/routes/guardrails.js +236 -0
  234. package/dist/routes/guardrails.js.map +1 -0
  235. package/dist/routes/identity.d.ts +39 -0
  236. package/dist/routes/identity.d.ts.map +1 -0
  237. package/dist/routes/identity.js +138 -0
  238. package/dist/routes/identity.js.map +1 -0
  239. package/dist/routes/mcp.d.ts +23 -0
  240. package/dist/routes/mcp.d.ts.map +1 -0
  241. package/dist/routes/mcp.js +727 -0
  242. package/dist/routes/mcp.js.map +1 -0
  243. package/dist/routes/memory.d.ts +16 -0
  244. package/dist/routes/memory.d.ts.map +1 -0
  245. package/dist/routes/memory.js +353 -0
  246. package/dist/routes/memory.js.map +1 -0
  247. package/dist/routes/observations.d.ts +19 -0
  248. package/dist/routes/observations.d.ts.map +1 -0
  249. package/dist/routes/observations.js +135 -0
  250. package/dist/routes/observations.js.map +1 -0
  251. package/dist/routes/orgs.d.ts +24 -0
  252. package/dist/routes/orgs.d.ts.map +1 -0
  253. package/dist/routes/orgs.js +208 -0
  254. package/dist/routes/orgs.js.map +1 -0
  255. package/dist/routes/pagination.d.ts +18 -0
  256. package/dist/routes/pagination.d.ts.map +1 -0
  257. package/dist/routes/pagination.js +35 -0
  258. package/dist/routes/pagination.js.map +1 -0
  259. package/dist/routes/policies.d.ts +23 -0
  260. package/dist/routes/policies.d.ts.map +1 -0
  261. package/dist/routes/policies.js +314 -0
  262. package/dist/routes/policies.js.map +1 -0
  263. package/dist/routes/projects.d.ts +45 -0
  264. package/dist/routes/projects.d.ts.map +1 -0
  265. package/dist/routes/projects.js +485 -0
  266. package/dist/routes/projects.js.map +1 -0
  267. package/dist/routes/proposals.d.ts +24 -0
  268. package/dist/routes/proposals.d.ts.map +1 -0
  269. package/dist/routes/proposals.js +581 -0
  270. package/dist/routes/proposals.js.map +1 -0
  271. package/dist/routes/provenance.d.ts +34 -0
  272. package/dist/routes/provenance.d.ts.map +1 -0
  273. package/dist/routes/provenance.js +274 -0
  274. package/dist/routes/provenance.js.map +1 -0
  275. package/dist/routes/providers.d.ts +32 -0
  276. package/dist/routes/providers.d.ts.map +1 -0
  277. package/dist/routes/providers.js +490 -0
  278. package/dist/routes/providers.js.map +1 -0
  279. package/dist/routes/public-run-tokens.d.ts +17 -0
  280. package/dist/routes/public-run-tokens.d.ts.map +1 -0
  281. package/dist/routes/public-run-tokens.js +69 -0
  282. package/dist/routes/public-run-tokens.js.map +1 -0
  283. package/dist/routes/retention.d.ts +19 -0
  284. package/dist/routes/retention.d.ts.map +1 -0
  285. package/dist/routes/retention.js +152 -0
  286. package/dist/routes/retention.js.map +1 -0
  287. package/dist/routes/reviewers.d.ts +5 -0
  288. package/dist/routes/reviewers.d.ts.map +1 -0
  289. package/dist/routes/reviewers.js +161 -0
  290. package/dist/routes/reviewers.js.map +1 -0
  291. package/dist/routes/runs.d.ts +34 -0
  292. package/dist/routes/runs.d.ts.map +1 -0
  293. package/dist/routes/runs.js +773 -0
  294. package/dist/routes/runs.js.map +1 -0
  295. package/dist/routes/s3.d.ts +31 -0
  296. package/dist/routes/s3.d.ts.map +1 -0
  297. package/dist/routes/s3.js +433 -0
  298. package/dist/routes/s3.js.map +1 -0
  299. package/dist/routes/schedules.d.ts +20 -0
  300. package/dist/routes/schedules.d.ts.map +1 -0
  301. package/dist/routes/schedules.js +234 -0
  302. package/dist/routes/schedules.js.map +1 -0
  303. package/dist/routes/scope-params.d.ts +57 -0
  304. package/dist/routes/scope-params.d.ts.map +1 -0
  305. package/dist/routes/scope-params.js +105 -0
  306. package/dist/routes/scope-params.js.map +1 -0
  307. package/dist/routes/secret-ref.d.ts +20 -0
  308. package/dist/routes/secret-ref.d.ts.map +1 -0
  309. package/dist/routes/secret-ref.js +42 -0
  310. package/dist/routes/secret-ref.js.map +1 -0
  311. package/dist/routes/secrets.d.ts +53 -0
  312. package/dist/routes/secrets.d.ts.map +1 -0
  313. package/dist/routes/secrets.js +715 -0
  314. package/dist/routes/secrets.js.map +1 -0
  315. package/dist/routes/signing-keys.d.ts +23 -0
  316. package/dist/routes/signing-keys.d.ts.map +1 -0
  317. package/dist/routes/signing-keys.js +212 -0
  318. package/dist/routes/signing-keys.js.map +1 -0
  319. package/dist/routes/sse.d.ts +58 -0
  320. package/dist/routes/sse.d.ts.map +1 -0
  321. package/dist/routes/sse.js +92 -0
  322. package/dist/routes/sse.js.map +1 -0
  323. package/dist/routes/teams.d.ts +30 -0
  324. package/dist/routes/teams.d.ts.map +1 -0
  325. package/dist/routes/teams.js +443 -0
  326. package/dist/routes/teams.js.map +1 -0
  327. package/dist/routes/tenant.d.ts +57 -0
  328. package/dist/routes/tenant.d.ts.map +1 -0
  329. package/dist/routes/tenant.js +352 -0
  330. package/dist/routes/tenant.js.map +1 -0
  331. package/dist/routes/tokens.d.ts +14 -0
  332. package/dist/routes/tokens.d.ts.map +1 -0
  333. package/dist/routes/tokens.js +231 -0
  334. package/dist/routes/tokens.js.map +1 -0
  335. package/dist/routes/tools.d.ts +33 -0
  336. package/dist/routes/tools.d.ts.map +1 -0
  337. package/dist/routes/tools.js +380 -0
  338. package/dist/routes/tools.js.map +1 -0
  339. package/dist/routes/webhook-endpoints.d.ts +10 -0
  340. package/dist/routes/webhook-endpoints.d.ts.map +1 -0
  341. package/dist/routes/webhook-endpoints.js +407 -0
  342. package/dist/routes/webhook-endpoints.js.map +1 -0
  343. package/dist/routes/webhooks.d.ts +21 -0
  344. package/dist/routes/webhooks.d.ts.map +1 -0
  345. package/dist/routes/webhooks.js +228 -0
  346. package/dist/routes/webhooks.js.map +1 -0
  347. package/dist/s3-credential-binding.d.ts +54 -0
  348. package/dist/s3-credential-binding.d.ts.map +1 -0
  349. package/dist/s3-credential-binding.js +4 -0
  350. package/dist/s3-credential-binding.js.map +1 -0
  351. package/dist/secrets-binding.d.ts +281 -0
  352. package/dist/secrets-binding.d.ts.map +1 -0
  353. package/dist/secrets-binding.js +10 -0
  354. package/dist/secrets-binding.js.map +1 -0
  355. package/dist/secrets-provider-binding.d.ts +164 -0
  356. package/dist/secrets-provider-binding.d.ts.map +1 -0
  357. package/dist/secrets-provider-binding.js +4 -0
  358. package/dist/secrets-provider-binding.js.map +1 -0
  359. package/dist/session-store-binding.d.ts +148 -0
  360. package/dist/session-store-binding.d.ts.map +1 -0
  361. package/dist/session-store-binding.js +4 -0
  362. package/dist/session-store-binding.js.map +1 -0
  363. package/dist/signing-key-binding.d.ts +210 -0
  364. package/dist/signing-key-binding.d.ts.map +1 -0
  365. package/dist/signing-key-binding.js +4 -0
  366. package/dist/signing-key-binding.js.map +1 -0
  367. package/dist/state-store-binding.d.ts +53 -0
  368. package/dist/state-store-binding.d.ts.map +1 -0
  369. package/dist/state-store-binding.js +38 -0
  370. package/dist/state-store-binding.js.map +1 -0
  371. package/dist/supervisor-binding.d.ts +526 -0
  372. package/dist/supervisor-binding.d.ts.map +1 -0
  373. package/dist/supervisor-binding.js +4 -0
  374. package/dist/supervisor-binding.js.map +1 -0
  375. package/dist/tenant-host-access.d.ts +41 -0
  376. package/dist/tenant-host-access.d.ts.map +1 -0
  377. package/dist/tenant-host-access.js +42 -0
  378. package/dist/tenant-host-access.js.map +1 -0
  379. package/dist/token-admin.d.ts +99 -0
  380. package/dist/token-admin.d.ts.map +1 -0
  381. package/dist/token-admin.js +4 -0
  382. package/dist/token-admin.js.map +1 -0
  383. package/dist/tool-binding.d.ts +247 -0
  384. package/dist/tool-binding.d.ts.map +1 -0
  385. package/dist/tool-binding.js +4 -0
  386. package/dist/tool-binding.js.map +1 -0
  387. package/dist/trigger-binding.d.ts +13 -0
  388. package/dist/trigger-binding.d.ts.map +1 -0
  389. package/dist/trigger-binding.js +4 -0
  390. package/dist/trigger-binding.js.map +1 -0
  391. package/dist/types.d.ts +71 -0
  392. package/dist/types.d.ts.map +1 -0
  393. package/dist/types.js +4 -0
  394. package/dist/types.js.map +1 -0
  395. package/dist/webhook-endpoint-binding.d.ts +230 -0
  396. package/dist/webhook-endpoint-binding.d.ts.map +1 -0
  397. package/dist/webhook-endpoint-binding.js +12 -0
  398. package/dist/webhook-endpoint-binding.js.map +1 -0
  399. package/dist/xml.d.ts +79 -0
  400. package/dist/xml.d.ts.map +1 -0
  401. package/dist/xml.js +115 -0
  402. package/dist/xml.js.map +1 -0
  403. package/openapi.json +29659 -0
  404. package/package.json +76 -4
  405. package/scripts/emit-openapi.mjs +44 -0
  406. package/src/adapter-binding.ts +204 -0
  407. package/src/agent-binding.ts +231 -0
  408. package/src/app.ts +1285 -0
  409. package/src/capability-binding.ts +83 -0
  410. package/src/cost-binding.ts +213 -0
  411. package/src/deployment-binding.ts +225 -0
  412. package/src/env-binding.ts +140 -0
  413. package/src/errors.ts +291 -0
  414. package/src/eval-run-binding.ts +209 -0
  415. package/src/eval-run-dispatcher.ts +497 -0
  416. package/src/eval-suite-binding.ts +257 -0
  417. package/src/event-bus-binding.ts +127 -0
  418. package/src/flow-binding.ts +213 -0
  419. package/src/guardrail-binding.ts +151 -0
  420. package/src/handler-binding.ts +132 -0
  421. package/src/hitl-binding.ts +172 -0
  422. package/src/identity-directory-binding.ts +128 -0
  423. package/src/identity-provider-binding.ts +203 -0
  424. package/src/image-registry-binding.ts +193 -0
  425. package/src/index.ts +606 -0
  426. package/src/key-management-binding.ts +91 -0
  427. package/src/mcp-endpoint-binding.ts +311 -0
  428. package/src/memory-binding.ts +239 -0
  429. package/src/middleware/auth.ts +437 -0
  430. package/src/middleware/authorize.ts +125 -0
  431. package/src/middleware/error-mapper.ts +37 -0
  432. package/src/middleware/idempotency.ts +160 -0
  433. package/src/middleware/principal.ts +64 -0
  434. package/src/middleware/public-run-routes.ts +50 -0
  435. package/src/middleware/request-id.ts +28 -0
  436. package/src/middleware/sigv4-verify.ts +374 -0
  437. package/src/middleware/sigv4.ts +165 -0
  438. package/src/openapi/generate.ts +307 -0
  439. package/src/openapi/operations.ts +5445 -0
  440. package/src/openapi/schemas.ts +6363 -0
  441. package/src/provenance-binding.ts +169 -0
  442. package/src/provider-binding.ts +196 -0
  443. package/src/public-run-token.ts +263 -0
  444. package/src/retention-binding.ts +78 -0
  445. package/src/reviewer-binding.ts +99 -0
  446. package/src/rotation-status-store.ts +209 -0
  447. package/src/routes/adapters.ts +319 -0
  448. package/src/routes/agents.ts +424 -0
  449. package/src/routes/approvals.ts +759 -0
  450. package/src/routes/artifacts.ts +317 -0
  451. package/src/routes/audit.ts +219 -0
  452. package/src/routes/auth.ts +806 -0
  453. package/src/routes/capabilities.ts +79 -0
  454. package/src/routes/compliance.ts +482 -0
  455. package/src/routes/conversations.ts +369 -0
  456. package/src/routes/cost.ts +327 -0
  457. package/src/routes/deployments.ts +1493 -0
  458. package/src/routes/env.ts +429 -0
  459. package/src/routes/eval-runs.ts +631 -0
  460. package/src/routes/eval-suites.ts +490 -0
  461. package/src/routes/event-triggers.ts +283 -0
  462. package/src/routes/flows.ts +423 -0
  463. package/src/routes/guardrails.ts +320 -0
  464. package/src/routes/identity.ts +203 -0
  465. package/src/routes/mcp.ts +940 -0
  466. package/src/routes/memory.ts +430 -0
  467. package/src/routes/observations.ts +175 -0
  468. package/src/routes/orgs.ts +273 -0
  469. package/src/routes/pagination.ts +51 -0
  470. package/src/routes/policies.ts +413 -0
  471. package/src/routes/projects.ts +634 -0
  472. package/src/routes/proposals.ts +719 -0
  473. package/src/routes/provenance.ts +406 -0
  474. package/src/routes/providers.ts +624 -0
  475. package/src/routes/public-run-tokens.ts +104 -0
  476. package/src/routes/retention.ts +193 -0
  477. package/src/routes/reviewers.ts +209 -0
  478. package/src/routes/runs.ts +981 -0
  479. package/src/routes/s3.ts +519 -0
  480. package/src/routes/schedules.ts +300 -0
  481. package/src/routes/scope-params.ts +133 -0
  482. package/src/routes/secret-ref.ts +52 -0
  483. package/src/routes/secrets.ts +975 -0
  484. package/src/routes/signing-keys.ts +259 -0
  485. package/src/routes/sse.ts +148 -0
  486. package/src/routes/teams.ts +584 -0
  487. package/src/routes/tenant.ts +530 -0
  488. package/src/routes/tokens.ts +285 -0
  489. package/src/routes/tools.ts +491 -0
  490. package/src/routes/webhook-endpoints.ts +534 -0
  491. package/src/routes/webhooks.ts +296 -0
  492. package/src/s3-credential-binding.ts +58 -0
  493. package/src/secrets-binding.ts +308 -0
  494. package/src/secrets-provider-binding.ts +167 -0
  495. package/src/session-store-binding.ts +163 -0
  496. package/src/signing-key-binding.ts +235 -0
  497. package/src/state-store-binding.ts +84 -0
  498. package/src/supervisor-binding.ts +554 -0
  499. package/src/tenant-host-access.ts +62 -0
  500. package/src/token-admin.ts +104 -0
  501. package/src/tool-binding.ts +274 -0
  502. package/src/trigger-binding.ts +38 -0
  503. package/src/types.ts +74 -0
  504. package/src/webhook-endpoint-binding.ts +246 -0
  505. package/src/xml.ts +196 -0
@@ -0,0 +1,940 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+
4
+ import { Hono } from 'hono';
5
+
6
+ import { ref, tuplesForCreate } from '@kindgi/authz';
7
+ import type { Scope } from '@kindgi/platform';
8
+ import type { Cursor, OrgId, ProjectId, TenantId } from '@kindgi/types';
9
+
10
+ import { statusFor, toWireError } from '../errors.js';
11
+ import {
12
+ type MCPClientProbeBinding,
13
+ type MCPEndpoint,
14
+ type MCPEndpointConfig,
15
+ type MCPEndpointRegistryBinding,
16
+ type MCPPromptDescriptor,
17
+ type MCPPromptMessage,
18
+ type MCPResourceContent,
19
+ type MCPResourceDescriptor,
20
+ type MCPTransport,
21
+ MCP_TRANSPORTS,
22
+ } from '../mcp-endpoint-binding.js';
23
+ import type { Authorizer } from '../middleware/authorize.js';
24
+ import { type TenantHostAccess, deniesHostReach, stdioRefusal } from '../tenant-host-access.js';
25
+ import type { AppEnv } from '../types.js';
26
+ import { clampLimit } from './pagination.js';
27
+ import { parseScopeParams, scopeResourceRef } from './scope-params.js';
28
+ import { parseSecretRef } from './secret-ref.js';
29
+
30
+ /**
31
+ * MCP-endpoint routes (mounted at `/v1/mcp`). Tenants declare the
32
+ * remote MCP servers they want the runtime to consume; at boot the
33
+ * runtime discovers each endpoint's tools and registers them into
34
+ * `ToolRegistryBinding` under the same tenant.
35
+ *
36
+ * Secrets do NOT cross the wire — `MCPEndpoint.secretRef` names a
37
+ * secret in the deployment's store, never a plaintext credential. The
38
+ * API surface accepts, stores, and returns only the reference.
39
+ *
40
+ * `hostAccess` (`KINDGI_TENANT_HOST_ACCESS`): under `deployed`, a stdio
41
+ * endpoint — a command the server would run on its own host — is
42
+ * refused with `403 host-access-denied`.
43
+ */
44
+ export function mcpRouter(
45
+ binding: MCPEndpointRegistryBinding,
46
+ clientProbe: MCPClientProbeBinding | undefined,
47
+ authorizer: Authorizer | undefined,
48
+ options: { readonly hostAccess: TenantHostAccess },
49
+ ): Hono<AppEnv> {
50
+ const r = new Hono<AppEnv>();
51
+
52
+ // Authorization PEP — config-shaped resource. `mcp_endpoint` has
53
+ // `admin from scope`, so cascade fires when scope tuple exists.
54
+ // Register gates at admin on the body's `scopeKind` + `scopeId`, parsed
55
+ // as the handler parses them (parseBodyScope); reads on :id gate at read
56
+ // on `mcp_endpoint:<id>`.
57
+ if (authorizer !== undefined) {
58
+ r.use('/endpoints', async (c, next) => {
59
+ if (c.req.method !== 'POST') return next();
60
+ const tenantId = c.get('tenantId') as TenantId;
61
+ const mw = authorizer.authorize('admin', async () => {
62
+ let body: unknown = {};
63
+ try {
64
+ body = await c.req.json();
65
+ } catch {
66
+ // POST handler validates + returns 400
67
+ }
68
+ const s =
69
+ body !== null && typeof body === 'object'
70
+ ? parseBodyScope(body, tenantId)
71
+ : { kind: 'err' as const };
72
+ return scopeResourceRef(s.kind === 'ok' ? s.scope : undefined, tenantId);
73
+ });
74
+ return mw(c, next);
75
+ });
76
+ r.use('/endpoints/:endpointId/*', async (c, next) => {
77
+ const action = c.req.method === 'GET' ? 'read' : 'admin';
78
+ const endpointId = c.req.param('endpointId') ?? '';
79
+ const mw = authorizer.authorize(action, () => ref('mcp_endpoint', endpointId));
80
+ return mw(c, next);
81
+ });
82
+ r.use('/endpoints/:endpointId', async (c, next) => {
83
+ const action = c.req.method === 'GET' ? 'read' : 'admin';
84
+ const endpointId = c.req.param('endpointId') ?? '';
85
+ const mw = authorizer.authorize(action, () => ref('mcp_endpoint', endpointId));
86
+ return mw(c, next);
87
+ });
88
+ }
89
+
90
+ // ---------- GET /endpoints (list, cursor-paginated, optional ?transport=) ----------
91
+ r.get('/endpoints', async (c) => {
92
+ const requestId = c.get('requestId');
93
+ const tenantId = c.get('tenantId') as TenantId;
94
+ const limit = clampLimit(c.req.query('limit'));
95
+ const cursorRaw = c.req.query('cursor');
96
+ const transportRaw = c.req.query('transport');
97
+
98
+ let transportFilter: MCPTransport | undefined;
99
+ if (transportRaw !== undefined && transportRaw.length > 0) {
100
+ if (!(MCP_TRANSPORTS as readonly string[]).includes(transportRaw)) {
101
+ c.status(statusFor('bad-input') as never);
102
+ return c.json(
103
+ toWireError(
104
+ {
105
+ code: 'bad-input',
106
+ message: `Unknown transport "${transportRaw}" — must be one of ${MCP_TRANSPORTS.join(' / ')}`,
107
+ },
108
+ requestId,
109
+ ),
110
+ );
111
+ }
112
+ transportFilter = transportRaw as MCPTransport;
113
+ }
114
+
115
+ // `inherit` IS LOAD-BEARING for this
116
+ // policy/config-scoped binding: the mcp-endpoint list does an
117
+ // upward hierarchy walk (project → org → tenant) when inherit=true
118
+ // (default). Pass the parsed values through faithfully;
119
+ // do NOT default them in the route.
120
+ const scopeParsed = parseScopeParams(c.req.query(), { tenantId });
121
+ if (scopeParsed.kind === 'err') {
122
+ c.status(statusFor('scope-invalid') as never);
123
+ return c.json(
124
+ toWireError({ code: 'scope-invalid', message: scopeParsed.message }, requestId),
125
+ );
126
+ }
127
+
128
+ const page = await binding.list({
129
+ tenantId,
130
+ limit,
131
+ ...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw as Cursor }),
132
+ ...(transportFilter !== undefined && { transportFilter }),
133
+ ...(scopeParsed.scope !== undefined && { scope: scopeParsed.scope }),
134
+ ...(scopeParsed.inherit !== undefined && { inherit: scopeParsed.inherit }),
135
+ });
136
+ return c.json({
137
+ data: page.data.map(serializeEndpoint),
138
+ hasMore: page.nextCursor !== undefined,
139
+ ...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
140
+ });
141
+ });
142
+
143
+ // ---------- GET /endpoints/:endpointId ----------
144
+ r.get('/endpoints/:endpointId', async (c) => {
145
+ const requestId = c.get('requestId');
146
+ const tenantId = c.get('tenantId') as TenantId;
147
+ const endpointId = c.req.param('endpointId');
148
+
149
+ const endpoint = await binding.get({ tenantId, endpointId });
150
+ if (endpoint === null) {
151
+ c.status(statusFor('mcp-endpoint-not-found') as never);
152
+ return c.json(
153
+ toWireError(
154
+ {
155
+ code: 'mcp-endpoint-not-found',
156
+ message: `No MCP endpoint registered with id "${endpointId}"`,
157
+ endpointId,
158
+ },
159
+ requestId,
160
+ ),
161
+ );
162
+ }
163
+ return c.json(serializeEndpoint(endpoint));
164
+ });
165
+
166
+ // ---------- POST /endpoints (register) ----------
167
+ r.post('/endpoints', async (c) => {
168
+ const requestId = c.get('requestId');
169
+ const tenantId = c.get('tenantId') as TenantId;
170
+
171
+ let body: unknown;
172
+ try {
173
+ body = await c.req.json();
174
+ } catch {
175
+ c.status(statusFor('bad-input') as never);
176
+ return c.json(
177
+ toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
178
+ );
179
+ }
180
+ if (body === null || typeof body !== 'object') {
181
+ c.status(statusFor('bad-input') as never);
182
+ return c.json(
183
+ toWireError({ code: 'bad-input', message: 'Request body must be an object' }, requestId),
184
+ );
185
+ }
186
+
187
+ const validation = validateMCPEndpoint(body);
188
+ if (validation.kind === 'err') {
189
+ c.status(statusFor('invalid-mcp-endpoint') as never);
190
+ return c.json(
191
+ toWireError(
192
+ {
193
+ code: 'invalid-mcp-endpoint',
194
+ message: validation.error.message,
195
+ reason: validation.error.reason,
196
+ },
197
+ requestId,
198
+ ),
199
+ );
200
+ }
201
+
202
+ if (validation.value.transport === 'stdio' && deniesHostReach(options.hostAccess, 'exec')) {
203
+ c.status(statusFor('host-access-denied') as never);
204
+ return c.json(
205
+ toWireError(
206
+ { code: 'host-access-denied', message: stdioRefusal(validation.value.endpointId) },
207
+ requestId,
208
+ ),
209
+ );
210
+ }
211
+
212
+ // Policy/config: register requires an explicit scope. Wire
213
+ // shape mirrors the query-param triplet used by list routes —
214
+ // `scopeKind + scopeId` in the body — for uniformity.
215
+ const scopeParsed = parseBodyScope(body, tenantId);
216
+ if (scopeParsed.kind === 'err') {
217
+ c.status(statusFor('scope-invalid') as never);
218
+ return c.json(
219
+ toWireError({ code: 'scope-invalid', message: scopeParsed.message }, requestId),
220
+ );
221
+ }
222
+
223
+ const registerScope = scopeParsed.scope;
224
+ const outcome = await binding.register({
225
+ tenantId,
226
+ endpoint: validation.value,
227
+ scope: registerScope,
228
+ enqueueTuples: (endpointId) =>
229
+ tuplesForCreate({
230
+ kind: 'mcp_endpoint',
231
+ id: endpointId,
232
+ tenantId,
233
+ scope: registerScope,
234
+ }),
235
+ });
236
+ if (outcome.kind === 'already-registered') {
237
+ c.status(statusFor('mcp-endpoint-already-registered') as never);
238
+ return c.json(
239
+ toWireError(
240
+ {
241
+ code: 'mcp-endpoint-already-registered',
242
+ message: `MCP endpoint "${outcome.endpointId}" is already registered`,
243
+ endpointId: outcome.endpointId,
244
+ },
245
+ requestId,
246
+ ),
247
+ );
248
+ }
249
+ if (outcome.kind === 'project-not-found') {
250
+ c.status(statusFor('scope-invalid') as never);
251
+ return c.json(
252
+ toWireError(
253
+ {
254
+ code: 'scope-invalid',
255
+ message: `Project "${outcome.projectId as unknown as string}" not found for tenant`,
256
+ projectId: outcome.projectId as unknown as string,
257
+ },
258
+ requestId,
259
+ ),
260
+ );
261
+ }
262
+ if (outcome.kind === 'org-not-found') {
263
+ c.status(statusFor('scope-invalid') as never);
264
+ return c.json(
265
+ toWireError(
266
+ {
267
+ code: 'scope-invalid',
268
+ message: `Org "${outcome.orgId as unknown as string}" not found for tenant`,
269
+ orgId: outcome.orgId as unknown as string,
270
+ },
271
+ requestId,
272
+ ),
273
+ );
274
+ }
275
+ c.status(201);
276
+ return c.json({ endpointId: outcome.endpointId });
277
+ });
278
+
279
+ // ---------- GET /endpoints/:endpointId/resources (list) ----------
280
+ r.get('/endpoints/:endpointId/resources', async (c) => {
281
+ const requestId = c.get('requestId');
282
+ const tenantId = c.get('tenantId') as TenantId;
283
+ const endpointId = c.req.param('endpointId');
284
+
285
+ if (clientProbe === undefined) {
286
+ c.status(statusFor('mcp-endpoint-not-found') as never);
287
+ return c.json(
288
+ toWireError(
289
+ {
290
+ code: 'mcp-endpoint-not-found',
291
+ message: 'MCP client probe not configured on this deployment',
292
+ endpointId,
293
+ },
294
+ requestId,
295
+ ),
296
+ );
297
+ }
298
+
299
+ const outcome = await clientProbe.listResources({ tenantId, endpointId });
300
+ if (outcome.kind === 'endpoint-not-found') {
301
+ c.status(statusFor('mcp-endpoint-not-found') as never);
302
+ return c.json(
303
+ toWireError(
304
+ {
305
+ code: 'mcp-endpoint-not-found',
306
+ message: `No MCP endpoint registered with id "${endpointId}"`,
307
+ endpointId,
308
+ },
309
+ requestId,
310
+ ),
311
+ );
312
+ }
313
+ if (outcome.kind === 'protocol-error') {
314
+ c.status(statusFor('mcp-resource-read-failed') as never);
315
+ return c.json(
316
+ toWireError(
317
+ {
318
+ code: 'mcp-resource-read-failed',
319
+ message: outcome.message,
320
+ endpointId,
321
+ },
322
+ requestId,
323
+ ),
324
+ );
325
+ }
326
+ return c.json({ data: outcome.resources.map(serializeResource) });
327
+ });
328
+
329
+ // ---------- GET /endpoints/:endpointId/resources/:uri (read; uri URL-encoded) ----------
330
+ r.get('/endpoints/:endpointId/resources/:uri', async (c) => {
331
+ const requestId = c.get('requestId');
332
+ const tenantId = c.get('tenantId') as TenantId;
333
+ const endpointId = c.req.param('endpointId');
334
+ const uri = decodeURIComponent(c.req.param('uri'));
335
+
336
+ if (clientProbe === undefined) {
337
+ c.status(statusFor('mcp-endpoint-not-found') as never);
338
+ return c.json(
339
+ toWireError(
340
+ {
341
+ code: 'mcp-endpoint-not-found',
342
+ message: 'MCP client probe not configured on this deployment',
343
+ endpointId,
344
+ },
345
+ requestId,
346
+ ),
347
+ );
348
+ }
349
+
350
+ const outcome = await clientProbe.readResource({ tenantId, endpointId, uri });
351
+ if (outcome.kind === 'endpoint-not-found') {
352
+ c.status(statusFor('mcp-endpoint-not-found') as never);
353
+ return c.json(
354
+ toWireError(
355
+ {
356
+ code: 'mcp-endpoint-not-found',
357
+ message: `No MCP endpoint registered with id "${endpointId}"`,
358
+ endpointId,
359
+ },
360
+ requestId,
361
+ ),
362
+ );
363
+ }
364
+ if (outcome.kind === 'resource-not-found') {
365
+ c.status(statusFor('mcp-resource-not-found') as never);
366
+ return c.json(
367
+ toWireError(
368
+ {
369
+ code: 'mcp-resource-not-found',
370
+ message: `No MCP resource "${outcome.uri}" at endpoint "${endpointId}"`,
371
+ endpointId,
372
+ uri: outcome.uri,
373
+ },
374
+ requestId,
375
+ ),
376
+ );
377
+ }
378
+ if (outcome.kind === 'read-failed') {
379
+ c.status(statusFor('mcp-resource-read-failed') as never);
380
+ return c.json(
381
+ toWireError(
382
+ {
383
+ code: 'mcp-resource-read-failed',
384
+ message: outcome.message,
385
+ endpointId,
386
+ uri,
387
+ },
388
+ requestId,
389
+ ),
390
+ );
391
+ }
392
+ return c.json(serializeResourceContent(outcome.content));
393
+ });
394
+
395
+ // ---------- GET /endpoints/:endpointId/prompts (list) ----------
396
+ r.get('/endpoints/:endpointId/prompts', async (c) => {
397
+ const requestId = c.get('requestId');
398
+ const tenantId = c.get('tenantId') as TenantId;
399
+ const endpointId = c.req.param('endpointId');
400
+
401
+ if (clientProbe === undefined) {
402
+ c.status(statusFor('mcp-endpoint-not-found') as never);
403
+ return c.json(
404
+ toWireError(
405
+ {
406
+ code: 'mcp-endpoint-not-found',
407
+ message: 'MCP client probe not configured on this deployment',
408
+ endpointId,
409
+ },
410
+ requestId,
411
+ ),
412
+ );
413
+ }
414
+
415
+ const outcome = await clientProbe.listPrompts({ tenantId, endpointId });
416
+ if (outcome.kind === 'endpoint-not-found') {
417
+ c.status(statusFor('mcp-endpoint-not-found') as never);
418
+ return c.json(
419
+ toWireError(
420
+ {
421
+ code: 'mcp-endpoint-not-found',
422
+ message: `No MCP endpoint registered with id "${endpointId}"`,
423
+ endpointId,
424
+ },
425
+ requestId,
426
+ ),
427
+ );
428
+ }
429
+ if (outcome.kind === 'protocol-error') {
430
+ c.status(statusFor('mcp-prompt-get-failed') as never);
431
+ return c.json(
432
+ toWireError(
433
+ {
434
+ code: 'mcp-prompt-get-failed',
435
+ message: outcome.message,
436
+ endpointId,
437
+ },
438
+ requestId,
439
+ ),
440
+ );
441
+ }
442
+ return c.json({ data: outcome.prompts.map(serializePrompt) });
443
+ });
444
+
445
+ // ---------- POST /endpoints/:endpointId/prompts/:name (get, args in body) ----------
446
+ r.post('/endpoints/:endpointId/prompts/:name', async (c) => {
447
+ const requestId = c.get('requestId');
448
+ const tenantId = c.get('tenantId') as TenantId;
449
+ const endpointId = c.req.param('endpointId');
450
+ const name = c.req.param('name');
451
+
452
+ if (clientProbe === undefined) {
453
+ c.status(statusFor('mcp-endpoint-not-found') as never);
454
+ return c.json(
455
+ toWireError(
456
+ {
457
+ code: 'mcp-endpoint-not-found',
458
+ message: 'MCP client probe not configured on this deployment',
459
+ endpointId,
460
+ },
461
+ requestId,
462
+ ),
463
+ );
464
+ }
465
+
466
+ let body: unknown = {};
467
+ const raw = await c.req.text();
468
+ if (raw.length > 0) {
469
+ try {
470
+ body = JSON.parse(raw);
471
+ } catch {
472
+ c.status(statusFor('bad-input') as never);
473
+ return c.json(
474
+ toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
475
+ );
476
+ }
477
+ }
478
+ if (body === null || typeof body !== 'object') {
479
+ c.status(statusFor('bad-input') as never);
480
+ return c.json(
481
+ toWireError({ code: 'bad-input', message: 'Request body must be an object' }, requestId),
482
+ );
483
+ }
484
+ const argsRaw = (body as { arguments?: unknown }).arguments;
485
+ let args: Readonly<Record<string, string>> | undefined;
486
+ if (argsRaw !== undefined) {
487
+ if (
488
+ typeof argsRaw !== 'object' ||
489
+ argsRaw === null ||
490
+ Object.values(argsRaw as Record<string, unknown>).some((v) => typeof v !== 'string')
491
+ ) {
492
+ c.status(statusFor('bad-input') as never);
493
+ return c.json(
494
+ toWireError(
495
+ {
496
+ code: 'bad-input',
497
+ message: 'arguments must be a Record<string, string>',
498
+ },
499
+ requestId,
500
+ ),
501
+ );
502
+ }
503
+ args = argsRaw as Readonly<Record<string, string>>;
504
+ }
505
+
506
+ const outcome = await clientProbe.getPrompt({
507
+ tenantId,
508
+ endpointId,
509
+ name,
510
+ ...(args !== undefined && { args }),
511
+ });
512
+ if (outcome.kind === 'endpoint-not-found') {
513
+ c.status(statusFor('mcp-endpoint-not-found') as never);
514
+ return c.json(
515
+ toWireError(
516
+ {
517
+ code: 'mcp-endpoint-not-found',
518
+ message: `No MCP endpoint registered with id "${endpointId}"`,
519
+ endpointId,
520
+ },
521
+ requestId,
522
+ ),
523
+ );
524
+ }
525
+ if (outcome.kind === 'prompt-not-found') {
526
+ c.status(statusFor('mcp-prompt-not-found') as never);
527
+ return c.json(
528
+ toWireError(
529
+ {
530
+ code: 'mcp-prompt-not-found',
531
+ message: `No MCP prompt "${outcome.name}" at endpoint "${endpointId}"`,
532
+ endpointId,
533
+ promptName: outcome.name,
534
+ },
535
+ requestId,
536
+ ),
537
+ );
538
+ }
539
+ if (outcome.kind === 'get-failed') {
540
+ c.status(statusFor('mcp-prompt-get-failed') as never);
541
+ return c.json(
542
+ toWireError(
543
+ {
544
+ code: 'mcp-prompt-get-failed',
545
+ message: outcome.message,
546
+ endpointId,
547
+ promptName: name,
548
+ },
549
+ requestId,
550
+ ),
551
+ );
552
+ }
553
+ return c.json({ messages: outcome.messages.map(serializePromptMessage) });
554
+ });
555
+
556
+ // ---------- POST /endpoints/:endpointId/unregister ----------
557
+ r.post('/endpoints/:endpointId/unregister', async (c) => {
558
+ const requestId = c.get('requestId');
559
+ const tenantId = c.get('tenantId') as TenantId;
560
+ const endpointId = c.req.param('endpointId');
561
+
562
+ const outcome = await binding.unregister({ tenantId, endpointId });
563
+ if (!outcome.unregistered) {
564
+ c.status(statusFor('mcp-endpoint-not-found') as never);
565
+ return c.json(
566
+ toWireError(
567
+ {
568
+ code: 'mcp-endpoint-not-found',
569
+ message: `No MCP endpoint "${endpointId}" to unregister`,
570
+ endpointId,
571
+ },
572
+ requestId,
573
+ ),
574
+ );
575
+ }
576
+ return c.json({ endpointId, unregistered: true });
577
+ });
578
+
579
+ return r;
580
+ }
581
+
582
+ function serializeResource(r: MCPResourceDescriptor): Record<string, unknown> {
583
+ return {
584
+ uri: r.uri,
585
+ name: r.name,
586
+ ...(r.description !== undefined && { description: r.description }),
587
+ ...(r.mimeType !== undefined && { mimeType: r.mimeType }),
588
+ };
589
+ }
590
+
591
+ function serializeResourceContent(c: MCPResourceContent): Record<string, unknown> {
592
+ return {
593
+ uri: c.uri,
594
+ ...(c.mimeType !== undefined && { mimeType: c.mimeType }),
595
+ ...(c.text !== undefined && { text: c.text }),
596
+ ...(c.blob !== undefined && { blob: c.blob }),
597
+ };
598
+ }
599
+
600
+ function serializePrompt(p: MCPPromptDescriptor): Record<string, unknown> {
601
+ return {
602
+ name: p.name,
603
+ ...(p.description !== undefined && { description: p.description }),
604
+ ...(p.arguments !== undefined && {
605
+ arguments: p.arguments.map((a) => ({
606
+ name: a.name,
607
+ ...(a.description !== undefined && { description: a.description }),
608
+ ...(a.required !== undefined && { required: a.required }),
609
+ })),
610
+ }),
611
+ };
612
+ }
613
+
614
+ function serializePromptMessage(m: MCPPromptMessage): Record<string, unknown> {
615
+ return { role: m.role, content: m.content };
616
+ }
617
+
618
+ function serializeEndpoint(e: MCPEndpoint): Record<string, unknown> {
619
+ return {
620
+ endpointId: e.endpointId,
621
+ name: e.name,
622
+ transport: e.transport,
623
+ config: e.config,
624
+ ...(e.secretRef !== undefined && { secretRef: e.secretRef }),
625
+ ...(e.instructions !== undefined && { instructions: e.instructions }),
626
+ ...(e.metadata !== undefined && { metadata: e.metadata }),
627
+ };
628
+ }
629
+
630
+ /** The register body: the endpoint, plus the scope it's registered in. */
631
+ const REGISTER_BODY_FIELDS = new Set([
632
+ 'endpointId',
633
+ 'name',
634
+ 'transport',
635
+ 'config',
636
+ 'secretRef',
637
+ 'instructions',
638
+ 'metadata',
639
+ 'scopeKind',
640
+ 'scopeId',
641
+ ]);
642
+
643
+ /**
644
+ * Wire-shape validator. Enforces the closed transport enum + the
645
+ * config-transport-matches-top-level guardrail + required fields per
646
+ * variant. Returns a `Result`-ish shape.
647
+ */
648
+ function validateMCPEndpoint(
649
+ body: unknown,
650
+ ):
651
+ | { kind: 'ok'; value: MCPEndpoint }
652
+ | { kind: 'err'; error: { message: string; reason: string } } {
653
+ const b = body as Partial<MCPEndpoint> & Record<string, unknown>;
654
+ const unknown = Object.keys(b).find((key) => !REGISTER_BODY_FIELDS.has(key));
655
+ if (unknown !== undefined) {
656
+ return {
657
+ kind: 'err',
658
+ error: { message: `Unknown field \`${unknown}\``, reason: 'unknown-field' },
659
+ };
660
+ }
661
+ if (typeof b.endpointId !== 'string' || b.endpointId.length === 0) {
662
+ return {
663
+ kind: 'err',
664
+ error: { message: 'endpointId required (non-empty string)', reason: 'empty-endpoint-id' },
665
+ };
666
+ }
667
+ if (typeof b.name !== 'string' || b.name.length === 0) {
668
+ return {
669
+ kind: 'err',
670
+ error: {
671
+ message: `endpoint "${b.endpointId}" missing name`,
672
+ reason: 'empty-name',
673
+ },
674
+ };
675
+ }
676
+ if (
677
+ typeof b.transport !== 'string' ||
678
+ !(MCP_TRANSPORTS as readonly string[]).includes(b.transport)
679
+ ) {
680
+ return {
681
+ kind: 'err',
682
+ error: {
683
+ message: `endpoint "${b.endpointId}" transport must be one of ${MCP_TRANSPORTS.join(' / ')} — got "${String(b.transport)}"`,
684
+ reason: 'unknown-transport',
685
+ },
686
+ };
687
+ }
688
+ const cfg = b.config;
689
+ if (cfg === undefined || cfg === null || typeof cfg !== 'object') {
690
+ return {
691
+ kind: 'err',
692
+ error: {
693
+ message: `endpoint "${b.endpointId}" config required (object)`,
694
+ reason: 'missing-config',
695
+ },
696
+ };
697
+ }
698
+ const cfgAny = cfg as Partial<MCPEndpointConfig> & Record<string, unknown>;
699
+ if (cfgAny.transport !== b.transport) {
700
+ return {
701
+ kind: 'err',
702
+ error: {
703
+ message: `endpoint "${b.endpointId}" config.transport must match top-level transport (got "${String(cfgAny.transport)}" vs "${b.transport}")`,
704
+ reason: 'config-transport-mismatch',
705
+ },
706
+ };
707
+ }
708
+ const configResult = validateConfig(b.endpointId, cfgAny);
709
+ if (configResult.kind === 'err') return configResult;
710
+
711
+ const secretRef = b.secretRef === undefined ? undefined : parseSecretRef(b.secretRef);
712
+ if (secretRef?.kind === 'err') {
713
+ return {
714
+ kind: 'err',
715
+ error: {
716
+ message: `endpoint "${b.endpointId}": ${secretRef.message}`,
717
+ reason: 'invalid-secret-ref',
718
+ },
719
+ };
720
+ }
721
+ if (b.instructions !== undefined && typeof b.instructions !== 'string') {
722
+ return {
723
+ kind: 'err',
724
+ error: {
725
+ message: `endpoint "${b.endpointId}" instructions must be a string`,
726
+ reason: 'invalid-instructions',
727
+ },
728
+ };
729
+ }
730
+ if (b.metadata !== undefined && (typeof b.metadata !== 'object' || b.metadata === null)) {
731
+ return {
732
+ kind: 'err',
733
+ error: {
734
+ message: `endpoint "${b.endpointId}" metadata must be an object`,
735
+ reason: 'invalid-metadata',
736
+ },
737
+ };
738
+ }
739
+
740
+ const value: MCPEndpoint = {
741
+ endpointId: b.endpointId,
742
+ name: b.name,
743
+ transport: b.transport as MCPTransport,
744
+ config: configResult.value,
745
+ ...(secretRef !== undefined && { secretRef: secretRef.value }),
746
+ ...(b.instructions !== undefined && { instructions: b.instructions as string }),
747
+ ...(b.metadata !== undefined && {
748
+ metadata: b.metadata as Readonly<Record<string, unknown>>,
749
+ }),
750
+ };
751
+ return { kind: 'ok', value };
752
+ }
753
+
754
+ function validateConfig(
755
+ endpointId: string,
756
+ cfg: Partial<MCPEndpointConfig> & Record<string, unknown>,
757
+ ):
758
+ | { kind: 'ok'; value: MCPEndpointConfig }
759
+ | { kind: 'err'; error: { message: string; reason: string } } {
760
+ if (cfg.transport === 'stdio') {
761
+ if (typeof cfg.command !== 'string' || cfg.command.length === 0) {
762
+ return {
763
+ kind: 'err',
764
+ error: {
765
+ message: `endpoint "${endpointId}" stdio config.command required (non-empty string)`,
766
+ reason: 'invalid-stdio-command',
767
+ },
768
+ };
769
+ }
770
+ if (cfg.args !== undefined) {
771
+ if (!Array.isArray(cfg.args) || cfg.args.some((a) => typeof a !== 'string')) {
772
+ return {
773
+ kind: 'err',
774
+ error: {
775
+ message: `endpoint "${endpointId}" stdio config.args must be an array of strings`,
776
+ reason: 'invalid-stdio-args',
777
+ },
778
+ };
779
+ }
780
+ }
781
+ if (cfg.env !== undefined) {
782
+ if (
783
+ typeof cfg.env !== 'object' ||
784
+ cfg.env === null ||
785
+ Object.values(cfg.env as Record<string, unknown>).some((v) => typeof v !== 'string')
786
+ ) {
787
+ return {
788
+ kind: 'err',
789
+ error: {
790
+ message: `endpoint "${endpointId}" stdio config.env must be a Record<string, string>`,
791
+ reason: 'invalid-stdio-env',
792
+ },
793
+ };
794
+ }
795
+ }
796
+ return {
797
+ kind: 'ok',
798
+ value: {
799
+ transport: 'stdio',
800
+ command: cfg.command as string,
801
+ ...(cfg.args !== undefined && { args: cfg.args as readonly string[] }),
802
+ ...(cfg.env !== undefined && { env: cfg.env as Readonly<Record<string, string>> }),
803
+ },
804
+ };
805
+ }
806
+ if (cfg.transport === 'http-sse') {
807
+ if (typeof cfg.url !== 'string' || cfg.url.length === 0) {
808
+ return {
809
+ kind: 'err',
810
+ error: {
811
+ message: `endpoint "${endpointId}" http-sse config.url required (non-empty string)`,
812
+ reason: 'invalid-http-sse-url',
813
+ },
814
+ };
815
+ }
816
+ if (cfg.sseUrl !== undefined && typeof cfg.sseUrl !== 'string') {
817
+ return {
818
+ kind: 'err',
819
+ error: {
820
+ message: `endpoint "${endpointId}" http-sse config.sseUrl must be a string`,
821
+ reason: 'invalid-http-sse-sse-url',
822
+ },
823
+ };
824
+ }
825
+ if (
826
+ cfg.headers !== undefined &&
827
+ (typeof cfg.headers !== 'object' ||
828
+ cfg.headers === null ||
829
+ Object.values(cfg.headers as Record<string, unknown>).some((v) => typeof v !== 'string'))
830
+ ) {
831
+ return {
832
+ kind: 'err',
833
+ error: {
834
+ message: `endpoint "${endpointId}" http-sse config.headers must be a Record<string, string>`,
835
+ reason: 'invalid-http-sse-headers',
836
+ },
837
+ };
838
+ }
839
+ return {
840
+ kind: 'ok',
841
+ value: {
842
+ transport: 'http-sse',
843
+ url: cfg.url as string,
844
+ ...(cfg.sseUrl !== undefined && { sseUrl: cfg.sseUrl as string }),
845
+ ...(cfg.headers !== undefined && {
846
+ headers: cfg.headers as Readonly<Record<string, string>>,
847
+ }),
848
+ },
849
+ };
850
+ }
851
+ // streamable-http
852
+ if (typeof cfg.url !== 'string' || cfg.url.length === 0) {
853
+ return {
854
+ kind: 'err',
855
+ error: {
856
+ message: `endpoint "${endpointId}" streamable-http config.url required (non-empty string)`,
857
+ reason: 'invalid-streamable-http-url',
858
+ },
859
+ };
860
+ }
861
+ if (
862
+ cfg.headers !== undefined &&
863
+ (typeof cfg.headers !== 'object' ||
864
+ cfg.headers === null ||
865
+ Object.values(cfg.headers as Record<string, unknown>).some((v) => typeof v !== 'string'))
866
+ ) {
867
+ return {
868
+ kind: 'err',
869
+ error: {
870
+ message: `endpoint "${endpointId}" streamable-http config.headers must be a Record<string, string>`,
871
+ reason: 'invalid-streamable-http-headers',
872
+ },
873
+ };
874
+ }
875
+ return {
876
+ kind: 'ok',
877
+ value: {
878
+ transport: 'streamable-http',
879
+ url: cfg.url as string,
880
+ ...(cfg.headers !== undefined && {
881
+ headers: cfg.headers as Readonly<Record<string, string>>,
882
+ }),
883
+ },
884
+ };
885
+ }
886
+
887
+ /**
888
+ * Parse the register-body's `scopeKind + scopeId` triplet into a
889
+ * discriminated `Scope`. Mirrors the query-param triplet shape from
890
+ * `parseScopeParams` so write bodies and read query params
891
+ * stay uniform. Cross-field validation:
892
+ *
893
+ * - `scopeKind` required, one of `'tenant' | 'org' | 'project'`.
894
+ * - `scopeKind = 'tenant'` → `scopeId` MUST be absent (tenant is
895
+ * implicit from the session).
896
+ * - `scopeKind ∈ {'org','project'}` → `scopeId` required, non-empty.
897
+ */
898
+ function parseBodyScope(
899
+ body: unknown,
900
+ tenantId: TenantId,
901
+ ):
902
+ | { readonly kind: 'ok'; readonly scope: Scope }
903
+ | { readonly kind: 'err'; readonly message: string } {
904
+ const b = body as { readonly scopeKind?: unknown; readonly scopeId?: unknown };
905
+ const kindRaw = b.scopeKind;
906
+ const idRaw = b.scopeId;
907
+
908
+ if (typeof kindRaw !== 'string' || kindRaw.length === 0) {
909
+ return {
910
+ kind: 'err',
911
+ message: 'scopeKind required in register body: one of "tenant" | "org" | "project"',
912
+ };
913
+ }
914
+ if (kindRaw !== 'tenant' && kindRaw !== 'org' && kindRaw !== 'project') {
915
+ return {
916
+ kind: 'err',
917
+ message: `scopeKind must be one of "tenant" | "org" | "project", got "${kindRaw}"`,
918
+ };
919
+ }
920
+ if (kindRaw === 'tenant') {
921
+ if (idRaw !== undefined && idRaw !== null && String(idRaw).length > 0) {
922
+ return {
923
+ kind: 'err',
924
+ message: `scopeKind="tenant" takes no scopeId (tenant is implicit from the session)`,
925
+ };
926
+ }
927
+ return { kind: 'ok', scope: { kind: 'tenant', tenantId } };
928
+ }
929
+ if (typeof idRaw !== 'string' || idRaw.length === 0) {
930
+ return {
931
+ kind: 'err',
932
+ message: `scopeKind="${kindRaw}" requires a non-empty scopeId in the body`,
933
+ };
934
+ }
935
+ const scope: Scope =
936
+ kindRaw === 'org'
937
+ ? { kind: 'org', tenantId, orgId: idRaw as OrgId }
938
+ : { kind: 'project', tenantId, projectId: idRaw as ProjectId };
939
+ return { kind: 'ok', scope };
940
+ }