@desplega.ai/agent-swarm 1.129.0 → 1.131.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 (226) hide show
  1. package/README.md +2 -2
  2. package/dist/{actions-kfv2dawe.js → actions-w53mbns9.js} +11 -11
  3. package/dist/{anthropic-messages-3xgme8my.js → anthropic-messages-rjmd2e7n.js} +5 -5
  4. package/dist/{app-q8vjk6e8.js → app-m9gwqsqv.js} +8 -8
  5. package/dist/{artifact-hg4t1nx7.js → artifact-jysj3wrg.js} +2 -2
  6. package/dist/{assistant-g037r345.js → assistant-bp65m6f3.js} +13 -13
  7. package/dist/{azure-openai-responses-xa4sh9f6.js → azure-openai-responses-c0yjmbfd.js} +8 -5
  8. package/dist/{boot-reembed-18pzsrxa.js → boot-reembed-62p0at2k.js} +6 -6
  9. package/dist/{boot-reembed-wpks2cj8.js → boot-reembed-xmfp6wdh.js} +7 -7
  10. package/dist/{boot-scrub-logs-n7szd57r.js → boot-scrub-logs-rr8q2dms.js} +5 -5
  11. package/dist/{claude-adapter-qz4r0ajt.js → claude-adapter-2y47mrkd.js} +9 -9
  12. package/dist/{cli-mhjnbgb6.js → cli-0rcyq6d9.js} +450 -186
  13. package/dist/{cli-ttkmehy0.js → cli-2q72qz2s.js} +274 -25
  14. package/dist/{cli-gztgc3hz.js → cli-2wadx7p2.js} +2 -2
  15. package/dist/cli-3fj60etf.js +153 -0
  16. package/dist/{cli-7ecgm5v0.js → cli-3kf51j15.js} +1 -1
  17. package/dist/{cli-vgexpfsr.js → cli-57khth04.js} +6 -3
  18. package/dist/{cli-2mbe7vk0.js → cli-5dsbcjjw.js} +1 -1
  19. package/dist/{cli-etr62zy6.js → cli-5kx36evn.js} +2 -2
  20. package/dist/{cli-v2tr6amf.js → cli-5n6e5yfn.js} +30 -8
  21. package/dist/{cli-hx02s9zq.js → cli-5v4rw6yd.js} +2 -2
  22. package/dist/{cli-v37yr6mf.js → cli-5ze9rv97.js} +4 -4
  23. package/dist/{cli-ch7t5v7n.js → cli-6map995v.js} +9 -4
  24. package/dist/{cli-h0457a67.js → cli-70xqj0z3.js} +3 -3
  25. package/dist/{cli-kk4f9r17.js → cli-72q8m8gk.js} +8 -6
  26. package/dist/{cli-7padk69a.js → cli-78xwvkhj.js} +2 -2
  27. package/dist/{cli-dxtxacy7.js → cli-9dr5qzc0.js} +45 -8
  28. package/dist/{cli-17zxdgsq.js → cli-a40rnf71.js} +6 -6
  29. package/dist/{cli-t53vnnxz.js → cli-a4jzdpa3.js} +2514 -1055
  30. package/dist/{cli-w10fkrf1.js → cli-akdvwc9v.js} +354 -115
  31. package/dist/{cli-1qkk5er0.js → cli-bmze986d.js} +1 -1
  32. package/dist/{cli-ga12dc1d.js → cli-bqw0mt1n.js} +3 -3
  33. package/dist/{cli-0sf92efp.js → cli-cdeg08wx.js} +1 -1
  34. package/dist/{cli-a8ynhkyj.js → cli-cvgjwnh1.js} +17 -15
  35. package/dist/{cli-9fxg3v5m.js → cli-d2tfkcga.js} +4 -4
  36. package/dist/{cli-nhcd7x43.js → cli-d3x3x1c9.js} +2 -2
  37. package/dist/{cli-6nh2qxvh.js → cli-darcwax3.js} +1 -1
  38. package/dist/{cli-yjbgmysx.js → cli-e7ckcg4v.js} +12 -12
  39. package/dist/{cli-4n2gcjpd.js → cli-efxfnq6q.js} +4 -3
  40. package/dist/{cli-z9xqqhfk.js → cli-er3a4bb0.js} +1 -1
  41. package/dist/{cli-xg2eezyv.js → cli-f1am9szv.js} +1 -1
  42. package/dist/{cli-xy4cwsm9.js → cli-fywms69x.js} +1 -1
  43. package/dist/{cli-33jj76y8.js → cli-g6b8x1h8.js} +1 -1
  44. package/dist/{cli-epsvdckx.js → cli-gm9cbhbq.js} +20 -10
  45. package/dist/{cli-rkndnn90.js → cli-k9qkf1hw.js} +6 -4
  46. package/dist/{cli-zejvt395.js → cli-kh3ba2zf.js} +1 -1
  47. package/dist/{cli-gb25p1h2.js → cli-nm5gtp1x.js} +2 -2
  48. package/dist/{cli-akxnpx17.js → cli-pm6xbh84.js} +1829 -1629
  49. package/dist/{cli-2k0ztbfp.js → cli-psh3c4va.js} +1 -1
  50. package/dist/{cli-39vgrsep.js → cli-qv61hp37.js} +2 -2
  51. package/dist/{cli-hv2fndhm.js → cli-r6kqqbj0.js} +6 -4
  52. package/dist/{cli-1y1cm570.js → cli-rzbpmxdr.js} +1 -1
  53. package/dist/{cli-mmrk00vp.js → cli-t1xze5qh.js} +1 -1
  54. package/dist/{cli-g252a9ky.js → cli-t55yw3a1.js} +2 -2
  55. package/dist/{cli-7bz8dzqa.js → cli-t76vw5db.js} +1184 -1522
  56. package/dist/{cli-4n4mdv21.js → cli-xpxde7rm.js} +7 -3
  57. package/dist/{cli-fpaa5k2q.js → cli-yw8vghx2.js} +54 -18
  58. package/dist/cli-zsspvvm2.js +490 -0
  59. package/dist/cli.js +27 -25
  60. package/dist/{codex-adapter-7v6t7ff6.js → codex-adapter-d24q75wk.js} +7 -7
  61. package/dist/{codex-hook-amndawyb.js → codex-hook-hq54t9ft.js} +2 -2
  62. package/dist/{codex-session-runner-e7j4khe2.js → codex-session-runner-g50vcsex.js} +7 -7
  63. package/dist/{commands-ex0k5tbf.js → commands-c3nrc5hg.js} +5 -5
  64. package/dist/{db-df7jatfc.js → db-nt7fg3tw.js} +5 -5
  65. package/dist/{google-generative-ai-y42hnw9p.js → google-generative-ai-hysrd8qx.js} +7 -5
  66. package/dist/{google-vertex-4sg66gb6.js → google-vertex-p5arrga0.js} +7 -5
  67. package/dist/{handlers-1j2cfqt2.js → handlers-fkr6swat.js} +13 -13
  68. package/dist/{hook-nx9a0mj3.js → hook-77wpvnjc.js} +7 -7
  69. package/dist/{hook-w6yaf6sy.js → hook-g019yehy.js} +8 -8
  70. package/dist/{http-4tz5h8wg.js → http-jewj0syk.js} +2993 -716
  71. package/dist/{index-0bpkzb09.js → index-070v4eyb.js} +3 -3
  72. package/dist/{index-0s67qv7h.js → index-6gm5he8h.js} +11 -11
  73. package/dist/{index-35gtv6gj.js → index-7n2xpbd4.js} +310 -40
  74. package/dist/{index-ker3gccb.js → index-9znhar3x.js} +4 -4
  75. package/dist/{index-5n2c8yay.js → index-hase6zbe.js} +2 -2
  76. package/dist/{index-kcf3tm9h.js → index-hfvggd0z.js} +12 -12
  77. package/dist/{index-7c0jqna0.js → index-hp1kdbjj.js} +13 -13
  78. package/dist/{keepalive-3j4a9168.js → keepalive-j0fjvqfd.js} +7 -7
  79. package/dist/{lead-6kpevymb.js → lead-1n8x30xe.js} +33 -33
  80. package/dist/{maintenance-m1k82ean.js → maintenance-gvev11sa.js} +7 -7
  81. package/dist/{mistral-conversations-bjkdfb6z.js → mistral-conversations-81fwav0j.js} +6 -6
  82. package/dist/{oauth-refresh-sweep-881k8e4q.js → oauth-refresh-sweep-s9ecsvh0.js} +6 -6
  83. package/dist/{onboard-c0ykffjn.js → onboard-pvm5b38w.js} +2 -2
  84. package/dist/{openai-codex-responses-xetseqvt.js → openai-codex-responses-5g27pd6f.js} +43 -23
  85. package/dist/{openai-completions-5r2g5axa.js → openai-completions-3vkmfz2a.js} +55 -11
  86. package/dist/{openai-responses-ce67hd23.js → openai-responses-dg4t7j7a.js} +8 -5
  87. package/dist/{openrouter-images-pzfp22jb.js → openrouter-images-g3gm8931.js} +1 -1
  88. package/dist/{otel-impl-sqagjerv.js → otel-impl-p6jvgd9c.js} +6 -4
  89. package/dist/{otel-3mp81ppd.js → otel-nqa12wf3.js} +2 -2
  90. package/dist/{pi-mono-adapter-k584k16g.js → pi-mono-adapter-t091s27g.js} +17117 -7517
  91. package/dist/{pricing-refresh-y82whbf9.js → pricing-refresh-k49rcyed.js} +7 -7
  92. package/dist/{rbac-roles-nvkqmzyd.js → rbac-roles-30pspvy7.js} +7 -7
  93. package/dist/{rbac-roles-4ht8gegc.js → rbac-roles-cr80g96t.js} +6 -6
  94. package/dist/{render-v2-wvqdgvvp.js → render-v2-xm457ng1.js} +8 -8
  95. package/dist/{seed-pricing-fy3rxhde.js → seed-pricing-yhpv35fr.js} +6 -6
  96. package/dist/{setup-ak5cnc6f.js → setup-nytnmwwr.js} +2 -2
  97. package/dist/{worker-d8769q8a.js → worker-msytr2cw.js} +33 -33
  98. package/openapi.json +34039 -11036
  99. package/package.json +8 -6
  100. package/src/apps/definition.ts +368 -26
  101. package/src/apps/row-store.ts +66 -10
  102. package/src/apps/schema-migrate.ts +95 -1
  103. package/src/apps/store.ts +13 -4
  104. package/src/apps/sync-run-as.ts +18 -0
  105. package/src/apps/sync.ts +934 -0
  106. package/src/apps/version.ts +16 -2
  107. package/src/assets/key.ts +8 -1
  108. package/src/be/asset-key-audit.ts +3 -1
  109. package/src/be/db-queries/mcp-oauth.ts +297 -24
  110. package/src/be/db.ts +42 -1
  111. package/src/be/migrations/129_asset_keys_apps_scripts.sql +161 -0
  112. package/src/be/scripts/db.ts +5 -2
  113. package/src/be/scripts/typecheck.ts +1 -0
  114. package/src/be/seed-scripts/catalog/app-sync-run.ts +32 -0
  115. package/src/be/seed-scripts/catalog/github-issues-pull.ts +102 -0
  116. package/src/be/seed-scripts/index.ts +18 -0
  117. package/src/be/seed-skills/index.ts +7 -0
  118. package/src/http/active-sessions.ts +26 -18
  119. package/src/http/agents.ts +94 -27
  120. package/src/http/api-keys.ts +91 -17
  121. package/src/http/approval-requests.ts +87 -10
  122. package/src/http/apps.ts +361 -53
  123. package/src/http/assets.ts +165 -31
  124. package/src/http/budgets.ts +7 -5
  125. package/src/http/codex-oauth-keep-warm.ts +21 -3
  126. package/src/http/config.ts +46 -16
  127. package/src/http/context.ts +33 -6
  128. package/src/http/ecosystem.ts +20 -6
  129. package/src/http/events.ts +24 -9
  130. package/src/http/favorites.ts +20 -6
  131. package/src/http/fs.ts +60 -17
  132. package/src/http/heartbeat.ts +18 -4
  133. package/src/http/inbox-state.ts +12 -6
  134. package/src/http/integrations.ts +25 -5
  135. package/src/http/kv.ts +36 -15
  136. package/src/http/mcp-bridge.ts +5 -1
  137. package/src/http/mcp-oauth.ts +332 -17
  138. package/src/http/mcp-servers.ts +56 -18
  139. package/src/http/memory.ts +282 -29
  140. package/src/http/metrics.ts +80 -17
  141. package/src/http/oauth-callback.ts +10 -4
  142. package/src/http/oauth-generic.ts +5 -1
  143. package/src/http/oauth-locks.ts +6 -3
  144. package/src/http/openapi.ts +57 -9
  145. package/src/http/page-proxy.ts +25 -5
  146. package/src/http/pages-public.ts +37 -20
  147. package/src/http/pages.ts +93 -28
  148. package/src/http/poll.ts +89 -5
  149. package/src/http/pricing.ts +9 -6
  150. package/src/http/prompt-templates.ts +85 -21
  151. package/src/http/route-def.ts +67 -4
  152. package/src/http/schedules.ts +63 -14
  153. package/src/http/script-connection-proxy.ts +30 -4
  154. package/src/http/script-connections.ts +393 -43
  155. package/src/http/script-runs.ts +73 -19
  156. package/src/http/scripts.ts +257 -39
  157. package/src/http/session-data.ts +87 -14
  158. package/src/http/sessions.ts +80 -5
  159. package/src/http/skills.ts +115 -35
  160. package/src/http/stats.ts +94 -13
  161. package/src/http/task-templates.ts +6 -4
  162. package/src/http/tasks.ts +230 -61
  163. package/src/http/trackers/jira.ts +90 -30
  164. package/src/http/trackers/linear.ts +46 -12
  165. package/src/http/users.ts +162 -25
  166. package/src/http/utils.ts +12 -2
  167. package/src/http/webhooks.ts +30 -16
  168. package/src/http/workflow-events.ts +18 -5
  169. package/src/http/workflows.ts +128 -39
  170. package/src/http/x.ts +37 -6
  171. package/src/oauth/ensure-mcp-token.ts +16 -1
  172. package/src/oauth/mcp-wrapper.ts +281 -26
  173. package/src/providers/pi-mono-adapter.ts +1 -1
  174. package/src/scripts-runtime/credential-broker/README.md +1 -1
  175. package/src/scripts-runtime/credential-broker/fetch-patch.ts +12 -2
  176. package/src/scripts-runtime/sdk-allowlist.ts +1 -0
  177. package/src/scripts-runtime/stdlib/fetch.ts +6 -0
  178. package/src/scripts-runtime/types/stdlib.d.ts +1 -0
  179. package/src/scripts-runtime/types/swarm-sdk.d.ts +1 -0
  180. package/src/server.ts +2 -0
  181. package/src/tests/apps-rbac.test.ts +110 -0
  182. package/src/tests/apps-spike2.test.ts +4 -1
  183. package/src/tests/apps-sync-engine.test.ts +2540 -0
  184. package/src/tests/apps-sync.test.ts +1627 -0
  185. package/src/tests/asset-key-api.test.ts +48 -2
  186. package/src/tests/asset-key-invariants.test.ts +92 -0
  187. package/src/tests/asset-key-migration.test.ts +174 -8
  188. package/src/tests/asset-key-normalization.test.ts +2 -0
  189. package/src/tests/credential-broker.test.ts +27 -2
  190. package/src/tests/mcp-oauth-dcr-reuse.test.ts +743 -0
  191. package/src/tests/mcp-oauth-ensure-token.test.ts +45 -0
  192. package/src/tests/mcp-oauth-manual-client.test.ts +135 -2
  193. package/src/tests/mcp-oauth-queries.test.ts +153 -0
  194. package/src/tests/mcp-oauth-wrapper.test.ts +432 -0
  195. package/src/tests/memory-http-recall-gating.test.ts +2 -0
  196. package/src/tests/openapi-response-contract.test.ts +138 -0
  197. package/src/tests/rbac-admission-e2e.test.ts +68 -0
  198. package/src/tests/script-connections.test.ts +3 -0
  199. package/src/tests/scripts-runtime-fetch.test.ts +121 -0
  200. package/src/tests/scripts-runtime-secret-egress.test.ts +4 -2
  201. package/src/tests/seed-scripts.test.ts +2 -2
  202. package/src/tests/swarm-tool-result-gate.test.ts +32 -0
  203. package/src/tests/task-working-dir.test.ts +8 -4
  204. package/src/tests/whoami-route.test.ts +127 -0
  205. package/src/tests/workflow-engine-v2.test.ts +80 -7
  206. package/src/tests/workflow-swarm-script.test.ts +104 -0
  207. package/src/tools/app-get.ts +10 -2
  208. package/src/tools/app-rollback.ts +1 -0
  209. package/src/tools/app-sync.ts +112 -0
  210. package/src/tools/script-common.ts +20 -0
  211. package/src/tools/tool-config.ts +2 -1
  212. package/src/tools/utils.ts +11 -0
  213. package/src/tools/workflows/create-workflow.ts +4 -1
  214. package/src/types.ts +1394 -1206
  215. package/src/utils/template.ts +8 -1
  216. package/src/utils/zod-openapi.ts +11 -0
  217. package/src/workflows/engine.ts +27 -4
  218. package/src/workflows/executors/swarm-script.ts +28 -0
  219. package/src/workflows/retry-poller.ts +19 -2
  220. package/templates/skills/apps/content.md +94 -5
  221. package/templates/skills/asset-namespaces/content.md +2 -2
  222. package/templates/skills/scheduled-task-resilience/SKILL.md +102 -0
  223. package/templates/skills/scheduled-task-resilience/config.json +14 -0
  224. package/templates/skills/scheduled-task-resilience/content.md +97 -0
  225. package/dist/cli-7wmybrt5.js +0 -115
  226. package/dist/cli-d91pvmq1.js +0 -14
