@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 CHANGED
@@ -11,6 +11,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [3.6.0] - 2026-07-09
15
+
16
+ ### Added
17
+
18
+ - `SocietyAffiliation` gains `affiliation_kind?: "member" | "origin"` and
19
+ `Person` gains `origin_countries?: string[]` (ADR-292), mirroring the same
20
+ fields on the `pica_people_create` / `pica_people_update` write surface.
21
+
22
+ - **`IntegrityResource`** (`client.integrity`) — the SDK surface for the
23
+ registration integrity floor (PR #1595): `assessEntity` (work/recording/
24
+ release grains; release is a documented v1 no-op), `assessOrg`, and the
25
+ `waive` / `revokeWaiver` write pair backing `pica_integrity_waive`.
26
+
27
+ - **`requestWithEnvelope()`** on `BaseResource` — like `request()` but
28
+ returns the FULL parsed `{data, twin?, twin_error?}` envelope instead of
29
+ narrowing to `.data`. `WorksResource.create` / `RecordingsResource.create`
30
+ now use it, so the auto-twin routes' `twin`/`twin_error` sibling fields
31
+ reach callers — `Work`/`Recording` create responses carry `twin` and
32
+ `twin_error` merged onto the returned entity (commit 689298e3c).
33
+
34
+ ## [3.5.0] - 2026-07-07
35
+
36
+ ### Added
37
+
38
+ - `catalogStats()` accepts an optional `{ entity, group_by }` argument and
39
+ serialises it to the query string, powering the Oracle aggregation on
40
+ `pica_catalog_stats` (one-dimension breakdowns + entity totals). Overloaded so
41
+ a no-arg call still returns the precise `CatalogStats` envelope type; a call
42
+ with params returns the widened breakdown shape. Backward-compatible — the
43
+ no-arg request is byte-identical to before.
44
+
14
45
  ## [3.4.0] - 2026-07-06
15
46
 
16
47
  ### Changed
