@withpica/mcp-sdk 3.11.0 → 3.12.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/dist/index.js CHANGED
@@ -721,6 +721,46 @@ class BookingsResource extends BaseResource {
721
721
  return this.request("PATCH", `/admin/bookings/${encodeURIComponent(id)}`, data);
722
722
  }
723
723
  }
724
+ /**
725
+ * Live shows and tour credits (ADR-313). Wraps `/admin/shows` and
726
+ * `/admin/setlist-items/[id]`.
727
+ */
728
+ class ShowsResource extends BaseResource {
729
+ /** POST /admin/shows — log a dated show, or a tour credit. */
730
+ async log(payload) {
731
+ return this.request("POST", "/admin/shows", payload);
732
+ }
733
+ /**
734
+ * GET /admin/shows — list shows for the org (newest first), or the single
735
+ * show + its folded-in setlist when `id` is given.
736
+ */
737
+ async query(params) {
738
+ const qp = new URLSearchParams();
739
+ if (params?.id)
740
+ qp.set("id", params.id);
741
+ if (params?.from)
742
+ qp.set("from", params.from);
743
+ if (params?.to)
744
+ qp.set("to", params.to);
745
+ if (params?.venue)
746
+ qp.set("venue", params.venue);
747
+ if (params?.city)
748
+ qp.set("city", params.city);
749
+ if (params?.country)
750
+ qp.set("country", params.country);
751
+ if (params?.unfiled_only !== undefined)
752
+ qp.set("unfiled_only", String(params.unfiled_only));
753
+ const qs = qp.toString();
754
+ return this.request("GET", `/admin/shows${qs ? `?${qs}` : ""}`);
755
+ }
756
+ /**
757
+ * PATCH /admin/setlist-items/[id] — confirm a setlist match, a cover, a
758
+ * performer, or (with `venue_id` + `show_id`) a venue candidate.
759
+ */
760
+ async matchItem(id, payload) {
761
+ return this.request("PATCH", `/admin/setlist-items/${encodeURIComponent(id)}`, payload);
762
+ }
763
+ }
724
764
  class CreditsResource extends BaseResource {
725
765
  async listForWork(workId) {
726
766
  return this.request("GET", `/admin/works/${workId}/credits`);
@@ -735,9 +775,14 @@ class CreditsResource extends BaseResource {
735
775
  return this.request("POST", `/admin/works/${workId}/collaborators`, { collaborators: collaborators.credits });
736
776
  }
737
777
  /**
738
- * ADR-232 atomic add — INSERT a single work credit. Race-safe under
739
- * concurrent writes (replace_work_credits is read-modify-write and
740
- * therefore not atomic for this verb). Returns the new credit_id.
778
+ * ADR-232 atomic add — INSERT a single work credit. NOT replace
779
+ * semantics: the work-level POST /credits is an additive upsert that
780
+ * re-reads and re-writes the whole set, so it is not atomic for this
781
+ * verb. createWorkCredit routes the row to its canonical home —
782
+ * publishing roles to work_collaborators, master attribution to
783
+ * recording_credits, owner to recording_splits (ADR-252 WS-A; the
784
+ * legacy work_credits table was dropped at DB-M3). Returns the new
785
+ * credit_id.
741
786
  */
742
787
  async atomicAdd(workId, input) {
743
788
  return this.request("POST", `/admin/works/${workId}/credits/atomic-add`, input);
@@ -1473,6 +1518,14 @@ class EnrichmentResource extends BaseResource {
1473
1518
  * `pending` rows are visible — applied/rejected/expired are hidden
1474
1519
  * regardless of filter. See ADR-163 for the design.
1475
1520
  *
1521
+ * ⚠️ `pending` is not the same as "still worth asking". A finding the
1522
+ * catalogue has since ANSWERED by another route keeps that status — nothing
1523
+ * re-asks the question after mint time — and applying it refuses. Those are
1524
+ * excluded, matching what `/inspect/found` shows, and
1525
+ * `data.excluded_stale` ({count, reasons}) reports the drop so a short page
1526
+ * is distinguishable from a filtered one. Applied after pagination, so a
1527
+ * page may return fewer rows than `limit`.
1528
+ *
1476
1529
  * ADR-264 C1: supports min_confidence, max_confidence, created_after
1477
1530
  * for filtering by confidence band and recency.
1478
1531
  */
@@ -1497,6 +1550,8 @@ class EnrichmentResource extends BaseResource {
1497
1550
  query.max_confidence = String(params.max_confidence);
1498
1551
  if (params?.created_after)
1499
1552
  query.created_after = params.created_after;
1553
+ if (params?.review_shape)
1554
+ query.review_shape = "true";
1500
1555
  const qs = new URLSearchParams(query).toString();
1501
1556
  const path = qs
1502
1557
  ? `/admin/enrichment-proposals?${qs}`
@@ -1537,6 +1592,28 @@ class EnrichmentResource extends BaseResource {
1537
1592
  async bulkRejectProposals(input) {
1538
1593
  return this.request("POST", "/admin/enrichment-proposals/bulk-reject", input);
1539
1594
  }
1595
+ /**
1596
+ * Apply many pending proposals in one call — the accept side of the
1597
+ * /inspect/found queue.
1598
+ *
1599
+ * Takes ids only; unlike `bulkRejectProposals` there is deliberately no
1600
+ * `filter` form, because a filter that bulk-ACCEPTS is a different kind of
1601
+ * thing from one that bulk-dismisses: rejecting a mis-filtered set costs a
1602
+ * re-proposal, accepting one writes to the catalogue.
1603
+ *
1604
+ * Caps at 100 per call. ⚠️ **Partial success is normal** — apply branches
1605
+ * into four different update/create paths and each id is applied
1606
+ * independently, so `failed` being non-empty alongside a non-zero `applied`
1607
+ * is the expected shape, not an error. Never report a partial as a success.
1608
+ *
1609
+ * Returns `{ applied, failed: [{ id, error }], skipped }`. `skipped` is
1610
+ * always empty here (a non-pending id arrives as a `failed` entry carrying
1611
+ * its own message); the key exists so one client shape reads apply, reject
1612
+ * and undo alike.
1613
+ */
1614
+ async bulkApplyProposals(input) {
1615
+ return this.request("POST", "/admin/enrichment-proposals/bulk-apply", input);
1616
+ }
1540
1617
  /**
1541
1618
  * ADR-178: File a proposal sourced from open-web agent research.
1542
1619
  *
@@ -1804,10 +1881,12 @@ class GdprResource extends BaseResource {
1804
1881
  }
1805
1882
  class DiscoveriesResource extends BaseResource {
1806
1883
  /**
1807
- * Drain a pending discovered_credits row into a work_credits row in
1808
- * the caller's org. Check-and-set on statusreturns
1809
- * DISCOVERY_ALREADY_RESOLVED (409) if another session won the race.
1810
- * is_first_claim=true triggers the checkout pill on the agent surface.
1884
+ * Claim a pending discovered_credits row in the caller's org. ADR-252
1885
+ * WS-A: this is a STATUS TRANSITION on discovered_creditsno credit
1886
+ * row is written anywhere by this call. Check-and-set on status —
1887
+ * returns DISCOVERY_ALREADY_RESOLVED (409) if another session won the
1888
+ * race. is_first_claim=true triggers the checkout pill on the agent
1889
+ * surface.
1811
1890
  */
1812
1891
  async claimCredit(id) {
1813
1892
  return this.request("POST", `/admin/discoveries/${encodeURIComponent(id)}/claim-credit`, {});
@@ -1825,10 +1904,13 @@ class DiscoveriesResource extends BaseResource {
1825
1904
  return this.request("POST", `/admin/discoveries/${encodeURIComponent(id)}/claim-custody`, {});
1826
1905
  }
1827
1906
  /**
1828
- * INSTANT path — drain a pending discovered_artists row into the
1829
- * work_claims + work_credits tables via
1830
- * artistClaimingService.processClaimDecision. No +72h window; identity
1831
- * evidence was validated at discovery time.
1907
+ * INSTANT path — drain a pending discovered_artists row via
1908
+ * artistClaimingService.processClaimDecision: CAS-updates work_claims
1909
+ * and inserts the claimed performer credit. ADR-252 WS-A: a performer
1910
+ * credit is a MASTER credit, so it lands in recording_credits (role
1911
+ * 'Performer') on the work's sole recording — NOT the dropped
1912
+ * work_credits table. No +72h window; identity evidence was validated
1913
+ * at discovery time.
1832
1914
  *
1833
1915
  * Refuses with 409 ADMIN_REVIEW_IN_PROGRESS when an open artist_claims
1834
1916
  * row exists for the same (work, person) — see response body
@@ -2282,6 +2364,49 @@ class ExportResource extends BaseResource {
2282
2364
  const csv = await this.requestText("GET", path);
2283
2365
  return { format: params.format, csv };
2284
2366
  }
2367
+ /**
2368
+ * The three diligence documents that had no agent path at all until
2369
+ * 2026-07-30 (ADR-303). Each has had a working route and a fully-styled PDF
2370
+ * for months, reachable only by typing the URL, because the buttons that
2371
+ * opened them lived in the `/admin` page tree ADR-251 retired.
2372
+ *
2373
+ * `delivery=url` is the default here for the same reason PR 3 moved the other
2374
+ * exports onto it: `request()` calls `response.json()`, so an inline binary ZIP
2375
+ * cannot cross this transport. `inline` swaps to `format=json` for a sandboxed
2376
+ * agent that cannot fetch a signed S3 URL.
2377
+ */
2378
+ /**
2379
+ * The ADR-100 catalogue snapshot: score, financials, ownership coverage, gaps
2380
+ * with a suggested action for each, physical and production assets, and a
2381
+ * "what to do next" list.
2382
+ *
2383
+ * It had no agent path and no UI control — its buttons lived on the
2384
+ * `/admin/catalog` pages ADR-251 retired, which is why an 80%-implemented
2385
+ * "replace the nine fragments with one document" decision quietly stopped
2386
+ * being reachable at all. Restored 2026-07-30 rather than deleted: the
2387
+ * roadmap and the production-asset provenance exist nowhere else.
2388
+ */
2389
+ async picaSnapshot(params) {
2390
+ return this.request("POST", "/admin/exports/pica", {
2391
+ scope: params?.scope ?? "everything",
2392
+ ...(params?.work_ids?.length ? { workIds: params.work_ids } : {}),
2393
+ });
2394
+ }
2395
+ async ownershipRecord(params) {
2396
+ return this.request("GET", `/admin/exports/ownership-record?${params?.inline ? "format=json" : "delivery=url"}`);
2397
+ }
2398
+ async rightsProof(params) {
2399
+ return this.request("GET", `/admin/exports/rights-proof?${params?.inline ? "format=json" : "delivery=url"}`);
2400
+ }
2401
+ /**
2402
+ * The diligence PACK (the ZIP with its PDF). Distinct from
2403
+ * `analytics.catalogDiligence()`, which reads the same data as JSON and stays
2404
+ * the right tool for "am I ready to register?" — a question that wants an
2405
+ * answer, not a document.
2406
+ */
2407
+ async diligencePack(params) {
2408
+ return this.request("GET", `/admin/exports/catalog-diligence?${params?.inline ? "format=json" : "delivery=url"}`);
2409
+ }
2285
2410
  async songRegistration(params) {
2286
2411
  // Returns a signed-URL JSON envelope:
2287
2412
  // { success, data: { download_url, expires_at, file_size_bytes, s3_key, ... } }
@@ -2598,7 +2723,11 @@ class CollaboratorsResource extends BaseResource {
2598
2723
  }
2599
2724
  /**
2600
2725
  * ADR-157 warm path — accept an invite addressed to the authenticated
2601
- * user. Writes a real work_credits row and flips status to confirmed.
2726
+ * user, and flip its status to confirmed. The credit write is
2727
+ * grain-routed (ADR-265): a composition-grain invite writes
2728
+ * work_collaborators, a master/owner-grain invite attests the person's
2729
+ * pending recording_credits. ADR-252 WS-A dropped work_credits at
2730
+ * DB-M3, so no row is written there.
2602
2731
  */
2603
2732
  async accept(inviteId) {
2604
2733
  return this.request("POST", `/admin/collaborators/invites/${inviteId}/accept`);
@@ -2954,9 +3083,14 @@ class RecordingCreditsResource extends BaseResource {
2954
3083
  };
2955
3084
  }
2956
3085
  /**
2957
- * ADR-232 atomic remove — DELETE with `?atomic=1` so the route returns 403
2958
- * INSUFFICIENT_SCOPE on 0-row instead of the legacy lenient silent
2959
- * success. AC-2 strict semantics for pica_credit_remove.
3086
+ * ADR-232 atomic remove — the route returns 403 INSUFFICIENT_SCOPE on a
3087
+ * 0-row delete. AC-2 strict semantics for pica_credit_remove.
3088
+ *
3089
+ * As of 2026-08-24 that is the route's behaviour for every caller, flagged
3090
+ * or not; `?atomic=1` is kept only so an older published server keeps
3091
+ * working, and is accepted-and-ignored server-side. **Remove when
3092
+ * `@withpica/mcp-server` 2.96.0 ships (the alias-removal release)**, together
3093
+ * with the route's param handling — the two must go in the same release.
2960
3094
  */
2961
3095
  async atomicRemove(recordingId, creditId) {
2962
3096
  return this.request("DELETE", `/admin/recordings/${recordingId}/credits/${creditId}?atomic=1`);
@@ -3485,7 +3619,9 @@ class ShareLinksResource extends BaseResource {
3485
3619
  */
3486
3620
  class ConsentResource extends BaseResource {
3487
3621
  async readiness(params) {
3488
- const qs = params?.limit ? `?limit=${encodeURIComponent(String(params.limit))}` : "";
3622
+ const qs = params?.limit
3623
+ ? `?limit=${encodeURIComponent(String(params.limit))}`
3624
+ : "";
3489
3625
  return this.request("GET", `/admin/consent/readiness${qs}`);
3490
3626
  }
3491
3627
  }
@@ -3712,6 +3848,8 @@ export class PicaClient {
3712
3848
  licensing;
3713
3849
  // ADR-289 Wave C1 — internal-team booking enquiries.
3714
3850
  bookings;
3851
+ // ADR-313 — live shows and tour credits.
3852
+ shows;
3715
3853
  credits;
3716
3854
  creditsBalance;
3717
3855
  picaScore;
@@ -3826,6 +3964,7 @@ export class PicaClient {
3826
3964
  this.recordings = new RecordingsResource(baseUrl, config.apiKey, debug);
3827
3965
  this.licensing = new LicensingResource(baseUrl, config.apiKey, debug);
3828
3966
  this.bookings = new BookingsResource(baseUrl, config.apiKey, debug);
3967
+ this.shows = new ShowsResource(baseUrl, config.apiKey, debug);
3829
3968
  this.credits = new CreditsResource(baseUrl, config.apiKey, debug);
3830
3969
  this.creditsBalance = new CreditsBalanceResource(baseUrl, config.apiKey, debug);
3831
3970
  this.picaScore = new PicaScoreResource(baseUrl, config.apiKey, debug);