n8n-nodes-browser-smart-automation 0.1.10 → 0.1.11
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/McpClientEX/McpClient.node.js +2 -2
- package/dist/McpClientEX/McpClient.node.js.map +1 -1
- package/dist/McpClientToolEX/McpClientTool.node.js +24 -15
- package/dist/McpClientToolEX/McpClientTool.node.js.map +1 -1
- package/dist/McpClientToolEX/loadOptions.js +1 -2
- package/dist/McpClientToolEX/loadOptions.js.map +1 -1
- package/dist/McpTriggerEX/McpTrigger.node.js +2 -2
- package/dist/McpTriggerEX/McpTrigger.node.js.map +1 -1
- package/package.json +1 -1
|
@@ -44,8 +44,8 @@ class McpClient {
|
|
|
44
44
|
description: "Standalone MCP Browser Client",
|
|
45
45
|
name: "mcpClient",
|
|
46
46
|
icon: {
|
|
47
|
-
light: "file
|
|
48
|
-
dark: "file
|
|
47
|
+
light: "file:nodes/assets/mcp.svg",
|
|
48
|
+
dark: "file:nodes/assets/mcp.dark.svg"
|
|
49
49
|
},
|
|
50
50
|
group: ["transform"],
|
|
51
51
|
version: 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../nodes/McpClientEX/McpClient.node.ts"],"sourcesContent":["import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type {\n\tIBinaryKeyData,\n\tIDataObject,\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeDescription,\n\tNodeExecutionWithMetadata,\n} from 'n8n-workflow';\nimport { jsonParse, NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';\nimport { ZodError } from 'zod';\nimport { prettifyError } from 'zod/v4/core';\nimport * as listSearch from './listSearch';\nimport * as resourceMapping from './resourceMapping';\nimport { credentials, transportSelect } from '../shared/descriptions';\nimport type { McpAuthenticationOption, McpServerTransport } from '../shared/types';\nimport {\n\tgetAuthHeaders,\n\ttryRefreshOAuth2Token,\n\tconnectMcpClient,\n\tmapToNodeOperationError,\n} from '../shared/utils';\n\nexport class McpClient implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'MCP Browser Client',\n\t\tdescription: 'Standalone MCP Browser Client',\n\t\tname: 'mcpClient',\n\t\ticon: {\n\t\t\tlight: 'file:../assets/mcp.svg',\n\t\t\tdark: 'file:../assets/mcp.dark.svg',\n\t\t},\n\t\tgroup: ['transform'],\n\t\tversion: 1,\n\t\tdefaults: {\n\t\t\tname: 'MCP Browser Client',\n\t\t},\n\t\tcredentials,\n\t\tinputs: [NodeConnectionTypes.Main],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tproperties: [\n\t\t\ttransportSelect({\n\t\t\t\tdefaultOption: 'httpStreamable',\n\t\t\t}),\n\t\t\t{\n\t\t\t\tdisplayName: 'MCP Endpoint URL',\n\t\t\t\tname: 'endpointUrl',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'e.g. https://my-mcp-server.ai/mcp',\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'The URL of the MCP server to connect to',\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: 'MCP OAuth2',\n\t\t\t\t\t\tvalue: 'mcpOAuth2Api',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Multiple Headers Auth',\n\t\t\t\t\t\tvalue: 'multipleHeadersAuth',\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', 'mcpOAuth2Api', 'multipleHeadersAuth'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Tool',\n\t\t\t\tname: 'tool',\n\t\t\t\ttype: 'resourceLocator',\n\t\t\t\tdefault: { mode: 'list', value: '' },\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'The tool to use',\n\t\t\t\tmodes: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'From List',\n\t\t\t\t\t\tname: 'list',\n\t\t\t\t\t\ttype: 'list',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tsearchListMethod: 'getTools',\n\t\t\t\t\t\t\tsearchable: true,\n\t\t\t\t\t\t\tskipCredentialsCheckInRLC: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'ID',\n\t\t\t\t\t\tname: 'id',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Input Mode',\n\t\t\t\tname: 'inputMode',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'manual',\n\t\t\t\tnoDataExpression: true,\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Manual',\n\t\t\t\t\t\tvalue: 'manual',\n\t\t\t\t\t\tdescription: 'Manually specify the input data for each tool parameter',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'JSON',\n\t\t\t\t\t\tvalue: 'json',\n\t\t\t\t\t\tdescription: 'Specify the input data as a JSON object',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Parameters',\n\t\t\t\tname: 'parameters',\n\t\t\t\ttype: 'resourceMapper',\n\t\t\t\tdefault: {\n\t\t\t\t\tmappingMode: 'defineBelow',\n\t\t\t\t\tvalue: null,\n\t\t\t\t},\n\t\t\t\tnoDataExpression: true,\n\t\t\t\trequired: true,\n\t\t\t\ttypeOptions: {\n\t\t\t\t\tloadOptionsDependsOn: ['tool.value'],\n\t\t\t\t\tresourceMapper: {\n\t\t\t\t\t\tresourceMapperMethod: 'getToolParameters',\n\t\t\t\t\t\thideNoDataError: true,\n\t\t\t\t\t\taddAllFields: false,\n\t\t\t\t\t\tsupportAutoMap: false,\n\t\t\t\t\t\tmode: 'add',\n\t\t\t\t\t\tfieldWords: {\n\t\t\t\t\t\t\tsingular: 'parameter',\n\t\t\t\t\t\t\tplural: 'parameters',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tinputMode: ['manual'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'JSON',\n\t\t\t\tname: 'jsonInput',\n\t\t\t\ttype: 'json',\n\t\t\t\ttypeOptions: {\n\t\t\t\t\trows: 5,\n\t\t\t\t},\n\t\t\t\tdefault: '{\\n \"my_field_1\": \"value\",\\n \"my_field_2\": 1\\n}\\n',\n\t\t\t\tvalidateType: 'object',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tinputMode: ['json'],\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: 'options',\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\tdescription: 'Additional options to add',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Convert to Binary',\n\t\t\t\t\t\tname: 'convertToBinary',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdefault: true,\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Whether to convert images and audio to binary data. If false, images and audio will be returned as base64 encoded strings.',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Timeout',\n\t\t\t\t\t\tname: 'timeout',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tminValue: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: 60000,\n\t\t\t\t\t\tdescription: 'Time in ms to wait for tool calls to finish',\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\tlistSearch,\n\t\tresourceMapping,\n\t};\n\n\tasync execute(\n\t\tthis: IExecuteFunctions,\n\t): Promise<INodeExecutionData[][] | NodeExecutionWithMetadata[][] | null> {\n\t\tconst authentication = this.getNodeParameter('authentication', 0) as McpAuthenticationOption;\n\t\tconst serverTransport = this.getNodeParameter('serverTransport', 0) as McpServerTransport;\n\t\tconst endpointUrl = this.getNodeParameter('endpointUrl', 0) as string;\n\t\tconst node = this.getNode();\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\tonUnauthorized: async (headers) => await tryRefreshOAuth2Token(this, authentication, headers),\n\t\t});\n\t\tif (!client.ok) {\n\t\t\tthrow mapToNodeOperationError(node, client.error);\n\t\t}\n\n\t\tconst inputMode = this.getNodeParameter('inputMode', 0, 'manual') as 'manual' | 'json';\n\t\tconst items = this.getInputData();\n\t\tconst returnData: INodeExecutionData[] = [];\n\t\tfor (let itemIndex = 0; itemIndex < items.length; itemIndex++) {\n\t\t\ttry {\n\t\t\t\tconst tool = this.getNodeParameter('tool.value', itemIndex) as string;\n\t\t\t\tconst options = this.getNodeParameter('options', itemIndex);\n\t\t\t\tlet parameters: IDataObject = {};\n\t\t\t\tif (inputMode === 'manual') {\n\t\t\t\t\tparameters = this.getNodeParameter('parameters.value', itemIndex) as IDataObject;\n\t\t\t\t} else {\n\t\t\t\t\tparameters = this.getNodeParameter('jsonInput', itemIndex) as IDataObject;\n\t\t\t\t}\n\n\t\t\t\tconst result = (await client.result.callTool(\n\t\t\t\t\t{\n\t\t\t\t\t\tname: tool,\n\t\t\t\t\t\targuments: parameters,\n\t\t\t\t\t},\n\t\t\t\t\tundefined,\n\t\t\t\t\t{\n\t\t\t\t\t\ttimeout: options.timeout ? Number(options.timeout) : undefined,\n\t\t\t\t\t},\n\t\t\t\t)) as CallToolResult;\n\n\t\t\t\tlet binaryIndex = 0;\n\t\t\t\tconst binary: IBinaryKeyData = {};\n\t\t\t\tconst content: IDataObject[] = [];\n\t\t\t\tconst convertToBinary = options.convertToBinary ?? true;\n\t\t\t\tfor (const contentItem of result.content) {\n\t\t\t\t\tif (contentItem.type === 'text') {\n\t\t\t\t\t\tcontent.push({\n\t\t\t\t\t\t\t...contentItem,\n\t\t\t\t\t\t\ttext: jsonParse(contentItem.text, { fallbackValue: contentItem.text }),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (convertToBinary && (contentItem.type === 'image' || contentItem.type === 'audio')) {\n\t\t\t\t\t\tbinary[`data_${binaryIndex}`] = await this.helpers.prepareBinaryData(\n\t\t\t\t\t\t\tBuffer.from(contentItem.data, 'base64'),\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tcontentItem.mimeType,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbinaryIndex++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tcontent.push(contentItem as IDataObject);\n\t\t\t\t}\n\n\t\t\t\treturnData.push({\n\t\t\t\t\tjson: {\n\t\t\t\t\t\tcontent: content.length > 0 ? content : undefined,\n\t\t\t\t\t},\n\t\t\t\t\tbinary: Object.keys(binary).length > 0 ? binary : undefined,\n\t\t\t\t\tpairedItem: {\n\t\t\t\t\t\titem: itemIndex,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (e) {\n\t\t\t\tconst errorMessage =\n\t\t\t\t\te instanceof ZodError ? prettifyError(e) : e instanceof Error ? e.message : String(e);\n\t\t\t\tif (this.continueOnFail()) {\n\t\t\t\t\treturnData.push({\n\t\t\t\t\t\tjson: {\n\t\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\t\tmessage: errorMessage,\n\t\t\t\t\t\t\t\tissues: e instanceof ZodError ? e.issues : undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpairedItem: {\n\t\t\t\t\t\t\titem: itemIndex,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tthrow new NodeOperationError(node, errorMessage, {\n\t\t\t\t\titemIndex,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn [returnData];\n\t}\n}\n"],"mappings":"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","names":["headers"]}
|
|
1
|
+
{"version":3,"sources":["../../nodes/McpClientEX/McpClient.node.ts"],"sourcesContent":["import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type {\n\tIBinaryKeyData,\n\tIDataObject,\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeDescription,\n\tNodeExecutionWithMetadata,\n} from 'n8n-workflow';\nimport { jsonParse, NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';\nimport { ZodError } from 'zod';\nimport { prettifyError } from 'zod/v4/core';\nimport * as listSearch from './listSearch';\nimport * as resourceMapping from './resourceMapping';\nimport { credentials, transportSelect } from '../shared/descriptions';\nimport type { McpAuthenticationOption, McpServerTransport } from '../shared/types';\nimport {\n\tgetAuthHeaders,\n\ttryRefreshOAuth2Token,\n\tconnectMcpClient,\n\tmapToNodeOperationError,\n} from '../shared/utils';\n\nexport class McpClient implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'MCP Browser Client',\n\t\tdescription: 'Standalone MCP Browser Client',\n\t\tname: 'mcpClient',\n\t\ticon: {\n\t\t\tlight: 'file:nodes/assets/mcp.svg',\n\t\t\tdark: 'file:nodes/assets/mcp.dark.svg',\n\t\t},\n\t\tgroup: ['transform'],\n\t\tversion: 1,\n\t\tdefaults: {\n\t\t\tname: 'MCP Browser Client',\n\t\t},\n\t\tcredentials,\n\t\tinputs: [NodeConnectionTypes.Main],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tproperties: [\n\t\t\ttransportSelect({\n\t\t\t\tdefaultOption: 'httpStreamable',\n\t\t\t}),\n\t\t\t{\n\t\t\t\tdisplayName: 'MCP Endpoint URL',\n\t\t\t\tname: 'endpointUrl',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'e.g. https://my-mcp-server.ai/mcp',\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'The URL of the MCP server to connect to',\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: 'MCP OAuth2',\n\t\t\t\t\t\tvalue: 'mcpOAuth2Api',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Multiple Headers Auth',\n\t\t\t\t\t\tvalue: 'multipleHeadersAuth',\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', 'mcpOAuth2Api', 'multipleHeadersAuth'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Tool',\n\t\t\t\tname: 'tool',\n\t\t\t\ttype: 'resourceLocator',\n\t\t\t\tdefault: { mode: 'list', value: '' },\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'The tool to use',\n\t\t\t\tmodes: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'From List',\n\t\t\t\t\t\tname: 'list',\n\t\t\t\t\t\ttype: 'list',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tsearchListMethod: 'getTools',\n\t\t\t\t\t\t\tsearchable: true,\n\t\t\t\t\t\t\tskipCredentialsCheckInRLC: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'ID',\n\t\t\t\t\t\tname: 'id',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Input Mode',\n\t\t\t\tname: 'inputMode',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'manual',\n\t\t\t\tnoDataExpression: true,\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Manual',\n\t\t\t\t\t\tvalue: 'manual',\n\t\t\t\t\t\tdescription: 'Manually specify the input data for each tool parameter',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'JSON',\n\t\t\t\t\t\tvalue: 'json',\n\t\t\t\t\t\tdescription: 'Specify the input data as a JSON object',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Parameters',\n\t\t\t\tname: 'parameters',\n\t\t\t\ttype: 'resourceMapper',\n\t\t\t\tdefault: {\n\t\t\t\t\tmappingMode: 'defineBelow',\n\t\t\t\t\tvalue: null,\n\t\t\t\t},\n\t\t\t\tnoDataExpression: true,\n\t\t\t\trequired: true,\n\t\t\t\ttypeOptions: {\n\t\t\t\t\tloadOptionsDependsOn: ['tool.value'],\n\t\t\t\t\tresourceMapper: {\n\t\t\t\t\t\tresourceMapperMethod: 'getToolParameters',\n\t\t\t\t\t\thideNoDataError: true,\n\t\t\t\t\t\taddAllFields: false,\n\t\t\t\t\t\tsupportAutoMap: false,\n\t\t\t\t\t\tmode: 'add',\n\t\t\t\t\t\tfieldWords: {\n\t\t\t\t\t\t\tsingular: 'parameter',\n\t\t\t\t\t\t\tplural: 'parameters',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tinputMode: ['manual'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'JSON',\n\t\t\t\tname: 'jsonInput',\n\t\t\t\ttype: 'json',\n\t\t\t\ttypeOptions: {\n\t\t\t\t\trows: 5,\n\t\t\t\t},\n\t\t\t\tdefault: '{\\n \"my_field_1\": \"value\",\\n \"my_field_2\": 1\\n}\\n',\n\t\t\t\tvalidateType: 'object',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tinputMode: ['json'],\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: 'options',\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\tdescription: 'Additional options to add',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Convert to Binary',\n\t\t\t\t\t\tname: 'convertToBinary',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdefault: true,\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Whether to convert images and audio to binary data. If false, images and audio will be returned as base64 encoded strings.',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Timeout',\n\t\t\t\t\t\tname: 'timeout',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tminValue: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: 60000,\n\t\t\t\t\t\tdescription: 'Time in ms to wait for tool calls to finish',\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\tlistSearch,\n\t\tresourceMapping,\n\t};\n\n\tasync execute(\n\t\tthis: IExecuteFunctions,\n\t): Promise<INodeExecutionData[][] | NodeExecutionWithMetadata[][] | null> {\n\t\tconst authentication = this.getNodeParameter('authentication', 0) as McpAuthenticationOption;\n\t\tconst serverTransport = this.getNodeParameter('serverTransport', 0) as McpServerTransport;\n\t\tconst endpointUrl = this.getNodeParameter('endpointUrl', 0) as string;\n\t\tconst node = this.getNode();\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\tonUnauthorized: async (headers) => await tryRefreshOAuth2Token(this, authentication, headers),\n\t\t});\n\t\tif (!client.ok) {\n\t\t\tthrow mapToNodeOperationError(node, client.error);\n\t\t}\n\n\t\tconst inputMode = this.getNodeParameter('inputMode', 0, 'manual') as 'manual' | 'json';\n\t\tconst items = this.getInputData();\n\t\tconst returnData: INodeExecutionData[] = [];\n\t\tfor (let itemIndex = 0; itemIndex < items.length; itemIndex++) {\n\t\t\ttry {\n\t\t\t\tconst tool = this.getNodeParameter('tool.value', itemIndex) as string;\n\t\t\t\tconst options = this.getNodeParameter('options', itemIndex);\n\t\t\t\tlet parameters: IDataObject = {};\n\t\t\t\tif (inputMode === 'manual') {\n\t\t\t\t\tparameters = this.getNodeParameter('parameters.value', itemIndex) as IDataObject;\n\t\t\t\t} else {\n\t\t\t\t\tparameters = this.getNodeParameter('jsonInput', itemIndex) as IDataObject;\n\t\t\t\t}\n\n\t\t\t\tconst result = (await client.result.callTool(\n\t\t\t\t\t{\n\t\t\t\t\t\tname: tool,\n\t\t\t\t\t\targuments: parameters,\n\t\t\t\t\t},\n\t\t\t\t\tundefined,\n\t\t\t\t\t{\n\t\t\t\t\t\ttimeout: options.timeout ? Number(options.timeout) : undefined,\n\t\t\t\t\t},\n\t\t\t\t)) as CallToolResult;\n\n\t\t\t\tlet binaryIndex = 0;\n\t\t\t\tconst binary: IBinaryKeyData = {};\n\t\t\t\tconst content: IDataObject[] = [];\n\t\t\t\tconst convertToBinary = options.convertToBinary ?? true;\n\t\t\t\tfor (const contentItem of result.content) {\n\t\t\t\t\tif (contentItem.type === 'text') {\n\t\t\t\t\t\tcontent.push({\n\t\t\t\t\t\t\t...contentItem,\n\t\t\t\t\t\t\ttext: jsonParse(contentItem.text, { fallbackValue: contentItem.text }),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (convertToBinary && (contentItem.type === 'image' || contentItem.type === 'audio')) {\n\t\t\t\t\t\tbinary[`data_${binaryIndex}`] = await this.helpers.prepareBinaryData(\n\t\t\t\t\t\t\tBuffer.from(contentItem.data, 'base64'),\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tcontentItem.mimeType,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbinaryIndex++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tcontent.push(contentItem as IDataObject);\n\t\t\t\t}\n\n\t\t\t\treturnData.push({\n\t\t\t\t\tjson: {\n\t\t\t\t\t\tcontent: content.length > 0 ? content : undefined,\n\t\t\t\t\t},\n\t\t\t\t\tbinary: Object.keys(binary).length > 0 ? binary : undefined,\n\t\t\t\t\tpairedItem: {\n\t\t\t\t\t\titem: itemIndex,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (e) {\n\t\t\t\tconst errorMessage =\n\t\t\t\t\te instanceof ZodError ? prettifyError(e) : e instanceof Error ? e.message : String(e);\n\t\t\t\tif (this.continueOnFail()) {\n\t\t\t\t\treturnData.push({\n\t\t\t\t\t\tjson: {\n\t\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\t\tmessage: errorMessage,\n\t\t\t\t\t\t\t\tissues: e instanceof ZodError ? e.issues : undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpairedItem: {\n\t\t\t\t\t\t\titem: itemIndex,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tthrow new NodeOperationError(node, errorMessage, {\n\t\t\t\t\titemIndex,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn [returnData];\n\t}\n}\n"],"mappings":"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","names":["headers"]}
|
|
@@ -88,8 +88,8 @@ class McpClientTool {
|
|
|
88
88
|
displayName: "MCP Browser Tool",
|
|
89
89
|
name: "mcpClientTool",
|
|
90
90
|
icon: {
|
|
91
|
-
light: "file
|
|
92
|
-
dark: "file
|
|
91
|
+
light: "file:nodes/assets/mcp.svg",
|
|
92
|
+
dark: "file:nodes/assets/mcp.dark.svg"
|
|
93
93
|
},
|
|
94
94
|
group: ["output"],
|
|
95
95
|
version: [1, 1.1, 1.2],
|
|
@@ -298,7 +298,11 @@ class McpClientTool {
|
|
|
298
298
|
displayName: "cdp Endpoint URL",
|
|
299
299
|
name: "cdp_endpointurl",
|
|
300
300
|
type: "string",
|
|
301
|
-
default: ""
|
|
301
|
+
default: "",
|
|
302
|
+
typeOptions: {
|
|
303
|
+
placeholder: "wss://gridnew.doingerp.com/devtools/02451af47fd279b6a42ff166683ad96f"
|
|
304
|
+
},
|
|
305
|
+
description: "The WebSocket endpoint URL for CDP connection"
|
|
302
306
|
},
|
|
303
307
|
{
|
|
304
308
|
displayName: "Timeout",
|
|
@@ -371,16 +375,21 @@ class McpClientTool {
|
|
|
371
375
|
if (!mcpTools?.length) {
|
|
372
376
|
throw new import_n8n_workflow.NodeOperationError(node, "MCP Server returned no tools", { itemIndex });
|
|
373
377
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
378
|
+
if (config.cdp_endpointurl && typeof config.cdp_endpointurl === "string" && config.cdp_endpointurl.trim() !== "") {
|
|
379
|
+
await client.callTool(
|
|
380
|
+
{
|
|
381
|
+
name: "browser_connect_cdp",
|
|
382
|
+
arguments: {
|
|
383
|
+
// Pass common keys to maximize compatibility across server implementations
|
|
384
|
+
endpoint: config.cdp_endpointurl
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
void 0,
|
|
388
|
+
{
|
|
389
|
+
timeout: config.timeout ? Number(config.timeout) : void 0
|
|
390
|
+
}
|
|
391
|
+
);
|
|
392
|
+
}
|
|
384
393
|
for (const tool of mcpTools) {
|
|
385
394
|
if (!item.json.tool || typeof item.json.tool !== "string") {
|
|
386
395
|
throw new import_n8n_workflow.NodeOperationError(node, "Tool name not found in item.json.tool or item.tool", {
|
|
@@ -394,12 +403,12 @@ class McpClientTool {
|
|
|
394
403
|
name: tool.name,
|
|
395
404
|
arguments: toolArguments
|
|
396
405
|
};
|
|
397
|
-
const
|
|
406
|
+
const result = await client.callTool(params, import_types.CallToolResultSchema, {
|
|
398
407
|
timeout: config.timeout
|
|
399
408
|
});
|
|
400
409
|
returnData.push({
|
|
401
410
|
json: {
|
|
402
|
-
response:
|
|
411
|
+
response: result.content || result
|
|
403
412
|
},
|
|
404
413
|
pairedItem: {
|
|
405
414
|
item: itemIndex
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../nodes/McpClientToolEX/McpClientTool.node.ts"],"sourcesContent":["import { CallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport {\n\ttype IDataObject,\n\ttype IExecuteFunctions,\n\ttype INodeExecutionData,\n\tNodeConnectionTypes,\n\tNodeOperationError,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype ISupplyDataFunctions,\n\ttype SupplyData,\n} from 'n8n-workflow';\n\nimport { logWrapper } from '../shared/logWrapper';\nimport { getConnectionHintNoticeField } from '../shared/sharedFields';\n\nimport { getTools } from './loadOptions';\nimport type { McpToolIncludeMode } from './types';\nimport { createCallTool, getSelectedTools, McpToolkit, mcpToolToDynamicTool } from './utils';\nimport { credentials, transportSelect } from '../shared/descriptions';\nimport type { McpAuthenticationOption, McpServerTransport } from '../shared/types';\nimport {\n\tconnectMcpClient,\n\tgetAllTools,\n\tgetAuthHeaders,\n\tmapToNodeOperationError,\n\ttryRefreshOAuth2Token,\n} from '../shared/utils';\n\n/**\n * Get node parameters for MCP client configuration\n */\nfunction getNodeConfig(\n\tctx: ISupplyDataFunctions | IExecuteFunctions,\n\titemIndex: number,\n): {\n\tauthentication: McpAuthenticationOption;\n\ttimeout: number;\n\tserverTransport: McpServerTransport;\n\tendpointUrl: string;\n\tcdp_endpointurl?: string;\n\tmode: McpToolIncludeMode;\n\tincludeTools: string[];\n\texcludeTools: string[];\n} {\n\tconst node = ctx.getNode();\n\tconst authentication = ctx.getNodeParameter(\n\t\t'authentication',\n\t\titemIndex,\n\t) as McpAuthenticationOption;\n\tconst timeout = ctx.getNodeParameter('options.timeout', itemIndex, 60000) as number;\n\tlet serverTransport: McpServerTransport;\n\tlet endpointUrl: string;\n\tif (node.typeVersion === 1) {\n\t\tserverTransport = 'sse';\n\t\tendpointUrl = ctx.getNodeParameter('sseEndpoint', itemIndex) as string;\n\t} else {\n\t\tserverTransport = ctx.getNodeParameter('serverTransport', itemIndex) as McpServerTransport;\n\t\tendpointUrl = ctx.getNodeParameter('endpointUrl', itemIndex) as string;\n\t}\n\tconst cdp_endpointurl = ctx.getNodeParameter('options.cdp_endpointurl', itemIndex,'wss://gridnew.doingerp.com/devtools/02451af47fd279b6a42ff166683ad96f') as string;\n\tconst mode = ctx.getNodeParameter('include', itemIndex) as McpToolIncludeMode;\n\tconst includeTools = ctx.getNodeParameter('includeTools', itemIndex, []) as string[];\n\tconst excludeTools = ctx.getNodeParameter('excludeTools', itemIndex, []) as string[];\n\n\treturn {\n\t\tauthentication,\n\t\ttimeout,\n\t\tserverTransport,\n\t\tendpointUrl,\n\t\tmode,\n\t\tcdp_endpointurl,\n\t\tincludeTools,\n\t\texcludeTools,\n\t};\n}\n\n/**\n * Connect to MCP server and get filtered tools\n */\nasync function connectAndGetTools(\n\tctx: ISupplyDataFunctions | IExecuteFunctions,\n\tconfig: ReturnType<typeof getNodeConfig>,\n) {\n\tconst node = ctx.getNode();\n\tconst { headers } = await getAuthHeaders(ctx, config.authentication);\n\n\tconst client = await connectMcpClient({\n\t\tserverTransport: config.serverTransport,\n\t\tendpointUrl: config.endpointUrl,\n\t\theaders,\n\t\tname: node.type,\n\t\tversion: node.typeVersion,\n\t\tonUnauthorized: async (headers) =>\n\t\t\tawait tryRefreshOAuth2Token(ctx, config.authentication, headers),\n\t});\n\n\tif (!client.ok) {\n\t\treturn { client, mcpTools: null, error: client.error };\n\t}\n\n\tconst allTools = await getAllTools(client.result);\n\tconst mcpTools = getSelectedTools({\n\t\ttools: allTools,\n\t\tmode: config.mode,\n\t\tincludeTools: config.includeTools,\n\t\texcludeTools: config.excludeTools,\n\t});\n\n\treturn { client: client.result, mcpTools, error: null };\n}\n\nexport class McpClientTool implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'MCP Browser Tool',\n\t\tname: 'mcpClientTool',\n\t\ticon: {\n\t\t\t\tlight: 'file:../assets/mcp.svg',\n\t\t\t\tdark: 'file:../assets/mcp.dark.svg',\n\t\t},\n\t\tgroup: ['output'],\n\t\tversion: [1, 1.1, 1.2],\n\t\tdescription: 'Connect tools from an MCP Server',\n\t\tdefaults: {\n\t\t\tname: 'MCP Browser Tool',\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 Browser Tool'],\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\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\ttransportSelect({\n\t\t\t\tdefaultOption: 'sse',\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}),\n\t\t\ttransportSelect({\n\t\t\t\tdefaultOption: 'httpStreamable',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.2 } }],\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\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { lt: 1.2 } }],\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: 'MCP OAuth2',\n\t\t\t\t\t\tvalue: 'mcpOAuth2Api',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Multiple Headers Auth',\n\t\t\t\t\t\tvalue: 'multipleHeadersAuth',\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\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.2 } }],\n\t\t\t\t\t},\n\t\t\t\t},\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', 'mcpOAuth2Api', 'multipleHeadersAuth'],\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\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\tdescription: 'Additional options to add',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'cdp Endpoint URL',\n\t\t\t\t\t\tname: 'cdp_endpointurl',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Timeout',\n\t\t\t\t\t\tname: 'timeout',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tminValue: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: 60000,\n\t\t\t\t\t\tdescription: 'Time in ms to wait for tool calls to finish',\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 node = this.getNode();\n\t\tconst config = getNodeConfig(this, itemIndex);\n\t\tconst setError = (error: NodeOperationError): SupplyData => {\n\t\t\tthis.addOutputData(NodeConnectionTypes.AiTool, itemIndex, error);\n\t\t\tthrow error;\n\t\t};\n\n\t\tconst { client, mcpTools, error } = await connectAndGetTools(this, config);\n\n\t\tif (error) {\n\t\t\tthis.logger.error('McpClientTool: Failed to connect to MCP Server', { error });\n\t\t\treturn setError(mapToNodeOperationError(node, error));\n\t\t}\n\n\t\tthis.logger.debug('McpClientTool: Successfully connected to MCP Server');\n\n\t\tif (!mcpTools?.length) {\n\t\t\treturn setError(\n\t\t\t\tnew NodeOperationError(node, 'MCP Server returned no tools', {\n\t\t\t\t\titemIndex,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Connected successfully to your MCP server but it returned an empty list of tools.',\n\t\t\t\t}),\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, config.timeout, (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.close() };\n\t}\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tconst node = this.getNode();\n\t\tconst items = this.getInputData();\n\t\tconst returnData: INodeExecutionData[] = [];\n\n\t\tfor (let itemIndex = 0; itemIndex < items.length; itemIndex++) {\n\t\t\tconst item = items[itemIndex];\n\t\t\tconst config = getNodeConfig(this, itemIndex);\n\n\t\t\tconst { client, mcpTools, error } = await connectAndGetTools(this, config);\n\n\t\t\tif (error) {\n\t\t\t\tthrow new NodeOperationError(node, error.error, { itemIndex });\n\t\t\t}\n\n\t\t\tif (!mcpTools?.length) {\n\t\t\t\tthrow new NodeOperationError(node, 'MCP Server returned no tools', { itemIndex });\n\t\t\t}\n\t\t\tconst result = (await client.callTool(\n\t\t\t\t{\n\t\t\t\t\tname: \"browser_cdp_connect\",\n\t\t\t\t\targuments: { \"endpoint\": config.cdp_endpointurl },\n\t\t\t\t},\n\t\t\t\tundefined,\n\t\t\t\t{\n\t\t\t\t\ttimeout: config.timeout ? Number(config.timeout) : undefined,\n\t\t\t\t},\n\t\t\t)) as CallToolResult;\n\t\t\tfor (const tool of mcpTools) {\n\t\t\t\t// Check for tool name in item.json.tool (for toolkit execution from agent)\n\t\t\t\t// or item.tool (for direct execution)\n\t\t\t\tif (!item.json.tool || typeof item.json.tool !== 'string') {\n\t\t\t\t\tthrow new NodeOperationError(node, 'Tool name not found in item.json.tool or item.tool', {\n\t\t\t\t\t\titemIndex,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst toolName = item.json.tool;\n\t\t\t\tif (toolName === tool.name) {\n\t\t\t\t\t// Extract the tool name from arguments before passing to MCP\n\t\t\t\t\tconst { tool: _, ...toolArguments } = item.json;\n\t\t\t\t\tconst params: {\n\t\t\t\t\t\tname: string;\n\t\t\t\t\t\targuments: IDataObject;\n\t\t\t\t\t} = {\n\t\t\t\t\t\tname: tool.name,\n\t\t\t\t\t\targuments: toolArguments,\n\t\t\t\t\t};\n\t\t\t\t\tconst result = await client.callTool(params, CallToolResultSchema, {\n\t\t\t\t\t\ttimeout: config.timeout,\n\t\t\t\t\t});\n\t\t\t\t\treturnData.push({\n\t\t\t\t\t\tjson: {\n\t\t\t\t\t\t\tresponse: (result.content || result) as IDataObject,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpairedItem: {\n\t\t\t\t\t\t\titem: itemIndex,\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\treturn [returnData];\n\t}\n}"],"mappings":"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","names":["import_utils","headers","error","result"]}
|
|
1
|
+
{"version":3,"sources":["../../nodes/McpClientToolEX/McpClientTool.node.ts"],"sourcesContent":["import { CallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport {\n\ttype IDataObject,\n\ttype IExecuteFunctions,\n\ttype INodeExecutionData,\n\tNodeConnectionTypes,\n\tNodeOperationError,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype ISupplyDataFunctions,\n\ttype SupplyData,\n} from 'n8n-workflow';\n\nimport { logWrapper } from '../shared/logWrapper';\nimport { getConnectionHintNoticeField } from '../shared/sharedFields';\n\nimport { getTools } from './loadOptions';\nimport type { McpToolIncludeMode } from './types';\nimport { createCallTool, getSelectedTools, McpToolkit, mcpToolToDynamicTool } from './utils';\nimport { credentials, transportSelect } from '../shared/descriptions';\nimport type { McpAuthenticationOption, McpServerTransport } from '../shared/types';\nimport {\n\tconnectMcpClient,\n\tgetAllTools,\n\tgetAuthHeaders,\n\tmapToNodeOperationError,\n\ttryRefreshOAuth2Token,\n} from '../shared/utils';\n\n/**\n * Get node parameters for MCP client configuration\n */\nfunction getNodeConfig(\n\tctx: ISupplyDataFunctions | IExecuteFunctions,\n\titemIndex: number,\n): {\n\tauthentication: McpAuthenticationOption;\n\ttimeout: number;\n\tserverTransport: McpServerTransport;\n\tendpointUrl: string;\n\tcdp_endpointurl?: string;\n\tmode: McpToolIncludeMode;\n\tincludeTools: string[];\n\texcludeTools: string[];\n} {\n\tconst node = ctx.getNode();\n\tconst authentication = ctx.getNodeParameter(\n\t\t'authentication',\n\t\titemIndex,\n\t) as McpAuthenticationOption;\n\tconst timeout = ctx.getNodeParameter('options.timeout', itemIndex, 60000) as number;\n\tlet serverTransport: McpServerTransport;\n\tlet endpointUrl: string;\n\tif (node.typeVersion === 1) {\n\t\tserverTransport = 'sse';\n\t\tendpointUrl = ctx.getNodeParameter('sseEndpoint', itemIndex) as string;\n\t} else {\n\t\tserverTransport = ctx.getNodeParameter('serverTransport', itemIndex) as McpServerTransport;\n\t\tendpointUrl = ctx.getNodeParameter('endpointUrl', itemIndex) as string;\n\t}\n\tconst cdp_endpointurl = ctx.getNodeParameter('options.cdp_endpointurl', itemIndex,'wss://gridnew.doingerp.com/devtools/02451af47fd279b6a42ff166683ad96f') as string;\n\tconst mode = ctx.getNodeParameter('include', itemIndex) as McpToolIncludeMode;\n\tconst includeTools = ctx.getNodeParameter('includeTools', itemIndex, []) as string[];\n\tconst excludeTools = ctx.getNodeParameter('excludeTools', itemIndex, []) as string[];\n\n\treturn {\n\t\tauthentication,\n\t\ttimeout,\n\t\tserverTransport,\n\t\tendpointUrl,\n\t\tmode,\n\t\tcdp_endpointurl,\n\t\tincludeTools,\n\t\texcludeTools,\n\t};\n}\n\n/**\n * Connect to MCP server and get filtered tools\n */\nasync function connectAndGetTools(\n\tctx: ISupplyDataFunctions | IExecuteFunctions,\n\tconfig: ReturnType<typeof getNodeConfig>,\n) {\n\tconst node = ctx.getNode();\n\tconst { headers } = await getAuthHeaders(ctx, config.authentication);\n\n\tconst client = await connectMcpClient({\n\t\tserverTransport: config.serverTransport,\n\t\tendpointUrl: config.endpointUrl,\n\t\theaders,\n\t\tname: node.type,\n\t\tversion: node.typeVersion,\n\t\tonUnauthorized: async (headers) =>\n\t\t\tawait tryRefreshOAuth2Token(ctx, config.authentication, headers),\n\t});\n\n\tif (!client.ok) {\n\t\treturn { client, mcpTools: null, error: client.error };\n\t}\n\n\tconst allTools = await getAllTools(client.result);\n\tconst mcpTools = getSelectedTools({\n\t\ttools: allTools,\n\t\tmode: config.mode,\n\t\tincludeTools: config.includeTools,\n\t\texcludeTools: config.excludeTools,\n\t});\n\n\treturn { client: client.result, mcpTools, error: null };\n}\n\nexport class McpClientTool implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'MCP Browser Tool',\n\t\tname: 'mcpClientTool',\n\t\ticon: {\n\t\t\tlight: 'file:nodes/assets/mcp.svg',\n\t\t\tdark: 'file:nodes/assets/mcp.dark.svg',\n\t\t},\n\t\tgroup: ['output'],\n\t\tversion: [1, 1.1, 1.2],\n\t\tdescription: 'Connect tools from an MCP Server',\n\t\tdefaults: {\n\t\t\tname: 'MCP Browser Tool',\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 Browser Tool'],\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\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\ttransportSelect({\n\t\t\t\tdefaultOption: 'sse',\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}),\n\t\t\ttransportSelect({\n\t\t\t\tdefaultOption: 'httpStreamable',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.2 } }],\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\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { lt: 1.2 } }],\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: 'MCP OAuth2',\n\t\t\t\t\t\tvalue: 'mcpOAuth2Api',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Multiple Headers Auth',\n\t\t\t\t\t\tvalue: 'multipleHeadersAuth',\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\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.2 } }],\n\t\t\t\t\t},\n\t\t\t\t},\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', 'mcpOAuth2Api', 'multipleHeadersAuth'],\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\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\tdescription: 'Additional options to add',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'cdp Endpoint URL',\n\t\t\t\t\t\tname: 'cdp_endpointurl',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tplaceholder: 'wss://gridnew.doingerp.com/devtools/02451af47fd279b6a42ff166683ad96f',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdescription: 'The WebSocket endpoint URL for CDP connection',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Timeout',\n\t\t\t\t\t\tname: 'timeout',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tminValue: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: 60000,\n\t\t\t\t\t\tdescription: 'Time in ms to wait for tool calls to finish',\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 node = this.getNode();\n\t\tconst config = getNodeConfig(this, itemIndex);\n\t\tconst setError = (error: NodeOperationError): SupplyData => {\n\t\t\tthis.addOutputData(NodeConnectionTypes.AiTool, itemIndex, error);\n\t\t\tthrow error;\n\t\t};\n\n\t\tconst { client, mcpTools, error } = await connectAndGetTools(this, config);\n\n\t\tif (error) {\n\t\t\tthis.logger.error('McpClientTool: Failed to connect to MCP Server', { error });\n\t\t\treturn setError(mapToNodeOperationError(node, error));\n\t\t}\n\n\t\tthis.logger.debug('McpClientTool: Successfully connected to MCP Server');\n\n\t\tif (!mcpTools?.length) {\n\t\t\treturn setError(\n\t\t\t\tnew NodeOperationError(node, 'MCP Server returned no tools', {\n\t\t\t\t\titemIndex,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Connected successfully to your MCP server but it returned an empty list of tools.',\n\t\t\t\t}),\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, config.timeout, (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.close() };\n\t}\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tconst node = this.getNode();\n\t\tconst items = this.getInputData();\n\t\tconst returnData: INodeExecutionData[] = [];\n\n\t\tfor (let itemIndex = 0; itemIndex < items.length; itemIndex++) {\n\t\t\tconst item = items[itemIndex];\n\t\t\tconst config = getNodeConfig(this, itemIndex);\n\n\t\t\tconst { client, mcpTools, error } = await connectAndGetTools(this, config);\n\n\t\t\tif (error) {\n\t\t\t\tthrow new NodeOperationError(node, error.error, { itemIndex });\n\t\t\t}\n\n\t\t\tif (!mcpTools?.length) {\n\t\t\t\tthrow new NodeOperationError(node, 'MCP Server returned no tools', { itemIndex });\n\t\t\t}\n\t\t\t// Attempt to establish CDP connection first if an endpoint is provided\n\t\t\tif (config.cdp_endpointurl && typeof config.cdp_endpointurl === 'string' && config.cdp_endpointurl.trim() !== '') {\n\t\t\t\tawait client.callTool(\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'browser_connect_cdp',\n\t\t\t\t\t\targuments: {\n\t\t\t\t\t\t\t// Pass common keys to maximize compatibility across server implementations\n\t\t\t\t\t\t\tendpoint: config.cdp_endpointurl,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tundefined,\n\t\t\t\t\t{\n\t\t\t\t\t\ttimeout: config.timeout ? Number(config.timeout) : undefined,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const tool of mcpTools) {\n\t\t\t\t// Check for tool name in item.json.tool (for toolkit execution from agent)\n\t\t\t\t// or item.tool (for direct execution)\n\t\t\t\tif (!item.json.tool || typeof item.json.tool !== 'string') {\n\t\t\t\t\tthrow new NodeOperationError(node, 'Tool name not found in item.json.tool or item.tool', {\n\t\t\t\t\t\titemIndex,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst toolName = item.json.tool;\n\t\t\t\tif (toolName === tool.name) {\n\t\t\t\t\t// Extract the tool name from arguments before passing to MCP\n\t\t\t\t\tconst { tool: _, ...toolArguments } = item.json;\n\t\t\t\t\tconst params: {\n\t\t\t\t\t\tname: string;\n\t\t\t\t\t\targuments: IDataObject;\n\t\t\t\t\t} = {\n\t\t\t\t\t\tname: tool.name,\n\t\t\t\t\t\targuments: toolArguments,\n\t\t\t\t\t};\n\t\t\t\t\tconst result = await client.callTool(params, CallToolResultSchema, {\n\t\t\t\t\t\ttimeout: config.timeout,\n\t\t\t\t\t});\n\t\t\t\t\treturnData.push({\n\t\t\t\t\t\tjson: {\n\t\t\t\t\t\t\tresponse: (result.content || result) as IDataObject,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpairedItem: {\n\t\t\t\t\t\t\titem: itemIndex,\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\treturn [returnData];\n\t}\n}"],"mappings":"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","names":["import_utils","headers","error"]}
|
|
@@ -48,8 +48,7 @@ async function getTools() {
|
|
|
48
48
|
throw (0, import_utils.mapToNodeOperationError)(node, client.error);
|
|
49
49
|
}
|
|
50
50
|
const tools = await (0, import_utils.getAllTools)(client.result);
|
|
51
|
-
const
|
|
52
|
-
await client.result.callTool(calledTool);
|
|
51
|
+
const calltool = tools.find((tool) => tool.name === "browser_connect_cdp");
|
|
53
52
|
return tools.map((tool) => ({
|
|
54
53
|
name: tool.name,
|
|
55
54
|
value: tool.name,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../nodes/McpClientToolEX/loadOptions.ts"],"sourcesContent":["import { type ILoadOptionsFunctions, type INodePropertyOptions } from 'n8n-workflow';\n\nimport type { McpAuthenticationOption, McpServerTransport } from '../shared/types';\nimport {\n\tconnectMcpClient,\n\tgetAllTools,\n\tgetAuthHeaders,\n\tmapToNodeOperationError,\n\ttryRefreshOAuth2Token,\n} from '../shared/utils';\n\nexport async function getTools(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {\n\tconst authentication = this.getNodeParameter('authentication') as McpAuthenticationOption;\n\tconst node = this.getNode();\n\tlet serverTransport: McpServerTransport;\n\tlet endpointUrl: string;\n\tlet cdp_endpointurl = this.getNodeParameter('options.cdp_endpointurl') as string;\n\tif (node.typeVersion === 1) {\n\t\tserverTransport = 'sse';\n\t\tendpointUrl = this.getNodeParameter('sseEndpoint') as string;\n\t} else {\n\t\tserverTransport = this.getNodeParameter('serverTransport') as McpServerTransport;\n\t\tendpointUrl = this.getNodeParameter('endpointUrl') as string;\n\t}\n\tconst { headers } = await getAuthHeaders(this, authentication);\n\tconst client = await connectMcpClient({\n\t\tserverTransport,\n\t\tendpointUrl,\n\t\theaders,\n\t\tname: node.type,\n\t\tversion: node.typeVersion,\n\t\tonUnauthorized: async (headers) => await tryRefreshOAuth2Token(this, authentication, headers),\n\t});\n\n\tif (!client.ok) {\n\t\tthrow mapToNodeOperationError(node, client.error);\n\t}\n\n\tconst tools = await getAllTools(client.result);\n\tconst
|
|
1
|
+
{"version":3,"sources":["../../nodes/McpClientToolEX/loadOptions.ts"],"sourcesContent":["import { type ILoadOptionsFunctions, type INodePropertyOptions } from 'n8n-workflow';\n\nimport type { McpAuthenticationOption, McpServerTransport } from '../shared/types';\nimport {\n\tconnectMcpClient,\n\tgetAllTools,\n\tgetAuthHeaders,\n\tmapToNodeOperationError,\n\ttryRefreshOAuth2Token,\n} from '../shared/utils';\n\nexport async function getTools(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {\n\tconst authentication = this.getNodeParameter('authentication') as McpAuthenticationOption;\n\tconst node = this.getNode();\n\tlet serverTransport: McpServerTransport;\n\tlet endpointUrl: string;\n\tlet cdp_endpointurl = this.getNodeParameter('options.cdp_endpointurl') as string;\n\tif (node.typeVersion === 1) {\n\t\tserverTransport = 'sse';\n\t\tendpointUrl = this.getNodeParameter('sseEndpoint') as string;\n\t} else {\n\t\tserverTransport = this.getNodeParameter('serverTransport') as McpServerTransport;\n\t\tendpointUrl = this.getNodeParameter('endpointUrl') as string;\n\t}\n\tconst { headers } = await getAuthHeaders(this, authentication);\n\tconst client = await connectMcpClient({\n\t\tserverTransport,\n\t\tendpointUrl,\n\t\theaders,\n\t\tname: node.type,\n\t\tversion: node.typeVersion,\n\t\tonUnauthorized: async (headers) => await tryRefreshOAuth2Token(this, authentication, headers),\n\t});\n\n\tif (!client.ok) {\n\t\tthrow mapToNodeOperationError(node, client.error);\n\t}\n\n\tconst tools = await getAllTools(client.result);\n\tconst calltool = tools.find((tool) => tool.name === 'browser_connect_cdp');\n\t\n\n\n\treturn tools.map((tool) => ({\n\t\tname: tool.name,\n\t\tvalue: tool.name,\n\t\tdescription: tool.description,\n\t\tinputSchema: tool.inputSchema,\n\t}));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,mBAMO;AAEP,eAAsB,WAAuE;AAC5F,QAAM,iBAAiB,KAAK,iBAAiB,gBAAgB;AAC7D,QAAM,OAAO,KAAK,QAAQ;AAC1B,MAAI;AACJ,MAAI;AACJ,MAAI,kBAAkB,KAAK,iBAAiB,yBAAyB;AACrE,MAAI,KAAK,gBAAgB,GAAG;AAC3B,sBAAkB;AAClB,kBAAc,KAAK,iBAAiB,aAAa;AAAA,EAClD,OAAO;AACN,sBAAkB,KAAK,iBAAiB,iBAAiB;AACzD,kBAAc,KAAK,iBAAiB,aAAa;AAAA,EAClD;AACA,QAAM,EAAE,QAAQ,IAAI,UAAM,6BAAe,MAAM,cAAc;AAC7D,QAAM,SAAS,UAAM,+BAAiB;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,KAAK;AAAA,IACX,SAAS,KAAK;AAAA,IACd,gBAAgB,OAAOA,aAAY,UAAM,oCAAsB,MAAM,gBAAgBA,QAAO;AAAA,EAC7F,CAAC;AAED,MAAI,CAAC,OAAO,IAAI;AACf,cAAM,sCAAwB,MAAM,OAAO,KAAK;AAAA,EACjD;AAEA,QAAM,QAAQ,UAAM,0BAAY,OAAO,MAAM;AAC7C,QAAM,WAAW,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,qBAAqB;AAIzE,SAAO,MAAM,IAAI,CAAC,UAAU;AAAA,IAC3B,MAAM,KAAK;AAAA,IACX,OAAO,KAAK;AAAA,IACZ,aAAa,KAAK;AAAA,IAClB,aAAa,KAAK;AAAA,EACnB,EAAE;AACH;","names":["headers"]}
|
|
@@ -33,8 +33,8 @@ class McpTrigger extends import_n8n_workflow.Node {
|
|
|
33
33
|
displayName: "MCP Browser Trigger",
|
|
34
34
|
name: "mcpTrigger",
|
|
35
35
|
icon: {
|
|
36
|
-
light: "file
|
|
37
|
-
dark: "file
|
|
36
|
+
light: "file:nodes/assets/mcp.svg",
|
|
37
|
+
dark: "file:nodes/assets/mcp.dark.svg"
|
|
38
38
|
},
|
|
39
39
|
group: ["trigger"],
|
|
40
40
|
version: [1, 1.1, 2],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../nodes/McpTriggerEX/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, nodeNameToToolName } from 'n8n-workflow';\n\nimport { getConnectedTools } from '../shared/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 Browser Trigger',\n\t\tname: 'mcpTrigger',\n\t\ticon: {\n\t\t\tlight: 'file:../assets/mcp.svg',\n\t\t\tdark: 'file:../assets/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 Browser endpoint',\n\t\tactivationMessage:\n\t\t\t'You can now connect your MCP Browsers to the URL, using SSE or Streamable HTTP transports.',\n\t\tdefaults: {\n\t\t\tname: 'MCP Browser 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 Browser'],\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>. Publish 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\t{\n\t\t\t\tname: 'default',\n\t\t\t\thttpMethod: 'DELETE',\n\t\t\t\tresponseMode: 'onReceived',\n\t\t\t\tisFullPath: true,\n\t\t\t\tpath: '={{$parameter[\"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 and DELETE requests.\n\t\t\t// POST 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\t\t\t// DELETE is used to terminate the session using the StreamableHTTPServerTransport\n\n\t\t\tif (req.method === 'DELETE') {\n\t\t\t\tawait mcpServerManager.handleDeleteRequest(req, resp);\n\t\t\t} else {\n\t\t\t\t// Check if there is a session and a transport is already established\n\t\t\t\tconst sessionId = mcpServerManager.getSessionId(req);\n\n\t\t\t\tif (sessionId && mcpServerManager.getTransport(sessionId)) {\n\t\t\t\t\tconst connectedTools = await getConnectedTools(context, true);\n\t\t\t\t\tconst wasToolCall = await mcpServerManager.handlePostMessage(req, resp, connectedTools);\n\t\t\t\t\tif (wasToolCall) return { noWebhookResponse: true, workflowData: [[{ json: {} }]] };\n\t\t\t\t} else {\n\t\t\t\t\t// If no session is established, this is a setup request\n\t\t\t\t\t// for the StreamableHTTPServerTransport, so we create a new transport\n\t\t\t\t\tawait mcpServerManager.createServerWithStreamableHTTPTransport(serverName, resp, req);\n\t\t\t\t}\n\t\t\t}\n\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/McpTriggerEX/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, nodeNameToToolName } from 'n8n-workflow';\n\nimport { getConnectedTools } from '../shared/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 Browser Trigger',\n\t\tname: 'mcpTrigger',\n\t\ticon: {\n\t\t\tlight: 'file:nodes/assets/mcp.svg',\n\t\t\tdark: 'file:nodes/assets/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 Browser endpoint',\n\t\tactivationMessage:\n\t\t\t'You can now connect your MCP Browsers to the URL, using SSE or Streamable HTTP transports.',\n\t\tdefaults: {\n\t\t\tname: 'MCP Browser 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 Browser'],\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>. Publish 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\t{\n\t\t\t\tname: 'default',\n\t\t\t\thttpMethod: 'DELETE',\n\t\t\t\tresponseMode: 'onReceived',\n\t\t\t\tisFullPath: true,\n\t\t\t\tpath: '={{$parameter[\"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 and DELETE requests.\n\t\t\t// POST 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\t\t\t// DELETE is used to terminate the session using the StreamableHTTPServerTransport\n\n\t\t\tif (req.method === 'DELETE') {\n\t\t\t\tawait mcpServerManager.handleDeleteRequest(req, resp);\n\t\t\t} else {\n\t\t\t\t// Check if there is a session and a transport is already established\n\t\t\t\tconst sessionId = mcpServerManager.getSessionId(req);\n\n\t\t\t\tif (sessionId && mcpServerManager.getTransport(sessionId)) {\n\t\t\t\t\tconst connectedTools = await getConnectedTools(context, true);\n\t\t\t\t\tconst wasToolCall = await mcpServerManager.handlePostMessage(req, resp, connectedTools);\n\t\t\t\t\tif (wasToolCall) return { noWebhookResponse: true, workflowData: [[{ json: {} }]] };\n\t\t\t\t} else {\n\t\t\t\t\t// If no session is established, this is a setup request\n\t\t\t\t\t// for the StreamableHTTPServerTransport, so we create a new transport\n\t\t\t\t\tawait mcpServerManager.createServerWithStreamableHTTPTransport(serverName, resp, req);\n\t\t\t\t}\n\t\t\t}\n\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":[]}
|