@withpica/mcp-sdk 3.19.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,29 @@ 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
+
14
37
  ## [3.19.0] - 2026-09-18
15
38
 
16
39
  ### Added
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
@@ -3568,6 +3681,20 @@ declare class ImportResource extends BaseResource {
3568
3681
  existingTitle: string;
3569
3682
  matchType: string;
3570
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
+ }>;
3571
3698
  newTracks: Array<{
3572
3699
  title: string;
3573
3700
  artists: Array<{
@@ -4592,6 +4719,18 @@ declare class RoyaltiesResource extends BaseResource {
4592
4719
  workId?: string;
4593
4720
  limit?: number;
4594
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>;
4595
4734
  stats(): Promise<any>;
4596
4735
  unmatched(opts?: {
4597
4736
  importBatchId?: string;
@@ -4636,7 +4775,7 @@ declare class StatementsResource extends BaseResource {
4636
4775
  * with `substrate_rows === 0` on a clause means "PICA does not know", not
4637
4776
  * "there are none" — the never-invent rule applied to a selection.
4638
4777
  */
4639
- export type SubstrateUnit = "works" | "credit_rows" | "audio_analysis_rows";
4778
+ export type SubstrateUnit = "works" | "credit_rows" | "audio_analysis_rows" | "audio_files";
4640
4779
  export interface CoverageEntry {
4641
4780
  clause: string;
4642
4781
  /**
@@ -4650,21 +4789,49 @@ export interface CoverageEntry {
4650
4789
  substrate_rows: number;
4651
4790
  /**
4652
4791
  * What `substrate_rows` counted. NOT the same unit as `org_rows`, which is
4653
- * always works: a role clause counts credits and a trait clause counts
4654
- * 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.
4655
4795
  */
4656
4796
  substrate_unit: SubstrateUnit;
4657
4797
  org_rows: number;
4658
4798
  }
4799
+ /**
4800
+ * @deprecated Never populated — `SelectionMember.playable` was always null
4801
+ * while it carried this type. It is now {@link MemberPlayable}.
4802
+ */
4659
4803
  export interface PlayableRef {
4660
4804
  source: "spotify" | "youtube" | "apple" | "audio_file";
4661
4805
  ref: string;
4662
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
+ }
4663
4830
  export interface SelectionMember {
4664
4831
  work_id: string;
4665
4832
  title: string;
4666
4833
  primary_artist: string | null;
4667
- playable: PlayableRef | null;
4834
+ playable: MemberPlayable | null;
4668
4835
  has_lyrics: boolean;
4669
4836
  }
4670
4837
  export interface ResolveResult {