package/src/http/kv.ts CHANGED
@@ -15,9 +15,9 @@ import { mcpOverflowAuthError } from "../kv-overflow";
15
15
  import { reservedNamespaceError } from "../kv-reserved-namespaces";
16
16
  import { can } from "../rbac";
17
17
  import { agentContextKey, pageContextKey } from "../tasks/context-key";
18
- import { KvKeySchema, KvNamespaceSchema, KvValueTypeSchema } from "../types";
18
+ import { KvEntrySchema, KvKeySchema, KvNamespaceSchema, KvValueTypeSchema } from "../types";
19
19
  import { route } from "./route-def";
20
- import { BODY_TOO_LARGE, enforceContentLengthCap, json, jsonError } from "./utils";
20
+ import { BODY_TOO_LARGE, enforceContentLengthCap, jsonError } from "./utils";
21
21
 
22
22
  /**
23
23
  * KV store HTTP surface — see plan & `src/be/migrations/061_kv_store.sql`.
@@ -72,21 +72,29 @@ const kvListQuerySchema = z.object({
72
72
  // ─── Routes ──────────────────────────────────────────────────────────────────
73
73
 
74
74
  const RESPONSES_GET = {
75
- 200: { description: "KV entry" },
75
+ 200: { description: "KV entry", schema: KvEntrySchema },
76
76
  404: { description: "KV entry not found or expired" },
77
77
  400: { description: "Validation error or unresolvable namespace" },
78
78
  } as const;
79
79
 
80
80
  const RESPONSES_PUT = {
81
- 200: { description: "KV entry stored" },
81
+ 200: { description: "KV entry stored", schema: KvEntrySchema },
82
82
  400: { description: "Validation error" },
83
83
  403: { description: "Caller may not write this namespace" },
84
84
  409: { description: "INCR collision: existing value_type is not 'integer'" },
85
85
  413: { description: "Body exceeds 2 MiB" },
86
86
  } as const;
87
87
 
88
+ // Wire shape sent by `sendList` — not an existing named entity, defined
89
+ // locally since it's a list+total+namespace wrapper unique to this endpoint.
90
+ const kvListResponseSchema = z.object({
91
+ entries: z.array(KvEntrySchema),
92
+ total: z.number().int().nonnegative(),
93
+ namespace: z.string(),
94
+ });
95
+
88
96
  const RESPONSES_LIST = {
89
- 200: { description: "KV entries in the resolved namespace" },
97
+ 200: { description: "KV entries in the resolved namespace", schema: kvListResponseSchema },
90
98
  400: { description: "Validation error or unresolvable namespace" },
91
99
  } as const;
92
100
 
@@ -212,6 +220,15 @@ const listKvExplicit = route({
212
220
  responses: RESPONSES_LIST,
213
221
  });
214
222
 
223
+ // The header-resolved and explicit-namespace route pairs share the exact same
224
+ // `responses` object references (RESPONSES_GET / RESPONSES_PUT / RESPONSES_LIST
225
+ // above), so their `.respond` methods are structurally identical types. These
226
+ // aliases let the shared `send*`/`handleIncr` helpers accept "whichever of the
227
+ // two matched" without re-deriving the response shape per call site.
228
+ type GetKvRespond = typeof getKvHeader.respond;
229
+ type PutKvRespond = typeof putKvHeader.respond;
230
+ type ListKvRespond = typeof listKvHeader.respond;
231
+
215
232
  // ─── Helpers ─────────────────────────────────────────────────────────────────
216
233
 
217
234
  /**
@@ -454,7 +471,7 @@ export async function handleKv(
454
471
  if (!ns) return true;
455
472
  const key = decodeKvSegment(res, parsed.params.key, "key");
456
473
  if (!key) return true;
457
- return sendGet(req, res, ns, key);
474
+ return sendGet(req, res, ns, key, getKvExplicit.respond);
458
475
  }
459
476
  if (putKvExplicit.match(req.method, pathSegments)) {
460
477
  if (enforceContentLengthCap(req, res, MAX_KV_BODY_BYTES) === BODY_TOO_LARGE) return true;
@@ -464,7 +481,7 @@ export async function handleKv(
464
481
  if (!ns) return true;
465
482
  const key = decodeKvSegment(res, parsed.params.key, "key");
466
483
  if (!key) return true;
467
- return sendPut(req, res, ns, key, parsed.body);
484
+ return sendPut(req, res, ns, key, parsed.body, putKvExplicit.respond);
468
485
  }
469
486
  if (deleteKvExplicit.match(req.method, pathSegments)) {
470
487
  const parsed = await deleteKvExplicit.parse(req, res, pathSegments, queryParams);
@@ -480,7 +497,7 @@ export async function handleKv(
480
497
  if (!parsed) return true;
481
498
  const ns = decodeKvSegment(res, parsed.params.namespace, "namespace");
482
499
  if (!ns) return true;
483
- return sendList(req, res, ns, parsed.query);
500
+ return sendList(req, res, ns, parsed.query, listKvExplicit.respond);
484
501
  }
485
502
 
486
503
  // ── Header-resolved variants ──────────────────────────────────────────────
@@ -494,7 +511,7 @@ export async function handleKv(
494
511
  }
495
512
  const key = decodeKvSegment(res, parsed.params.key, "key");
496
513
  if (!key) return true;
497
- return sendGet(req, res, ns, key);
514
+ return sendGet(req, res, ns, key, getKvHeader.respond);
498
515
  }
499
516
  if (putKvHeader.match(req.method, pathSegments)) {
500
517
  if (enforceContentLengthCap(req, res, MAX_KV_BODY_BYTES) === BODY_TOO_LARGE) return true;
@@ -507,7 +524,7 @@ export async function handleKv(
507
524
  }
508
525
  const key = decodeKvSegment(res, parsed.params.key, "key");
509
526
  if (!key) return true;
510
- return sendPut(req, res, ns, key, parsed.body);
527
+ return sendPut(req, res, ns, key, parsed.body, putKvHeader.respond);
511
528
  }
512
529
  if (deleteKvHeader.match(req.method, pathSegments)) {
513
530
  const parsed = await deleteKvHeader.parse(req, res, pathSegments, queryParams);
@@ -529,7 +546,7 @@ export async function handleKv(
529
546
  jsonError(res, "namespace is required (pass X-Source-Task-Id or X-Agent-ID)", 400);
530
547
  return true;
531
548
  }
532
- return sendList(req, res, ns, parsed.query);
549
+ return sendList(req, res, ns, parsed.query, listKvHeader.respond);
533
550
  }
534
551
 
535
552
  return false;
@@ -595,10 +612,11 @@ async function handleIncr(
595
612
  return true;
596
613
  }
597
614
 
615
+ const respond: PutKvRespond = explicit ? incrKvExplicit.respond : incrKvHeader.respond;
598
616
  const by = body?.by ?? 1;
599
617
  try {
600
618
  const entry = incrKv(namespace, key, by);
601
- json(res, entry);
619
+ respond(res, 200, entry);
602
620
  } catch (err) {
603
621
  if (err instanceof KvTypeCollisionError) {
604
622
  jsonError(res, err.message, 409);
@@ -615,6 +633,7 @@ function sendGet(
615
633
  res: ServerResponse,
616
634
  namespace: string,
617
635
  key: string,
636
+ respond: GetKvRespond,
618
637
  ): boolean {
619
638
  const authErr = authorizeRead(namespace, buildAuthCtx(req));
620
639
  if (authErr) {
@@ -626,7 +645,7 @@ function sendGet(
626
645
  jsonError(res, "not found", 404);
627
646
  return true;
628
647
  }
629
- json(res, entry);
648
+ respond(res, 200, entry);
630
649
  return true;
631
650
  }
632
651
 
@@ -636,6 +655,7 @@ function sendPut(
636
655
  namespace: string,
637
656
  key: string,
638
657
  body: z.infer<typeof kvSetBodySchema>,
658
+ respond: PutKvRespond,
639
659
  ): boolean {
640
660
  const authErr = authorizeWrite(namespace, buildAuthCtx(req));
641
661
  if (authErr) {
@@ -660,7 +680,7 @@ function sendPut(
660
680
  valueType,
661
681
  expiresAt,
662
682
  });
663
- json(res, entry);
683
+ respond(res, 200, entry);
664
684
  } catch (err) {
665
685
  const msg = err instanceof Error ? err.message : "upsert failed";
666
686
  jsonError(res, msg, 400);
@@ -694,6 +714,7 @@ function sendList(
694
714
  res: ServerResponse,
695
715
  namespace: string,
696
716
  query: z.infer<typeof kvListQuerySchema>,
717
+ respond: ListKvRespond,
697
718
  ): boolean {
698
719
  const authErr = authorizeRead(namespace, buildAuthCtx(req));
699
720
  if (authErr) {
@@ -705,6 +726,6 @@ function sendList(
705
726
  const prefix = query.prefix && query.prefix.length > 0 ? query.prefix : undefined;
706
727
  const entries = listKv(namespace, { prefix, limit, offset });
707
728
  const total = countKv(namespace, { prefix });
708
- json(res, { entries, total, namespace });
729
+ respond(res, 200, { entries, total, namespace });
709
730
  return true;
710
731
  }
@@ -40,7 +40,11 @@ const mcpBridgeRoute = route({
40
40
  args: z.record(z.string(), z.unknown()).default({}),
41
41
  }),
42
42
  responses: {
43
- 200: { description: "Tool result" },
43
+ 200: {
44
+ description: "Tool result",
45
+ unstructured:
46
+ "Generic MCP tool proxy — response shape is whatever the invoked tool's structuredContent/content returns, which varies per tool",
47
+ },
44
48
  400: { description: "Invalid tool name or args" },
45
49
  403: { description: "Tool not in SDK allowlist" },
46
50
  404: { description: "Tool not found" },