@n8n/n8n-nodes-langchain 1.103.0 → 1.104.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/known/nodes.json +4 -0
- package/dist/nodes/agents/Agent/Agent.node.js +1 -2
- package/dist/nodes/agents/Agent/Agent.node.js.map +1 -1
- package/dist/nodes/document_loaders/DocumentGithubLoader/DocumentGithubLoader.node.js +1 -1
- package/dist/nodes/document_loaders/DocumentGithubLoader/DocumentGithubLoader.node.js.map +1 -1
- package/dist/nodes/mcp/McpClientTool/McpClientTool.node.js +4 -5
- package/dist/nodes/mcp/McpClientTool/McpClientTool.node.js.map +1 -1
- package/dist/nodes/mcp/McpClientTool/utils.js +8 -3
- package/dist/nodes/mcp/McpClientTool/utils.js.map +1 -1
- package/dist/nodes/trigger/ChatTrigger/Chat.node.js +250 -0
- package/dist/nodes/trigger/ChatTrigger/Chat.node.js.map +1 -0
- package/dist/nodes/trigger/ChatTrigger/ChatTrigger.node.js +88 -30
- package/dist/nodes/trigger/ChatTrigger/ChatTrigger.node.js.map +1 -1
- package/dist/nodes/trigger/ChatTrigger/templates.js +1 -1
- package/dist/nodes/trigger/ChatTrigger/templates.js.map +1 -1
- package/dist/nodes/trigger/ChatTrigger/util.js +82 -0
- package/dist/nodes/trigger/ChatTrigger/util.js.map +1 -0
- package/dist/nodes/vendors/GoogleGemini/actions/text/message.operation.js +2 -1
- package/dist/nodes/vendors/GoogleGemini/actions/text/message.operation.js.map +1 -1
- package/dist/nodes/vendors/OpenAi/actions/assistant/message.operation.js +3 -4
- package/dist/nodes/vendors/OpenAi/actions/assistant/message.operation.js.map +1 -1
- package/dist/types/nodes.json +4 -3
- package/dist/utils/helpers.js +12 -0
- package/dist/utils/helpers.js.map +1 -1
- package/package.json +9 -7
package/dist/known/nodes.json
CHANGED
|
@@ -307,6 +307,10 @@
|
|
|
307
307
|
"className": "ChatTrigger",
|
|
308
308
|
"sourcePath": "dist/nodes/trigger/ChatTrigger/ChatTrigger.node.js"
|
|
309
309
|
},
|
|
310
|
+
"chat": {
|
|
311
|
+
"className": "Chat",
|
|
312
|
+
"sourcePath": "dist/nodes/trigger/ChatTrigger/Chat.node.js"
|
|
313
|
+
},
|
|
310
314
|
"vectorStoreInMemory": {
|
|
311
315
|
"className": "VectorStoreInMemory",
|
|
312
316
|
"sourcePath": "dist/nodes/vector_store/VectorStoreInMemory/VectorStoreInMemory.node.js"
|
|
@@ -47,8 +47,7 @@ class Agent extends import_n8n_workflow.VersionedNodeType {
|
|
|
47
47
|
]
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
|
-
|
|
51
|
-
defaultVersion: 2.1
|
|
50
|
+
defaultVersion: 2.2
|
|
52
51
|
};
|
|
53
52
|
const nodeVersions = {
|
|
54
53
|
1: new import_AgentV1.AgentV1(baseDescription),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/agents/Agent/Agent.node.ts"],"sourcesContent":["import type { INodeTypeBaseDescription, IVersionedNodeType } from 'n8n-workflow';\nimport { VersionedNodeType } from 'n8n-workflow';\n\nimport { AgentV1 } from './V1/AgentV1.node';\nimport { AgentV2 } from './V2/AgentV2.node';\n\nexport class Agent extends VersionedNodeType {\n\tconstructor() {\n\t\tconst baseDescription: INodeTypeBaseDescription = {\n\t\t\tdisplayName: 'AI Agent',\n\t\t\tname: 'agent',\n\t\t\ticon: 'fa:robot',\n\t\t\ticonColor: 'black',\n\t\t\tgroup: ['transform'],\n\t\t\tdescription: 'Generates an action plan and executes it. Can use external tools.',\n\t\t\tcodex: {\n\t\t\t\talias: ['LangChain', 'Chat', 'Conversational', 'Plan and Execute', 'ReAct', 'Tools'],\n\t\t\t\tcategories: ['AI'],\n\t\t\t\tsubcategories: {\n\t\t\t\t\tAI: ['Agents', 'Root Nodes'],\n\t\t\t\t},\n\t\t\t\tresources: {\n\t\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/agents/Agent/Agent.node.ts"],"sourcesContent":["import type { INodeTypeBaseDescription, IVersionedNodeType } from 'n8n-workflow';\nimport { VersionedNodeType } from 'n8n-workflow';\n\nimport { AgentV1 } from './V1/AgentV1.node';\nimport { AgentV2 } from './V2/AgentV2.node';\n\nexport class Agent extends VersionedNodeType {\n\tconstructor() {\n\t\tconst baseDescription: INodeTypeBaseDescription = {\n\t\t\tdisplayName: 'AI Agent',\n\t\t\tname: 'agent',\n\t\t\ticon: 'fa:robot',\n\t\t\ticonColor: 'black',\n\t\t\tgroup: ['transform'],\n\t\t\tdescription: 'Generates an action plan and executes it. Can use external tools.',\n\t\t\tcodex: {\n\t\t\t\talias: ['LangChain', 'Chat', 'Conversational', 'Plan and Execute', 'ReAct', 'Tools'],\n\t\t\t\tcategories: ['AI'],\n\t\t\t\tsubcategories: {\n\t\t\t\t\tAI: ['Agents', 'Root Nodes'],\n\t\t\t\t},\n\t\t\t\tresources: {\n\t\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdefaultVersion: 2.2,\n\t\t};\n\n\t\tconst nodeVersions: IVersionedNodeType['nodeVersions'] = {\n\t\t\t1: new AgentV1(baseDescription),\n\t\t\t1.1: new AgentV1(baseDescription),\n\t\t\t1.2: new AgentV1(baseDescription),\n\t\t\t1.3: new AgentV1(baseDescription),\n\t\t\t1.4: new AgentV1(baseDescription),\n\t\t\t1.5: new AgentV1(baseDescription),\n\t\t\t1.6: new AgentV1(baseDescription),\n\t\t\t1.7: new AgentV1(baseDescription),\n\t\t\t1.8: new AgentV1(baseDescription),\n\t\t\t1.9: new AgentV1(baseDescription),\n\t\t\t2: new AgentV2(baseDescription),\n\t\t\t2.1: new AgentV2(baseDescription),\n\t\t\t2.2: new AgentV2(baseDescription),\n\t\t\t// IMPORTANT Reminder to update AgentTool\n\t\t};\n\n\t\tsuper(nodeVersions, baseDescription);\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,0BAAkC;AAElC,qBAAwB;AACxB,qBAAwB;AAEjB,MAAM,cAAc,sCAAkB;AAAA,EAC5C,cAAc;AACb,UAAM,kBAA4C;AAAA,MACjD,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAW;AAAA,MACX,OAAO,CAAC,WAAW;AAAA,MACnB,aAAa;AAAA,MACb,OAAO;AAAA,QACN,OAAO,CAAC,aAAa,QAAQ,kBAAkB,oBAAoB,SAAS,OAAO;AAAA,QACnF,YAAY,CAAC,IAAI;AAAA,QACjB,eAAe;AAAA,UACd,IAAI,CAAC,UAAU,YAAY;AAAA,QAC5B;AAAA,QACA,WAAW;AAAA,UACV,sBAAsB;AAAA,YACrB;AAAA,cACC,KAAK;AAAA,YACN;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,MACA,gBAAgB;AAAA,IACjB;AAEA,UAAM,eAAmD;AAAA,MACxD,GAAG,IAAI,uBAAQ,eAAe;AAAA,MAC9B,KAAK,IAAI,uBAAQ,eAAe;AAAA,MAChC,KAAK,IAAI,uBAAQ,eAAe;AAAA,MAChC,KAAK,IAAI,uBAAQ,eAAe;AAAA,MAChC,KAAK,IAAI,uBAAQ,eAAe;AAAA,MAChC,KAAK,IAAI,uBAAQ,eAAe;AAAA,MAChC,KAAK,IAAI,uBAAQ,eAAe;AAAA,MAChC,KAAK,IAAI,uBAAQ,eAAe;AAAA,MAChC,KAAK,IAAI,uBAAQ,eAAe;AAAA,MAChC,KAAK,IAAI,uBAAQ,eAAe;AAAA,MAChC,GAAG,IAAI,uBAAQ,eAAe;AAAA,MAC9B,KAAK,IAAI,uBAAQ,eAAe;AAAA,MAChC,KAAK,IAAI,uBAAQ,eAAe;AAAA;AAAA,IAEjC;AAEA,UAAM,cAAc,eAAe;AAAA,EACpC;AACD;","names":[]}
|
|
@@ -23,9 +23,9 @@ __export(DocumentGithubLoader_node_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(DocumentGithubLoader_node_exports);
|
|
24
24
|
var import_github = require("@langchain/community/document_loaders/web/github");
|
|
25
25
|
var import_textsplitters = require("@langchain/textsplitters");
|
|
26
|
-
var import_n8n_workflow = require("n8n-workflow");
|
|
27
26
|
var import_logWrapper = require("../../../utils/logWrapper");
|
|
28
27
|
var import_sharedFields = require("../../../utils/sharedFields");
|
|
28
|
+
var import_n8n_workflow = require("n8n-workflow");
|
|
29
29
|
function getInputs(parameters) {
|
|
30
30
|
const inputs = [];
|
|
31
31
|
const textSplittingMode = parameters?.textSplittingMode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/document_loaders/DocumentGithubLoader/DocumentGithubLoader.node.ts"],"sourcesContent":["import { GithubRepoLoader } from '@langchain/community/document_loaders/web/github';\nimport type { TextSplitter } from '@langchain/textsplitters';\nimport { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';\nimport {\n\tNodeConnectionTypes,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype ISupplyDataFunctions,\n\ttype SupplyData,\n\ttype IDataObject,\n\ttype INodeInputConfiguration,\n} from 'n8n-workflow';\n\
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/document_loaders/DocumentGithubLoader/DocumentGithubLoader.node.ts"],"sourcesContent":["import { GithubRepoLoader } from '@langchain/community/document_loaders/web/github';\nimport type { TextSplitter } from '@langchain/textsplitters';\nimport { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';\nimport { logWrapper } from '@utils/logWrapper';\nimport { getConnectionHintNoticeField } from '@utils/sharedFields';\nimport {\n\tNodeConnectionTypes,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype ISupplyDataFunctions,\n\ttype SupplyData,\n\ttype IDataObject,\n\ttype INodeInputConfiguration,\n} from 'n8n-workflow';\n\nfunction getInputs(parameters: IDataObject) {\n\tconst inputs: INodeInputConfiguration[] = [];\n\n\tconst textSplittingMode = parameters?.textSplittingMode;\n\t// If text splitting mode is 'custom' or does not exist (v1), we need to add an input for the text splitter\n\tif (!textSplittingMode || textSplittingMode === 'custom') {\n\t\tinputs.push({\n\t\t\tdisplayName: 'Text Splitter',\n\t\t\tmaxConnections: 1,\n\t\t\ttype: 'ai_textSplitter',\n\t\t\trequired: true,\n\t\t});\n\t}\n\n\treturn inputs;\n}\n\nexport class DocumentGithubLoader implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'GitHub Document Loader',\n\t\tname: 'documentGithubLoader',\n\t\ticon: 'file:github.svg',\n\t\tgroup: ['transform'],\n\t\tversion: [1, 1.1],\n\t\tdefaultVersion: 1.1,\n\t\tdescription: 'Use GitHub data as input to this chain',\n\t\tdefaults: {\n\t\t\tname: 'GitHub Document Loader',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['AI'],\n\t\t\tsubcategories: {\n\t\t\t\tAI: ['Document Loaders'],\n\t\t\t},\n\t\t\tresources: {\n\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t{\n\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.documentgithubloader/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\tname: 'githubApi',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\n\t\tinputs: `={{ ((parameter) => { ${getInputs.toString()}; return getInputs(parameter) })($parameter) }}`,\n\t\tinputNames: ['Text Splitter'],\n\n\t\toutputs: [NodeConnectionTypes.AiDocument],\n\t\toutputNames: ['Document'],\n\t\tproperties: [\n\t\t\tgetConnectionHintNoticeField([NodeConnectionTypes.AiVectorStore]),\n\t\t\t{\n\t\t\t\tdisplayName: 'Repository Link',\n\t\t\t\tname: 'repository',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Branch',\n\t\t\t\tname: 'branch',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'main',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Text Splitting',\n\t\t\t\tname: 'textSplittingMode',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'simple',\n\t\t\t\trequired: true,\n\t\t\t\tnoDataExpression: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1.1],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Simple',\n\t\t\t\t\t\tvalue: 'simple',\n\t\t\t\t\t\tdescription: 'Splits every 1000 characters with a 200 character overlap',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Custom',\n\t\t\t\t\t\tvalue: 'custom',\n\t\t\t\t\t\tdescription: 'Connect a custom text-splitting sub-node',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'additionalOptions',\n\t\t\t\ttype: 'collection',\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\tdefault: {},\n\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Recursive',\n\t\t\t\t\t\tname: 'recursive',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Ignore Paths',\n\t\t\t\t\t\tname: 'ignorePaths',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'Comma-separated list of paths to ignore, e.g. \"docs, src/tests',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tasync supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData> {\n\t\tthis.logger.debug('Supplying data for Github Document Loader');\n\t\tconst node = this.getNode();\n\n\t\tconst repository = this.getNodeParameter('repository', itemIndex) as string;\n\t\tconst branch = this.getNodeParameter('branch', itemIndex) as string;\n\t\tconst credentials = await this.getCredentials('githubApi');\n\t\tconst { ignorePaths, recursive } = this.getNodeParameter('additionalOptions', 0) as {\n\t\t\trecursive: boolean;\n\t\t\tignorePaths: string;\n\t\t};\n\t\tlet textSplitter: TextSplitter | undefined;\n\n\t\tif (node.typeVersion === 1.1) {\n\t\t\tconst textSplittingMode = this.getNodeParameter('textSplittingMode', itemIndex, 'simple') as\n\t\t\t\t| 'simple'\n\t\t\t\t| 'custom';\n\n\t\t\tif (textSplittingMode === 'simple') {\n\t\t\t\ttextSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000, chunkOverlap: 200 });\n\t\t\t} else if (textSplittingMode === 'custom') {\n\t\t\t\ttextSplitter = (await this.getInputConnectionData(NodeConnectionTypes.AiTextSplitter, 0)) as\n\t\t\t\t\t| TextSplitter\n\t\t\t\t\t| undefined;\n\t\t\t}\n\t\t} else {\n\t\t\ttextSplitter = (await this.getInputConnectionData(NodeConnectionTypes.AiTextSplitter, 0)) as\n\t\t\t\t| TextSplitter\n\t\t\t\t| undefined;\n\t\t}\n\n\t\tconst { index } = this.addInputData(NodeConnectionTypes.AiDocument, [\n\t\t\t[{ json: { repository, branch, ignorePaths, recursive } }],\n\t\t]);\n\t\tconst docs = new GithubRepoLoader(repository, {\n\t\t\tbranch,\n\t\t\tignorePaths: (ignorePaths ?? '').split(',').map((p) => p.trim()),\n\t\t\trecursive,\n\t\t\taccessToken: (credentials.accessToken as string) || '',\n\t\t\tapiUrl: credentials.server as string,\n\t\t});\n\n\t\tconst loadedDocs = textSplitter\n\t\t\t? await textSplitter.splitDocuments(await docs.load())\n\t\t\t: await docs.load();\n\n\t\tthis.addOutputData(NodeConnectionTypes.AiDocument, index, [[{ json: { loadedDocs } }]]);\n\t\treturn {\n\t\t\tresponse: logWrapper(loadedDocs, this),\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -21,9 +21,9 @@ __export(McpClientTool_node_exports, {
|
|
|
21
21
|
McpClientTool: () => McpClientTool
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(McpClientTool_node_exports);
|
|
24
|
-
var import_n8n_workflow = require("n8n-workflow");
|
|
25
24
|
var import_logWrapper = require("../../../utils/logWrapper");
|
|
26
25
|
var import_sharedFields = require("../../../utils/sharedFields");
|
|
26
|
+
var import_n8n_workflow = require("n8n-workflow");
|
|
27
27
|
var import_loadOptions = require("./loadOptions");
|
|
28
28
|
var import_utils = require("./utils");
|
|
29
29
|
class McpClientTool {
|
|
@@ -286,11 +286,10 @@ class McpClientTool {
|
|
|
286
286
|
(tool) => (0, import_logWrapper.logWrapper)(
|
|
287
287
|
(0, import_utils.mcpToolToDynamicTool)(
|
|
288
288
|
tool,
|
|
289
|
-
(0, import_utils.createCallTool)(tool.name, client.result, (
|
|
289
|
+
(0, import_utils.createCallTool)(tool.name, client.result, (errorMessage) => {
|
|
290
|
+
const error = new import_n8n_workflow.NodeOperationError(node, errorMessage, { itemIndex });
|
|
291
|
+
void this.addOutputData(import_n8n_workflow.NodeConnectionTypes.AiTool, itemIndex, error);
|
|
290
292
|
this.logger.error(`McpClientTool: Tool "${tool.name}" failed to execute`, { error });
|
|
291
|
-
throw new import_n8n_workflow.NodeOperationError(node, `Failed to execute tool "${tool.name}"`, {
|
|
292
|
-
description: error
|
|
293
|
-
});
|
|
294
293
|
})
|
|
295
294
|
),
|
|
296
295
|
this
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/mcp/McpClientTool/McpClientTool.node.ts"],"sourcesContent":["import {\n\tNodeConnectionTypes,\n\tNodeOperationError,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype ISupplyDataFunctions,\n\ttype SupplyData,\n} from 'n8n-workflow';\n\nimport { logWrapper } from '@utils/logWrapper';\nimport { getConnectionHintNoticeField } from '@utils/sharedFields';\n\nimport { getTools } from './loadOptions';\nimport type { McpServerTransport, McpAuthenticationOption, McpToolIncludeMode } from './types';\nimport {\n\tconnectMcpClient,\n\tcreateCallTool,\n\tgetAllTools,\n\tgetAuthHeaders,\n\tgetSelectedTools,\n\tMcpToolkit,\n\tmcpToolToDynamicTool,\n} from './utils';\n\nexport class McpClientTool implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'MCP Client Tool',\n\t\tname: 'mcpClientTool',\n\t\ticon: {\n\t\t\tlight: 'file:../mcp.svg',\n\t\t\tdark: 'file:../mcp.dark.svg',\n\t\t},\n\t\tgroup: ['output'],\n\t\tversion: [1, 1.1],\n\t\tdescription: 'Connect tools from an MCP Server',\n\t\tdefaults: {\n\t\t\tname: 'MCP Client',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['AI'],\n\t\t\tsubcategories: {\n\t\t\t\tAI: ['Model Context Protocol', 'Tools'],\n\t\t\t},\n\t\t\talias: ['Model Context Protocol', 'MCP Client'],\n\t\t\tresources: {\n\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t{\n\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolmcp/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\tinputs: [],\n\t\toutputs: [{ type: NodeConnectionTypes.AiTool, displayName: 'Tools' }],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-credentials-name-unsuffixed\n\t\t\t\tname: 'httpBearerAuth',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['bearerAuth'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'httpHeaderAuth',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['headerAuth'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tproperties: [\n\t\t\tgetConnectionHintNoticeField([NodeConnectionTypes.AiAgent]),\n\t\t\t{\n\t\t\t\tdisplayName: 'SSE Endpoint',\n\t\t\t\tname: 'sseEndpoint',\n\t\t\t\ttype: 'string',\n\t\t\t\tdescription: 'SSE Endpoint of your MCP server',\n\t\t\t\tplaceholder: 'e.g. https://my-mcp-server.ai/sse',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Endpoint',\n\t\t\t\tname: 'endpointUrl',\n\t\t\t\ttype: 'string',\n\t\t\t\tdescription: 'Endpoint of your MCP server',\n\t\t\t\tplaceholder: 'e.g. https://my-mcp-server.ai/mcp',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.1 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Server Transport',\n\t\t\t\tname: 'serverTransport',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Server Sent Events (Deprecated)',\n\t\t\t\t\t\tvalue: 'sse',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'HTTP Streamable',\n\t\t\t\t\t\tvalue: 'httpStreamable',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'sse',\n\t\t\t\tdescription: 'The transport used by your endpoint',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.1 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Authentication',\n\t\t\t\tname: 'authentication',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Bearer Auth',\n\t\t\t\t\t\tvalue: 'bearerAuth',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Header Auth',\n\t\t\t\t\t\tvalue: 'headerAuth',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'None',\n\t\t\t\t\t\tvalue: 'none',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'none',\n\t\t\t\tdescription: 'The way to authenticate with your endpoint',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Credentials',\n\t\t\t\tname: 'credentials',\n\t\t\t\ttype: 'credentials',\n\t\t\t\tdefault: '',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['headerAuth', 'bearerAuth'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Tools to Include',\n\t\t\t\tname: 'include',\n\t\t\t\ttype: 'options',\n\t\t\t\tdescription: 'How to select the tools you want to be exposed to the AI Agent',\n\t\t\t\tdefault: 'all',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'All',\n\t\t\t\t\t\tvalue: 'all',\n\t\t\t\t\t\tdescription: 'Also include all unchanged fields from the input',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Selected',\n\t\t\t\t\t\tvalue: 'selected',\n\t\t\t\t\t\tdescription: 'Also include the tools listed in the parameter \"Tools to Include\"',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'All Except',\n\t\t\t\t\t\tvalue: 'except',\n\t\t\t\t\t\tdescription: 'Exclude the tools listed in the parameter \"Tools to Exclude\"',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Tools to Include',\n\t\t\t\tname: 'includeTools',\n\t\t\t\ttype: 'multiOptions',\n\t\t\t\tdefault: [],\n\t\t\t\tdescription:\n\t\t\t\t\t'Choose from the list, or specify IDs using an <a href=\"https://docs.n8n.io/code/expressions/\">expression</a>',\n\t\t\t\ttypeOptions: {\n\t\t\t\t\tloadOptionsMethod: 'getTools',\n\t\t\t\t\tloadOptionsDependsOn: ['sseEndpoint'],\n\t\t\t\t},\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tinclude: ['selected'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Tools to Exclude',\n\t\t\t\tname: 'excludeTools',\n\t\t\t\ttype: 'multiOptions',\n\t\t\t\tdefault: [],\n\t\t\t\tdescription:\n\t\t\t\t\t'Choose from the list, or specify IDs using an <a href=\"https://docs.n8n.io/code/expressions/\">expression</a>',\n\t\t\t\ttypeOptions: {\n\t\t\t\t\tloadOptionsMethod: 'getTools',\n\t\t\t\t},\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tinclude: ['except'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t};\n\n\tmethods = {\n\t\tloadOptions: {\n\t\t\tgetTools,\n\t\t},\n\t};\n\n\tasync supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData> {\n\t\tconst authentication = this.getNodeParameter(\n\t\t\t'authentication',\n\t\t\titemIndex,\n\t\t) as McpAuthenticationOption;\n\t\tconst node = this.getNode();\n\n\t\tlet serverTransport: McpServerTransport;\n\t\tlet endpointUrl: string;\n\t\tif (node.typeVersion === 1) {\n\t\t\tserverTransport = 'sse';\n\t\t\tendpointUrl = this.getNodeParameter('sseEndpoint', itemIndex) as string;\n\t\t} else {\n\t\t\tserverTransport = this.getNodeParameter('serverTransport', itemIndex) as McpServerTransport;\n\t\t\tendpointUrl = this.getNodeParameter('endpointUrl', itemIndex) as string;\n\t\t}\n\n\t\tconst { headers } = await getAuthHeaders(this, authentication);\n\t\tconst client = await connectMcpClient({\n\t\t\tserverTransport,\n\t\t\tendpointUrl,\n\t\t\theaders,\n\t\t\tname: node.type,\n\t\t\tversion: node.typeVersion,\n\t\t});\n\n\t\tconst setError = (message: string, description?: string): SupplyData => {\n\t\t\tconst error = new NodeOperationError(node, message, { itemIndex, description });\n\t\t\tthis.addOutputData(NodeConnectionTypes.AiTool, itemIndex, error);\n\t\t\tthrow error;\n\t\t};\n\n\t\tif (!client.ok) {\n\t\t\tthis.logger.error('McpClientTool: Failed to connect to MCP Server', {\n\t\t\t\terror: client.error,\n\t\t\t});\n\n\t\t\tswitch (client.error.type) {\n\t\t\t\tcase 'invalid_url':\n\t\t\t\t\treturn setError('Could not connect to your MCP server. The provided URL is invalid.');\n\t\t\t\tcase 'connection':\n\t\t\t\tdefault:\n\t\t\t\t\treturn setError('Could not connect to your MCP server');\n\t\t\t}\n\t\t}\n\n\t\tthis.logger.debug('McpClientTool: Successfully connected to MCP Server');\n\n\t\tconst mode = this.getNodeParameter('include', itemIndex) as McpToolIncludeMode;\n\t\tconst includeTools = this.getNodeParameter('includeTools', itemIndex, []) as string[];\n\t\tconst excludeTools = this.getNodeParameter('excludeTools', itemIndex, []) as string[];\n\n\t\tconst allTools = await getAllTools(client.result);\n\t\tconst mcpTools = getSelectedTools({\n\t\t\ttools: allTools,\n\t\t\tmode,\n\t\t\tincludeTools,\n\t\t\texcludeTools,\n\t\t});\n\n\t\tif (!mcpTools.length) {\n\t\t\treturn setError(\n\t\t\t\t'MCP Server returned no tools',\n\t\t\t\t'Connected successfully to your MCP server but it returned an empty list of tools.',\n\t\t\t);\n\t\t}\n\n\t\tconst tools = mcpTools.map((tool) =>\n\t\t\tlogWrapper(\n\t\t\t\tmcpToolToDynamicTool(\n\t\t\t\t\ttool,\n\t\t\t\t\tcreateCallTool(tool.name, client.result, (error) => {\n\t\t\t\t\t\tthis.logger.error(`McpClientTool: Tool \"${tool.name}\" failed to execute`, { error });\n\t\t\t\t\t\tthrow new NodeOperationError(node, `Failed to execute tool \"${tool.name}\"`, {\n\t\t\t\t\t\t\tdescription: error,\n\t\t\t\t\t\t});\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tthis,\n\t\t\t),\n\t\t);\n\n\t\tthis.logger.debug(`McpClientTool: Connected to MCP Server with ${tools.length} tools`);\n\n\t\tconst toolkit = new McpToolkit(tools);\n\n\t\treturn { response: toolkit, closeFunction: async () => await client.result.close() };\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/mcp/McpClientTool/McpClientTool.node.ts"],"sourcesContent":["import { logWrapper } from '@utils/logWrapper';\nimport { getConnectionHintNoticeField } from '@utils/sharedFields';\nimport {\n\tNodeConnectionTypes,\n\tNodeOperationError,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype ISupplyDataFunctions,\n\ttype SupplyData,\n} from 'n8n-workflow';\n\nimport { getTools } from './loadOptions';\nimport type { McpServerTransport, McpAuthenticationOption, McpToolIncludeMode } from './types';\nimport {\n\tconnectMcpClient,\n\tcreateCallTool,\n\tgetAllTools,\n\tgetAuthHeaders,\n\tgetSelectedTools,\n\tMcpToolkit,\n\tmcpToolToDynamicTool,\n} from './utils';\n\nexport class McpClientTool implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'MCP Client Tool',\n\t\tname: 'mcpClientTool',\n\t\ticon: {\n\t\t\tlight: 'file:../mcp.svg',\n\t\t\tdark: 'file:../mcp.dark.svg',\n\t\t},\n\t\tgroup: ['output'],\n\t\tversion: [1, 1.1],\n\t\tdescription: 'Connect tools from an MCP Server',\n\t\tdefaults: {\n\t\t\tname: 'MCP Client',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['AI'],\n\t\t\tsubcategories: {\n\t\t\t\tAI: ['Model Context Protocol', 'Tools'],\n\t\t\t},\n\t\t\talias: ['Model Context Protocol', 'MCP Client'],\n\t\t\tresources: {\n\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t{\n\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolmcp/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\tinputs: [],\n\t\toutputs: [{ type: NodeConnectionTypes.AiTool, displayName: 'Tools' }],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-credentials-name-unsuffixed\n\t\t\t\tname: 'httpBearerAuth',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['bearerAuth'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'httpHeaderAuth',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['headerAuth'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tproperties: [\n\t\t\tgetConnectionHintNoticeField([NodeConnectionTypes.AiAgent]),\n\t\t\t{\n\t\t\t\tdisplayName: 'SSE Endpoint',\n\t\t\t\tname: 'sseEndpoint',\n\t\t\t\ttype: 'string',\n\t\t\t\tdescription: 'SSE Endpoint of your MCP server',\n\t\t\t\tplaceholder: 'e.g. https://my-mcp-server.ai/sse',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Endpoint',\n\t\t\t\tname: 'endpointUrl',\n\t\t\t\ttype: 'string',\n\t\t\t\tdescription: 'Endpoint of your MCP server',\n\t\t\t\tplaceholder: 'e.g. https://my-mcp-server.ai/mcp',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.1 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Server Transport',\n\t\t\t\tname: 'serverTransport',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Server Sent Events (Deprecated)',\n\t\t\t\t\t\tvalue: 'sse',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'HTTP Streamable',\n\t\t\t\t\t\tvalue: 'httpStreamable',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'sse',\n\t\t\t\tdescription: 'The transport used by your endpoint',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.1 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Authentication',\n\t\t\t\tname: 'authentication',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Bearer Auth',\n\t\t\t\t\t\tvalue: 'bearerAuth',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Header Auth',\n\t\t\t\t\t\tvalue: 'headerAuth',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'None',\n\t\t\t\t\t\tvalue: 'none',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'none',\n\t\t\t\tdescription: 'The way to authenticate with your endpoint',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Credentials',\n\t\t\t\tname: 'credentials',\n\t\t\t\ttype: 'credentials',\n\t\t\t\tdefault: '',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['headerAuth', 'bearerAuth'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Tools to Include',\n\t\t\t\tname: 'include',\n\t\t\t\ttype: 'options',\n\t\t\t\tdescription: 'How to select the tools you want to be exposed to the AI Agent',\n\t\t\t\tdefault: 'all',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'All',\n\t\t\t\t\t\tvalue: 'all',\n\t\t\t\t\t\tdescription: 'Also include all unchanged fields from the input',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Selected',\n\t\t\t\t\t\tvalue: 'selected',\n\t\t\t\t\t\tdescription: 'Also include the tools listed in the parameter \"Tools to Include\"',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'All Except',\n\t\t\t\t\t\tvalue: 'except',\n\t\t\t\t\t\tdescription: 'Exclude the tools listed in the parameter \"Tools to Exclude\"',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Tools to Include',\n\t\t\t\tname: 'includeTools',\n\t\t\t\ttype: 'multiOptions',\n\t\t\t\tdefault: [],\n\t\t\t\tdescription:\n\t\t\t\t\t'Choose from the list, or specify IDs using an <a href=\"https://docs.n8n.io/code/expressions/\">expression</a>',\n\t\t\t\ttypeOptions: {\n\t\t\t\t\tloadOptionsMethod: 'getTools',\n\t\t\t\t\tloadOptionsDependsOn: ['sseEndpoint'],\n\t\t\t\t},\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tinclude: ['selected'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Tools to Exclude',\n\t\t\t\tname: 'excludeTools',\n\t\t\t\ttype: 'multiOptions',\n\t\t\t\tdefault: [],\n\t\t\t\tdescription:\n\t\t\t\t\t'Choose from the list, or specify IDs using an <a href=\"https://docs.n8n.io/code/expressions/\">expression</a>',\n\t\t\t\ttypeOptions: {\n\t\t\t\t\tloadOptionsMethod: 'getTools',\n\t\t\t\t},\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tinclude: ['except'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t};\n\n\tmethods = {\n\t\tloadOptions: {\n\t\t\tgetTools,\n\t\t},\n\t};\n\n\tasync supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData> {\n\t\tconst authentication = this.getNodeParameter(\n\t\t\t'authentication',\n\t\t\titemIndex,\n\t\t) as McpAuthenticationOption;\n\t\tconst node = this.getNode();\n\n\t\tlet serverTransport: McpServerTransport;\n\t\tlet endpointUrl: string;\n\t\tif (node.typeVersion === 1) {\n\t\t\tserverTransport = 'sse';\n\t\t\tendpointUrl = this.getNodeParameter('sseEndpoint', itemIndex) as string;\n\t\t} else {\n\t\t\tserverTransport = this.getNodeParameter('serverTransport', itemIndex) as McpServerTransport;\n\t\t\tendpointUrl = this.getNodeParameter('endpointUrl', itemIndex) as string;\n\t\t}\n\n\t\tconst { headers } = await getAuthHeaders(this, authentication);\n\t\tconst client = await connectMcpClient({\n\t\t\tserverTransport,\n\t\t\tendpointUrl,\n\t\t\theaders,\n\t\t\tname: node.type,\n\t\t\tversion: node.typeVersion,\n\t\t});\n\n\t\tconst setError = (message: string, description?: string): SupplyData => {\n\t\t\tconst error = new NodeOperationError(node, message, { itemIndex, description });\n\t\t\tthis.addOutputData(NodeConnectionTypes.AiTool, itemIndex, error);\n\t\t\tthrow error;\n\t\t};\n\n\t\tif (!client.ok) {\n\t\t\tthis.logger.error('McpClientTool: Failed to connect to MCP Server', {\n\t\t\t\terror: client.error,\n\t\t\t});\n\n\t\t\tswitch (client.error.type) {\n\t\t\t\tcase 'invalid_url':\n\t\t\t\t\treturn setError('Could not connect to your MCP server. The provided URL is invalid.');\n\t\t\t\tcase 'connection':\n\t\t\t\tdefault:\n\t\t\t\t\treturn setError('Could not connect to your MCP server');\n\t\t\t}\n\t\t}\n\n\t\tthis.logger.debug('McpClientTool: Successfully connected to MCP Server');\n\n\t\tconst mode = this.getNodeParameter('include', itemIndex) as McpToolIncludeMode;\n\t\tconst includeTools = this.getNodeParameter('includeTools', itemIndex, []) as string[];\n\t\tconst excludeTools = this.getNodeParameter('excludeTools', itemIndex, []) as string[];\n\n\t\tconst allTools = await getAllTools(client.result);\n\t\tconst mcpTools = getSelectedTools({\n\t\t\ttools: allTools,\n\t\t\tmode,\n\t\t\tincludeTools,\n\t\t\texcludeTools,\n\t\t});\n\n\t\tif (!mcpTools.length) {\n\t\t\treturn setError(\n\t\t\t\t'MCP Server returned no tools',\n\t\t\t\t'Connected successfully to your MCP server but it returned an empty list of tools.',\n\t\t\t);\n\t\t}\n\n\t\tconst tools = mcpTools.map((tool) =>\n\t\t\tlogWrapper(\n\t\t\t\tmcpToolToDynamicTool(\n\t\t\t\t\ttool,\n\t\t\t\t\tcreateCallTool(tool.name, client.result, (errorMessage) => {\n\t\t\t\t\t\tconst error = new NodeOperationError(node, errorMessage, { itemIndex });\n\t\t\t\t\t\tvoid this.addOutputData(NodeConnectionTypes.AiTool, itemIndex, error);\n\t\t\t\t\t\tthis.logger.error(`McpClientTool: Tool \"${tool.name}\" failed to execute`, { error });\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tthis,\n\t\t\t),\n\t\t);\n\n\t\tthis.logger.debug(`McpClientTool: Connected to MCP Server with ${tools.length} tools`);\n\n\t\tconst toolkit = new McpToolkit(tools);\n\n\t\treturn { response: toolkit, closeFunction: async () => await client.result.close() };\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -33,10 +33,10 @@ var import_client = require("@modelcontextprotocol/sdk/client/index.js");
|
|
|
33
33
|
var import_sse = require("@modelcontextprotocol/sdk/client/sse.js");
|
|
34
34
|
var import_streamableHttp = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
35
35
|
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
36
|
+
var import_schemaParsing = require("../../../utils/schemaParsing");
|
|
36
37
|
var import_agents = require("langchain/agents");
|
|
37
38
|
var import_n8n_workflow = require("n8n-workflow");
|
|
38
39
|
var import_zod = require("zod");
|
|
39
|
-
var import_schemaParsing = require("../../../utils/schemaParsing");
|
|
40
40
|
async function getAllTools(client, cursor) {
|
|
41
41
|
const { tools, nextCursor } = await client.listTools({ cursor });
|
|
42
42
|
if (nextCursor) {
|
|
@@ -83,13 +83,18 @@ const getErrorDescriptionFromToolCall = (result) => {
|
|
|
83
83
|
};
|
|
84
84
|
const createCallTool = (name, client, onError) => async (args) => {
|
|
85
85
|
let result;
|
|
86
|
+
function handleError(error) {
|
|
87
|
+
const errorDescription = getErrorDescriptionFromToolCall(error) ?? `Failed to execute tool "${name}"`;
|
|
88
|
+
onError(errorDescription);
|
|
89
|
+
return errorDescription;
|
|
90
|
+
}
|
|
86
91
|
try {
|
|
87
92
|
result = await client.callTool({ name, arguments: args }, import_types.CompatibilityCallToolResultSchema);
|
|
88
93
|
} catch (error) {
|
|
89
|
-
return
|
|
94
|
+
return handleError(error);
|
|
90
95
|
}
|
|
91
96
|
if (result.isError) {
|
|
92
|
-
return
|
|
97
|
+
return handleError(result);
|
|
93
98
|
}
|
|
94
99
|
if (result.toolResult !== void 0) {
|
|
95
100
|
return result.toolResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/mcp/McpClientTool/utils.ts"],"sourcesContent":["import { DynamicStructuredTool, type DynamicStructuredToolInput } from '@langchain/core/tools';\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { CompatibilityCallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { Toolkit } from 'langchain/agents';\nimport {\n\tcreateResultError,\n\tcreateResultOk,\n\ttype IDataObject,\n\ttype IExecuteFunctions,\n\ttype Result,\n} from 'n8n-workflow';\nimport { z } from 'zod';\n\nimport { convertJsonSchemaToZod } from '@utils/schemaParsing';\n\nimport type {\n\tMcpAuthenticationOption,\n\tMcpTool,\n\tMcpServerTransport,\n\tMcpToolIncludeMode,\n} from './types';\n\nexport async function getAllTools(client: Client, cursor?: string): Promise<McpTool[]> {\n\tconst { tools, nextCursor } = await client.listTools({ cursor });\n\n\tif (nextCursor) {\n\t\treturn (tools as McpTool[]).concat(await getAllTools(client, nextCursor));\n\t}\n\n\treturn tools as McpTool[];\n}\n\nexport function getSelectedTools({\n\tmode,\n\tincludeTools,\n\texcludeTools,\n\ttools,\n}: {\n\tmode: McpToolIncludeMode;\n\tincludeTools?: string[];\n\texcludeTools?: string[];\n\ttools: McpTool[];\n}) {\n\tswitch (mode) {\n\t\tcase 'selected': {\n\t\t\tif (!includeTools?.length) return tools;\n\t\t\tconst include = new Set(includeTools);\n\t\t\treturn tools.filter((tool) => include.has(tool.name));\n\t\t}\n\t\tcase 'except': {\n\t\t\tconst except = new Set(excludeTools ?? []);\n\t\t\treturn tools.filter((tool) => !except.has(tool.name));\n\t\t}\n\t\tcase 'all':\n\t\tdefault:\n\t\t\treturn tools;\n\t}\n}\n\nexport const getErrorDescriptionFromToolCall = (result: unknown): string | undefined => {\n\tif (result && typeof result === 'object') {\n\t\tif ('content' in result && Array.isArray(result.content)) {\n\t\t\tconst errorMessage = (result.content as Array<{ type: 'text'; text: string }>).find(\n\t\t\t\t(content) => content && typeof content === 'object' && typeof content.text === 'string',\n\t\t\t)?.text;\n\t\t\treturn errorMessage;\n\t\t} else if ('toolResult' in result && typeof result.toolResult === 'string') {\n\t\t\treturn result.toolResult;\n\t\t}\n\t\tif ('message' in result && typeof result.message === 'string') {\n\t\t\treturn result.message;\n\t\t}\n\t}\n\n\treturn undefined;\n};\n\nexport const createCallTool =\n\t(name: string, client: Client, onError: (error: string | undefined) => void) =>\n\tasync (args: IDataObject) => {\n\t\tlet result: Awaited<ReturnType<Client['callTool']>>;\n\t\ttry {\n\t\t\tresult = await client.callTool({ name, arguments: args }, CompatibilityCallToolResultSchema);\n\t\t} catch (error) {\n\t\t\treturn onError(getErrorDescriptionFromToolCall(error));\n\t\t}\n\n\t\tif (result.isError) {\n\t\t\treturn onError(getErrorDescriptionFromToolCall(result));\n\t\t}\n\n\t\tif (result.toolResult !== undefined) {\n\t\t\treturn result.toolResult;\n\t\t}\n\n\t\tif (result.content !== undefined) {\n\t\t\treturn result.content;\n\t\t}\n\n\t\treturn result;\n\t};\n\nexport function mcpToolToDynamicTool(\n\ttool: McpTool,\n\tonCallTool: DynamicStructuredToolInput['func'],\n): DynamicStructuredTool<z.ZodObject<any, any, any, any>> {\n\tconst rawSchema = convertJsonSchemaToZod(tool.inputSchema);\n\n\t// Ensure we always have an object schema for structured tools\n\tconst objectSchema =\n\t\trawSchema instanceof z.ZodObject ? rawSchema : z.object({ value: rawSchema });\n\n\treturn new DynamicStructuredTool({\n\t\tname: tool.name,\n\t\tdescription: tool.description ?? '',\n\t\tschema: objectSchema,\n\t\tfunc: onCallTool,\n\t\tmetadata: { isFromToolkit: true },\n\t});\n}\n\nexport class McpToolkit extends Toolkit {\n\tconstructor(public tools: Array<DynamicStructuredTool<z.ZodObject<any, any, any, any>>>) {\n\t\tsuper();\n\t}\n}\n\nfunction safeCreateUrl(url: string, baseUrl?: string | URL): Result<URL, Error> {\n\ttry {\n\t\treturn createResultOk(new URL(url, baseUrl));\n\t} catch (error) {\n\t\treturn createResultError(error);\n\t}\n}\n\nfunction normalizeAndValidateUrl(input: string): Result<URL, Error> {\n\tconst withProtocol = !/^https?:\\/\\//i.test(input) ? `https://${input}` : input;\n\tconst parsedUrl = safeCreateUrl(withProtocol);\n\n\tif (!parsedUrl.ok) {\n\t\treturn createResultError(parsedUrl.error);\n\t}\n\n\treturn parsedUrl;\n}\n\ntype ConnectMcpClientError =\n\t| { type: 'invalid_url'; error: Error }\n\t| { type: 'connection'; error: Error };\nexport async function connectMcpClient({\n\theaders,\n\tserverTransport,\n\tendpointUrl,\n\tname,\n\tversion,\n}: {\n\tserverTransport: McpServerTransport;\n\tendpointUrl: string;\n\theaders?: Record<string, string>;\n\tname: string;\n\tversion: number;\n}): Promise<Result<Client, ConnectMcpClientError>> {\n\tconst endpoint = normalizeAndValidateUrl(endpointUrl);\n\n\tif (!endpoint.ok) {\n\t\treturn createResultError({ type: 'invalid_url', error: endpoint.error });\n\t}\n\n\tconst client = new Client({ name, version: version.toString() }, { capabilities: { tools: {} } });\n\n\tif (serverTransport === 'httpStreamable') {\n\t\ttry {\n\t\t\tconst transport = new StreamableHTTPClientTransport(endpoint.result, {\n\t\t\t\trequestInit: { headers },\n\t\t\t});\n\t\t\tawait client.connect(transport);\n\t\t\treturn createResultOk(client);\n\t\t} catch (error) {\n\t\t\treturn createResultError({ type: 'connection', error });\n\t\t}\n\t}\n\n\ttry {\n\t\tconst sseTransport = new SSEClientTransport(endpoint.result, {\n\t\t\teventSourceInit: {\n\t\t\t\tfetch: async (url, init) =>\n\t\t\t\t\tawait fetch(url, {\n\t\t\t\t\t\t...init,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t...headers,\n\t\t\t\t\t\t\tAccept: 'text/event-stream',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\trequestInit: { headers },\n\t\t});\n\t\tawait client.connect(sseTransport);\n\t\treturn createResultOk(client);\n\t} catch (error) {\n\t\treturn createResultError({ type: 'connection', error });\n\t}\n}\n\nexport async function getAuthHeaders(\n\tctx: Pick<IExecuteFunctions, 'getCredentials'>,\n\tauthentication: McpAuthenticationOption,\n): Promise<{ headers?: Record<string, string> }> {\n\tswitch (authentication) {\n\t\tcase 'headerAuth': {\n\t\t\tconst header = await ctx\n\t\t\t\t.getCredentials<{ name: string; value: string }>('httpHeaderAuth')\n\t\t\t\t.catch(() => null);\n\n\t\t\tif (!header) return {};\n\n\t\t\treturn { headers: { [header.name]: header.value } };\n\t\t}\n\t\tcase 'bearerAuth': {\n\t\t\tconst result = await ctx\n\t\t\t\t.getCredentials<{ token: string }>('httpBearerAuth')\n\t\t\t\t.catch(() => null);\n\n\t\t\tif (!result) return {};\n\n\t\t\treturn { headers: { Authorization: `Bearer ${result.token}` } };\n\t\t}\n\t\tcase 'none':\n\t\tdefault: {\n\t\t\treturn {};\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/mcp/McpClientTool/utils.ts"],"sourcesContent":["import { DynamicStructuredTool, type DynamicStructuredToolInput } from '@langchain/core/tools';\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { CompatibilityCallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { convertJsonSchemaToZod } from '@utils/schemaParsing';\nimport { Toolkit } from 'langchain/agents';\nimport {\n\tcreateResultError,\n\tcreateResultOk,\n\ttype IDataObject,\n\ttype IExecuteFunctions,\n\ttype Result,\n} from 'n8n-workflow';\nimport { z } from 'zod';\n\nimport type {\n\tMcpAuthenticationOption,\n\tMcpServerTransport,\n\tMcpTool,\n\tMcpToolIncludeMode,\n} from './types';\n\nexport async function getAllTools(client: Client, cursor?: string): Promise<McpTool[]> {\n\tconst { tools, nextCursor } = await client.listTools({ cursor });\n\n\tif (nextCursor) {\n\t\treturn (tools as McpTool[]).concat(await getAllTools(client, nextCursor));\n\t}\n\n\treturn tools as McpTool[];\n}\n\nexport function getSelectedTools({\n\tmode,\n\tincludeTools,\n\texcludeTools,\n\ttools,\n}: {\n\tmode: McpToolIncludeMode;\n\tincludeTools?: string[];\n\texcludeTools?: string[];\n\ttools: McpTool[];\n}) {\n\tswitch (mode) {\n\t\tcase 'selected': {\n\t\t\tif (!includeTools?.length) return tools;\n\t\t\tconst include = new Set(includeTools);\n\t\t\treturn tools.filter((tool) => include.has(tool.name));\n\t\t}\n\t\tcase 'except': {\n\t\t\tconst except = new Set(excludeTools ?? []);\n\t\t\treturn tools.filter((tool) => !except.has(tool.name));\n\t\t}\n\t\tcase 'all':\n\t\tdefault:\n\t\t\treturn tools;\n\t}\n}\n\nexport const getErrorDescriptionFromToolCall = (result: unknown): string | undefined => {\n\tif (result && typeof result === 'object') {\n\t\tif ('content' in result && Array.isArray(result.content)) {\n\t\t\tconst errorMessage = (result.content as Array<{ type: 'text'; text: string }>).find(\n\t\t\t\t(content) => content && typeof content === 'object' && typeof content.text === 'string',\n\t\t\t)?.text;\n\t\t\treturn errorMessage;\n\t\t} else if ('toolResult' in result && typeof result.toolResult === 'string') {\n\t\t\treturn result.toolResult;\n\t\t}\n\t\tif ('message' in result && typeof result.message === 'string') {\n\t\t\treturn result.message;\n\t\t}\n\t}\n\n\treturn undefined;\n};\n\nexport const createCallTool =\n\t(name: string, client: Client, onError: (error: string) => void) => async (args: IDataObject) => {\n\t\tlet result: Awaited<ReturnType<Client['callTool']>>;\n\n\t\tfunction handleError(error: unknown) {\n\t\t\tconst errorDescription =\n\t\t\t\tgetErrorDescriptionFromToolCall(error) ?? `Failed to execute tool \"${name}\"`;\n\t\t\tonError(errorDescription);\n\t\t\treturn errorDescription;\n\t\t}\n\n\t\ttry {\n\t\t\tresult = await client.callTool({ name, arguments: args }, CompatibilityCallToolResultSchema);\n\t\t} catch (error) {\n\t\t\treturn handleError(error);\n\t\t}\n\n\t\tif (result.isError) {\n\t\t\treturn handleError(result);\n\t\t}\n\n\t\tif (result.toolResult !== undefined) {\n\t\t\treturn result.toolResult;\n\t\t}\n\n\t\tif (result.content !== undefined) {\n\t\t\treturn result.content;\n\t\t}\n\n\t\treturn result;\n\t};\n\nexport function mcpToolToDynamicTool(\n\ttool: McpTool,\n\tonCallTool: DynamicStructuredToolInput['func'],\n): DynamicStructuredTool {\n\tconst rawSchema = convertJsonSchemaToZod(tool.inputSchema);\n\n\t// Ensure we always have an object schema for structured tools\n\tconst objectSchema =\n\t\trawSchema instanceof z.ZodObject ? rawSchema : z.object({ value: rawSchema });\n\n\treturn new DynamicStructuredTool({\n\t\tname: tool.name,\n\t\tdescription: tool.description ?? '',\n\t\tschema: objectSchema,\n\t\tfunc: onCallTool,\n\t\tmetadata: { isFromToolkit: true },\n\t});\n}\n\nexport class McpToolkit extends Toolkit {\n\tconstructor(public tools: DynamicStructuredTool[]) {\n\t\tsuper();\n\t}\n}\n\nfunction safeCreateUrl(url: string, baseUrl?: string | URL): Result<URL, Error> {\n\ttry {\n\t\treturn createResultOk(new URL(url, baseUrl));\n\t} catch (error) {\n\t\treturn createResultError(error);\n\t}\n}\n\nfunction normalizeAndValidateUrl(input: string): Result<URL, Error> {\n\tconst withProtocol = !/^https?:\\/\\//i.test(input) ? `https://${input}` : input;\n\tconst parsedUrl = safeCreateUrl(withProtocol);\n\n\tif (!parsedUrl.ok) {\n\t\treturn createResultError(parsedUrl.error);\n\t}\n\n\treturn parsedUrl;\n}\n\ntype ConnectMcpClientError =\n\t| { type: 'invalid_url'; error: Error }\n\t| { type: 'connection'; error: Error };\nexport async function connectMcpClient({\n\theaders,\n\tserverTransport,\n\tendpointUrl,\n\tname,\n\tversion,\n}: {\n\tserverTransport: McpServerTransport;\n\tendpointUrl: string;\n\theaders?: Record<string, string>;\n\tname: string;\n\tversion: number;\n}): Promise<Result<Client, ConnectMcpClientError>> {\n\tconst endpoint = normalizeAndValidateUrl(endpointUrl);\n\n\tif (!endpoint.ok) {\n\t\treturn createResultError({ type: 'invalid_url', error: endpoint.error });\n\t}\n\n\tconst client = new Client({ name, version: version.toString() }, { capabilities: { tools: {} } });\n\n\tif (serverTransport === 'httpStreamable') {\n\t\ttry {\n\t\t\tconst transport = new StreamableHTTPClientTransport(endpoint.result, {\n\t\t\t\trequestInit: { headers },\n\t\t\t});\n\t\t\tawait client.connect(transport);\n\t\t\treturn createResultOk(client);\n\t\t} catch (error) {\n\t\t\treturn createResultError({ type: 'connection', error });\n\t\t}\n\t}\n\n\ttry {\n\t\tconst sseTransport = new SSEClientTransport(endpoint.result, {\n\t\t\teventSourceInit: {\n\t\t\t\tfetch: async (url, init) =>\n\t\t\t\t\tawait fetch(url, {\n\t\t\t\t\t\t...init,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t...headers,\n\t\t\t\t\t\t\tAccept: 'text/event-stream',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\trequestInit: { headers },\n\t\t});\n\t\tawait client.connect(sseTransport);\n\t\treturn createResultOk(client);\n\t} catch (error) {\n\t\treturn createResultError({ type: 'connection', error });\n\t}\n}\n\nexport async function getAuthHeaders(\n\tctx: Pick<IExecuteFunctions, 'getCredentials'>,\n\tauthentication: McpAuthenticationOption,\n): Promise<{ headers?: Record<string, string> }> {\n\tswitch (authentication) {\n\t\tcase 'headerAuth': {\n\t\t\tconst header = await ctx\n\t\t\t\t.getCredentials<{ name: string; value: string }>('httpHeaderAuth')\n\t\t\t\t.catch(() => null);\n\n\t\t\tif (!header) return {};\n\n\t\t\treturn { headers: { [header.name]: header.value } };\n\t\t}\n\t\tcase 'bearerAuth': {\n\t\t\tconst result = await ctx\n\t\t\t\t.getCredentials<{ token: string }>('httpBearerAuth')\n\t\t\t\t.catch(() => null);\n\n\t\t\tif (!result) return {};\n\n\t\t\treturn { headers: { Authorization: `Bearer ${result.token}` } };\n\t\t}\n\t\tcase 'none':\n\t\tdefault: {\n\t\t\treturn {};\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var Chat_node_exports = {};
|
|
20
|
+
__export(Chat_node_exports, {
|
|
21
|
+
Chat: () => Chat
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(Chat_node_exports);
|
|
24
|
+
var import_n8n_workflow = require("n8n-workflow");
|
|
25
|
+
var import_util = require("./util");
|
|
26
|
+
const limitWaitTimeProperties = [
|
|
27
|
+
{
|
|
28
|
+
displayName: "Limit Type",
|
|
29
|
+
name: "limitType",
|
|
30
|
+
type: "options",
|
|
31
|
+
default: "afterTimeInterval",
|
|
32
|
+
description: "Sets the condition for the execution to resume. Can be a specified date or after some time.",
|
|
33
|
+
options: [
|
|
34
|
+
{
|
|
35
|
+
name: "After Time Interval",
|
|
36
|
+
description: "Waits for a certain amount of time",
|
|
37
|
+
value: "afterTimeInterval"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "At Specified Time",
|
|
41
|
+
description: "Waits until the set date and time to continue",
|
|
42
|
+
value: "atSpecifiedTime"
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
displayName: "Amount",
|
|
48
|
+
name: "resumeAmount",
|
|
49
|
+
type: "number",
|
|
50
|
+
displayOptions: {
|
|
51
|
+
show: {
|
|
52
|
+
limitType: ["afterTimeInterval"]
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
typeOptions: {
|
|
56
|
+
minValue: 0,
|
|
57
|
+
numberPrecision: 2
|
|
58
|
+
},
|
|
59
|
+
default: 1,
|
|
60
|
+
description: "The time to wait"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
displayName: "Unit",
|
|
64
|
+
name: "resumeUnit",
|
|
65
|
+
type: "options",
|
|
66
|
+
displayOptions: {
|
|
67
|
+
show: {
|
|
68
|
+
limitType: ["afterTimeInterval"]
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
options: [
|
|
72
|
+
{
|
|
73
|
+
name: "Minutes",
|
|
74
|
+
value: "minutes"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "Hours",
|
|
78
|
+
value: "hours"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "Days",
|
|
82
|
+
value: "days"
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
default: "hours",
|
|
86
|
+
description: "Unit of the interval value"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
displayName: "Max Date and Time",
|
|
90
|
+
name: "maxDateAndTime",
|
|
91
|
+
type: "dateTime",
|
|
92
|
+
displayOptions: {
|
|
93
|
+
show: {
|
|
94
|
+
limitType: ["atSpecifiedTime"]
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
default: "",
|
|
98
|
+
description: "Continue execution after the specified date and time"
|
|
99
|
+
}
|
|
100
|
+
];
|
|
101
|
+
const limitWaitTimeOption = {
|
|
102
|
+
displayName: "Limit Wait Time",
|
|
103
|
+
name: "limitWaitTime",
|
|
104
|
+
type: "fixedCollection",
|
|
105
|
+
description: "Whether to limit the time this node should wait for a user response before execution resumes",
|
|
106
|
+
default: { values: { limitType: "afterTimeInterval", resumeAmount: 45, resumeUnit: "minutes" } },
|
|
107
|
+
options: [
|
|
108
|
+
{
|
|
109
|
+
displayName: "Values",
|
|
110
|
+
name: "values",
|
|
111
|
+
values: limitWaitTimeProperties
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
displayOptions: {
|
|
115
|
+
show: {
|
|
116
|
+
[`/${import_n8n_workflow.CHAT_WAIT_USER_REPLY}`]: [true]
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
class Chat {
|
|
121
|
+
constructor() {
|
|
122
|
+
this.description = {
|
|
123
|
+
displayName: "Respond to Chat",
|
|
124
|
+
name: "chat",
|
|
125
|
+
icon: "fa:comments",
|
|
126
|
+
iconColor: "black",
|
|
127
|
+
group: ["input"],
|
|
128
|
+
version: 1,
|
|
129
|
+
description: "Send a message to a chat",
|
|
130
|
+
defaults: {
|
|
131
|
+
name: "Respond to Chat"
|
|
132
|
+
},
|
|
133
|
+
codex: {
|
|
134
|
+
categories: ["Core Nodes", "HITL"],
|
|
135
|
+
subcategories: {
|
|
136
|
+
HITL: ["Human in the Loop"]
|
|
137
|
+
},
|
|
138
|
+
alias: ["human", "wait", "hitl"],
|
|
139
|
+
resources: {
|
|
140
|
+
primaryDocumentation: [
|
|
141
|
+
{
|
|
142
|
+
url: "https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-langchain.chat/"
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
inputs: `={{ (${import_util.configureInputs})($parameter) }}`,
|
|
148
|
+
outputs: [import_n8n_workflow.NodeConnectionTypes.Main],
|
|
149
|
+
properties: [
|
|
150
|
+
{
|
|
151
|
+
displayName: "Verify you're using a chat trigger with the 'Response Mode' option set to 'Using Response Nodes'",
|
|
152
|
+
name: "generalNotice",
|
|
153
|
+
type: "notice",
|
|
154
|
+
default: ""
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
displayName: "Message",
|
|
158
|
+
name: "message",
|
|
159
|
+
type: "string",
|
|
160
|
+
default: "",
|
|
161
|
+
required: true,
|
|
162
|
+
typeOptions: {
|
|
163
|
+
rows: 6
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
displayName: "Wait for User Reply",
|
|
168
|
+
name: import_n8n_workflow.CHAT_WAIT_USER_REPLY,
|
|
169
|
+
type: "boolean",
|
|
170
|
+
default: true
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
displayName: "Options",
|
|
174
|
+
name: "options",
|
|
175
|
+
type: "collection",
|
|
176
|
+
placeholder: "Add Option",
|
|
177
|
+
default: {},
|
|
178
|
+
options: [
|
|
179
|
+
{
|
|
180
|
+
displayName: "Add Memory Input Connection",
|
|
181
|
+
name: "memoryConnection",
|
|
182
|
+
type: "boolean",
|
|
183
|
+
default: false
|
|
184
|
+
},
|
|
185
|
+
limitWaitTimeOption
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
]
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
async onMessage(context, data) {
|
|
192
|
+
const options = context.getNodeParameter("options", 0, {});
|
|
193
|
+
const waitForReply = context.getNodeParameter(import_n8n_workflow.CHAT_WAIT_USER_REPLY, 0, true);
|
|
194
|
+
if (!waitForReply) {
|
|
195
|
+
const inputData = context.getInputData();
|
|
196
|
+
return [inputData];
|
|
197
|
+
}
|
|
198
|
+
if (options.memoryConnection) {
|
|
199
|
+
const memory = await context.getInputConnectionData(import_n8n_workflow.NodeConnectionTypes.AiMemory, 0);
|
|
200
|
+
const message = data.json?.chatInput;
|
|
201
|
+
if (memory && message) {
|
|
202
|
+
await memory.chatHistory.addUserMessage(message);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return [[data]];
|
|
206
|
+
}
|
|
207
|
+
async execute() {
|
|
208
|
+
const connectedNodes = this.getParentNodes(this.getNode().name, {
|
|
209
|
+
includeNodeParameters: true
|
|
210
|
+
});
|
|
211
|
+
const chatTrigger = connectedNodes.find(
|
|
212
|
+
(node) => node.type === import_n8n_workflow.CHAT_TRIGGER_NODE_TYPE && !node.disabled
|
|
213
|
+
);
|
|
214
|
+
if (!chatTrigger) {
|
|
215
|
+
throw new import_n8n_workflow.NodeOperationError(
|
|
216
|
+
this.getNode(),
|
|
217
|
+
"Workflow must be started from a chat trigger node"
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
const parameters = chatTrigger.parameters;
|
|
221
|
+
if (parameters.mode === "webhook") {
|
|
222
|
+
throw new import_n8n_workflow.NodeOperationError(
|
|
223
|
+
this.getNode(),
|
|
224
|
+
'"Embeded chat" is not supported, change the "Mode" in the chat trigger node to the "Hosted Chat"'
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
if (parameters.options.responseMode !== "responseNodes") {
|
|
228
|
+
throw new import_n8n_workflow.NodeOperationError(
|
|
229
|
+
this.getNode(),
|
|
230
|
+
'"Response Mode" in the chat trigger node must be set to "Respond Nodes"'
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
const message = this.getNodeParameter("message", 0) ?? "";
|
|
234
|
+
const options = this.getNodeParameter("options", 0, {});
|
|
235
|
+
if (options.memoryConnection) {
|
|
236
|
+
const memory = await this.getInputConnectionData(import_n8n_workflow.NodeConnectionTypes.AiMemory, 0);
|
|
237
|
+
if (memory) {
|
|
238
|
+
await memory.chatHistory.addAIChatMessage(message);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const waitTill = (0, import_util.configureWaitTillDate)(this);
|
|
242
|
+
await this.putExecutionToWait(waitTill);
|
|
243
|
+
return [[{ json: {}, sendMessage: message }]];
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
247
|
+
0 && (module.exports = {
|
|
248
|
+
Chat
|
|
249
|
+
});
|
|
250
|
+
//# sourceMappingURL=Chat.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/trigger/ChatTrigger/Chat.node.ts"],"sourcesContent":["/* eslint-disable n8n-nodes-base/node-dirname-against-convention */\nimport type { BaseChatMemory } from 'langchain/memory';\nimport {\n\tCHAT_TRIGGER_NODE_TYPE,\n\tCHAT_WAIT_USER_REPLY,\n\tNodeConnectionTypes,\n\tNodeOperationError,\n} from 'n8n-workflow';\nimport type {\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeTypeDescription,\n\tINodeType,\n\tINodeProperties,\n} from 'n8n-workflow';\n\nimport { configureInputs, configureWaitTillDate } from './util';\n\nconst limitWaitTimeProperties: INodeProperties[] = [\n\t{\n\t\tdisplayName: 'Limit Type',\n\t\tname: 'limitType',\n\t\ttype: 'options',\n\t\tdefault: 'afterTimeInterval',\n\t\tdescription:\n\t\t\t'Sets the condition for the execution to resume. Can be a specified date or after some time.',\n\t\toptions: [\n\t\t\t{\n\t\t\t\tname: 'After Time Interval',\n\t\t\t\tdescription: 'Waits for a certain amount of time',\n\t\t\t\tvalue: 'afterTimeInterval',\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'At Specified Time',\n\t\t\t\tdescription: 'Waits until the set date and time to continue',\n\t\t\t\tvalue: 'atSpecifiedTime',\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tdisplayName: 'Amount',\n\t\tname: 'resumeAmount',\n\t\ttype: 'number',\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\tlimitType: ['afterTimeInterval'],\n\t\t\t},\n\t\t},\n\t\ttypeOptions: {\n\t\t\tminValue: 0,\n\t\t\tnumberPrecision: 2,\n\t\t},\n\t\tdefault: 1,\n\t\tdescription: 'The time to wait',\n\t},\n\t{\n\t\tdisplayName: 'Unit',\n\t\tname: 'resumeUnit',\n\t\ttype: 'options',\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\tlimitType: ['afterTimeInterval'],\n\t\t\t},\n\t\t},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tname: 'Minutes',\n\t\t\t\tvalue: 'minutes',\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'Hours',\n\t\t\t\tvalue: 'hours',\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'Days',\n\t\t\t\tvalue: 'days',\n\t\t\t},\n\t\t],\n\t\tdefault: 'hours',\n\t\tdescription: 'Unit of the interval value',\n\t},\n\t{\n\t\tdisplayName: 'Max Date and Time',\n\t\tname: 'maxDateAndTime',\n\t\ttype: 'dateTime',\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\tlimitType: ['atSpecifiedTime'],\n\t\t\t},\n\t\t},\n\t\tdefault: '',\n\t\tdescription: 'Continue execution after the specified date and time',\n\t},\n];\n\nconst limitWaitTimeOption: INodeProperties = {\n\tdisplayName: 'Limit Wait Time',\n\tname: 'limitWaitTime',\n\ttype: 'fixedCollection',\n\tdescription:\n\t\t'Whether to limit the time this node should wait for a user response before execution resumes',\n\tdefault: { values: { limitType: 'afterTimeInterval', resumeAmount: 45, resumeUnit: 'minutes' } },\n\toptions: [\n\t\t{\n\t\t\tdisplayName: 'Values',\n\t\t\tname: 'values',\n\t\t\tvalues: limitWaitTimeProperties,\n\t\t},\n\t],\n\tdisplayOptions: {\n\t\tshow: {\n\t\t\t[`/${CHAT_WAIT_USER_REPLY}`]: [true],\n\t\t},\n\t},\n};\n\nexport class Chat implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Respond to Chat',\n\t\tname: 'chat',\n\t\ticon: 'fa:comments',\n\t\ticonColor: 'black',\n\t\tgroup: ['input'],\n\t\tversion: 1,\n\t\tdescription: 'Send a message to a chat',\n\t\tdefaults: {\n\t\t\tname: 'Respond to Chat',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['Core Nodes', 'HITL'],\n\t\t\tsubcategories: {\n\t\t\t\tHITL: ['Human in the Loop'],\n\t\t\t},\n\t\t\talias: ['human', 'wait', 'hitl'],\n\t\t\tresources: {\n\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t{\n\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-langchain.chat/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\tinputs: `={{ (${configureInputs})($parameter) }}`,\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName:\n\t\t\t\t\t\"Verify you're using a chat trigger with the 'Response Mode' option set to 'Using Response Nodes'\",\n\t\t\t\tname: 'generalNotice',\n\t\t\t\ttype: 'notice',\n\t\t\t\tdefault: '',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Message',\n\t\t\t\tname: 'message',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\ttypeOptions: {\n\t\t\t\t\trows: 6,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Wait for User Reply',\n\t\t\t\tname: CHAT_WAIT_USER_REPLY,\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'collection',\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Add Memory Input Connection',\n\t\t\t\t\t\tname: 'memoryConnection',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t},\n\t\t\t\t\tlimitWaitTimeOption,\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tasync onMessage(\n\t\tcontext: IExecuteFunctions,\n\t\tdata: INodeExecutionData,\n\t): Promise<INodeExecutionData[][]> {\n\t\tconst options = context.getNodeParameter('options', 0, {}) as {\n\t\t\tmemoryConnection?: boolean;\n\t\t};\n\n\t\tconst waitForReply = context.getNodeParameter(CHAT_WAIT_USER_REPLY, 0, true) as boolean;\n\n\t\tif (!waitForReply) {\n\t\t\tconst inputData = context.getInputData();\n\t\t\treturn [inputData];\n\t\t}\n\n\t\tif (options.memoryConnection) {\n\t\t\tconst memory = (await context.getInputConnectionData(NodeConnectionTypes.AiMemory, 0)) as\n\t\t\t\t| BaseChatMemory\n\t\t\t\t| undefined;\n\n\t\t\tconst message = data.json?.chatInput;\n\n\t\t\tif (memory && message) {\n\t\t\t\tawait memory.chatHistory.addUserMessage(message as string);\n\t\t\t}\n\t\t}\n\n\t\treturn [[data]];\n\t}\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tconst connectedNodes = this.getParentNodes(this.getNode().name, {\n\t\t\tincludeNodeParameters: true,\n\t\t});\n\n\t\tconst chatTrigger = connectedNodes.find(\n\t\t\t(node) => node.type === CHAT_TRIGGER_NODE_TYPE && !node.disabled,\n\t\t);\n\n\t\tif (!chatTrigger) {\n\t\t\tthrow new NodeOperationError(\n\t\t\t\tthis.getNode(),\n\t\t\t\t'Workflow must be started from a chat trigger node',\n\t\t\t);\n\t\t}\n\n\t\tconst parameters = chatTrigger.parameters as {\n\t\t\tmode?: 'hostedChat' | 'webhook';\n\t\t\toptions: { responseMode: 'lastNode' | 'responseNodes' | 'streaming' | 'responseNode' };\n\t\t};\n\n\t\tif (parameters.mode === 'webhook') {\n\t\t\tthrow new NodeOperationError(\n\t\t\t\tthis.getNode(),\n\t\t\t\t'\"Embeded chat\" is not supported, change the \"Mode\" in the chat trigger node to the \"Hosted Chat\"',\n\t\t\t);\n\t\t}\n\n\t\tif (parameters.options.responseMode !== 'responseNodes') {\n\t\t\tthrow new NodeOperationError(\n\t\t\t\tthis.getNode(),\n\t\t\t\t'\"Response Mode\" in the chat trigger node must be set to \"Respond Nodes\"',\n\t\t\t);\n\t\t}\n\n\t\tconst message = (this.getNodeParameter('message', 0) as string) ?? '';\n\t\tconst options = this.getNodeParameter('options', 0, {}) as {\n\t\t\tmemoryConnection?: boolean;\n\t\t};\n\n\t\tif (options.memoryConnection) {\n\t\t\tconst memory = (await this.getInputConnectionData(NodeConnectionTypes.AiMemory, 0)) as\n\t\t\t\t| BaseChatMemory\n\t\t\t\t| undefined;\n\n\t\t\tif (memory) {\n\t\t\t\tawait memory.chatHistory.addAIChatMessage(message);\n\t\t\t}\n\t\t}\n\n\t\tconst waitTill = configureWaitTillDate(this);\n\n\t\tawait this.putExecutionToWait(waitTill);\n\t\treturn [[{ json: {}, sendMessage: message }]];\n\t}\n}\n"],"mappings":"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","names":[]}
|