@withpica/mcp-sdk 3.19.0 → 3.21.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.21.0] - 2026-09-29
15
+
16
+ ### Added
17
+
18
+ - `rights.propose(workId, body)`, `rights.status(ruleId)` and
19
+ `rights.inspect(workId)` — ADR-321 Phase 2, over
20
+ `POST /admin/works/{id}/rights/propose`, `GET /admin/rights/rules/{id}` and
21
+ `GET /admin/works/{id}/rights`.
22
+
23
+ ## [3.20.0] - 2026-09-26
24
+
25
+ ### Changed
26
+
27
+ - Licensing enquiry `proposed_budget_amount` / `proposed_budget_currency` are
28
+ optional on input and nullable on the returned enquiry (no budget given).
29
+ - `IdentifyResult` carries the flat ACRCloud identification the route actually
30
+ returns (`acrId`, `confidence`, `title`, `artist`, …); `match` is deprecated.
31
+ - `listEnrichmentProposals` accepts `entity_type: "audio_file"`.
32
+
33
+ ### Added
34
+
35
+ - `royalties.blockers(workId)` and `royalties.blockersCatalogue({ code, limit,
36
+ offset })` — ADR-321 Phase 0, over `GET /admin/works/{id}/money-blockers` and
37
+ `GET /admin/money-blockers`.
38
+ - **`health.getLowScoreWorksPage({ limit, offset, threshold })`** and
39
+ **`health.getWorksHealthPage({ limit, offset, unreconciledOnly })`** — the
40
+ paged health reads with the routes' `meta` (true `total` / scan progress).
41
+ The argument-less `getLowScoreWorks()` / `getWorksHealth()` are unchanged.
42
+ - **`audioFiles.bulkUpdate(items, { dry_run })`** —
43
+ `POST /admin/audio-files/bulk-update`, lean per-item results.
44
+ - **`audioFiles.list({ work_ids })`** — several works in one read.
45
+
14
46
  ## [3.19.0] - 2026-09-18
15
47
 
16
48
  ### 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;
@@ -997,6 +1025,13 @@ declare class WorksResource extends BaseResource {
997
1025
  }): Promise<Work>;
998
1026
  update(id: string, updates: Partial<Work>): Promise<Work>;
999
1027
  delete(id: string): Promise<DeletionResult>;
1028
+ /**
1029
+ * @deprecated `works` has no `is_verified` column, so PATCH /admin/works/[id]
1030
+ * refuses this body (VALIDATION_ERROR "unknown field 'is_verified'") on every
1031
+ * call. PICA keeps no work-level verified flag; the MCP tool
1032
+ * `pica_works_verify` no longer calls this. Kept only so the published SDK's
1033
+ * surface does not break; remove at the next major.
1034
+ */
1000
1035
  verify(id: string): Promise<Work>;
1001
1036
  bulkDelete(ids: string[]): Promise<void>;
1002
1037
  bulkMoveToPerformances(ids: string[]): Promise<unknown>;
