@withpica/mcp-sdk 3.15.0 → 3.17.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.17.0] - 2026-09-13
15
+
16
+ ### Fixed
17
+
18
+ - **`credits.atomicUpdate()` now returns what its type declares.** It went
19
+ through `request()`, whose `return data.data || data` narrowed the route's
20
+ `{ data, credit_id, work_id, allocation }` envelope to the bare credit row —
21
+ so `allocation` (the work's writer allocation after the edit, which
22
+ `pica_credit_update` promises in its description) was always `undefined`,
23
+ and the tool's `allocation.status` completion hints were dead code. It now
24
+ uses `requestWithEnvelope` and returns `{ credit_id, work_id, credit,
25
+ allocation }`. Callers that read credit fields off the top-level result
26
+ should read `result.credit` — the declared shape never promised them there.
27
+
28
+ ## [3.16.0] - 2026-09-09
29
+
30
+ ### Added
31
+
32
+ - `works.search()` accepts `has_lyrics` (boolean) and writes it to the query
33
+ string. Without it a caller could not count works holding a lyric sheet
34
+ without paging the whole catalogue, which is how a connector session came to
35
+ inspect one work, see `lyrics: null`, and report that lyrics were not being
36
+ stored for an org holding 178 of them (PICA FIX_LOG 2026-09-09).
37
+
38
+ ⚠️ **`@withpica/mcp-server` must not be published against 3.15.0 once its
39
+ `pica_works_query` declares `has_lyrics`.** `URLSearchParams` drops unknown
40
+ keys silently, so an older SDK would send no filter, the route would return the
41
+ unfiltered catalogue, and the tool description tells the agent to read `total`
42
+ as the answer — it would report every work as having lyrics. Publish this
43
+ package first.
44
+
14
45
  ## [3.15.0] - 2026-09-08
15
46
 
16
47
  ### Added
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> & {
@@ -1342,6 +1347,22 @@ export interface WorkCreditAtomicAddInput {
1342
1347
  share_pct?: number;
1343
1348
  notes?: string;
1344
1349
  }
1350
+ /**
1351
+ * In-place edit of ONE credit (2026-09-11). Every field optional; only the
1352
+ * fields present are written. `share_pct: null` records the share as
1353
+ * UNKNOWN, never as 0. `instrument` applies to a recording (master) credit.
1354
+ */
1355
+ export interface WorkCreditAtomicUpdateInput {
1356
+ credit_type?: WorkCreditAtomicAddInput["credit_type"];
1357
+ share_pct?: number | null;
1358
+ credited_name?: string | null;
1359
+ notes?: string | null;
1360
+ instrument?: string | null;
1361
+ }
1362
+ export interface AtomicCreditUpdateResult extends AtomicCreditResult {
1363
+ /** The work's writer allocation AFTER this change — closed / open / incomplete / no_writers / unscalable. */
1364
+ allocation?: Record<string, unknown>;
1365
+ }
1345
1366
  export interface AtomicCreditResult {
1346
1367
  credit_id: string;
1347
1368
  credit?: Record<string, unknown>;
@@ -1370,6 +1391,20 @@ declare class CreditsResource extends BaseResource {
1370
1391
  * semantics — never leaks 404 vs 403 via latency).
1371
1392
  */
1372
1393
  atomicRemove(workId: string, creditId: string): Promise<AtomicCreditResult>;
1394
+ /**
1395
+ * Edit one credit in place — the verb between add and remove.
1396
+ *
1397
+ * Goes through `requestWithEnvelope`, not `request()`: the route answers
1398
+ * `{ success, data: <credit row>, credit_id, work_id, allocation }` with
1399
+ * `allocation` as a SIBLING of `data`, and `request()`'s
1400
+ * `return data.data || data` narrowed that to the bare credit row — so
1401
+ * every caller received an object that matched none of this method's
1402
+ * declared return type, and `allocation` (which `pica_credit_update`
1403
+ * promises in its description) was always undefined. Measured 2026-09-12
1404
+ * on the #2210 preview; pinned by the holdout contract
1405
+ * `scenarios/contracts/credit-update.spec.ts` leg 4.
1406
+ */
1407
+ atomicUpdate(workId: string, creditId: string, patch: WorkCreditAtomicUpdateInput): Promise<AtomicCreditUpdateResult>;
1373
1408
  /**
1374
1409
  * Send pending credits on a work to their recipients for attestation.
1375
1410
  * Lightweight alternative to pica_split_sheet_send — fans out the
@@ -1508,6 +1543,31 @@ interface IdentifyResult {
1508
1543
  confidence: number;
1509
1544
  };
1510
1545
  }
1546
+ export interface AudioFileTranscriptSegment {
1547
+ start: number;
1548
+ end: number;
1549
+ text: string;
1550
+ confidence?: number;
1551
+ }
1552
+ export interface AudioFileTranscript {
1553
+ audio_file_id: string;
1554
+ has_transcript: boolean;
1555
+ /** absent when has_transcript is false */
1556
+ work_id?: string | null;
1557
+ recording_id?: string | null;
1558
+ /** false when the transcript reaches no work — nothing else can show it */
1559
+ reaches_work?: boolean;
1560
+ transcript: {
1561
+ full_text: string;
1562
+ language: string | null;
1563
+ confidence: number | null;
1564
+ segment_count: number;
1565
+ segments: AudioFileTranscriptSegment[];
1566
+ processor: string | null;
1567
+ model_version: string | null;
1568
+ created_at: string | null;
1569
+ } | null;
1570
+ }
1511
1571
  declare class AudioFilesResource extends BaseResource {
1512
1572
  list(params?: {
1513
1573
  work_id?: string;
@@ -1519,6 +1579,16 @@ declare class AudioFilesResource extends BaseResource {
1519
1579
  offset?: number;
1520
1580
  }): Promise<AudioFile[]>;
1521
1581
  get(id: string): Promise<AudioFile>;
1582
+ /**
1583
+ * The stored Whisper transcript for one audio file, linked to a work or not.
1584
+ *
1585
+ * Until 2026-09-07 a transcript was readable only as `works.lyrics` after
1586
+ * propagation, so a transcript on an unlinked file had no reader at all —
1587
+ * 218 of 558 on prod. `has_transcript: false` is a normal answer, not an
1588
+ * error, and `reaches_work` says whether this transcript can be seen
1589
+ * anywhere else.
1590
+ */
1591
+ getTranscript(id: string): Promise<AudioFileTranscript>;
1522
1592
  /**
1523
1593
  * Attach ALL orphan audio files whose suggested match is ISRC-high and
1524
1594
  * non-ambiguous, in one call. Pairings are recomputed server-side at
@@ -3208,7 +3278,12 @@ declare class ExportResource extends BaseResource {
3208
3278
  }): Promise<any>;
3209
3279
  }
3210
3280
  declare class DuplicatesResource extends BaseResource {
3211
- findDuplicates(entityType: "works" | "people" | "releases" | "recordings"): Promise<any>;
3281
+ /**
3282
+ * ⚠️ `audio_files` is findable but NOT mergeable — `merge` below keeps the
3283
+ * narrower union deliberately. Re-uploaded audio is resolved by a person
3284
+ * deleting a file, never by a merge (ops issue dcea642b, 2026-09-10).
3285
+ */
3286
+ findDuplicates(entityType: "works" | "people" | "releases" | "recordings" | "audio_files"): Promise<any>;
3212
3287
  merge(entityType: "work" | "person" | "recording" | "release", winnerId: string, loserIds: string[]): Promise<any>;
3213
3288
  }
3214
3289
  declare class EntityContextResource extends BaseResource {