import { Box, Text } from 'ink' import * as React from 'react' import { z } from 'zod' import { FallbackToolUseRejectedMessage } from '../../components/FallbackToolUseRejectedMessage' import { type Tool } from '../../Tool' import { getTheme } from '../../utils/theme' import { DESCRIPTION, PROMPT } from './prompt' import { OutputLine } from '../BashTool/OutputLine' // Allow any input object since MCP tools define their own schemas const inputSchema = z.object({}).passthrough() export const MCPTool = { async isEnabled() { return true }, isReadOnly() { return false }, isConcurrencySafe() { return false // MCPTool can modify state through MCP calls, not safe for concurrent execution }, // Overridden in mcpClient.ts name: 'mcp', // Overridden in mcpClient.ts async description() { return DESCRIPTION }, // Overridden in mcpClient.ts async prompt() { return PROMPT }, inputSchema, // Overridden in mcpClient.ts async *call() { yield { type: 'result', data: '', resultForAssistant: '', } }, needsPermissions() { return true }, renderToolUseMessage(input) { return Object.entries(input) .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) .join(', ') }, // Overridden in mcpClient.ts userFacingName: () => 'mcp', renderToolUseRejectedMessage() { return }, renderToolResultMessage(output) { const verbose = false // Set default value for verbose if (Array.isArray(output)) { return ( {output.map((item, i) => { if (item.type === 'image') { return (   ⎿   [Image] ) } const lines = item.text.split('\n').length return ( ) })} ) } if (!output) { return (   ⎿   (No content) ) } const lines = output.split('\n').length return }, renderResultForAssistant(content) { return content }, } satisfies Tool