@withpica/mcp-sdk 1.47.0 → 1.48.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,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [1.48.0] - 2026-06-25
15
+
16
+ ### Added
17
+
18
+ - **`resolveRelease(id, body)`** → `POST /admin/releases/:id/resolve`, plus the
19
+ `ResolveReleaseResult` type. Backs `pica_resolve_release` (release-grain
20
+ Spotify gap-fill enrichment through the authority gate).
21
+ - **`CatalogHealthResource`** — `catalogHealth()` (`GET /admin/catalog-health`,
22
+ whole-catalog completeness + cleanliness verdict), `catalogHealthPlan(body)`
23
+ (derives an actionable fix-plan + `planToken`), and `catalogHealthFix(body)`
24
+ (applies accepted `actionIds` / `all_safe_auto`, returning honest
25
+ `applied` / `skipped`). Plus the `CatalogHealth*` result types. Back
26
+ `pica_catalog_health` / `_plan` / `_fix` (ADR-272 / ADR-273).
27
+ - **`DocumentsResource`** — `listCatalog(params)`, `read(id, params)` (bounded
28
+ content read), and `link(id, entity_type, entity_id)` (provenance link to a
29
+ work / person / recording). Backs the ADR-274 document bridge
30
+ (`pica_documents_list` / `_read` / `_link`).
31
+
14
32
  ## [1.47.0] - 2026-06-22
15
33
 
16
34
  ### Added
package/dist/index.d.ts CHANGED
@@ -92,6 +92,42 @@ export interface ResolveRecordingResult {
92
92
  skipped_lower_authority: SkippedAuthorityReceipt[];
93
93
  recovery_hints: string[];
94
94
  }
95
+ /**
96
+ * Release resolver result. Mirrors the server-side `ResolveReleaseResult`
97
+ * in the resolver service. Duplicated here — no type-sharing mechanism with
98
+ * the PICA monorepo; drift is caught by the holdout suite.
99
+ */
100
+ export interface ResolveReleaseResult {
101
+ entity_type: "release";
102
+ entity_id: string;
103
+ /** v1 is Spotify-only; field narrowed to reflect the single eligible source. */
104
+ sources_run: Array<"spotify">;
105
+ applied: Array<{
106
+ source: "spotify";
107
+ rule_id: string;
108
+ fields: string[];
109
+ target_entity_type: "release";
110
+ target_entity_id: string;
111
+ }>;
112
+ proposals: Array<{
113
+ proposal_id: string;
114
+ source: "spotify";
115
+ rule_id: string;
116
+ confidence: number | null;
117
+ field_count: number;
118
+ signals: Record<string, unknown> | null;
119
+ }>;
120
+ errors: Array<{
121
+ source: "spotify";
122
+ rule_id?: string;
123
+ error_code: string;
124
+ retry_after_ms?: number;
125
+ message?: string;
126
+ }>;
127
+ overwrote: OverwriteReceipt[];
128
+ skipped_lower_authority: SkippedAuthorityReceipt[];
129
+ recovery_hints: string[];
130
+ }
95
131
  /**
96
132
  * ADR-179 Phase 2 person resolver result. Mirrors the server-side
97
133
  * `ResolvePersonResult` in `lib/services/enrichment-cascade/resolver.ts`.
@@ -278,6 +314,7 @@ interface Recording {
278
314
  isrc?: string;
279
315
  duration_seconds?: number;
280
316
  work_id?: string;
317
+ notes?: string | null;
281
318
  created_at: string;
282
319
  updated_at: string;
283
320
  }
@@ -1009,10 +1046,7 @@ declare class MultimediaResource extends BaseResource {
1009
1046
  person_id?: string;
1010
1047
  limit?: number;
1011
1048
  offset?: number;
1012
- }): Promise<{
1013
- data: MultimediaItem[];
1014
- count: number;
1015
- }>;
1049
+ }): Promise<PaginatedResult<MultimediaItem>>;
1016
1050
  create(data: Partial<MultimediaItem>): Promise<MultimediaItem>;
1017
1051
  importFromUrl(params: {
1018
1052
  url: string;
@@ -1305,6 +1339,22 @@ declare class EnrichmentResource extends BaseResource {
1305
1339
  */
