@withpica/mcp-server
Version:
MCP Server for withPICA — enables AI assistants to interact with your withPICA music catalog
164 lines • 9.43 kB
JavaScript
// Copyright (c) 2025-2026 Withpica Ltd. All rights reserved.
import { formatSuccess } from "@withpica/mcp-utils";
export class RecordingCustodyTools {
pica;
constructor(pica) {
this.pica = pica;
}
getTools() {
return [
{
definition: {
name: "pica_recording_custody_assign",
scope: "admin",
audiences: ["stdio", "http", "public"],
tier: "write",
description: "Transfer custody of a recording to another party — e.g. when a demo is " +
"delivered to a label, a recording is licensed, or master ownership is assigned. " +
"Control types (delivery, license, admin_grant) leave ownership " +
"unchanged. Ownership types: " +
"'assignment' (title transfers), 'full_transfer' (ownership AND control) — these " +
"also move the master ownership splits append-only (the transferor's active era " +
"closes, the transferee's opens; partial transfers are refused if ambiguous or " +
"exceeding the transferor's share). Credits never move. " +
"To RECORD who owns a master (e.g. the artist owns 100%): full_transfer, percentage 100, " +
"their new_custodian_global_creator_id — if they already hold the master split, the split " +
"history is left untouched and only the custody leg is written; when that global creator " +
"is exactly one person in your catalogue, the new split row carries that person. " +
"Supply exactly one custodian target. reason is required. " +
"Admin/owner access required; you must own the recording. " +
"Use pica_recording_provenance first to read the current chain; " +
"this one writes a new leg.",
workflows: "infrastructure",
vernacular_kind: "specialist",
vernacular_reason: "Specialist context; not yet covered by the Creator Question Atlas — pending telemetry-driven addition per ADR-226 Phase 4 substrate writes.",
inputSchema: {
type: "object",
properties: {
recording_id: {
type: "string",
description: "UUID of the recording whose custody to transfer.",
},
transfer_type: {
type: "string",
enum: [
"delivery",
"license",
"admin_grant",
"assignment",
"full_transfer",
],
description: "'delivery' = handed over; 'license' = rights to use; 'admin_grant' = administration; " +
"'assignment' = ownership (title) transfers; 'full_transfer' = ownership AND control. " +
"Ownership types also move the master ownership splits append-only.",
},
percentage: {
type: "number",
description: "Share being transferred, > 0 and <= 100. For ownership types this is the " +
"share of master ownership that moves from the transferor to the transferee.",
},
territory: {
type: "string",
description: "Territory code the transfer applies to — 'WW' for worldwide (the convention the work-level custody chain reads).",
},
reason: {
type: "string",
description: "Required freetext explaining the handoff.",
},
new_custodian_org_id: {
type: "string",
description: "UUID of the receiving org. Supply exactly one custodian target.",
},
new_custodian_global_publisher_id: {
type: "string",
description: "Global publisher identity of the receiver. Supply exactly one custodian target.",
},
new_custodian_global_creator_id: {
type: "string",
description: "Global creator identity of the receiver. Supply exactly one custodian target.",
},
evidence: {
type: "string",
description: "Optional reference/URL to the agreement or document backing this transfer.",
},
},
required: [
"recording_id",
"transfer_type",
"percentage",
"territory",
"reason",
],
},
annotations: {
title: "assign recording custody",
destructiveHint: false,
idempotentHint: false,
},
},
executor: this.assign.bind(this),
},
{
definition: {
name: "pica_recording_provenance",
scope: "read:catalog",
audiences: ["stdio", "http", "public"],
tier: "read",
description: "Use when the user asks: 'who controls this recording?', 'show the recording's " +
"chain of custody', 'where did this master come from?'. Returns the ordered custody " +
"legs (each transfer: custodian, type, territory, percentage, effective dates, reason) " +
"plus the immutable origin credits (who made it). Available to any authenticated org member. " +
"To record a new transfer rather than read the chain, use " +
"pica_recording_custody_assign.",
workflows: "infrastructure",
vernacular_kind: "creator-entry",
inputSchema: {
type: "object",
properties: {
recording_id: {
type: "string",
description: "UUID of the recording whose provenance trail to fetch.",
},
},
required: ["recording_id"],
},
annotations: {
title: "recording provenance trail",
readOnlyHint: true,
idempotentHint: true,
},
},
executor: this.provenance.bind(this),
},
];
}
async assign(args) {
const data = await this.pica.recordingCustody.assign({
recording_id: args.recording_id,
transfer_type: args.transfer_type,
percentage: args.percentage,
territory: args.territory,
reason: args.reason,
new_custodian_org_id: args.new_custodian_org_id,
new_custodian_global_publisher_id: args.new_custodian_global_publisher_id,
new_custodian_global_creator_id: args.new_custodian_global_creator_id,
evidence: args.evidence,
});
const isOwnership = args.transfer_type === "assignment" ||
args.transfer_type === "full_transfer";
return formatSuccess(isOwnership
? `Custody recorded (${args.transfer_type}). A new custody leg was written. Master ownership splits moved append-only (transferor era closed, transferee era opened) — unless the transferee already held that share, in which case the split history is unchanged. Read pica_recording_splits_list to confirm.`
: `Custody transferred (${args.transfer_type}). A new custody leg was recorded on the recording's control chain.`, data);
}
async provenance(args) {
const data = await this.pica.recordingCustody.trail({
recording_id: args.recording_id,
});
const legs = data?.legs ?? [];
const originCredits = data?.originCredits ?? [];
return formatSuccess(legs.length > 0 || originCredits.length > 0
? `Provenance trail: ${legs.length} custody leg(s) + ${originCredits.length} origin credit(s).`
: "No custody legs or origin credits recorded for this recording yet.", data);
}
}
//# sourceMappingURL=recording-custody.js.map