/ tools / MCPTool / MCPTool.ts
MCPTool.ts
 1  import { z } from 'zod/v4'
 2  import { buildTool, type ToolDef } from '../../Tool.js'
 3  import { lazySchema } from '../../utils/lazySchema.js'
 4  import type { PermissionResult } from '../../utils/permissions/PermissionResult.js'
 5  import { isOutputLineTruncated } from '../../utils/terminal.js'
 6  import { DESCRIPTION, PROMPT } from './prompt.js'
 7  import {
 8    renderToolResultMessage,
 9    renderToolUseMessage,
10    renderToolUseProgressMessage,
11  } from './UI.js'
12  
13  // Allow any input object since MCP tools define their own schemas
14  export const inputSchema = lazySchema(() => z.object({}).passthrough())
15  type InputSchema = ReturnType<typeof inputSchema>
16  
17  export const outputSchema = lazySchema(() =>
18    z.string().describe('MCP tool execution result'),
19  )
20  type OutputSchema = ReturnType<typeof outputSchema>
21  
22  export type Output = z.infer<OutputSchema>
23  
24  // Re-export MCPProgress from centralized types to break import cycles
25  export type { MCPProgress } from '../../types/tools.js'
26  
27  export const MCPTool = buildTool({
28    isMcp: true,
29    // Overridden in mcpClient.ts with the real MCP tool name + args
30    isOpenWorld() {
31      return false
32    },
33    // Overridden in mcpClient.ts
34    name: 'mcp',
35    maxResultSizeChars: 100_000,
36    // Overridden in mcpClient.ts
37    async description() {
38      return DESCRIPTION
39    },
40    // Overridden in mcpClient.ts
41    async prompt() {
42      return PROMPT
43    },
44    get inputSchema(): InputSchema {
45      return inputSchema()
46    },
47    get outputSchema(): OutputSchema {
48      return outputSchema()
49    },
50    // Overridden in mcpClient.ts
51    async call() {
52      return {
53        data: '',
54      }
55    },
56    async checkPermissions(): Promise<PermissionResult> {
57      return {
58        behavior: 'passthrough',
59        message: 'MCPTool requires permission.',
60      }
61    },
62    renderToolUseMessage,
63    // Overridden in mcpClient.ts
64    userFacingName: () => 'mcp',
65    renderToolUseProgressMessage,
66    renderToolResultMessage,
67    isResultTruncated(output: Output): boolean {
68      return isOutputLineTruncated(output)
69    },
70    mapToolResultToToolResultBlockParam(content, toolUseID) {
71      return {
72        tool_use_id: toolUseID,
73        type: 'tool_result',
74        content,
75      }
76    },
77  } satisfies ToolDef<InputSchema, Output>)