@withpica/mcp-sdk 3.4.0 → 3.6.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 +31 -0
- package/dist/index.d.ts +179 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +168 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -203,6 +203,37 @@ class BaseResource {
|
|
|
203
203
|
}
|
|
204
204
|
return (data.data || data);
|
|
205
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* Like `request`, but returns the FULL parsed envelope instead of
|
|
208
|
+
* narrowing to `.data`. Needed by the two spreadsheet-moment auto-twin
|
|
209
|
+
* routes (`POST /admin/works`, `POST /admin/recordings`), whose response
|
|
210
|
+
* carries `twin`/`twin_error` as siblings of `data` — `request()`'s
|
|
211
|
+
* `return data.data || data` would otherwise silently drop them before
|
|
212
|
+
* the MCP tool ever sees a twin was created.
|
|
213
|
+
*/
|
|
214
|
+
async requestWithEnvelope(method, path, body) {
|
|
215
|
+
const url = `${this.baseUrl}${path}`;
|
|
216
|
+
const timeoutMs = getTimeoutForPath(path);
|
|
217
|
+
if (this.debug) {
|
|
218
|
+
console.error(`[PICA SDK] ${method} ${url} (timeout: ${timeoutMs}ms)`);
|
|
219
|
+
}
|
|
220
|
+
const response = await this.fetchWithRetry(url, {
|
|
221
|
+
method,
|
|
222
|
+
headers: {
|
|
223
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
224
|
+
"Content-Type": "application/json",
|
|
225
|
+
...this.getBypassHeaders(),
|
|
226
|
+
},
|
|
227
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
228
|
+
}, timeoutMs);
|
|
229
|
+
const json = await response.json();
|
|
230
|
+
// Same success:false guard as `request()` — see its comment above.
|
|
231
|
+
if (json && typeof json === "object" && json.success === false) {
|
|
232
|
+
const msg = typeof json.error === "string" ? json.error : "unspecified error";
|
|
233
|
+
throw new ApiError(`API returned success:false: ${msg}`, response.status, false);
|
|
234
|
+
}
|
|
235
|
+
return json;
|
|
236
|
+
}
|
|
206
237
|
/**
|
|
207
238
|
* Make a request whose SUCCESS body is raw text, not a JSON envelope —
|
|
208
239
|
* for routes that stream a generated file (e.g. `text/csv`) rather than
|
|
@@ -312,6 +343,40 @@ class WorksResource extends BaseResource {
|
|
|
312
343
|
qp.set("sort", params.sort);
|
|
313
344
|
if (params.society_code)
|
|
314
345
|
qp.set("society_code", params.society_code);
|
|
346
|
+
if (params.work_type)
|
|
347
|
+
qp.set("work_type", params.work_type);
|
|
348
|
+
if (params.work_status)
|
|
349
|
+
qp.set("work_status", params.work_status);
|
|
350
|
+
if (params.genre)
|
|
351
|
+
qp.set("genre", params.genre);
|
|
352
|
+
if (params.mood)
|
|
353
|
+
qp.set("mood", params.mood);
|
|
354
|
+
if (params.tempo_min !== undefined)
|
|
355
|
+
qp.set("tempo_min", String(params.tempo_min));
|
|
356
|
+
if (params.tempo_max !== undefined)
|
|
357
|
+
qp.set("tempo_max", String(params.tempo_max));
|
|
358
|
+
if (params.primary_artist)
|
|
359
|
+
qp.set("primary_artist", params.primary_artist);
|
|
360
|
+
if (params.artist)
|
|
361
|
+
qp.set("artist", params.artist);
|
|
362
|
+
if (params.label)
|
|
363
|
+
qp.set("label", params.label);
|
|
364
|
+
if (params.available_for_licensing !== undefined)
|
|
365
|
+
qp.set("available_for_licensing", String(params.available_for_licensing));
|
|
366
|
+
if (params.release_format)
|
|
367
|
+
qp.set("release_format", params.release_format);
|
|
368
|
+
if (params.is_featured !== undefined)
|
|
369
|
+
qp.set("is_featured", String(params.is_featured));
|
|
370
|
+
if (params.published !== undefined)
|
|
371
|
+
qp.set("published", String(params.published));
|
|
372
|
+
if (params.created_from)
|
|
373
|
+
qp.set("created_from", params.created_from);
|
|
374
|
+
if (params.created_to)
|
|
375
|
+
qp.set("created_to", params.created_to);
|
|
376
|
+
if (params.has_iswc !== undefined)
|
|
377
|
+
qp.set("has_iswc", String(params.has_iswc));
|
|
378
|
+
if (params.has_publisher !== undefined)
|
|
379
|
+
qp.set("has_publisher", String(params.has_publisher));
|
|
315
380
|
const qs = qp.toString();
|
|
316
381
|
return this.requestPaginated("GET", `/admin/works${qs ? `?${qs}` : ""}`);
|
|
317
382
|
}
|
|
@@ -319,7 +384,19 @@ class WorksResource extends BaseResource {
|
|
|
319
384
|
return this.request("GET", `/admin/works/${id}`);
|
|
320
385
|
}
|
|
321
386
|
async create(data) {
|
|
322
|
-
|
|
387
|
+
// Spreadsheet-moment auto-twin — the route response carries `twin` /
|
|
388
|
+
// `twin_error` as siblings of `data`, which the plain `request()`
|
|
389
|
+
// helper would drop (it narrows to `.data`). Fetch the full envelope
|
|
390
|
+
// and merge the twin fields onto the returned Work so callers (and the
|
|
391
|
+
// MCP tool executor) can see them.
|
|
392
|
+
const envelope = await this.requestWithEnvelope("POST", "/admin/works", data);
|
|
393
|
+
return {
|
|
394
|
+
...envelope.data,
|
|
395
|
+
twin: envelope.twin ?? null,
|
|
396
|
+
...(envelope.twin_error !== undefined && {
|
|
397
|
+
twin_error: envelope.twin_error,
|
|
398
|
+
}),
|
|
399
|
+
};
|
|
323
400
|
}
|
|
324
401
|
async update(id, updates) {
|
|
325
402
|
return this.request("PATCH", `/admin/works/${id}`, updates);
|
|
@@ -409,6 +486,14 @@ class PeopleResource extends BaseResource {
|
|
|
409
486
|
qp.set("record_kind", params.record_kind);
|
|
410
487
|
if (params.outreach_state)
|
|
411
488
|
qp.set("outreach_state", params.outreach_state);
|
|
489
|
+
if (params.has_email !== undefined)
|
|
490
|
+
qp.set("has_email", String(params.has_email));
|
|
491
|
+
if (params.has_phone !== undefined)
|
|
492
|
+
qp.set("has_phone", String(params.has_phone));
|
|
493
|
+
if (params.roles && params.roles.length > 0)
|
|
494
|
+
qp.set("roles", params.roles.join(","));
|
|
495
|
+
if (params.tags && params.tags.length > 0)
|
|
496
|
+
qp.set("tags", params.tags.join(","));
|
|
412
497
|
const qs = qp.toString();
|
|
413
498
|
return this.requestPaginated("GET", `/admin/people${qs ? `?${qs}` : ""}`);
|
|
414
499
|
}
|
|
@@ -662,6 +747,37 @@ class PicaScoreResource extends BaseResource {
|
|
|
662
747
|
return this.request("GET", "/admin/pica-score");
|
|
663
748
|
}
|
|
664
749
|
}
|
|
750
|
+
class IntegrityResource extends BaseResource {
|
|
751
|
+
/**
|
|
752
|
+
* GET /admin/integrity/assess?entity_type=&entity_id= -> single-entity assessment.
|
|
753
|
+
* NOTE: for entity_type "release" this is a documented v1 no-op — no
|
|
754
|
+
* release-grain gap code exists yet, so `gaps` is always empty by design
|
|
755
|
+
* (see assessEntity's release branch in lib/services/integrity-floor.ts).
|
|
756
|
+
*/
|
|
757
|
+
async assessEntity(entityType, entityId) {
|
|
758
|
+
const qp = new URLSearchParams({
|
|
759
|
+
entity_type: entityType,
|
|
760
|
+
entity_id: entityId,
|
|
761
|
+
});
|
|
762
|
+
return this.request("GET", `/admin/integrity/assess?${qp.toString()}`);
|
|
763
|
+
}
|
|
764
|
+
/** GET /admin/integrity/assess (no params) -> org-grain summary. */
|
|
765
|
+
async assessOrg() {
|
|
766
|
+
return this.request("GET", "/admin/integrity/assess");
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* POST /admin/integrity/waivers. Duplicate-active-waiver is a 409
|
|
770
|
+
* (`ConflictError` on the app side) — surfaces here as a non-retryable
|
|
771
|
+
* `ApiError` with `status === 409` (see `BaseResource.request`).
|
|
772
|
+
*/
|
|
773
|
+
async waive(input) {
|
|
774
|
+
return this.request("POST", "/admin/integrity/waivers", input);
|
|
775
|
+
}
|
|
776
|
+
/** PATCH /admin/integrity/waivers { waiver_id, revoke: true }. No un-revoke path. */
|
|
777
|
+
async revokeWaiver(waiverId) {
|
|
778
|
+
await this.request("PATCH", "/admin/integrity/waivers", { waiver_id: waiverId, revoke: true });
|
|
779
|
+
}
|
|
780
|
+
}
|
|
665
781
|
class AudioFilesResource extends BaseResource {
|
|
666
782
|
async list(params) {
|
|
667
783
|
const queryParams = new URLSearchParams();
|
|
@@ -771,6 +887,18 @@ class AgreementsResource extends BaseResource {
|
|
|
771
887
|
queryParams.set("includeWorkCounts", "true");
|
|
772
888
|
if (params?.awaiting_signature)
|
|
773
889
|
queryParams.set("awaiting_signature", "true");
|
|
890
|
+
if (params?.start_date_from)
|
|
891
|
+
queryParams.set("start_date_from", params.start_date_from);
|
|
892
|
+
if (params?.start_date_to)
|
|
893
|
+
queryParams.set("start_date_to", params.start_date_to);
|
|
894
|
+
if (params?.end_date_from)
|
|
895
|
+
queryParams.set("end_date_from", params.end_date_from);
|
|
896
|
+
if (params?.end_date_to)
|
|
897
|
+
queryParams.set("end_date_to", params.end_date_to);
|
|
898
|
+
if (params?.expiring_within_days !== undefined)
|
|
899
|
+
queryParams.set("expiring_within_days", String(params.expiring_within_days));
|
|
900
|
+
if (params?.has_end_date !== undefined)
|
|
901
|
+
queryParams.set("has_end_date", String(params.has_end_date));
|
|
774
902
|
if (params?.limit !== undefined)
|
|
775
903
|
queryParams.set("limit", String(params.limit));
|
|
776
904
|
if (params?.offset !== undefined)
|
|
@@ -1046,6 +1174,18 @@ class RecordingsResource extends BaseResource {
|
|
|
1046
1174
|
qp.set("missing_field_count_gt", String(params.missing_field_count_gt));
|
|
1047
1175
|
if (params.missing_field_count_lt !== undefined)
|
|
1048
1176
|
qp.set("missing_field_count_lt", String(params.missing_field_count_lt));
|
|
1177
|
+
if (params.has_isrc !== undefined)
|
|
1178
|
+
qp.set("has_isrc", String(params.has_isrc));
|
|
1179
|
+
if (params.version_type)
|
|
1180
|
+
qp.set("version_type", params.version_type);
|
|
1181
|
+
if (params.recorded_from)
|
|
1182
|
+
qp.set("recorded_from", params.recorded_from);
|
|
1183
|
+
if (params.recorded_to)
|
|
1184
|
+
qp.set("recorded_to", params.recorded_to);
|
|
1185
|
+
if (params.created_from)
|
|
1186
|
+
qp.set("created_from", params.created_from);
|
|
1187
|
+
if (params.created_to)
|
|
1188
|
+
qp.set("created_to", params.created_to);
|
|
1049
1189
|
const qs = qp.toString();
|
|
1050
1190
|
return this.requestPaginated("GET", `/admin/recordings?${qs}`);
|
|
1051
1191
|
}
|
|
@@ -1053,7 +1193,18 @@ class RecordingsResource extends BaseResource {
|
|
|
1053
1193
|
return this.request("GET", `/admin/recordings/${id}`);
|
|
1054
1194
|
}
|
|
1055
1195
|
async create(data) {
|
|
1056
|
-
|
|
1196
|
+
// Spreadsheet-moment auto-twin — mirrors WorksResource.create above:
|
|
1197
|
+
// fetch the full envelope so `twin`/`twin_error` survive onto the
|
|
1198
|
+
// returned Recording instead of being dropped by `request()`'s
|
|
1199
|
+
// `.data`-only narrowing.
|
|
1200
|
+
const envelope = await this.requestWithEnvelope("POST", "/admin/recordings", data);
|
|
1201
|
+
return {
|
|
1202
|
+
...envelope.data,
|
|
1203
|
+
twin: envelope.twin ?? null,
|
|
1204
|
+
...(envelope.twin_error !== undefined && {
|
|
1205
|
+
twin_error: envelope.twin_error,
|
|
1206
|
+
}),
|
|
1207
|
+
};
|
|
1057
1208
|
}
|
|
1058
1209
|
async update(id, updates) {
|
|
1059
1210
|
return this.request("PATCH", `/admin/recordings/${id}`, updates);
|
|
@@ -2914,6 +3065,10 @@ class ReleasesResource extends BaseResource {
|
|
|
2914
3065
|
parts.push(`upc=${encodeURIComponent(params.upc)}`);
|
|
2915
3066
|
if (params?.spotify_album_id)
|
|
2916
3067
|
parts.push(`spotify_album_id=${encodeURIComponent(params.spotify_album_id)}`);
|
|
3068
|
+
if (params?.release_date_from)
|
|
3069
|
+
parts.push(`release_date_from=${encodeURIComponent(params.release_date_from)}`);
|
|
3070
|
+
if (params?.release_date_to)
|
|
3071
|
+
parts.push(`release_date_to=${encodeURIComponent(params.release_date_to)}`);
|
|
2917
3072
|
const qs = parts.length > 0 ? `?${parts.join("&")}` : "";
|
|
2918
3073
|
return this.request("GET", `/admin/releases${qs}`);
|
|
2919
3074
|
}
|
|
@@ -3553,13 +3708,18 @@ export class PicaClient {
|
|
|
3553
3708
|
shareSend;
|
|
3554
3709
|
accessSimulate;
|
|
3555
3710
|
approvals;
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
async catalogStats() {
|
|
3711
|
+
// Registration Integrity Floor (spec 2026-07-09, Task 8).
|
|
3712
|
+
integrity;
|
|
3713
|
+
async catalogStats(params) {
|
|
3560
3714
|
const baseUrl = this.works["baseUrl"];
|
|
3561
3715
|
const apiKey = this.works["apiKey"];
|
|
3562
|
-
const
|
|
3716
|
+
const qp = new URLSearchParams();
|
|
3717
|
+
if (params?.entity)
|
|
3718
|
+
qp.set("entity", params.entity);
|
|
3719
|
+
if (params?.group_by)
|
|
3720
|
+
qp.set("group_by", params.group_by);
|
|
3721
|
+
const suffix = qp.toString() ? `?${qp.toString()}` : "";
|
|
3722
|
+
const res = await fetch(`${baseUrl}/admin/catalog/stats${suffix}`, {
|
|
3563
3723
|
headers: {
|
|
3564
3724
|
Authorization: `Bearer ${apiKey}`,
|
|
3565
3725
|
"Content-Type": "application/json",
|
|
@@ -3658,6 +3818,7 @@ export class PicaClient {
|
|
|
3658
3818
|
this.shareSend = new ShareSendResource(baseUrl, config.apiKey, debug);
|
|
3659
3819
|
this.accessSimulate = new AccessSimulateResource(baseUrl, config.apiKey, debug);
|
|
3660
3820
|
this.approvals = new ApprovalsResource(baseUrl, config.apiKey, debug);
|
|
3821
|
+
this.integrity = new IntegrityResource(baseUrl, config.apiKey, debug);
|
|
3661
3822
|
}
|
|
3662
3823
|
}
|
|
3663
3824
|
//# sourceMappingURL=index.js.map
|