import type { ConvexHttpClient } from 'convex/browser'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; import type { z, ZodRawShape } from 'zod'; /** * A tool, described once. * * The previous shape kept three things apart that always change together: a * hand-written JSON Schema literal, a `handleX` function that re-declared the * same argument types with `as` casts, and a `case 'x':` in a switch that * wired them up. Nothing checked that the three agreed — and they did not: * `args.year as number` happily accepted the string `"2020"` and failed later, * inside Convex, with an error the agent could not act on. * * Here the Zod shape IS the schema (the SDK converts it to JSON Schema for the * client), IS the runtime validation (the SDK rejects bad arguments before the * handler runs), and IS the argument type (`z.infer`). One source, three uses. */ export type ToolDef = { name: string; /** Human-facing label shown by clients that display one. */ title: string; description: string; inputSchema: S; /** * Behaviour hints for the client. `readOnlyHint` lets an agent know a call * is safe to retry or run speculatively; `destructiveHint` is what makes a * client ask before running `ingest_delete`. Absent before — every tool * looked equally dangerous, which means none did. */ annotations?: { readOnlyHint?: boolean; destructiveHint?: boolean; idempotentHint?: boolean; openWorldHint?: boolean; }; run: (client: ConvexHttpClient, args: z.infer>) => Promise; /** * Optional override for turning the result into MCP content. Only * `get_figure` needs it, to return the image as an `ImageContent` block * rather than as JSON. */ toContent?: (result: unknown) => CallToolResult; }; /** Identity helper that keeps the generic bound to the literal shape. */ export declare function defineTool(def: ToolDef): ToolDef;