package/dist/index.d.ts CHANGED
@@ -277,6 +277,8 @@ export interface SocietyRegistration {
277
277
  export interface SocietyAffiliation {
278
278
  society_code: string;
279
279
  membership_number: string | null;
280
+ /** ADR-292: `member` (current, default) or `origin` (home-country society for that code). */
281
+ affiliation_kind?: "member" | "origin";
280
282
  }
281
283
  interface Work {
282
284
  id: string;
@@ -314,6 +316,11 @@ interface Work {
314
316
  licensing_notes?: string | null;
315
317
  created_at: string;
316
318
  updated_at: string;
319
+ twin?: {
320
+ id: string;
321
+ recording_title: string;
322
+ } | null;
323
+ twin_error?: string;
317
324
  }
318
325
  interface Person {
319
326
  id: string;
@@ -331,6 +338,8 @@ interface Person {
331
338
  outreach_state?: "ready" | "needs_email" | "needs_disambiguation" | "not_a_target" | "do_not_contact" | "previously_declined";
332
339
  /** Society affiliations (ADR-282: society-agnostic write shape). */
333
340
  society_affiliations?: SocietyAffiliation[];
341
+ /** ADR-292: heritage/origin countries (ISO 3166-1 alpha-2, text[] column on public.people). */
342
+ origin_countries?: string[];
334
343
  created_at: string;
335
344
  updated_at: string;
336
345
  }
@@ -344,6 +353,11 @@ interface Recording {
344
353
  society_registrations?: SocietyRegistration[];
345
354
  created_at: string;
346
355
  updated_at: string;
356
+ twin?: {
357
+ id: string;
358
+ title: string;
359
+ } | null;
360
+ twin_error?: string;
347
361
  }
348
362
  interface ProductionAssetLink {
349
363
  asset_id: string;
@@ -807,6 +821,19 @@ declare class BaseResource {
807
821
  private fetchWithTimeout;
808
822
  private fetchWithRetry;
809
823
  protected request<T>(method: string, path: string, body?: any): Promise<T>;
824
+ /**
825
+ * Like `request`, but returns the FULL parsed envelope instead of
826
+ * narrowing to `.data`. Needed by the two spreadsheet-moment auto-twin
827
+ * routes (`POST /admin/works`, `POST /admin/recordings`), whose response
828
+ * carries `twin`/`twin_error` as siblings of `data` — `request()`'s
829
+ * `return data.data || data` would otherwise silently drop them before
830
+ * the MCP tool ever sees a twin was created.
831
+ */
832
+ protected requestWithEnvelope<T>(method: string, path: string, body?: any): Promise<{
833
+ data: T;
834
+ twin?: unknown;
835
+ twin_error?: string;
836
+ }>;
810
837
  /**
811
838
  * Make a request whose SUCCESS body is raw text, not a JSON envelope —
812
839
  * for routes that stream a generated file (e.g. `text/csv`) rather than
@@ -854,9 +881,45 @@ declare class WorksResource extends BaseResource {
854
881
  sort?: "completeness_score:asc" | "completeness_score:desc" | "missing_field_count:asc" | "missing_field_count:desc" | "streaming_activity:asc" | "streaming_activity:desc";
855
882
  /** Filter to works registered with a collection society (case-insensitive code, e.g. 'ASCAP', 'PRS', 'GEMA'). */
856
883
  society_code?: string;
884
+ /** Filter by work type (song, instrumental, library, demo, sample). */
885
+ work_type?: string;
886
+ /** Filter by work status (demo, unreleased, released, pitched, placed, archived). */
887
+ work_status?: string;
888
+ /** Filter to works tagged with this genre (case-sensitive array-contains). */
889
+ genre?: string;
890
+ /** Filter to works whose primary recording carries this mood tag. */
891
+ mood?: string;
892
+ /** Filter to works whose primary recording tempo is >= this BPM. */
893
+ tempo_min?: number;
894
+ /** Filter to works whose primary recording tempo is <= this BPM. */
895
+ tempo_max?: number;
896
+ /** Exact primary-artist name match. */
897
+ primary_artist?: string;
898
+ /** Exact primary-artist name match (alias of primary_artist). */
899
+ artist?: string;
900
+ /** Filter by derived label (primary recording label, else primary release parent_label). */
901
+ label?: string;
902
+ /** Filter to works available (true) / not available (false) for licensing. */
903
+ available_for_licensing?: boolean;
904
+ /** Filter by the primary release's format (single, ep, album, compilation). */
905
+ release_format?: string;
906
+ /** Filter to featured (true) / non-featured (false) works. */
907
+ is_featured?: boolean;
908
+ /** Filter by directory-published state. */
909
+ published?: boolean;
910
+ /** Only works added/composed on or after this ISO date (YYYY-MM-DD). */
911
+ created_from?: string;
912
+ /** Only works added/composed on or before this ISO date (YYYY-MM-DD). */
913
+ created_to?: string;
914
+ /** Filter to works that have (true) or lack (false) an ISWC. */
915
+ has_iswc?: boolean;
916
+ /** Filter to works that have (true) or lack (false) a publisher_name. */
917
+ has_publisher?: boolean;
857
918
  }): Promise<PaginatedResult<Work>>;
858
919
  get(id: string): Promise<Work>;
859
- create(data: Partial<Work>): Promise<Work>;
920
+ create(data: Partial<Work> & {
921
+ create_twin?: boolean;
922
+ }): Promise<Work>;
860
923
  update(id: string, updates: Partial<Work>): Promise<Work>;
861
924
  delete(id: string): Promise<DeletionResult>;
862
925
  verify(id: string): Promise<Work>;
@@ -960,6 +1023,14 @@ declare class PeopleResource extends BaseResource {
960
1023
  record_kind?: "individual" | "placeholder" | "artefact";
961
1024
  /** Filter by outreach readiness. */
962
1025
  outreach_state?: "ready" | "needs_email" | "needs_disambiguation" | "not_a_target" | "do_not_contact" | "previously_declined";
1026
+ /** Filter to people who have (true) / lack (false) an email address. */
1027
+ has_email?: boolean;
1028
+ /** Filter to people who have (true) / lack (false) a phone number. */
1029
+ has_phone?: boolean;
1030
+ /** Filter to people holding ANY of these roles (array-overlap). */
1031
+ roles?: string[];
1032
+ /** Filter to people carrying ANY of these tags (array-overlap). */
1033
+ tags?: string[];
963
1034
  }): Promise<PaginatedResult<Person>>;
964
1035
  get(id: string): Promise<Person>;
965
1036
  create(data: Partial<Person>): Promise<Person>;
@@ -1135,6 +1206,79 @@ declare class CreditsBalanceResource extends BaseResource {
1135
1206
  declare class PicaScoreResource extends BaseResource {
1136
1207
  get(): Promise<PicaScore>;
1137
1208
  }
1209
+ /**
1210
+ * Registration Integrity Floor (spec 2026-07-09, Task 8). SDK-local types —
1211
+ * duplicated field-for-field from `lib/services/integrity-floor.ts`'s
1212
+ * exported shapes (the SDK does not import from `lib/`, mcp<->lib
1213
+ * isolation). Keep in sync by hand if the service's exported types change.
1214
+ */
1215
+ export type IntegrityGapCode = "WORK_NO_RECORDING" | "RECORDING_NO_WORK" | "RECORDING_NO_RELEASE" | "WORK_NO_WRITER" | "RECORDING_NO_OWNER" | "COLLABORATOR_NOT_INVITED" | "COLLABORATOR_NOT_ATTESTED";
1216
+ export type IntegrityEntityType = "work" | "recording" | "release" | "person";
1217
+ export interface AttestationProposal {
1218
+ kind: "send_attestation_invites";
1219
+ people: Array<{
1220
+ person_id: string;
1221
+ name: string;
1222
+ has_email: boolean;
1223
+ }>;
1224
+ tool: "pica_collaborators_invite_bulk";
1225
+ note: string;
1226
+ }
1227
+ export interface IntegrityGap {
1228
+ code: IntegrityGapCode;
1229
+ entity: {
1230
+ type: IntegrityEntityType;
1231
+ id: string;
1232
+ label: string;
1233
+ };
1234
+ severity: "critical" | "important";
1235
+ label: string;
1236
+ action_hint: string;
1237
+ proposed_action?: AttestationProposal;
1238
+ waivable: true;
1239
+ }
1240
+ export interface EntityAssessment {
1241
+ entity: {
1242
+ type: IntegrityEntityType;
1243
+ id: string;
1244
+ };
1245
+ gaps: IntegrityGap[];
1246
+ waived_count: number;
1247
+ }
1248
+ export interface OrgIntegritySummary {
1249
+ total_gaps: number;
1250
+ critical_gaps: number;
1251
+ waived_gaps: number;
1252
+ top_gaps: IntegrityGap[];
1253
+ attestation_pending: number;
1254
+ is_empty_catalog: boolean;
1255
+ }
1256
+ declare class IntegrityResource extends BaseResource {
1257
+ /**
1258
+ * GET /admin/integrity/assess?entity_type=&entity_id= -> single-entity assessment.
1259
+ * NOTE: for entity_type "release" this is a documented v1 no-op — no
1260
+ * release-grain gap code exists yet, so `gaps` is always empty by design
1261
+ * (see assessEntity's release branch in lib/services/integrity-floor.ts).
1262
+ */
1263
+ assessEntity(entityType: "work" | "recording" | "release", entityId: string): Promise<EntityAssessment>;
1264
+ /** GET /admin/integrity/assess (no params) -> org-grain summary. */
1265
+ assessOrg(): Promise<OrgIntegritySummary>;
1266
+ /**
1267
+ * POST /admin/integrity/waivers. Duplicate-active-waiver is a 409
1268
+ * (`ConflictError` on the app side) — surfaces here as a non-retryable
1269
+ * `ApiError` with `status === 409` (see `BaseResource.request`).
1270
+ */
1271
+ waive(input: {
1272
+ gap_code: string;
1273
+ entity_type: string;
1274
+ entity_id: string;
1275
+ reason: string;
1276
+ }): Promise<{
1277
+ id: string;
1278
+ }>;
1279
+ /** PATCH /admin/integrity/waivers { waiver_id, revoke: true }. No un-revoke path. */
1280
+ revokeWaiver(waiverId: string): Promise<void>;
1281
+ }
1138
1282
  interface PresignedUploadResult {
1139
1283
  uploadUrl: string;
1140
1284
  uploadId: string;
@@ -1273,6 +1417,18 @@ declare class AgreementsResource extends BaseResource {
1273
1417
  * the hood.
1274
1418
  */
1275
1419
  awaiting_signature?: boolean;
1420
+ /** Agreements with start_date on/after this ISO date (YYYY-MM-DD). */
1421
+ start_date_from?: string;
1422
+ /** Agreements with start_date on/before this ISO date. */
1423
+ start_date_to?: string;
1424
+ /** Agreements with end_date on/after this ISO date. */
1425
+ end_date_from?: string;
1426
+ /** Agreements with end_date on/before this ISO date. */
1427
+ end_date_to?: string;
1428
+ /** Active agreements whose end_date falls within N days from today. */
1429
+ expiring_within_days?: number;
1430
+ /** true → only agreements that have an end_date; false → only open-ended. */
1431
+ has_end_date?: boolean;
1276
1432
  limit?: number;
1277
1433
  offset?: number;
1278
1434
  }): Promise<Agreement[]>;
@@ -1496,9 +1652,23 @@ declare class RecordingsResource extends BaseResource {
1496
1652
  missing_field_count_gt?: number;
1497
1653
  /** ADR-270 §3.4 — filter: missing_field_count strictly less than this */
1498
1654
  missing_field_count_lt?: number;
1655
+ /** Structured Recall — filter to recordings with (true) or without (false) an ISRC */
1656
+ has_isrc?: boolean;
1657
+ /** Structured Recall — filter by version type */
1658
+ version_type?: string;
1659
+ /** Structured Recall — inclusive ISO date range on recordings.recorded_at */
1660
+ recorded_from?: string;
1661
+ /** Structured Recall — inclusive ISO date range on recordings.recorded_at */
1662
+ recorded_to?: string;
1663
+ /** Structured Recall — inclusive ISO date range on recordings.created_at */
1664
+ created_from?: string;
1665
+ /** Structured Recall — inclusive ISO date range on recordings.created_at */
1666
+ created_to?: string;
1499
1667
  }): Promise<PaginatedResult<Recording>>;
1500
1668
  get(id: string): Promise<Recording>;
1501
- create(data: Partial<Recording>): Promise<Recording>;
1669
+ create(data: Partial<Recording> & {
1670
+ create_twin?: boolean;
1671
+ }): Promise<Recording>;
1502
1672
  update(id: string, updates: Partial<Recording>): Promise<Recording>;
1503
1673
  delete(id: string): Promise<DeletionResult>;
1504
1674
  getByWork(workId: string): Promise<Recording[]>;
@@ -3652,6 +3822,8 @@ declare class ReleasesResource extends BaseResource {
3652
3822
  query?: string;
3653
3823
  upc?: string;
3654
3824
  spotify_album_id?: string;
3825
+ release_date_from?: string;
3826
+ release_date_to?: string;
3655
3827
  }): Promise<any>;
3656
3828
  get(id: string): Promise<any>;
3657
3829
  /**
@@ -4207,10 +4379,15 @@ export declare class PicaClient {
4207
4379
  shareSend: ShareSendResource;
4208
4380
  accessSimulate: AccessSimulateResource;
4209
4381
  approvals: ApprovalsResource;
4382
+ integrity: IntegrityResource;
4210
4383
  /**
4211
4384
  * Get accurate catalog stats via SQL counts (no pagination limits)
4212
4385
  */
4213
4386
  catalogStats(): Promise<CatalogStats>;
4387
+ catalogStats(params: {
4388
+ entity?: string;
4389
+ group_by?: string;
4390
+ }): Promise<CatalogStats | Record<string, unknown>>;
4214
4391
  constructor(config: PicaClientConfig);
4215
4392
  }
4216
4393
  export type { Work, Person, Recording, PaginatedResult, PicaClientConfig, SyncSearchParams, SyncTrack, SyncSearchResult, LicenseEnquiryInput, LicenseEnquiry, BookingEnquiry, WorkCredit, WorkCreditsInput, PicaScore, PicaScorePillar, AudioFile, AudioAnalysisStatus, PresignedUploadResult, CompleteUploadResult, IdentifyResult, MultimediaItem, Agreement, AgreementWorkLink, CreateAgreementFromTemplateParams, AgreementSendForSignatureResult, AgreementSendForSignatureSentEntry, AgreementSendForSignatureSkippedEntry, AgreementSendForSignatureSkipReason, SyncPlacement, SyncPlacementSource, SyncPlacementRecording, SyncPlacementWithRelations, SyncPlacementContactInput, SyncPlacementRecordingInput, SyncPlacementSourceInput, CreateSyncPlacementInput, UpdateSyncPlacementInput, SyncPlacementQueryParams, SyncPlacementStatus, SyncPlacementVerificationStatus, SyncPlacementConfidentialityLevel, SyncPlacementSourceKind, CatalogStats, NotificationsSummary, CreateUploadSessionInput, CreateUploadSessionResult, };