UNPKG

@tanstack/ai-mcp

Version:

Host-side Model Context Protocol client for TanStack AI: discover and run MCP server tools, resources, and prompts in any adapter's chat() loop, with generated end-to-end types.

986 lines (985 loc) • 35.1 kB
import { JSONSchema } from '@tanstack/ai'; import { AnyHarness, HarnessHost, HarnessUser } from '@tanstack/ai-harness'; import { OpenAccess } from '@tanstack/ai-harness/server'; import { MCPToolContext } from './server/context.js'; import { MCPHandleOptions } from './server/index.js'; export { mcp } from './harness-plugin.js'; export type { McpServerConfig, McpServerStatus } from './harness-plugin.js'; /** Options for {@link createHarnessMcpServer}. */ export interface HarnessMcpServerOptions<U extends HarnessUser = HarnessUser> { /** * The host that runs the sessions, from `createHarnessHost`. With * `access`, `access.getUser` reads the user of each HTTP request, and the * host checks each tool call of that user. */ host: HarnessHost<U>; /** The harness to serve. */ harness: AnyHarness; /** * For a host without `access` only: who the tool calls run as. `true`: * with no user (one user). `{ user }`: as that user, for * example the one local user of a stdio server. Without host access and * without this option, the server throws at the start, so it never serves * every thread to everyone by mistake. */ openAccess?: OpenAccess<U>; /** The conversation of a tool call that names no `threadId`. Default `'main'`. */ threadId?: string; /** * What happens when a turn stops for a tool call that needs approval. * - `'ask'` (default): ask the user in the MCP client (elicitation). A * client without elicitation gets the approvals in the result. It answers * them with `approve`, `reject`, or `resolve`. * - `'auto'`: approve every tool call. * * Both modes answer tool approvals only. When the turn also waits for * another kind of interrupt, every interrupt comes back in the result. The * client answers them all with one `resolve`. */ approvals?: 'ask' | 'auto'; /** * The folders that a `path` attachment of `chat` can read from. A path must * resolve, after every symlink, to a file inside one of them. Leave it out, * and every `path` attachment is refused. * * The stdio CLI (`--mcp`) passes the working folder. An HTTP server should * pass none, because a remote client must not read files on the server. */ filePaths?: ReadonlyArray<string>; /** The MCP server name. Default: the harness name. */ name?: string; /** The MCP server version. Default `'1.0.0'`. */ version?: string; } /** What a tool call of this server gets on `ctx.context`. */ type CallContext = MCPToolContext<Record<string, unknown>>; /** * Serves a harness as an MCP server, so any MCP client (Claude Code, Claude * Desktop, Cursor, another agent) can use it. * * The tools are `chat`, `steer`, `cancel`, `approve`, `reject`, `resolve`, * `answer`, and `status`, plus `agent_<name>` for each agent in * `harness.expose.agents`, `command_<name>` for each plugin command in * `harness.expose.commands`, and `tool_<name>` for each tool in * `harness.expose.tools`. * Every tool takes an optional `threadId`. Sessions open with * `host.open(harness, { threadId, user })`, so the host checks each * call. The `status` tool and the media resource only read: they use * `host.observe`, so they open no session and mount no plugins. * * Who makes the calls: * * - A host with `access`: the user that `access.getUser` finds for each * HTTP request. `null` gets a 401. A refused action is a tool error. Each * spec 2025 session belongs to its user, and `handle` replaces the * `authInfo` of its options for that. Such a server needs HTTP: over stdio * it throws. The server lists the agents of the harness definition, and * no commands or agents of plugins, as it opens no session at the start. * - A host without `access`: the `openAccess` user, or no user * with `openAccess: true`. * * The server throws at the start for a host without `access` and without * `openAccess`, and for a host with both. * * A result lists the open waits of its work in `waits`, each with its * `kind` (see `waitKind`): `approval`, `question`, `sign-in`, * `client-tool`, or `human`. `interrupts` are the waits of a stopped turn, * and `questions` the questions of the work. `approve` and `reject` answer * the approvals of the turn only. `resolve` answers the interrupts of the * turn, or the waits of a background agent run: `approved` for an * approval, and `payload` for the others. `answer` answers a question. * * `chat` takes `attachments`: `{ path }` (only inside `filePaths`), * `{ url, mimeType? }` (the model reads the URL, the server does not fetch * it), or `{ data, mimeType }` (base64). A result lists the media that the * work made in `media`. An image or audio file up to 5 MB comes back inline. * Any other file comes back as a `resource_link` to * `harness-media://<threadId>/<id>`, which `resources/read` returns. * * The result is the server from `createMCPServer`. Mount `server.fetch` on * an HTTP route, or pass the server to `serveMCPStdio`. * * @param options - The host, the harness, who the calls run as, the default thread, the approval mode, and the folders for `path` attachments * * @example * ```ts * const server = await createHarnessMcpServer({ * host, * harness: assistant, * openAccess: { user: { id: 'local-user' } }, * }) * serveMCPStdio(server) * ``` */ export declare function createHarnessMcpServer<U extends HarnessUser = HarnessUser>(options: HarnessMcpServerOptions<U>): Promise<{ fetch: (request: Request) => Promise<Response>; handle: (request: Request, handleOptions?: MCPHandleOptions) => Promise<Response>; name: string; version: string; tools: readonly [] | readonly [import('@tanstack/ai').ServerTool<{ type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }, undefined, "chat", CallContext, false, undefined> & { inputSchema: { type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }; outputSchema: undefined; approvalSchema: undefined; }, import('@tanstack/ai').ServerTool<{ type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }, undefined, "steer", CallContext, false, undefined> & { inputSchema: { type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }; outputSchema: undefined; approvalSchema: undefined; }, import('@tanstack/ai').ServerTool<{ type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }, undefined, "cancel", CallContext, false, undefined> & { inputSchema: { type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }; outputSchema: undefined; approvalSchema: undefined; }, import('@tanstack/ai').ServerTool<{ type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }, undefined, "approve", CallContext, false, undefined> & { inputSchema: { type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }; outputSchema: undefined; approvalSchema: undefined; }, import('@tanstack/ai').ServerTool<{ type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }, undefined, "reject", CallContext, false, undefined> & { inputSchema: { type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }; outputSchema: undefined; approvalSchema: undefined; }, import('@tanstack/ai').ServerTool<{ type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }, undefined, "resolve", CallContext, false, undefined> & { inputSchema: { type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }; outputSchema: undefined; approvalSchema: undefined; }, import('@tanstack/ai').ServerTool<{ type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }, undefined, "answer", CallContext, false, undefined> & { inputSchema: { type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }; outputSchema: undefined; approvalSchema: undefined; }, import('@tanstack/ai').ServerTool<{ type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }, undefined, "status", CallContext, false, undefined> & { inputSchema: { type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }; outputSchema: undefined; approvalSchema: undefined; }, ...((import('@tanstack/ai').ServerTool<{ type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }, undefined, string, CallContext, false, undefined> & { inputSchema: { type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }; outputSchema: undefined; approvalSchema: undefined; }) | (import('@tanstack/ai').ServerTool<{ type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }, undefined, "append", CallContext, false, undefined> & { inputSchema: { type: string; properties: { threadId: JSONSchema; }; items?: JSONSchema | Array<JSONSchema>; required?: Array<string>; enum?: Array<unknown>; const?: unknown; description?: string; default?: unknown; $ref?: string; $defs?: Record<string, JSONSchema>; definitions?: Record<string, JSONSchema>; allOf?: Array<JSONSchema>; anyOf?: Array<JSONSchema>; oneOf?: Array<JSONSchema>; not?: JSONSchema; if?: JSONSchema; then?: JSONSchema; else?: JSONSchema; minimum?: number; maximum?: number; exclusiveMinimum?: number; exclusiveMaximum?: number; minLength?: number; maxLength?: number; pattern?: string; format?: string; minItems?: number; maxItems?: number; uniqueItems?: boolean; additionalProperties?: boolean | JSONSchema; additionalItems?: boolean | JSONSchema; patternProperties?: Record<string, JSONSchema>; propertyNames?: JSONSchema; minProperties?: number; maxProperties?: number; title?: string; examples?: Array<unknown>; }; outputSchema: undefined; approvalSchema: undefined; }))[]]; resources: readonly [] | readonly [{ readonly uriTemplate: "harness-media://{threadId}/{id}"; readonly name: "media"; readonly mimeType: "application/octet-stream"; readonly argsSchema: { readonly parse: typeof mediaAddress; }; } & { read: (uri: URL, variables: import('@modelcontextprotocol/server').Variables, ctx: import('./server/definitions.js').MCPResourceContext) => { blob: string; mimeType: string; } | Promise<{ blob: string; mimeType: string; }>; }]; prompts: [] | readonly []; }>; /** * The thread and media id of a `harness-media://<threadId>/<id>` URI, from * the template variables. `mediaUri` encodes both, so they are decoded here. */ declare function mediaAddress(variables: unknown): { threadId: string; id: string; };