@withpica/mcp-sdk 3.11.0 → 3.13.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
@@ -1941,6 +2023,28 @@ class FeedbackResource extends BaseResource {
1941
2023
  return this.request("POST", "/feedback", params);
1942
2024
  }
1943
2025
  }
2026
+ class BillingResource extends BaseResource {
2027
+ /**
2028
+ * Mint a pay link for one offer. Minting is not charging: the link is a
2029
+ * capability an agent POSTs with a Machine Payments credential, or a person
2030
+ * opens in a browser and pays by card.
2031
+ *
2032
+ * Refusals arrive as `ApiError` carrying the route's status with its JSON
2033
+ * body embedded in the message (the shape `duplicates.ts` and
2034
+ * `integrity.ts` already parse): 403 `billing not enabled`; 400
2035
+ * `nothing_held_for_entity` / `entity_id is required to unlock`; 409
2036
+ * `offer_no_longer_applies`, whose body lists the offers that DO apply.
2037
+ * A 403 can ALSO come from the auth wrapper in front of the route rather
2038
+ * than the route itself (`{ error: { code: "INSUFFICIENT_SCOPE", … } }`),
2039
+ * so status alone never identifies which refusal this is — read the body.
2040
+ * They are deliberately not caught here — the MCP tool turns each into a
2041
+ * structured refusal, and a resource that swallowed them would leave every
2042
+ * other caller unable to tell a refusal from an outage.
2043
+ */
2044
+ async mintPayLink(params) {
2045
+ return this.request("POST", "/admin/billing/pay-link", params);
2046
+ }
2047
+ }
1944
2048
  class SubscriptionResource extends BaseResource {
1945
2049
  /**
1946
2050
  * Read the org's billing posture. Wraps the same
@@ -2282,6 +2386,49 @@ class ExportResource extends BaseResource {
2282
2386
  const csv = await this.requestText("GET", path);
2283
2387
  return { format: params.format, csv };
2284
2388
  }
2389
+ /**
2390
+ * The three diligence documents that had no agent path at all until
2391
+ * 2026-07-30 (ADR-303). Each has had a working route and a fully-styled PDF
2392
+ * for months, reachable only by typing the URL, because the buttons that
2393
+ * opened them lived in the `/admin` page tree ADR-251 retired.
2394
+ *
2395
+ * `delivery=url` is the default here for the same reason PR 3 moved the other
2396
+ * exports onto it: `request()` calls `response.json()`, so an inline binary ZIP
2397
+ * cannot cross this transport. `inline` swaps to `format=json` for a sandboxed
2398
+ * agent that cannot fetch a signed S3 URL.
2399
+ */
2400
+ /**
2401
+ * The ADR-100 catalogue snapshot: score, financials, ownership coverage, gaps
2402
+ * with a suggested action for each, physical and production assets, and a
2403
+ * "what to do next" list.
2404
+ *
2405
+ * It had no agent path and no UI control — its buttons lived on the
2406
+ * `/admin/catalog` pages ADR-251 retired, which is why an 80%-implemented
2407
+ * "replace the nine fragments with one document" decision quietly stopped
2408
+ * being reachable at all. Restored 2026-07-30 rather than deleted: the
2409
+ * roadmap and the production-asset provenance exist nowhere else.
2410
+ */
2411
+ async picaSnapshot(params) {
2412
+ return this.request("POST", "/admin/exports/pica", {
2413
+ scope: params?.scope ?? "everything",
2414
+ ...(params?.work_ids?.length ? { workIds: params.work_ids } : {}),
2415
+ });
2416
+ }
2417
+ async ownershipRecord(params) {
2418
+ return this.request("GET", `/admin/exports/ownership-record?${params?.inline ? "format=json" : "delivery=url"}`);
2419
+ }
2420
+ async rightsProof(params) {
2421
+ return this.request("GET", `/admin/exports/rights-proof?${params?.inline ? "format=json" : "delivery=url"}`);
2422
+ }
2423
+ /**
2424
+ * The diligence PACK (the ZIP with its PDF). Distinct from
2425
+ * `analytics.catalogDiligence()`, which reads the same data as JSON and stays
2426
+ * the right tool for "am I ready to register?" — a question that wants an
2427
+ * answer, not a document.
2428
+ */
2429
+ async diligencePack(params) {
2430
+ return this.request("GET", `/admin/exports/catalog-diligence?${params?.inline ? "format=json" : "delivery=url"}`);
2431
+ }
2285
2432
  async songRegistration(params) {
2286
2433
  // Returns a signed-URL JSON envelope:
2287
2434
  // { success, data: { download_url, expires_at, file_size_bytes, s3_key, ... } }
@@ -2598,7 +2745,11 @@ class CollaboratorsResource extends BaseResource {
2598
2745
  }
2599
2746
  /**
2600
2747
  * ADR-157 warm path — accept an invite addressed to the authenticated
2601
- * user. Writes a real work_credits row and flips status to confirmed.
2748
+ * user, and flip its status to confirmed. The credit write is
2749
+ * grain-routed (ADR-265): a composition-grain invite writes
2750
+ * work_collaborators, a master/owner-grain invite attests the person's
2751
+ * pending recording_credits. ADR-252 WS-A dropped work_credits at
2752
+ * DB-M3, so no row is written there.
2602
2753
  */
2603
2754
  async accept(inviteId) {
2604
2755
  return this.request("POST", `/admin/collaborators/invites/${inviteId}/accept`);
@@ -2954,9 +3105,14 @@ class RecordingCreditsResource extends BaseResource {
2954
3105
  };
2955
3106
  }
2956
3107
  /**
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.
3108
+ * ADR-232 atomic remove — the route returns 403 INSUFFICIENT_SCOPE on a
3109
+ * 0-row delete. AC-2 strict semantics for pica_credit_remove.
3110
+ *
3111
+ * As of 2026-08-24 that is the route's behaviour for every caller, flagged
3112
+ * or not; `?atomic=1` is kept only so an older published server keeps
3113
+ * working, and is accepted-and-ignored server-side. **Remove when
3114
+ * `@withpica/mcp-server` 2.96.0 ships (the alias-removal release)**, together
3115
+ * with the route's param handling — the two must go in the same release.
2960
3116
  */
2961
3117
  async atomicRemove(recordingId, creditId) {
2962
3118
  return this.request("DELETE", `/admin/recordings/${recordingId}/credits/${creditId}?atomic=1`);
@@ -3485,7 +3641,9 @@ class ShareLinksResource extends BaseResource {
3485
3641
  */
3486
3642
  class ConsentResource extends BaseResource {
3487
3643
  async readiness(params) {
3488
- const qs = params?.limit ? `?limit=${encodeURIComponent(String(params.limit))}` : "";
3644
+ const qs = params?.limit
3645
+ ? `?limit=${encodeURIComponent(String(params.limit))}`
3646
+ : "";
3489
3647
  return this.request("GET", `/admin/consent/readiness${qs}`);
3490
3648
  }
3491
3649
  }
@@ -3712,6 +3870,8 @@ export class PicaClient {
3712
3870
  licensing;
3713
3871
  // ADR-289 Wave C1 — internal-team booking enquiries.
3714
3872
  bookings;
3873
+ // ADR-313 — live shows and tour credits.
3874
+ shows;
3715
3875
  credits;
3716
3876
  creditsBalance;
3717
3877
  picaScore;
@@ -3784,6 +3944,8 @@ export class PicaClient {
3784
3944
  workflowOutcomes;
3785
3945
  feedback;
3786
3946
  subscription;
3947
+ /** MPP pay rail (WS-B) — mints pay links; never charges. */
3948
+ billing;
3787
3949
  opsIssues;
3788
3950
  discoveries;
3789
3951
  agentIdentity;
@@ -3826,6 +3988,7 @@ export class PicaClient {
3826
3988
  this.recordings = new RecordingsResource(baseUrl, config.apiKey, debug);
3827
3989
  this.licensing = new LicensingResource(baseUrl, config.apiKey, debug);
3828
3990
  this.bookings = new BookingsResource(baseUrl, config.apiKey, debug);
3991
+ this.shows = new ShowsResource(baseUrl, config.apiKey, debug);
3829
3992
  this.credits = new CreditsResource(baseUrl, config.apiKey, debug);
3830
3993
  this.creditsBalance = new CreditsBalanceResource(baseUrl, config.apiKey, debug);
3831
3994
  this.picaScore = new PicaScoreResource(baseUrl, config.apiKey, debug);
@@ -3895,6 +4058,7 @@ export class PicaClient {
3895
4058
  this.workflowOutcomes = new WorkflowOutcomesResource(baseUrl, config.apiKey, debug);
3896
4059
  this.feedback = new FeedbackResource(baseUrl, config.apiKey, debug);
3897
4060
  this.subscription = new SubscriptionResource(baseUrl, config.apiKey, debug);
4061
+ this.billing = new BillingResource(baseUrl, config.apiKey, debug);
3898
4062
  this.opsIssues = new OpsIssuesResource(baseUrl, config.apiKey, debug);
3899
4063
  this.discoveries = new DiscoveriesResource(baseUrl, config.apiKey, debug);
3900
4064
  this.agentIdentity = new AgentIdentityResource(baseUrl, config.apiKey, debug);