1306
1340
  force?: boolean;
1307
1341
  }): Promise<ResolveRecordingResult>;
1342
+ /**
1343
+ * Resolve a release against every eligible enrichment source.
1344
+ * v1 is Spotify-only — a release resolve always re-checks Spotify and
1345
+ * gap-fills empty fields via the authority gate (no idempotence stamps
1346
+ * exist for releases). `force` is accepted for API parity but has no
1347
+ * distinct effect here.
1348
+ *
1349
+ * @param releaseId UUID of the release to resolve.
1350
+ * @param options
1351
+ * sources: optional whitelist. v1 supports `spotify` only.
1352
+ * force: accepted for parity; no distinct effect for releases.
1353
+ */
1354
+ resolveRelease(releaseId: string, options?: {
1355
+ sources?: Array<"spotify">;
1356
+ force?: boolean;
1357
+ }): Promise<ResolveReleaseResult>;
1308
1358
  /**
1309
1359
  * ADR-164: manually re-evaluate a work against every cascade rule.
1310
1360
  * Idempotent — rules whose preconditions are already satisfied skip.
@@ -1443,10 +1493,107 @@ declare class RegistrationResource extends BaseResource {
1443
1493
  getCoverage(): Promise<any>;
1444
1494
  getWorkCascadeStatus(workId: string): Promise<any>;
1445
1495
  }
1496
+ export interface CatalogHealthItem {
1497
+ grain: "work" | "recording" | "release" | "person";
1498
+ issue: string;
1499
+ dimension: "completeness" | "cleanliness";
1500
+ severity: "high" | "medium" | "low";
1501
+ count: number;
1502
+ sampleIds: string[];
1503
+ truncated: boolean;
1504
+ needsScope: string | null;
1505
+ actionableByCaller: boolean;
1506
+ }
1507
+ export interface CatalogHealthVerdict {
1508
+ score: number | null;
1509
+ dimensionScores: {
1510
+ completeness: number | null;
1511
+ cleanliness: number | null;
1512
+ };
1513
+ assessed: string[];
1514
+ notAssessed: string[];
1515
+ items: CatalogHealthItem[];
1516
+ generatedAt: string;
1517
+ }
1518
+ export interface CatalogHealthPlanAction {
1519
+ actionId: string;
1520
+ issue: string;
1521
+ actionKind: string;
1522
+ disposition: "auto" | "propose";
1523
+ destructive: boolean;
1524
+ needsScope: string;
1525
+ actionableByCaller: boolean;
1526
+ entityRefs: {
1527
+ type: string;
1528
+ id: string;
1529
+ }[];
1530
+ preview: Record<string, unknown>;
1531
+ }
1532
+ export interface CatalogHealthResidualItem {
1533
+ issue: string;
1534
+ count: number;
1535
+ reason: string;
1536
+ next_tool?: string;
1537
+ }
1538
+ export interface CatalogHealthPlan {
1539
+ score: number | null;
1540
+ dimensionScores: {
1541
+ completeness: number | null;
1542
+ cleanliness: number | null;
1543
+ };
1544
+ targetScore: number;
1545
+ actions: CatalogHealthPlanAction[];
1546
+ residual: CatalogHealthResidualItem[];
1547
+ planToken: string;
1548
+ generatedAt: string;
1549
+ }
1550
+ export interface CatalogHealthAppliedResult {
1551
+ actionId: string;
1552
+ met: true;
1553
+ summary: string;
1554
+ }
1555
+ export interface CatalogHealthSkippedResult {
1556
+ actionId: string;
1557
+ met: false;
1558
+ reason: "scope_denied" | "guard_blocked" | "stale" | "not_accepted";
1559
+ }
1560
+ export interface CatalogHealthFixResult {
1561
+ applied: CatalogHealthAppliedResult[];
1562
+ skipped: CatalogHealthSkippedResult[];
1563
+ verdict: unknown;
1564
+ outcomesRecorded: number;
1565
+ }
1446
1566
  declare class HealthResource extends BaseResource {
1447
1567
  getWorksHealth(): Promise<any>;
1448
1568
  getLowScoreWorks(): Promise<any>;
1449
1569
  getWorkCompleteness(workId: string): Promise<any>;
1570
+ /**
1571
+ * ADR-272 — org-scoped catalog health verdict (completeness + cleanliness
1572
+ * with a ranked punch-list). The route returns `{ success, data: verdict }`;
1573
+ * BaseResource.request unwraps the `{ success, data }` envelope via
1574
+ * `data.data || data`, so this resolves to the verdict object directly
1575
+ * (NOT a second `.data` — the recurring double-unwrap trap). Typed against
1576
+ * the UNWRAPPED shape.
1577
+ */
1578
+ catalogHealth(): Promise<CatalogHealthVerdict>;
1579
+ /**
1580
+ * ADR-273 — scope-gated fix plan. POSTs to /admin/catalog-health/plan,
1581
+ * returns a CatalogHealthPlan with actionable fix-actions + planToken.
1582
+ * Mutates nothing.
1583
+ */
1584
+ catalogHealthPlan(body: {
1585
+ targetScore?: number;
1586
+ only?: string[];
1587
+ }): Promise<CatalogHealthPlan>;
1588
+ /**
1589
+ * ADR-273 — apply accepted fix actions from a prior plan. Requires planToken
1590
+ * from catalogHealthPlan; accept is a list of actionIds (or "all_safe_auto").
1591
+ * Returns honest per-action met/unmet plus a fresh verdict.
1592
+ */
1593
+ catalogHealthFix(body: {
1594
+ planToken: string;
1595
+ accept: string[];
1596
+ }): Promise<CatalogHealthFixResult>;
1450
1597
  }
