UNPKG

@n8n/n8n-nodes-langchain

Version:

![Banner image](https://user-images.githubusercontent.com/10284570/173569848-c624317f-42b1-45a6-ab09-f0ea3c247648.png)

415 lines 14.2 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var McpClientTool_node_exports = {}; __export(McpClientTool_node_exports, { McpClientTool: () => McpClientTool }); module.exports = __toCommonJS(McpClientTool_node_exports); var import_types = require("@modelcontextprotocol/sdk/types.js"); var import_n8n_workflow = require("n8n-workflow"); var import_logWrapper = require("../../../utils/logWrapper"); var import_sharedFields = require("../../../utils/sharedFields"); var import_loadOptions = require("./loadOptions"); var import_utils = require("./utils"); var import_descriptions = require("../shared/descriptions"); var import_utils2 = require("../shared/utils"); var import_pick = __toESM(require("lodash/pick")); function getNodeConfig(ctx, itemIndex) { const node = ctx.getNode(); const authentication = ctx.getNodeParameter( "authentication", itemIndex ); const timeout = ctx.getNodeParameter("options.timeout", itemIndex, 6e4); let serverTransport; let endpointUrl; if (node.typeVersion === 1) { serverTransport = "sse"; endpointUrl = ctx.getNodeParameter("sseEndpoint", itemIndex); } else { serverTransport = ctx.getNodeParameter("serverTransport", itemIndex); endpointUrl = ctx.getNodeParameter("endpointUrl", itemIndex); } const mode = ctx.getNodeParameter("include", itemIndex); const includeTools = ctx.getNodeParameter("includeTools", itemIndex, []); const excludeTools = ctx.getNodeParameter("excludeTools", itemIndex, []); return { authentication, timeout, serverTransport, endpointUrl, mode, includeTools, excludeTools }; } async function connectAndGetTools(ctx, config) { const node = ctx.getNode(); const { headers } = await (0, import_utils2.getAuthHeaders)(ctx, config.authentication); const client = await (0, import_utils2.connectMcpClient)({ serverTransport: config.serverTransport, endpointUrl: config.endpointUrl, headers, name: node.type, version: node.typeVersion, onUnauthorized: async (headers2) => await (0, import_utils2.tryRefreshOAuth2Token)(ctx, config.authentication, headers2) }); if (!client.ok) { return { client, mcpTools: null, error: client.error }; } const allTools = await (0, import_utils2.getAllTools)(client.result); const mcpTools = (0, import_utils.getSelectedTools)({ tools: allTools, mode: config.mode, includeTools: config.includeTools, excludeTools: config.excludeTools }); return { client: client.result, mcpTools, error: null }; } class McpClientTool { constructor() { this.description = { displayName: "MCP Client Tool", name: "mcpClientTool", icon: { light: "file:../mcp.svg", dark: "file:../mcp.dark.svg" }, group: ["output"], version: [1, 1.1, 1.2], description: "Connect tools from an MCP Server", defaults: { name: "MCP Client" }, codex: { categories: ["AI"], subcategories: { AI: ["Model Context Protocol", "Tools"] }, alias: ["Model Context Protocol", "MCP Client"], resources: { primaryDocumentation: [ { url: "https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolmcp/" } ] } }, inputs: [], outputs: [{ type: import_n8n_workflow.NodeConnectionTypes.AiTool, displayName: "Tools" }], credentials: import_descriptions.credentials, properties: [ (0, import_sharedFields.getConnectionHintNoticeField)([import_n8n_workflow.NodeConnectionTypes.AiAgent]), { displayName: "SSE Endpoint", name: "sseEndpoint", type: "string", description: "SSE Endpoint of your MCP server", placeholder: "e.g. https://my-mcp-server.ai/sse", default: "", required: true, displayOptions: { show: { "@version": [1] } } }, { displayName: "Endpoint", name: "endpointUrl", type: "string", description: "Endpoint of your MCP server", placeholder: "e.g. https://my-mcp-server.ai/mcp", default: "", required: true, displayOptions: { show: { "@version": [{ _cnd: { gte: 1.1 } }] } } }, (0, import_descriptions.transportSelect)({ defaultOption: "sse", displayOptions: { show: { "@version": [1.1] } } }), (0, import_descriptions.transportSelect)({ defaultOption: "httpStreamable", displayOptions: { show: { "@version": [{ _cnd: { gte: 1.2 } }] } } }), { displayName: "Authentication", name: "authentication", type: "options", options: [ { name: "Bearer Auth", value: "bearerAuth" }, { name: "Header Auth", value: "headerAuth" }, { name: "None", value: "none" } ], default: "none", description: "The way to authenticate with your endpoint", displayOptions: { show: { "@version": [{ _cnd: { lt: 1.2 } }] } } }, { displayName: "Authentication", name: "authentication", type: "options", options: [ { name: "Bearer Auth", value: "bearerAuth" }, { name: "Header Auth", value: "headerAuth" }, { name: "MCP OAuth2", value: "mcpOAuth2Api" }, { name: "Multiple Headers Auth", value: "multipleHeadersAuth" }, { name: "None", value: "none" } ], default: "none", description: "The way to authenticate with your endpoint", displayOptions: { show: { "@version": [{ _cnd: { gte: 1.2 } }] } } }, { displayName: "Credentials", name: "credentials", type: "credentials", default: "", displayOptions: { show: { authentication: ["headerAuth", "bearerAuth", "mcpOAuth2Api", "multipleHeadersAuth"] } } }, { displayName: "Tools to Include", name: "include", type: "options", description: "How to select the tools you want to be exposed to the AI Agent", default: "all", options: [ { name: "All", value: "all", description: "Also include all unchanged fields from the input" }, { name: "Selected", value: "selected", description: 'Also include the tools listed in the parameter "Tools to Include"' }, { name: "All Except", value: "except", description: 'Exclude the tools listed in the parameter "Tools to Exclude"' } ] }, { displayName: "Tools to Include", name: "includeTools", type: "multiOptions", default: [], description: 'Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: "getTools", loadOptionsDependsOn: ["sseEndpoint"] }, displayOptions: { show: { include: ["selected"] } } }, { displayName: "Tools to Exclude", name: "excludeTools", type: "multiOptions", default: [], description: 'Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: "getTools" }, displayOptions: { show: { include: ["except"] } } }, { displayName: "Options", name: "options", placeholder: "Add Option", description: "Additional options to add", type: "collection", default: {}, options: [ { displayName: "Timeout", name: "timeout", type: "number", typeOptions: { minValue: 1 }, default: 6e4, description: "Time in ms to wait for tool calls to finish" } ] } ] }; this.methods = { loadOptions: { getTools: import_loadOptions.getTools } }; } async supplyData(itemIndex) { const node = this.getNode(); const config = getNodeConfig(this, itemIndex); const setError = (error2) => { this.addOutputData(import_n8n_workflow.NodeConnectionTypes.AiTool, itemIndex, error2); throw error2; }; const { client, mcpTools, error } = await connectAndGetTools(this, config); if (error) { this.logger.error("McpClientTool: Failed to connect to MCP Server", { error }); return setError((0, import_utils2.mapToNodeOperationError)(node, error)); } this.logger.debug("McpClientTool: Successfully connected to MCP Server"); if (!mcpTools?.length) { return setError( new import_n8n_workflow.NodeOperationError(node, "MCP Server returned no tools", { itemIndex, description: "Connected successfully to your MCP server but it returned an empty list of tools." }) ); } const tools = mcpTools.map( (tool) => (0, import_logWrapper.logWrapper)( (0, import_utils.mcpToolToDynamicTool)( tool, (0, import_utils.createCallTool)(tool.name, client, config.timeout, (errorMessage) => { const error2 = new import_n8n_workflow.NodeOperationError(node, errorMessage, { itemIndex }); void this.addOutputData(import_n8n_workflow.NodeConnectionTypes.AiTool, itemIndex, error2); this.logger.error(`McpClientTool: Tool "${tool.name}" failed to execute`, { error: error2 }); }) ), this ) ); this.logger.debug(`McpClientTool: Connected to MCP Server with ${tools.length} tools`); const toolkit = new import_utils.McpToolkit(tools); return { response: toolkit, closeFunction: async () => await client.close() }; } async execute() { const node = this.getNode(); const items = this.getInputData(); const returnData = []; for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { const item = items[itemIndex]; const config = getNodeConfig(this, itemIndex); const { client, mcpTools, error } = await connectAndGetTools(this, config); if (error) { throw new import_n8n_workflow.NodeOperationError(node, error.error, { itemIndex }); } if (!mcpTools?.length) { throw new import_n8n_workflow.NodeOperationError(node, "MCP Server returned no tools", { itemIndex }); } for (const tool of mcpTools) { if (!item.json.tool || typeof item.json.tool !== "string") { throw new import_n8n_workflow.NodeOperationError(node, "Tool name not found in item.json.tool or item.tool", { itemIndex }); } const toolName = item.json.tool; if (toolName === tool.name) { const { tool: _, ...toolArguments } = item.json; const schema = tool.inputSchema; const sanitizedToolArguments = schema.additionalProperties !== true ? (0, import_pick.default)(toolArguments, Object.keys(schema.properties ?? {})) : toolArguments; const params = { name: tool.name, arguments: sanitizedToolArguments }; const result = await client.callTool(params, import_types.CallToolResultSchema, { timeout: config.timeout }); returnData.push({ json: { response: result.content }, pairedItem: { item: itemIndex } }); } } } return [returnData]; } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { McpClientTool }); //# sourceMappingURL=McpClientTool.node.js.map