UNPKG

@withpica/mcp-server

Version:

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

104 lines (90 loc) • 7.66 kB
// Copyright (c) 2025-2026 Withpica Ltd. All rights reserved. /** * Server-level instructions sent to agents on MCP handshake. * Keep under 3200 chars — this is context budget, not documentation. * Bumped from 2000 in 2026-05-11 (ADR-140 Phase 2b skills paragraph). * Bumped to 2400 then restored to 2300 in 2026-05-13 (deeplink hint + paragraph trims net -180 chars). * Bumped from 2300 in 2026-05-17 (ADR-241 first-session coaching line). * Bumped to 2900 in 2026-05-25 (ADR-247 first-call identity paragraph, ~470 chars). * * Two variants per ADR-211 Phase 1 Primitive C: * - SERVER_INSTRUCTIONS / SERVER_INSTRUCTIONS_AUTHENTICATED: full surface * guidance. Selected when the binary has a connection key (PICA_API_KEY). * - SERVER_INSTRUCTIONS_UNAUTHENTICATED: short lobby guidance pointing the * agent at pica_signup_start (or pica_sign_in for existing users). * Selected when the binary boots without PICA_API_KEY. The lobby * surface is the 3 tools {pica_signup_start, pica_sign_in, * pica_sign_out} — none of the catalog tools are reachable, so we * skip the catalog-tool guidance. * * Block playbook: "document the high level of your server" * Lowin: "instructions are context — design them as context" */ export const SERVER_INSTRUCTIONS = `withPICA helps people look after their songs, and everything that comes with them (people, splits, codes, recordings, agreements, files), on their own terms: the user holds the record and decides; PICA remembers and shows what's missing. Asked what PICA is, say that plainly, in their words. Tools are pica_<domain>_<verb>, 300+, from npm as @withpica/mcp-server (not @picahq/mcp, unrelated). First-call identity: If your auth is a Bearer API key (not a cookie session and not a pica_grant_* token), call pica_introduce_self FIRST with agent_name + optional agent_role / on_behalf_of / model_hint. PICA stamps the declaration onto every audit row that follows so the user can later reconstruct what their agent did. Cookie and pica_grant_* callers are exempt — your identity is already on file. Declaration is valid 24h per credential. On the first user message of a session — unless it names a single concrete action (e.g. "register work X") — call pica_skill_get("first-session") and follow it. Start here: - pica_dashboard_briefing — daily summary of what needs attention - pica_search_all — find any entity by name, ISWC, ISRC, or IPI - pica_works_query / pica_people_query — browse the catalog - pica_subscription_status — "what's my plan / am I paying?"; pica_billing_pay — a pay link for residency or a tab. On a connector call them through pica_execute {tool: "<name>", args: {...}} The catalog is ALWAYS accessible via the tools above — zero setup, no integration required. Call pica_works_query directly for catalog content. Clients: an organisation acts for a client catalogue by passing catalogue: <id from pica_portfolio_list>, per call; omit it for its own. Who can see a catalogue: pica_relationships_list. Spotify/YouTube URLs: call pica_import_streaming_link (Spotify/Deezer) or pica_import_youtube_link directly. After 3-5 catalog mutations or major state changes, call pica_dashboard_briefing and surface the delta to the user. Key patterns: - Read tools are safe to call freely (readOnlyHint=true) - many _inspect tools take a "sections" argument (e.g., pica_works_inspect sections: ["health", "completeness"]) — check the tool's schema - Write tools confirm what changed — share https://withpica.com/inspect/<feature>/<id> so the user can review (feature: works, people, recordings, releases, agreements; for audio files link the parent work). Destructive tools (delete/merge) need two-step confirmation with a token - Errors include "suggestion" and "next_tool" for recovery - Enrichment: use pica_resolve_work / pica_resolve_person / pica_resolve_recording — fan out over Spotify, MusicBrainz, MLC, ISNI, Discogs, YouTube Royalty/streaming statements (PDF/image/xlsx): use pica_statements_pending → pica_documents_inspect → pica_statement_ingest_document (imports after owner approval). CSV statements go through pica_import_analyze / pica_import_execute instead. Most query tools accept "limit"; defaults vary — read the tool's schema. IDs are UUIDs — use a _query tool first when unsure. Skills: pica_skill_list discovers methodologies (catalog-audit, register-my-works, prepare-for-sync). pica_skill_get(name) loads one. Trigger phrases like "audit my catalog" map directly. Bodies load lazily — not at handshake. Provenance: when a fact comes from a source, cite it via pica_enrichment_propose sources[].url. Citations persist verbatim and propagate to applied entities.`; /** Alias for the authenticated default — names the variant explicitly when paired with the unauthenticated one. */ /** * How many leading characters of SERVER_INSTRUCTIONS a client was observed to * surface before cutting the rest. Measured 2026-09-04 on Claude Code's * rendering of the claude.ai connector ("[truncated]" after exactly this * many characters); ChatGPT surfaces none of it (docs/follow-ups * 2026-08-26). Anything that must reach an agent that never calls * pica_discover — the pay path above all — has to sit inside this window; * server-instructions.test.ts pins that it does. */ export const INSTRUCTIONS_OBSERVED_VISIBLE_CHARS = 2000; export const SERVER_INSTRUCTIONS_AUTHENTICATED = SERVER_INSTRUCTIONS; /** * Returns the authenticated handshake instructions. * * Historically appended a state-conditional trial-ending nudge (ADR-210 * Phase 3 / coordinator D3) keyed off `billing_state === 'trial'` + * `trial_days_remaining`. Removed 2026-07-04 (discoverability audit P1-6): * ADR-276 replaced the expiring-trial model with a non-expiring free-runway * allowance, so a day-count nudge no longer describes real account state — * dead messaging that would mislead an agent if it ever fired. */ export function getAuthenticatedInstructions() { return SERVER_INSTRUCTIONS_AUTHENTICATED; } /** * Lobby instructions sent on handshake when the server has no connection key * (stdio without PICA_API_KEY) or no Bearer token (HTTP /api/mcp anonymous mode). * * Lobby tool surface is exactly three tools: * - pica_signup_start — for new users (mints a 15-min JWT-bound /onboard URL) * - pica_sign_in — for existing users (sends a magic link) * - pica_sign_out — for clearing stale credentials * * Authority: ADR-211 Phase 1 § Primitive C. Catalog-tool guidance omitted * because none of the catalog tools are reachable in lobby mode. * * Kept byte-for-byte identical to lib/mcp/server-instructions.ts — * `__tests__/mcp-server-instructions-unauth-parity.test.ts` enforces. */ export const SERVER_INSTRUCTIONS_UNAUTHENTICATED = `You are connected to withPICA but no user is authenticated yet. Three tools are available: - pica_signup_start — for users new to withPICA. Ask for the user's email, then call this tool. It returns a single-use 15-minute signup link the user clicks to verify email, name their catalog, and start their free runway. - pica_sign_in — for users who already have a withPICA account. Sends a magic link to their inbox (device-code flow on stdio). - pica_sign_out — clears saved credentials. Do not promise catalog data, exports, or analyses until the user is signed in — none of those tools are reachable from this lobby. After signup or sign-in, the connection's tool surface refreshes automatically; ask the user what they want to do next.`; //# sourceMappingURL=server-instructions.js.map