1451
1598
  declare class DashboardResource extends BaseResource {
1452
1599
  discoveries(params?: {
@@ -2148,6 +2295,13 @@ declare class ExportResource extends BaseResource {
2148
2295
  }): Promise<any>;
2149
2296
  industryReady(params?: {
2150
2297
  work_ids?: string[];
2298
+ /**
2299
+ * "zip" (default) returns a signed-URL JSON envelope to the generated ZIP
2300
+ * on S3. "json" returns the structured export data inline — reachable by
2301
+ * sandboxed agents whose allowlist excludes the S3 host (ops_issue
2302
+ * 8662c489).
2303
+ */
2304
+ format?: "zip" | "json";
2151
2305
  }): Promise<any>;
2152
2306
  catalogAssetReport(params: {
2153
2307
  sections: {
@@ -2503,6 +2657,20 @@ declare class ImportResource extends BaseResource {
2503
2657
  }
2504
2658
  declare class DocumentsResource extends BaseResource {
2505
2659
  analyse(id: string): Promise<Record<string, unknown>>;
2660
+ listCatalog(params?: {
2661
+ parsed_status?: string;
2662
+ limit?: number;
2663
+ offset?: number;
2664
+ }): Promise<{
2665
+ documents: unknown[];
2666
+ total: number;
2667
+ has_more: boolean;
2668
+ }>;
2669
+ read(id: string, params?: {
2670
+ offset?: number;
2671
+ max_chars?: number;
2672
+ }): Promise<Record<string, unknown>>;
2673
+ link(id: string, entity_type: string, entity_id: string): Promise<unknown>;
2506
2674
  }
2507
2675
  interface CollaboratorInvite {
2508
2676
  id: string;