UNPKG

@withpica/mcp-server

Version:

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

177 lines • 8.33 kB
// Copyright (c) 2025-2026 Withpica Ltd. All rights reserved. /** * The one alias registry. Populated per-consolidation; EMPTY as of * mcp-server 2.99.0. * * REMOVAL (mcp-server 2.99.0, founder decision 2026-09-29): the last eleven * aliases were removed — their entries here, their TOOL_METADATA mirrors, * and any standalone ToolDefinitions that still sat beside the canonical * tools. Prod `agent_events` over the 60 days to 2026-09-29: 4 calls in all * (pica_recording_credits_bulk_update 2, last 08-17; pica_releases_get 1, * 08-01; pica_royalties_summary 1, 09-14; the other eight zero). Calling any * of them now gets TOOL_NOT_FOUND whose message names its replacement; the * replacement also leads `did_you_mean` when the caller can call it. The * name → replacement mapping is RETIRED_TOOLS below — the one copy. * The dated notes below are the history of how that deadline moved. * * REMOVAL SWEEP (mcp-server 2.93.0, 2026-07-12): the first batch of WS5 * deprecated names were traffic-gated against prod `agent_events` (30-day * window). Six identity read-fold aliases with ZERO recent traffic were * DELETED entirely this release — their alias entry here, their standalone * ToolDefinition, TOOL_METADATA, cost-model, and required-schemas companion * rows all went with them: `pica_projects_get`, `pica_notes_get`, * `pica_sessions_list`, `pica_sessions_get`, `pica_statements_get`, * `pica_share_links_list`. The ten aliases that then remained still carried * real live traffic, so they STAYED callable — their `removal_target` was * consciously extended (the "expire loudly" lint would otherwise have blocked * the 2.93.0 publish), with the traffic check to be re-run before the new * target. They were finally removed in 2.99.0 (above). * * ⚠️ `removal_target` HERE IS DOCUMENTATION, NOT THE GATE (noted 2026-08-13). * `checkDeprecationExpiry` in `scripts/lint-mcp-tools.ts` reads the value from * TOOL_METADATA in `metadata.ts`, never this file — so if the two disagree it * is metadata's value that expires the alias. * * They cannot silently disagree any more: `checkAliasMetadataMirror` * (`scripts/lint-mcp-tools.ts`) is handed this file's targets by * `loadAliasRemovalTargets` and hard-fails on any mismatch, not merely on a * missing mirror. That comparison was ADDED because they HAD drifted: this * file said 2.95.0 while metadata said 2.96.0, and the package shipped 2.95.2 * without the lint firing. Realigned to 2.96.0, then DEFERRED to * 2.97.0 on 2026-08-26 — the MPP pay rail (WS-B) needed a minor bump for a new * tool, the next minor after 2.95.4 is unavoidably 2.96.0, and none of these * ten aliases had been removed. See the matching comment in `metadata.ts`. If * you change a target, change BOTH — or the comment stops describing the * deadline the build actually enforces. * * ⚠️ Deferred 2026-09-04: 2.97.0 became the ops-root-causes release * (aliases, envelopes, offsets — PR fix/ops-root-causes-2026-09-03). * Alias removal needs its own PR with an agent_events usage check per * alias (SELECT tool_name, count(*) FROM agent_events WHERE tool_name IN * (…) AND created_at > now() - interval '60 days'). Founder item F10 * schedules it before 2.98.0; deferred again 2026-09-29 to 2.99.0 (founder: * 2.98.0 shipped the ADR-321 Phase 2 release without removals). */ export const TOOL_ALIASES = [ // Empty since mcp-server 2.99.0 — every alias has been removed (history in // the comment above). Add a new entry here, with its TOOL_METADATA mirror, // for the next deprecation. ]; export const RETIRED_TOOLS = { // mcp-server 2.99.0 (founder, 2026-09-29) — the last eleven aliases. pica_releases_list: { replacement: "pica_releases_query", removed_in: "2.99.0", }, pica_releases_get: { replacement: "pica_releases_inspect", removed_in: "2.99.0", }, pica_releases_bulk_attach_tracks: { replacement: "pica_releases_attach_track", removed_in: "2.99.0", argument_change: "pass the tracks as items[] (the old tracks field)", }, pica_releases_attach_track_by_identifier: { replacement: "pica_releases_attach_track", removed_in: "2.99.0", argument_change: "pass identifier_type + value (with track_number) on pica_releases_attach_track", }, pica_projects_list: { replacement: "pica_projects_query", removed_in: "2.99.0", }, pica_notes_list: { replacement: "pica_notes_query", removed_in: "2.99.0" }, pica_documents_list: { replacement: "pica_documents_query", removed_in: "2.99.0", }, pica_documents_read: { replacement: "pica_documents_inspect", removed_in: "2.99.0", }, pica_statements_list: { replacement: "pica_statements_query", removed_in: "2.99.0", }, pica_royalties_summary: { replacement: "pica_royalties_blockers", removed_in: "2.99.0", argument_change: "work_id and limit carry over; gap_type and priority have no equivalent", }, pica_recording_credits_bulk_update: { replacement: "pica_recording_credits_update", removed_in: "2.99.0", argument_change: "pass the credit set as a credits[] array (with release_id or recording_ids)", }, }; /** The retired-tool record for a name, if it is one. */ export function getRetiredTool(name) { return Object.prototype.hasOwnProperty.call(RETIRED_TOOLS, name) ? RETIRED_TOOLS[name] : undefined; } /** * Adjust a not-found answer for a retired name. Pure. * * `similar` is the similarity-ranked suggestion list the caller already built * (at most three names). For a retired name whose replacement `canCall` * accepts, the replacement goes FIRST and the list stays at most three long; * `note` is the sentence to lead the message with. A replacement the caller * cannot call is named in `note` (the mapping is published in the package * CHANGELOG) but never added to the suggestions. This function does not * filter `similar` itself: each caller builds it from names the caller can * call (`canSuggest` in discovery.ts; the `allowedToolNames` pool in * app/api/mcp/tool-not-found.ts). For any other name the list comes back * unchanged and `note` is null. */ export function retiredToolAnswer(name, similar, canCall) { const retired = getRetiredTool(name); if (!retired) return { suggestions: [...similar], note: null }; const suggestions = canCall(retired.replacement) ? [ retired.replacement, ...similar.filter((n) => n !== retired.replacement), ].slice(0, 3) : [...similar]; const note = `${name} was retired in mcp-server ${retired.removed_in}; use ` + `${retired.replacement} instead` + (retired.argument_change ? ` — ${retired.argument_change}` : "") + "."; return { suggestions, note }; } /** True when a tool's metadata marks it deprecated (aliased). Pure. */ export function isDeprecatedMeta(meta) { return meta?.deprecated === true; } /** Look up the alias record for a deprecated name, if any. */ export function getAliasFor(name) { return TOOL_ALIASES.find((a) => a.deprecated === name); } /** * For every alias whose canonical is present in `registered`, register the * deprecated name as a hidden, callable clone that delegates to the canonical. * Aliases with a missing canonical (e.g. lobby mode) are skipped silently. */ export function expandAliases(registered, aliases) { for (const alias of aliases) { const canonical = registered.get(alias.canonical); if (!canonical) continue; const canonicalExecutor = canonical.executor; const def = { ...canonical.definition, name: alias.deprecated, tier: canonical.definition.tier, scope: canonical.definition.scope, audiences: canonical.definition.audiences, inputSchema: canonical.definition.inputSchema, }; registered.set(alias.deprecated, { definition: def, executor: (args, ctx) => canonicalExecutor(alias.adaptArgs ? alias.adaptArgs(args) : args, ctx), }); } } //# sourceMappingURL=deprecations.js.map