@n8n/n8n-nodes-langchain 1.97.1 → 1.98.1

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.
@@ -271,8 +271,8 @@ class AgentV1 {
271
271
  properties: [
272
272
  {
273
273
  displayName: 'Tip: Get a feel for agents with our quick <a href="https://docs.n8n.io/advanced-ai/intro-tutorial/" target="_blank">tutorial</a> or see an <a href="/templates/1954" target="_blank">example</a> of how this node works',
274
- name: "notice_tip",
275
- type: "notice",
274
+ name: "aiAgentStarterCallout",
275
+ type: "callout",
276
276
  default: "",
277
277
  displayOptions: {
278
278
  show: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../nodes/agents/Agent/V1/AgentV1.node.ts"],"sourcesContent":["import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';\nimport type {\n\tINodeInputConfiguration,\n\tINodeInputFilter,\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeDescription,\n\tINodeProperties,\n\tNodeConnectionType,\n\tINodeTypeBaseDescription,\n} from 'n8n-workflow';\n\nimport { promptTypeOptions, textFromPreviousNode, textInput } from '@utils/descriptions';\n\nimport { conversationalAgentProperties } from '../agents/ConversationalAgent/description';\nimport { conversationalAgentExecute } from '../agents/ConversationalAgent/execute';\nimport { openAiFunctionsAgentProperties } from '../agents/OpenAiFunctionsAgent/description';\nimport { openAiFunctionsAgentExecute } from '../agents/OpenAiFunctionsAgent/execute';\nimport { planAndExecuteAgentProperties } from '../agents/PlanAndExecuteAgent/description';\nimport { planAndExecuteAgentExecute } from '../agents/PlanAndExecuteAgent/execute';\nimport { reActAgentAgentProperties } from '../agents/ReActAgent/description';\nimport { reActAgentAgentExecute } from '../agents/ReActAgent/execute';\nimport { sqlAgentAgentProperties } from '../agents/SqlAgent/description';\nimport { sqlAgentAgentExecute } from '../agents/SqlAgent/execute';\nimport { toolsAgentProperties } from '../agents/ToolsAgent/V1/description';\nimport { toolsAgentExecute } from '../agents/ToolsAgent/V1/execute';\n\n// Function used in the inputs expression to figure out which inputs to\n// display based on the agent type\nfunction getInputs(\n\tagent:\n\t\t| 'toolsAgent'\n\t\t| 'conversationalAgent'\n\t\t| 'openAiFunctionsAgent'\n\t\t| 'planAndExecuteAgent'\n\t\t| 'reActAgent'\n\t\t| 'sqlAgent',\n\thasOutputParser?: boolean,\n): Array<NodeConnectionType | INodeInputConfiguration> {\n\tinterface SpecialInput {\n\t\ttype: NodeConnectionType;\n\t\tfilter?: INodeInputFilter;\n\t\trequired?: boolean;\n\t}\n\n\tconst getInputData = (\n\t\tinputs: SpecialInput[],\n\t): Array<NodeConnectionType | INodeInputConfiguration> => {\n\t\tconst displayNames: { [key: string]: string } = {\n\t\t\tai_languageModel: 'Model',\n\t\t\tai_memory: 'Memory',\n\t\t\tai_tool: 'Tool',\n\t\t\tai_outputParser: 'Output Parser',\n\t\t};\n\n\t\treturn inputs.map(({ type, filter }) => {\n\t\t\tconst isModelType = type === ('ai_languageModel' as NodeConnectionType);\n\t\t\tlet displayName = type in displayNames ? displayNames[type] : undefined;\n\t\t\tif (\n\t\t\t\tisModelType &&\n\t\t\t\t['openAiFunctionsAgent', 'toolsAgent', 'conversationalAgent'].includes(agent)\n\t\t\t) {\n\t\t\t\tdisplayName = 'Chat Model';\n\t\t\t}\n\t\t\tconst input: INodeInputConfiguration = {\n\t\t\t\ttype,\n\t\t\t\tdisplayName,\n\t\t\t\trequired: isModelType,\n\t\t\t\tmaxConnections: ['ai_languageModel', 'ai_memory', 'ai_outputParser'].includes(\n\t\t\t\t\ttype as NodeConnectionType,\n\t\t\t\t)\n\t\t\t\t\t? 1\n\t\t\t\t\t: undefined,\n\t\t\t};\n\n\t\t\tif (filter) {\n\t\t\t\tinput.filter = filter;\n\t\t\t}\n\n\t\t\treturn input;\n\t\t});\n\t};\n\n\tlet specialInputs: SpecialInput[] = [];\n\n\tif (agent === 'conversationalAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t\tfilter: {\n\t\t\t\t\tnodes: [\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAnthropic',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAwsBedrock',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGroq',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOllama',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenAi',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleGemini',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatMistralCloud',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatDeepSeek',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenRouter',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatXAiGrok',\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_memory',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_tool',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_outputParser',\n\t\t\t},\n\t\t];\n\t} else if (agent === 'toolsAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t\tfilter: {\n\t\t\t\t\tnodes: [\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAnthropic',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAwsBedrock',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatMistralCloud',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOllama',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenAi',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGroq',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleGemini',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatDeepSeek',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenRouter',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatXAiGrok',\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_memory',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_tool',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_outputParser',\n\t\t\t},\n\t\t];\n\t} else if (agent === 'openAiFunctionsAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t\tfilter: {\n\t\t\t\t\tnodes: [\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenAi',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi',\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_memory',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_tool',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_outputParser',\n\t\t\t},\n\t\t];\n\t} else if (agent === 'reActAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_tool',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_outputParser',\n\t\t\t},\n\t\t];\n\t} else if (agent === 'sqlAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_memory',\n\t\t\t},\n\t\t];\n\t} else if (agent === 'planAndExecuteAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_tool',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_outputParser',\n\t\t\t},\n\t\t];\n\t}\n\n\tif (hasOutputParser === false) {\n\t\tspecialInputs = specialInputs.filter((input) => input.type !== 'ai_outputParser');\n\t}\n\treturn ['main', ...getInputData(specialInputs)];\n}\n\nconst agentTypeProperty: INodeProperties = {\n\tdisplayName: 'Agent',\n\tname: 'agent',\n\ttype: 'options',\n\tnoDataExpression: true,\n\t// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items\n\toptions: [\n\t\t{\n\t\t\tname: 'Tools Agent',\n\t\t\tvalue: 'toolsAgent',\n\t\t\tdescription:\n\t\t\t\t'Utilizes structured tool schemas for precise and reliable tool selection and execution. Recommended for complex tasks requiring accurate and consistent tool usage, but only usable with models that support tool calling.',\n\t\t},\n\t\t{\n\t\t\tname: 'Conversational Agent',\n\t\t\tvalue: 'conversationalAgent',\n\t\t\tdescription:\n\t\t\t\t'Describes tools in the system prompt and parses JSON responses for tool calls. More flexible but potentially less reliable than the Tools Agent. Suitable for simpler interactions or with models not supporting structured schemas.',\n\t\t},\n\t\t{\n\t\t\tname: 'OpenAI Functions Agent',\n\t\t\tvalue: 'openAiFunctionsAgent',\n\t\t\tdescription:\n\t\t\t\t\"Leverages OpenAI's function calling capabilities to precisely select and execute tools. Excellent for tasks requiring structured outputs when working with OpenAI models.\",\n\t\t},\n\t\t{\n\t\t\tname: 'Plan and Execute Agent',\n\t\t\tvalue: 'planAndExecuteAgent',\n\t\t\tdescription:\n\t\t\t\t'Creates a high-level plan for complex tasks and then executes each step. Suitable for multi-stage problems or when a strategic approach is needed.',\n\t\t},\n\t\t{\n\t\t\tname: 'ReAct Agent',\n\t\t\tvalue: 'reActAgent',\n\t\t\tdescription:\n\t\t\t\t'Combines reasoning and action in an iterative process. Effective for tasks that require careful analysis and step-by-step problem-solving.',\n\t\t},\n\t\t{\n\t\t\tname: 'SQL Agent',\n\t\t\tvalue: 'sqlAgent',\n\t\t\tdescription:\n\t\t\t\t'Specializes in interacting with SQL databases. Ideal for data analysis tasks, generating queries, or extracting insights from structured data.',\n\t\t},\n\t],\n\tdefault: '',\n};\n\nexport class AgentV1 implements INodeType {\n\tdescription: INodeTypeDescription;\n\n\tconstructor(baseDescription: INodeTypeBaseDescription) {\n\t\tthis.description = {\n\t\t\tversion: [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9],\n\t\t\t...baseDescription,\n\t\t\tdefaults: {\n\t\t\t\tname: 'AI Agent',\n\t\t\t\tcolor: '#404040',\n\t\t\t},\n\t\t\tinputs: `={{\n\t\t\t\t((agent, hasOutputParser) => {\n\t\t\t\t\t${getInputs.toString()};\n\t\t\t\t\treturn getInputs(agent, hasOutputParser)\n\t\t\t\t})($parameter.agent, $parameter.hasOutputParser === undefined || $parameter.hasOutputParser === true)\n\t\t\t}}`,\n\t\t\toutputs: [NodeConnectionTypes.Main],\n\t\t\tcredentials: [\n\t\t\t\t{\n\t\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-credentials-name-unsuffixed\n\t\t\t\t\tname: 'mySql',\n\t\t\t\t\trequired: true,\n\t\t\t\t\ttestedBy: 'mysqlConnectionTest',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t\t'/dataSource': ['mysql'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'postgres',\n\t\t\t\t\trequired: true,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t\t'/dataSource': ['postgres'],\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\tproperties: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName:\n\t\t\t\t\t\t'Tip: Get a feel for agents with our quick <a href=\"https://docs.n8n.io/advanced-ai/intro-tutorial/\" target=\"_blank\">tutorial</a> or see an <a href=\"/templates/1954\" target=\"_blank\">example</a> of how this node works',\n\t\t\t\t\tname: 'notice_tip',\n\t\t\t\t\ttype: 'notice',\n\t\t\t\t\tdefault: '',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tagent: ['conversationalAgent', 'toolsAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName:\n\t\t\t\t\t\t\"This node is using Agent that has been deprecated. Please switch to using 'Tools Agent' instead.\",\n\t\t\t\t\tname: 'deprecated',\n\t\t\t\t\ttype: 'notice',\n\t\t\t\t\tdefault: '',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tagent: [\n\t\t\t\t\t\t\t\t'conversationalAgent',\n\t\t\t\t\t\t\t\t'openAiFunctionsAgent',\n\t\t\t\t\t\t\t\t'planAndExecuteAgent',\n\t\t\t\t\t\t\t\t'reActAgent',\n\t\t\t\t\t\t\t\t'sqlAgent',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t// Make Conversational Agent the default agent for versions 1.5 and below\n\t\t\t\t{\n\t\t\t\t\t...agentTypeProperty,\n\t\t\t\t\toptions: agentTypeProperty?.options?.filter(\n\t\t\t\t\t\t(o) => 'value' in o && o.value !== 'toolsAgent',\n\t\t\t\t\t),\n\t\t\t\t\tdisplayOptions: { show: { '@version': [{ _cnd: { lte: 1.5 } }] } },\n\t\t\t\t\tdefault: 'conversationalAgent',\n\t\t\t\t},\n\t\t\t\t// Make Tools Agent the default agent for versions 1.6 and 1.7\n\t\t\t\t{\n\t\t\t\t\t...agentTypeProperty,\n\t\t\t\t\tdisplayOptions: { show: { '@version': [{ _cnd: { between: { from: 1.6, to: 1.7 } } }] } },\n\t\t\t\t\tdefault: 'toolsAgent',\n\t\t\t\t},\n\t\t\t\t// Make Tools Agent the only agent option for versions 1.8 and above\n\t\t\t\t{\n\t\t\t\t\t...agentTypeProperty,\n\t\t\t\t\ttype: 'hidden',\n\t\t\t\t\tdisplayOptions: { show: { '@version': [{ _cnd: { gte: 1.8 } }] } },\n\t\t\t\t\tdefault: 'toolsAgent',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t...promptTypeOptions,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t'@version': [{ _cnd: { lte: 1.2 } }],\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t...textFromPreviousNode,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: { promptType: ['auto'], '@version': [{ _cnd: { gte: 1.7 } }] },\n\t\t\t\t\t\t// SQL Agent has data source and credentials parameters so we need to include this input there manually\n\t\t\t\t\t\t// to preserve the order\n\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t...textInput,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tpromptType: ['define'],\n\t\t\t\t\t\t},\n\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName:\n\t\t\t\t\t\t'For more reliable structured output parsing, consider using the Tools agent',\n\t\t\t\t\tname: 'notice',\n\t\t\t\t\ttype: 'notice',\n\t\t\t\t\tdefault: '',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\thasOutputParser: [true],\n\t\t\t\t\t\t\tagent: [\n\t\t\t\t\t\t\t\t'conversationalAgent',\n\t\t\t\t\t\t\t\t'reActAgent',\n\t\t\t\t\t\t\t\t'planAndExecuteAgent',\n\t\t\t\t\t\t\t\t'openAiFunctionsAgent',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Require Specific Output Format',\n\t\t\t\t\tname: 'hasOutputParser',\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tnoDataExpression: true,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t'@version': [{ _cnd: { lte: 1.2 } }],\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: `Connect an <a data-action='openSelectiveNodeCreator' data-action-parameter-connectiontype='${NodeConnectionTypes.AiOutputParser}'>output parser</a> on the canvas to specify the output format you require`,\n\t\t\t\t\tname: 'notice',\n\t\t\t\t\ttype: 'notice',\n\t\t\t\t\tdefault: '',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\thasOutputParser: [true],\n\t\t\t\t\t\t\tagent: ['toolsAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\t...toolsAgentProperties,\n\t\t\t\t...conversationalAgentProperties,\n\t\t\t\t...openAiFunctionsAgentProperties,\n\t\t\t\t...reActAgentAgentProperties,\n\t\t\t\t...sqlAgentAgentProperties,\n\t\t\t\t...planAndExecuteAgentProperties,\n\t\t\t],\n\t\t};\n\t}\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tconst agentType = this.getNodeParameter('agent', 0, '') as string;\n\t\tconst nodeVersion = this.getNode().typeVersion;\n\n\t\tif (agentType === 'conversationalAgent') {\n\t\t\treturn await conversationalAgentExecute.call(this, nodeVersion);\n\t\t} else if (agentType === 'toolsAgent') {\n\t\t\treturn await toolsAgentExecute.call(this);\n\t\t} else if (agentType === 'openAiFunctionsAgent') {\n\t\t\treturn await openAiFunctionsAgentExecute.call(this, nodeVersion);\n\t\t} else if (agentType === 'reActAgent') {\n\t\t\treturn await reActAgentAgentExecute.call(this, nodeVersion);\n\t\t} else if (agentType === 'sqlAgent') {\n\t\t\treturn await sqlAgentAgentExecute.call(this);\n\t\t} else if (agentType === 'planAndExecuteAgent') {\n\t\t\treturn await planAndExecuteAgentExecute.call(this, nodeVersion);\n\t\t}\n\n\t\tthrow new NodeOperationError(this.getNode(), `The agent type \"${agentType}\" is not supported`);\n\t}\n}\n"],"mappings":"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","names":["import_description","import_execute"]}
1
+ {"version":3,"sources":["../../../../../nodes/agents/Agent/V1/AgentV1.node.ts"],"sourcesContent":["import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';\nimport type {\n\tINodeInputConfiguration,\n\tINodeInputFilter,\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeDescription,\n\tINodeProperties,\n\tNodeConnectionType,\n\tINodeTypeBaseDescription,\n} from 'n8n-workflow';\n\nimport { promptTypeOptions, textFromPreviousNode, textInput } from '@utils/descriptions';\n\nimport { conversationalAgentProperties } from '../agents/ConversationalAgent/description';\nimport { conversationalAgentExecute } from '../agents/ConversationalAgent/execute';\nimport { openAiFunctionsAgentProperties } from '../agents/OpenAiFunctionsAgent/description';\nimport { openAiFunctionsAgentExecute } from '../agents/OpenAiFunctionsAgent/execute';\nimport { planAndExecuteAgentProperties } from '../agents/PlanAndExecuteAgent/description';\nimport { planAndExecuteAgentExecute } from '../agents/PlanAndExecuteAgent/execute';\nimport { reActAgentAgentProperties } from '../agents/ReActAgent/description';\nimport { reActAgentAgentExecute } from '../agents/ReActAgent/execute';\nimport { sqlAgentAgentProperties } from '../agents/SqlAgent/description';\nimport { sqlAgentAgentExecute } from '../agents/SqlAgent/execute';\nimport { toolsAgentProperties } from '../agents/ToolsAgent/V1/description';\nimport { toolsAgentExecute } from '../agents/ToolsAgent/V1/execute';\n\n// Function used in the inputs expression to figure out which inputs to\n// display based on the agent type\nfunction getInputs(\n\tagent:\n\t\t| 'toolsAgent'\n\t\t| 'conversationalAgent'\n\t\t| 'openAiFunctionsAgent'\n\t\t| 'planAndExecuteAgent'\n\t\t| 'reActAgent'\n\t\t| 'sqlAgent',\n\thasOutputParser?: boolean,\n): Array<NodeConnectionType | INodeInputConfiguration> {\n\tinterface SpecialInput {\n\t\ttype: NodeConnectionType;\n\t\tfilter?: INodeInputFilter;\n\t\trequired?: boolean;\n\t}\n\n\tconst getInputData = (\n\t\tinputs: SpecialInput[],\n\t): Array<NodeConnectionType | INodeInputConfiguration> => {\n\t\tconst displayNames: { [key: string]: string } = {\n\t\t\tai_languageModel: 'Model',\n\t\t\tai_memory: 'Memory',\n\t\t\tai_tool: 'Tool',\n\t\t\tai_outputParser: 'Output Parser',\n\t\t};\n\n\t\treturn inputs.map(({ type, filter }) => {\n\t\t\tconst isModelType = type === ('ai_languageModel' as NodeConnectionType);\n\t\t\tlet displayName = type in displayNames ? displayNames[type] : undefined;\n\t\t\tif (\n\t\t\t\tisModelType &&\n\t\t\t\t['openAiFunctionsAgent', 'toolsAgent', 'conversationalAgent'].includes(agent)\n\t\t\t) {\n\t\t\t\tdisplayName = 'Chat Model';\n\t\t\t}\n\t\t\tconst input: INodeInputConfiguration = {\n\t\t\t\ttype,\n\t\t\t\tdisplayName,\n\t\t\t\trequired: isModelType,\n\t\t\t\tmaxConnections: ['ai_languageModel', 'ai_memory', 'ai_outputParser'].includes(\n\t\t\t\t\ttype as NodeConnectionType,\n\t\t\t\t)\n\t\t\t\t\t? 1\n\t\t\t\t\t: undefined,\n\t\t\t};\n\n\t\t\tif (filter) {\n\t\t\t\tinput.filter = filter;\n\t\t\t}\n\n\t\t\treturn input;\n\t\t});\n\t};\n\n\tlet specialInputs: SpecialInput[] = [];\n\n\tif (agent === 'conversationalAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t\tfilter: {\n\t\t\t\t\tnodes: [\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAnthropic',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAwsBedrock',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGroq',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOllama',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenAi',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleGemini',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatMistralCloud',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatDeepSeek',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenRouter',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatXAiGrok',\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_memory',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_tool',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_outputParser',\n\t\t\t},\n\t\t];\n\t} else if (agent === 'toolsAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t\tfilter: {\n\t\t\t\t\tnodes: [\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAnthropic',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAwsBedrock',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatMistralCloud',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOllama',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenAi',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGroq',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleGemini',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatDeepSeek',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenRouter',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatXAiGrok',\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_memory',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_tool',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_outputParser',\n\t\t\t},\n\t\t];\n\t} else if (agent === 'openAiFunctionsAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t\tfilter: {\n\t\t\t\t\tnodes: [\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenAi',\n\t\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi',\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_memory',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_tool',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_outputParser',\n\t\t\t},\n\t\t];\n\t} else if (agent === 'reActAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_tool',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_outputParser',\n\t\t\t},\n\t\t];\n\t} else if (agent === 'sqlAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_memory',\n\t\t\t},\n\t\t];\n\t} else if (agent === 'planAndExecuteAgent') {\n\t\tspecialInputs = [\n\t\t\t{\n\t\t\t\ttype: 'ai_languageModel',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_tool',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'ai_outputParser',\n\t\t\t},\n\t\t];\n\t}\n\n\tif (hasOutputParser === false) {\n\t\tspecialInputs = specialInputs.filter((input) => input.type !== 'ai_outputParser');\n\t}\n\treturn ['main', ...getInputData(specialInputs)];\n}\n\nconst agentTypeProperty: INodeProperties = {\n\tdisplayName: 'Agent',\n\tname: 'agent',\n\ttype: 'options',\n\tnoDataExpression: true,\n\t// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items\n\toptions: [\n\t\t{\n\t\t\tname: 'Tools Agent',\n\t\t\tvalue: 'toolsAgent',\n\t\t\tdescription:\n\t\t\t\t'Utilizes structured tool schemas for precise and reliable tool selection and execution. Recommended for complex tasks requiring accurate and consistent tool usage, but only usable with models that support tool calling.',\n\t\t},\n\t\t{\n\t\t\tname: 'Conversational Agent',\n\t\t\tvalue: 'conversationalAgent',\n\t\t\tdescription:\n\t\t\t\t'Describes tools in the system prompt and parses JSON responses for tool calls. More flexible but potentially less reliable than the Tools Agent. Suitable for simpler interactions or with models not supporting structured schemas.',\n\t\t},\n\t\t{\n\t\t\tname: 'OpenAI Functions Agent',\n\t\t\tvalue: 'openAiFunctionsAgent',\n\t\t\tdescription:\n\t\t\t\t\"Leverages OpenAI's function calling capabilities to precisely select and execute tools. Excellent for tasks requiring structured outputs when working with OpenAI models.\",\n\t\t},\n\t\t{\n\t\t\tname: 'Plan and Execute Agent',\n\t\t\tvalue: 'planAndExecuteAgent',\n\t\t\tdescription:\n\t\t\t\t'Creates a high-level plan for complex tasks and then executes each step. Suitable for multi-stage problems or when a strategic approach is needed.',\n\t\t},\n\t\t{\n\t\t\tname: 'ReAct Agent',\n\t\t\tvalue: 'reActAgent',\n\t\t\tdescription:\n\t\t\t\t'Combines reasoning and action in an iterative process. Effective for tasks that require careful analysis and step-by-step problem-solving.',\n\t\t},\n\t\t{\n\t\t\tname: 'SQL Agent',\n\t\t\tvalue: 'sqlAgent',\n\t\t\tdescription:\n\t\t\t\t'Specializes in interacting with SQL databases. Ideal for data analysis tasks, generating queries, or extracting insights from structured data.',\n\t\t},\n\t],\n\tdefault: '',\n};\n\nexport class AgentV1 implements INodeType {\n\tdescription: INodeTypeDescription;\n\n\tconstructor(baseDescription: INodeTypeBaseDescription) {\n\t\tthis.description = {\n\t\t\tversion: [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9],\n\t\t\t...baseDescription,\n\t\t\tdefaults: {\n\t\t\t\tname: 'AI Agent',\n\t\t\t\tcolor: '#404040',\n\t\t\t},\n\t\t\tinputs: `={{\n\t\t\t\t((agent, hasOutputParser) => {\n\t\t\t\t\t${getInputs.toString()};\n\t\t\t\t\treturn getInputs(agent, hasOutputParser)\n\t\t\t\t})($parameter.agent, $parameter.hasOutputParser === undefined || $parameter.hasOutputParser === true)\n\t\t\t}}`,\n\t\t\toutputs: [NodeConnectionTypes.Main],\n\t\t\tcredentials: [\n\t\t\t\t{\n\t\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-credentials-name-unsuffixed\n\t\t\t\t\tname: 'mySql',\n\t\t\t\t\trequired: true,\n\t\t\t\t\ttestedBy: 'mysqlConnectionTest',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t\t'/dataSource': ['mysql'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'postgres',\n\t\t\t\t\trequired: true,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t\t'/dataSource': ['postgres'],\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\tproperties: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName:\n\t\t\t\t\t\t'Tip: Get a feel for agents with our quick <a href=\"https://docs.n8n.io/advanced-ai/intro-tutorial/\" target=\"_blank\">tutorial</a> or see an <a href=\"/templates/1954\" target=\"_blank\">example</a> of how this node works',\n\t\t\t\t\tname: 'aiAgentStarterCallout',\n\t\t\t\t\ttype: 'callout',\n\t\t\t\t\tdefault: '',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tagent: ['conversationalAgent', 'toolsAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName:\n\t\t\t\t\t\t\"This node is using Agent that has been deprecated. Please switch to using 'Tools Agent' instead.\",\n\t\t\t\t\tname: 'deprecated',\n\t\t\t\t\ttype: 'notice',\n\t\t\t\t\tdefault: '',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tagent: [\n\t\t\t\t\t\t\t\t'conversationalAgent',\n\t\t\t\t\t\t\t\t'openAiFunctionsAgent',\n\t\t\t\t\t\t\t\t'planAndExecuteAgent',\n\t\t\t\t\t\t\t\t'reActAgent',\n\t\t\t\t\t\t\t\t'sqlAgent',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t// Make Conversational Agent the default agent for versions 1.5 and below\n\t\t\t\t{\n\t\t\t\t\t...agentTypeProperty,\n\t\t\t\t\toptions: agentTypeProperty?.options?.filter(\n\t\t\t\t\t\t(o) => 'value' in o && o.value !== 'toolsAgent',\n\t\t\t\t\t),\n\t\t\t\t\tdisplayOptions: { show: { '@version': [{ _cnd: { lte: 1.5 } }] } },\n\t\t\t\t\tdefault: 'conversationalAgent',\n\t\t\t\t},\n\t\t\t\t// Make Tools Agent the default agent for versions 1.6 and 1.7\n\t\t\t\t{\n\t\t\t\t\t...agentTypeProperty,\n\t\t\t\t\tdisplayOptions: { show: { '@version': [{ _cnd: { between: { from: 1.6, to: 1.7 } } }] } },\n\t\t\t\t\tdefault: 'toolsAgent',\n\t\t\t\t},\n\t\t\t\t// Make Tools Agent the only agent option for versions 1.8 and above\n\t\t\t\t{\n\t\t\t\t\t...agentTypeProperty,\n\t\t\t\t\ttype: 'hidden',\n\t\t\t\t\tdisplayOptions: { show: { '@version': [{ _cnd: { gte: 1.8 } }] } },\n\t\t\t\t\tdefault: 'toolsAgent',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t...promptTypeOptions,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t'@version': [{ _cnd: { lte: 1.2 } }],\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t...textFromPreviousNode,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: { promptType: ['auto'], '@version': [{ _cnd: { gte: 1.7 } }] },\n\t\t\t\t\t\t// SQL Agent has data source and credentials parameters so we need to include this input there manually\n\t\t\t\t\t\t// to preserve the order\n\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t...textInput,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tpromptType: ['define'],\n\t\t\t\t\t\t},\n\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName:\n\t\t\t\t\t\t'For more reliable structured output parsing, consider using the Tools agent',\n\t\t\t\t\tname: 'notice',\n\t\t\t\t\ttype: 'notice',\n\t\t\t\t\tdefault: '',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\thasOutputParser: [true],\n\t\t\t\t\t\t\tagent: [\n\t\t\t\t\t\t\t\t'conversationalAgent',\n\t\t\t\t\t\t\t\t'reActAgent',\n\t\t\t\t\t\t\t\t'planAndExecuteAgent',\n\t\t\t\t\t\t\t\t'openAiFunctionsAgent',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Require Specific Output Format',\n\t\t\t\t\tname: 'hasOutputParser',\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tnoDataExpression: true,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t'@version': [{ _cnd: { lte: 1.2 } }],\n\t\t\t\t\t\t\tagent: ['sqlAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: `Connect an <a data-action='openSelectiveNodeCreator' data-action-parameter-connectiontype='${NodeConnectionTypes.AiOutputParser}'>output parser</a> on the canvas to specify the output format you require`,\n\t\t\t\t\tname: 'notice',\n\t\t\t\t\ttype: 'notice',\n\t\t\t\t\tdefault: '',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\thasOutputParser: [true],\n\t\t\t\t\t\t\tagent: ['toolsAgent'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\t...toolsAgentProperties,\n\t\t\t\t...conversationalAgentProperties,\n\t\t\t\t...openAiFunctionsAgentProperties,\n\t\t\t\t...reActAgentAgentProperties,\n\t\t\t\t...sqlAgentAgentProperties,\n\t\t\t\t...planAndExecuteAgentProperties,\n\t\t\t],\n\t\t};\n\t}\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tconst agentType = this.getNodeParameter('agent', 0, '') as string;\n\t\tconst nodeVersion = this.getNode().typeVersion;\n\n\t\tif (agentType === 'conversationalAgent') {\n\t\t\treturn await conversationalAgentExecute.call(this, nodeVersion);\n\t\t} else if (agentType === 'toolsAgent') {\n\t\t\treturn await toolsAgentExecute.call(this);\n\t\t} else if (agentType === 'openAiFunctionsAgent') {\n\t\t\treturn await openAiFunctionsAgentExecute.call(this, nodeVersion);\n\t\t} else if (agentType === 'reActAgent') {\n\t\t\treturn await reActAgentAgentExecute.call(this, nodeVersion);\n\t\t} else if (agentType === 'sqlAgent') {\n\t\t\treturn await sqlAgentAgentExecute.call(this);\n\t\t} else if (agentType === 'planAndExecuteAgent') {\n\t\t\treturn await planAndExecuteAgentExecute.call(this, nodeVersion);\n\t\t}\n\n\t\tthrow new NodeOperationError(this.getNode(), `The agent type \"${agentType}\" is not supported`);\n\t}\n}\n"],"mappings":"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","names":["import_description","import_execute"]}
@@ -108,9 +108,9 @@ class AgentV2 {
108
108
  outputs: [import_n8n_workflow.NodeConnectionTypes.Main],
109
109
  properties: [
110
110
  {
111
- displayName: 'Tip: Get a feel for agents with our quick <a href="https://docs.n8n.io/advanced-ai/intro-tutorial/" target="_blank">tutorial</a> or see an <a href="/templates/1954" target="_blank">example</a> of how this node works',
112
- name: "notice_tip",
113
- type: "notice",
111
+ displayName: 'Tip: Get a feel for agents with our quick <a href="https://docs.n8n.io/advanced-ai/intro-tutorial/" target="_blank">tutorial</a> or see an <a href="/workflows/templates/1954" target="_blank">example</a> of how this node works',
112
+ name: "aiAgentStarterCallout",
113
+ type: "callout",
114
114
  default: ""
115
115
  },
116
116
  import_descriptions.promptTypeOptions,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../nodes/agents/Agent/V2/AgentV2.node.ts"],"sourcesContent":["import { NodeConnectionTypes } from 'n8n-workflow';\nimport type {\n\tINodeInputConfiguration,\n\tINodeInputFilter,\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeDescription,\n\tNodeConnectionType,\n\tINodeTypeBaseDescription,\n} from 'n8n-workflow';\n\nimport { promptTypeOptions, textFromPreviousNode, textInput } from '@utils/descriptions';\n\nimport { toolsAgentProperties } from '../agents/ToolsAgent/V2/description';\nimport { toolsAgentExecute } from '../agents/ToolsAgent/V2/execute';\n\n// Function used in the inputs expression to figure out which inputs to\n// display based on the agent type\nfunction getInputs(hasOutputParser?: boolean): Array<NodeConnectionType | INodeInputConfiguration> {\n\tinterface SpecialInput {\n\t\ttype: NodeConnectionType;\n\t\tfilter?: INodeInputFilter;\n\t\trequired?: boolean;\n\t}\n\n\tconst getInputData = (\n\t\tinputs: SpecialInput[],\n\t): Array<NodeConnectionType | INodeInputConfiguration> => {\n\t\tconst displayNames: { [key: string]: string } = {\n\t\t\tai_languageModel: 'Model',\n\t\t\tai_memory: 'Memory',\n\t\t\tai_tool: 'Tool',\n\t\t\tai_outputParser: 'Output Parser',\n\t\t};\n\n\t\treturn inputs.map(({ type, filter }) => {\n\t\t\tconst isModelType = type === 'ai_languageModel';\n\t\t\tlet displayName = type in displayNames ? displayNames[type] : undefined;\n\t\t\tif (isModelType) {\n\t\t\t\tdisplayName = 'Chat Model';\n\t\t\t}\n\t\t\tconst input: INodeInputConfiguration = {\n\t\t\t\ttype,\n\t\t\t\tdisplayName,\n\t\t\t\trequired: isModelType,\n\t\t\t\tmaxConnections: ['ai_languageModel', 'ai_memory', 'ai_outputParser'].includes(\n\t\t\t\t\ttype as NodeConnectionType,\n\t\t\t\t)\n\t\t\t\t\t? 1\n\t\t\t\t\t: undefined,\n\t\t\t};\n\n\t\t\tif (filter) {\n\t\t\t\tinput.filter = filter;\n\t\t\t}\n\n\t\t\treturn input;\n\t\t});\n\t};\n\n\tlet specialInputs: SpecialInput[] = [\n\t\t{\n\t\t\ttype: 'ai_languageModel',\n\t\t\tfilter: {\n\t\t\t\tnodes: [\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAnthropic',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAwsBedrock',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatMistralCloud',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOllama',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenAi',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGroq',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleGemini',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatDeepSeek',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenRouter',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatXAiGrok',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.code',\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\ttype: 'ai_memory',\n\t\t},\n\t\t{\n\t\t\ttype: 'ai_tool',\n\t\t\trequired: true,\n\t\t},\n\t\t{\n\t\t\ttype: 'ai_outputParser',\n\t\t},\n\t];\n\n\tif (hasOutputParser === false) {\n\t\tspecialInputs = specialInputs.filter((input) => input.type !== 'ai_outputParser');\n\t}\n\treturn ['main', ...getInputData(specialInputs)];\n}\n\nexport class AgentV2 implements INodeType {\n\tdescription: INodeTypeDescription;\n\n\tconstructor(baseDescription: INodeTypeBaseDescription) {\n\t\tthis.description = {\n\t\t\t...baseDescription,\n\t\t\tversion: 2,\n\t\t\tdefaults: {\n\t\t\t\tname: 'AI Agent',\n\t\t\t\tcolor: '#404040',\n\t\t\t},\n\t\t\tinputs: `={{\n\t\t\t\t((hasOutputParser) => {\n\t\t\t\t\t${getInputs.toString()};\n\t\t\t\t\treturn getInputs(hasOutputParser)\n\t\t\t\t})($parameter.hasOutputParser === undefined || $parameter.hasOutputParser === true)\n\t\t\t}}`,\n\t\t\toutputs: [NodeConnectionTypes.Main],\n\t\t\tproperties: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName:\n\t\t\t\t\t\t'Tip: Get a feel for agents with our quick <a href=\"https://docs.n8n.io/advanced-ai/intro-tutorial/\" target=\"_blank\">tutorial</a> or see an <a href=\"/templates/1954\" target=\"_blank\">example</a> of how this node works',\n\t\t\t\t\tname: 'notice_tip',\n\t\t\t\t\ttype: 'notice',\n\t\t\t\t\tdefault: '',\n\t\t\t\t},\n\t\t\t\tpromptTypeOptions,\n\t\t\t\t{\n\t\t\t\t\t...textFromPreviousNode,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tpromptType: ['auto'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t...textInput,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tpromptType: ['define'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Require Specific Output Format',\n\t\t\t\t\tname: 'hasOutputParser',\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tnoDataExpression: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: `Connect an <a data-action='openSelectiveNodeCreator' data-action-parameter-connectiontype='${NodeConnectionTypes.AiOutputParser}'>output parser</a> on the canvas to specify the output format you require`,\n\t\t\t\t\tname: 'notice',\n\t\t\t\t\ttype: 'notice',\n\t\t\t\t\tdefault: '',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\thasOutputParser: [true],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t...toolsAgentProperties,\n\t\t\t],\n\t\t};\n\t}\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\treturn await toolsAgentExecute.call(this);\n\t}\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../nodes/agents/Agent/V2/AgentV2.node.ts"],"sourcesContent":["import { NodeConnectionTypes } from 'n8n-workflow';\nimport type {\n\tINodeInputConfiguration,\n\tINodeInputFilter,\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeDescription,\n\tNodeConnectionType,\n\tINodeTypeBaseDescription,\n} from 'n8n-workflow';\n\nimport { promptTypeOptions, textFromPreviousNode, textInput } from '@utils/descriptions';\n\nimport { toolsAgentProperties } from '../agents/ToolsAgent/V2/description';\nimport { toolsAgentExecute } from '../agents/ToolsAgent/V2/execute';\n\n// Function used in the inputs expression to figure out which inputs to\n// display based on the agent type\nfunction getInputs(hasOutputParser?: boolean): Array<NodeConnectionType | INodeInputConfiguration> {\n\tinterface SpecialInput {\n\t\ttype: NodeConnectionType;\n\t\tfilter?: INodeInputFilter;\n\t\trequired?: boolean;\n\t}\n\n\tconst getInputData = (\n\t\tinputs: SpecialInput[],\n\t): Array<NodeConnectionType | INodeInputConfiguration> => {\n\t\tconst displayNames: { [key: string]: string } = {\n\t\t\tai_languageModel: 'Model',\n\t\t\tai_memory: 'Memory',\n\t\t\tai_tool: 'Tool',\n\t\t\tai_outputParser: 'Output Parser',\n\t\t};\n\n\t\treturn inputs.map(({ type, filter }) => {\n\t\t\tconst isModelType = type === 'ai_languageModel';\n\t\t\tlet displayName = type in displayNames ? displayNames[type] : undefined;\n\t\t\tif (isModelType) {\n\t\t\t\tdisplayName = 'Chat Model';\n\t\t\t}\n\t\t\tconst input: INodeInputConfiguration = {\n\t\t\t\ttype,\n\t\t\t\tdisplayName,\n\t\t\t\trequired: isModelType,\n\t\t\t\tmaxConnections: ['ai_languageModel', 'ai_memory', 'ai_outputParser'].includes(\n\t\t\t\t\ttype as NodeConnectionType,\n\t\t\t\t)\n\t\t\t\t\t? 1\n\t\t\t\t\t: undefined,\n\t\t\t};\n\n\t\t\tif (filter) {\n\t\t\t\tinput.filter = filter;\n\t\t\t}\n\n\t\t\treturn input;\n\t\t});\n\t};\n\n\tlet specialInputs: SpecialInput[] = [\n\t\t{\n\t\t\ttype: 'ai_languageModel',\n\t\t\tfilter: {\n\t\t\t\tnodes: [\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAnthropic',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatAwsBedrock',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatMistralCloud',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOllama',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenAi',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGroq',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatGoogleGemini',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatDeepSeek',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatOpenRouter',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.lmChatXAiGrok',\n\t\t\t\t\t'@n8n/n8n-nodes-langchain.code',\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\ttype: 'ai_memory',\n\t\t},\n\t\t{\n\t\t\ttype: 'ai_tool',\n\t\t\trequired: true,\n\t\t},\n\t\t{\n\t\t\ttype: 'ai_outputParser',\n\t\t},\n\t];\n\n\tif (hasOutputParser === false) {\n\t\tspecialInputs = specialInputs.filter((input) => input.type !== 'ai_outputParser');\n\t}\n\treturn ['main', ...getInputData(specialInputs)];\n}\n\nexport class AgentV2 implements INodeType {\n\tdescription: INodeTypeDescription;\n\n\tconstructor(baseDescription: INodeTypeBaseDescription) {\n\t\tthis.description = {\n\t\t\t...baseDescription,\n\t\t\tversion: 2,\n\t\t\tdefaults: {\n\t\t\t\tname: 'AI Agent',\n\t\t\t\tcolor: '#404040',\n\t\t\t},\n\t\t\tinputs: `={{\n\t\t\t\t((hasOutputParser) => {\n\t\t\t\t\t${getInputs.toString()};\n\t\t\t\t\treturn getInputs(hasOutputParser)\n\t\t\t\t})($parameter.hasOutputParser === undefined || $parameter.hasOutputParser === true)\n\t\t\t}}`,\n\t\t\toutputs: [NodeConnectionTypes.Main],\n\t\t\tproperties: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName:\n\t\t\t\t\t\t'Tip: Get a feel for agents with our quick <a href=\"https://docs.n8n.io/advanced-ai/intro-tutorial/\" target=\"_blank\">tutorial</a> or see an <a href=\"/workflows/templates/1954\" target=\"_blank\">example</a> of how this node works',\n\t\t\t\t\tname: 'aiAgentStarterCallout',\n\t\t\t\t\ttype: 'callout',\n\t\t\t\t\tdefault: '',\n\t\t\t\t},\n\t\t\t\tpromptTypeOptions,\n\t\t\t\t{\n\t\t\t\t\t...textFromPreviousNode,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tpromptType: ['auto'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t...textInput,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\tpromptType: ['define'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Require Specific Output Format',\n\t\t\t\t\tname: 'hasOutputParser',\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tnoDataExpression: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: `Connect an <a data-action='openSelectiveNodeCreator' data-action-parameter-connectiontype='${NodeConnectionTypes.AiOutputParser}'>output parser</a> on the canvas to specify the output format you require`,\n\t\t\t\t\tname: 'notice',\n\t\t\t\t\ttype: 'notice',\n\t\t\t\t\tdefault: '',\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\thasOutputParser: [true],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t...toolsAgentProperties,\n\t\t\t],\n\t\t};\n\t}\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\treturn await toolsAgentExecute.call(this);\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -16,12 +16,14 @@ var __copyProps = (to, from, except, desc) => {
16
16
  return to;
17
17
  };
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var FlushingSSEServerTransport_exports = {};
20
- __export(FlushingSSEServerTransport_exports, {
21
- FlushingSSEServerTransport: () => FlushingSSEServerTransport
19
+ var FlushingTransport_exports = {};
20
+ __export(FlushingTransport_exports, {
21
+ FlushingSSEServerTransport: () => FlushingSSEServerTransport,
22
+ FlushingStreamableHTTPTransport: () => FlushingStreamableHTTPTransport
22
23
  });
23
- module.exports = __toCommonJS(FlushingSSEServerTransport_exports);
24
+ module.exports = __toCommonJS(FlushingTransport_exports);
24
25
  var import_sse = require("@modelcontextprotocol/sdk/server/sse.js");
26
+ var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
25
27
  class FlushingSSEServerTransport extends import_sse.SSEServerTransport {
26
28
  constructor(_endpoint, response) {
27
29
  super(_endpoint, response);
@@ -31,9 +33,28 @@ class FlushingSSEServerTransport extends import_sse.SSEServerTransport {
31
33
  await super.send(message);
32
34
  this.response.flush();
33
35
  }
36
+ async handleRequest(req, resp, message) {
37
+ await super.handlePostMessage(req, resp, message);
38
+ this.response.flush();
39
+ }
40
+ }
41
+ class FlushingStreamableHTTPTransport extends import_streamableHttp.StreamableHTTPServerTransport {
42
+ constructor(options, response) {
43
+ super(options);
44
+ this.response = response;
45
+ }
46
+ async send(message) {
47
+ await super.send(message);
48
+ this.response.flush();
49
+ }
50
+ async handleRequest(req, resp, parsedBody) {
51
+ await super.handleRequest(req, resp, parsedBody);
52
+ this.response.flush();
53
+ }
34
54
  }
35
55
  // Annotate the CommonJS export names for ESM import in node:
36
56
  0 && (module.exports = {
37
- FlushingSSEServerTransport
57
+ FlushingSSEServerTransport,
58
+ FlushingStreamableHTTPTransport
38
59
  });
39
- //# sourceMappingURL=FlushingSSEServerTransport.js.map
60
+ //# sourceMappingURL=FlushingTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../nodes/mcp/McpTrigger/FlushingTransport.ts"],"sourcesContent":["import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport type { StreamableHTTPServerTransportOptions } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport type { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';\nimport type { Response } from 'express';\nimport type { IncomingMessage, ServerResponse } from 'http';\n\nexport type CompressionResponse = Response & {\n\t/**\n\t * `flush()` is defined in the compression middleware.\n\t * This is necessary because the compression middleware sometimes waits\n\t * for a certain amount of data before sending the data to the client\n\t */\n\tflush: () => void;\n};\n\nexport class FlushingSSEServerTransport extends SSEServerTransport {\n\tconstructor(\n\t\t_endpoint: string,\n\t\tprivate response: CompressionResponse,\n\t) {\n\t\tsuper(_endpoint, response);\n\t}\n\n\tasync send(message: JSONRPCMessage): Promise<void> {\n\t\tawait super.send(message);\n\t\tthis.response.flush();\n\t}\n\n\tasync handleRequest(\n\t\treq: IncomingMessage,\n\t\tresp: ServerResponse,\n\t\tmessage: IncomingMessage,\n\t): Promise<void> {\n\t\tawait super.handlePostMessage(req, resp, message);\n\t\tthis.response.flush();\n\t}\n}\n\nexport class FlushingStreamableHTTPTransport extends StreamableHTTPServerTransport {\n\tprivate response: CompressionResponse;\n\n\tconstructor(options: StreamableHTTPServerTransportOptions, response: CompressionResponse) {\n\t\tsuper(options);\n\t\tthis.response = response;\n\t}\n\n\tasync send(message: JSONRPCMessage): Promise<void> {\n\t\tawait super.send(message);\n\t\tthis.response.flush();\n\t}\n\n\tasync handleRequest(\n\t\treq: IncomingMessage,\n\t\tresp: ServerResponse,\n\t\tparsedBody?: unknown,\n\t): Promise<void> {\n\t\tawait super.handleRequest(req, resp, parsedBody);\n\t\tthis.response.flush();\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAmC;AACnC,4BAA8C;AAevC,MAAM,mCAAmC,8BAAmB;AAAA,EAClE,YACC,WACQ,UACP;AACD,UAAM,WAAW,QAAQ;AAFjB;AAAA,EAGT;AAAA,EAEA,MAAM,KAAK,SAAwC;AAClD,UAAM,MAAM,KAAK,OAAO;AACxB,SAAK,SAAS,MAAM;AAAA,EACrB;AAAA,EAEA,MAAM,cACL,KACA,MACA,SACgB;AAChB,UAAM,MAAM,kBAAkB,KAAK,MAAM,OAAO;AAChD,SAAK,SAAS,MAAM;AAAA,EACrB;AACD;AAEO,MAAM,wCAAwC,oDAA8B;AAAA,EAGlF,YAAY,SAA+C,UAA+B;AACzF,UAAM,OAAO;AACb,SAAK,WAAW;AAAA,EACjB;AAAA,EAEA,MAAM,KAAK,SAAwC;AAClD,UAAM,MAAM,KAAK,OAAO;AACxB,SAAK,SAAS,MAAM;AAAA,EACrB;AAAA,EAEA,MAAM,cACL,KACA,MACA,YACgB;AAChB,UAAM,MAAM,cAAc,KAAK,MAAM,UAAU;AAC/C,SAAK,SAAS,MAAM;AAAA,EACrB;AACD;","names":[]}
@@ -30,9 +30,10 @@ __export(McpServer_exports, {
30
30
  module.exports = __toCommonJS(McpServer_exports);
31
31
  var import_server = require("@modelcontextprotocol/sdk/server/index.js");
32
32
  var import_types = require("@modelcontextprotocol/sdk/types.js");
33
+ var import_crypto = require("crypto");
33
34
  var import_n8n_workflow = require("n8n-workflow");
34
35
  var import_zod_to_json_schema = require("zod-to-json-schema");
35
- var import_FlushingSSEServerTransport = require("./FlushingSSEServerTransport");
36
+ var import_FlushingTransport = require("./FlushingTransport");
36
37
  var _instance;
37
38
  function wasToolCall(body) {
38
39
  try {
@@ -43,9 +44,8 @@ function wasToolCall(body) {
43
44
  return false;
44
45
  }
45
46
  }
46
- function getRequestId(body) {
47
+ function getRequestId(message) {
47
48
  try {
48
- const message = JSON.parse(body);
49
49
  const parsedMessage = import_types.JSONRPCMessageSchema.parse(message);
50
50
  return "id" in parsedMessage ? String(parsedMessage.id) : void 0;
51
51
  } catch {
@@ -68,19 +68,21 @@ const _McpServerManager = class _McpServerManager {
68
68
  }
69
69
  return __privateGet(_McpServerManager, _instance);
70
70
  }
71
- async createServerAndTransport(serverName, postUrl, resp) {
72
- const transport = new import_FlushingSSEServerTransport.FlushingSSEServerTransport(postUrl, resp);
71
+ async createServerWithSSETransport(serverName, postUrl, resp) {
73
72
  const server = new import_server.Server(
74
73
  {
75
74
  name: serverName,
76
75
  version: "0.1.0"
77
76
  },
78
77
  {
79
- capabilities: { tools: {} }
78
+ capabilities: {
79
+ tools: {}
80
+ }
80
81
  }
81
82
  );
83
+ const transport = new import_FlushingTransport.FlushingSSEServerTransport(postUrl, resp);
82
84
  this.setUpHandlers(server);
83
- const { sessionId } = transport;
85
+ const sessionId = transport.sessionId;
84
86
  this.transports[sessionId] = transport;
85
87
  this.servers[sessionId] = server;
86
88
  resp.on("close", async () => {
@@ -94,18 +96,60 @@ const _McpServerManager = class _McpServerManager {
94
96
  resp.flush();
95
97
  }
96
98
  }
99
+ getSessionId(req) {
100
+ return req.query.sessionId ?? req.headers["mcp-session-id"];
101
+ }
102
+ getTransport(sessionId) {
103
+ return this.transports[sessionId];
104
+ }
105
+ async createServerWithStreamableHTTPTransport(serverName, resp, req) {
106
+ const server = new import_server.Server(
107
+ {
108
+ name: serverName,
109
+ version: "0.1.0"
110
+ },
111
+ {
112
+ capabilities: {
113
+ tools: {}
114
+ }
115
+ }
116
+ );
117
+ const transport = new import_FlushingTransport.FlushingStreamableHTTPTransport(
118
+ {
119
+ sessionIdGenerator: () => (0, import_crypto.randomUUID)(),
120
+ onsessioninitialized: (sessionId) => {
121
+ this.logger.debug(`New session initialized: ${sessionId}`);
122
+ transport.onclose = () => {
123
+ this.logger.debug(`Deleting transport for ${sessionId}`);
124
+ delete this.tools[sessionId];
125
+ delete this.transports[sessionId];
126
+ delete this.servers[sessionId];
127
+ };
128
+ this.transports[sessionId] = transport;
129
+ this.servers[sessionId] = server;
130
+ }
131
+ },
132
+ resp
133
+ );
134
+ this.setUpHandlers(server);
135
+ await server.connect(transport);
136
+ await transport.handleRequest(req, resp, req?.body);
137
+ if (resp.flush) {
138
+ resp.flush();
139
+ }
140
+ }
97
141
  async handlePostMessage(req, resp, connectedTools) {
98
- const sessionId = req.query.sessionId;
99
- const transport = this.transports[sessionId];
100
- if (transport) {
101
- const bodyString = req.rawBody.toString();
102
- const messageId = getRequestId(bodyString);
142
+ const sessionId = this.getSessionId(req);
143
+ const transport = this.getTransport(sessionId);
144
+ if (sessionId && transport) {
145
+ const message = (0, import_n8n_workflow.jsonParse)(req.rawBody.toString());
146
+ const messageId = getRequestId(message);
103
147
  const callId = messageId ? `${sessionId}_${messageId}` : sessionId;
104
148
  this.tools[sessionId] = connectedTools;
105
149
  try {
106
150
  await new Promise(async (resolve) => {
107
151
  this.resolveFunctions[callId] = resolve;
108
- await transport.handlePostMessage(req, resp, bodyString);
152
+ await transport.handleRequest(req, resp, message);
109
153
  });
110
154
  } finally {
111
155
  delete this.resolveFunctions[callId];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../nodes/mcp/McpTrigger/McpServer.ts"],"sourcesContent":["import type { Tool } from '@langchain/core/tools';\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';\nimport type {\n\tJSONRPCMessage,\n\tServerRequest,\n\tServerNotification,\n} from '@modelcontextprotocol/sdk/types.js';\nimport {\n\tJSONRPCMessageSchema,\n\tListToolsRequestSchema,\n\tCallToolRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport type * as express from 'express';\nimport { OperationalError, type Logger } from 'n8n-workflow';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\n\nimport { FlushingSSEServerTransport } from './FlushingSSEServerTransport';\nimport type { CompressionResponse } from './FlushingSSEServerTransport';\n\n/**\n * Parses the JSONRPC message and checks whether the method used was a tool\n * call. This is necessary in order to not have executions for listing tools\n * and other commands sent by the MCP client\n */\nfunction wasToolCall(body: string) {\n\ttry {\n\t\tconst message: unknown = JSON.parse(body);\n\t\tconst parsedMessage: JSONRPCMessage = JSONRPCMessageSchema.parse(message);\n\t\treturn (\n\t\t\t'method' in parsedMessage &&\n\t\t\t'id' in parsedMessage &&\n\t\t\tparsedMessage?.method === CallToolRequestSchema.shape.method.value\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Extracts the request ID from a JSONRPC message (for example for tool calls).\n * Returns undefined if the message doesn't have an ID (for example on a tool list request)\n *\n */\nfunction getRequestId(body: string): string | undefined {\n\ttry {\n\t\tconst message: unknown = JSON.parse(body);\n\t\tconst parsedMessage: JSONRPCMessage = JSONRPCMessageSchema.parse(message);\n\t\treturn 'id' in parsedMessage ? String(parsedMessage.id) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * This singleton is shared across the instance, making sure it is the one\n * keeping account of MCP servers.\n * It needs to stay in memory to keep track of the long-lived connections.\n * It requires a logger at first creation to set everything up.\n */\nexport class McpServerManager {\n\tstatic #instance: McpServerManager;\n\n\tservers: { [sessionId: string]: Server } = {};\n\n\ttransports: { [sessionId: string]: FlushingSSEServerTransport } = {};\n\n\tprivate tools: { [sessionId: string]: Tool[] } = {};\n\n\tprivate resolveFunctions: { [callId: string]: CallableFunction } = {};\n\n\tlogger: Logger;\n\n\tprivate constructor(logger: Logger) {\n\t\tthis.logger = logger;\n\t\tthis.logger.debug('MCP Server created');\n\t}\n\n\tstatic instance(logger: Logger): McpServerManager {\n\t\tif (!McpServerManager.#instance) {\n\t\t\tMcpServerManager.#instance = new McpServerManager(logger);\n\t\t\tlogger.debug('Created singleton MCP manager');\n\t\t}\n\n\t\treturn McpServerManager.#instance;\n\t}\n\n\tasync createServerAndTransport(\n\t\tserverName: string,\n\t\tpostUrl: string,\n\t\tresp: CompressionResponse,\n\t): Promise<void> {\n\t\tconst transport = new FlushingSSEServerTransport(postUrl, resp);\n\t\tconst server = new Server(\n\t\t\t{\n\t\t\t\tname: serverName,\n\t\t\t\tversion: '0.1.0',\n\t\t\t},\n\t\t\t{\n\t\t\t\tcapabilities: { tools: {} },\n\t\t\t},\n\t\t);\n\n\t\tthis.setUpHandlers(server);\n\t\tconst { sessionId } = transport;\n\t\tthis.transports[sessionId] = transport;\n\t\tthis.servers[sessionId] = server;\n\n\t\tresp.on('close', async () => {\n\t\t\tthis.logger.debug(`Deleting transport for ${sessionId}`);\n\t\t\tdelete this.tools[sessionId];\n\t\t\tdelete this.transports[sessionId];\n\t\t\tdelete this.servers[sessionId];\n\t\t});\n\n\t\tawait server.connect(transport);\n\n\t\t// Make sure we flush the compression middleware, so that it's not waiting for more content to be added to the buffer\n\t\tif (resp.flush) {\n\t\t\tresp.flush();\n\t\t}\n\t}\n\n\tasync handlePostMessage(req: express.Request, resp: CompressionResponse, connectedTools: Tool[]) {\n\t\tconst sessionId = req.query.sessionId as string;\n\t\tconst transport = this.transports[sessionId];\n\t\tif (transport) {\n\t\t\t// We need to add a promise here because the `handlePostMessage` will send something to the\n\t\t\t// MCP Server, that will run in a different context. This means that the return will happen\n\t\t\t// almost immediately, and will lead to marking the sub-node as \"running\" in the final execution\n\t\t\tconst bodyString = req.rawBody.toString();\n\t\t\tconst messageId = getRequestId(bodyString);\n\n\t\t\t// Use session & message ID if available, otherwise fall back to sessionId\n\t\t\tconst callId = messageId ? `${sessionId}_${messageId}` : sessionId;\n\t\t\tthis.tools[sessionId] = connectedTools;\n\n\t\t\ttry {\n\t\t\t\tawait new Promise(async (resolve) => {\n\t\t\t\t\tthis.resolveFunctions[callId] = resolve;\n\t\t\t\t\tawait transport.handlePostMessage(req, resp, bodyString);\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\tdelete this.resolveFunctions[callId];\n\t\t\t}\n\t\t} else {\n\t\t\tthis.logger.warn(`No transport found for session ${sessionId}`);\n\t\t\tresp.status(401).send('No transport found for sessionId');\n\t\t}\n\n\t\tif (resp.flush) {\n\t\t\tresp.flush();\n\t\t}\n\n\t\treturn wasToolCall(req.rawBody.toString());\n\t}\n\n\tsetUpHandlers(server: Server) {\n\t\tserver.setRequestHandler(\n\t\t\tListToolsRequestSchema,\n\t\t\tasync (_, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => {\n\t\t\t\tif (!extra.sessionId) {\n\t\t\t\t\tthrow new OperationalError('Require a sessionId for the listing of tools');\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\ttools: this.tools[extra.sessionId].map((tool) => {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tname: tool.name,\n\t\t\t\t\t\t\tdescription: tool.description,\n\t\t\t\t\t\t\t// Allow additional properties on tool call input\n\t\t\t\t\t\t\tinputSchema: zodToJsonSchema(tool.schema, { removeAdditionalStrategy: 'strict' }),\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);\n\n\t\tserver.setRequestHandler(\n\t\t\tCallToolRequestSchema,\n\t\t\tasync (request, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => {\n\t\t\t\tif (!request.params?.name || !request.params?.arguments) {\n\t\t\t\t\tthrow new OperationalError('Require a name and arguments for the tool call');\n\t\t\t\t}\n\t\t\t\tif (!extra.sessionId) {\n\t\t\t\t\tthrow new OperationalError('Require a sessionId for the tool call');\n\t\t\t\t}\n\n\t\t\t\tconst callId = extra.requestId ? `${extra.sessionId}_${extra.requestId}` : extra.sessionId;\n\n\t\t\t\tconst requestedTool: Tool | undefined = this.tools[extra.sessionId].find(\n\t\t\t\t\t(tool) => tool.name === request.params.name,\n\t\t\t\t);\n\t\t\t\tif (!requestedTool) {\n\t\t\t\t\tthrow new OperationalError('Tool not found');\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await requestedTool.invoke(request.params.arguments);\n\t\t\t\t\tif (this.resolveFunctions[callId]) {\n\t\t\t\t\t\tthis.resolveFunctions[callId]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.logger.warn(`No resolve function found for ${callId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.logger.debug(`Got request for ${requestedTool.name}, and executed it.`);\n\n\t\t\t\t\tif (typeof result === 'object') {\n\t\t\t\t\t\treturn { content: [{ type: 'text', text: JSON.stringify(result) }] };\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof result === 'string') {\n\t\t\t\t\t\treturn { content: [{ type: 'text', text: result }] };\n\t\t\t\t\t}\n\t\t\t\t\treturn { content: [{ type: 'text', text: String(result) }] };\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.logger.error(`Error while executing Tool ${requestedTool.name}: ${error}`);\n\t\t\t\t\treturn { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] };\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\tserver.onclose = () => {\n\t\t\tthis.logger.debug('Closing MCP Server');\n\t\t};\n\t\tserver.onerror = (error: unknown) => {\n\t\t\tthis.logger.error(`MCP Error: ${error}`);\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../nodes/mcp/McpTrigger/McpServer.ts"],"sourcesContent":["import type { Tool } from '@langchain/core/tools';\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';\nimport type {\n\tJSONRPCMessage,\n\tServerRequest,\n\tServerNotification,\n} from '@modelcontextprotocol/sdk/types.js';\nimport {\n\tJSONRPCMessageSchema,\n\tListToolsRequestSchema,\n\tCallToolRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { randomUUID } from 'crypto';\nimport type * as express from 'express';\nimport type { IncomingMessage } from 'http';\nimport { jsonParse, OperationalError, type Logger } from 'n8n-workflow';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\n\nimport { FlushingSSEServerTransport, FlushingStreamableHTTPTransport } from './FlushingTransport';\nimport type { CompressionResponse } from './FlushingTransport';\n\n/**\n * Parses the JSONRPC message and checks whether the method used was a tool\n * call. This is necessary in order to not have executions for listing tools\n * and other commands sent by the MCP client\n */\nfunction wasToolCall(body: string) {\n\ttry {\n\t\tconst message: unknown = JSON.parse(body);\n\t\tconst parsedMessage: JSONRPCMessage = JSONRPCMessageSchema.parse(message);\n\t\treturn (\n\t\t\t'method' in parsedMessage &&\n\t\t\t'id' in parsedMessage &&\n\t\t\tparsedMessage?.method === CallToolRequestSchema.shape.method.value\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Extracts the request ID from a JSONRPC message (for example for tool calls).\n * Returns undefined if the message doesn't have an ID (for example on a tool list request)\n *\n */\nfunction getRequestId(message: unknown): string | undefined {\n\ttry {\n\t\tconst parsedMessage: JSONRPCMessage = JSONRPCMessageSchema.parse(message);\n\t\treturn 'id' in parsedMessage ? String(parsedMessage.id) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * This singleton is shared across the instance, making sure it is the one\n * keeping account of MCP servers.\n * It needs to stay in memory to keep track of the long-lived connections.\n * It requires a logger at first creation to set everything up.\n */\nexport class McpServerManager {\n\tstatic #instance: McpServerManager;\n\n\tservers: { [sessionId: string]: Server } = {};\n\n\ttransports: {\n\t\t[sessionId: string]: FlushingSSEServerTransport | FlushingStreamableHTTPTransport;\n\t} = {};\n\n\tprivate tools: { [sessionId: string]: Tool[] } = {};\n\n\tprivate resolveFunctions: { [callId: string]: CallableFunction } = {};\n\n\tlogger: Logger;\n\n\tprivate constructor(logger: Logger) {\n\t\tthis.logger = logger;\n\t\tthis.logger.debug('MCP Server created');\n\t}\n\n\tstatic instance(logger: Logger): McpServerManager {\n\t\tif (!McpServerManager.#instance) {\n\t\t\tMcpServerManager.#instance = new McpServerManager(logger);\n\t\t\tlogger.debug('Created singleton MCP manager');\n\t\t}\n\n\t\treturn McpServerManager.#instance;\n\t}\n\n\tasync createServerWithSSETransport(\n\t\tserverName: string,\n\t\tpostUrl: string,\n\t\tresp: CompressionResponse,\n\t): Promise<void> {\n\t\tconst server = new Server(\n\t\t\t{\n\t\t\t\tname: serverName,\n\t\t\t\tversion: '0.1.0',\n\t\t\t},\n\t\t\t{\n\t\t\t\tcapabilities: {\n\t\t\t\t\ttools: {},\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tconst transport = new FlushingSSEServerTransport(postUrl, resp);\n\n\t\tthis.setUpHandlers(server);\n\n\t\tconst sessionId = transport.sessionId;\n\t\tthis.transports[sessionId] = transport;\n\t\tthis.servers[sessionId] = server;\n\n\t\tresp.on('close', async () => {\n\t\t\tthis.logger.debug(`Deleting transport for ${sessionId}`);\n\t\t\tdelete this.tools[sessionId];\n\t\t\tdelete this.transports[sessionId];\n\t\t\tdelete this.servers[sessionId];\n\t\t});\n\t\tawait server.connect(transport);\n\n\t\t// Make sure we flush the compression middleware, so that it's not waiting for more content to be added to the buffer\n\t\tif (resp.flush) {\n\t\t\tresp.flush();\n\t\t}\n\t}\n\n\tgetSessionId(req: express.Request): string | undefined {\n\t\t// Session ID can be passed either as a query parameter (SSE transport)\n\t\t// or in the header (StreamableHTTP transport).\n\t\treturn (req.query.sessionId ?? req.headers['mcp-session-id']) as string | undefined;\n\t}\n\n\tgetTransport(\n\t\tsessionId: string,\n\t): FlushingSSEServerTransport | FlushingStreamableHTTPTransport | undefined {\n\t\treturn this.transports[sessionId];\n\t}\n\n\tasync createServerWithStreamableHTTPTransport(\n\t\tserverName: string,\n\t\tresp: CompressionResponse,\n\t\treq?: express.Request,\n\t): Promise<void> {\n\t\tconst server = new Server(\n\t\t\t{\n\t\t\t\tname: serverName,\n\t\t\t\tversion: '0.1.0',\n\t\t\t},\n\t\t\t{\n\t\t\t\tcapabilities: {\n\t\t\t\t\ttools: {},\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tconst transport = new FlushingStreamableHTTPTransport(\n\t\t\t{\n\t\t\t\tsessionIdGenerator: () => randomUUID(),\n\t\t\t\tonsessioninitialized: (sessionId) => {\n\t\t\t\t\tthis.logger.debug(`New session initialized: ${sessionId}`);\n\t\t\t\t\ttransport.onclose = () => {\n\t\t\t\t\t\tthis.logger.debug(`Deleting transport for ${sessionId}`);\n\t\t\t\t\t\tdelete this.tools[sessionId];\n\t\t\t\t\t\tdelete this.transports[sessionId];\n\t\t\t\t\t\tdelete this.servers[sessionId];\n\t\t\t\t\t};\n\t\t\t\t\tthis.transports[sessionId] = transport;\n\t\t\t\t\tthis.servers[sessionId] = server;\n\t\t\t\t},\n\t\t\t},\n\t\t\tresp,\n\t\t);\n\n\t\tthis.setUpHandlers(server);\n\n\t\tawait server.connect(transport);\n\n\t\tawait transport.handleRequest(req as IncomingMessage, resp, req?.body);\n\t\tif (resp.flush) {\n\t\t\tresp.flush();\n\t\t}\n\t}\n\n\tasync handlePostMessage(req: express.Request, resp: CompressionResponse, connectedTools: Tool[]) {\n\t\t// Session ID can be passed either as a query parameter (SSE transport)\n\t\t// or in the header (StreamableHTTP transport).\n\t\tconst sessionId = this.getSessionId(req);\n\t\tconst transport = this.getTransport(sessionId as string);\n\t\tif (sessionId && transport) {\n\t\t\t// We need to add a promise here because the `handlePostMessage` will send something to the\n\t\t\t// MCP Server, that will run in a different context. This means that the return will happen\n\t\t\t// almost immediately, and will lead to marking the sub-node as \"running\" in the final execution\n\t\t\tconst message = jsonParse(req.rawBody.toString());\n\t\t\tconst messageId = getRequestId(message);\n\t\t\t// Use session & message ID if available, otherwise fall back to sessionId\n\t\t\tconst callId = messageId ? `${sessionId}_${messageId}` : sessionId;\n\t\t\tthis.tools[sessionId] = connectedTools;\n\n\t\t\ttry {\n\t\t\t\tawait new Promise(async (resolve) => {\n\t\t\t\t\tthis.resolveFunctions[callId] = resolve;\n\t\t\t\t\tawait transport.handleRequest(req, resp, message as IncomingMessage);\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\tdelete this.resolveFunctions[callId];\n\t\t\t}\n\t\t} else {\n\t\t\tthis.logger.warn(`No transport found for session ${sessionId}`);\n\t\t\tresp.status(401).send('No transport found for sessionId');\n\t\t}\n\n\t\tif (resp.flush) {\n\t\t\tresp.flush();\n\t\t}\n\n\t\treturn wasToolCall(req.rawBody.toString());\n\t}\n\n\tsetUpHandlers(server: Server) {\n\t\tserver.setRequestHandler(\n\t\t\tListToolsRequestSchema,\n\t\t\tasync (_, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => {\n\t\t\t\tif (!extra.sessionId) {\n\t\t\t\t\tthrow new OperationalError('Require a sessionId for the listing of tools');\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\ttools: this.tools[extra.sessionId].map((tool) => {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tname: tool.name,\n\t\t\t\t\t\t\tdescription: tool.description,\n\t\t\t\t\t\t\t// Allow additional properties on tool call input\n\t\t\t\t\t\t\tinputSchema: zodToJsonSchema(tool.schema, { removeAdditionalStrategy: 'strict' }),\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);\n\n\t\tserver.setRequestHandler(\n\t\t\tCallToolRequestSchema,\n\t\t\tasync (request, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => {\n\t\t\t\tif (!request.params?.name || !request.params?.arguments) {\n\t\t\t\t\tthrow new OperationalError('Require a name and arguments for the tool call');\n\t\t\t\t}\n\t\t\t\tif (!extra.sessionId) {\n\t\t\t\t\tthrow new OperationalError('Require a sessionId for the tool call');\n\t\t\t\t}\n\n\t\t\t\tconst callId = extra.requestId ? `${extra.sessionId}_${extra.requestId}` : extra.sessionId;\n\n\t\t\t\tconst requestedTool: Tool | undefined = this.tools[extra.sessionId].find(\n\t\t\t\t\t(tool) => tool.name === request.params.name,\n\t\t\t\t);\n\t\t\t\tif (!requestedTool) {\n\t\t\t\t\tthrow new OperationalError('Tool not found');\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await requestedTool.invoke(request.params.arguments);\n\t\t\t\t\tif (this.resolveFunctions[callId]) {\n\t\t\t\t\t\tthis.resolveFunctions[callId]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.logger.warn(`No resolve function found for ${callId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.logger.debug(`Got request for ${requestedTool.name}, and executed it.`);\n\n\t\t\t\t\tif (typeof result === 'object') {\n\t\t\t\t\t\treturn { content: [{ type: 'text', text: JSON.stringify(result) }] };\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof result === 'string') {\n\t\t\t\t\t\treturn { content: [{ type: 'text', text: result }] };\n\t\t\t\t\t}\n\t\t\t\t\treturn { content: [{ type: 'text', text: String(result) }] };\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.logger.error(`Error while executing Tool ${requestedTool.name}: ${error}`);\n\t\t\t\t\treturn { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] };\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\tserver.onclose = () => {\n\t\t\tthis.logger.debug('Closing MCP Server');\n\t\t};\n\t\tserver.onerror = (error: unknown) => {\n\t\t\tthis.logger.error(`MCP Error: ${error}`);\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -39,9 +39,9 @@ class McpTrigger extends import_n8n_workflow.Node {
39
39
  dark: "file:../mcp.dark.svg"
40
40
  },
41
41
  group: ["trigger"],
42
- version: [1, 1.1],
42
+ version: [1, 1.1, 2],
43
43
  description: "Expose n8n tools as an MCP Server endpoint",
44
- activationMessage: "You can now connect your MCP Clients to the SSE URL.",
44
+ activationMessage: "You can now connect your MCP Clients to the URL, using SSE or Streamable HTTP transports.",
45
45
  defaults: {
46
46
  name: "MCP Server Trigger"
47
47
  },
@@ -125,7 +125,7 @@ class McpTrigger extends import_n8n_workflow.Node {
125
125
  httpMethod: "GET",
126
126
  responseMode: "onReceived",
127
127
  isFullPath: true,
128
- path: `={{$parameter["path"]}}/${MCP_SSE_SETUP_PATH}`,
128
+ path: `={{$parameter["path"]}}{{parseFloat($nodeVersion)<2 ? '/${MCP_SSE_SETUP_PATH}' : ''}}`,
129
129
  nodeType: "mcp",
130
130
  ndvHideMethod: true,
131
131
  ndvHideUrl: false
@@ -135,7 +135,7 @@ class McpTrigger extends import_n8n_workflow.Node {
135
135
  httpMethod: "POST",
136
136
  responseMode: "onReceived",
137
137
  isFullPath: true,
138
- path: `={{$parameter["path"]}}/${MCP_SSE_MESSAGES_PATH}`,
138
+ path: `={{$parameter["path"]}}{{parseFloat($nodeVersion)<2 ? '/${MCP_SSE_MESSAGES_PATH}' : ''}}`,
139
139
  nodeType: "mcp",
140
140
  ndvHideMethod: true,
141
141
  ndvHideUrl: true
@@ -161,16 +161,18 @@ class McpTrigger extends import_n8n_workflow.Node {
161
161
  const serverName = node.typeVersion > 1 ? (0, import_helpers.nodeNameToToolName)(node) : "n8n-mcp-server";
162
162
  const mcpServerManager = import_McpServer.McpServerManager.instance(context.logger);
163
163
  if (webhookName === "setup") {
164
- const postUrl = req.path.replace(
165
- new RegExp(`/${MCP_SSE_SETUP_PATH}$`),
166
- `/${MCP_SSE_MESSAGES_PATH}`
167
- );
168
- await mcpServerManager.createServerAndTransport(serverName, postUrl, resp);
164
+ const postUrl = node.typeVersion < 2 ? req.path.replace(new RegExp(`/${MCP_SSE_SETUP_PATH}$`), `/${MCP_SSE_MESSAGES_PATH}`) : req.path;
165
+ await mcpServerManager.createServerWithSSETransport(serverName, postUrl, resp);
169
166
  return { noWebhookResponse: true };
170
167
  } else if (webhookName === "default") {
171
- const connectedTools = await (0, import_helpers.getConnectedTools)(context, true);
172
- const wasToolCall = await mcpServerManager.handlePostMessage(req, resp, connectedTools);
173
- if (wasToolCall) return { noWebhookResponse: true, workflowData: [[{ json: {} }]] };
168
+ const sessionId = mcpServerManager.getSessionId(req);
169
+ if (sessionId && mcpServerManager.getTransport(sessionId)) {
170
+ const connectedTools = await (0, import_helpers.getConnectedTools)(context, true);
171
+ const wasToolCall = await mcpServerManager.handlePostMessage(req, resp, connectedTools);
172
+ if (wasToolCall) return { noWebhookResponse: true, workflowData: [[{ json: {} }]] };
173
+ } else {
174
+ await mcpServerManager.createServerWithStreamableHTTPTransport(serverName, resp, req);
175
+ }
174
176
  return { noWebhookResponse: true };
175
177
  }
176
178
  return { workflowData: [[{ json: {} }]] };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../nodes/mcp/McpTrigger/McpTrigger.node.ts"],"sourcesContent":["import { WebhookAuthorizationError } from 'n8n-nodes-base/dist/nodes/Webhook/error';\nimport { validateWebhookAuthentication } from 'n8n-nodes-base/dist/nodes/Webhook/utils';\nimport type { INodeTypeDescription, IWebhookFunctions, IWebhookResponseData } from 'n8n-workflow';\nimport { NodeConnectionTypes, Node } from 'n8n-workflow';\n\nimport { getConnectedTools, nodeNameToToolName } from '@utils/helpers';\n\nimport type { CompressionResponse } from './FlushingSSEServerTransport';\nimport { McpServerManager } from './McpServer';\n\nconst MCP_SSE_SETUP_PATH = 'sse';\nconst MCP_SSE_MESSAGES_PATH = 'messages';\n\nexport class McpTrigger extends Node {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'MCP Server Trigger',\n\t\tname: 'mcpTrigger',\n\t\ticon: {\n\t\t\tlight: 'file:../mcp.svg',\n\t\t\tdark: 'file:../mcp.dark.svg',\n\t\t},\n\t\tgroup: ['trigger'],\n\t\tversion: [1, 1.1],\n\t\tdescription: 'Expose n8n tools as an MCP Server endpoint',\n\t\tactivationMessage: 'You can now connect your MCP Clients to the SSE URL.',\n\t\tdefaults: {\n\t\t\tname: 'MCP Server Trigger',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['AI', 'Core Nodes'],\n\t\t\tsubcategories: {\n\t\t\t\tAI: ['Root Nodes', 'Model Context Protocol'],\n\t\t\t\t'Core Nodes': ['Other Trigger Nodes'],\n\t\t\t},\n\t\t\talias: ['Model Context Protocol', 'MCP Server'],\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.mcptrigger/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\ttriggerPanel: {\n\t\t\theader: 'Listen for MCP events',\n\t\t\texecutionsHelp: {\n\t\t\t\tinactive:\n\t\t\t\t\t\"This trigger has two modes: test and production.<br /><br /><b>Use test mode while you build your workflow</b>. Click the 'execute step' button, then make an MCP request to the test URL. The executions will show up in the editor.<br /><br /><b>Use production mode to run your workflow automatically</b>. <a data-key='activate'>Activate</a> the workflow, then make requests to the production URL. These executions will show up in the <a data-key='executions'>executions list</a>, but not the editor.\",\n\t\t\t\tactive:\n\t\t\t\t\t\"This trigger has two modes: test and production.<br /><br /><b>Use test mode while you build your workflow</b>. Click the 'execute step' button, then make an MCP request to the test URL. The executions will show up in the editor.<br /><br /><b>Use production mode to run your workflow automatically</b>. Since your workflow is activated, you can make requests to the production URL. These executions will show up in the <a data-key='executions'>executions list</a>, but not the editor.\",\n\t\t\t},\n\t\t\tactivationHint:\n\t\t\t\t'Once you’ve finished building your workflow, run it without having to click this button by using the production URL.',\n\t\t},\n\t\tinputs: [\n\t\t\t{\n\t\t\t\ttype: NodeConnectionTypes.AiTool,\n\t\t\t\tdisplayName: 'Tools',\n\t\t\t},\n\t\t],\n\t\toutputs: [],\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\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{ name: 'None', value: 'none' },\n\t\t\t\t\t{ name: 'Bearer Auth', value: 'bearerAuth' },\n\t\t\t\t\t{ name: 'Header Auth', value: 'headerAuth' },\n\t\t\t\t],\n\t\t\t\tdefault: 'none',\n\t\t\t\tdescription: 'The way to authenticate',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Path',\n\t\t\t\tname: 'path',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'webhook',\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'The base path for this MCP server',\n\t\t\t},\n\t\t],\n\t\twebhooks: [\n\t\t\t{\n\t\t\t\tname: 'setup',\n\t\t\t\thttpMethod: 'GET',\n\t\t\t\tresponseMode: 'onReceived',\n\t\t\t\tisFullPath: true,\n\t\t\t\tpath: `={{$parameter[\"path\"]}}/${MCP_SSE_SETUP_PATH}`,\n\t\t\t\tnodeType: 'mcp',\n\t\t\t\tndvHideMethod: true,\n\t\t\t\tndvHideUrl: false,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'default',\n\t\t\t\thttpMethod: 'POST',\n\t\t\t\tresponseMode: 'onReceived',\n\t\t\t\tisFullPath: true,\n\t\t\t\tpath: `={{$parameter[\"path\"]}}/${MCP_SSE_MESSAGES_PATH}`,\n\t\t\t\tnodeType: 'mcp',\n\t\t\t\tndvHideMethod: true,\n\t\t\t\tndvHideUrl: true,\n\t\t\t},\n\t\t],\n\t};\n\n\tasync webhook(context: IWebhookFunctions): Promise<IWebhookResponseData> {\n\t\tconst webhookName = context.getWebhookName();\n\t\tconst req = context.getRequestObject();\n\t\tconst resp = context.getResponseObject() as unknown as CompressionResponse;\n\n\t\ttry {\n\t\t\tawait validateWebhookAuthentication(context, 'authentication');\n\t\t} catch (error) {\n\t\t\tif (error instanceof WebhookAuthorizationError) {\n\t\t\t\tresp.writeHead(error.responseCode);\n\t\t\t\tresp.end(error.message);\n\t\t\t\treturn { noWebhookResponse: true };\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tconst node = context.getNode();\n\t\t// Get a url/tool friendly name for the server, based on the node name\n\t\tconst serverName = node.typeVersion > 1 ? nodeNameToToolName(node) : 'n8n-mcp-server';\n\n\t\tconst mcpServerManager: McpServerManager = McpServerManager.instance(context.logger);\n\n\t\tif (webhookName === 'setup') {\n\t\t\t// Sets up the transport and opens the long-lived connection. This resp\n\t\t\t// will stay streaming, and is the channel that sends the events\n\t\t\tconst postUrl = req.path.replace(\n\t\t\t\tnew RegExp(`/${MCP_SSE_SETUP_PATH}$`),\n\t\t\t\t`/${MCP_SSE_MESSAGES_PATH}`,\n\t\t\t);\n\t\t\tawait mcpServerManager.createServerAndTransport(serverName, postUrl, resp);\n\n\t\t\treturn { noWebhookResponse: true };\n\t\t} else if (webhookName === 'default') {\n\t\t\t// This is the command-channel, and is actually executing the tools. This\n\t\t\t// sends the response back through the long-lived connection setup in the\n\t\t\t// 'setup' call\n\t\t\tconst connectedTools = await getConnectedTools(context, true);\n\n\t\t\tconst wasToolCall = await mcpServerManager.handlePostMessage(req, resp, connectedTools);\n\n\t\t\tif (wasToolCall) return { noWebhookResponse: true, workflowData: [[{ json: {} }]] };\n\t\t\treturn { noWebhookResponse: true };\n\t\t}\n\n\t\treturn { workflowData: [[{ json: {} }]] };\n\t}\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../nodes/mcp/McpTrigger/McpTrigger.node.ts"],"sourcesContent":["import { WebhookAuthorizationError } from 'n8n-nodes-base/dist/nodes/Webhook/error';\nimport { validateWebhookAuthentication } from 'n8n-nodes-base/dist/nodes/Webhook/utils';\nimport type { INodeTypeDescription, IWebhookFunctions, IWebhookResponseData } from 'n8n-workflow';\nimport { NodeConnectionTypes, Node } from 'n8n-workflow';\n\nimport { getConnectedTools, nodeNameToToolName } from '@utils/helpers';\n\nimport type { CompressionResponse } from './FlushingTransport';\nimport { McpServerManager } from './McpServer';\n\nconst MCP_SSE_SETUP_PATH = 'sse';\nconst MCP_SSE_MESSAGES_PATH = 'messages';\n\nexport class McpTrigger extends Node {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'MCP Server Trigger',\n\t\tname: 'mcpTrigger',\n\t\ticon: {\n\t\t\tlight: 'file:../mcp.svg',\n\t\t\tdark: 'file:../mcp.dark.svg',\n\t\t},\n\t\tgroup: ['trigger'],\n\t\tversion: [1, 1.1, 2],\n\t\tdescription: 'Expose n8n tools as an MCP Server endpoint',\n\t\tactivationMessage:\n\t\t\t'You can now connect your MCP Clients to the URL, using SSE or Streamable HTTP transports.',\n\t\tdefaults: {\n\t\t\tname: 'MCP Server Trigger',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['AI', 'Core Nodes'],\n\t\t\tsubcategories: {\n\t\t\t\tAI: ['Root Nodes', 'Model Context Protocol'],\n\t\t\t\t'Core Nodes': ['Other Trigger Nodes'],\n\t\t\t},\n\t\t\talias: ['Model Context Protocol', 'MCP Server'],\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.mcptrigger/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\ttriggerPanel: {\n\t\t\theader: 'Listen for MCP events',\n\t\t\texecutionsHelp: {\n\t\t\t\tinactive:\n\t\t\t\t\t\"This trigger has two modes: test and production.<br /><br /><b>Use test mode while you build your workflow</b>. Click the 'execute step' button, then make an MCP request to the test URL. The executions will show up in the editor.<br /><br /><b>Use production mode to run your workflow automatically</b>. <a data-key='activate'>Activate</a> the workflow, then make requests to the production URL. These executions will show up in the <a data-key='executions'>executions list</a>, but not the editor.\",\n\t\t\t\tactive:\n\t\t\t\t\t\"This trigger has two modes: test and production.<br /><br /><b>Use test mode while you build your workflow</b>. Click the 'execute step' button, then make an MCP request to the test URL. The executions will show up in the editor.<br /><br /><b>Use production mode to run your workflow automatically</b>. Since your workflow is activated, you can make requests to the production URL. These executions will show up in the <a data-key='executions'>executions list</a>, but not the editor.\",\n\t\t\t},\n\t\t\tactivationHint:\n\t\t\t\t'Once you’ve finished building your workflow, run it without having to click this button by using the production URL.',\n\t\t},\n\t\tinputs: [\n\t\t\t{\n\t\t\t\ttype: NodeConnectionTypes.AiTool,\n\t\t\t\tdisplayName: 'Tools',\n\t\t\t},\n\t\t],\n\t\toutputs: [],\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\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{ name: 'None', value: 'none' },\n\t\t\t\t\t{ name: 'Bearer Auth', value: 'bearerAuth' },\n\t\t\t\t\t{ name: 'Header Auth', value: 'headerAuth' },\n\t\t\t\t],\n\t\t\t\tdefault: 'none',\n\t\t\t\tdescription: 'The way to authenticate',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Path',\n\t\t\t\tname: 'path',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'webhook',\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'The base path for this MCP server',\n\t\t\t},\n\t\t],\n\t\twebhooks: [\n\t\t\t{\n\t\t\t\tname: 'setup',\n\t\t\t\thttpMethod: 'GET',\n\t\t\t\tresponseMode: 'onReceived',\n\t\t\t\tisFullPath: true,\n\t\t\t\tpath: `={{$parameter[\"path\"]}}{{parseFloat($nodeVersion)<2 ? '/${MCP_SSE_SETUP_PATH}' : ''}}`,\n\t\t\t\tnodeType: 'mcp',\n\t\t\t\tndvHideMethod: true,\n\t\t\t\tndvHideUrl: false,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'default',\n\t\t\t\thttpMethod: 'POST',\n\t\t\t\tresponseMode: 'onReceived',\n\t\t\t\tisFullPath: true,\n\t\t\t\tpath: `={{$parameter[\"path\"]}}{{parseFloat($nodeVersion)<2 ? '/${MCP_SSE_MESSAGES_PATH}' : ''}}`,\n\t\t\t\tnodeType: 'mcp',\n\t\t\t\tndvHideMethod: true,\n\t\t\t\tndvHideUrl: true,\n\t\t\t},\n\t\t],\n\t};\n\n\tasync webhook(context: IWebhookFunctions): Promise<IWebhookResponseData> {\n\t\tconst webhookName = context.getWebhookName();\n\t\tconst req = context.getRequestObject();\n\t\tconst resp = context.getResponseObject() as unknown as CompressionResponse;\n\n\t\ttry {\n\t\t\tawait validateWebhookAuthentication(context, 'authentication');\n\t\t} catch (error) {\n\t\t\tif (error instanceof WebhookAuthorizationError) {\n\t\t\t\tresp.writeHead(error.responseCode);\n\t\t\t\tresp.end(error.message);\n\t\t\t\treturn { noWebhookResponse: true };\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tconst node = context.getNode();\n\t\t// Get a url/tool friendly name for the server, based on the node name\n\t\tconst serverName = node.typeVersion > 1 ? nodeNameToToolName(node) : 'n8n-mcp-server';\n\n\t\tconst mcpServerManager: McpServerManager = McpServerManager.instance(context.logger);\n\n\t\tif (webhookName === 'setup') {\n\t\t\t// Sets up the transport and opens the long-lived connection. This resp\n\t\t\t// will stay streaming, and is the channel that sends the events\n\n\t\t\t// Prior to version 2.0, we use different paths for the setup and messages.\n\t\t\tconst postUrl =\n\t\t\t\tnode.typeVersion < 2\n\t\t\t\t\t? req.path.replace(new RegExp(`/${MCP_SSE_SETUP_PATH}$`), `/${MCP_SSE_MESSAGES_PATH}`)\n\t\t\t\t\t: req.path;\n\t\t\tawait mcpServerManager.createServerWithSSETransport(serverName, postUrl, resp);\n\n\t\t\treturn { noWebhookResponse: true };\n\t\t} else if (webhookName === 'default') {\n\t\t\t// Here we handle POST requests. These can be either\n\t\t\t// 1) Client calls in an established session using the SSE transport, or\n\t\t\t// 2) Client calls in an established session using the StreamableHTTPServerTransport\n\t\t\t// 3) Session setup requests using the StreamableHTTPServerTransport\n\n\t\t\t// Check if there is a session and a transport is already established\n\t\t\tconst sessionId = mcpServerManager.getSessionId(req);\n\t\t\tif (sessionId && mcpServerManager.getTransport(sessionId)) {\n\t\t\t\tconst connectedTools = await getConnectedTools(context, true);\n\t\t\t\tconst wasToolCall = await mcpServerManager.handlePostMessage(req, resp, connectedTools);\n\t\t\t\tif (wasToolCall) return { noWebhookResponse: true, workflowData: [[{ json: {} }]] };\n\t\t\t} else {\n\t\t\t\t// If no session is established, this is a setup request\n\t\t\t\t// for the StreamableHTTPServerTransport, so we create a new transport\n\t\t\t\tawait mcpServerManager.createServerWithStreamableHTTPTransport(serverName, resp, req);\n\t\t\t}\n\t\t\treturn { noWebhookResponse: true };\n\t\t}\n\n\t\treturn { workflowData: [[{ json: {} }]] };\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -25,6 +25,18 @@ var import_n8n_workflow = require("n8n-workflow");
25
25
  var import_sharedFields = require("../../../../utils/sharedFields");
26
26
  var import_operations = require("./operations");
27
27
  var import_utils = require("./utils");
28
+ const ragStarterCallout = {
29
+ displayName: "Tip: Get a feel for vector stores in n8n with our",
30
+ name: "ragStarterCallout",
31
+ type: "callout",
32
+ typeOptions: {
33
+ calloutAction: {
34
+ label: "RAG starter template",
35
+ type: "openRagStarterTemplate"
36
+ }
37
+ },
38
+ default: ""
39
+ };
28
40
  const createVectorStoreNode = (args) => class VectorStoreNodeType {
29
41
  constructor() {
30
42
  this.description = {
@@ -96,6 +108,7 @@ const createVectorStoreNode = (args) => class VectorStoreNodeType {
96
108
  })($parameter)
97
109
  }}`,
98
110
  properties: [
111
+ ragStarterCallout,
99
112
  {
100
113
  displayName: "Operation Mode",
101
114
  name: "mode",