UNPKG

@langchain/mcp-adapters

Version:
1 lines 39.5 kB
{"version":3,"file":"tools.cjs","names":["getDebugLog","schema: JsonSchemaObject","obj: JsonSchemaObject","visitedRefs: Set<string>","result: JsonSchemaObject","message: string","cause?: Error","ZodErrorV4","ZodErrorV3","z","error: unknown","resource:\n | EmbeddedResource[\"resource\"]\n | ReadResourceResult[\"contents\"][number]","client: MCPInstance","response: ReadResourceResult","content: MCPContentBlock","useStandardContentBlocks: boolean | undefined","toolName: string","serverName: string","blocks: ContentBlock.Data.StandardFileBlock[]","resource: EmbeddedResource","content: ReadResourceResult[\"contents\"][number]","contentType: CallToolResultContentType","outputHandling?: OutputHandling","_resolveDetailedOutputHandling","convertedContent: (ContentBlock | ContentBlock.Multimodal.Standard)[]","content: EmbeddedResource","enhancedArtifacts: ExtendedArtifact[]","requestOptions: RequestOptions","state: State","callToolArgs: Parameters<typeof finalClient.callTool>","normalizedContent:\n | string\n | (ContentBlock | ContentBlock.Data.DataContentBlock)[]","normalizedArtifacts: (\n | EmbeddedResource\n | ContentBlock.Multimodal.Standard\n )[]","ToolMessage","Command","defaultLoadMcpToolsOptions: LoadMcpToolsOptions","options?: LoadMcpToolsOptions","mcpTools: MCPTool[]","toolsResponse: ListToolsResult | undefined","tool: MCPTool","DynamicStructuredTool","args: Record<string, unknown>","_runManager?: CallbackManagerForToolRun","config?: RunnableConfig"],"sources":["../src/tools.ts"],"sourcesContent":["import { z, ZodError as ZodErrorV4 } from \"zod/v4\";\nimport { ZodError as ZodErrorV3 } from \"zod/v3\";\nimport {\n type CallToolResult,\n type ContentBlock as MCPContentBlock,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Client as MCPClient } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type {\n EmbeddedResource,\n ReadResourceResult,\n Tool as MCPTool,\n ListToolsResult,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport { DynamicStructuredTool } from \"@langchain/core/tools\";\nimport type { ContentBlock } from \"@langchain/core/messages\";\nimport { RunnableConfig } from \"@langchain/core/runnables\";\nimport type { CallbackManagerForToolRun } from \"@langchain/core/callbacks/manager\";\nimport { ToolMessage } from \"@langchain/core/messages\";\nimport { Command, getCurrentTaskInput } from \"@langchain/langgraph\";\n\nimport type { Notifications } from \"./types.js\";\n\nimport {\n _resolveDetailedOutputHandling,\n type CallToolResultContentType,\n type LoadMcpToolsOptions,\n type OutputHandling,\n} from \"./types.js\";\nimport type { ToolHooks, State } from \"./hooks.js\";\nimport type { Client } from \"./connection.js\";\nimport { getDebugLog } from \"./logging.js\";\n\nconst debugLog = getDebugLog(\"tools\");\n\n/**\n * JSON Schema type definitions for dereferencing $defs.\n */\ntype JsonSchemaObject = {\n type?: string;\n properties?: Record<string, JsonSchemaObject>;\n items?: JsonSchemaObject | JsonSchemaObject[];\n additionalProperties?: boolean | JsonSchemaObject;\n $ref?: string;\n $defs?: Record<string, JsonSchemaObject>;\n definitions?: Record<string, JsonSchemaObject>;\n allOf?: JsonSchemaObject[];\n anyOf?: JsonSchemaObject[];\n oneOf?: JsonSchemaObject[];\n not?: JsonSchemaObject;\n if?: JsonSchemaObject;\n then?: JsonSchemaObject;\n else?: JsonSchemaObject;\n required?: string[];\n description?: string;\n default?: unknown;\n enum?: unknown[];\n const?: unknown;\n [key: string]: unknown;\n};\n\n/**\n * Dereferences $ref pointers in a JSON Schema by inlining the definitions from $defs.\n * This is necessary because some JSON Schema validators (like @cfworker/json-schema)\n * don't automatically resolve $ref references to $defs.\n *\n * @param schema - The JSON Schema to dereference\n * @returns A new schema with all $ref pointers resolved\n */\nfunction dereferenceJsonSchema(schema: JsonSchemaObject): JsonSchemaObject {\n const definitions = schema.$defs ?? schema.definitions ?? {};\n\n /**\n * Recursively resolve $ref pointers in the schema.\n * Tracks visited refs to prevent infinite recursion with circular references.\n */\n function resolveRefs(\n obj: JsonSchemaObject,\n visitedRefs: Set<string> = new Set()\n ): JsonSchemaObject {\n if (typeof obj !== \"object\" || obj === null) {\n return obj;\n }\n\n // Handle $ref\n if (obj.$ref && typeof obj.$ref === \"string\") {\n const refPath = obj.$ref;\n\n // Only handle local references to $defs or definitions\n const defsMatch = refPath.match(/^#\\/\\$defs\\/(.+)$/);\n const definitionsMatch = refPath.match(/^#\\/definitions\\/(.+)$/);\n const match = defsMatch || definitionsMatch;\n\n if (match) {\n const defName = match[1];\n const definition = definitions[defName];\n\n if (definition) {\n // Check for circular reference\n if (visitedRefs.has(refPath)) {\n // Return a placeholder for circular refs to avoid infinite loop\n debugLog(\n `WARNING: Circular reference detected for ${refPath}, using empty object`\n );\n return { type: \"object\" };\n }\n\n // Track this ref as visited\n const newVisitedRefs = new Set(visitedRefs);\n newVisitedRefs.add(refPath);\n\n // Merge the resolved definition with any other properties from the original object\n // (excluding $ref itself)\n const { $ref: _, ...restOfObj } = obj;\n const resolvedDef = resolveRefs(definition, newVisitedRefs);\n return { ...resolvedDef, ...restOfObj };\n } else {\n debugLog(`WARNING: Could not resolve $ref: ${refPath}`);\n }\n }\n // For non-local refs, return as-is\n return obj;\n }\n\n // Recursively process all properties\n const result: JsonSchemaObject = {};\n\n for (const [key, value] of Object.entries(obj)) {\n // Skip $defs and definitions as they're no longer needed after dereferencing\n if (key === \"$defs\" || key === \"definitions\") {\n continue;\n }\n\n if (Array.isArray(value)) {\n result[key] = value.map((item) =>\n typeof item === \"object\" && item !== null\n ? resolveRefs(item as JsonSchemaObject, visitedRefs)\n : item\n );\n } else if (typeof value === \"object\" && value !== null) {\n result[key] = resolveRefs(value as JsonSchemaObject, visitedRefs);\n } else {\n result[key] = value;\n }\n }\n\n return result;\n }\n\n return resolveRefs(schema);\n}\n\n/**\n * MCP instance is either a Client or a MCPClient.\n *\n * `MCPClient`: is the base instance from the `@modelcontextprotocol/sdk` package.\n * `Client`: is an extension of the `MCPClient` that adds the `fork` method to easier create a new client with different headers.\n *\n * This distinction is necessary to keep the interface of the `getTools` method simple.\n */\ntype MCPInstance = Client | MCPClient;\n\n/**\n * Custom error class for tool exceptions\n */\nexport class ToolException extends Error {\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"ToolException\";\n\n /**\n * don't display the large ZodError stack trace\n */\n if (\n cause &&\n // eslint-disable-next-line no-instanceof/no-instanceof\n (cause instanceof ZodErrorV4 || cause instanceof ZodErrorV3)\n ) {\n const minifiedZodError = new Error(z.prettifyError(cause));\n const stackByLine = cause.stack?.split(\"\\n\") || [];\n minifiedZodError.stack = cause.stack\n ?.split(\"\\n\")\n .slice(stackByLine.findIndex((l) => l.includes(\" at\")))\n .join(\"\\n\");\n this.cause = minifiedZodError;\n } else if (cause) {\n this.cause = cause;\n }\n }\n}\n\nexport function isToolException(error: unknown): error is ToolException {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"name\" in error &&\n error.name === \"ToolException\"\n );\n}\n\nfunction isResourceReference(\n resource:\n | EmbeddedResource[\"resource\"]\n | ReadResourceResult[\"contents\"][number]\n): boolean {\n return (\n typeof resource === \"object\" &&\n resource !== null &&\n \"uri\" in resource &&\n typeof (resource as { uri?: unknown }).uri === \"string\" &&\n (!(\"blob\" in resource) || resource.blob == null) &&\n (!(\"text\" in resource) || resource.text == null)\n );\n}\n\nasync function* _embeddedResourceToStandardFileBlocks(\n resource:\n | EmbeddedResource[\"resource\"]\n | ReadResourceResult[\"contents\"][number],\n client: MCPInstance\n): AsyncGenerator<\n | (ContentBlock.Data.StandardFileBlock & ContentBlock.Data.Base64ContentBlock)\n | (ContentBlock.Data.StandardFileBlock &\n ContentBlock.Data.PlainTextContentBlock)\n> {\n if (isResourceReference(resource)) {\n const response: ReadResourceResult = await client.readResource({\n uri: resource.uri,\n });\n for (const content of response.contents) {\n yield* _embeddedResourceToStandardFileBlocks(content, client);\n }\n return;\n }\n\n if (\"blob\" in resource && resource.blob != null) {\n yield {\n type: \"file\",\n source_type: \"base64\",\n data: resource.blob,\n mime_type: resource.mimeType,\n ...(resource.uri != null ? { metadata: { uri: resource.uri } } : {}),\n } as ContentBlock.Data.StandardFileBlock &\n ContentBlock.Data.Base64ContentBlock;\n }\n if (\"text\" in resource && resource.text != null) {\n yield {\n type: \"file\",\n source_type: \"text\",\n mime_type: resource.mimeType,\n text: resource.text,\n ...(resource.uri != null ? { metadata: { uri: resource.uri } } : {}),\n } as ContentBlock.Data.StandardFileBlock &\n ContentBlock.Data.PlainTextContentBlock;\n }\n}\n\nasync function _toolOutputToContentBlocks(\n content: MCPContentBlock,\n useStandardContentBlocks: true,\n client: MCPInstance,\n toolName: string,\n serverName: string\n): Promise<ContentBlock.Multimodal.Standard[]>;\nasync function _toolOutputToContentBlocks(\n content: MCPContentBlock,\n useStandardContentBlocks: false | undefined,\n client: MCPInstance,\n toolName: string,\n serverName: string\n): Promise<ContentBlock[]>;\nasync function _toolOutputToContentBlocks(\n content: MCPContentBlock,\n useStandardContentBlocks: boolean | undefined,\n client: MCPInstance,\n toolName: string,\n serverName: string\n): Promise<(ContentBlock | ContentBlock.Multimodal.Standard)[]>;\nasync function _toolOutputToContentBlocks(\n content: MCPContentBlock,\n useStandardContentBlocks: boolean | undefined,\n client: MCPInstance,\n toolName: string,\n serverName: string\n): Promise<(ContentBlock | ContentBlock.Multimodal.Standard)[]> {\n const blocks: ContentBlock.Data.StandardFileBlock[] = [];\n switch (content.type) {\n case \"text\":\n return [\n {\n type: \"text\",\n ...(useStandardContentBlocks\n ? {\n source_type: \"text\",\n }\n : {}),\n text: content.text,\n } as ContentBlock.Text,\n ];\n case \"image\":\n if (useStandardContentBlocks) {\n return [\n {\n type: \"image\",\n source_type: \"base64\",\n data: content.data,\n mime_type: content.mimeType,\n } as ContentBlock.Data.StandardImageBlock,\n ];\n }\n return [\n {\n type: \"image_url\",\n image_url: {\n url: `data:${content.mimeType};base64,${content.data}`,\n },\n } as ContentBlock,\n ];\n case \"audio\":\n // We don't check `useStandardContentBlocks` here because we only support audio via\n // standard content blocks\n return [\n {\n type: \"audio\",\n source_type: \"base64\",\n data: content.data,\n mime_type: content.mimeType,\n } as ContentBlock.Data.StandardAudioBlock,\n ];\n case \"resource\":\n for await (const block of _embeddedResourceToStandardFileBlocks(\n content.resource,\n client\n )) {\n blocks.push(block);\n }\n return blocks;\n default:\n throw new ToolException(\n `MCP tool '${toolName}' on server '${serverName}' returned a content block with unexpected type \"${\n (content as { type: string }).type\n }.\" Expected one of \"text\", \"image\", or \"audio\".`\n );\n }\n}\n\nasync function _embeddedResourceToArtifact(\n resource: EmbeddedResource,\n useStandardContentBlocks: boolean | undefined,\n client: MCPInstance,\n toolName: string,\n serverName: string\n): Promise<(EmbeddedResource | ContentBlock.Multimodal.Standard)[]> {\n if (useStandardContentBlocks) {\n return _toolOutputToContentBlocks(\n resource,\n useStandardContentBlocks,\n client,\n toolName,\n serverName\n );\n }\n\n if (\n (!(\"blob\" in resource) || resource.blob == null) &&\n (!(\"text\" in resource) || resource.text == null) &&\n \"uri\" in resource &&\n typeof resource.uri === \"string\"\n ) {\n const response: ReadResourceResult = await client.readResource({\n uri: resource.uri,\n });\n\n return response.contents.map(\n (content: ReadResourceResult[\"contents\"][number]) => ({\n type: \"resource\",\n resource: {\n ...content,\n },\n })\n );\n }\n return [resource];\n}\n\n/**\n * Special artifact type for structured content from MCP tool results\n * @internal\n */\ntype MCPStructuredContentArtifact = {\n type: \"mcp_structured_content\";\n data: NonNullable<CallToolResult[\"structuredContent\"]>;\n};\n\n/**\n * Special artifact type for meta information from MCP tool results\n * @internal\n */\ntype MCPMetaArtifact = {\n type: \"mcp_meta\";\n data: NonNullable<CallToolResult[\"_meta\"]>;\n};\n\n/**\n * Extended artifact type that includes MCP-specific artifacts\n * @internal\n */\ntype ExtendedArtifact =\n | EmbeddedResource\n | ContentBlock.Multimodal.Standard\n | MCPStructuredContentArtifact\n | MCPMetaArtifact;\n\n/**\n * Content type that may include structuredContent and meta\n * @internal\n */\ntype ExtendedContent =\n | (ContentBlock | ContentBlock.Multimodal.Standard)[]\n | (ContentBlock.Text & {\n structuredContent?: NonNullable<CallToolResult[\"structuredContent\"]>;\n meta?: NonNullable<CallToolResult[\"_meta\"]>;\n })\n | string;\n\n/**\n * @internal\n */\ntype ConvertCallToolResultArgs = {\n /**\n * The name of the server to call the tool on (used for error messages and logging)\n */\n serverName: string;\n /**\n * The name of the tool that was called\n */\n toolName: string;\n /**\n * The result from the MCP tool call\n */\n result: CallToolResult;\n /**\n * The MCP client that was used to call the tool\n */\n client: Client | MCPClient;\n /**\n * If true, the tool will use LangChain's standard multimodal content blocks for tools that output\n * image or audio content. This option has no effect on handling of embedded resource tool output.\n */\n useStandardContentBlocks?: boolean;\n /**\n * Defines where to place each tool output type in the LangChain ToolMessage.\n */\n outputHandling?: OutputHandling;\n};\n\nfunction _getOutputTypeForContentType(\n contentType: CallToolResultContentType,\n outputHandling?: OutputHandling\n): \"content\" | \"artifact\" {\n if (outputHandling === \"content\" || outputHandling === \"artifact\") {\n return outputHandling;\n }\n\n const resolved = _resolveDetailedOutputHandling(outputHandling);\n\n return (\n resolved[contentType] ??\n (contentType === \"resource\" ? \"artifact\" : \"content\")\n );\n}\n\n/**\n * Process the result from calling an MCP tool.\n * Extracts text content and non-text content for better agent compatibility.\n *\n * @internal\n *\n * @param args - The arguments to pass to the tool\n * @returns A tuple of [textContent, nonTextContent]\n */\nasync function _convertCallToolResult({\n serverName,\n toolName,\n result,\n client,\n useStandardContentBlocks,\n outputHandling,\n}: ConvertCallToolResultArgs): Promise<[ExtendedContent, ExtendedArtifact[]]> {\n if (!result) {\n throw new ToolException(\n `MCP tool '${toolName}' on server '${serverName}' returned an invalid result - tool call response was undefined`\n );\n }\n\n if (!Array.isArray(result.content)) {\n throw new ToolException(\n `MCP tool '${toolName}' on server '${serverName}' returned an invalid result - expected an array of content, but was ${typeof result.content}`\n );\n }\n\n if (result.isError) {\n throw new ToolException(\n `MCP tool '${toolName}' on server '${serverName}' returned an error: ${result.content\n .map((content: MCPContentBlock) =>\n content.type === \"text\" ? content.text : \"\"\n )\n .join(\"\\n\")}`\n );\n }\n\n const convertedContent: (ContentBlock | ContentBlock.Multimodal.Standard)[] =\n (\n await Promise.all(\n result.content\n .filter(\n (content: MCPContentBlock) =>\n _getOutputTypeForContentType(content.type, outputHandling) ===\n \"content\"\n )\n .map((content: MCPContentBlock) =>\n _toolOutputToContentBlocks(\n content,\n useStandardContentBlocks,\n client,\n toolName,\n serverName\n )\n )\n )\n ).flat();\n\n // Create the text content output\n const artifacts = (\n await Promise.all(\n (\n result.content.filter(\n (content: MCPContentBlock) =>\n _getOutputTypeForContentType(content.type, outputHandling) ===\n \"artifact\"\n ) as EmbeddedResource[]\n ).map((content: EmbeddedResource) => {\n return _embeddedResourceToArtifact(\n content,\n useStandardContentBlocks,\n client,\n toolName,\n serverName\n );\n })\n )\n ).flat();\n\n // Extract structuredContent and _meta from result\n // These are optional fields that are part of the CallToolResult type\n const structuredContent = result.structuredContent;\n const meta = result._meta;\n\n // Add structuredContent and meta as special artifacts\n const enhancedArtifacts: ExtendedArtifact[] = [...artifacts];\n if (structuredContent) {\n enhancedArtifacts.push({\n type: \"mcp_structured_content\",\n data: structuredContent,\n });\n }\n if (meta) {\n enhancedArtifacts.push({\n type: \"mcp_meta\",\n data: meta,\n });\n }\n\n // If we have structuredContent or meta, create an enhanced content that includes all info\n if (convertedContent.length === 1 && convertedContent[0].type === \"text\") {\n const textBlock = convertedContent[0] as ContentBlock.Text;\n const textContent = textBlock.text;\n\n // If we have structuredContent or meta, wrap the content with additional info\n if (structuredContent || meta) {\n return [\n {\n ...textBlock,\n ...(structuredContent ? { structuredContent } : {}),\n ...(meta ? { meta } : {}),\n } as ExtendedContent,\n enhancedArtifacts,\n ];\n }\n\n return [textContent as ExtendedContent, enhancedArtifacts];\n }\n\n return [convertedContent as ExtendedContent, enhancedArtifacts];\n}\n\n/**\n * @internal\n */\ntype CallToolArgs = {\n /**\n * The name of the server to call the tool on (used for error messages and logging)\n */\n serverName: string;\n /**\n * The name of the tool to call\n */\n toolName: string;\n /**\n * The MCP client to call the tool on\n */\n client: Client | MCPClient;\n /**\n * The arguments to pass to the tool - must conform to the tool's input schema\n */\n args: Record<string, unknown>;\n /**\n * Optional RunnableConfig with timeout settings\n */\n config?: RunnableConfig;\n /**\n * If true, the tool will use LangChain's standard multimodal content blocks for tools that output\n * image or audio content. This option has no effect on handling of embedded resource tool output.\n */\n useStandardContentBlocks?: boolean;\n /**\n * Defines where to place each tool output type in the LangChain ToolMessage.\n */\n outputHandling?: OutputHandling;\n\n /**\n * `onProgress` callbacks used for tool calls.\n */\n onProgress?: Notifications[\"onProgress\"];\n\n /**\n * `beforeToolCall` callbacks used for tool calls.\n */\n beforeToolCall?: ToolHooks[\"beforeToolCall\"];\n\n /**\n * `afterToolCall` callbacks used for tool calls.\n */\n afterToolCall?: ToolHooks[\"afterToolCall\"];\n};\n\ntype ContentBlocksWithArtifacts =\n | [ExtendedContent, ExtendedArtifact[]]\n | Command;\n\n/**\n * Call an MCP tool.\n *\n * Use this with `.bind` to capture the fist three arguments, then pass to the constructor of DynamicStructuredTool.\n *\n * @internal\n * @param args - The arguments to pass to the tool\n * @returns A tuple of [textContent, nonTextContent]\n */\nasync function _callTool({\n serverName,\n toolName,\n client,\n args,\n config,\n useStandardContentBlocks,\n outputHandling,\n onProgress,\n beforeToolCall,\n afterToolCall,\n}: CallToolArgs): Promise<ContentBlocksWithArtifacts> {\n try {\n debugLog(`INFO: Calling tool ${toolName}(${JSON.stringify(args)})`);\n\n // Extract timeout from RunnableConfig and pass to MCP SDK\n // Note: ensureConfig() converts timeout into an AbortSignal and deletes the timeout field.\n // To preserve the numeric timeout for SDKs that accept an explicit timeout value, we read\n // it from metadata.timeoutMs if present, falling back to any direct timeout.\n const numericTimeout =\n (config?.metadata?.timeoutMs as number | undefined) ?? config?.timeout;\n const requestOptions: RequestOptions = {\n ...(numericTimeout ? { timeout: numericTimeout } : {}),\n ...(config?.signal ? { signal: config.signal } : {}),\n ...(onProgress\n ? {\n onprogress: (progress) => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n onProgress?.(progress, {\n type: \"tool\",\n name: toolName,\n args,\n server: serverName,\n });\n },\n }\n : {}),\n };\n\n let state: State = {};\n try {\n state = getCurrentTaskInput(config) as State;\n } catch (error) {\n debugLog(\n `State can't be derrived as LangGraph is not used: ${String(error)}`\n );\n }\n\n const beforeToolCallInterception = await beforeToolCall?.(\n {\n name: toolName,\n args,\n serverName,\n },\n state,\n config ?? {}\n );\n\n const finalArgs = Object.assign(\n args,\n beforeToolCallInterception?.args || {}\n );\n\n const headers = beforeToolCallInterception?.headers || {};\n const hasHeaderChanges = Object.entries(headers).length > 0;\n if (hasHeaderChanges && typeof (client as Client).fork !== \"function\") {\n throw new ToolException(\n `MCP client for server \"${serverName}\" does not support header changes`\n );\n }\n\n const finalClient =\n hasHeaderChanges && typeof (client as Client).fork === \"function\"\n ? await (client as Client).fork(headers)\n : client;\n\n const callToolArgs: Parameters<typeof finalClient.callTool> = [\n {\n name: toolName,\n arguments: finalArgs,\n },\n ];\n\n if (Object.keys(requestOptions).length > 0) {\n callToolArgs.push(undefined); // optional output schema arg\n callToolArgs.push(requestOptions);\n }\n\n const result = (await finalClient.callTool(\n ...callToolArgs\n )) as CallToolResult;\n const [content, artifacts] = await _convertCallToolResult({\n serverName,\n toolName,\n result,\n client: finalClient,\n useStandardContentBlocks,\n outputHandling,\n });\n\n // Convert ExtendedContent to the format expected by afterToolCall\n // afterToolCall expects: string | (ContentBlock | ContentBlock.Data.DataContentBlock)[]\n // ExtendedContent can be: string | ContentBlock[] | (ContentBlock.Text & {...})\n const normalizedContent:\n | string\n | (ContentBlock | ContentBlock.Data.DataContentBlock)[] =\n typeof content === \"string\"\n ? content\n : Array.isArray(content)\n ? (content as (ContentBlock | ContentBlock.Data.DataContentBlock)[])\n : ([content] as (\n | ContentBlock\n | ContentBlock.Data.DataContentBlock\n )[]);\n\n // Filter artifacts to only include types expected by afterToolCall\n // afterToolCall expects: (EmbeddedResource | ContentBlock.Multimodal.Standard)[]\n // ExtendedArtifact includes additional types (MCPStructuredContentArtifact, MCPMetaArtifact)\n // which need to be filtered out\n const normalizedArtifacts: (\n | EmbeddedResource\n | ContentBlock.Multimodal.Standard\n )[] = artifacts.filter(\n (\n artifact\n ): artifact is EmbeddedResource | ContentBlock.Multimodal.Standard =>\n artifact.type === \"resource\" ||\n (artifact.type !== \"mcp_structured_content\" &&\n artifact.type !== \"mcp_meta\" &&\n typeof artifact === \"object\" &&\n artifact !== null &&\n \"source_type\" in artifact)\n ) as (EmbeddedResource | ContentBlock.Multimodal.Standard)[];\n\n const interceptedResult = await afterToolCall?.(\n {\n name: toolName,\n args: finalArgs,\n result: [normalizedContent, normalizedArtifacts],\n serverName,\n },\n state,\n config ?? {}\n );\n\n if (!interceptedResult) {\n return [content, artifacts];\n }\n\n if (typeof interceptedResult.result === \"string\") {\n return [interceptedResult.result, []];\n }\n\n if (Array.isArray(interceptedResult.result)) {\n return interceptedResult.result as ContentBlocksWithArtifacts;\n }\n\n if (ToolMessage.isInstance(interceptedResult.result)) {\n return [interceptedResult.result.contentBlocks, []];\n }\n\n // eslint-disable-next-line no-instanceof/no-instanceof\n if (interceptedResult?.result instanceof Command) {\n return interceptedResult.result;\n }\n\n throw new Error(\n `Unexpected result value type from afterToolCall: expected either a Command, a ToolMessage or a tuple of ContentBlock and Artifact, but got ${interceptedResult.result}`\n );\n } catch (error) {\n // eslint-disable-next-line no-instanceof/no-instanceof\n if (error instanceof ZodErrorV4 || error instanceof ZodErrorV3) {\n throw new ToolException(z.prettifyError(error), error);\n }\n\n debugLog(`Error calling tool ${toolName}: ${String(error)}`);\n if (isToolException(error)) {\n throw error;\n }\n throw new ToolException(`Error calling tool ${toolName}: ${String(error)}`);\n }\n}\n\nconst defaultLoadMcpToolsOptions: LoadMcpToolsOptions = {\n throwOnLoadError: true,\n prefixToolNameWithServerName: false,\n additionalToolNamePrefix: \"\",\n useStandardContentBlocks: false,\n};\n\n/**\n * Load all tools from an MCP client.\n *\n * @param serverName - The name of the server to load tools from\n * @param client - The MCP client\n * @returns A list of LangChain tools\n */\nexport async function loadMcpTools(\n serverName: string,\n client: MCPInstance,\n options?: LoadMcpToolsOptions\n): Promise<DynamicStructuredTool[]> {\n const {\n throwOnLoadError,\n prefixToolNameWithServerName,\n additionalToolNamePrefix,\n useStandardContentBlocks,\n outputHandling,\n defaultToolTimeout,\n } = {\n ...defaultLoadMcpToolsOptions,\n ...(options ?? {}),\n };\n\n const mcpTools: MCPTool[] = [];\n\n // Get tools in a single operation\n let toolsResponse: ListToolsResult | undefined;\n do {\n toolsResponse = await client.listTools({\n ...(toolsResponse?.nextCursor\n ? { cursor: toolsResponse.nextCursor }\n : {}),\n });\n mcpTools.push(...(toolsResponse.tools || []));\n } while (toolsResponse.nextCursor);\n\n debugLog(`INFO: Found ${mcpTools.length} MCP tools`);\n\n const initialPrefix = additionalToolNamePrefix\n ? `${additionalToolNamePrefix}__`\n : \"\";\n const serverPrefix = prefixToolNameWithServerName ? `${serverName}__` : \"\";\n const toolNamePrefix = `${initialPrefix}${serverPrefix}`;\n\n // Filter out tools without names and convert in a single map operation\n return (\n await Promise.all(\n mcpTools\n .filter((tool: MCPTool) => !!tool.name)\n .map(async (tool: MCPTool) => {\n try {\n if (!tool.inputSchema.properties) {\n // Workaround for MCP SDK not consistently providing properties\n tool.inputSchema.properties = {};\n }\n\n // Dereference $defs/$ref in the schema to support Pydantic v2 schemas\n // and other JSON schemas that use $defs for nested type definitions\n const dereferencedSchema = dereferenceJsonSchema(\n tool.inputSchema as JsonSchemaObject\n );\n\n const dst = new DynamicStructuredTool({\n name: `${toolNamePrefix}${tool.name}`,\n description: tool.description || \"\",\n schema: dereferencedSchema,\n responseFormat: \"content_and_artifact\",\n metadata: { annotations: tool.annotations },\n defaultConfig: defaultToolTimeout\n ? { timeout: defaultToolTimeout }\n : undefined,\n func: async (\n args: Record<string, unknown>,\n _runManager?: CallbackManagerForToolRun,\n config?: RunnableConfig\n ) => {\n return _callTool({\n serverName,\n toolName: tool.name,\n client,\n args,\n config,\n useStandardContentBlocks,\n outputHandling,\n onProgress: options?.onProgress,\n beforeToolCall: options?.beforeToolCall,\n afterToolCall: options?.afterToolCall,\n });\n },\n });\n debugLog(`INFO: Successfully loaded tool: ${dst.name}`);\n return dst;\n } catch (error) {\n debugLog(`ERROR: Failed to load tool \"${tool.name}\":`, error);\n if (throwOnLoadError) {\n throw error;\n }\n return null;\n }\n })\n )\n ).filter(Boolean) as DynamicStructuredTool[];\n}\n"],"mappings":"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"}