@withpica/mcp-sdk 3.18.0 → 3.20.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,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [3.20.0] - 2026-09-26
15
+
16
+ ### Changed
17
+
18
+ - Licensing enquiry `proposed_budget_amount` / `proposed_budget_currency` are
19
+ optional on input and nullable on the returned enquiry (no budget given).
20
+ - `IdentifyResult` carries the flat ACRCloud identification the route actually
21
+ returns (`acrId`, `confidence`, `title`, `artist`, …); `match` is deprecated.
22
+ - `listEnrichmentProposals` accepts `entity_type: "audio_file"`.
23
+
24
+ ### Added
25
+
26
+ - `royalties.blockers(workId)` and `royalties.blockersCatalogue({ code, limit,
27
+ offset })` — ADR-321 Phase 0, over `GET /admin/works/{id}/money-blockers` and
28
+ `GET /admin/money-blockers`.
29
+ - **`health.getLowScoreWorksPage({ limit, offset, threshold })`** and
30
+ **`health.getWorksHealthPage({ limit, offset, unreconciledOnly })`** — the
31
+ paged health reads with the routes' `meta` (true `total` / scan progress).
32
+ The argument-less `getLowScoreWorks()` / `getWorksHealth()` are unchanged.
33
+ - **`audioFiles.bulkUpdate(items, { dry_run })`** —
34
+ `POST /admin/audio-files/bulk-update`, lean per-item results.
35
+ - **`audioFiles.list({ work_ids })`** — several works in one read.
36
+
37
+ ## [3.19.0] - 2026-09-18
38
+
39
+ ### Added
40
+
41
+ - **`exports.songDossiers({ work_ids })`** — `POST /admin/exports/song-dossiers`.
42
+ One ZIP of the song dossier (PDF + JSON) for each work named, returned as the
43
+ signed-URL JSON envelope plus a per-work `works[]` account. 1 to 60 ids; a
44
+ malformed id or a longer list is a 400.
45
+
14
46
  ## [3.18.0] - 2026-09-17
15
47
 
16
48
  ### Removed
package/dist/index.d.ts CHANGED
@@ -418,6 +418,32 @@ interface PicaScore {
418
418
  topActions: string[];
419
419
  calculatedAt: string;
420
420
  }
421
+ /** One item of `audioFiles.bulkUpdate` — the fields pica_audio_update sets. */
422
+ export interface AudioBulkUpdateItem {
423
+ id: string;
424
+ file_type?: "master" | "instrumental" | "stem" | "demo" | "version";
425
+ stem_label?: string | null;
426
+ version_label?: string | null;
427
+ title?: string;
428
+ }
429
+ export type AudioBulkUpdateItemResult = {
430
+ id: string;
431
+ status: "updated" | "would_update";
432
+ changed: Array<"file_type" | "stem_label" | "version_label" | "title">;
433
+ } | {
434
+ id: string;
435
+ status: "failed";
436
+ reason: string;
437
+ };
438
+ /** Response of POST /admin/audio-files/bulk-update. */
439
+ export interface AudioBulkUpdateResult {
440
+ dry_run: boolean;
441
+ requested: number;
442
+ /** Updated — or, on a dry run, would be updated. */
443
+ updated: number;
444
+ failed: number;
445
+ results: AudioBulkUpdateItemResult[];
446
+ }
421
447
  /**
422
448
  * Outcome of a server-recomputed bulk attach of high-confidence orphan-audio
423
449
  * matches (POST /admin/audio-files/bulk-assign-suggested). Mirrors
@@ -762,8 +788,9 @@ interface LicenseEnquiryInput {
762
788
  territory: string;
763
789
  duration: string;
764
790
  distribution?: string[];
765
- proposed_budget_amount: number;
766
- proposed_budget_currency: string;
791
+ /** Optional since 2026-09-25; omit or null for no budget given. */
792
+ proposed_budget_amount?: number | null;
793
+ proposed_budget_currency?: string;
767
794
  budget_notes?: string;
768
795
  }
