import { type FuncType, type Type } from '@frontmcp/di'; import { type ZodType } from '@frontmcp/lazy-zod'; import { type ElicitOptions, type ElicitResult } from '../../elicitation'; import type { AIPlatformType, ClientInfo, McpLoggingLevel } from '../../notification'; import { type ToolInputOf, type ToolOutputOf } from '../decorators'; import { type ToolInputType, type ToolMetadata, type ToolOutputType } from '../metadata'; import { ExecutionContextBase, type ExecutionContextBaseArgs } from './execution-context.interface'; export type ToolType = Type | FuncType | string; type HistoryEntry = { at: number; stage?: string; value: T | undefined; note?: string; }; export type ToolCtorArgs = ExecutionContextBaseArgs & { metadata: ToolMetadata; input: In; /** Progress token from the request's _meta, used for progress notifications */ progressToken?: string | number; /** * AbortSignal that fires when the enclosing request is cancelled. * Populated for task-augmented `tools/call` invocations so long-running work * can observe `tasks/cancel` promptly (MCP 2025-11-25 tasks spec). * Non-task invocations leave this unset. */ signal?: AbortSignal; }; export declare abstract class ToolContext, Out = ToolOutputOf<{ outputSchema: OutSchema; }>> extends ExecutionContextBase { protected readonly toolId: string; protected readonly toolName: string; readonly metadata: ToolMetadata; private _rawInput?; private _input?; private _outputDraft?; private _output?; private readonly _inputHistory; private readonly _outputHistory; private readonly _progressToken?; /** * AbortSignal exposed to tool authors. Fires when a task-augmented call is * cancelled via `tasks/cancel` (MCP 2025-11-25). Undefined for non-task calls. */ readonly signal?: AbortSignal; constructor(args: ToolCtorArgs); abstract execute(input: In): Promise; get input(): In; set input(v: In | undefined); get inputHistory(): ReadonlyArray>; get output(): Out | undefined; set output(v: Out | undefined); get outputHistory(): ReadonlyArray>; respond(value: Out): never; /** * Send a notification message to the current session. * Uses 'notifications/message' per MCP 2025-11-25 spec. * * @param message - The notification message (string) or structured data (object) * @param level - Log level: 'debug', 'info', 'warning', or 'error' (default: 'info') * @returns true if the notification was sent, false if session unavailable * * @example * ```typescript * async execute(input: Input): Promise { * await this.notify('Starting processing...', 'info'); * await this.notify({ step: 1, total: 5, status: 'in_progress' }); * // ... processing * await this.notify('Processing complete', 'info'); * return result; * } * ``` */ protected notify(message: string | Record, level?: McpLoggingLevel): Promise; /** * Send a progress notification to the current session. * Uses 'notifications/progress' per MCP 2025-11-25 spec. * * Only works if the client requested progress updates by including a * progressToken in the request's _meta field. If no progressToken was * provided, this method logs a debug message and returns false. * * @param progress - Current progress value (should increase monotonically) * @param total - Total progress value (optional) * @param message - Progress message (optional) * @returns true if the notification was sent, false if no progressToken or session * * @example * ```typescript * async execute(input: Input): Promise { * const items = input.items; * for (let i = 0; i < items.length; i++) { * await this.progress(i + 1, items.length, `Processing item ${i + 1}`); * await processItem(items[i]); * } * return { processed: items.length }; * } * ``` */ protected progress(progress: number, total?: number, message?: string): Promise; /** * Notify subscribed clients that a resource's contents changed. * * Sends `notifications/resources/updated` to every session subscribed to `uri` * (via `resources/subscribe`); a no-op for sessions that aren't subscribed. Call * this when a tool mutates state that backs a `@Resource` so subscribers re-fetch. * * @param uri - The URI of the resource whose contents changed. * * @example * ```typescript * async execute(input: Input): Promise { * await this.saveNote(input); * this.notifyResourceUpdated(`notes://${input.id}`); * return { ok: true }; * } * ``` */ protected notifyResourceUpdated(uri: string): void; /** * Notify all connected clients that the set of available resources changed. * * Broadcasts `notifications/resources/list_changed` so clients re-run * `resources/list`. Call this when a tool adds or removes resources at runtime. */ protected notifyResourceListChanged(): void; /** * Request interactive input from the user during tool execution. * * Sends an elicitation request to the client for user input. The client * presents the message and a form (or URL) to collect user response. * * Only one elicit per session is allowed. A new elicit will cancel any pending one. * On timeout, an ElicitationTimeoutError is thrown to kill tool execution. * * For clients that don't support elicitation, the framework automatically handles * the fallback flow using the sendElicitationResult tool. * * @param message - Prompt message to display to user * @param requestedSchema - Zod schema defining expected input structure * @param options - Mode ('form'|'url'), ttl (default 5min), elicitationId (for URL mode) * @returns ElicitResult with status and typed content * @throws ElicitationNotSupportedError if client doesn't support elicitation and no fallback available * @throws ElicitationFallbackRequired (internal) triggers fallback flow for non-supporting clients * @throws ElicitationTimeoutError if request times out (kills execution) * * @example * ```typescript * async execute(input: Input): Promise { * const result = await this.elicit('Confirm action?', z.object({ * confirmed: z.boolean(), * reason: z.string().optional() * })); * * if (result.status !== 'accept') { * return { cancelled: true }; * } * // result.content is typed { confirmed: boolean, reason?: string } * return { confirmed: result.content!.confirmed }; * } * ``` */ protected elicit(message: string, requestedSchema: S, options?: ElicitOptions): Promise ? O : unknown>>; /** * Get the detected AI platform type for the current session. * This is auto-detected from the client info during MCP initialization. * * Use this to customize tool responses (e.g., UI format) based on the calling platform. * * @returns The detected platform type, or 'unknown' if not detected * @example * ```typescript * async execute(input: Input): Promise { * const platform = this.platform; * if (platform === 'openai') { * // Return OpenAI-specific response format * } * // ... * } * ``` */ get platform(): AIPlatformType; /** * Get the client info (name and version) for the current session. * This is captured from the MCP initialize request. * * @returns The client info, or undefined if not available * @example * ```typescript * async execute(input: Input): Promise { * const client = this.clientInfo; * console.log(`Called by: ${client?.name} v${client?.version}`); * // ... * } * ``` */ get clientInfo(): ClientInfo | undefined; } export {}; //# sourceMappingURL=tool.interface.d.ts.map