@@ -18,10 +18,19 @@ import {
18
18
MessageContentImageUrl ,
19
19
MessageContentText ,
20
20
} from "@langchain/core/messages" ;
21
- import { JSONSchema , JSONSchemaToZod } from "@dmitryrechkin/json-schema-to-zod" ;
22
-
21
+ import type { JSONSchema } from "@dmitryrechkin/json-schema-to-zod" ;
22
+ import type { ZodSchema } from "zod" ;
23
23
import debug from "debug" ;
24
24
25
+ let JSONSchemaToZod : { convert : ( schema : JSONSchema ) => ZodSchema } | undefined ;
26
+
27
+ async function convertSchema ( schema : JSONSchema ) : Promise < ZodSchema > {
28
+ if ( ! JSONSchemaToZod ) {
29
+ ( { JSONSchemaToZod } = await import ( "@dmitryrechkin/json-schema-to-zod" ) ) ;
30
+ }
31
+ return JSONSchemaToZod . convert ( schema ) ;
32
+ }
33
+
25
34
// Replace direct initialization with lazy initialization
26
35
let debugLog : debug . Debugger ;
27
36
function getDebugLog ( ) {
@@ -208,36 +217,39 @@ export async function loadMcpTools(
208
217
getDebugLog ( ) ( `INFO: Found ${ toolsResponse . tools ?. length || 0 } MCP tools` ) ;
209
218
210
219
// Filter out tools without names and convert in a single map operation
211
- return ( toolsResponse . tools || [ ] )
212
- . filter ( ( tool : MCPTool ) => ! ! tool . name )
213
- . map ( ( tool : MCPTool ) => {
214
- try {
215
- const dst = new DynamicStructuredTool ( {
216
- name : tool . name ,
217
- description : tool . description || "" ,
218
- schema : JSONSchemaToZod . convert (
219
- ( tool . inputSchema ?? {
220
- type : "object" ,
221
- properties : { } ,
222
- } ) as JSONSchema
223
- ) ,
224
- responseFormat : "content_and_artifact" ,
225
- func : _callTool . bind (
226
- null ,
227
- serverName ,
228
- tool . name ,
229
- client
230
- ) as DynamicStructuredToolInput [ "func" ] ,
231
- } ) ;
232
- getDebugLog ( ) ( `INFO: Successfully loaded tool: ${ dst . name } ` ) ;
233
- return dst ;
234
- } catch ( error ) {
235
- getDebugLog ( ) ( `ERROR: Failed to load tool "${ tool . name } ":` , error ) ;
236
- if ( throwOnLoadError ) {
237
- throw error ;
238
- }
239
- return null ;
240
- }
241
- } )
242
- . filter ( Boolean ) as StructuredToolInterface [ ] ;
220
+ return (
221
+ await Promise . all (
222
+ ( toolsResponse . tools || [ ] )
223
+ . filter ( ( tool : MCPTool ) => ! ! tool . name )
224
+ . map ( async ( tool : MCPTool ) => {
225
+ try {
226
+ const dst = new DynamicStructuredTool ( {
227
+ name : tool . name ,
228
+ description : tool . description || "" ,
229
+ schema : await convertSchema (
230
+ ( tool . inputSchema ?? {
231
+ type : "object" ,
232
+ properties : { } ,
233
+ } ) as JSONSchema
234
+ ) ,
235
+ responseFormat : "content_and_artifact" ,
236
+ func : _callTool . bind (
237
+ null ,
238
+ serverName ,
239
+ tool . name ,
240
+ client
241
+ ) as DynamicStructuredToolInput [ "func" ] ,
242
+ } ) ;
243
+ getDebugLog ( ) ( `INFO: Successfully loaded tool: ${ dst . name } ` ) ;
244
+ return dst ;
245
+ } catch ( error ) {
246
+ getDebugLog ( ) ( `ERROR: Failed to load tool "${ tool . name } ":` , error ) ;
247
+ if ( throwOnLoadError ) {
248
+ throw error ;
249
+ }
250
+ return null ;
251
+ }
252
+ } )
253
+ )
254
+ ) . filter ( Boolean ) as StructuredToolInterface [ ] ;
243
255
}
0 commit comments