@withpica/mcp-server 2.11.0 → 2.23.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.
- package/CHANGELOG.md +639 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -2
- package/dist/config.js.map +1 -1
- package/dist/prompts/index.d.ts +48 -16
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +320 -607
- package/dist/prompts/index.js.map +1 -1
- package/dist/tools/agreement-types.d.ts.map +1 -1
- package/dist/tools/agreement-types.js +14 -129
- package/dist/tools/agreement-types.js.map +1 -1
- package/dist/tools/agreements.d.ts.map +1 -1
- package/dist/tools/agreements.js +11 -109
- package/dist/tools/agreements.js.map +1 -1
- package/dist/tools/assets.d.ts.map +1 -1
- package/dist/tools/assets.js +17 -257
- package/dist/tools/assets.js.map +1 -1
- package/dist/tools/audit.d.ts +19 -0
- package/dist/tools/audit.d.ts.map +1 -0
- package/dist/tools/audit.js +57 -0
- package/dist/tools/audit.js.map +1 -0
- package/dist/tools/bulk.d.ts +7 -1
- package/dist/tools/bulk.d.ts.map +1 -1
- package/dist/tools/bulk.js +24 -2
- package/dist/tools/bulk.js.map +1 -1
- package/dist/tools/credits.d.ts.map +1 -1
- package/dist/tools/credits.js +27 -13
- package/dist/tools/credits.js.map +1 -1
- package/dist/tools/discovery.d.ts.map +1 -1
- package/dist/tools/discovery.js +25 -0
- package/dist/tools/discovery.js.map +1 -1
- package/dist/tools/enrichment.d.ts +47 -0
- package/dist/tools/enrichment.d.ts.map +1 -1
- package/dist/tools/enrichment.js +416 -19
- package/dist/tools/enrichment.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +17 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/labels.d.ts +20 -0
- package/dist/tools/labels.d.ts.map +1 -0
- package/dist/tools/labels.js +47 -0
- package/dist/tools/labels.js.map +1 -0
- package/dist/tools/metadata.d.ts.map +1 -1
- package/dist/tools/metadata.js +93 -0
- package/dist/tools/metadata.js.map +1 -1
- package/dist/tools/multimedia.d.ts.map +1 -1
- package/dist/tools/multimedia.js +86 -11
- package/dist/tools/multimedia.js.map +1 -1
- package/dist/tools/notes.d.ts.map +1 -1
- package/dist/tools/notes.js +4 -1
- package/dist/tools/notes.js.map +1 -1
- package/dist/tools/people.d.ts +228 -4
- package/dist/tools/people.d.ts.map +1 -1
- package/dist/tools/people.js +238 -262
- package/dist/tools/people.js.map +1 -1
- package/dist/tools/projects.d.ts +1 -0
- package/dist/tools/projects.d.ts.map +1 -1
- package/dist/tools/projects.js +188 -17
- package/dist/tools/projects.js.map +1 -1
- package/dist/tools/publishers.d.ts +15 -1
- package/dist/tools/publishers.d.ts.map +1 -1
- package/dist/tools/publishers.js +43 -9
- package/dist/tools/publishers.js.map +1 -1
- package/dist/tools/recordings.d.ts +53 -2
- package/dist/tools/recordings.d.ts.map +1 -1
- package/dist/tools/recordings.js +185 -122
- package/dist/tools/recordings.js.map +1 -1
- package/dist/tools/recovery-hints.d.ts.map +1 -1
- package/dist/tools/recovery-hints.js +49 -0
- package/dist/tools/recovery-hints.js.map +1 -1
- package/dist/tools/releases.d.ts +19 -1
- package/dist/tools/releases.d.ts.map +1 -1
- package/dist/tools/releases.js +538 -32
- package/dist/tools/releases.js.map +1 -1
- package/dist/tools/sessions.d.ts.map +1 -1
- package/dist/tools/sessions.js +42 -8
- package/dist/tools/sessions.js.map +1 -1
- package/dist/tools/settings.d.ts +4 -0
- package/dist/tools/settings.d.ts.map +1 -1
- package/dist/tools/settings.js +155 -1
- package/dist/tools/settings.js.map +1 -1
- package/dist/tools/share-links.d.ts.map +1 -1
- package/dist/tools/share-links.js +19 -53
- package/dist/tools/share-links.js.map +1 -1
- package/dist/tools/split-sheets.d.ts.map +1 -1
- package/dist/tools/split-sheets.js +3 -42
- package/dist/tools/split-sheets.js.map +1 -1
- package/dist/tools/team.d.ts.map +1 -1
- package/dist/tools/team.js +9 -4
- package/dist/tools/team.js.map +1 -1
- package/dist/tools/works.d.ts +27 -1
- package/dist/tools/works.d.ts.map +1 -1
- package/dist/tools/works.js +119 -219
- package/dist/tools/works.js.map +1 -1
- package/package.json +3 -2
- package/server.json +2 -2
package/dist/tools/releases.js
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
// Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
|
|
2
2
|
import { formatSuccess, formatStructuredList } from "@withpica/mcp-utils";
|
|
3
|
+
/**
|
|
4
|
+
* Canonical write-schema for `releases`. Every property below must
|
|
5
|
+
* correspond to a real column on `public.releases`. Keep this list
|
|
6
|
+
* tight — reintroducing a phantom field is the exact regression
|
|
7
|
+
* ADR-174 Phase 2 exists to prevent.
|
|
8
|
+
*/
|
|
9
|
+
const RELEASE_WRITE_PROPERTIES = {
|
|
10
|
+
title: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Release title",
|
|
13
|
+
},
|
|
14
|
+
release_date: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Release date (YYYY-MM-DD)",
|
|
17
|
+
},
|
|
18
|
+
release_type: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "Release type",
|
|
21
|
+
enum: ["album", "ep", "single", "compilation"],
|
|
22
|
+
},
|
|
23
|
+
pre_release_date: {
|
|
24
|
+
type: "string",
|
|
25
|
+
description: "Pre-release / announcement date (YYYY-MM-DD)",
|
|
26
|
+
},
|
|
27
|
+
upc: {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Universal Product Code (UPC/EAN barcode)",
|
|
30
|
+
},
|
|
31
|
+
catalog_number: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "Label catalog number",
|
|
34
|
+
},
|
|
35
|
+
label_organization_id: {
|
|
36
|
+
type: "string",
|
|
37
|
+
description: "organisations.id of the label (must be an org with org_type='label'). " +
|
|
38
|
+
"Resolve a label name to an ID via pica_labels_query first — never pass a free-text name.",
|
|
39
|
+
},
|
|
40
|
+
distributor_organization_id: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "organisations.id of the distributor. Resolve a distributor name via pica_search_all first.",
|
|
43
|
+
},
|
|
44
|
+
artwork_url: {
|
|
45
|
+
type: "string",
|
|
46
|
+
description: "Album artwork URL",
|
|
47
|
+
},
|
|
48
|
+
spotify_album_uri: {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: "Spotify album URI (e.g. spotify:album:…)",
|
|
51
|
+
},
|
|
52
|
+
spotify_url: {
|
|
53
|
+
type: "string",
|
|
54
|
+
description: "Spotify album web URL",
|
|
55
|
+
},
|
|
56
|
+
apple_music_url: {
|
|
57
|
+
type: "string",
|
|
58
|
+
description: "Apple Music album URL",
|
|
59
|
+
},
|
|
60
|
+
other_urls: {
|
|
61
|
+
type: "object",
|
|
62
|
+
description: "DSP URLs keyed by service name (e.g. { tidal: '…', deezer: '…' })",
|
|
63
|
+
additionalProperties: { type: "string" },
|
|
64
|
+
},
|
|
65
|
+
notes: {
|
|
66
|
+
type: "string",
|
|
67
|
+
description: "Internal notes",
|
|
68
|
+
},
|
|
69
|
+
};
|
|
3
70
|
export class ReleasesTools {
|
|
4
71
|
pica;
|
|
5
72
|
constructor(pica) {
|
|
@@ -10,7 +77,7 @@ export class ReleasesTools {
|
|
|
10
77
|
{
|
|
11
78
|
definition: {
|
|
12
79
|
name: "pica_releases_list",
|
|
13
|
-
description: "List releases — albums, EPs, and singles with release dates, labels, and UPCs.",
|
|
80
|
+
description: "List releases — albums, EPs, and singles with release dates, labels, distributors, and UPCs.",
|
|
14
81
|
inputSchema: {
|
|
15
82
|
type: "object",
|
|
16
83
|
properties: {
|
|
@@ -40,69 +107,478 @@ export class ReleasesTools {
|
|
|
40
107
|
{
|
|
41
108
|
definition: {
|
|
42
109
|
name: "pica_releases_create",
|
|
43
|
-
description: "Create a new release — set
|
|
110
|
+
description: "Create a new release — set title, dates, type, catalog number, " +
|
|
111
|
+
"label/distributor organisation IDs, artwork, DSP URLs, and notes. " +
|
|
112
|
+
"For label_organization_id use pica_labels_query first to resolve a name to an ID " +
|
|
113
|
+
"(freetext label names are not accepted — the DB stores label as an FK to organisations).",
|
|
114
|
+
inputSchema: {
|
|
115
|
+
type: "object",
|
|
116
|
+
properties: RELEASE_WRITE_PROPERTIES,
|
|
117
|
+
required: ["title"],
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
executor: this.createRelease.bind(this),
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
definition: {
|
|
124
|
+
name: "pica_releases_update",
|
|
125
|
+
description: "Update release details — any field in the release write schema. " +
|
|
126
|
+
"For label_organization_id use pica_labels_query first to resolve a name to an ID.",
|
|
44
127
|
inputSchema: {
|
|
45
128
|
type: "object",
|
|
46
129
|
properties: {
|
|
47
|
-
|
|
130
|
+
id: { type: "string", description: "Release ID" },
|
|
131
|
+
...RELEASE_WRITE_PROPERTIES,
|
|
132
|
+
},
|
|
133
|
+
required: ["id"],
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
executor: this.updateRelease.bind(this),
|
|
137
|
+
},
|
|
138
|
+
// ADR-173: release-track primitives + compound workflow
|
|
139
|
+
{
|
|
140
|
+
definition: {
|
|
141
|
+
name: "pica_releases_attach_track",
|
|
142
|
+
description: "Attach a recording and/or work to a release at a specific (disc, track) position. " +
|
|
143
|
+
"At least one of recording_id or work_id must be provided. Idempotent on " +
|
|
144
|
+
"(release_id, disc_number, track_number) — a second call at the same position " +
|
|
145
|
+
"updates the existing row rather than creating a duplicate. " +
|
|
146
|
+
"→ then: pica_releases_list_tracks (verify tracklist), pica_releases_reorder_tracks (change order)",
|
|
147
|
+
inputSchema: {
|
|
148
|
+
type: "object",
|
|
149
|
+
properties: {
|
|
150
|
+
release_id: { type: "string", description: "Release ID" },
|
|
151
|
+
recording_id: {
|
|
48
152
|
type: "string",
|
|
49
|
-
description: "
|
|
153
|
+
description: "Recording ID (optional — at least one of recording_id or work_id must be provided)",
|
|
50
154
|
},
|
|
51
|
-
|
|
155
|
+
work_id: {
|
|
52
156
|
type: "string",
|
|
53
|
-
description: "
|
|
157
|
+
description: "Work ID (optional — omit for licensed-masters releases where no composition record exists)",
|
|
54
158
|
},
|
|
55
|
-
|
|
56
|
-
type: "
|
|
57
|
-
description: "
|
|
159
|
+
track_number: {
|
|
160
|
+
type: "number",
|
|
161
|
+
description: "Position on disc (1-based)",
|
|
58
162
|
},
|
|
59
|
-
|
|
60
|
-
type: "
|
|
61
|
-
description: "
|
|
163
|
+
disc_number: {
|
|
164
|
+
type: "number",
|
|
165
|
+
description: "Disc number (default 1)",
|
|
62
166
|
},
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
167
|
+
},
|
|
168
|
+
required: ["release_id", "track_number"],
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
executor: this.attachTrack.bind(this),
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
definition: {
|
|
175
|
+
name: "pica_releases_list_tracks",
|
|
176
|
+
description: "List tracks on a release in (disc_number, track_number) order with " +
|
|
177
|
+
"inlined title, artist, ISRC, and duration from the linked recording and work. " +
|
|
178
|
+
"→ then: pica_releases_reorder_tracks (change order), pica_recordings_inspect (deep-dive a track)",
|
|
179
|
+
inputSchema: {
|
|
180
|
+
type: "object",
|
|
181
|
+
properties: {
|
|
182
|
+
release_id: { type: "string", description: "Release ID" },
|
|
183
|
+
},
|
|
184
|
+
required: ["release_id"],
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
executor: this.listTracks.bind(this),
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
definition: {
|
|
191
|
+
name: "pica_releases_detach_track",
|
|
192
|
+
description: "Remove a track from a release by position. Soft-confirmation: call without " +
|
|
193
|
+
"confirm:true to see a preview of the row that would be removed, then call " +
|
|
194
|
+
"again with confirm:true to execute.",
|
|
195
|
+
inputSchema: {
|
|
196
|
+
type: "object",
|
|
197
|
+
properties: {
|
|
198
|
+
release_id: { type: "string", description: "Release ID" },
|
|
199
|
+
track_number: {
|
|
200
|
+
type: "number",
|
|
201
|
+
description: "Position on disc (1-based)",
|
|
202
|
+
},
|
|
203
|
+
disc_number: {
|
|
204
|
+
type: "number",
|
|
205
|
+
description: "Disc number (default 1)",
|
|
206
|
+
},
|
|
207
|
+
confirm: {
|
|
208
|
+
type: "boolean",
|
|
209
|
+
description: "Set to true to execute the detach after reviewing the preview",
|
|
66
210
|
},
|
|
67
211
|
},
|
|
68
|
-
required: ["
|
|
212
|
+
required: ["release_id", "track_number"],
|
|
69
213
|
},
|
|
70
214
|
},
|
|
71
|
-
executor: this.
|
|
215
|
+
executor: this.detachTrack.bind(this),
|
|
72
216
|
},
|
|
73
217
|
{
|
|
74
218
|
definition: {
|
|
75
|
-
name: "
|
|
76
|
-
description: "
|
|
219
|
+
name: "pica_releases_reorder_tracks",
|
|
220
|
+
description: "Reorder tracks on a release atomically. Pass the full new order as an array " +
|
|
221
|
+
"of { track_id, track_number, disc_number } — the entire reorder commits or " +
|
|
222
|
+
"rolls back as one transaction. Duplicate (disc_number, track_number) pairs " +
|
|
223
|
+
"in the payload are rejected before any DB write.",
|
|
77
224
|
inputSchema: {
|
|
78
225
|
type: "object",
|
|
79
226
|
properties: {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
227
|
+
release_id: { type: "string", description: "Release ID" },
|
|
228
|
+
new_order: {
|
|
229
|
+
type: "array",
|
|
230
|
+
description: "New ordering of tracks. Every existing track should appear here.",
|
|
231
|
+
items: {
|
|
232
|
+
type: "object",
|
|
233
|
+
properties: {
|
|
234
|
+
track_id: {
|
|
235
|
+
type: "string",
|
|
236
|
+
description: "release_tracks.id",
|
|
237
|
+
},
|
|
238
|
+
track_number: { type: "number" },
|
|
239
|
+
disc_number: {
|
|
240
|
+
type: "number",
|
|
241
|
+
description: "Default 1",
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
required: ["track_id", "track_number"],
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
required: ["release_id", "new_order"],
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
executor: this.reorderTracks.bind(this),
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
definition: {
|
|
255
|
+
name: "pica_releases_attach_recording_with_work",
|
|
256
|
+
description: "Attach a recording to a release at a specific position, automatically " +
|
|
257
|
+
"pulling the recording's linked work (if any) onto the same track row. " +
|
|
258
|
+
"Saves agents the recordings.work_id lookup that pica_releases_attach_track " +
|
|
259
|
+
"would otherwise require. Idempotent on (release_id, disc_number, track_number).",
|
|
260
|
+
inputSchema: {
|
|
261
|
+
type: "object",
|
|
262
|
+
properties: {
|
|
263
|
+
release_id: { type: "string", description: "Release ID" },
|
|
264
|
+
recording_id: { type: "string", description: "Recording ID" },
|
|
265
|
+
track_number: {
|
|
266
|
+
type: "number",
|
|
267
|
+
description: "Position on disc (1-based)",
|
|
268
|
+
},
|
|
269
|
+
disc_number: {
|
|
270
|
+
type: "number",
|
|
271
|
+
description: "Disc number (default 1)",
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
required: ["release_id", "recording_id", "track_number"],
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
executor: this.attachRecordingWithWork.bind(this),
|
|
278
|
+
},
|
|
279
|
+
// ADR-175: release workflow tools — compound operations on the primitives
|
|
280
|
+
{
|
|
281
|
+
definition: {
|
|
282
|
+
name: "pica_releases_bulk_attach_tracks",
|
|
283
|
+
description: "Attach many tracks to a release in a single atomic call. Same " +
|
|
284
|
+
"idempotency semantics as pica_releases_attach_track — a duplicate " +
|
|
285
|
+
"(disc_number, track_number) position updates rather than duplicates. " +
|
|
286
|
+
"Duplicate positions WITHIN the payload are rejected before any DB " +
|
|
287
|
+
"write. Use when you have an existing release and the full tracklist " +
|
|
288
|
+
"at once; use pica_releases_create_with_tracks when the release does " +
|
|
289
|
+
"not yet exist.",
|
|
290
|
+
inputSchema: {
|
|
291
|
+
type: "object",
|
|
292
|
+
properties: {
|
|
293
|
+
release_id: { type: "string", description: "Release ID" },
|
|
294
|
+
tracks: {
|
|
295
|
+
type: "array",
|
|
296
|
+
description: "Tracks to attach. Each entry needs at least one of recording_id " +
|
|
297
|
+
"or work_id, plus track_number (1-based).",
|
|
298
|
+
items: {
|
|
299
|
+
type: "object",
|
|
300
|
+
properties: {
|
|
301
|
+
recording_id: {
|
|
302
|
+
type: "string",
|
|
303
|
+
description: "Recording ID (optional if work_id is present)",
|
|
304
|
+
},
|
|
305
|
+
work_id: {
|
|
306
|
+
type: "string",
|
|
307
|
+
description: "Work ID (optional if recording_id is present)",
|
|
308
|
+
},
|
|
309
|
+
track_number: {
|
|
310
|
+
type: "number",
|
|
311
|
+
description: "Position on disc (1-based)",
|
|
312
|
+
},
|
|
313
|
+
disc_number: {
|
|
314
|
+
type: "number",
|
|
315
|
+
description: "Disc number (default 1)",
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
required: ["track_number"],
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
required: ["release_id", "tracks"],
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
executor: this.bulkAttachTracks.bind(this),
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
definition: {
|
|
329
|
+
name: "pica_releases_move_track",
|
|
330
|
+
description: "Swap two track positions on a release atomically. Internally reads " +
|
|
331
|
+
"both rows and writes them with exchanged (disc_number, track_number) " +
|
|
332
|
+
"in one transaction. For the rare full re-sequence, use " +
|
|
333
|
+
"pica_releases_reorder_tracks instead.",
|
|
334
|
+
inputSchema: {
|
|
335
|
+
type: "object",
|
|
336
|
+
properties: {
|
|
337
|
+
release_id: { type: "string", description: "Release ID" },
|
|
338
|
+
from: {
|
|
339
|
+
type: "object",
|
|
340
|
+
description: "Source position",
|
|
341
|
+
properties: {
|
|
342
|
+
track_number: { type: "number" },
|
|
343
|
+
disc_number: { type: "number", description: "Default 1" },
|
|
344
|
+
},
|
|
345
|
+
required: ["track_number"],
|
|
85
346
|
},
|
|
86
|
-
|
|
347
|
+
to: {
|
|
348
|
+
type: "object",
|
|
349
|
+
description: "Destination position (must be occupied — this is a swap, not a slide)",
|
|
350
|
+
properties: {
|
|
351
|
+
track_number: { type: "number" },
|
|
352
|
+
disc_number: { type: "number", description: "Default 1" },
|
|
353
|
+
},
|
|
354
|
+
required: ["track_number"],
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
required: ["release_id", "from", "to"],
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
executor: this.moveTrack.bind(this),
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
definition: {
|
|
364
|
+
name: "pica_releases_attach_track_by_identifier",
|
|
365
|
+
description: "Attach a track by external identifier (ISRC, Spotify URL, Spotify " +
|
|
366
|
+
"track URI, YouTube video id, MusicBrainz recording id, MLC " +
|
|
367
|
+
"recording id). The identifier is resolved to an internal recording " +
|
|
368
|
+
"id in the caller's organisation before attaching. This tool does " +
|
|
369
|
+
"NOT create recordings — if the identifier resolves to nothing the " +
|
|
370
|
+
"call fails with a recovery hint pointing at pica_import_streaming_" +
|
|
371
|
+
"link or the relevant import tool. Intended for the post-import " +
|
|
372
|
+
"attach step. → then: pica_releases_list_tracks (verify tracklist).",
|
|
373
|
+
inputSchema: {
|
|
374
|
+
type: "object",
|
|
375
|
+
properties: {
|
|
376
|
+
release_id: { type: "string", description: "Release ID" },
|
|
377
|
+
identifier_type: {
|
|
87
378
|
type: "string",
|
|
88
|
-
|
|
379
|
+
enum: [
|
|
380
|
+
"isrc",
|
|
381
|
+
"spotify_url",
|
|
382
|
+
"spotify_track_uri",
|
|
383
|
+
"youtube_video_id",
|
|
384
|
+
"musicbrainz_recording_id",
|
|
385
|
+
"mlc_recording_id",
|
|
386
|
+
],
|
|
387
|
+
description: "Type of external identifier to resolve",
|
|
89
388
|
},
|
|
90
|
-
|
|
389
|
+
value: {
|
|
91
390
|
type: "string",
|
|
92
|
-
description: "
|
|
391
|
+
description: "The identifier value itself",
|
|
392
|
+
},
|
|
393
|
+
track_number: {
|
|
394
|
+
type: "number",
|
|
395
|
+
description: "Position on disc (1-based)",
|
|
396
|
+
},
|
|
397
|
+
disc_number: {
|
|
398
|
+
type: "number",
|
|
399
|
+
description: "Disc number (default 1)",
|
|
93
400
|
},
|
|
94
|
-
|
|
401
|
+
},
|
|
402
|
+
required: [
|
|
403
|
+
"release_id",
|
|
404
|
+
"identifier_type",
|
|
405
|
+
"value",
|
|
406
|
+
"track_number",
|
|
407
|
+
],
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
executor: this.attachTrackByIdentifier.bind(this),
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
definition: {
|
|
414
|
+
name: "pica_releases_create_with_tracks",
|
|
415
|
+
description: "Create a release and its tracks in a single atomic transaction. " +
|
|
416
|
+
"Any failure — FK violation, identifier lookup miss, invalid track " +
|
|
417
|
+
"entry — rolls the entire release back. No partial releases. Each " +
|
|
418
|
+
"track entry can pass recording_id/work_id directly OR pass an " +
|
|
419
|
+
"identifier_lookup object which the tool resolves server-side " +
|
|
420
|
+
"(same semantics as pica_releases_attach_track_by_identifier). " +
|
|
421
|
+
"Use this when importing a new album — use pica_releases_bulk_" +
|
|
422
|
+
"attach_tracks when the release already exists.",
|
|
423
|
+
inputSchema: {
|
|
424
|
+
type: "object",
|
|
425
|
+
properties: {
|
|
426
|
+
release: {
|
|
427
|
+
type: "object",
|
|
428
|
+
description: "Release fields (same shape as pica_releases_create). " +
|
|
429
|
+
"title is required; release_type defaults to 'single'.",
|
|
430
|
+
properties: {
|
|
431
|
+
title: { type: "string", description: "Release title" },
|
|
432
|
+
release_type: {
|
|
433
|
+
type: "string",
|
|
434
|
+
enum: ["album", "ep", "single", "compilation"],
|
|
435
|
+
description: "Release type (default 'single')",
|
|
436
|
+
},
|
|
437
|
+
release_date: {
|
|
438
|
+
type: "string",
|
|
439
|
+
description: "Release date (YYYY-MM-DD)",
|
|
440
|
+
},
|
|
441
|
+
pre_release_date: {
|
|
442
|
+
type: "string",
|
|
443
|
+
description: "Pre-release / announcement date (YYYY-MM-DD)",
|
|
444
|
+
},
|
|
445
|
+
upc: { type: "string", description: "UPC / EAN barcode" },
|
|
446
|
+
catalog_number: {
|
|
447
|
+
type: "string",
|
|
448
|
+
description: "Label catalog number",
|
|
449
|
+
},
|
|
450
|
+
label_organization_id: {
|
|
451
|
+
type: "string",
|
|
452
|
+
description: "organisations.id of the label — resolve via pica_labels_query first.",
|
|
453
|
+
},
|
|
454
|
+
distributor_organization_id: {
|
|
455
|
+
type: "string",
|
|
456
|
+
description: "organisations.id of the distributor.",
|
|
457
|
+
},
|
|
458
|
+
artwork_url: {
|
|
459
|
+
type: "string",
|
|
460
|
+
description: "Album artwork URL",
|
|
461
|
+
},
|
|
462
|
+
spotify_album_uri: { type: "string" },
|
|
463
|
+
spotify_url: { type: "string" },
|
|
464
|
+
apple_music_url: { type: "string" },
|
|
465
|
+
other_urls: {
|
|
466
|
+
type: "object",
|
|
467
|
+
additionalProperties: { type: "string" },
|
|
468
|
+
},
|
|
469
|
+
notes: { type: "string" },
|
|
470
|
+
},
|
|
471
|
+
required: ["title"],
|
|
472
|
+
},
|
|
473
|
+
tracks: {
|
|
474
|
+
type: "array",
|
|
475
|
+
description: "Track entries. Each needs track_number plus one of: " +
|
|
476
|
+
"recording_id, work_id, or identifier_lookup.",
|
|
477
|
+
items: {
|
|
478
|
+
type: "object",
|
|
479
|
+
properties: {
|
|
480
|
+
recording_id: { type: "string" },
|
|
481
|
+
work_id: { type: "string" },
|
|
482
|
+
identifier_lookup: {
|
|
483
|
+
type: "object",
|
|
484
|
+
description: "Resolve a recording by external identifier in " +
|
|
485
|
+
"the caller's org before inserting the track. " +
|
|
486
|
+
"Misses and collisions abort the whole create.",
|
|
487
|
+
properties: {
|
|
488
|
+
identifier_type: {
|
|
489
|
+
type: "string",
|
|
490
|
+
enum: [
|
|
491
|
+
"isrc",
|
|
492
|
+
"spotify_url",
|
|
493
|
+
"spotify_track_uri",
|
|
494
|
+
"youtube_video_id",
|
|
495
|
+
"musicbrainz_recording_id",
|
|
496
|
+
"mlc_recording_id",
|
|
497
|
+
],
|
|
498
|
+
},
|
|
499
|
+
value: { type: "string" },
|
|
500
|
+
},
|
|
501
|
+
required: ["identifier_type", "value"],
|
|
502
|
+
},
|
|
503
|
+
track_number: {
|
|
504
|
+
type: "number",
|
|
505
|
+
description: "Position on disc (1-based)",
|
|
506
|
+
},
|
|
507
|
+
disc_number: {
|
|
508
|
+
type: "number",
|
|
509
|
+
description: "Disc number (default 1)",
|
|
510
|
+
},
|
|
511
|
+
},
|
|
512
|
+
required: ["track_number"],
|
|
513
|
+
},
|
|
514
|
+
},
|
|
515
|
+
},
|
|
516
|
+
required: ["release", "tracks"],
|
|
517
|
+
},
|
|
518
|
+
},
|
|
519
|
+
executor: this.createWithTracks.bind(this),
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
definition: {
|
|
523
|
+
name: "pica_releases_completeness_check",
|
|
524
|
+
description: "Run the release-scoped completeness diligence report. Pass a " +
|
|
525
|
+
"release_id for a single-release report, or omit for a scan of " +
|
|
526
|
+
"every release in the caller's organisation. Returns a list of " +
|
|
527
|
+
"issues per release with severity (critical/warning/suggestion) " +
|
|
528
|
+
"and a recovery hint pointing at the right tool. Issues also " +
|
|
529
|
+
"surface in pica_catalog_diligence; this tool gives release-" +
|
|
530
|
+
"level granularity.",
|
|
531
|
+
inputSchema: {
|
|
532
|
+
type: "object",
|
|
533
|
+
properties: {
|
|
534
|
+
release_id: {
|
|
95
535
|
type: "string",
|
|
96
|
-
description: "
|
|
536
|
+
description: "Optional — a single release to check. Omit to scan " +
|
|
537
|
+
"every release in the organisation.",
|
|
97
538
|
},
|
|
98
539
|
},
|
|
99
|
-
required: ["id"],
|
|
100
540
|
},
|
|
101
541
|
},
|
|
102
|
-
executor: this.
|
|
542
|
+
executor: this.completenessCheck.bind(this),
|
|
103
543
|
},
|
|
104
544
|
];
|
|
105
545
|
}
|
|
546
|
+
async attachTrack(args) {
|
|
547
|
+
const track = await this.pica.releases.attachTrack(args.release_id, {
|
|
548
|
+
recording_id: args.recording_id ?? null,
|
|
549
|
+
work_id: args.work_id ?? null,
|
|
550
|
+
track_number: args.track_number,
|
|
551
|
+
disc_number: args.disc_number,
|
|
552
|
+
});
|
|
553
|
+
return formatSuccess("Track attached to release", track);
|
|
554
|
+
}
|
|
555
|
+
async listTracks(args) {
|
|
556
|
+
const tracks = await this.pica.releases.listTracks(args.release_id);
|
|
557
|
+
return formatSuccess("Release tracks retrieved", tracks);
|
|
558
|
+
}
|
|
559
|
+
async detachTrack(args) {
|
|
560
|
+
const result = await this.pica.releases.detachTrack(args.release_id, {
|
|
561
|
+
track_number: args.track_number,
|
|
562
|
+
disc_number: args.disc_number,
|
|
563
|
+
confirm: args.confirm,
|
|
564
|
+
});
|
|
565
|
+
const message = result?.data?.confirmed
|
|
566
|
+
? "Track detached from release"
|
|
567
|
+
: "Preview of track to be detached — call again with confirm:true to execute";
|
|
568
|
+
return formatSuccess(message, result);
|
|
569
|
+
}
|
|
570
|
+
async reorderTracks(args) {
|
|
571
|
+
const tracks = await this.pica.releases.reorderTracks(args.release_id, args.new_order);
|
|
572
|
+
return formatSuccess("Release tracks reordered", tracks);
|
|
573
|
+
}
|
|
574
|
+
async attachRecordingWithWork(args) {
|
|
575
|
+
const track = await this.pica.releases.attachRecordingWithWork(args.release_id, {
|
|
576
|
+
recording_id: args.recording_id,
|
|
577
|
+
track_number: args.track_number,
|
|
578
|
+
disc_number: args.disc_number,
|
|
579
|
+
});
|
|
580
|
+
return formatSuccess("Recording attached to release with work", track);
|
|
581
|
+
}
|
|
106
582
|
async listReleases(args) {
|
|
107
583
|
const result = await this.pica.releases.list({
|
|
108
584
|
limit: args.limit,
|
|
@@ -124,5 +600,35 @@ export class ReleasesTools {
|
|
|
124
600
|
const release = await this.pica.releases.update(id, updates);
|
|
125
601
|
return formatSuccess("Release updated", release);
|
|
126
602
|
}
|
|
603
|
+
// ADR-175 workflow executors
|
|
604
|
+
async bulkAttachTracks(args) {
|
|
605
|
+
const tracks = await this.pica.releases.bulkAttachTracks(args.release_id, args.tracks);
|
|
606
|
+
return formatSuccess(`Bulk attached ${Array.isArray(args.tracks) ? args.tracks.length : 0} tracks`, tracks);
|
|
607
|
+
}
|
|
608
|
+
async moveTrack(args) {
|
|
609
|
+
const tracks = await this.pica.releases.moveTrack(args.release_id, args.from, args.to);
|
|
610
|
+
return formatSuccess("Tracks swapped", tracks);
|
|
611
|
+
}
|
|
612
|
+
async attachTrackByIdentifier(args) {
|
|
613
|
+
const result = await this.pica.releases.attachTrackByIdentifier(args.release_id, {
|
|
614
|
+
identifier_type: args.identifier_type,
|
|
615
|
+
value: args.value,
|
|
616
|
+
track_number: args.track_number,
|
|
617
|
+
disc_number: args.disc_number,
|
|
618
|
+
});
|
|
619
|
+
return formatSuccess("Track attached by identifier", result);
|
|
620
|
+
}
|
|
621
|
+
async createWithTracks(args) {
|
|
622
|
+
const result = await this.pica.releases.createWithTracks({
|
|
623
|
+
release: args.release,
|
|
624
|
+
tracks: args.tracks,
|
|
625
|
+
});
|
|
626
|
+
const count = Array.isArray(args.tracks) ? args.tracks.length : 0;
|
|
627
|
+
return formatSuccess(`Release created with ${count} tracks`, result);
|
|
628
|
+
}
|
|
629
|
+
async completenessCheck(args) {
|
|
630
|
+
const report = await this.pica.releases.completenessCheck(args.release_id ? { release_id: args.release_id } : undefined);
|
|
631
|
+
return formatSuccess("Release completeness report", report);
|
|
632
|
+
}
|
|
127
633
|
}
|
|
128
634
|
//# sourceMappingURL=releases.js.map
|