UNPKG

@withpica/mcp-server

Version:

MCP Server for withPICA — enables AI assistants to interact with your withPICA music catalog

137 lines • 7.6 kB
// Copyright (c) 2025-2026 Withpica Ltd. All rights reserved. import { formatSuccess } from "@withpica/mcp-utils"; export class StatementsTools { pica; constructor(pica) { this.pica = pica; } getTools() { return [ { definition: { name: "pica_statements_pending", scope: "read:finances", audiences: ["stdio", "http", "public"], tier: "read", description: "List uploaded royalty/streaming statement documents the user hasn't imported yet. For each, read it with pica_documents_inspect, extract the line items, and import with pica_statement_ingest_document. Returns lean summaries (id, title, parsing_status) — no financial figures. Statements can't be emailed into PICA: if the user has a statement that isn't listed, ask them to upload it (the result's forwarding field says the same). Statements already imported are not listed here — use pica_statements_query for those.", workflows: "infrastructure", vernacular_kind: "specialist", vernacular_reason: "Specialist discovery for the statement-ingestion flow, outside the Creator Question Atlas.", annotations: { title: "pending statements", readOnlyHint: true, idempotentHint: true, }, inputSchema: { type: "object", properties: { parsed_status: { type: "string", enum: ["pending", "completed", "all"], description: "filter by parse state", }, limit: { type: "number", minimum: 1, maximum: 50, description: "max rows (default 25, max 50)", }, offset: { type: "number", description: "pagination offset" }, }, }, }, executor: this.listPending.bind(this), }, { definition: { name: "pica_statement_ingest_document", scope: "write:finances", audiences: ["stdio", "http", "public"], tier: "write", // Delegated agents (OAuth/grant) propose; the org owner approves // in-view/email; PICA replays via human-approval-executor (ADR-250). approvalMode: "human", description: "When the user has uploaded a royalty/streaming statement document (PDF, image, or xlsx — NOT csv; csv goes through pica_import_analyze / pica_import_execute instead, a deterministic row-by-row importer with no AI extraction step), read it with pica_documents_inspect, extract the line items, then call this to import them. Money is fallible: extract fewer rows confidently over many rows wrongly, set a per-row confidence, and never guess a figure. Returns a summary; the import only lands after the owner approves. Find pending statements with pica_statements_pending.", workflows: "infrastructure", vernacular_kind: "specialist", vernacular_reason: "Financial write behind human approval; invoked by exact name in a specialist statement-ingestion flow, outside the Creator Question Atlas.", annotations: { title: "ingest statement document" }, inputSchema: { type: "object", properties: { document_id: { type: "string", description: "the uploaded statement document id", }, source: { type: "string", description: "the society/distributor the statement is from, e.g. 'PRS', 'DistroKid'", }, statement_period: { type: "string", description: "e.g. 'Q4 2025' (optional)", }, rows: { type: "array", description: "one entry per statement line you read", items: { type: "object", properties: { work_title: { type: "string" }, amount: { type: "number" }, currency: { type: "string" }, payment_date: { type: "string", description: "ISO date YYYY-MM-DD", }, stream_quantity: { type: "number", description: "plays/streams; omit for society statements", }, territory: { type: "string" }, revenue_type: { type: "string" }, isrc: { type: "string" }, iswc: { type: "string" }, ipi: { type: "string" }, tunecode: { type: "string" }, writer_name: { type: "string" }, confidence: { type: "number", description: "0-1, your confidence in this line", }, }, required: [ "work_title", "amount", "payment_date", "confidence", ], }, }, }, required: ["document_id", "source", "rows"], }, }, executor: this.ingestDocument.bind(this), }, ]; } async listPending(args) { const result = await this.pica.statements.listPending({ limit: args.limit, offset: args.offset, parsed_status: args.parsed_status, }); return formatSuccess("Pending statements", result); } async ingestDocument(args) { const result = await this.pica.statements.ingestDocument({ document_id: args.document_id, source: args.source, statement_period: args.statement_period, rows: args.rows, }); return formatSuccess("Statement rows ingested", result); } } //# sourceMappingURL=statements.js.map