@withpica/mcp-server
Version:
MCP Server for withPICA — enables AI assistants to interact with your withPICA music catalog
136 lines • 7.52 kB
TypeScript
/**
* Silent-alias engine. A deprecated tool name stays callable and routes to its
* canonical replacement, is hidden from discovery, and carries a soft
* `_meta.deprecation` hint. Aliases are declared as data here; `expandAliases`
* materialises them into the registry at registration time. Removal is a
* traffic-informed decision (prod `agent_events`), forced by the "expire
* loudly" lint on `removal_target` (`checkDeprecationExpiry` in
* `scripts/lint-mcp-tools.ts`), which fails a publish at or past the target
* while the alias still exists.
*/
import type { ToolDefinition, ToolExecutor, ToolMetadata } from "./index.js";
export interface ToolAlias {
/** The deprecated tool name (kept callable, hidden from discovery). */
deprecated: string;
/** The canonical tool the alias routes to. Must be a registered tool name. */
canonical: string;
/** Semver at which the alias must be gone. Enforced by lint-mcp-tools. */
removal_target: string;
/** Maps the deprecated arg shape onto the canonical's. Identity if omitted. */
adaptArgs?: (args: Record<string, any>) => Record<string, any>;
}
/**
* 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 declare const TOOL_ALIASES: ToolAlias[];
/**
* A tool name that no longer exists, and what replaced it.
*
* An alias whose deadline passes is DELETED — it stops being callable — but a
* caller still using the old name deserves more than a similarity guess:
* "pica_projects_list" ranks create/delete/inspect above the query tool that
* actually replaced it. This table is the one place that knows what replaced
* what. Both not-found answers read it through {@link retiredToolAnswer}: the
* registry's `pica_execute` / `pica_tool_details` (`discovery.ts`) and the
* hosted route's gate (`app/api/mcp/tool-not-found.ts`, handed this function
* by `route.ts`). The call stays an error — `TOOL_NOT_FOUND` — so an old name
* never silently works again.
*/
export interface RetiredTool {
/** The registered tool to call instead. */
replacement: string;
/** The package version that removed the old name. */
removed_in: string;
/** How the arguments changed, when they did. Appended to the message. */
argument_change?: string;
}
export declare const RETIRED_TOOLS: Readonly<Record<string, RetiredTool>>;
/** The retired-tool record for a name, if it is one. */
export declare function getRetiredTool(name: string): RetiredTool | 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 declare function retiredToolAnswer(name: string, similar: readonly string[], canCall: (tool: string) => boolean): {
suggestions: string[];
note: string | null;
};
/** True when a tool's metadata marks it deprecated (aliased). Pure. */
export declare function isDeprecatedMeta(meta: {
deprecated?: boolean;
} | undefined): boolean;
/** Look up the alias record for a deprecated name, if any. */
export declare function getAliasFor(name: string): ToolAlias | undefined;
type RegistryEntry = {
definition: ToolDefinition;
executor: ToolExecutor;
metadata?: ToolMetadata;
};
/**
* 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 declare function expandAliases(registered: Map<string, RegistryEntry>, aliases: ToolAlias[]): void;
export {};
//# sourceMappingURL=deprecations.d.ts.map