@withpica/mcp-server
Version:
MCP Server for withPICA — enables AI assistants to interact with your withPICA music catalog
1,280 lines • 58 kB
JavaScript
// Copyright (c) 2025-2026 Withpica Ltd. All rights reserved.
//
// AUTO-GENERATED by mcp-server/scripts/build-required-schemas.ts.
// Do not edit by hand. Re-run via `cd mcp-server && npm run prebuild`.
// Source: required-schemas.source.ts + schema-mirror.json + ToolRegistry inputSchemas.
// ADR-214 — required-fields contracts per workflow.
export const REQUIRED_SCHEMAS = {
"agreement-required": {
"workflow": "agreement-required",
"summary": "Required fields to create an agreement, then attach works and (optionally) render from a template.",
"primary_tool": "pica_agreements_create",
"primary_required": [
"title",
"agreement_type",
"other_party_name"
],
"primary_recommended": [
"id",
"other_party_type",
"description",
"notes",
"tags",
"agreement_category",
"status",
"signing_date",
"start_date",
"end_date",
"expires_at",
"renewal_date",
"termination_date",
"counterparty_org_id",
"counterparty_email",
"advance_amount",
"advance_currency",
"is_recoupable",
"financial_terms",
"agreement_terms",
"termination_notice_period_days",
"include_future_works"
],
"enums": {
"agreement_type": [
"admin_only",
"artist_contract",
"co_publishing",
"distribution",
"library_music",
"master_recording",
"other",
"production",
"publishing_admin",
"report",
"sub_publishing",
"termination"
],
"other_party_type": [
"artist",
"individual",
"label",
"music_library",
"other",
"production_company",
"publisher"
],
"status": [
"active",
"cancelled",
"completed",
"draft",
"expired",
"fully_executed",
"partially_signed",
"pending_signature",
"terminated",
"unknown"
]
},
"companion_calls": [
{
"tool": "pica_agreements_update",
"when": "After creation — to amend any inline field. Status changes trigger notifications; counterparty_org_id changes require the linked-org check at the route layer.",
"required": [
"id"
]
},
{
"tool": "pica_agreements_link_work",
"when": "Attach a work to the agreement. Optionally set a royalty split percentage per work.",
"required": [
"agreement_id",
"work_id"
]
},
{
"tool": "pica_agreement_templates_render",
"when": "Template-driven flow — fill an agreement template with catalog data (work_id + people_ids) before creating the agreement row.",
"required": [
"id"
]
},
{
"tool": "pica_agreements_create_from_template",
"when": "Template-driven flow with signers in one call — render a template and create the resulting agreement in draft status with required_signers already set. The only creation path that can set required_signers; pica_agreements_create has no such field.",
"required": [
"template_id",
"title",
"agreement_type",
"required_signers",
"variables"
]
},
{
"tool": "pica_agreements_send_for_signature",
"when": "Send every required signer of a draft agreement a personal signing link by email.",
"required": [
"agreement_id"
]
}
],
"example": {
"title": "Songwriter Admin Deal — Midnight Rivers",
"agreement_type": "publishing_admin",
"other_party_name": "Indigo Music Publishing Ltd."
}
},
"audio-upload-required": {
"workflow": "audio-upload-required",
"summary": "Three-step chain to add an audio master / stem / version to the catalog: presign → PUT → finalize, then optional async analyze + poll.",
"primary_tool": "pica_audio_presigned_upload",
"primary_required": [
"filename",
"content_type",
"file_size"
],
"primary_recommended": [
"work_id",
"title",
"file_type"
],
"enums": {
"file_type": [
"demo",
"instrumental",
"master",
"stem",
"version"
],
"classification": [
"composition",
"demo",
"drum_pack",
"loop",
"other",
"released_song",
"sample",
"stem",
"unreleased_song"
]
},
"companion_calls": [
{
"tool": "pica_audio_complete_upload",
"when": "Step 2 — after the uploader PUTs the file to the signed URL returned by step 1. Finalizes the upload, writes the audio_files row, and (optionally) links or auto-creates a recording for master files.",
"required": [
"upload_id",
"key",
"bucket",
"filename",
"content_type",
"file_size"
]
},
{
"tool": "pica_audio_analyze",
"when": "Step 3 (optional, async). Triggers BPM / key / mood feature extraction (Librosa) and lyrics transcription (Whisper). Each side bills 1 credit. Does not auto-run on complete_upload — explicit call required.",
"required": [
"id"
]
},
{
"tool": "pica_audio_inspect",
"when": "Step 4 (poll). Call with sections: ['analysis', 'status'] until the analysis job reports complete. Lyrics transcripts land on the transcriptions row and auto-copy to works.lyrics only when it is empty — existing lyrics are never overwritten.",
"required": [
"id"
]
}
],
"example": {
"filename": "midnight-rivers-master.wav",
"content_type": "audio/wav",
"file_size": 48234567,
"work_id": "<optional uuid — auto-creates a recording for master files>"
}
},
"claim-required": {
"workflow": "claim-required",
"summary": "Resolve pending discoveries (credits, custody, artist links) into your catalog. Each discovery type has a typed claim verb; the generic discoveries_review surface accepts/rejects without specialised handling.",
"primary_tool": "pica_discoveries_query",
"primary_required": [],
"primary_recommended": [
"status",
"limit"
],
"enums": {
"status": [
"expired",
"pending",
"resolved",
"revoked"
],
"match_basis": [
"email",
"ipi",
"ipn",
"isni",
"musicbrainz"
],
"custody_type": [
"composition",
"master"
]
},
"companion_calls": [
{
"tool": "pica_discoveries_review",
"when": "Generic accept/reject for any discovery row — accepted discoveries update your catalog automatically. Use for non-credit / non-custody / non-artist discoveries, or when the typed claim tools refuse on rate-limit / state preconditions.",
"required": [
"discovery_id",
"status"
]
},
{
"tool": "pica_claim_credit",
"when": "Mark a discovered_credits row as claimed — a status transition that grants view access to the linked work (no credit row is written). Rate-limited to 20 claims/hour. Re-claiming an already-resolved row returns DISCOVERY_ALREADY_RESOLVED (409).",
"required": [
"id"
]
},
{
"tool": "pica_claim_custody",
"when": "Drain a discovered_custody row into a pending custody_claims row with +72h silent-consent auto-approve. The current custodian keeps the catalog row until the window elapses.",
"required": [
"id"
]
},
{
"tool": "pica_claim_artist",
"when": "Drain a discovered_artists row instantly (identity evidence already validated at discovery time). Requires your identity to already be linked via pica_update_my_identity. Refuses (409) when an open artist_claims review row exists.",
"required": [
"id"
]
}
],
"example": {
"status": "pending",
"limit": 50
}
},
"enrichment-resolve-required": {
"workflow": "enrichment-resolve-required",
"summary": "Fan out enrichment across every eligible source for an entity (work / recording / person), then review fuzzy Tier B matches in the proposals queue. Tier A identifier matches apply directly; Tier B fuzzy matches queue as proposals.",
"primary_tool": "pica_resolve_work",
"primary_required": [
"work_id"
],
"primary_recommended": [
"sources",
"include_fuzzy",
"force"
],
"enums": {
"status": [
"applied",
"expired",
"pending",
"rejected"
],
"entity_type": [
"audio_file",
"person",
"recording",
"work"
],
"proposal_action": [
"create",
"update"
],
"file_type": [
"demo",
"instrumental",
"master",
"stem",
"version"
]
},
"companion_calls": [
{
"tool": "pica_resolve_recording",
"when": "Recording-side variant. Fans out across Spotify, YouTube, MusicBrainz, Discogs. Triggered by the canonical spotify_track_id / youtube_video_id on the recording.",
"required": [
"recording_id"
]
},
{
"tool": "pica_resolve_release",
"when": "Release-side variant. Fans out across Spotify, MusicBrainz, Discogs. Triggered by trigger identifiers on the release (e.g. spotify_album_id, upc).",
"required": [
"release_id"
]
},
{
"tool": "pica_resolve_person",
"when": "Person-side variant. Fans out across ISNI and MusicBrainz (Wikidata downstream). Triggered by isni / musicbrainz_id on the person.",
"required": [
"person_id"
]
},
{
"tool": "pica_enrichment_proposals_list",
"when": "After resolve — list pending Tier B fuzzy matches awaiting review. Only pending status is returned.",
"required": []
},
{
"tool": "pica_enrichment_proposal_apply",
"when": "Commit a reviewed proposal. Drift detection runs first on update proposals — pass force=true only after the user has reviewed any conflicts from a prior drift_detected response. For a file-type question (entity_type audio_file) pass the user's chosen file_type (and, for a stem, an optional stem_label); ask them about each file, never pick for them.",
"required": [
"proposal_id"
],
"constraint": "file_type ∈ audio_files.file_type and only on entity_type audio_file; stem_label only with file_type stem, max 60 characters; a refused answer is INVALID_FILE_TYPE_ANSWER and writes nothing"
},
{
"tool": "pica_enrichment_proposal_reject",
"when": "Dismiss a proposal. Content-hash suppression permanently blocks re-proposal of the same exact content; cascade only re-proposes if the source data genuinely changes.",
"required": [
"proposal_id"
]
},
{
"tool": "pica_enrichment_proposals_bulk_reject",
"when": "Dismiss up to 100 pending proposals in one call — by explicit proposal_ids OR a filter (rule_id / source / max_confidence). Per-proposal effects identical to the single reject (permanent content-hash suppression). Pass dry_run=true first to preview the real affected set.",
"required": [],
"constraint": "exactly one of proposal_ids or filter must be supplied; dry_run previews without mutating"
},
{
"tool": "pica_enrichment_proposals_bulk_apply",
"when": "Accept a reviewed batch — up to 100 pending proposals in one call, by EXPLICIT ids only. There is deliberately no filter form: a mis-filtered bulk reject costs a re-proposal, a mis-filtered bulk apply writes to the catalogue. Pass dry_run=true first to see what would land.",
"required": [
"proposal_ids"
],
"constraint": "proposal_ids only, max 100; partial success is the NORMAL shape — a non-empty failed[] beside a non-zero applied is expected, never report a partial as a success; dry_run=true returns { would_affect, not_pending } and writes nothing, and would_affect is an upper bound because drift is only detected at write time"
}
],
"example": {
"work_id": "<uuid>",
"sources": [
"mlc",
"spotify"
],
"include_fuzzy": true
}
},
"export-required": {
"workflow": "export-required",
"summary": "Generate exports of works in formats matching the destination — pica_export_catalog_csv emits per-work or per-batch industry submission files (pro / distributor / nro / sync-pdf), pica_export_song_registration bundles CSV/JSON/PDF plus a CWR field-mapping guide for PRO registration (a mapping guide, NOT a CWR file — PICA has no CWR emitter), pica_export_industry_ready packages metadata for publishers/labels/sync, pica_export_catalog_asset_report (CAR) bundles diligence/finance evidence, pica_export_ai_consent emits per-work + per-contributor AI declaration matrices. Four diligence documents complete the set: pica_export_snapshot (owner-facing, what to fix next), pica_export_ownership_record (the register of who owns what), pica_export_rights_proof (the evidence behind that register), pica_export_diligence_pack (readiness for registration or sale). For everything PICA holds about specific songs — recordings, releases, credits, people — pica_export_song_dossiers bundles one dossier per work into a ZIP.",
"primary_tool": "pica_export_catalog_csv",
"primary_required": [
"format"
],
"primary_recommended": [
"work_id",
"work_ids"
],
"enums": {},
"companion_calls": [
{
"tool": "pica_export_song_registration",
"when": "Song-registration bundle for PRO/CMO submission — CSVs plus a CWR field-mapping guide, not a CWR file.",
"required": []
},
{
"tool": "pica_export_industry_ready",
"when": "Industry-ready metadata package — formatted for distribution to publishers, labels, and sync agents.",
"required": []
},
{
"tool": "pica_export_catalog_asset_report",
"when": "Catalog Asset Report (CAR) — unified ZIP bundle with cover PDF, evidence folders, integrity manifest. Property-lending framing for finance / insurance / diligence. Nested `sections` object accepts boolean flags: valuation, assets, agreements, intelligence. Ownership is always included. The report is unsigned: only someone signed in to PICA can attest it, from the export panel.",
"required": []
},
{
"tool": "pica_export_ai_consent",
"when": "AI-usage consent declaration matrix — per-work + per-contributor declarations of human-made / AI-assisted / AI-generated.",
"required": []
},
{
"tool": "pica_export_snapshot",
"when": "Catalogue snapshot for the OWNER deciding what to fix — PICA score per pillar, ownership coverage, gaps ranked by severity each with a suggested action, production-asset provenance, and a prioritised what-to-do-next list. Scope with scope='work'|'selected'|'everything'. For a lender/buyer-facing document use pica_export_catalog_asset_report instead.",
"required": []
},
{
"tool": "pica_export_song_dossiers",
"when": "Everything PICA holds about specific songs, as one ZIP: a song dossier (PDF + JSON) per work — the work, its recordings, the releases they appear on, people, provenance, consent. 1 to 60 work_ids; more is refused, not truncated. A file for the catalogue owner; it sends nothing to anyone.",
"required": [
"work_ids"
]
},
{
"tool": "pica_export_ownership_record",
"when": "The ownership REGISTER — per-contributor and per-asset record of who owns what, with claim status, share percentages, contributor IPI/ISNI, and the definitions a lawyer needs to read it. Pair with pica_export_rights_proof, which is the evidence behind this register.",
"required": []
},
{
"tool": "pica_export_rights_proof",
"when": "The EVIDENCE behind the ownership register — timestamped claims, contributor attestations, identity verification, evidence-integrity hashes. Use when asked to PROVE ownership rather than state it.",
"required": []
},
{
"tool": "pica_export_diligence_pack",
"when": "Catalogue diligence pack as a document — readiness scoring, ownership clarity, identifier completeness, uninsured insurable assets, gaps ranked by severity with a suggested action. For the same analysis as JSON (cheaper, no document) call pica_catalog_diligence instead.",
"required": []
}
],
"example": {
"format": "pro",
"work_id": "11111111-1111-1111-1111-111111111111"
}
},
"handover-required": {
"workflow": "handover-required",
"summary": "A catalogue an organisation builds for a client, who accepts to own it (ADR-333 D5). The organisation creates it with pica_handover_create (nothing is sent; while it is being prepared it can enter facts, but nothing is published, agreed or signed in its favour), then sends it with pica_handover_send, which emails the client; they have 60 days to accept. relationship_type is what the organisation keeps once they accept: administrator, representative or viewer, over the whole catalogue. Sending is the person's own decision: from a connected app it becomes an approval for the person; otherwise PICA may return HUMAN_CONFIRMATION_REQUIRED with the screen to send it on. Accepting is the client's own act, signed in with the address it was sent to: they keep or remove each item that names the organisation, then accept or decline. No tool accepts or declines; pica_handover_answer gives the client the link.",
"primary_tool": "pica_handover_create",
"primary_required": [
"client_name",
"client_email",
"relationship_type"
],
"primary_recommended": [
"catalogue_name",
"catalogue_org_id"
],
"enums": {},
"companion_calls": [
{
"tool": "pica_handover_send",
"when": "When the catalogue is ready: emails the client and starts the 60 days.",
"required": [
"handover_id"
],
"constraint": "expected_version is optional; when given and the hand-over changed since, nothing is sent."
},
{
"tool": "pica_handover_answer",
"when": "The client asks how to take over a catalogue prepared for them. Returns the screen link only; it never accepts or declines.",
"required": []
}
],
"example": {
"catalogue_name": "Alice Example",
"client_name": "Alice Example",
"client_email": "alice@example.com",
"relationship_type": "administrator"
}
},
"multimedia-required": {
"workflow": "multimedia-required",
"summary": "Required fields to register a multimedia item (photo / video / audio / external streaming link), and the patterns for importing or attaching to a work.",
"primary_tool": "pica_multimedia_create",
"primary_required": [
"title",
"content_type"
],
"primary_recommended": [
"url",
"classification",
"caption",
"description",
"tags",
"credits",
"duration_seconds",
"collection_id",
"display_order",
"is_featured",
"is_published",
"venue",
"event_name",
"performance_date",
"setlist_position",
"sync_side",
"spotify_url",
"spotify_track_uri",
"spotify_track_id",
"youtube_url",
"youtube_video_id",
"soundcloud_url",
"thumbnail_url"
],
"enums": {
"content_type": [
"live_performance",
"soundcloud_track",
"spotify_track",
"uploaded_audio",
"uploaded_photo",
"uploaded_video",
"youtube_video"
],
"classification": [
"album_artwork",
"artist_showcase",
"behind_the_scenes",
"general",
"live_performance",
"music_video",
"promo_material",
"studio_session",
"sync_placement"
]
},
"companion_calls": [
{
"tool": "pica_multimedia_import_url",
"when": "Import an external image or video URL — downloads the file into PICA storage rather than referencing it externally. Use for Spotify artwork, web images, etc.",
"required": [
"url"
]
},
{
"tool": "pica_multimedia_link_youtube",
"when": "YouTube-specific variant — pulls thumbnail, title, and view count automatically. Use this instead of pica_multimedia_create for YouTube videos.",
"required": [
"youtube_video_id",
"title"
]
},
{
"tool": "pica_multimedia_link_work",
"when": "Attach an existing multimedia item to a work with a typed relationship (music_video_for, sync_placement, album_artwork, etc.).",
"required": [
"multimedia_id",
"work_id",
"relationship_type"
]
}
],
"example": {
"title": "Midnight Rivers — Official Music Video",
"content_type": "youtube_video",
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
},
"person-required": {
"workflow": "person-required",
"summary": "Required fields to register a person (writer, performer, producer, publisher). Identifiers (IPI / ISNI / PRO / MusicBrainz / etc.) are inline-settable at create time.",
"primary_tool": "pica_people_create",
"primary_required": [
"first_name",
"last_name"
],
"primary_recommended": [
"middle_name",
"name",
"stage_name",
"stage_names",
"person_type",
"biography",
"email",
"emails",
"phone",
"website",
"social_media",
"roles",
"tags",
"is_group",
"cae_ipi_number",
"ipi",
"ipn_number",
"society_affiliations",
"pro_name",
"pro_member_number",
"default_publisher",
"default_publisher_ipi",
"company",
"position",
"territory",
"origin_countries",
"relationship_strength",
"email_preferences",
"profile_image_url",
"notes",
"isni",
"musicbrainz_id",
"wikidata_id",
"discogs_artist_id",
"deezer_artist_id",
"imdb_id",
"viaf_id",
"date_of_birth",
"date_of_death",
"gender",
"nationality",
"nationality_wikidata_id",
"birth_place",
"birth_place_wikidata_id",
"instruments",
"career_start_year",
"languages_spoken"
],
"enums": {},
"companion_calls": [
{
"tool": "pica_people_update",
"when": "After creation — to amend name, identifiers (IPI / ISNI / PRO / MusicBrainz / etc.), or any other inline field. Same payload shape as create plus `id`.",
"required": [
"id"
]
}
],
"example": {
"first_name": "Jane",
"last_name": "Doe",
"cae_ipi_number": "00000000001",
"isni": "0000000123456789",
"pro_member_number": "PRS123456"
}
},
"recording-credits-required": {
"workflow": "recording-credits-required",
"summary": "Required fields per credit row when attaching MainArtist / FeaturedArtist / Producer / Engineer credits to a recording. Distinct role enum from work credits. person_id is optional — credits can carry just credited_name.",
"primary_tool": "pica_recording_credits_update",
"primary_required": [],
"primary_recommended": [
"recording_id",
"person_id",
"credited_name",
"role",
"split_percentage",
"split_type",
"display_order",
"notes",
"instrument",
"release_id",
"recording_ids",
"credits",
"dry_run"
],
"enums": {
"role": [
"Arranger",
"Co-Producer",
"Engineer",
"Executive Producer",
"FeaturedArtist",
"Instrumentalist",
"MainArtist",
"Mastering Engineer",
"Mixer",
"Other",
"Performer",
"Producer",
"Programmer",
"Recording Engineer",
"Remixer",
"Vocalist"
]
},
"companion_calls": [],
"example": {
"recording_id": "<uuid>",
"credited_name": "The Riverbed Trio",
"role": "MainArtist",
"person_id": "<uuid>"
}
},
"recording-required": {
"workflow": "recording-required",
"summary": "Required fields to register a recording (a specific master, version, or live capture of a work).",
"primary_tool": "pica_recordings_create",
"primary_required": [
"title",
"artist_name",
"version_type"
],
"primary_recommended": [
"recording_title",
"notes",
"primary_artist_id",
"work_id",
"ownership_percentage",
"labels",
"isrc",
"isrc_source",
"musicbrainz_recording_id",
"society_registrations",
"duration_ms",
"preview_url",
"album_art_url",
"spotify_url",
"spotify_track_uri",
"spotify_track_id",
"youtube_video_id",
"youtube_url",
"apple_music_url",
"deezer_track_id",
"recorded_at",
"studio_name",
"ai_disclosure",
"provenance_attestation",
"training_rights",
"create_twin"
],
"enums": {
"version_type": [
"acoustic",
"alternate",
"alternate_master",
"cover",
"live_performance",
"lyric_video",
"master",
"music_video",
"remix"
]
},
"companion_calls": [
{
"tool": "pica_recording_credits_update",
"when": "Per credit — attach a single MainArtist / Producer / Engineer credit (single form needs recording_id + credited_name + role). Also accepts a credits[] batch across release_id / recording_ids (b477cd175 write-merge) — see recording-credits-required for the batch shape. Multi-mode, so the schema-level required list is empty; mode requirements live in this prose.",
"required": []
},
{
"tool": "pica_recordings_update",
"when": "After creation — to amend recording_title, artist_name, version_type, isrc, duration_ms, or any other inline field. Same payload shape as create plus `id`.",
"required": [
"id"
]
}
],
"example": {
"title": "Midnight Rivers (Master)",
"artist_name": "The Riverbed Trio",
"version_type": "master",
"isrc": "USABC2300001",
"duration_ms": 213000
}
},
"recording-splits-required": {
"workflow": "recording-splits-required",
"summary": "Required fields per row when assigning master-rights ownership on a recording. Distinct from publishing splits on works (those flow through pica_credits_update + pica_split_sheet_*). Recording splits drive master royalty payouts and downstream credit gating; pica_recording_splits_create runs an ADR-200 Class D form-confirmation gate when the client supports `elicitation/url`. Use `dry_run: true` first — it writes nothing and returns the shares already recorded plus `likely_refusal` when the write would be refused.",
"primary_tool": "pica_recording_splits_create",
"primary_required": [
"recording_id",
"split_type",
"percentage"
],
"primary_recommended": [
"person_id",
"role",
"territory",
"start_date",
"end_date",
"notes",
"dry_run"
],
"enums": {
"split_type": [
"master",
"mechanical",
"performance",
"sync"
],
"role": [
"engineer",
"label",
"masterer",
"mixer",
"other",
"owner",
"performer",
"producer"
]
},
"companion_calls": [
{
"tool": "pica_recording_splits_verify",
"when": "After create — explicitly mark a split as confirmed/agreed by the relevant parties. Sets verified=true + verified_at + verified_by on the row.",
"required": [
"recording_id",
"split_id"
]
},
{
"tool": "pica_recording_splits_list",
"when": "List all splits on a recording — verify totals and per-row verification state.",
"required": [
"recording_id"
]
},
{
"tool": "pica_recording_splits_update",
"when": "A recorded share is wrong — relink a holder-less ('unknown') row to a person, or change its percentage, role, split_type, territory or dates. The 100% total is checked after the change with this row's old value left out. Changing who/how much/dates clears the holder's confirmation (verification_cleared).",
"required": [
"recording_id",
"split_id"
]
},
{
"tool": "pica_recording_splits_end",
"when": "A share should stop counting toward the total — sets end_date (default today) and keeps the row as history. Use instead of deleting.",
"required": [
"recording_id",
"split_id"
]
}
],
"example": {
"recording_id": "<uuid>",
"split_type": "master",
"percentage": 50,
"role": "owner",
"person_id": "<optional uuid>",
"territory": "worldwide"
}
},
"relationship-required": {
"workflow": "relationship-required",
"summary": "Who looks after a catalogue (ADR-333). An owner invites an organisation by email with pica_relationships_grant; an organisation asks a client by email with pica_portfolio_invite. The other side answers with pica_relationships_answer: accept (optionally narrowing — never widening — type or scope), decline, or edit (a counter-proposal, or the owner's change to an active relationship). Every step on an existing relationship sends expected_version, the version read from pica_relationships_list or pica_portfolio_list; if the terms moved since, nothing happens and STATUS_CHANGED returns the current terms to read out again. Types: administrator (edits directly; splits and custody go to the owner), representative (every change goes to the owner as a proposal), viewer (sees and exports), co_owner (sees its share). Scope fields: half (both | composition | master), territories (only WW, worldwide, today: a limit to some countries is refused until a route can honour it), term_starts_on / term_ends_on (YYYY-MM-DD or null), money, directory (administrator only), catalogue (whole | chosen) with work_ids / recording_ids. Accepting, changing, revoking and an owner's invitation are the person's own decision: from a connected app they become an approval for the person; from PICA's own assistant they return HUMAN_CONFIRMATION_REQUIRED with the screen to do it on.",
"primary_tool": "pica_relationships_grant",
"primary_required": [
"email",
"type"
],
"primary_recommended": [
"scope"
],
"enums": {},
"companion_calls": [
{
"tool": "pica_portfolio_invite",
"when": "An organisation asks a client to let it look after their catalogue. Scope takes half, territories and term only: the client chooses what it covers when they accept.",
"required": [
"email",
"type"
]
},
{
"tool": "pica_relationships_list",
"when": "Before any step: read the relationship, its plain-words scope and its version; also lists invitations waiting for the person (invite_id + answer_for_one_of).",
"required": []
},
{
"tool": "pica_relationships_answer",
"when": "Answer a request: relationship_id + expected_version + action; or invite_id + organisation_id to accept an invitation by email (invitations can't be declined; they lapse after 30 days).",
"required": [],
"constraint": "Either relationship_id + expected_version + action, or invite_id + organisation_id. accept may only narrow type or scope; decline takes only a reason; edit needs a type or scope. With invite_id, action is accept and organisation_id is one of answer_for_one_of."
},
{
"tool": "pica_relationships_revoke",
"when": "The owner ends a relationship (or withdraws its own request). Irreversible; takes effect on the organisation's next request.",
"required": [
"relationship_id",
"expected_version"
]
},
{
"tool": "pica_relationships_step_down",
"when": "The organisation ends its own side (or withdraws its own request). Irreversible.",
"required": [
"relationship_id",
"expected_version"
]
},
{
"tool": "pica_relationships_activity",
"when": "What was done through a relationship: one relationship by relationship_id, or across the catalogue (side owner) or the organisation's clients (side organisation).",
"required": []
},
{
"tool": "pica_portfolio_list",
"when": "An organisation's clients: each catalogue id to pass as `catalogue` to the catalogue tools, what a change does there (direct, proposal, none), and the version for stepping down.",
"required": []
},
{
"tool": "pica_portfolio_briefing",
"when": "The same clients with up to five things each that need attention within scope.",
"required": []
}
],
"example": {
"email": "manager@example.com",
"type": "administrator",
"scope": {
"half": "composition",
"territories": [
"WW"
],
"term_ends_on": "2027-12-31",
"money": false,
"catalogue": "whole"
}
}
},
"session-required": {
"workflow": "session-required",
"summary": "Required fields to log a studio session — title + start_time + end_time (ISO 8601 datetimes). Optional `session_type_id` is a UUID FK to the org's session_types lookup table; resolve via pica_sessions_types. The `status` column accepts scheduled / in_progress / completed / cancelled per the inputSchema, but the values are NOT enforced by a DB CHECK constraint — verify against the live tool's inputSchema if values matter to the caller.",
"primary_tool": "pica_sessions_create",
"primary_required": [
"title",
"start_time",
"end_time"
],
"primary_recommended": [
"description",
"session_type_id",
"timezone",
"is_all_day",
"location",
"location_url",
"work_id",
"recording_id",
"status",
"notes",
"metadata",
"participants"
],
"enums": {},
"companion_calls": [
{
"tool": "pica_sessions_types",
"when": "Pre-flight to discover valid session_type_id values for this org. The lookup table is org-scoped and seeded with recording / mixing / mastering / writing / production / rehearsal entries on org bootstrap.",
"required": []
},
{
"tool": "pica_sessions_inspect",
"when": "After creation — verify the session row + participants persisted as expected. Reads back the full session record including any participants attached at create time. Pass id OR session_id (interchangeable entry points — requiredOneOf, so the schema-level required list is empty).",
"required": []
},
{
"tool": "pica_sessions_query",
"when": "Discovery / browse — list recent or upcoming sessions for the workspace.",
"required": []
}
],
"example": {
"title": "Vocal recording — Midnight Rivers",
"start_time": "2026-05-08T14:00:00+01:00",
"end_time": "2026-05-08T17:00:00+01:00",
"session_type_id": "<uuid from pica_sessions_types>",
"location": "Tileyard Studios",
"work_id": "<optional uuid>"
}
},
"split-sheet-required": {
"workflow": "split-sheet-required",
"summary": "Required fields to generate a publishing split sheet on a work. Pre-condition: the work's writer credits (set via pica_credits_update) must already total 100% — pica_split_sheet_generate validates and returns 400 otherwise. The generated sheet snapshots current splits + signature state; pica_split_sheet_send notifies each credited writer for review/signature. The split_sheets.status column defaults 'draft' and is NOT enforced by a DB CHECK constraint.",
"primary_tool": "pica_split_sheet_generate",
"primary_required": [
"work_id"
],
"primary_recommended": [],
"enums": {},
"companion_calls": [
{
"tool": "pica_split_sheet_send",
"when": "After generate — notify each credited writer for review/signature via in-app notification + Telegram (if connected) + email. Non-PICA-user writers receive a collaboration invite email instead. Soft-fails per-writer; aggregate result reports delivered / not_a_pica_user / failed counts.",
"required": [
"work_id",
"split_sheet_id"
]
},
{
"tool": "pica_split_sheet_get",
"when": "Read back a specific sheet with its full content + signature state. Use after send to check who has signed.",
"required": [
"work_id",
"split_sheet_id"
]
},
{
"tool": "pica_split_sheet_list",
"when": "List all sheets for a work — useful when multiple revisions exist (e.g. a sheet was generated, splits changed, regenerate).",
"required": [
"work_id"
]
}
],
"example": {
"work_id": "<uuid — credits must total 100% first via pica_credits_update>"
}
},
"sync-placement-required": {
"workflow": "sync-placement-required",
"summary": "Sync-placement create flow — atomic write of (placement + draft sync_license agreement + at least one agreement_party + recordings + evidence sources) in a single Postgres transaction. At least one entry in `contacts[]` is required (empty rejects with structured MISSING_CONTACT). Contacts may reference an existing `person_id` OR pass `person_name` + `role` (+ optional email/company/position) to auto-create a person row inline. The verification_status auto-advances based on evidence kinds: any non-attestation source ('cue_sheet', 'invoice', 'agreement_pdf', 'email', 'screenshot', 'web', 'spreadsheet_import') → evidence_attached; only 'user_attestation' → self_attested; none → unverified. Operator-only fields (verification_status='operator_verified'|'disputed', confidentiality_level changes, hard delete) throw OPERATOR_REQUIRED for customer agents; use update with status:'terminated' for self-service retirement.",
"primary_tool": "pica_sync_placements_create",
"primary_required": [
"work_id",
"production_title",
"contacts"
],
"primary_recommended": [
"production_type",
"brand",
"production_company",
"status",
"fee_amount",
"fee_currency",
"use_start_date",
"use_end_date",
"territory",
"media_channels",
"notes",
"confidentiality_level",
"recordings",
"sources"
],
"enums": {
"status": [
"aired",
"expired",
"licensed",
"renewed",
"terminated"
],
"verification_status": [
"disputed",
"evidence_attached",
"operator_verified",
"self_attested",
"unverified"
],
"confidentiality_level": [
"private",
"public",
"redacted_in_public_car"
]
},
"companion_calls": [
{
"tool": "pica_sync_placements_inspect",
"when": "After create — read the placement back to confirm verification_status auto-advance and inspect the linked agreement + parties + recordings + sources.",
"required": [
"id"
]
},
{
"tool": "pica_sync_placements_update",
"when": "Patch fee, dates, status, territory, media_channels, brand, production_company, or any other inline field. Status transitions follow the placement state machine; illegal transitions throw INVALID_TRANSITION.",
"required": [
"id"
]
},
{
"tool": "pica_sync_placements_cite",
"when": "Attach an evidence source after creation — auto-advances verification_status when the kind is non-attestation.",
"required": [
"id",
"url",
"kind"
]
},
{
"tool": "pica_sync_placements_delete",
"when": "Operator-only hard delete (two-step confirmation). Customer agents should use pica_sync_placements_update with status:'terminated' instead for self-service soft-delete.",
"required": [
"id"
]
},
{
"tool": "pica_sync_placements_query",
"when": "List placements for the org — filter by work_id, status, verification_status, brand, production_company, person_id, recording_id, source_license_enquiry_id, min_fee, currency.",
"required": []
}
],
"example": {
"work_id": "00000000-0000-0000-0000-000000000000",
"production_title": "Midnight Rivers — Trailer 2026",
"production_type": "trailer",
"brand": "Lumière Studios",
"production_company": "Lumière Studios Inc.",
"status": "licensed",
"fee_amount": 25000,
"fee_currency": "USD",
"use_start_date": "2026-06-01",
"use_end_date": "2027-05-31",
"territory": [
"WW"
],
"media_channels": [
"theatrical",
"online"
],
"confidentiality_level": "redacted_in_public_car",
"contacts": [
{
"person_name": "Sarah Lee",
"role": "music_supervisor",
"email": "sarah@lumiere.example",
"company": "Lumière Studios"
}
],
"recordings": [
{
"recording_id": "00000000-0000-0000-0000-000000000001",
"role": "main_master",
"master_fee": 12500,
"master_share_licensed_pct": 100
}
],
"sources": [
{
"url": "https://example.com/agreements/midnight-rivers.pdf",
"kind": "agreement_pdf",
"field_coverage": [
"fee_amount",
"use_start_date",
"territory"
]
}
]
}
},
"work-credits-required": {
"workflow": "work-credits-required",
"summary": "Required fields per credit row when attaching writer/composer/publisher credits to a work. The tool exposes `role` (composition roles route to `work_collaborators`, master roles to `recording_credits`, keyed by grain) and `splits` (mapped to `split_percentage`). Splits must sum to 100. Valid role values are enumerated on the `role` field of `pica_credits_update`. Attestation is not a field you send: every credit starts as pending and only the credited person confirms it (pica_credits_send_for_attestation).",
"primary_tool": "pica_credits_update",
"primary_required": [
"work_id",
"credits"
],
"primary_recommended": [],
"enums": {},
"companion_calls": [
{
"tool": "pica_credit_update",
"when": "After credits exist — edit ONE credit in place (a writer's share, a role, the displayed name, notes, an instrument, or who it is for via person_id) without re-sending the set. Find the credit_id with pica_credits_list. The credit keeps its id; its attestation state is kept unless person_id changes who it is for, which sends a confirmed, disputed or declined credit back to pending.",
"required": [
"work_id",
"credit_id"
],
"constraint": "At least one of share_pct, credit_type, credited_name, notes, instrument, person_id. share_pct is 0-100, or null to record the share as UNKNOWN (never 0). Writer-split closure is NOT enforced on a single edit — re-split one writer at a time. person_id must be a person in this organisation, not deleted, and not already holding this role on the song or recording (CREDIT_PERSON_CONFLICT); linking a name-only credit to a differently named person needs confirm_name_mismatch: true."
},
{
"tool": "pica_credits_send_for_attestation",
"when": "After attaching credits — send confirmation prompts to credited collaborators so each person can attest or dispute their own row. Lightweight alternative to pica_split_sheet_send when a signed split sheet isn't needed.",
"required": [
"work_id"
]
}
],
"example": {
"work_id": "<uuid>",
"credits": [
{
"person_id": "<uuid>",
"role": "writer",
"splits": 50
},
{
"person_id": "<uuid>",
"role": "writer",
"splits": 50
}
]
}
},
"work-required": {
"workflow": "work-required",
"summary": "Required fields to register a fully-credited musical work.",
"primary_tool": "pica_works_create",
"primary_required": [
"title",
"work_type"
],
"primary_recommended": [
"work_status",
"iswc",
"isrc",
"tunecode",
"society_registrations",
"spotify_track_uri",
"duration_seconds",
"tempo",
"key",
"genre",
"mood",
"primary_artist",
"primary_artist_id",
"disambiguation",
"original_work_id",
"display_artist",
"publisher_name",
"lyrics",
"lyrics_language",
"published",
"notes",
"metadata",
"ai_disclosure",
"provenance_attestation",
"training_rights",
"create_twin"
],
"enums": {
"work_type": [
"demo",
"instrumental",
"library",
"sample",
"score",
"song"
],
"work_status": [
"archived",
"demo",
"pitched",
"placed",
"released",
"unreleased"
]
},
"companion_calls": [
{
"tool": "pica_credits_update",
"when": "Once per work, batch — attach all writer/publisher splits in a single call.",
"required": [
"work_id",
"credits"
],
"per_row_required": [
"person_id",
"role"
],
"constraint": "splits values must sum to 100 across all credits for the work (the tool maps role→work_collaborators/recording_credits by grain and splits→split_percentage)."
},
{
"tool": "pica_credit_update",
"when": "After credits exist — edit ONE credit in place (a writer's share, a role, the displayed name, notes, an instrument, or who it is for via person_id) without re-sending the set. Find the credit_id with pica_credits_list. The credit keeps its id; its attestation state is kept unless person_id changes who it is for, which sends a confirmed, disputed or declined credit back to pending.",
"required": [
"work_id",
"credit_id"
],
"constraint": "At least one of share_pct, credit_type, credited_name, notes, instrument, person_id. share_pct is 0-100, or null to record the share as UNKNOWN (never 0). Writer-split closure is NOT enforced on a single edit — re-split one writer at a time. person_id must be a person in this organisation, not deleted, and not already holding this role on the song or recording (CREDIT_PERSON_CONFLICT); linking a name-only credit to a differently named person needs confirm_name_mismatch: true."
},
{
"tool": "pica_works_update",
"when": "After creation — to amend title, work_type, work_status, iswc, lyrics, or any other inline field. Use the same payload shape as create with the addition of `id`.",
"required": [
"id"
]
},
{
"tool": "pica_works_attest",
"when": "After registering — stamp a human-creation provenance attestation for sync libraries / provenance certificates. Captures who signed it, when, and the attestation method.",
"required": [
"id"
]
},
{
"tool": "pica_credits_send_for_attestation",
"when": "After attaching credits — notify each credited person (in-app + telegram + email) that they have a pending credit awaiting their attestation. Lightweight alternative to pica_split_sheet_send when a signed document isn't needed.",
"required": [
"work_id"
]
},
{
"tool": "pica_works_verify_registrations",
"when": "When registration status is unknown — mode 'check' looks works up at the MLC and records what the lookup PROVED (found = positive society fact; clean not-found = verified-absent assertion); mode 'confirm_unregistered' records the user's own confirmation. Up to 25 works per call; idempotent.",
"required": [
"work_ids",
"mode"
]
}
],
"example": {
"title": "Midnight Rivers",
"work_type": "song",
"iswc": "T-123.456.789-0",
"duration_seconds": 213
}
}
};
//# sourceMappingURL=required-schemas.generated.js.map