@withpica/mcp-sdk 1.39.1 → 1.41.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,8 +11,67 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [1.41.0] - 2026-06-14
15
+
14
16
  ### Added
15
17
 
18
+ - **`bulk.reassignRecordingArtist({ recordingIds? | fromPersonId, toPersonId, dryRun? })`** — bulk-repoint recordings' `primary_artist_id` via `POST /admin/recordings/bulk-reassign-artist`. Backs the new `pica_recordings_bulk_reassign_artist` tool.
19
+
20
+ ## [1.40.0] - 2026-06-12
21
+
22
+ ADR-264 WS2 verify-before-assert + WS4 bulk recording credits + ADR-268 WS1
23
+ party claims / WS2 label identifiers / WS5 ownership transfer types. Removes
24
+ the never-functional `TeamResource`.
25
+
26
+ ### Changed
27
+
28
+ - **`RecordingCustodyResource.assign`** now accepts the ownership transfer
29
+ types `assignment` and `full_transfer` (ADR-268 WS5, the ADR-262
30
+ fast-follow): the `transfer_type` union widens from
31
+ `delivery|license|admin_grant` to all five types. Ownership legs also move
32
+ the recording's master ownership splits append-only inside the same
33
+ transaction (the transferor's active era closes, the transferee's opens;
34
+ the credit layer never moves). Ambiguous or over-share partial transfers
35
+ are refused as client-recoverable 400s
36
+ (`PARTIAL_TRANSFER_AMBIGUOUS` / `INSUFFICIENT_TRANSFEROR_SHARE` /
37
+ `INVALID_PERCENTAGE`).
38
+ - **`LabelsResource.create`** accepts an optional `identifiers` object
39
+ (`musicbrainz_label_id` / `isni` / `label_code` / `discogs_label_id` /
40
+ `wikidata_id` / `deezer_label_id`) — ADR-268 WS2 identifier-first dedup;
41
+ `LabelOrganisation` gains `global_label_id` (the bridge to the resolved
42
+ global label identity).
43
+ - **`RecordingCredit` gains `instrument: string | null`** and
44
+ **`RecordingCreditCreateInput` gains `instrument?: string | null`**
45
+ (ADR-259 Stage 2) — the played instrument(s) for a credit, e.g. `"drums"`
46
+ or `"drums, bass"` (one credit per person; multiple instruments list on
47
+ the same row). Passed through on `recordingCredits.create()`.
48
+
49
+ ### Removed
50
+
51
+ - **`TeamResource` (`client.team.*` — list/get/invite/update/remove)** —
52
+ existed solely to back the `pica_team_*` MCP tools, which were removed
53
+ 2026-06-11 (founder decision). `/api/admin/team/*` is session-only by
54
+ design (ADR-248: team membership is human-only), so every bearer SDK call
55
+ through this resource always received a hard 401; removal is honesty, not
56
+ a regression. Team membership is managed by humans in `/settings`.
57
+
58
+ ### Added
59
+
60
+ - **`PartyClaimsResource` (`client.partyClaims.*`)** — ADR-268 WS1.
61
+ `invite({target_organisation_id, invited_email, release_id?, recording_id?})`
62
+ POSTs `/admin/party-claims` (send a claim invite for an unclaimed party
63
+ org; resolves the unwrapped `{invite, disputed, claim_url}` object) and
64
+ `list({target_organisation_id?, status?, limit?})` GETs the calling org's
65
+ sent claims. Backs the new `pica_party_claim_invite` /
66
+ `pica_party_claim_status` tools.
67
+
68
+ - **`RecordingCreditsResource.bulkUpdate(input)`** — ADR-264 WS4 prerequisite.
69
+ POST `/admin/recording-credits/bulk` with exactly one of `release_id`
70
+ (targets every recording on the release's tracklist) / `recording_ids`,
71
+ plus the `credits[]` set applied to every target recording and optional
72
+ `dry_run`. Returns per-row `created` / `skipped_existing` (or
73
+ `would_create` / `would_skip_existing` on dry-run) results plus summary
74
+ counts. Typed against the unwrapped route payload.
16
75
  - **`WorksResource.verifyRegistrations(input)`** — ADR-264 WS2 verify-before-assert.
17
76
  POST `/admin/works/verify-registrations` with `work_ids` (1-25), `mode`
18
77
  (`"check"` runs an MLC lookup per work; `"confirm_unregistered"` records the
package/dist/index.d.ts CHANGED
@@ -1124,13 +1124,6 @@ declare class NotesResource extends BaseResource {
1124
1124
  }): Promise<any>;
1125
1125
  delete(id: string): Promise<void>;
1126
1126
  }