769
796
  interface LicenseEnquiry {
@@ -779,7 +806,8 @@ interface LicenseEnquiry {
779
806
  territory: string;
780
807
  duration: string;
781
808
  distribution: string[] | null;
782
- proposed_budget_amount: number;
809
+ /** NULL = no budget given. */
810
+ proposed_budget_amount: number | null;
783
811
  proposed_budget_currency: string;
784
812
  budget_notes: string | null;
785
813
  status: string;
@@ -1533,6 +1561,22 @@ interface IdentifyResult {
1533
1561
  alreadyIdentified?: boolean;
1534
1562
  audioFileId?: string;
1535
1563
  message?: string;
1564
+ acrId?: string | null;
1565
+ confidence?: number | null;
1566
+ title?: string | null;
1567
+ artist?: string | null;
1568
+ album?: string | null;
1569
+ label?: string | null;
1570
+ releaseDate?: string | null;
1571
+ externalIds?: {
1572
+ isrc?: string[];
1573
+ upc?: string[];
1574
+ iswc?: string[];
1575
+ } | null;
1576
+ /**
1577
+ * @deprecated Never sent by the route — kept only so existing consumers
1578
+ * still compile. Read the flat fields above.
1579
+ */
1536
1580
  match?: {
1537
1581
  title?: string;
1538
1582
  artist?: string;
@@ -1571,6 +1615,8 @@ export interface AudioFileTranscript {
1571
1615
  declare class AudioFilesResource extends BaseResource {
1572
1616
  list(params?: {
1573
1617
  work_id?: string;
1618
+ /** Several works at once, sent comma-separated (route caps the count). */
1619
+ work_ids?: string[];
1574
1620
  file_type?: string;
1575
1621
  unprocessed?: boolean;
1576
1622
  unassigned?: boolean;
@@ -1623,6 +1669,15 @@ declare class AudioFilesResource extends BaseResource {
1623
1669
  version_label?: string | null;
1624
1670
  title?: string;
1625
1671
  }): Promise<AudioFile>;
1672
+ /**
1673
+ * Per-file metadata patches for up to 200 files in one request (ops issue
1674
+ * 5c53049a). Returns one lean result per item — `updated`, `would_update`
1675
+ * (dry run) or `failed` with a reason — never the rows. Wraps
1676
+ * POST /admin/audio-files/bulk-update.
1677
+ */
1678
+ bulkUpdate(items: AudioBulkUpdateItem[], params?: {
1679
+ dry_run?: boolean;
1680
+ }): Promise<AudioBulkUpdateResult>;
1626
1681
  analyze(id: string, options?: {
1627
1682
  forceReAnalyze?: boolean;
1628
1683
  enableAudio?: boolean;
@@ -1825,7 +1880,12 @@ declare class WorkspaceResource extends BaseResource {
1825
1880
  declare class ShareSendResource extends BaseResource {
1826
1881
  send(args: {
1827
1882
  entity_type: "recording" | "work" | "audio_file" | "document";
1828
- entity_id: string;
1883
+ /** one work. Give this OR entity_ids. */
1884
+ entity_id?: string;
1885
+ /** several works → one link, one email, in this order. */
1886
+ entity_ids?: string[];
1887
+ /** show split percentages to the recipient (default false). */
1888
+ include_splits?: boolean;
1829
1889
  recipient: {
1830
1890
  kind: "user_id" | "collaborator_id" | "email";
1831
1891
  value: string;
@@ -1839,6 +1899,7 @@ declare class ShareSendResource extends BaseResource {
1839
1899
  send_id: string;
1840
1900
  share_link_id: string;
1841
1901
  share_url: string;
1902
+ work_ids: string[];
1842
1903
  recipient_resolution: {
1843
1904
  classification: "internal_user" | "internal_contact" | "external";
1844
1905
  display_name: string | null;
@@ -2113,7 +2174,7 @@ declare class EnrichmentResource extends BaseResource {
2113
2174
  * for filtering by confidence band and recency.
2114
2175
  */
2115
2176
  listEnrichmentProposals(params?: {
2116
- entity_type?: "work" | "person" | "recording";
2177
+ entity_type?: "work" | "person" | "recording" | "audio_file";
2117
2178
  entity_id?: string;
2118
2179
  rule_id?: string;
2119
2180
  source?: string;
@@ -2364,9 +2425,61 @@ export interface CatalogHealthFixResult {
2364
2425
  verdict: unknown;
2365
2426
  outcomesRecorded: number;
2366
2427
  }
2428
+ /** `meta` of GET /admin/quality/completeness/low-score. */
2429
+ export interface LowScoreWorksPageMeta {
2430
+ threshold: number;
2431
+ limit: number;
2432
+ offset: number;
2433
+ count: number;
2434
+ /** Works below the threshold by the cached score; null when unknown. */
2435
+ total: number | null;
2436
+ has_more: boolean | null;
2437
+ }
2438
+ /** `meta` of GET /admin/quality/works-health. */
2439
+ export interface WorksHealthPageMeta {
2440
+ limit: number;
2441
+ offset: number;
2442
+ unreconciled_only: boolean;
2443
+ count: number;
2444
+ /** Candidate works assembled by this call. */
2445
+ scanned: number;
2446
+ /** Live works with a canonical node; null when unknown. */
2447
+ candidates_total: number | null;
2448
+ has_more: boolean;
2449
+ next_offset: number | null;
2450
+ }
2367
2451
  declare class HealthResource extends BaseResource {
2368
2452
  getWorksHealth(): Promise<any>;
2369
2453
  getLowScoreWorks(): Promise<any>;
2454
+ /**
2455
+ * One page of works below a completeness threshold, with the route's
2456
+ * `meta` (true `total` below the threshold, `has_more`). Backs
2457
+ * `pica_works_query {health_filter: "low_completeness"}` — the bare
2458
+ * `getLowScoreWorks()` above sends no limit/offset, so the tool used to
2459
+ * ignore both (ops issue 314325eb).
2460
+ */
2461
+ getLowScoreWorksPage(params: {
2462
+ limit?: number;
2463
+ offset?: number;
2464
+ threshold?: number;
2465
+ }): Promise<{
2466
+ data: any[];
2467
+ meta?: LowScoreWorksPageMeta;
2468
+ }>;
2469
+ /**
2470
+ * One page of the cross-org reconciliation scan, with the route's `meta`
2471
+ * (`scanned`, `candidates_total`, `next_offset`). `offset`/`limit` page the
2472
+ * candidate works, not the returned rows — see the route. Backs
2473
+ * `pica_works_query {health_filter: "needs_attention"}`.
2474
+ */
2475
+ getWorksHealthPage(params: {
2476
+ limit?: number;
2477
+ offset?: number;
2478
+ unreconciledOnly?: boolean;
2479
+ }): Promise<{
2480
+ data: any[];
2481
+ meta?: WorksHealthPageMeta;
2482
+ }>;
2370
2483
  getWorkCompleteness(workId: string): Promise<any>;
2371
2484
  /**
2372
2485
  * ADR-277 WS2 — opt-in per-field provenance for a work: one entry per
@@ -2476,11 +2589,11 @@ declare class SettingsResource extends BaseResource {
2476
2589
  * the auth context — `user_id` is never accepted (ADR-184 rule 2).
2477
2590
  *
2478
2591
  * The route lazy-creates the backing `people` row if the user's
2479
- * `user_profiles.person_id` is null, then fires
2480
- * `crossLinkOnIdentifierUpdate` so newly-visible cross-org credits
2481
- * appear on the next `pica_discoveries_query`. Response includes the
2482
- * count of new discoveries in each of the 3 typed tables so the
2483
- * agent can surface "found N more…" in the same conversation.
2592
+ * `user_profiles.person_id` is null. Identifiers are saved on that record
2593
+ * only; this call triggers no cross-org linking (a typed IPI is not
2594
+ * evidence).
2595
+ * Response includes the count of discoveries written in each of the 3
2596
+ * typed tables in the last 10 seconds.
2484
2597
  * ADR-189 Phase 3.
2485
2598
  */
2486
2599
  updateMyIdentity(params: {
@@ -3271,6 +3384,16 @@ declare class ExportResource extends BaseResource {
3271
3384
  };
3272
3385
  work_ids?: string[];
3273
3386
  }): Promise<any>;
3387
+ /**
3388
+ * One ZIP holding the song dossier (PDF + JSON) of each work named — the
3389
+ * work, its recordings, the releases they appear on, people, provenance and
3390
+ * consent — plus a manifest and README. Returns a signed-URL JSON envelope
3391
+ * with a per-work `works[]` account of what was included. 1–60 work ids;
3392
+ * a malformed id or a longer list is refused with a 400.
3393
+ */
3394
+ songDossiers(params: {
3395
+ work_ids: string[];
3396
+ }): Promise<any>;
3274
3397
  aiConsent(params?: {
3275
3398
  work_ids?: string[];
3276
3399
  }): Promise<any>;
@@ -3558,6 +3681,20 @@ declare class ImportResource extends BaseResource {
3558
3681
  existingTitle: string;
3559
3682
  matchType: string;
3560
3683
  }>;
3684
+ /**
3685
+ * Same title as a work under a different (or no recorded) artist. These
3686
+ * tracks stay in `newTracks`; optional because an older server omits it.
3687
+ */
3688
+ possibleMatches?: Array<{
3689
+ track: {
3690
+ title: string;
3691
+ externalId: string;
3692
+ };
3693
+ existingWorkId: string;
3694
+ existingTitle: string;
3695
+ existingArtist: string | null;
3696
+ reason: string;
3697
+ }>;
3561
3698
  newTracks: Array<{
3562
3699
  title: string;
3563
3700
  artists: Array<{
@@ -4582,6 +4719,18 @@ declare class RoyaltiesResource extends BaseResource {
4582
4719
  workId?: string;
4583
4720
  limit?: number;
4584
4721
  }): Promise<any[]>;
4722
+ /**
4723
+ * ADR-321 Phase 0 — what in one song's record is likely holding up its
4724
+ * society income. `state` is "clear" only when every area was checked;
4725
+ * `unchecked` lists areas that could not be.
4726
+ */
4727
+ blockers(workId: string): Promise<any>;
4728
+ /** ADR-321 Phase 0 — the catalogue roll-up: summary + songs not clear, paged. */
4729
+ blockersCatalogue(params?: {
4730
+ code?: string;
4731
+ limit?: number;
4732
+ offset?: number;
4733
+ }): Promise<any>;
4585
4734
  stats(): Promise<any>;
4586
4735
  unmatched(opts?: {
4587
4736
  importBatchId?: string;
@@ -4626,7 +4775,7 @@ declare class StatementsResource extends BaseResource {
4626
4775
  * with `substrate_rows === 0` on a clause means "PICA does not know", not
4627
4776
  * "there are none" — the never-invent rule applied to a selection.
4628
4777
  */
4629
- export type SubstrateUnit = "works" | "credit_rows" | "audio_analysis_rows";
4778
+ export type SubstrateUnit = "works" | "credit_rows" | "audio_analysis_rows" | "audio_files";
4630
4779
  export interface CoverageEntry {
4631
4780
  clause: string;
4632
4781
  /**
@@ -4640,21 +4789,49 @@ export interface CoverageEntry {
4640
4789
  substrate_rows: number;
4641
4790
  /**
4642
4791
  * What `substrate_rows` counted. NOT the same unit as `org_rows`, which is
4643
- * always works: a role clause counts credits and a trait clause counts
4644
- * audio analyses, so the two numbers are not two halves of one fraction.
4792
+ * always works: a role clause counts credits, a trait clause counts audio
4793
+ * analyses and a has_audio clause counts attached audio files, so the two
4794
+ * numbers are not two halves of one fraction.
4645
4795
  */
4646
4796
  substrate_unit: SubstrateUnit;
4647
4797
  org_rows: number;
4648
4798
  }
4799
+ /**
4800
+ * @deprecated Never populated — `SelectionMember.playable` was always null
4801
+ * while it carried this type. It is now {@link MemberPlayable}.
4802
+ */
4649
4803
  export interface PlayableRef {
4650
4804
  source: "spotify" | "youtube" | "apple" | "audio_file";
4651
4805
  ref: string;
4652
4806
  }
4807
+ /** One of a work's audio files other than its primary, in lean form. */
4808
+ export interface AudioVersionRef {
4809
+ audio_file_id: string;
4810
+ /** master / version / demo / instrumental / stem */
4811
+ file_type: string;
4812
+ /** stem label, else version label, else filename */
4813
+ label: string;
4814
+ }
4815
+ /**
4816
+ * What a selection member plays: its primary audio file (the master when it
4817
+ * has one — `is_master` false means a fallback pick) plus every other audio
4818
+ * file on the work, so a renderer can offer master, PA and stems as one
4819
+ * bundle. Null exactly when the work has no audio file. Owned audio only —
4820
+ * streaming pointers are not resolved into a member yet.
4821
+ */
4822
+ export interface MemberPlayable {
4823
+ audio_file_id: string;
4824
+ file_type: string;
4825
+ duration_seconds: number | null;
4826
+ label: string;
4827
+ is_master: boolean;
4828
+ versions: AudioVersionRef[];
4829
+ }
4653
4830
  export interface SelectionMember {
4654
4831
  work_id: string;
4655
4832
  title: string;
4656
4833
  primary_artist: string | null;
4657
- playable: PlayableRef | null;
4834
+ playable: MemberPlayable | null;
4658
4835
  has_lyrics: boolean;
4659
4836
  }
4660
4837
  export interface ResolveResult {