import { z } from 'zod/v4' import { buildTool, type ToolDef } from '../../Tool.js' import { lazySchema } from '../../utils/lazySchema.js' import type { PermissionResult } from '../../utils/permissions/PermissionResult.js' import { isOutputLineTruncated } from '../../utils/terminal.js' import { DESCRIPTION, PROMPT } from './prompt.js' import { renderToolResultMessage, renderToolUseMessage, renderToolUseProgressMessage, } from './UI.js' // Allow any input object since MCP tools define their own schemas export const inputSchema = lazySchema(() => z.object({}).passthrough()) type InputSchema = ReturnType export const outputSchema = lazySchema(() => z.string().describe('MCP tool execution result'), ) type OutputSchema = ReturnType export type Output = z.infer // Re-export MCPProgress from centralized types to break import cycles export type { MCPProgress } from '../../types/tools.js' export const MCPTool = buildTool({ isMcp: true, // Overridden in mcpClient.ts with the real MCP tool name + args isOpenWorld() { return false }, // Overridden in mcpClient.ts name: 'mcp', maxResultSizeChars: 100_000, // Overridden in mcpClient.ts async description() { return DESCRIPTION }, // Overridden in mcpClient.ts async prompt() { return PROMPT }, get inputSchema(): InputSchema { return inputSchema() }, get outputSchema(): OutputSchema { return outputSchema() }, // Overridden in mcpClient.ts async call() { return { data: '', } }, async checkPermissions(): Promise { return { behavior: 'passthrough', message: 'MCPTool requires permission.', } }, renderToolUseMessage, // Overridden in mcpClient.ts userFacingName: () => 'mcp', renderToolUseProgressMessage, renderToolResultMessage, isResultTruncated(output: Output): boolean { return isOutputLineTruncated(output) }, mapToolResultToToolResultBlockParam(content, toolUseID) { return { tool_use_id: toolUseID, type: 'tool_result', content, } }, } satisfies ToolDef)