@withpica/mcp-server 1.3.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 (347) hide show
  1. package/.claude/settings.local.json +5 -0
  2. package/CHANGELOG.md +1850 -0
  3. package/README.md +304 -0
  4. package/assets/fonts/GeistSans-Light.woff2 +0 -0
  5. package/assets/fonts/InstrumentSerif-Italic.woff2 +0 -0
  6. package/assets/fonts/InstrumentSerif-Regular.woff2 +0 -0
  7. package/dist/apps/download.d.ts +2 -0
  8. package/dist/apps/download.d.ts.map +1 -0
  9. package/dist/apps/download.js +125 -0
  10. package/dist/apps/download.js.map +1 -0
  11. package/dist/apps/generated/shared-bundle.d.ts +5 -0
  12. package/dist/apps/generated/shared-bundle.d.ts.map +1 -0
  13. package/dist/apps/generated/shared-bundle.js +7 -0
  14. package/dist/apps/generated/shared-bundle.js.map +1 -0
  15. package/dist/apps/release.d.ts +2 -0
  16. package/dist/apps/release.d.ts.map +1 -0
  17. package/dist/apps/release.js +69 -0
  18. package/dist/apps/release.js.map +1 -0
  19. package/dist/apps/shared.d.ts +15 -0
  20. package/dist/apps/shared.d.ts.map +1 -0
  21. package/dist/apps/shared.js +480 -0
  22. package/dist/apps/shared.js.map +1 -0
  23. package/dist/apps/upload.d.ts +2 -0
  24. package/dist/apps/upload.d.ts.map +1 -0
  25. package/dist/apps/upload.js +280 -0
  26. package/dist/apps/upload.js.map +1 -0
  27. package/dist/config.d.ts +14 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +73 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/index.d.ts +3 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +35 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/prompts/index.d.ts +86 -0
  36. package/dist/prompts/index.d.ts.map +1 -0
  37. package/dist/prompts/index.js +645 -0
  38. package/dist/prompts/index.js.map +1 -0
  39. package/dist/resources/agent-guide.d.ts +15 -0
  40. package/dist/resources/agent-guide.d.ts.map +1 -0
  41. package/dist/resources/agent-guide.js +284 -0
  42. package/dist/resources/agent-guide.js.map +1 -0
  43. package/dist/resources/index.d.ts +66 -0
  44. package/dist/resources/index.d.ts.map +1 -0
  45. package/dist/resources/index.js +510 -0
  46. package/dist/resources/index.js.map +1 -0
  47. package/dist/resources/llms-primer.d.ts +2 -0
  48. package/dist/resources/llms-primer.d.ts.map +1 -0
  49. package/dist/resources/llms-primer.js +68 -0
  50. package/dist/resources/llms-primer.js.map +1 -0
  51. package/dist/resources/required-schemas.generated.d.ts +455 -0
  52. package/dist/resources/required-schemas.generated.d.ts.map +1 -0
  53. package/dist/resources/required-schemas.generated.js +1041 -0
  54. package/dist/resources/required-schemas.generated.js.map +1 -0
  55. package/dist/resources/required-schemas.source.d.ts +53 -0
  56. package/dist/resources/required-schemas.source.d.ts.map +1 -0
  57. package/dist/resources/required-schemas.source.js +493 -0
  58. package/dist/resources/required-schemas.source.js.map +1 -0
  59. package/dist/resources/welcome.d.ts +14 -0
  60. package/dist/resources/welcome.d.ts.map +1 -0
  61. package/dist/resources/welcome.js +26 -0
  62. package/dist/resources/welcome.js.map +1 -0
  63. package/dist/server-instructions.d.ts +60 -0
  64. package/dist/server-instructions.d.ts.map +1 -0
  65. package/dist/server-instructions.js +93 -0
  66. package/dist/server-instructions.js.map +1 -0
  67. package/dist/server.d.ts +52 -0
  68. package/dist/server.d.ts.map +1 -0
  69. package/dist/server.js +334 -0
  70. package/dist/server.js.map +1 -0
  71. package/dist/tools/access-simulate.d.ts +23 -0
  72. package/dist/tools/access-simulate.d.ts.map +1 -0
  73. package/dist/tools/access-simulate.js +162 -0
  74. package/dist/tools/access-simulate.js.map +1 -0
  75. package/dist/tools/agent-identity.d.ts +36 -0
  76. package/dist/tools/agent-identity.d.ts.map +1 -0
  77. package/dist/tools/agent-identity.js +274 -0
  78. package/dist/tools/agent-identity.js.map +1 -0
  79. package/dist/tools/agreement-types.d.ts +27 -0
  80. package/dist/tools/agreement-types.d.ts.map +1 -0
  81. package/dist/tools/agreement-types.js +281 -0
  82. package/dist/tools/agreement-types.js.map +1 -0
  83. package/dist/tools/agreements.d.ts +20 -0
  84. package/dist/tools/agreements.d.ts.map +1 -0
  85. package/dist/tools/agreements.js +282 -0
  86. package/dist/tools/agreements.js.map +1 -0
  87. package/dist/tools/analytics.d.ts +20 -0
  88. package/dist/tools/analytics.d.ts.map +1 -0
  89. package/dist/tools/analytics.js +130 -0
  90. package/dist/tools/analytics.js.map +1 -0
  91. package/dist/tools/app-tools.d.ts +15 -0
  92. package/dist/tools/app-tools.d.ts.map +1 -0
  93. package/dist/tools/app-tools.js +388 -0
  94. package/dist/tools/app-tools.js.map +1 -0
  95. package/dist/tools/assets.d.ts +25 -0
  96. package/dist/tools/assets.d.ts.map +1 -0
  97. package/dist/tools/assets.js +454 -0
  98. package/dist/tools/assets.js.map +1 -0
  99. package/dist/tools/audio-files.d.ts +20 -0
  100. package/dist/tools/audio-files.d.ts.map +1 -0
  101. package/dist/tools/audio-files.js +409 -0
  102. package/dist/tools/audio-files.js.map +1 -0
  103. package/dist/tools/audit.d.ts +19 -0
  104. package/dist/tools/audit.d.ts.map +1 -0
  105. package/dist/tools/audit.js +58 -0
  106. package/dist/tools/audit.js.map +1 -0
  107. package/dist/tools/auth.d.ts +22 -0
  108. package/dist/tools/auth.d.ts.map +1 -0
  109. package/dist/tools/auth.js +212 -0
  110. package/dist/tools/auth.js.map +1 -0
  111. package/dist/tools/bulk.d.ts +22 -0
  112. package/dist/tools/bulk.d.ts.map +1 -0
  113. package/dist/tools/bulk.js +164 -0
  114. package/dist/tools/bulk.js.map +1 -0
  115. package/dist/tools/calendar.d.ts +15 -0
  116. package/dist/tools/calendar.d.ts.map +1 -0
  117. package/dist/tools/calendar.js +68 -0
  118. package/dist/tools/calendar.js.map +1 -0
  119. package/dist/tools/collaborators.d.ts +21 -0
  120. package/dist/tools/collaborators.d.ts.map +1 -0
  121. package/dist/tools/collaborators.js +381 -0
  122. package/dist/tools/collaborators.js.map +1 -0
  123. package/dist/tools/comparisons.d.ts +22 -0
  124. package/dist/tools/comparisons.d.ts.map +1 -0
  125. package/dist/tools/comparisons.js +80 -0
  126. package/dist/tools/comparisons.js.map +1 -0
  127. package/dist/tools/credits.d.ts +39 -0
  128. package/dist/tools/credits.d.ts.map +1 -0
  129. package/dist/tools/credits.js +541 -0
  130. package/dist/tools/credits.js.map +1 -0
  131. package/dist/tools/custody-hints.d.ts +16 -0
  132. package/dist/tools/custody-hints.d.ts.map +1 -0
  133. package/dist/tools/custody-hints.js +27 -0
  134. package/dist/tools/custody-hints.js.map +1 -0
  135. package/dist/tools/custody.d.ts +38 -0
  136. package/dist/tools/custody.d.ts.map +1 -0
  137. package/dist/tools/custody.js +281 -0
  138. package/dist/tools/custody.js.map +1 -0
  139. package/dist/tools/dashboard.d.ts +22 -0
  140. package/dist/tools/dashboard.d.ts.map +1 -0
  141. package/dist/tools/dashboard.js +258 -0
  142. package/dist/tools/dashboard.js.map +1 -0
  143. package/dist/tools/directory.d.ts +15 -0
  144. package/dist/tools/directory.d.ts.map +1 -0
  145. package/dist/tools/directory.js +107 -0
  146. package/dist/tools/directory.js.map +1 -0
  147. package/dist/tools/discovery.d.ts +49 -0
  148. package/dist/tools/discovery.d.ts.map +1 -0
  149. package/dist/tools/discovery.js +851 -0
  150. package/dist/tools/discovery.js.map +1 -0
  151. package/dist/tools/disputes.d.ts +18 -0
  152. package/dist/tools/disputes.d.ts.map +1 -0
  153. package/dist/tools/disputes.js +62 -0
  154. package/dist/tools/disputes.js.map +1 -0
  155. package/dist/tools/documents.d.ts +15 -0
  156. package/dist/tools/documents.d.ts.map +1 -0
  157. package/dist/tools/documents.js +37 -0
  158. package/dist/tools/documents.js.map +1 -0
  159. package/dist/tools/duplicates.d.ts +25 -0
  160. package/dist/tools/duplicates.d.ts.map +1 -0
  161. package/dist/tools/duplicates.js +108 -0
  162. package/dist/tools/duplicates.js.map +1 -0
  163. package/dist/tools/enrichment.d.ts +56 -0
  164. package/dist/tools/enrichment.d.ts.map +1 -0
  165. package/dist/tools/enrichment.js +616 -0
  166. package/dist/tools/enrichment.js.map +1 -0
  167. package/dist/tools/exports.d.ts +19 -0
  168. package/dist/tools/exports.d.ts.map +1 -0
  169. package/dist/tools/exports.js +184 -0
  170. package/dist/tools/exports.js.map +1 -0
  171. package/dist/tools/feedback.d.ts +22 -0
  172. package/dist/tools/feedback.d.ts.map +1 -0
  173. package/dist/tools/feedback.js +100 -0
  174. package/dist/tools/feedback.js.map +1 -0
  175. package/dist/tools/forbidden-keywords.d.ts +62 -0
  176. package/dist/tools/forbidden-keywords.d.ts.map +1 -0
  177. package/dist/tools/forbidden-keywords.js +99 -0
  178. package/dist/tools/forbidden-keywords.js.map +1 -0
  179. package/dist/tools/gap-hints.d.ts +53 -0
  180. package/dist/tools/gap-hints.d.ts.map +1 -0
  181. package/dist/tools/gap-hints.js +245 -0
  182. package/dist/tools/gap-hints.js.map +1 -0
  183. package/dist/tools/groups.d.ts +29 -0
  184. package/dist/tools/groups.d.ts.map +1 -0
  185. package/dist/tools/groups.js +186 -0
  186. package/dist/tools/groups.js.map +1 -0
  187. package/dist/tools/import-documents.d.ts +21 -0
  188. package/dist/tools/import-documents.d.ts.map +1 -0
  189. package/dist/tools/import-documents.js +206 -0
  190. package/dist/tools/import-documents.js.map +1 -0
  191. package/dist/tools/import.d.ts +31 -0
  192. package/dist/tools/import.d.ts.map +1 -0
  193. package/dist/tools/import.js +610 -0
  194. package/dist/tools/import.js.map +1 -0
  195. package/dist/tools/index.d.ts +293 -0
  196. package/dist/tools/index.d.ts.map +1 -0
  197. package/dist/tools/index.js +1182 -0
  198. package/dist/tools/index.js.map +1 -0
  199. package/dist/tools/integrations.d.ts +19 -0
  200. package/dist/tools/integrations.d.ts.map +1 -0
  201. package/dist/tools/integrations.js +120 -0
  202. package/dist/tools/integrations.js.map +1 -0
  203. package/dist/tools/labels.d.ts +20 -0
  204. package/dist/tools/labels.d.ts.map +1 -0
  205. package/dist/tools/labels.js +48 -0
  206. package/dist/tools/labels.js.map +1 -0
  207. package/dist/tools/licensing.d.ts +40 -0
  208. package/dist/tools/licensing.d.ts.map +1 -0
  209. package/dist/tools/licensing.js +436 -0
  210. package/dist/tools/licensing.js.map +1 -0
  211. package/dist/tools/memory.d.ts +21 -0
  212. package/dist/tools/memory.d.ts.map +1 -0
  213. package/dist/tools/memory.js +120 -0
  214. package/dist/tools/memory.js.map +1 -0
  215. package/dist/tools/metadata.d.ts +15 -0
  216. package/dist/tools/metadata.d.ts.map +1 -0
  217. package/dist/tools/metadata.js +1532 -0
  218. package/dist/tools/metadata.js.map +1 -0
  219. package/dist/tools/multimedia.d.ts +19 -0
  220. package/dist/tools/multimedia.d.ts.map +1 -0
  221. package/dist/tools/multimedia.js +371 -0
  222. package/dist/tools/multimedia.js.map +1 -0
  223. package/dist/tools/my-reported-issues.d.ts +32 -0
  224. package/dist/tools/my-reported-issues.d.ts.map +1 -0
  225. package/dist/tools/my-reported-issues.js +123 -0
  226. package/dist/tools/my-reported-issues.js.map +1 -0
  227. package/dist/tools/notes.d.ts +21 -0
  228. package/dist/tools/notes.d.ts.map +1 -0
  229. package/dist/tools/notes.js +115 -0
  230. package/dist/tools/notes.js.map +1 -0
  231. package/dist/tools/notifications.d.ts +28 -0
  232. package/dist/tools/notifications.d.ts.map +1 -0
  233. package/dist/tools/notifications.js +417 -0
  234. package/dist/tools/notifications.js.map +1 -0
  235. package/dist/tools/onboarding.d.ts +24 -0
  236. package/dist/tools/onboarding.d.ts.map +1 -0
  237. package/dist/tools/onboarding.js +81 -0
  238. package/dist/tools/onboarding.js.map +1 -0
  239. package/dist/tools/people.d.ts +254 -0
  240. package/dist/tools/people.d.ts.map +1 -0
  241. package/dist/tools/people.js +481 -0
  242. package/dist/tools/people.js.map +1 -0
  243. package/dist/tools/projects.d.ts +20 -0
  244. package/dist/tools/projects.d.ts.map +1 -0
  245. package/dist/tools/projects.js +316 -0
  246. package/dist/tools/projects.js.map +1 -0
  247. package/dist/tools/public-filter.d.ts +43 -0
  248. package/dist/tools/public-filter.d.ts.map +1 -0
  249. package/dist/tools/public-filter.js +356 -0
  250. package/dist/tools/public-filter.js.map +1 -0
  251. package/dist/tools/publishers.d.ts +30 -0
  252. package/dist/tools/publishers.d.ts.map +1 -0
  253. package/dist/tools/publishers.js +105 -0
  254. package/dist/tools/publishers.js.map +1 -0
  255. package/dist/tools/purchases.d.ts +27 -0
  256. package/dist/tools/purchases.d.ts.map +1 -0
  257. package/dist/tools/purchases.js +9 -0
  258. package/dist/tools/purchases.js.map +1 -0
  259. package/dist/tools/recording-attribution-hints.d.ts +24 -0
  260. package/dist/tools/recording-attribution-hints.d.ts.map +1 -0
  261. package/dist/tools/recording-attribution-hints.js +27 -0
  262. package/dist/tools/recording-attribution-hints.js.map +1 -0
  263. package/dist/tools/recordings.d.ts +96 -0
  264. package/dist/tools/recordings.d.ts.map +1 -0
  265. package/dist/tools/recordings.js +564 -0
  266. package/dist/tools/recordings.js.map +1 -0
  267. package/dist/tools/recovery-hints.d.ts +40 -0
  268. package/dist/tools/recovery-hints.d.ts.map +1 -0
  269. package/dist/tools/recovery-hints.js +827 -0
  270. package/dist/tools/recovery-hints.js.map +1 -0
  271. package/dist/tools/release-rich.d.ts +31 -0
  272. package/dist/tools/release-rich.d.ts.map +1 -0
  273. package/dist/tools/release-rich.js +245 -0
  274. package/dist/tools/release-rich.js.map +1 -0
  275. package/dist/tools/releases.d.ts +36 -0
  276. package/dist/tools/releases.d.ts.map +1 -0
  277. package/dist/tools/releases.js +649 -0
  278. package/dist/tools/releases.js.map +1 -0
  279. package/dist/tools/report-issue.d.ts +21 -0
  280. package/dist/tools/report-issue.d.ts.map +1 -0
  281. package/dist/tools/report-issue.js +101 -0
  282. package/dist/tools/report-issue.js.map +1 -0
  283. package/dist/tools/royalties.d.ts +23 -0
  284. package/dist/tools/royalties.d.ts.map +1 -0
  285. package/dist/tools/royalties.js +262 -0
  286. package/dist/tools/royalties.js.map +1 -0
  287. package/dist/tools/search.d.ts +30 -0
  288. package/dist/tools/search.d.ts.map +1 -0
  289. package/dist/tools/search.js +115 -0
  290. package/dist/tools/search.js.map +1 -0
  291. package/dist/tools/send.d.ts +17 -0
  292. package/dist/tools/send.d.ts.map +1 -0
  293. package/dist/tools/send.js +188 -0
  294. package/dist/tools/send.js.map +1 -0
  295. package/dist/tools/sessions.d.ts +18 -0
  296. package/dist/tools/sessions.d.ts.map +1 -0
  297. package/dist/tools/sessions.js +153 -0
  298. package/dist/tools/sessions.js.map +1 -0
  299. package/dist/tools/settings.d.ts +23 -0
  300. package/dist/tools/settings.d.ts.map +1 -0
  301. package/dist/tools/settings.js +365 -0
  302. package/dist/tools/settings.js.map +1 -0
  303. package/dist/tools/share-links.d.ts +22 -0
  304. package/dist/tools/share-links.d.ts.map +1 -0
  305. package/dist/tools/share-links.js +188 -0
  306. package/dist/tools/share-links.js.map +1 -0
  307. package/dist/tools/signup.d.ts +26 -0
  308. package/dist/tools/signup.d.ts.map +1 -0
  309. package/dist/tools/signup.js +266 -0
  310. package/dist/tools/signup.js.map +1 -0
  311. package/dist/tools/split-sheets.d.ts +25 -0
  312. package/dist/tools/split-sheets.d.ts.map +1 -0
  313. package/dist/tools/split-sheets.js +309 -0
  314. package/dist/tools/split-sheets.js.map +1 -0
  315. package/dist/tools/storage-config.d.ts +13 -0
  316. package/dist/tools/storage-config.d.ts.map +1 -0
  317. package/dist/tools/storage-config.js +245 -0
  318. package/dist/tools/storage-config.js.map +1 -0
  319. package/dist/tools/subscription.d.ts +60 -0
  320. package/dist/tools/subscription.d.ts.map +1 -0
  321. package/dist/tools/subscription.js +440 -0
  322. package/dist/tools/subscription.js.map +1 -0
  323. package/dist/tools/sync-placements.d.ts +31 -0
  324. package/dist/tools/sync-placements.d.ts.map +1 -0
  325. package/dist/tools/sync-placements.js +431 -0
  326. package/dist/tools/sync-placements.js.map +1 -0
  327. package/dist/tools/team.d.ts +22 -0
  328. package/dist/tools/team.d.ts.map +1 -0
  329. package/dist/tools/team.js +144 -0
  330. package/dist/tools/team.js.map +1 -0
  331. package/dist/tools/telegram.d.ts +21 -0
  332. package/dist/tools/telegram.d.ts.map +1 -0
  333. package/dist/tools/telegram.js +144 -0
  334. package/dist/tools/telegram.js.map +1 -0
  335. package/dist/tools/uploads.d.ts +17 -0
  336. package/dist/tools/uploads.d.ts.map +1 -0
  337. package/dist/tools/uploads.js +165 -0
  338. package/dist/tools/uploads.js.map +1 -0
  339. package/dist/tools/works.d.ts +71 -0
  340. package/dist/tools/works.d.ts.map +1 -0
  341. package/dist/tools/works.js +694 -0
  342. package/dist/tools/works.js.map +1 -0
  343. package/package.json +54 -0
  344. package/scripts/build-required-schemas.ts +233 -0
  345. package/scripts/bundle-apps.ts +61 -0
  346. package/scripts/refresh-schema-mirror.ts +182 -0
  347. package/server.json +20 -0
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Recordings Tools — MCP tools for managing recordings.
3
+ *
4
+ * ADR-149 Phase 5b: Consolidated to query+inspect pattern.
5
+ * - pica_recordings_query replaces pica_recordings_list + pica_recordings_by_work
6
+ * - pica_recordings_inspect replaces pica_recordings_get (with sections support)
7
+ *
8
+ * ADR-174 Phase 2 item 3 reconciliation: the write surface covers only
9
+ * real columns on `public.recordings`. Phantom fields previously
10
+ * accepted via `additionalProperties: true` are gone; agents that
11
+ * tried to set them silently dropped data on the way to Postgres.
12
+ *
13
+ * Two pre-flight surprises documented inline below:
14
+ *
15
+ * 1. `title` is a legacy alias for `recording_title`. The HTTP route
16
+ * translates before the service sees the payload (POST since the
17
+ * route was written, PATCH only since ADR-174). The tool keeps
18
+ * `title` as the input field name for caller ergonomics; the
19
+ * description marks the rename explicitly.
20
+ *
21
+ * 2. Duration lives in `duration_ms` on recordings (works carry
22
+ * `duration_seconds`). Agents conflating the two get a 400 with
23
+ * a redirect from the route allow-list.
24
+ *
25
+ * Add-candidates surfaced per the audit at
26
+ * docs/audits/2026-04-14-mcp-db-reconciliation.md §3:
27
+ * duration_ms, preview_url, album_art_url, spotify_url,
28
+ * spotify_track_uri, spotify_track_id, youtube_video_id, youtube_url,
29
+ * apple_music_url, deezer_track_id, mlc_recording_id, mlc_song_code.
30
+ *
31
+ * Most of these are populated by the enrichment cascade on streaming
32
+ * import; exposing them lets agents seed or override that data
33
+ * deliberately rather than discovering — surprised — that the field
34
+ * they thought they set was silently absent.
35
+ *
36
+ * `isrc_prefix` is intentionally NOT in this set — column is GENERATED
37
+ * ALWAYS in `public.recordings` (left(replace(isrc,'-',''),5)). Caught
38
+ * by ADR-198 Phase 1 contract — every write attempt 500'd with PG
39
+ * 428C9 "cannot insert non-DEFAULT value into generated column".
40
+ */
41
+ import { PicaClient } from "@withpica/mcp-sdk";
42
+ import { ToolDefinition, ToolExecutor } from "./index.js";
43
+ /**
44
+ * Canonical write-schema for `recordings`. Every property must
45
+ * correspond to a real column on `public.recordings` (or be the
46
+ * documented `title` legacy alias) — verified against
47
+ * `lib/db/database.types.ts`. The HTTP route at
48
+ * `app/api/admin/recordings/route.ts` carries the same allow-list
49
+ * (plus the `recording_type` legacy alias for non-MCP callers); this
50
+ * list is the narrower MCP-agent contract.
51
+ *
52
+ * `version_type` is enum-restricted by the
53
+ * `recordings_version_type_check` CHECK constraint (ADR-166 Phase 1).
54
+ * Reflecting the enum here means agents see invalid values as schema
55
+ * errors at the tool surface, not as 500s round-tripped from Postgres.
56
+ */
57
+ declare const RECORDING_WRITE_PROPERTIES: Record<string, Record<string, unknown>>;
58
+ export declare class RecordingsTools {
59
+ private pica;
60
+ constructor(pica: PicaClient);
61
+ /**
62
+ * Get all recordings tools
63
+ */
64
+ getTools(): Array<{
65
+ definition: ToolDefinition;
66
+ executor: ToolExecutor;
67
+ }>;
68
+ /**
69
+ * Query recordings — list all, search by text, or filter by work
70
+ */
71
+ private queryRecordings;
72
+ /**
73
+ * Inspect a recording — get details with optional section filtering
74
+ */
75
+ private inspectRecording;
76
+ /**
77
+ * Create recording.
78
+ *
79
+ * `version_type` defaults to 'master' (the DB-level default and the
80
+ * canonical ADR-166 value). Pre-ADR-174 the executor defaulted to
81
+ * 'original', which is not a valid version_type — every call without
82
+ * an explicit type tripped the recording-type CHECK constraint and
83
+ * surfaced as a 500 from the service.
84
+ */
85
+ private createRecording;
86
+ /**
87
+ * Update recording
88
+ */
89
+ private updateRecording;
90
+ /**
91
+ * Delete recording
92
+ */
93
+ private deleteRecording;
94
+ }
95
+ export { RECORDING_WRITE_PROPERTIES };
96
+ //# sourceMappingURL=recordings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recordings.d.ts","sourceRoot":"","sources":["../../src/tools/recordings.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,UAAU,EAAuB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAc,MAAM,YAAY,CAAC;AAYtE;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA6IvE,CAAC;AAEF,qBAAa,eAAe;IAC1B,OAAO,CAAC,IAAI,CAAa;gBAEb,IAAI,EAAE,UAAU;IAI5B;;OAEG;IACH,QAAQ,IAAI,KAAK,CAAC;QAAE,UAAU,EAAE,cAAc,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC;IAiJzE;;OAEG;YACW,eAAe;IAkC7B;;OAEG;YACW,gBAAgB;IAiL9B;;;;;;;;OAQG;YACW,eAAe;IAgB7B;;OAEG;YACW,eAAe;IAW7B;;OAEG;YACW,eAAe;CAM9B;AAED,OAAO,EAAE,0BAA0B,EAAE,CAAC"}
@@ -0,0 +1,564 @@
1
+ // Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
2
+ /**
3
+ * Recordings Tools — MCP tools for managing recordings.
4
+ *
5
+ * ADR-149 Phase 5b: Consolidated to query+inspect pattern.
6
+ * - pica_recordings_query replaces pica_recordings_list + pica_recordings_by_work
7
+ * - pica_recordings_inspect replaces pica_recordings_get (with sections support)
8
+ *
9
+ * ADR-174 Phase 2 item 3 reconciliation: the write surface covers only
10
+ * real columns on `public.recordings`. Phantom fields previously
11
+ * accepted via `additionalProperties: true` are gone; agents that
12
+ * tried to set them silently dropped data on the way to Postgres.
13
+ *
14
+ * Two pre-flight surprises documented inline below:
15
+ *
16
+ * 1. `title` is a legacy alias for `recording_title`. The HTTP route
17
+ * translates before the service sees the payload (POST since the
18
+ * route was written, PATCH only since ADR-174). The tool keeps
19
+ * `title` as the input field name for caller ergonomics; the
20
+ * description marks the rename explicitly.
21
+ *
22
+ * 2. Duration lives in `duration_ms` on recordings (works carry
23
+ * `duration_seconds`). Agents conflating the two get a 400 with
24
+ * a redirect from the route allow-list.
25
+ *
26
+ * Add-candidates surfaced per the audit at
27
+ * docs/audits/2026-04-14-mcp-db-reconciliation.md §3:
28
+ * duration_ms, preview_url, album_art_url, spotify_url,
29
+ * spotify_track_uri, spotify_track_id, youtube_video_id, youtube_url,
30
+ * apple_music_url, deezer_track_id, mlc_recording_id, mlc_song_code.
31
+ *
32
+ * Most of these are populated by the enrichment cascade on streaming
33
+ * import; exposing them lets agents seed or override that data
34
+ * deliberately rather than discovering — surprised — that the field
35
+ * they thought they set was silently absent.
36
+ *
37
+ * `isrc_prefix` is intentionally NOT in this set — column is GENERATED
38
+ * ALWAYS in `public.recordings` (left(replace(isrc,'-',''),5)). Caught
39
+ * by ADR-198 Phase 1 contract — every write attempt 500'd with PG
40
+ * 428C9 "cannot insert non-DEFAULT value into generated column".
41
+ */
42
+ import { EntityNotFoundError } from "@withpica/mcp-sdk";
43
+ import { formatSuccess, formatStructuredList, withBillingGate, pushSectionError, } from "@withpica/mcp-utils";
44
+ import { buildRecordingAttributionHints } from "./recording-attribution-hints.js";
45
+ /**
46
+ * Canonical write-schema for `recordings`. Every property must
47
+ * correspond to a real column on `public.recordings` (or be the
48
+ * documented `title` legacy alias) — verified against
49
+ * `lib/db/database.types.ts`. The HTTP route at
50
+ * `app/api/admin/recordings/route.ts` carries the same allow-list
51
+ * (plus the `recording_type` legacy alias for non-MCP callers); this
52
+ * list is the narrower MCP-agent contract.
53
+ *
54
+ * `version_type` is enum-restricted by the
55
+ * `recordings_version_type_check` CHECK constraint (ADR-166 Phase 1).
56
+ * Reflecting the enum here means agents see invalid values as schema
57
+ * errors at the tool surface, not as 500s round-tripped from Postgres.
58
+ */
59
+ const RECORDING_WRITE_PROPERTIES = {
60
+ // Core (legacy `title` alias — translated to `recording_title` by the
61
+ // HTTP route; included here so agents don't have to know the rename).
62
+ title: {
63
+ type: "string",
64
+ description: "Recording title. Legacy alias — the HTTP route translates this to the canonical `recording_title` column. Either field is accepted; pass `title` for ergonomics.",
65
+ },
66
+ recording_title: {
67
+ type: "string",
68
+ description: "Recording title (canonical column name).",
69
+ },
70
+ artist_name: {
71
+ type: "string",
72
+ description: "Artist name for this recording",
73
+ },
74
+ version_type: {
75
+ type: "string",
76
+ description: "Recording version type. Defaults to 'master' on create. Enforced by DB CHECK constraint.",
77
+ enum: [
78
+ "master",
79
+ "alternate_master",
80
+ "music_video",
81
+ "lyric_video",
82
+ "live_performance",
83
+ "acoustic",
84
+ "remix",
85
+ "cover",
86
+ "alternate",
87
+ ],
88
+ },
89
+ work_id: {
90
+ type: "string",
91
+ description: "ID of the work this recording is of (FK to works). A bad UUID returns 400 RECORDING_FK_VIOLATION — call pica_works_query first to resolve a title to an ID.",
92
+ },
93
+ ownership_percentage: {
94
+ type: "number",
95
+ description: "Ownership percentage (0–100, validated server-side)",
96
+ },
97
+ labels: {
98
+ type: "string",
99
+ description: "Record label(s) as freetext. Legacy column — the structured home is `global_recording_labels` (not yet exposed via MCP).",
100
+ },
101
+ // Identifiers
102
+ isrc: {
103
+ type: "string",
104
+ description: "International Standard Recording Code (e.g. GBUM71804829). Triggers global_recordings linking on create/update.",
105
+ },
106
+ isrc_source: {
107
+ type: "string",
108
+ description: "Where the ISRC came from (e.g. 'spotify', 'mlc', 'manual', 'ppl', 'apple_music', 'youtube_music', 'soundcloud', 'disco').",
109
+ },
110
+ musicbrainz_recording_id: {
111
+ type: "string",
112
+ description: "MusicBrainz recording UUID",
113
+ },
114
+ mlc_recording_id: {
115
+ type: "string",
116
+ description: "MLC recording ID",
117
+ },
118
+ mlc_song_code: {
119
+ type: "string",
120
+ description: "MLC song code (links recording to its work registration)",
121
+ },
122
+ // Master metadata (ADR-165 Phase 2 — populated by enrichment but
123
+ // settable from MCP for manual seeding/overrides).
124
+ duration_ms: {
125
+ type: "number",
126
+ description: "Duration in milliseconds. Note: `works` carries duration_seconds; `recordings` carries duration_ms.",
127
+ },
128
+ preview_url: {
129
+ type: "string",
130
+ description: "30-second preview URL (Spotify or equivalent)",
131
+ },
132
+ album_art_url: {
133
+ type: "string",
134
+ description: "Denormalised album artwork URL. Source of truth is releases.artwork_url; duplicated here for catalogue-card hot paths.",
135
+ },
136
+ spotify_url: {
137
+ type: "string",
138
+ description: "Per-track Spotify URL (e.g. https://open.spotify.com/track/...). Distinct from releases.spotify_url which is the album-level URL.",
139
+ },
140
+ spotify_track_uri: {
141
+ type: "string",
142
+ description: "spotify:track:{id} URI for the master. Distinct from release_tracks.spotify_track_uri (per-track-in-release).",
143
+ },
144
+ spotify_track_id: {
145
+ type: "string",
146
+ description: "Spotify external track id (for dedup + cascade matching)",
147
+ },
148
+ youtube_video_id: {
149
+ type: "string",
150
+ description: "YouTube video id. Non-master version types (music_video, lyric_video, etc.) get their own video id.",
151
+ },
152
+ youtube_url: {
153
+ type: "string",
154
+ description: "YouTube watch URL",
155
+ },
156
+ apple_music_url: {
157
+ type: "string",
158
+ description: "Apple Music track URL",
159
+ },
160
+ deezer_track_id: {
161
+ type: "string",
162
+ description: "Deezer track id",
163
+ },
164
+ // PPL
165
+ ppl_registered: {
166
+ type: "boolean",
167
+ description: "Whether registered with PPL",
168
+ },
169
+ ppl_recording_id: {
170
+ type: "string",
171
+ description: "PPL recording ID",
172
+ },
173
+ // Declared jsonb extension points
174
+ ai_disclosure: {
175
+ type: "object",
176
+ description: "AI disclosure object (UK AI Copyright compliance). Fields: composition, performance, production, mastering ('none'|'assisted'|'generated'), tools_used (string[]), disclosure_date, disclosed_by.",
177
+ },
178
+ provenance_attestation: {
179
+ type: "object",
180
+ description: "Human creation proof. Fields: human_created (bool), attested_by, attested_at, attestation_method, supporting_evidence, ip_address, signature_hash, certificate_id.",
181
+ },
182
+ training_rights: {
183
+ type: "object",
184
+ description: "B2B ML licensing compliance object. Fields: available_for_training (bool), training_terms, minimum_fee, excluded_uses, permitted_uses, geographic_restrictions, requires_attribution, requires_notification, license_duration, updated_at, updated_by.",
185
+ },
186
+ };
187
+ export class RecordingsTools {
188
+ pica;
189
+ constructor(pica) {
190
+ this.pica = pica;
191
+ }
192
+ /**
193
+ * Get all recordings tools
194
+ */
195
+ getTools() {
196
+ return [
197
+ {
198
+ definition: {
199
+ name: "pica_recordings_query",
200
+ description: "Find recordings — list all, search by query, or filter by work. " +
201
+ "→ then: pica_recordings_inspect (details for a specific recording)",
202
+ workflows: "infrastructure",
203
+ inputSchema: {
204
+ type: "object",
205
+ properties: {
206
+ query: {
207
+ type: "string",
208
+ description: "Search by title, ISRC, or artist name",
209
+ },
210
+ work_id: {
211
+ type: "string",
212
+ description: "Filter recordings by work ID (replaces pica_recordings_by_work)",
213
+ },
214
+ limit: {
215
+ type: "number",
216
+ description: "Max results (default: 50)",
217
+ },
218
+ },
219
+ },
220
+ },
221
+ executor: this.queryRecordings.bind(this),
222
+ },
223
+ {
224
+ definition: {
225
+ name: "pica_recordings_inspect",
226
+ description: "Get details for a specific recording. Omit sections for everything. " +
227
+ "Sections: basic (recording row + ISRC prefix intel), credits (work-side credits via parent work), recording_credits (first-party operator-authored production credits on this recording), audio (audio files via parent work), production_assets, releases. " +
228
+ "Round-trip a pica_recording_credits_update write via sections:['recording_credits']. " +
229
+ "→ then: pica_audio_query (audio files), pica_credits_update (fix work-side credits), pica_recording_credits_update (add a recording-side credit)",
230
+ workflows: "infrastructure",
231
+ inputSchema: {
232
+ type: "object",
233
+ properties: {
234
+ id: {
235
+ type: "string",
236
+ description: "Recording ID",
237
+ },
238
+ sections: {
239
+ type: "array",
240
+ items: {
241
+ type: "string",
242
+ enum: [
243
+ "basic",
244
+ "credits",
245
+ "recording_credits",
246
+ "audio",
247
+ "production_assets",
248
+ "releases",
249
+ ],
250
+ },
251
+ description: 'Which data sections to include. Omit for all sections. Use ["basic"] for lightweight lookup. Use ["recording_credits"] to round-trip a pica_recording_credits_update write.',
252
+ },
253
+ },
254
+ required: ["id"],
255
+ },
256
+ },
257
+ executor: this.inspectRecording.bind(this),
258
+ },
259
+ {
260
+ definition: {
261
+ name: "pica_recordings_create",
262
+ description: "Create a new recording. IMPORTANT: call pica_recordings_query with work_id first to check for existing recordings on the same work — duplicate masters cause ISRC conflicts. " +
263
+ "Album metadata (album_name, album_release_date, upc, track_number) lives on pica_releases_create/update, not here. " +
264
+ "Label-as-org belongs on the release (pica_releases_*.label_organization_id via pica_labels_query); the legacy `labels` freetext column is kept for backwards compat. " +
265
+ "ISWCs identify works, not recordings — set them via pica_works_create/update. " +
266
+ "Duration is in milliseconds (`duration_ms`); the `duration_seconds` works convention is rejected with a 400. " +
267
+ "After several mutations, surface a pica_dashboard_briefing to the user. " +
268
+ "→ before: pica_recordings_query (check duplicates) → then: pica_audio_presigned_upload (upload audio), pica_audio_analyze (extract features)",
269
+ workflows: ["recording-required"],
270
+ inputSchema: {
271
+ type: "object",
272
+ properties: RECORDING_WRITE_PROPERTIES,
273
+ required: ["title", "artist_name", "version_type"],
274
+ },
275
+ },
276
+ executor: withBillingGate(this.pica, "recording creation", this.createRecording.bind(this)),
277
+ },
278
+ {
279
+ definition: {
280
+ name: "pica_recordings_update",
281
+ description: "Update an existing recording. Only real `recordings` columns are accepted. " +
282
+ "Album metadata (album_name, upc, track_number) belongs on pica_releases_create/update; ISWC belongs on pica_works_create/update; duration is in `duration_ms` (not `duration_seconds`). " +
283
+ "Bad keys return a 400 with a redirect message naming the correct tool. " +
284
+ "→ then: pica_recordings_inspect (verify changes persisted)",
285
+ workflows: ["recording-required"],
286
+ inputSchema: {
287
+ type: "object",
288
+ properties: {
289
+ id: {
290
+ type: "string",
291
+ description: "Recording ID (required)",
292
+ },
293
+ ...RECORDING_WRITE_PROPERTIES,
294
+ },
295
+ required: ["id"],
296
+ },
297
+ },
298
+ executor: withBillingGate(this.pica, "recording update", this.updateRecording.bind(this)),
299
+ },
300
+ {
301
+ definition: {
302
+ name: "pica_recordings_delete",
303
+ description: "Delete a recording (destructive — unlinks from release tracks and work).",
304
+ workflows: "infrastructure",
305
+ inputSchema: {
306
+ type: "object",
307
+ properties: {
308
+ id: {
309
+ type: "string",
310
+ description: "Recording ID",
311
+ },
312
+ },
313
+ required: ["id"],
314
+ },
315
+ },
316
+ executor: withBillingGate(this.pica, "recording deletion", this.deleteRecording.bind(this)),
317
+ },
318
+ ];
319
+ }
320
+ /**
321
+ * Query recordings — list all, search by text, or filter by work
322
+ */
323
+ async queryRecordings(args) {
324
+ const limit = args.limit || 50;
325
+ const workId = args.work_id;
326
+ const query = args.query;
327
+ // Filter by work_id — delegate to getByWork
328
+ if (workId) {
329
+ const recordings = await this.pica.recordings.getByWork(workId);
330
+ return formatStructuredList(recordings, "recording", {
331
+ work_id: workId,
332
+ total: recordings.length,
333
+ });
334
+ }
335
+ // Search by text query — delegate to search method (client-side filtering)
336
+ if (query) {
337
+ const result = await this.pica.recordings.search({ query, limit });
338
+ return formatStructuredList(result.data, "recording", {
339
+ query,
340
+ total: result.total,
341
+ hasMore: result.hasMore,
342
+ });
343
+ }
344
+ // Default: list all
345
+ const recordings = await this.pica.recordings.list({ limit });
346
+ return formatStructuredList(recordings, "recording", {
347
+ total: recordings.length,
348
+ limit,
349
+ });
350
+ }
351
+ /**
352
+ * Inspect a recording — get details with optional section filtering
353
+ */
354
+ async inspectRecording(args) {
355
+ const id = args.id;
356
+ const sections = args.sections;
357
+ const allSections = !sections || sections.length === 0;
358
+ const result = {};
359
+ // ADR-224 — see works.ts for the doctrine. recordings_inspect's
360
+ // pre-conversion pattern was the sibling-field shape (`result.X = []`
361
+ // + `result.X_error = msg`), the medium-severity variant of the four
362
+ // ADR-224 found. Flag-off mode preserves the sibling-field shape;
363
+ // flag-on drops the sibling fields and routes failures through
364
+ // errors[]. Primary-entity EntityNotFoundError propagation (PR #110,
365
+ // 2026-04-26) is preserved unchanged in both modes — that's a hard
366
+ // error signal that doesn't go through the section-error path.
367
+ const useStructured = process.env.ADR_224_STRUCTURED_ERRORS === "1";
368
+ const errors = [];
369
+ const TOOL_NAME = "pica_recordings_inspect";
370
+ // Basic section: recording details + ISRC prefix intel
371
+ if (allSections || sections?.includes("basic")) {
372
+ try {
373
+ const recording = await this.pica.recordings.get(id);
374
+ result.recording = recording;
375
+ // Enrich with ISRC prefix intelligence if ISRC is present
376
+ if (recording.isrc) {
377
+ const prefixIntel = await this.pica.recordings.prefixLookup(recording.isrc);
378
+ if (prefixIntel) {
379
+ result.prefix_intel = prefixIntel;
380
+ }
381
+ }
382
+ }
383
+ catch (error) {
384
+ // 404 on the primary entity is a hard error — propagate so the
385
+ // agent sees an explicit not-found signal instead of a 200 with
386
+ // a partial-empty payload (ADR-198 verification 2026-04-26 —
387
+ // pica_recordings_inspect was hallucinating into the void on
388
+ // missing route handlers / missing recordings). This propagation
389
+ // predates and is independent of ADR-224 — kept unchanged.
390
+ if (error instanceof EntityNotFoundError) {
391
+ throw error;
392
+ }
393
+ if (!useStructured) {
394
+ result.recording_error =
395
+ error instanceof Error
396
+ ? error.message
397
+ : "Failed to fetch recording";
398
+ }
399
+ pushSectionError(errors, TOOL_NAME, "basic", error, id);
400
+ }
401
+ }
402
+ // Credits section: work credits (via recording's parent work)
403
+ if (allSections || sections?.includes("credits")) {
404
+ try {
405
+ // We need the recording to get its work_id
406
+ const recording = result.recording ||
407
+ (await this.pica.recordings.get(id));
408
+ const workId = recording.work_id;
409
+ if (workId) {
410
+ const credits = await this.pica.credits.listForWork(workId);
411
+ result.credits = credits;
412
+ }
413
+ else {
414
+ result.credits = [];
415
+ result.credits_note = "No parent work linked — no credits available";
416
+ }
417
+ }
418
+ catch (error) {
419
+ if (!useStructured) {
420
+ result.credits_error =
421
+ error instanceof Error ? error.message : "Failed to fetch credits";
422
+ }
423
+ else {
424
+ result.credits = null;
425
+ }
426
+ pushSectionError(errors, TOOL_NAME, "credits", error, id);
427
+ }
428
+ }
429
+ // ADR-213 Primitive A.1 — additive recording_credits section.
430
+ // Distinct from the `credits` section above (which reads work-side
431
+ // credits via the parent work). This reads first-party operator-
432
+ // authored production credits directly from the recording_credits
433
+ // table. Closes the round-trip path for pica_recording_credits_update
434
+ // per ADR-198. Trade-secret separation: this never touches the
435
+ // enrichment-cascade-fed `credits` table (per ip-protection.md).
436
+ if (allSections || sections?.includes("recording_credits")) {
437
+ try {
438
+ result.recording_credits = await this.pica.recordingCredits.list(id);
439
+ }
440
+ catch (error) {
441
+ if (!useStructured) {
442
+ result.recording_credits = [];
443
+ result.recording_credits_error =
444
+ error instanceof Error
445
+ ? error.message
446
+ : "Failed to fetch recording_credits";
447
+ }
448
+ else {
449
+ result.recording_credits = null;
450
+ }
451
+ pushSectionError(errors, TOOL_NAME, "recording_credits", error, id);
452
+ }
453
+ }
454
+ // Audio section: audio files linked to the parent work
455
+ if (allSections || sections?.includes("audio")) {
456
+ try {
457
+ const recording = result.recording ||
458
+ (await this.pica.recordings.get(id));
459
+ const workId = recording.work_id;
460
+ if (workId) {
461
+ const audioFiles = await this.pica.audioFiles.list({
462
+ work_id: workId,
463
+ });
464
+ result.audio_files = audioFiles;
465
+ }
466
+ else {
467
+ result.audio_files = [];
468
+ result.audio_note =
469
+ "No parent work linked — no audio files available";
470
+ }
471
+ }
472
+ catch (error) {
473
+ if (!useStructured) {
474
+ result.audio_error =
475
+ error instanceof Error
476
+ ? error.message
477
+ : "Failed to fetch audio files";
478
+ }
479
+ else {
480
+ result.audio_files = null;
481
+ }
482
+ pushSectionError(errors, TOOL_NAME, "audio", error, id);
483
+ }
484
+ }
485
+ // ADR-156 op #3 Session B Task 5 — surface linked physical assets
486
+ // so the inspect tool is discoverable from the recording side.
487
+ if (allSections || sections?.includes("production_assets")) {
488
+ try {
489
+ result.production_assets =
490
+ await this.pica.recordings.listProductionAssets(id);
491
+ }
492
+ catch (error) {
493
+ if (!useStructured) {
494
+ result.production_assets = [];
495
+ result.production_assets_error =
496
+ error instanceof Error
497
+ ? error.message
498
+ : "Failed to fetch production assets";
499
+ }
500
+ else {
501
+ result.production_assets = null;
502
+ }
503
+ pushSectionError(errors, TOOL_NAME, "production_assets", error, id);
504
+ }
505
+ }
506
+ // ADR-173 Decision 2 — every release this recording appears on,
507
+ // with its track position. Answers "which albums is this master
508
+ // on?" in one call.
509
+ if (allSections || sections?.includes("releases")) {
510
+ try {
511
+ result.releases = await this.pica.recordings.listReleases(id);
512
+ }
513
+ catch (error) {
514
+ if (!useStructured) {
515
+ result.releases = [];
516
+ result.releases_error =
517
+ error instanceof Error ? error.message : "Failed to fetch releases";
518
+ }
519
+ else {
520
+ result.releases = null;
521
+ }
522
+ pushSectionError(errors, TOOL_NAME, "releases", error, id);
523
+ }
524
+ }
525
+ const enriched = useStructured ? { ...result, errors } : result;
526
+ return formatSuccess("Recording details", enriched);
527
+ }
528
+ /**
529
+ * Create recording.
530
+ *
531
+ * `version_type` defaults to 'master' (the DB-level default and the
532
+ * canonical ADR-166 value). Pre-ADR-174 the executor defaulted to
533
+ * 'original', which is not a valid version_type — every call without
534
+ * an explicit type tripped the recording-type CHECK constraint and
535
+ * surfaced as a 500 from the service.
536
+ */
537
+ async createRecording(args) {
538
+ if (!args.version_type)
539
+ args.version_type = "master";
540
+ const recording = await this.pica.recordings.create(args);
541
+ // ADR-213 Primitive A — append attribution hints so every new recording
542
+ // prompts the ownership / credits / master-claim conversation by default.
543
+ // Mirror of buildCustodyHints (works.ts:723) for the recordings side.
544
+ const hints = buildRecordingAttributionHints(recording);
545
+ return formatSuccess("Recording created successfully", recording, hints);
546
+ }
547
+ /**
548
+ * Update recording
549
+ */
550
+ async updateRecording(args) {
551
+ const { id, ...updates } = args;
552
+ const recording = await this.pica.recordings.update(id, updates);
553
+ return formatSuccess("Recording updated successfully", recording);
554
+ }
555
+ /**
556
+ * Delete recording
557
+ */
558
+ async deleteRecording(args) {
559
+ await this.pica.recordings.delete(args.id);
560
+ return formatSuccess(`Recording ${args.id} deleted successfully`);
561
+ }
562
+ }
563
+ export { RECORDING_WRITE_PROPERTIES };
564
+ //# sourceMappingURL=recordings.js.map