/** * Tool registry — one validated entry point for invoking module tools by name. * * MCP clients call tools through FastMCP, which validates arguments against * each tool's schema before `execute` runs. Server features that call tools * internally (code_mode, deprecated aliases, discovery mode) must apply the * same validation, otherwise schema defaults, bounds and enums are skipped. * They all go through `ToolRegistry.invoke()`. */ import type { Tool } from "fastmcp"; import type { ApiModule } from "../shared/types.js"; type IssuePathSegment = PropertyKey | { key: PropertyKey; }; interface ValidationIssue { message: string; path?: ReadonlyArray; } /** A registered module tool. */ export interface RegisteredTool { /** Canonical tool name. */ name: string; /** Name of the module that owns the tool. */ module: string; /** The FastMCP tool definition. */ tool: Tool; } /** Outcome of `ToolRegistry.invoke()`. Never throws for expected failures. */ export type InvokeResult = { ok: true; tool: RegisteredTool; result: unknown; } | { ok: false; kind: "unknown_tool" | "invalid_args" | "execution_error"; message: string; tool?: RegisteredTool; }; /** Render validation issues as "field: message; other: message". */ export declare function formatIssues(issues: ReadonlyArray): string; export declare class ToolRegistry { private readonly tools; private readonly aliases; /** Register a module tool under its canonical name. */ register(moduleName: string, tool: Tool): RegisteredTool; /** Map a legacy name to a canonical tool. */ addAlias(alias: string, canonical: string): void; /** Look up a tool by canonical name or alias. */ resolve(name: string): RegisteredTool | undefined; /** True when `name` is a registered alias (not a canonical name). */ isAlias(name: string): boolean; /** Canonical tool names, sorted. */ names(): string[]; /** Alias → canonical pairs. */ aliasEntries(): [string, string][]; /** * Canonical names that look like `name` — shared underscore-separated * tokens or substring matches — best first. For "did you mean" hints. */ suggest(name: string, limit?: number): string[]; /** All registered tools. */ entries(): RegisteredTool[]; get size(): number; /** * Validate `args` against the tool's schema without executing it. * Applies defaults, bounds and enums exactly as FastMCP does for direct calls. */ validate(name: string, args: unknown): Promise<{ ok: true; tool: RegisteredTool; value: unknown; } | { ok: false; kind: "unknown_tool" | "invalid_args"; message: string; tool?: RegisteredTool; }>; /** Validate `args` (see `validate`), then run the tool's `execute`. */ invoke(name: string, args: unknown, context?: unknown): Promise; } /** Build a registry from the loaded modules plus a legacy-name alias map. */ export declare function buildToolRegistry(modules: Pick[], aliases?: Record): ToolRegistry; export {}; //# sourceMappingURL=tool-registry.d.ts.map