1127
- declare class TeamResource extends BaseResource {
1128
- list(): Promise<any>;
1129
- get(id: string): Promise<any>;
1130
- invite(data: Record<string, any>): Promise<any>;
1131
- update(id: string, data: Record<string, any>): Promise<any>;
1132
- remove(id: string): Promise<any>;
1133
- }
1134
1127
  declare class RecordingsResource extends BaseResource {
1135
1128
  list(params?: {
1136
1129
  limit?: number;
@@ -1405,8 +1398,8 @@ declare class DashboardResource extends BaseResource {
1405
1398
  /**
1406
1399
  * Actionable items projection — `{class, entity_id, entity_type,
1407
1400
  * entity_label, failure_mode, urgency: {score, components,
1408
- * model_version}, drill_down_skill, suggested_skill (alias, slated
1409
- * for removal)}` per row, sorted by `urgency.score` desc, capped at
1401
+ * model_version}, drill_down_skill}` per row (the suggested_skill
1402
+ * alias was removed 2026-06-11), sorted by `urgency.score` desc, capped at
1410
1403
  * `limit`. Backed by the shared actionable-items source so counts
1411
1404
  * agree with `pica_dashboard_briefing.critical_issues_total` and
1412
1405
  * `pica_count_explain.sources[].count` for the same org/moment.
@@ -2067,6 +2060,18 @@ declare class BulkResource extends BaseResource {
2067
2060
  updatePeopleRoles(personIds: string[], roles: string[], action?: string): Promise<any>;
2068
2061
  addPeopleTags(personIds: string[], tags: string[]): Promise<unknown>;
2069
2062
  linkArtist(workIds: string[], personId: string, artistName: string): Promise<unknown>;
2063
+ /**
2064
+ * Bulk-repoint recordings' primary_artist_id. Pass exactly one selector:
2065
+ * `recordingIds` (explicit set) or `fromPersonId` (every recording on that
2066
+ * person). `toPersonId` null clears the link. write:catalog; no destructive
2067
+ * scope needed — only the structured link changes.
2068
+ */
2069
+ reassignRecordingArtist(input: {
2070
+ recordingIds?: string[];
2071
+ fromPersonId?: string;
2072
+ toPersonId: string | null;
2073
+ dryRun?: boolean;
2074
+ }): Promise<unknown>;
2070
2075
  addCollaborator(workIds: string[], collaborator: {
2071
2076
  person_id: string;
2072
2077
  role: string;
@@ -2767,6 +2772,8 @@ export interface RecordingCredit {
2767
2772
  person_id: string | null;
2768
2773
  credited_name: string;
2769
2774
  role: string;
2775
+ /** Instrument(s) performed, e.g. "drums" or "drums, bass" (ADR-259 Stage 2). */
2776
+ instrument: string | null;
2770
2777
  split_percentage: number | null;
2771
2778
  split_type: string | null;
2772
2779
  display_order: number;
@@ -2779,11 +2786,49 @@ export interface RecordingCreditCreateInput {
2779
2786
  person_id?: string | null;
2780
2787
  credited_name: string;
2781
2788
  role: string;
2789
+ /** Instrument(s) performed, e.g. "drums" or "drums, bass" (ADR-259 Stage 2). */
2790
+ instrument?: string | null;
2782
2791
  split_percentage?: number | null;
2783
2792
  split_type?: string | null;
2784
2793
  display_order?: number;
2785
2794
  notes?: string | null;
2786
2795
  }
2796
+ export interface RecordingCreditsBulkCreditInput {
2797
+ credited_name: string;
2798
+ role: string;
2799
+ person_id?: string | null;
2800
+ split_percentage?: number | null;
2801
+ split_type?: string | null;
2802
+ display_order?: number;
2803
+ notes?: string | null;
2804
+ }
2805
+ export interface RecordingCreditsBulkUpdateInput {
2806
+ /** Target every recording on this release. Exactly one of release_id / recording_ids. */
2807
+ release_id?: string;
2808
+ recording_ids?: string[];
2809
+ /** The credit set applied to EVERY target recording. */
2810
+ credits: RecordingCreditsBulkCreditInput[];
2811
+ /** Preview the create/skip decision set without writing. */
2812
+ dry_run?: boolean;
2813
+ }
2814
+ export type RecordingCreditsBulkRowStatus = "created" | "skipped_existing" | "would_create" | "would_skip_existing";
2815
+ export interface RecordingCreditsBulkRowResult {
2816
+ recording_id: string;
2817
+ credited_name: string;
2818
+ role: string;
2819
+ status: RecordingCreditsBulkRowStatus;
2820
+ credit_id?: string;
2821
+ }
2822
+ export interface RecordingCreditsBulkUpdateResult {
2823
+ dry_run: boolean;
2824
+ target_recording_count: number;
2825
+ total_rows: number;
2826
+ created: number;
2827
+ skipped_existing: number;
2828
+ would_create: number;
2829
+ would_skip_existing: number;
2830
+ results: RecordingCreditsBulkRowResult[];
2831
+ }
2787
2832
  declare class RecordingCreditsResource extends BaseResource {
2788
2833
  list(recordingId: string): Promise<RecordingCredit[]>;
2789
2834
  create(recordingId: string, input: RecordingCreditCreateInput): Promise<RecordingCredit>;
@@ -2799,6 +2844,13 @@ declare class RecordingCreditsResource extends BaseResource {
2799
2844
  * success. AC-2 strict semantics for pica_credit_remove.
2800
2845
  */
2801
2846
  atomicRemove(recordingId: string, creditId: string): Promise<AtomicCreditResult>;
2847
+ /**
2848
+ * ADR-264 WS4 prerequisite — apply one credit set across many recordings
2849
+ * (a release's tracklist via release_id, or an explicit recording_ids
2850
+ * list) in a single call. Existing (recording, credited_name, role) rows
2851
+ * are skipped, never overwritten; dry_run previews the same decision set.
2852
+ */
2853
+ bulkUpdate(input: RecordingCreditsBulkUpdateInput): Promise<RecordingCreditsBulkUpdateResult>;
2802
2854
  }
2803
2855
  export type ShareTraceEntityType = "work" | "recording" | "person";
2804
2856
  export interface ShareTraceQuery {
@@ -2955,6 +3007,17 @@ export interface LabelOrganisation {
2955
3007
  verification_status: string | null;
2956
3008
  org_type: string;
2957
3009
  contact_email?: string | null;
3010
+ /** ADR-268 WS2 bridge to the enrichment-side global label identity. */
3011
+ global_label_id?: string | null;
3012
+ }
3013
+ /** External label identifiers accepted by labels.create (ADR-268 WS2). */
3014
+ export interface LabelIdentifiers {
3015
+ musicbrainz_label_id?: string;
3016
+ isni?: string;
3017
+ label_code?: string;
3018
+ discogs_label_id?: string;
3019
+ wikidata_id?: string;
3020
+ deezer_label_id?: string;
2958
3021
  }
2959
3022
  declare class LabelsResource extends BaseResource {
2960
3023
  list(params?: {
@@ -2968,11 +3031,63 @@ declare class LabelsResource extends BaseResource {
2968
3031
  country?: string;
2969
3032
  website?: string;
2970
3033
  contact_email?: string;
3034
+ /**
3035
+ * ADR-268 WS2: when supplied, server-side dedup is identifier-based —
3036
+ * an org already bridged to the resolved global label identity is
3037
+ * returned (already_existed) even if the name differs.
3038
+ */
3039
+ identifiers?: LabelIdentifiers;
2971
3040
  }): Promise<(LabelOrganisation & {
2972
3041
  org_type: string;
2973
3042
  already_existed?: boolean;
2974
3043
  }) | null>;
2975
3044
  }
3045
+ export interface PartyClaimInviteSummary {
3046
+ id: string;
3047
+ organisation_id: string;
3048
+ source: "invite" | "unsolicited";
3049
+ invited_by_organisation_id: string | null;
3050
+ invited_email: string;
3051
+ status: string;
3052
+ expires_at: string | null;
3053
+ claimed_at: string | null;
3054
+ claim_code: string | null;
3055
+ release_id: string | null;
3056
+ recording_id: string | null;
3057
+ created_at: string;
3058
+ organisation?: {
3059
+ id: string;
3060
+ name: string;
3061
+ org_type: string;
3062
+ verification_status: string | null;
3063
+ };
3064
+ }
3065
+ export interface PartyClaimInviteResult {
3066
+ invite: PartyClaimInviteSummary;
3067
+ disputed: boolean;
3068
+ claim_url: string | null;
3069
+ }
3070
+ /**
3071
+ * ADR-268 WS1 — party org claim flow. `invite()` sends an artist-anchored
3072
+ * claim invite for an unclaimed label/distributor/publisher org;
3073
+ * `list()` reads the claims the calling org has sent.
3074
+ *
3075
+ * Typed against the UNWRAPPED reality (ADR-265 lesson): BaseResource.request
3076
+ * auto-unwraps the `{success,data}` envelope, so methods see `data` itself.
3077
+ */
3078
+ declare class PartyClaimsResource extends BaseResource {
3079
+ invite(params: {
3080
+ target_organisation_id: string;
3081
+ invited_email: string;
3082
+ release_id?: string;
3083
+ recording_id?: string;
3084
+ }): Promise<PartyClaimInviteResult | null>;
3085
+ list(params?: {
3086
+ target_organisation_id?: string;
3087
+ status?: string;
3088
+ limit?: number;
3089
+ }): Promise<PartyClaimInviteSummary[]>;
3090
+ }
2976
3091
  declare class ReleasesResource extends BaseResource {
2977
3092
  list(params?: {
2978
3093
  limit?: number;
@@ -3234,17 +3349,19 @@ declare class CustodyResource extends BaseResource {
3234
3349
  }
3235
3350
  declare class RecordingCustodyResource extends BaseResource {
3236
3351
  /**
3237
- * Assign (transfer) custody of a recording. Admin/owner only. v1 supports
3238
- * control/possession transfer types only (delivery|license|admin_grant);
3239
- * ownership transfer (assignment|full_transfer) is a fast-follow and the
3240
- * route/service reject it. At least one custodian target must be supplied
3241
- * (org, global publisher, or global creator).
3352
+ * Assign (transfer) custody of a recording. Admin/owner only.
3353
+ * Control/possession types (delivery|license|admin_grant) leave ownership
3354
+ * unchanged. Ownership types (assignment|full_transfer ADR-268 WS5) also
3355
+ * move the master ownership splits append-only in the same transaction:
3356
+ * the transferor's active era closes, the transferee's opens; ambiguous or
3357
+ * over-share partial transfers are refused (400). At least one custodian
3358
+ * target must be supplied (org, global publisher, or global creator).
3242
3359
  */
3243
3360
  assign(body: {
3244
3361
  recording_id: string;
3245
3362
  percentage: number;
3246
3363
  territory: string;
3247
- transfer_type: "delivery" | "license" | "admin_grant";
3364
+ transfer_type: "delivery" | "license" | "admin_grant" | "assignment" | "full_transfer";
3248
3365
  reason: string;
3249
3366
  new_custodian_org_id?: string | null;
3250
3367
  new_custodian_global_publisher_id?: string | null;
@@ -3421,7 +3538,6 @@ export declare class PicaClient {
3421
3538
  sessions: SessionsResource;
3422
3539
  assets: AssetsResource;
3423
3540
  notes: NotesResource;
3424
- team: TeamResource;
3425
3541
  projects: ProjectsResource;
3426
3542
  releases: ReleasesResource;
3427
3543
  splitSheets: SplitSheetsResource;
@@ -3432,6 +3548,7 @@ export declare class PicaClient {
3432
3548
  audioPipelineStatus: AudioPipelineStatusResource;
3433
3549
  publishers: PublishersResource;
3434
3550
  labels: LabelsResource;
3551
+ partyClaims: PartyClaimsResource;
3435
3552
  agreementTemplates: AgreementTemplatesResource;
3436
3553
  producerAgreements: ProducerAgreementsResource;
3437
3554
  workForHire: WorkForHireResource;