import type { AuthContext } from '@nacre.work/api'; /** * The tool catalog, from docs/mcp.md 5.4. * * Every entry names the permission it needs, and the permission is checked on * every call by the authorization service. A valid token grants access to no * document by itself — EMA and ID-JAG authorize the *connection*, and that is a * different question from whether this caller may read this layer. */ export type ToolPermission = 'read' | 'write'; export interface Layer { readonly id: string; readonly slug: string; readonly name: string; /** User-facing copy: it ends up in the generated tool description. */ readonly description: string; readonly documentCount: number; } export interface ToolDefinition { readonly name: string; readonly description: string; readonly inputSchema: Record; readonly permission: ToolPermission; } /** A tool as MCP defines one: no `permission`, because that field is ours. */ export type WireTool = Omit; /** * The catalog as it goes on the wire. * * `permission` is this repository's own bookkeeping — it names what a tool * resolves, and `mcp-surface.test.ts` asserts each one. MCP's `Tool` object has * no such member, so putting it in a response is a non-standard field a client * validating against the schema is entitled to refuse. * * Streamable HTTP stripped it and STDIO did not, so for the whole life of both * transports `tools/list` answered with different objects depending on which * one you asked — and `transport-parity.test.ts`, which exists against exactly * that, compared the tool *names* and was green. One function now, because two * places that have to remember is what produced it, and the parity case * compares the shape. */ export declare const onTheWire: (tools: readonly ToolDefinition[]) => WireTool[]; /** * How many layers `tools/list` names inside the search description. * * A sample, not the catalog. The description used to interpolate every layer * the caller can read, which reads well at three and is a megabytes-long tool * description at the scale layers are sold for — one per patient, one per * matter. A dozen is enough for a model to see what kind of thing a layer is; * `list_layers` is the enumeration surface, and the description says so when * there are more. */ export declare const CATALOG_SAMPLE = 12; export declare function searchDescription(layers: readonly Layer[], options?: { readonly more: boolean; }): string; export declare function catalog(layers: readonly Layer[], options?: { readonly more: boolean; }): readonly ToolDefinition[]; /** What a tool call needs to reach the rest of the system. */ export interface ToolContext { readonly auth: AuthContext; readonly requestId: string; } /** * The catalog as a dispatcher sees it: names and permissions, no listing. * * A tool's name and its permission are static; only the search *description* * depends on the caller's layers, and nothing reads a description while * dispatching. Both transports used to fetch the full per-caller catalog to * find a tool by name — a listing per call, paid for by every caller on every * call, read by nobody. */ export declare function dispatchCatalog(): readonly ToolDefinition[]; //# sourceMappingURL=tools.d.ts.map