@collage-dam/mcp-server 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 (306) hide show
  1. package/.env.example +56 -0
  2. package/CHANGELOG.md +90 -0
  3. package/LICENSE +21 -0
  4. package/README.md +512 -0
  5. package/dist/client.d.ts +497 -0
  6. package/dist/client.d.ts.map +1 -0
  7. package/dist/client.js +1162 -0
  8. package/dist/client.js.map +1 -0
  9. package/dist/conventions/confirmation.d.ts +89 -0
  10. package/dist/conventions/confirmation.d.ts.map +1 -0
  11. package/dist/conventions/confirmation.js +132 -0
  12. package/dist/conventions/confirmation.js.map +1 -0
  13. package/dist/conventions/dry-run/batch-executor.d.ts +36 -0
  14. package/dist/conventions/dry-run/batch-executor.d.ts.map +1 -0
  15. package/dist/conventions/dry-run/batch-executor.js +89 -0
  16. package/dist/conventions/dry-run/batch-executor.js.map +1 -0
  17. package/dist/conventions/dry-run/diff-renderer.d.ts +34 -0
  18. package/dist/conventions/dry-run/diff-renderer.d.ts.map +1 -0
  19. package/dist/conventions/dry-run/diff-renderer.js +158 -0
  20. package/dist/conventions/dry-run/diff-renderer.js.map +1 -0
  21. package/dist/conventions/dry-run/index.d.ts +13 -0
  22. package/dist/conventions/dry-run/index.d.ts.map +1 -0
  23. package/dist/conventions/dry-run/index.js +10 -0
  24. package/dist/conventions/dry-run/index.js.map +1 -0
  25. package/dist/conventions/dry-run/mutating-tool.d.ts +64 -0
  26. package/dist/conventions/dry-run/mutating-tool.d.ts.map +1 -0
  27. package/dist/conventions/dry-run/mutating-tool.js +88 -0
  28. package/dist/conventions/dry-run/mutating-tool.js.map +1 -0
  29. package/dist/conventions/dry-run/summary.d.ts +66 -0
  30. package/dist/conventions/dry-run/summary.d.ts.map +1 -0
  31. package/dist/conventions/dry-run/summary.js +185 -0
  32. package/dist/conventions/dry-run/summary.js.map +1 -0
  33. package/dist/conventions/dry-run/types.d.ts +597 -0
  34. package/dist/conventions/dry-run/types.d.ts.map +1 -0
  35. package/dist/conventions/dry-run/types.js +108 -0
  36. package/dist/conventions/dry-run/types.js.map +1 -0
  37. package/dist/conventions/dry-run/with-dry-run.d.ts +66 -0
  38. package/dist/conventions/dry-run/with-dry-run.d.ts.map +1 -0
  39. package/dist/conventions/dry-run/with-dry-run.js +219 -0
  40. package/dist/conventions/dry-run/with-dry-run.js.map +1 -0
  41. package/dist/conventions/env.d.ts +49 -0
  42. package/dist/conventions/env.d.ts.map +1 -0
  43. package/dist/conventions/env.js +84 -0
  44. package/dist/conventions/env.js.map +1 -0
  45. package/dist/conventions/errors.d.ts +68 -0
  46. package/dist/conventions/errors.d.ts.map +1 -0
  47. package/dist/conventions/errors.js +81 -0
  48. package/dist/conventions/errors.js.map +1 -0
  49. package/dist/conventions/logger.d.ts +28 -0
  50. package/dist/conventions/logger.d.ts.map +1 -0
  51. package/dist/conventions/logger.js +105 -0
  52. package/dist/conventions/logger.js.map +1 -0
  53. package/dist/conventions/pagination.d.ts +37 -0
  54. package/dist/conventions/pagination.d.ts.map +1 -0
  55. package/dist/conventions/pagination.js +53 -0
  56. package/dist/conventions/pagination.js.map +1 -0
  57. package/dist/conventions/rate-limiter.d.ts +54 -0
  58. package/dist/conventions/rate-limiter.d.ts.map +1 -0
  59. package/dist/conventions/rate-limiter.js +143 -0
  60. package/dist/conventions/rate-limiter.js.map +1 -0
  61. package/dist/conventions/response-budget.d.ts +66 -0
  62. package/dist/conventions/response-budget.d.ts.map +1 -0
  63. package/dist/conventions/response-budget.js +89 -0
  64. package/dist/conventions/response-budget.js.map +1 -0
  65. package/dist/conventions/schema-version.d.ts +27 -0
  66. package/dist/conventions/schema-version.d.ts.map +1 -0
  67. package/dist/conventions/schema-version.js +29 -0
  68. package/dist/conventions/schema-version.js.map +1 -0
  69. package/dist/conventions/state-store-redis.d.ts +32 -0
  70. package/dist/conventions/state-store-redis.d.ts.map +1 -0
  71. package/dist/conventions/state-store-redis.js +77 -0
  72. package/dist/conventions/state-store-redis.js.map +1 -0
  73. package/dist/conventions/state-store.d.ts +46 -0
  74. package/dist/conventions/state-store.d.ts.map +1 -0
  75. package/dist/conventions/state-store.js +105 -0
  76. package/dist/conventions/state-store.js.map +1 -0
  77. package/dist/index.d.ts +5 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +421 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/prompts/collection-audit.d.ts +13 -0
  82. package/dist/prompts/collection-audit.d.ts.map +1 -0
  83. package/dist/prompts/collection-audit.js +168 -0
  84. package/dist/prompts/collection-audit.js.map +1 -0
  85. package/dist/prompts/create-distribution.d.ts +15 -0
  86. package/dist/prompts/create-distribution.d.ts.map +1 -0
  87. package/dist/prompts/create-distribution.js +111 -0
  88. package/dist/prompts/create-distribution.js.map +1 -0
  89. package/dist/prompts/helpers.d.ts +20 -0
  90. package/dist/prompts/helpers.d.ts.map +1 -0
  91. package/dist/prompts/helpers.js +53 -0
  92. package/dist/prompts/helpers.js.map +1 -0
  93. package/dist/prompts/library-health-audit.d.ts +13 -0
  94. package/dist/prompts/library-health-audit.d.ts.map +1 -0
  95. package/dist/prompts/library-health-audit.js +131 -0
  96. package/dist/prompts/library-health-audit.js.map +1 -0
  97. package/dist/prompts/usage-insights.d.ts +13 -0
  98. package/dist/prompts/usage-insights.d.ts.map +1 -0
  99. package/dist/prompts/usage-insights.js +98 -0
  100. package/dist/prompts/usage-insights.js.map +1 -0
  101. package/dist/prompts/wrap-prompt-as-tool.d.ts +48 -0
  102. package/dist/prompts/wrap-prompt-as-tool.d.ts.map +1 -0
  103. package/dist/prompts/wrap-prompt-as-tool.js +61 -0
  104. package/dist/prompts/wrap-prompt-as-tool.js.map +1 -0
  105. package/dist/resources/asset-by-id.d.ts +4 -0
  106. package/dist/resources/asset-by-id.d.ts.map +1 -0
  107. package/dist/resources/asset-by-id.js +27 -0
  108. package/dist/resources/asset-by-id.js.map +1 -0
  109. package/dist/resources/collections.d.ts +5 -0
  110. package/dist/resources/collections.d.ts.map +1 -0
  111. package/dist/resources/collections.js +48 -0
  112. package/dist/resources/collections.js.map +1 -0
  113. package/dist/resources/custom-fields.d.ts +4 -0
  114. package/dist/resources/custom-fields.d.ts.map +1 -0
  115. package/dist/resources/custom-fields.js +30 -0
  116. package/dist/resources/custom-fields.js.map +1 -0
  117. package/dist/resources/folders.d.ts +5 -0
  118. package/dist/resources/folders.d.ts.map +1 -0
  119. package/dist/resources/folders.js +73 -0
  120. package/dist/resources/folders.js.map +1 -0
  121. package/dist/resources/helpers.d.ts +17 -0
  122. package/dist/resources/helpers.d.ts.map +1 -0
  123. package/dist/resources/helpers.js +59 -0
  124. package/dist/resources/helpers.js.map +1 -0
  125. package/dist/resources/portals.d.ts +5 -0
  126. package/dist/resources/portals.d.ts.map +1 -0
  127. package/dist/resources/portals.js +81 -0
  128. package/dist/resources/portals.js.map +1 -0
  129. package/dist/resources/recent-and-dashboard.d.ts +5 -0
  130. package/dist/resources/recent-and-dashboard.d.ts.map +1 -0
  131. package/dist/resources/recent-and-dashboard.js +42 -0
  132. package/dist/resources/recent-and-dashboard.js.map +1 -0
  133. package/dist/tools/asset-selection.d.ts +102 -0
  134. package/dist/tools/asset-selection.d.ts.map +1 -0
  135. package/dist/tools/asset-selection.js +133 -0
  136. package/dist/tools/asset-selection.js.map +1 -0
  137. package/dist/tools/audit/audit-folder-structure.d.ts +108 -0
  138. package/dist/tools/audit/audit-folder-structure.d.ts.map +1 -0
  139. package/dist/tools/audit/audit-folder-structure.js +260 -0
  140. package/dist/tools/audit/audit-folder-structure.js.map +1 -0
  141. package/dist/tools/audit/audit-naming-conventions.d.ts +83 -0
  142. package/dist/tools/audit/audit-naming-conventions.d.ts.map +1 -0
  143. package/dist/tools/audit/audit-naming-conventions.js +238 -0
  144. package/dist/tools/audit/audit-naming-conventions.js.map +1 -0
  145. package/dist/tools/audit/audit-tagging-hygiene.d.ts +77 -0
  146. package/dist/tools/audit/audit-tagging-hygiene.d.ts.map +1 -0
  147. package/dist/tools/audit/audit-tagging-hygiene.js +402 -0
  148. package/dist/tools/audit/audit-tagging-hygiene.js.map +1 -0
  149. package/dist/tools/audit/detect-duplicates.d.ts +62 -0
  150. package/dist/tools/audit/detect-duplicates.d.ts.map +1 -0
  151. package/dist/tools/audit/detect-duplicates.js +0 -0
  152. package/dist/tools/audit/detect-duplicates.js.map +1 -0
  153. package/dist/tools/audit/types.d.ts +526 -0
  154. package/dist/tools/audit/types.d.ts.map +1 -0
  155. package/dist/tools/audit/types.js +188 -0
  156. package/dist/tools/audit/types.js.map +1 -0
  157. package/dist/tools/bulk-move-assets.d.ts +78 -0
  158. package/dist/tools/bulk-move-assets.d.ts.map +1 -0
  159. package/dist/tools/bulk-move-assets.js +122 -0
  160. package/dist/tools/bulk-move-assets.js.map +1 -0
  161. package/dist/tools/bulk-normalize-filenames.d.ts +62 -0
  162. package/dist/tools/bulk-normalize-filenames.d.ts.map +1 -0
  163. package/dist/tools/bulk-normalize-filenames.js +237 -0
  164. package/dist/tools/bulk-normalize-filenames.js.map +1 -0
  165. package/dist/tools/bulk-rename-assets.d.ts +79 -0
  166. package/dist/tools/bulk-rename-assets.d.ts.map +1 -0
  167. package/dist/tools/bulk-rename-assets.js +139 -0
  168. package/dist/tools/bulk-rename-assets.js.map +1 -0
  169. package/dist/tools/bulk-tags.d.ts +107 -0
  170. package/dist/tools/bulk-tags.d.ts.map +1 -0
  171. package/dist/tools/bulk-tags.js +220 -0
  172. package/dist/tools/bulk-tags.js.map +1 -0
  173. package/dist/tools/client-adapters.d.ts +76 -0
  174. package/dist/tools/client-adapters.d.ts.map +1 -0
  175. package/dist/tools/client-adapters.js +648 -0
  176. package/dist/tools/client-adapters.js.map +1 -0
  177. package/dist/tools/collection-membership.d.ts +90 -0
  178. package/dist/tools/collection-membership.d.ts.map +1 -0
  179. package/dist/tools/collection-membership.js +195 -0
  180. package/dist/tools/collection-membership.js.map +1 -0
  181. package/dist/tools/create-collection.d.ts +63 -0
  182. package/dist/tools/create-collection.d.ts.map +1 -0
  183. package/dist/tools/create-collection.js +151 -0
  184. package/dist/tools/create-collection.js.map +1 -0
  185. package/dist/tools/create-folder.d.ts +46 -0
  186. package/dist/tools/create-folder.d.ts.map +1 -0
  187. package/dist/tools/create-folder.js +83 -0
  188. package/dist/tools/create-folder.js.map +1 -0
  189. package/dist/tools/create-share-link.d.ts +107 -0
  190. package/dist/tools/create-share-link.d.ts.map +1 -0
  191. package/dist/tools/create-share-link.js +239 -0
  192. package/dist/tools/create-share-link.js.map +1 -0
  193. package/dist/tools/get-asset-details.d.ts +401 -0
  194. package/dist/tools/get-asset-details.d.ts.map +1 -0
  195. package/dist/tools/get-asset-details.js +56 -0
  196. package/dist/tools/get-asset-details.js.map +1 -0
  197. package/dist/tools/get-collection.d.ts +126 -0
  198. package/dist/tools/get-collection.d.ts.map +1 -0
  199. package/dist/tools/get-collection.js +52 -0
  200. package/dist/tools/get-collection.js.map +1 -0
  201. package/dist/tools/get-embed-code.d.ts +195 -0
  202. package/dist/tools/get-embed-code.d.ts.map +1 -0
  203. package/dist/tools/get-embed-code.js +214 -0
  204. package/dist/tools/get-embed-code.js.map +1 -0
  205. package/dist/tools/insights/analyze-share-links.d.ts +159 -0
  206. package/dist/tools/insights/analyze-share-links.d.ts.map +1 -0
  207. package/dist/tools/insights/analyze-share-links.js +314 -0
  208. package/dist/tools/insights/analyze-share-links.js.map +1 -0
  209. package/dist/tools/insights/insight-cache.d.ts +36 -0
  210. package/dist/tools/insights/insight-cache.d.ts.map +1 -0
  211. package/dist/tools/insights/insight-cache.js +98 -0
  212. package/dist/tools/insights/insight-cache.js.map +1 -0
  213. package/dist/tools/insights/report-asset-activation.d.ts +149 -0
  214. package/dist/tools/insights/report-asset-activation.d.ts.map +1 -0
  215. package/dist/tools/insights/report-asset-activation.js +380 -0
  216. package/dist/tools/insights/report-asset-activation.js.map +1 -0
  217. package/dist/tools/insights/report-stale-assets.d.ts +120 -0
  218. package/dist/tools/insights/report-stale-assets.d.ts.map +1 -0
  219. package/dist/tools/insights/report-stale-assets.js +281 -0
  220. package/dist/tools/insights/report-stale-assets.js.map +1 -0
  221. package/dist/tools/insights/report-top-assets.d.ts +139 -0
  222. package/dist/tools/insights/report-top-assets.d.ts.map +1 -0
  223. package/dist/tools/insights/report-top-assets.js +407 -0
  224. package/dist/tools/insights/report-top-assets.js.map +1 -0
  225. package/dist/tools/list-categories.d.ts +127 -0
  226. package/dist/tools/list-categories.d.ts.map +1 -0
  227. package/dist/tools/list-categories.js +68 -0
  228. package/dist/tools/list-categories.js.map +1 -0
  229. package/dist/tools/list-collections.d.ts +127 -0
  230. package/dist/tools/list-collections.d.ts.map +1 -0
  231. package/dist/tools/list-collections.js +53 -0
  232. package/dist/tools/list-collections.js.map +1 -0
  233. package/dist/tools/list-custom-fields.d.ts +125 -0
  234. package/dist/tools/list-custom-fields.d.ts.map +1 -0
  235. package/dist/tools/list-custom-fields.js +51 -0
  236. package/dist/tools/list-custom-fields.js.map +1 -0
  237. package/dist/tools/list-share-links.d.ts +192 -0
  238. package/dist/tools/list-share-links.d.ts.map +1 -0
  239. package/dist/tools/list-share-links.js +92 -0
  240. package/dist/tools/list-share-links.js.map +1 -0
  241. package/dist/tools/list-workspaces.d.ts +88 -0
  242. package/dist/tools/list-workspaces.d.ts.map +1 -0
  243. package/dist/tools/list-workspaces.js +71 -0
  244. package/dist/tools/list-workspaces.js.map +1 -0
  245. package/dist/tools/move-asset.d.ts +48 -0
  246. package/dist/tools/move-asset.d.ts.map +1 -0
  247. package/dist/tools/move-asset.js +85 -0
  248. package/dist/tools/move-asset.js.map +1 -0
  249. package/dist/tools/rename-asset.d.ts +88 -0
  250. package/dist/tools/rename-asset.d.ts.map +1 -0
  251. package/dist/tools/rename-asset.js +100 -0
  252. package/dist/tools/rename-asset.js.map +1 -0
  253. package/dist/tools/rename-folder.d.ts +55 -0
  254. package/dist/tools/rename-folder.d.ts.map +1 -0
  255. package/dist/tools/rename-folder.js +101 -0
  256. package/dist/tools/rename-folder.js.map +1 -0
  257. package/dist/tools/revoke-share-link.d.ts +55 -0
  258. package/dist/tools/revoke-share-link.d.ts.map +1 -0
  259. package/dist/tools/revoke-share-link.js +77 -0
  260. package/dist/tools/revoke-share-link.js.map +1 -0
  261. package/dist/tools/search/facets.d.ts +34 -0
  262. package/dist/tools/search/facets.d.ts.map +1 -0
  263. package/dist/tools/search/facets.js +147 -0
  264. package/dist/tools/search/facets.js.map +1 -0
  265. package/dist/tools/search/filter-builder.d.ts +33 -0
  266. package/dist/tools/search/filter-builder.d.ts.map +1 -0
  267. package/dist/tools/search/filter-builder.js +111 -0
  268. package/dist/tools/search/filter-builder.js.map +1 -0
  269. package/dist/tools/search/search-assets.d.ts +41 -0
  270. package/dist/tools/search/search-assets.d.ts.map +1 -0
  271. package/dist/tools/search/search-assets.js +162 -0
  272. package/dist/tools/search/search-assets.js.map +1 -0
  273. package/dist/tools/search/search-collections.d.ts +35 -0
  274. package/dist/tools/search/search-collections.d.ts.map +1 -0
  275. package/dist/tools/search/search-collections.js +103 -0
  276. package/dist/tools/search/search-collections.js.map +1 -0
  277. package/dist/tools/search/types.d.ts +1047 -0
  278. package/dist/tools/search/types.d.ts.map +1 -0
  279. package/dist/tools/search/types.js +216 -0
  280. package/dist/tools/search/types.js.map +1 -0
  281. package/dist/tools/update-asset-metadata.d.ts +78 -0
  282. package/dist/tools/update-asset-metadata.d.ts.map +1 -0
  283. package/dist/tools/update-asset-metadata.js +203 -0
  284. package/dist/tools/update-asset-metadata.js.map +1 -0
  285. package/dist/tools/update-collection.d.ts +69 -0
  286. package/dist/tools/update-collection.d.ts.map +1 -0
  287. package/dist/tools/update-collection.js +142 -0
  288. package/dist/tools/update-collection.js.map +1 -0
  289. package/dist/tools/view-category-contents.d.ts +231 -0
  290. package/dist/tools/view-category-contents.d.ts.map +1 -0
  291. package/dist/tools/view-category-contents.js +97 -0
  292. package/dist/tools/view-category-contents.js.map +1 -0
  293. package/dist/types.d.ts +1326 -0
  294. package/dist/types.d.ts.map +1 -0
  295. package/dist/types.js +288 -0
  296. package/dist/types.js.map +1 -0
  297. package/dist/typesense.d.ts +84 -0
  298. package/dist/typesense.d.ts.map +1 -0
  299. package/dist/typesense.js +243 -0
  300. package/dist/typesense.js.map +1 -0
  301. package/docs/api-field-verification.md +244 -0
  302. package/docs/deployment-runbook.md +446 -0
  303. package/docs/security-review.md +195 -0
  304. package/docs/typesense-filter-schema.md +262 -0
  305. package/docs/verified-endpoints.md +38 -0
  306. package/package.json +72 -0