@@ -1533,6 +1568,22 @@ interface IdentifyResult {
1533
1568
  alreadyIdentified?: boolean;
1534
1569
  audioFileId?: string;
1535
1570
  message?: string;
1571
+ acrId?: string | null;
1572
+ confidence?: number | null;
1573
+ title?: string | null;
1574
+ artist?: string | null;
1575
+ album?: string | null;
1576
+ label?: string | null;
1577
+ releaseDate?: string | null;
1578
+ externalIds?: {
1579
+ isrc?: string[];
1580
+ upc?: string[];
1581
+ iswc?: string[];
1582
+ } | null;
1583
+ /**
1584
+ * @deprecated Never sent by the route — kept only so existing consumers
1585
+ * still compile. Read the flat fields above.
1586
+ */
1536
1587
  match?: {
1537
1588
  title?: string;
1538
1589
  artist?: string;
@@ -1571,6 +1622,8 @@ export interface AudioFileTranscript {
1571
1622
  declare class AudioFilesResource extends BaseResource {
1572
1623
  list(params?: {
1573
1624
  work_id?: string;
1625
+ /** Several works at once, sent comma-separated (route caps the count). */
1626
+ work_ids?: string[];
1574
1627
  file_type?: string;
1575
1628
  unprocessed?: boolean;
1576
1629
  unassigned?: boolean;
@@ -1623,6 +1676,15 @@ declare class AudioFilesResource extends BaseResource {
1623
1676
  version_label?: string | null;
1624
1677
  title?: string;
1625
1678
  }): Promise<AudioFile>;
1679
+ /**
1680
+ * Per-file metadata patches for up to 200 files in one request (ops issue
1681
+ * 5c53049a). Returns one lean result per item — `updated`, `would_update`
1682
+ * (dry run) or `failed` with a reason — never the rows. Wraps
1683
+ * POST /admin/audio-files/bulk-update.
1684
+ */
1685
+ bulkUpdate(items: AudioBulkUpdateItem[], params?: {
1686
+ dry_run?: boolean;
1687
+ }): Promise<AudioBulkUpdateResult>;
1626
1688
  analyze(id: string, options?: {
1627
1689
  forceReAnalyze?: boolean;
1628
1690
  enableAudio?: boolean;
@@ -1825,7 +1887,12 @@ declare class WorkspaceResource extends BaseResource {
1825
1887
  declare class ShareSendResource extends BaseResource {
1826
1888
  send(args: {
1827
1889
  entity_type: "recording" | "work" | "audio_file" | "document";
1828
- entity_id: string;
1890
+ /** one work. Give this OR entity_ids. */
1891
+ entity_id?: string;
1892
+ /** several works → one link, one email, in this order. */
1893
+ entity_ids?: string[];
1894
+ /** show split percentages to the recipient (default false). */
1895
+ include_splits?: boolean;
1829
1896
  recipient: {
1830
1897
  kind: "user_id" | "collaborator_id" | "email";
1831
1898
  value: string;
@@ -1839,6 +1906,7 @@ declare class ShareSendResource extends BaseResource {
1839
1906
  send_id: string;
1840
1907
  share_link_id: string;
1841
1908
  share_url: string;
1909
+ work_ids: string[];
1842
1910
  recipient_resolution: {
1843
1911
  classification: "internal_user" | "internal_contact" | "external";
1844
1912
  display_name: string | null;
@@ -2113,7 +2181,7 @@ declare class EnrichmentResource extends BaseResource {
2113
2181
  * for filtering by confidence band and recency.
2114
2182
  */
2115
2183
  listEnrichmentProposals(params?: {
2116
- entity_type?: "work" | "person" | "recording";
2184
+ entity_type?: "work" | "person" | "recording" | "audio_file";
2117
2185
  entity_id?: string;
2118
2186
  rule_id?: string;
2119
2187
  source?: string;
@@ -2145,10 +2213,17 @@ declare class EnrichmentResource extends BaseResource {
2145
2213
  * `artist_title_to_youtube` recording-create), a uniqueness check
2146
2214
  * runs instead; conflicts return `{ status: 'create_conflict' }` and
2147
2215
  * cannot be forced.
2216
+ *
2217
+ * File-type questions (`entity_type: 'audio_file'`) take the owner's own
2218
+ * answer: `file_type` (master / version / instrumental / demo / stem) and,
2219
+ * for a stem, an optional `stem_label`. A refused answer is a 400 with
2220
+ * `code: 'INVALID_FILE_TYPE_ANSWER'`.
2148
2221
  */
2149
2222
  applyEnrichmentProposal(proposalId: string, options?: {
2150
2223
  force?: boolean;
2151
2224
  resolution_note?: string;
2225
+ file_type?: "master" | "version" | "instrumental" | "demo" | "stem";
2226
+ stem_label?: string;
2152
2227
  }): Promise<any>;
2153
2228
  /**
2154
2229
  * Reject a pending proposal. Content-hash suppression (ADR-163)
@@ -2364,9 +2439,61 @@ export interface CatalogHealthFixResult {
2364
2439
  verdict: unknown;
2365
2440
  outcomesRecorded: number;
2366
2441
  }
2442
+ /** `meta` of GET /admin/quality/completeness/low-score. */
2443
+ export interface LowScoreWorksPageMeta {
2444
+ threshold: number;
2445
+ limit: number;
2446
+ offset: number;
2447
+ count: number;
2448
+ /** Works below the threshold by the cached score; null when unknown. */
2449
+ total: number | null;
2450
+ has_more: boolean | null;
2451
+ }
2452
+ /** `meta` of GET /admin/quality/works-health. */
2453
+ export interface WorksHealthPageMeta {
2454
+ limit: number;
2455
+ offset: number;
2456
+ unreconciled_only: boolean;
2457
+ count: number;
2458
+ /** Candidate works assembled by this call. */
2459
+ scanned: number;
2460
+ /** Live works with a canonical node; null when unknown. */
2461
+ candidates_total: number | null;
2462
+ has_more: boolean;
2463
+ next_offset: number | null;
2464
+ }
2367
2465
  declare class HealthResource extends BaseResource {
2368
2466
  getWorksHealth(): Promise<any>;
2369
2467
  getLowScoreWorks(): Promise<any>;
2468
+ /**
2469
+ * One page of works below a completeness threshold, with the route's
2470
+ * `meta` (true `total` below the threshold, `has_more`). Backs
2471
+ * `pica_works_query {health_filter: "low_completeness"}` — the bare
2472
+ * `getLowScoreWorks()` above sends no limit/offset, so the tool used to
2473
+ * ignore both (ops issue 314325eb).
2474
+ */
2475
+ getLowScoreWorksPage(params: {
2476
+ limit?: number;
2477
+ offset?: number;
2478
+ threshold?: number;
2479
+ }): Promise<{
2480
+ data: any[];
2481
+ meta?: LowScoreWorksPageMeta;
2482
+ }>;
2483
+ /**
2484
+ * One page of the cross-org reconciliation scan, with the route's `meta`
2485
+ * (`scanned`, `candidates_total`, `next_offset`). `offset`/`limit` page the
2486
+ * candidate works, not the returned rows — see the route. Backs
2487
+ * `pica_works_query {health_filter: "needs_attention"}`.
2488
+ */
2489
+ getWorksHealthPage(params: {
2490
+ limit?: number;
2491
+ offset?: number;
2492
+ unreconciledOnly?: boolean;
2493
+ }): Promise<{
2494
+ data: any[];
2495
+ meta?: WorksHealthPageMeta;
2496
+ }>;
2370
2497
  getWorkCompleteness(workId: string): Promise<any>;
2371
2498
  /**
2372
2499
  * ADR-277 WS2 — opt-in per-field provenance for a work: one entry per
@@ -3568,6 +3695,20 @@ declare class ImportResource extends BaseResource {
3568
3695
  existingTitle: string;
3569
3696
  matchType: string;
3570
3697
  }>;
3698
+ /**
3699
+ * Same title as a work under a different (or no recorded) artist. These
3700
+ * tracks stay in `newTracks`; optional because an older server omits it.
3701
+ */
3702
+ possibleMatches?: Array<{
3703
+ track: {
3704
+ title: string;
3705
+ externalId: string;
3706
+ };
3707
+ existingWorkId: string;
3708
+ existingTitle: string;
3709
+ existingArtist: string | null;
3710
+ reason: string;
3711
+ }>;
3571
3712
  newTracks: Array<{
3572
3713
  title: string;
3573
3714
  artists: Array<{
@@ -4570,6 +4711,24 @@ declare class WorkForHireResource extends BaseResource {
4570
4711
  update(id: string, data: Record<string, any>): Promise<any>;
4571
4712
  delete(id: string): Promise<void>;
4572
4713
  }
4714
+ /**
4715
+ * ADR-321 Phase 2 — programmable rights. `propose` only proposes: the route
4716
+ * never activates a rule on an API key, and each party confirms by email.
4717
+ */
4718
+ declare class RightsResource extends BaseResource {
4719
+ /**
4720
+ * POST /admin/works/{id}/rights/propose. Body is one of
4721
+ * `{ rule: "song" }`, `{ rule: "master", recording_id }` or
4722
+ * `{ rule: "share", side?, recording_id?, subject_person_id, kind,
4723
+ * parties: [{ person_id, share_bp }], effective_from, effective_to? }`.
4724
+ * A refusal is a 422 carrying `details.reasons`.
4725
+ */
4726
+ propose(workId: string, body: Record<string, unknown>): Promise<any>;
4727
+ /** GET /admin/rights/rules/{id} — one rule's status and confirmations. */
4728
+ status(ruleId: string): Promise<any>;
4729
+ /** GET /admin/works/{id}/rights — every rule on a song, history, holds. */
4730
+ inspect(workId: string): Promise<any>;
4731
+ }
4573
4732
  declare class RoyaltiesResource extends BaseResource {
4574
4733
  payments(params?: {
4575
4734
  source?: string;
@@ -4592,6 +4751,18 @@ declare class RoyaltiesResource extends BaseResource {
4592
4751
  workId?: string;
4593
4752
  limit?: number;
4594
4753
  }): Promise<any[]>;
4754
+ /**
4755
+ * ADR-321 Phase 0 — what in one song's record is likely holding up its
4756
+ * society income. `state` is "clear" only when every area was checked;
4757
+ * `unchecked` lists areas that could not be.
4758
+ */
4759
+ blockers(workId: string): Promise<any>;
4760
+ /** ADR-321 Phase 0 — the catalogue roll-up: summary + songs not clear, paged. */
4761
+ blockersCatalogue(params?: {
4762
+ code?: string;
4763
+ limit?: number;
4764
+ offset?: number;
4765
+ }): Promise<any>;
4595
4766
  stats(): Promise<any>;
4596
4767
  unmatched(opts?: {
4597
4768
  importBatchId?: string;
@@ -4636,7 +4807,7 @@ declare class StatementsResource extends BaseResource {
4636
4807
  * with `substrate_rows === 0` on a clause means "PICA does not know", not
4637
4808
  * "there are none" — the never-invent rule applied to a selection.
4638
4809
  */
4639
- export type SubstrateUnit = "works" | "credit_rows" | "audio_analysis_rows";
4810
+ export type SubstrateUnit = "works" | "credit_rows" | "audio_analysis_rows" | "audio_files";
4640
4811
  export interface CoverageEntry {
4641
4812
  clause: string;
4642
4813
  /**
@@ -4650,21 +4821,49 @@ export interface CoverageEntry {
4650
4821
  substrate_rows: number;
4651
4822
  /**
4652
4823
  * 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.
4824
+ * always works: a role clause counts credits, a trait clause counts audio
4825
+ * analyses and a has_audio clause counts attached audio files, so the two
4826
+ * numbers are not two halves of one fraction.
4655
4827
  */
4656
4828
  substrate_unit: SubstrateUnit;
4657
4829
  org_rows: number;
4658
4830
  }
4831
+ /**
4832
+ * @deprecated Never populated — `SelectionMember.playable` was always null
4833
+ * while it carried this type. It is now {@link MemberPlayable}.
4834
+ */
4659
4835
  export interface PlayableRef {
4660
4836
  source: "spotify" | "youtube" | "apple" | "audio_file";
4661
4837
  ref: string;
4662
4838
  }
4839
+ /** One of a work's audio files other than its primary, in lean form. */
4840
+ export interface AudioVersionRef {
4841
+ audio_file_id: string;
4842
+ /** master / version / demo / instrumental / stem */
4843
+ file_type: string;
4844
+ /** stem label, else version label, else filename */
4845
+ label: string;
4846
+ }
4847
+ /**
4848
+ * What a selection member plays: its primary audio file (the master when it
4849
+ * has one — `is_master` false means a fallback pick) plus every other audio
4850
+ * file on the work, so a renderer can offer master, PA and stems as one
4851
+ * bundle. Null exactly when the work has no audio file. Owned audio only —
4852
+ * streaming pointers are not resolved into a member yet.
4853
+ */
4854
+ export interface MemberPlayable {
4855
+ audio_file_id: string;
4856
+ file_type: string;
4857
+ duration_seconds: number | null;
4858
+ label: string;
4859
+ is_master: boolean;
4860
+ versions: AudioVersionRef[];
4861
+ }
4663
4862
  export interface SelectionMember {
4664
4863
  work_id: string;
4665
4864
  title: string;
4666
4865
  primary_artist: string | null;
4667
- playable: PlayableRef | null;
4866
+ playable: MemberPlayable | null;
4668
4867
  has_lyrics: boolean;
4669
4868
  }
4670
4869
  export interface ResolveResult {
@@ -5045,6 +5244,8 @@ export declare class PicaClient {
5045
5244
  producerAgreements: ProducerAgreementsResource;
5046
5245
  workForHire: WorkForHireResource;
5047
5246
  royalties: RoyaltiesResource;
5247
+ /** ADR-321 Phase 2 — programmable rights (propose / status / inspect). */
5248
+ rights: RightsResource;
5048
5249
  statements: StatementsResource;
5049
5250
  /** ADR-319 — saved catalog selections. */
5050
5251
  selections: SelectionsResource;