@withpica/mcp-sdk 3.14.0 → 3.16.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,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [3.16.0] - 2026-09-09
15
+
16
+ ### Added
17
+
18
+ - `works.search()` accepts `has_lyrics` (boolean) and writes it to the query
19
+ string. Without it a caller could not count works holding a lyric sheet
20
+ without paging the whole catalogue, which is how a connector session came to
21
+ inspect one work, see `lyrics: null`, and report that lyrics were not being
22
+ stored for an org holding 178 of them (PICA FIX_LOG 2026-09-09).
23
+
24
+ ⚠️ **`@withpica/mcp-server` must not be published against 3.15.0 once its
25
+ `pica_works_query` declares `has_lyrics`.** `URLSearchParams` drops unknown
26
+ keys silently, so an older SDK would send no filter, the route would return the
27
+ unfiltered catalogue, and the tool description tells the agent to read `total`
28
+ as the answer — it would report every work as having lyrics. Publish this
29
+ package first.
30
+
31
+ ## [3.15.0] - 2026-09-08
32
+
33
+ ### Added
34
+
35
+ - `selections` resource (ADR-319 saved catalog selections) — `list`,
36
+ `create`, `inspect` (id + optional `resolve`/`limit`/`offset`), `update`,
37
+ `delete` over `/admin/selections`. Backs the new `pica_selections_*` MCP
38
+ tools (Task 8).
39
+ - `health.catalogHealthFix` accepts an optional `selections` array
40
+ (`{ actionId, chosenPersonId }`) — the human choice a `resolve_person`
41
+ action needs. Type-only on this side (the body is forwarded as-is); the
42
+ route validates it.
43
+
14
44
  PR #2118 (`fix/avatar-import-path-2026-09-03`) is merged into the release branch, so its changes ship in the version below; publish in the order mcp-utils → mcp-sdk → mcp-server.
15
45
 
16
46
  ## [3.14.0] - 2026-09-04
package/dist/index.d.ts CHANGED
@@ -985,6 +985,11 @@ declare class WorksResource extends BaseResource {
985
985
  has_iswc?: boolean;
986
986
  /** Filter to works that have (true) or lack (false) a publisher_name. */
987
987
  has_publisher?: boolean;
988
+ /**
989
+ * Filter to works that have (true) or lack (false) a stored lyric sheet
990
+ * (works.lyrics; blank counts as lacking).
991
+ */
992
+ has_lyrics?: boolean;
988
993
  }): Promise<PaginatedResult<Work>>;
989
994
  get(id: string): Promise<Work>;