@@ -0,0 +1,108 @@
1
+ // ── Dry-Run Framework Types ──────────────────────────────────────────
2
+ // Generic types describing the three-phase dry-run pattern used by every
3
+ // mutating tool: plan (pure) → preview (rendered diff) → execute (after
4
+ // explicit confirmation). All structures are JSON-serialisable so they can
5
+ // be persisted in the ephemeral state store (in-memory or Redis) and
6
+ // returned over both stdio and streamable HTTP transports unchanged.
7
+ import { z } from 'zod';
8
+ import { McpToolErrorSchema } from '../errors.js';
9
+ // ── Risk Flags ───────────────────────────────────────────────────────
10
+ /**
11
+ * Severity classifier for risk flags surfaced in the preview.
12
+ * `info` is purely informational, `warning` is recoverable, `critical`
13
+ * indicates the operation will overwrite data or affect many records.
14
+ */
15
+ export const RiskSeveritySchema = z.enum(['info', 'warning', 'critical']);
16
+ export const RiskFlagSchema = z.object({
17
+ code: z.string().min(1),
18
+ severity: RiskSeveritySchema,
19
+ message: z.string().min(1),
20
+ count: z.number().int().nonnegative().optional(),
21
+ });
22
+ // ── Per-Item Change Records ──────────────────────────────────────────
23
+ /**
24
+ * A single proposed change. `before` and `after` are arbitrary JSON
25
+ * projections of the field(s) that will mutate. `id` is a stable identifier
26
+ * for the underlying record so the per-item ledger can correlate failures
27
+ * back to the planned change.
28
+ */
29
+ export const ChangeRecordSchema = z.object({
30
+ id: z.string().min(1),
31
+ operation: z.enum(['create', 'update', 'delete']),
32
+ before: z.record(z.unknown()).nullable(),
33
+ after: z.record(z.unknown()).nullable(),
34
+ /** Tool-specific metadata copied through to the executor. */
35
+ metadata: z.record(z.unknown()).optional(),
36
+ });
37
+ // ── Plan ─────────────────────────────────────────────────────────────
38
+ /**
39
+ * The serialisable change-script produced by the `plan` phase. This is the
40
+ * single artefact that flows through the state store and into the executor.
41
+ *
42
+ * Generic over the tool-specific input shape so consumers can recover the
43
+ * original arguments at execute time without re-deriving them.
44
+ */
45
+ export const dryRunPlanSchema = (inputSchema) => z.object({
46
+ tool: z.string().min(1),
47
+ input: inputSchema,
48
+ changes: z.array(ChangeRecordSchema),
49
+ risk_flags: z.array(RiskFlagSchema),
50
+ aggregates: z.record(z.number()),
51
+ /** ISO timestamp the plan was generated. */
52
+ generated_at: z.string().datetime(),
53
+ });
54
+ // ── Preview ──────────────────────────────────────────────────────────
55
+ /**
56
+ * Tabular row produced by the preview renderer. Cells are stringified for
57
+ * deterministic display; structured data lives in `DryRunPlan.changes`.
58
+ */
59
+ export const PreviewRowSchema = z.object({
60
+ id: z.string(),
61
+ operation: z.enum(['create', 'update', 'delete']),
62
+ field: z.string(),
63
+ before: z.string(),
64
+ after: z.string(),
65
+ });
66
+ export const DryRunPreviewSchema = z.object({
67
+ rows: z.array(PreviewRowSchema),
68
+ /** Column headers in order. */
69
+ columns: z.array(z.string()),
70
+ summary: z.string().min(1),
71
+ risk_flags: z.array(RiskFlagSchema),
72
+ aggregates: z.record(z.number()),
73
+ /** True if `rows` was truncated for display. */
74
+ truncated: z.boolean(),
75
+ /** Total row count before truncation. */
76
+ total_rows: z.number().int().nonnegative(),
77
+ });
78
+ // ── Execute Result ───────────────────────────────────────────────────
79
+ export const ItemLedgerEntrySchema = z.object({
80
+ id: z.string(),
81
+ operation: z.enum(['create', 'update', 'delete']),
82
+ ok: z.boolean(),
83
+ error: McpToolErrorSchema.optional(),
84
+ /** Optional opaque result payload (e.g. updated record id). */
85
+ result: z.unknown().optional(),
86
+ });
87
+ export const ProgressEventSchema = z.object({
88
+ type: z.literal('progress'),
89
+ completed: z.number().int().nonnegative(),
90
+ total: z.number().int().nonnegative(),
91
+ /** Wall-clock timestamp for the event. */
92
+ ts: z.string().datetime(),
93
+ });
94
+ export const ExecuteResultSchema = z.object({
95
+ tool: z.string().min(1),
96
+ confirmation_id: z.string().min(1),
97
+ ledger: z.array(ItemLedgerEntrySchema),
98
+ totals: z.object({
99
+ attempted: z.number().int().nonnegative(),
100
+ succeeded: z.number().int().nonnegative(),
101
+ failed: z.number().int().nonnegative(),
102
+ }),
103
+ /** Rolled-up progress events when streaming is unavailable (HTTP transport). */
104
+ progress: z.array(ProgressEventSchema),
105
+ started_at: z.string().datetime(),
106
+ completed_at: z.string().datetime(),
107
+ });
108
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/conventions/dry-run/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import { type McpToolError } from '../errors.js';
2
+ import type { EphemeralStateStore } from '../state-store.js';
3
+ import { type ApplyFn } from './batch-executor.js';
4
+ import type { ChangeRecord, DryRunPlan, DryRunResponse, ExecuteResult, ProgressEvent, RiskFlag } from './types.js';
5
+ export interface PlanResult {
6
+ changes: ChangeRecord[];
7
+ riskFlags?: RiskFlag[];
8
+ /** Tool-specific aggregate counts merged with framework defaults. */
9
+ extraAggregates?: Record<string, number>;
10
+ }
11
+ export interface DryRunHandlerInput<TInput> {
12
+ /** Tool-specific arguments after Zod validation. */
13
+ input: TInput;
14
+ /** Optional confirmation token. When supplied, execute phase is invoked. */
15
+ confirmation_token?: string;
16
+ }
17
+ export interface WithDryRunConfig<TInput, TItemResult = unknown> {
18
+ /** Stable tool identifier (e.g. `rename_asset`). */
19
+ tool: string;
20
+ /** HMAC secret used to sign confirmation tokens. */
21
+ secret: string;
22
+ /** Ephemeral store for pending plans (5-min TTL). */
23
+ store: EphemeralStateStore<DryRunPlan<TInput>>;
24
+ /** Pure plan function — returns proposed changes without performing them. */
25
+ plan: (input: TInput) => Promise<PlanResult> | PlanResult;
26
+ /** Per-item executor invoked once per change in the execute phase. */
27
+ apply: ApplyFn<TItemResult>;
28
+ /** Override default batch size (25, capped at 500). */
29
+ chunkSize?: number;
30
+ /** Override max rendered preview rows (default 100). */
31
+ maxPreviewRows?: number;
32
+ /** Confirmation token TTL in milliseconds (default 5 minutes). */
33
+ confirmationTtlMs?: number;
34
+ /** Stream progress events (stdio transport). HTTP transport leaves this off. */
35
+ onProgress?: (event: ProgressEvent) => void;
36
+ }
37
+ export type DryRunHandler<TInput, TItemResult = unknown> = (args: DryRunHandlerInput<TInput>) => Promise<{
38
+ ok: true;
39
+ phase: 'plan';
40
+ response: DryRunResponse<TInput>;
41
+ } | {
42
+ ok: true;
43
+ phase: 'execute';
44
+ response: ExecuteResult<TItemResult>;
45
+ } | {
46
+ ok: false;
47
+ error: McpToolError;
48
+ }>;
49
+ /** Compact summary of a plan included in CONFIRMATION_STATE_DIVERGED errors. */
50
+ export interface PlanSummary {
51
+ fingerprint: string;
52
+ changes: number;
53
+ generated_at: string;
54
+ }
55
+ /**
56
+ * Build a dry-run-enforced handler from a tool-specific plan/apply pair.
57
+ *
58
+ * Behaviour:
59
+ * - With no `confirmation_token` → runs `plan`, persists it under a fresh
60
+ * HMAC ULID, returns `{ phase: 'plan', response: { plan, preview, ... } }`.
61
+ * - With a `confirmation_token` → verifies HMAC, atomically retrieves the
62
+ * plan from the store (single-use), and invokes the batch executor.
63
+ * - Stale, missing, or replayed tokens return typed `McpToolError`.
64
+ */
65
+ export declare function withDryRun<TInput, TItemResult = unknown>(config: WithDryRunConfig<TInput, TItemResult>): DryRunHandler<TInput, TItemResult>;
66
+ //# sourceMappingURL=with-dry-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-dry-run.d.ts","sourceRoot":"","sources":["../../../src/conventions/dry-run/with-dry-run.ts"],"names":[],"mappings":"AAeA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAEL,KAAK,OAAO,EAGb,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EAEV,cAAc,EACd,aAAa,EACb,aAAa,EACb,QAAQ,EACT,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,qEAAqE;IACrE,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,kBAAkB,CAAC,MAAM;IACxC,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAC7D,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/C,6EAA6E;IAC7E,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC;IAC1D,sEAAsE;IACtE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC5B,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gFAAgF;IAChF,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC7C;AAED,MAAM,MAAM,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,IAAI,CACzD,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,KAC7B,OAAO,CACR;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;CAAE,GAC7D;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAC,WAAW,CAAC,CAAA;CAAE,GACpE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,CACrC,CAAC;AAEF,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAYD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,EACtD,MAAM,EAAE,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC,GAC5C,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,CAOpC"}
@@ -0,0 +1,219 @@
1
+ // ── withDryRun() Higher-Order Wrapper ────────────────────────────────
2
+ // Wraps a mutating tool handler so every invocation is forced through the
3
+ // three phases: plan (pure), preview (rendered diff), execute (only after
4
+ // explicit confirmation token). The wrapper is the only path through which
5
+ // a mutation may reach the upstream API — concrete tools embed their domain
6
+ // logic in the `plan` and `apply` callbacks.
7
+ import { createConfirmationToken, fingerprintChanges, signConfirmation, verifyConfirmation, DEFAULT_TTL_MS, MEMO_TTL_MS, } from '../confirmation.js';
8
+ import { createToolError } from '../errors.js';
9
+ import { logger } from '../logger.js';
10
+ import { batchExecute, DEFAULT_CHUNK_SIZE, } from './batch-executor.js';
11
+ import { renderDiff, DEFAULT_MAX_PREVIEW_ROWS } from './diff-renderer.js';
12
+ import { buildSummary, computeAggregates } from './summary.js';
13
+ function summarisePlan(plan) {
14
+ return {
15
+ fingerprint: plan.fingerprint,
16
+ changes: plan.changes.length,
17
+ generated_at: plan.generated_at,
18
+ };
19
+ }
20
+ // ── Wrapper ──────────────────────────────────────────────────────────
21
+ /**
22
+ * Build a dry-run-enforced handler from a tool-specific plan/apply pair.
23
+ *
24
+ * Behaviour:
25
+ * - With no `confirmation_token` → runs `plan`, persists it under a fresh
26
+ * HMAC ULID, returns `{ phase: 'plan', response: { plan, preview, ... } }`.
27
+ * - With a `confirmation_token` → verifies HMAC, atomically retrieves the
28
+ * plan from the store (single-use), and invokes the batch executor.
29
+ * - Stale, missing, or replayed tokens return typed `McpToolError`.
30
+ */
31
+ export function withDryRun(config) {
32
+ return async ({ input, confirmation_token }) => {
33
+ if (confirmation_token === undefined || confirmation_token === '') {
34
+ return runPlanPhase(config, input);
35
+ }
36
+ return runExecutePhase(config, confirmation_token, input);
37
+ };
38
+ }
39
+ // ── Plan Phase ───────────────────────────────────────────────────────
40
+ async function runPlanPhase(config, input) {
41
+ let planResult;
42
+ try {
43
+ planResult = await config.plan(input);
44
+ }
45
+ catch (err) {
46
+ const message = err instanceof Error ? err.message : String(err);
47
+ return {
48
+ ok: false,
49
+ error: createToolError('INTERNAL', `plan() failed: ${message}`),
50
+ };
51
+ }
52
+ const aggregates = computeAggregates(planResult.changes, planResult.extraAggregates ?? {});
53
+ const riskFlags = planResult.riskFlags ?? [];
54
+ // Soft TTL on the token (visible to the caller in `expires_at`); long
55
+ // memo TTL on the plan record so an expired-token execute can recover
56
+ // the prior fingerprint and auto-refresh.
57
+ const tokenTtlMs = config.confirmationTtlMs ?? DEFAULT_TTL_MS;
58
+ const token = createConfirmationToken(config.secret, tokenTtlMs);
59
+ const plan = {
60
+ tool: config.tool,
61
+ input,
62
+ changes: planResult.changes,
63
+ risk_flags: riskFlags,
64
+ aggregates,
65
+ generated_at: new Date().toISOString(),
66
+ fingerprint: fingerprintChanges(planResult.changes),
67
+ token_expires_at: token.expires_at,
68
+ };
69
+ const diff = renderDiff(plan.changes, {
70
+ maxRows: config.maxPreviewRows ?? DEFAULT_MAX_PREVIEW_ROWS,
71
+ });
72
+ const { summary } = buildSummary({
73
+ tool: config.tool,
74
+ changes: plan.changes,
75
+ riskFlags,
76
+ aggregates,
77
+ });
78
+ const preview = {
79
+ rows: diff.rows,
80
+ columns: diff.columns,
81
+ summary,
82
+ risk_flags: riskFlags,
83
+ aggregates,
84
+ truncated: diff.truncated,
85
+ total_rows: diff.total_rows,
86
+ };
87
+ await config.store.set(token.confirmation_id, plan, MEMO_TTL_MS);
88
+ return {
89
+ ok: true,
90
+ phase: 'plan',
91
+ response: {
92
+ dry_run: true,
93
+ plan,
94
+ preview,
95
+ confirmation: token,
96
+ },
97
+ };
98
+ }
99
+ // ── Execute Phase ────────────────────────────────────────────────────
100
+ async function runExecutePhase(config, signedToken, input) {
101
+ const { valid, confirmationId } = verifyConfirmation(signedToken, config.secret);
102
+ if (!valid || confirmationId === null) {
103
+ return {
104
+ ok: false,
105
+ error: createToolError('CONFIRMATION_MISSING', 'Confirmation token is invalid or could not be verified.'),
106
+ };
107
+ }
108
+ // Atomically pop the plan from the memo store. If absent, the memo TTL
109
+ // (1h by default) has elapsed — true hard expiry.
110
+ const priorPlan = await config.store.getAndDelete(confirmationId);
111
+ if (priorPlan === undefined) {
112
+ return {
113
+ ok: false,
114
+ error: createToolError('CONFIRMATION_STALE', 'Confirmation token is expired or has already been used.'),
115
+ };
116
+ }
117
+ if (priorPlan.tool !== config.tool) {
118
+ // Cross-tool token reuse — possible only if state stores are shared.
119
+ return {
120
+ ok: false,
121
+ error: createToolError('CONFIRMATION_STALE', `Confirmation token belongs to tool '${priorPlan.tool}', not '${config.tool}'.`),
122
+ };
123
+ }
124
+ // Soft expiry check: if the token's `expires_at` has passed, run the
125
+ // auto-refresh path before consuming the plan. Re-plan from the user's
126
+ // input, fingerprint the result, and compare against the prior
127
+ // fingerprint. Match → continue with the prior plan (intent unchanged).
128
+ // Mismatch → return CONFIRMATION_STATE_DIVERGED so the user can re-confirm.
129
+ let plan = priorPlan;
130
+ const nowMs = Date.now();
131
+ const softExpiryMs = Date.parse(priorPlan.token_expires_at);
132
+ if (Number.isFinite(softExpiryMs) && nowMs > softExpiryMs) {
133
+ let refreshed;
134
+ try {
135
+ refreshed = await config.plan(input);
136
+ }
137
+ catch (err) {
138
+ const message = err instanceof Error ? err.message : String(err);
139
+ return {
140
+ ok: false,
141
+ error: createToolError('INTERNAL', `auto-refresh plan() failed: ${message}`),
142
+ };
143
+ }
144
+ const newFingerprint = fingerprintChanges(refreshed.changes);
145
+ if (newFingerprint === priorPlan.fingerprint) {
146
+ const newToken = signConfirmation(confirmationId, config.secret);
147
+ logger.info({
148
+ tool: config.tool,
149
+ confirmation_id: confirmationId,
150
+ prior_token_id: signedToken.slice(0, 8) + '…',
151
+ new_token_id: newToken.slice(0, 8) + '…',
152
+ fingerprint: priorPlan.fingerprint,
153
+ }, 'dry_run.auto_refresh');
154
+ // Continue with the prior plan; the user already confirmed it.
155
+ }
156
+ else {
157
+ const newAggregates = computeAggregates(refreshed.changes, refreshed.extraAggregates ?? {});
158
+ const newPlan = {
159
+ tool: config.tool,
160
+ input,
161
+ changes: refreshed.changes,
162
+ risk_flags: refreshed.riskFlags ?? [],
163
+ aggregates: newAggregates,
164
+ generated_at: new Date().toISOString(),
165
+ fingerprint: newFingerprint,
166
+ token_expires_at: priorPlan.token_expires_at,
167
+ };
168
+ logger.warn({
169
+ tool: config.tool,
170
+ confirmation_id: confirmationId,
171
+ prior_fingerprint: priorPlan.fingerprint,
172
+ new_fingerprint: newFingerprint,
173
+ }, 'dry_run.state_diverged');
174
+ return {
175
+ ok: false,
176
+ error: createToolError('CONFIRMATION_STATE_DIVERGED', `The plan you confirmed no longer matches the current workspace state. Re-run the preview to see what changed.`, {
177
+ cause: {
178
+ prior_plan: summarisePlan(priorPlan),
179
+ new_plan: summarisePlan(newPlan),
180
+ },
181
+ }),
182
+ };
183
+ }
184
+ }
185
+ const startedAt = new Date().toISOString();
186
+ let batch;
187
+ try {
188
+ const batchOpts = {
189
+ changes: plan.changes,
190
+ apply: config.apply,
191
+ chunkSize: config.chunkSize ?? DEFAULT_CHUNK_SIZE,
192
+ };
193
+ if (config.onProgress)
194
+ batchOpts.onProgress = config.onProgress;
195
+ batch = await batchExecute(batchOpts);
196
+ }
197
+ catch (err) {
198
+ const message = err instanceof Error ? err.message : String(err);
199
+ return {
200
+ ok: false,
201
+ error: createToolError('INTERNAL', `batch executor failed: ${message}`),
202
+ };
203
+ }
204
+ const completedAt = new Date().toISOString();
205
+ return {
206
+ ok: true,
207
+ phase: 'execute',
208
+ response: {
209
+ tool: config.tool,
210
+ confirmation_id: confirmationId,
211
+ ledger: batch.ledger,
212
+ totals: batch.totals,
213
+ progress: batch.progress,
214
+ started_at: startedAt,
215
+ completed_at: completedAt,
216
+ },
217
+ };
218
+ }
219
+ //# sourceMappingURL=with-dry-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-dry-run.js","sourceRoot":"","sources":["../../../src/conventions/dry-run/with-dry-run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Read a required environment variable. Throws a descriptive error if the
4
+ * variable is missing or empty.
5
+ */
6
+ export declare function getRequiredEnv(name: string): string;
7
+ /**
8
+ * Read an optional environment variable, returning `defaultValue` when the
9
+ * variable is missing or empty.
10
+ */
11
+ export declare function getOptionalEnv(name: string, defaultValue: string): string;
12
+ declare const ConfigSchema: z.ZodObject<{
13
+ collageApiKey: z.ZodString;
14
+ collageWorkspaceId: z.ZodString;
15
+ collageApiUrl: z.ZodString;
16
+ collageSearchBase: z.ZodString;
17
+ confirmationSecret: z.ZodString;
18
+ maxRps: z.ZodNumber;
19
+ redisUrl: z.ZodOptional<z.ZodString>;
20
+ logLevel: z.ZodEnum<["debug", "info", "warn", "error"]>;
21
+ }, "strip", z.ZodTypeAny, {
22
+ collageApiKey: string;
23
+ collageWorkspaceId: string;
24
+ collageApiUrl: string;
25
+ collageSearchBase: string;
26
+ confirmationSecret: string;
27
+ maxRps: number;
28
+ logLevel: "debug" | "info" | "warn" | "error";
29
+ redisUrl?: string | undefined;
30
+ }, {
31
+ collageApiKey: string;
32
+ collageWorkspaceId: string;
33
+ collageApiUrl: string;
34
+ collageSearchBase: string;
35
+ confirmationSecret: string;
36
+ maxRps: number;
37
+ logLevel: "debug" | "info" | "warn" | "error";
38
+ redisUrl?: string | undefined;
39
+ }>;
40
+ export type AppConfig = z.infer<typeof ConfigSchema>;
41
+ /**
42
+ * Load and validate the full application config from environment variables.
43
+ *
44
+ * Secret fields are redacted in `toJSON()` / `toString()` to prevent
45
+ * accidental leakage in logs or error messages.
46
+ */
47
+ export declare function loadConfig(): AppConfig;
48
+ export {};
49
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/conventions/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASnD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAMzE;AAID,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;EAShB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AA4BrD;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,SAAS,CA2BtC"}
@@ -0,0 +1,84 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Read a required environment variable. Throws a descriptive error if the
4
+ * variable is missing or empty.
5
+ */
6
+ export function getRequiredEnv(name) {
7
+ const value = process.env[name];
8
+ if (value === undefined || value === '') {
9
+ throw new Error(`Missing required environment variable: ${name}. ` +
10
+ `Set it in your .env file or export it before starting the server.`);
11
+ }
12
+ return value;
13
+ }
14
+ /**
15
+ * Read an optional environment variable, returning `defaultValue` when the
16
+ * variable is missing or empty.
17
+ */
18
+ export function getOptionalEnv(name, defaultValue) {
19
+ const value = process.env[name];
20
+ if (value === undefined || value === '') {
21
+ return defaultValue;
22
+ }
23
+ return value;
24
+ }
25
+ const LogLevelSchema = z.enum(['debug', 'info', 'warn', 'error']);
26
+ const ConfigSchema = z.object({
27
+ collageApiKey: z.string().min(1),
28
+ collageWorkspaceId: z.string().min(1),
29
+ collageApiUrl: z.string().url(),
30
+ collageSearchBase: z.string().url(),
31
+ confirmationSecret: z.string().min(1),
32
+ maxRps: z.number().int().positive(),
33
+ redisUrl: z.string().optional(),
34
+ logLevel: LogLevelSchema,
35
+ });
36
+ /** Fields whose values must never appear in serialised output. */
37
+ const SECRET_FIELDS = new Set([
38
+ 'collageApiKey',
39
+ 'confirmationSecret',
40
+ ]);
41
+ /**
42
+ * Build a config object that redacts secrets from `toJSON()` and
43
+ * `toString()` so they never leak into logs or error messages.
44
+ */
45
+ function withRedaction(config) {
46
+ const redactedJson = {};
47
+ for (const [key, value] of Object.entries(config)) {
48
+ redactedJson[key] = SECRET_FIELDS.has(key) ? '[REDACTED]' : value;
49
+ }
50
+ return Object.assign(Object.create(null), config, {
51
+ toJSON() {
52
+ return { ...redactedJson };
53
+ },
54
+ toString() {
55
+ return JSON.stringify(redactedJson);
56
+ },
57
+ });
58
+ }
59
+ /**
60
+ * Load and validate the full application config from environment variables.
61
+ *
62
+ * Secret fields are redacted in `toJSON()` / `toString()` to prevent
63
+ * accidental leakage in logs or error messages.
64
+ */
65
+ export function loadConfig() {
66
+ const raw = {
67
+ collageApiKey: getRequiredEnv('COLLAGE_API_KEY'),
68
+ collageWorkspaceId: getRequiredEnv('COLLAGE_WORKSPACE_ID'),
69
+ collageApiUrl: getOptionalEnv('COLLAGE_API_URL', 'https://damapi.collage.inc/api/v1/'),
70
+ collageSearchBase: getOptionalEnv('COLLAGE_SEARCH_BASE', 'https://app.collage.inc'),
71
+ confirmationSecret: getRequiredEnv('MCP_CONFIRMATION_SECRET'),
72
+ maxRps: Number(getOptionalEnv('COLLAGE_MAX_RPS', '10')),
73
+ redisUrl: process.env['REDIS_URL'] || undefined,
74
+ logLevel: getOptionalEnv('LOG_LEVEL', 'info'),
75
+ };
76
+ const validated = ConfigSchema.parse(raw);
77
+ if (validated.confirmationSecret.length < 32) {
78
+ process.stderr.write('WARN: MCP_CONFIRMATION_SECRET is shorter than 32 characters. ' +
79
+ 'Use at least 32 high-entropy bytes (e.g. `openssl rand -hex 32`) ' +
80
+ 'so HMAC tokens are not feasibly forgeable.\n');
81
+ }
82
+ return withRedaction(validated);
83
+ }
84
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/conventions/env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import { z } from 'zod';
2
+ export declare const ErrorCodeSchema: z.ZodEnum<["UNAUTHORIZED", "FORBIDDEN", "NOT_FOUND", "VALIDATION", "RATE_LIMITED", "UPSTREAM", "CONFIRMATION_STALE", "CONFIRMATION_MISSING", "CONFIRMATION_STATE_DIVERGED", "ENTITLEMENT", "INTERNAL"]>;
3
+ export type ErrorCode = z.infer<typeof ErrorCodeSchema>;
4
+ export declare const McpToolErrorCauseSchema: z.ZodObject<{
5
+ upstream_status: z.ZodOptional<z.ZodNumber>;
6
+ request_id: z.ZodOptional<z.ZodString>;
7
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
8
+ upstream_status: z.ZodOptional<z.ZodNumber>;
9
+ request_id: z.ZodOptional<z.ZodString>;
10
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
11
+ upstream_status: z.ZodOptional<z.ZodNumber>;
12
+ request_id: z.ZodOptional<z.ZodString>;
13
+ }, z.ZodTypeAny, "passthrough">>;
14
+ export declare const McpToolErrorSchema: z.ZodObject<{
15
+ code: z.ZodEnum<["UNAUTHORIZED", "FORBIDDEN", "NOT_FOUND", "VALIDATION", "RATE_LIMITED", "UPSTREAM", "CONFIRMATION_STALE", "CONFIRMATION_MISSING", "CONFIRMATION_STATE_DIVERGED", "ENTITLEMENT", "INTERNAL"]>;
16
+ message: z.ZodString;
17
+ retriable: z.ZodBoolean;
18
+ cause: z.ZodOptional<z.ZodObject<{
19
+ upstream_status: z.ZodOptional<z.ZodNumber>;
20
+ request_id: z.ZodOptional<z.ZodString>;
21
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
22
+ upstream_status: z.ZodOptional<z.ZodNumber>;
23
+ request_id: z.ZodOptional<z.ZodString>;
24
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
25
+ upstream_status: z.ZodOptional<z.ZodNumber>;
26
+ request_id: z.ZodOptional<z.ZodString>;
27
+ }, z.ZodTypeAny, "passthrough">>>;
28
+ }, "strip", z.ZodTypeAny, {
29
+ code: "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "VALIDATION" | "RATE_LIMITED" | "UPSTREAM" | "CONFIRMATION_STALE" | "CONFIRMATION_MISSING" | "CONFIRMATION_STATE_DIVERGED" | "ENTITLEMENT" | "INTERNAL";
30
+ message: string;
31
+ retriable: boolean;
32
+ cause?: z.objectOutputType<{
33
+ upstream_status: z.ZodOptional<z.ZodNumber>;
34
+ request_id: z.ZodOptional<z.ZodString>;
35
+ }, z.ZodTypeAny, "passthrough"> | undefined;
36
+ }, {
37
+ code: "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "VALIDATION" | "RATE_LIMITED" | "UPSTREAM" | "CONFIRMATION_STALE" | "CONFIRMATION_MISSING" | "CONFIRMATION_STATE_DIVERGED" | "ENTITLEMENT" | "INTERNAL";
38
+ message: string;
39
+ retriable: boolean;
40
+ cause?: z.objectInputType<{
41
+ upstream_status: z.ZodOptional<z.ZodNumber>;
42
+ request_id: z.ZodOptional<z.ZodString>;
43
+ }, z.ZodTypeAny, "passthrough"> | undefined;
44
+ }>;
45
+ export type McpToolError = z.infer<typeof McpToolErrorSchema>;
46
+ /**
47
+ * Returns whether the given error code is retriable by default.
48
+ */
49
+ export declare function isRetriable(code: ErrorCode): boolean;
50
+ interface CreateToolErrorOpts {
51
+ retriable?: boolean;
52
+ cause?: {
53
+ upstream_status?: number;
54
+ request_id?: string;
55
+ [key: string]: unknown;
56
+ };
57
+ }
58
+ /**
59
+ * Create a validated McpToolError.
60
+ * If `retriable` is not provided, it defaults based on the error code.
61
+ */
62
+ export declare function createToolError(code: ErrorCode, message: string, opts?: CreateToolErrorOpts): McpToolError;
63
+ /**
64
+ * Map an HTTP status code to the corresponding McpToolError code.
65
+ */
66
+ export declare function mapHttpStatusToErrorCode(status: number): ErrorCode;
67
+ export {};
68
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/conventions/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA4BxB,eAAO,MAAM,eAAe,yMAAsB,CAAC;AACnD,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,eAAO,MAAM,uBAAuB;;;;;;;;;gCAKpB,CAAC;AAEjB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAEpD;AAED,UAAU,mBAAmB;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE;QACN,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;CACH;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,mBAAmB,GACzB,YAAY,CAQd;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAmBlE"}