990
995
  create(data: Partial<Work> & {
@@ -1508,6 +1513,31 @@ interface IdentifyResult {
1508
1513
  confidence: number;
1509
1514
  };
1510
1515
  }
1516
+ export interface AudioFileTranscriptSegment {
1517
+ start: number;
1518
+ end: number;
1519
+ text: string;
1520
+ confidence?: number;
1521
+ }
1522
+ export interface AudioFileTranscript {
1523
+ audio_file_id: string;
1524
+ has_transcript: boolean;
1525
+ /** absent when has_transcript is false */
1526
+ work_id?: string | null;
1527
+ recording_id?: string | null;
1528
+ /** false when the transcript reaches no work — nothing else can show it */
1529
+ reaches_work?: boolean;
1530
+ transcript: {
1531
+ full_text: string;
1532
+ language: string | null;
1533
+ confidence: number | null;
1534
+ segment_count: number;
1535
+ segments: AudioFileTranscriptSegment[];
1536
+ processor: string | null;
1537
+ model_version: string | null;
1538
+ created_at: string | null;
1539
+ } | null;
1540
+ }
1511
1541
  declare class AudioFilesResource extends BaseResource {
1512
1542
  list(params?: {
1513
1543
  work_id?: string;
@@ -1519,6 +1549,16 @@ declare class AudioFilesResource extends BaseResource {
1519
1549
  offset?: number;
1520
1550
  }): Promise<AudioFile[]>;
1521
1551
  get(id: string): Promise<AudioFile>;
1552
+ /**
1553
+ * The stored Whisper transcript for one audio file, linked to a work or not.
1554
+ *
1555
+ * Until 2026-09-07 a transcript was readable only as `works.lyrics` after
1556
+ * propagation, so a transcript on an unlinked file had no reader at all —
1557
+ * 218 of 558 on prod. `has_transcript: false` is a normal answer, not an
1558
+ * error, and `reaches_work` says whether this transcript can be seen
1559
+ * anywhere else.
1560
+ */
1561
+ getTranscript(id: string): Promise<AudioFileTranscript>;
1522
1562
  /**
1523
1563
  * Attach ALL orphan audio files whose suggested match is ISRC-high and
1524
1564
  * non-ambiguous, in one call. Pairings are recomputed server-side at
@@ -2330,11 +2370,17 @@ declare class HealthResource extends BaseResource {
2330
2370
  /**
2331
2371
  * ADR-273 — apply accepted fix actions from a prior plan. Requires planToken
2332
2372
  * from catalogHealthPlan; accept is a list of actionIds (or "all_safe_auto").
2373
+ * `selections` carries the human choice a resolve_person action needs
2374
+ * ({ actionId, chosenPersonId }); a selection also accepts its action.
2333
2375
  * Returns honest per-action met/unmet plus a fresh verdict.
2334
2376
  */
2335
2377
  catalogHealthFix(body: {
2336
2378
  planToken: string;
2337
2379
  accept: string[];
2380
+ selections?: Array<{
2381
+ actionId: string;
2382
+ chosenPersonId: string;
2383
+ }>;
2338
2384
  }): Promise<CatalogHealthFixResult>;
2339
2385
  }
2340
2386
  declare class DashboardResource extends BaseResource {
@@ -4536,6 +4582,104 @@ declare class StatementsResource extends BaseResource {
4536
4582
  rows: unknown[];
4537
4583
  }): Promise<Record<string, unknown>>;
4538
4584
  }
4585
+ /**
4586
+ * ADR-319 — saved catalog selections. `mcp-sdk` is a standalone published
4587
+ * package with no access to the app's path aliases, so this is a hand-kept
4588
+ * mirror of `lib/services/catalog-selection/types.ts` rather than an
4589
+ * import. Keep the two in sync by hand when the shape changes.
4590
+ *
4591
+ * `evaluable`/`substrate_rows`/`org_rows` on {@link CoverageEntry} are the
4592
+ * whole point of the feature (ADR-319 Decision 3): a zero-member resolution
4593
+ * with `substrate_rows === 0` on a clause means "PICA does not know", not
4594
+ * "there are none" — the never-invent rule applied to a selection.
4595
+ */
4596
+ export type SubstrateUnit = "works" | "credit_rows" | "audio_analysis_rows";
4597
+ export interface CoverageEntry {
4598
+ clause: string;
4599
+ /**
4600
+ * False when the resolver had nothing to run the clause against — today,
4601
+ * a role class the vocabulary no longer carries, which a stored predicate
4602
+ * can still name. The clause is narrowed to nothing rather than dropped,
4603
+ * and this flag is what says the empty answer is PICA's ignorance rather
4604
+ * than the catalogue's.
4605
+ */
4606
+ evaluable: boolean;
4607
+ substrate_rows: number;
4608
+ /**
4609
+ * What `substrate_rows` counted. NOT the same unit as `org_rows`, which is
4610
+ * always works: a role clause counts credits and a trait clause counts
4611
+ * audio analyses, so the two numbers are not two halves of one fraction.
4612
+ */
4613
+ substrate_unit: SubstrateUnit;
4614
+ org_rows: number;
4615
+ }
4616
+ export interface PlayableRef {
4617
+ source: "spotify" | "youtube" | "apple" | "audio_file";
4618
+ ref: string;
4619
+ }
4620
+ export interface SelectionMember {
4621
+ work_id: string;
4622
+ title: string;
4623
+ primary_artist: string | null;
4624
+ playable: PlayableRef | null;
4625
+ has_lyrics: boolean;
4626
+ }
4627
+ export interface ResolveResult {
4628
+ members: SelectionMember[];
4629
+ total: number;
4630
+ coverage: CoverageEntry[];
4631
+ /** True when `total` exceeded the page size and members is a first page. */
4632
+ truncated: boolean;
4633
+ }
4634
+ export interface CatalogSelection {
4635
+ id: string;
4636
+ organisation_id: string;
4637
+ name: string;
4638
+ description: string | null;
4639
+ predicate: Record<string, unknown>;
4640
+ renderer: "listen" | "worklist";
4641
+ visibility: "private" | "shared" | "public";
4642
+ created_by: string | null;
4643
+ created_at: string;
4644
+ updated_at: string;
4645
+ last_resolved_at: string | null;
4646
+ last_resolved_count: number | null;
4647
+ is_deleted: boolean;
4648
+ }
4649
+ export interface CreateSelectionInput {
4650
+ name: string;
4651
+ description?: string;
4652
+ /** `{ version: 1, all: [...clauses] }` — validated server-side. */
4653
+ predicate: Record<string, unknown>;
4654
+ renderer?: "listen" | "worklist";
4655
+ }
4656
+ export interface UpdateSelectionInput {
4657
+ name?: string;
4658
+ description?: string;
4659
+ predicate?: Record<string, unknown>;
4660
+ }
4661
+ declare class SelectionsResource extends BaseResource {
4662
+ list(params?: {
4663
+ limit?: number;
4664
+ offset?: number;
4665
+ }): Promise<CatalogSelection[]>;
4666
+ create(data: CreateSelectionInput): Promise<CatalogSelection>;
4667
+ /**
4668
+ * Per-id read. `resolve: true` also resolves the predicate — the route
4669
+ * returns `{ selection, resolution }` instead of `{ selection }`, and
4670
+ * `resolution` is omitted below when the caller didn't ask for it.
4671
+ */
4672
+ inspect(id: string, opts?: {
4673
+ resolve?: boolean;
4674
+ limit?: number;
4675
+ offset?: number;
4676
+ }): Promise<{
4677
+ selection: CatalogSelection;
4678
+ resolution?: ResolveResult;
4679
+ }>;
4680
+ update(id: string, data: UpdateSelectionInput): Promise<CatalogSelection>;
4681
+ delete(id: string): Promise<void>;
4682
+ }
4539
4683
  declare class ShareLinksResource extends BaseResource {
4540
4684
  list(params?: {
4541
4685
  work_id?: string;
@@ -4859,6 +5003,8 @@ export declare class PicaClient {
4859
5003
  workForHire: WorkForHireResource;
4860
5004
  royalties: RoyaltiesResource;
4861
5005
  statements: StatementsResource;
5006
+ /** ADR-319 — saved catalog selections. */
5007
+ selections: SelectionsResource;
4862
5008
  shareLinks: ShareLinksResource;
4863
5009
  consent: ConsentResource;
4864
5010
  custody: CustodyResource;