n8n-nodes-browser-smart-automation 0.1.10 → 0.1.12
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 +68 -16
- 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"]}
|
|
@@ -29,6 +29,15 @@ var import_loadOptions = require("./loadOptions");
|
|
|
29
29
|
var import_utils = require("./utils");
|
|
30
30
|
var import_descriptions = require("../shared/descriptions");
|
|
31
31
|
var import_utils2 = require("../shared/utils");
|
|
32
|
+
const mcpClientCache = /* @__PURE__ */ new Map();
|
|
33
|
+
function getCacheKey(serverTransport, endpointUrl, nodeType) {
|
|
34
|
+
return `${nodeType}|${serverTransport}|${endpointUrl}`;
|
|
35
|
+
}
|
|
36
|
+
const cdpConnectedCache = /* @__PURE__ */ new Set();
|
|
37
|
+
function getCdpKey(cacheKey, cdpEndpointUrl) {
|
|
38
|
+
const ep = typeof cdpEndpointUrl === "string" ? cdpEndpointUrl.trim() : "";
|
|
39
|
+
return ep ? `${cacheKey}|cdp:${ep}` : null;
|
|
40
|
+
}
|
|
32
41
|
function getNodeConfig(ctx, itemIndex) {
|
|
33
42
|
const node = ctx.getNode();
|
|
34
43
|
const authentication = ctx.getNodeParameter(
|
|
@@ -63,6 +72,30 @@ function getNodeConfig(ctx, itemIndex) {
|
|
|
63
72
|
async function connectAndGetTools(ctx, config) {
|
|
64
73
|
const node = ctx.getNode();
|
|
65
74
|
const { headers } = await (0, import_utils2.getAuthHeaders)(ctx, config.authentication);
|
|
75
|
+
const cacheKey = getCacheKey(config.serverTransport, config.endpointUrl, node.type);
|
|
76
|
+
const cachedClient = mcpClientCache.get(cacheKey);
|
|
77
|
+
if (cachedClient) {
|
|
78
|
+
const cdpKey2 = getCdpKey(cacheKey, config.cdp_endpointurl);
|
|
79
|
+
if (cdpKey2 && !cdpConnectedCache.has(cdpKey2)) {
|
|
80
|
+
await cachedClient.callTool(
|
|
81
|
+
{
|
|
82
|
+
name: "browser_connect_cdp",
|
|
83
|
+
arguments: { endpoint: config.cdp_endpointurl }
|
|
84
|
+
},
|
|
85
|
+
void 0,
|
|
86
|
+
{ timeout: config.timeout ? Number(config.timeout) : void 0 }
|
|
87
|
+
);
|
|
88
|
+
cdpConnectedCache.add(cdpKey2);
|
|
89
|
+
}
|
|
90
|
+
const allTools2 = await (0, import_utils2.getAllTools)(cachedClient);
|
|
91
|
+
const mcpTools2 = (0, import_utils.getSelectedTools)({
|
|
92
|
+
tools: allTools2,
|
|
93
|
+
mode: config.mode,
|
|
94
|
+
includeTools: config.includeTools,
|
|
95
|
+
excludeTools: config.excludeTools
|
|
96
|
+
});
|
|
97
|
+
return { client: cachedClient, mcpTools: mcpTools2, error: null };
|
|
98
|
+
}
|
|
66
99
|
const client = await (0, import_utils2.connectMcpClient)({
|
|
67
100
|
serverTransport: config.serverTransport,
|
|
68
101
|
endpointUrl: config.endpointUrl,
|
|
@@ -74,6 +107,19 @@ async function connectAndGetTools(ctx, config) {
|
|
|
74
107
|
if (!client.ok) {
|
|
75
108
|
return { client, mcpTools: null, error: client.error };
|
|
76
109
|
}
|
|
110
|
+
mcpClientCache.set(cacheKey, client.result);
|
|
111
|
+
const cdpKey = getCdpKey(cacheKey, config.cdp_endpointurl);
|
|
112
|
+
if (cdpKey && !cdpConnectedCache.has(cdpKey)) {
|
|
113
|
+
await client.result.callTool(
|
|
114
|
+
{
|
|
115
|
+
name: "browser_connect_cdp",
|
|
116
|
+
arguments: { endpoint: config.cdp_endpointurl }
|
|
117
|
+
},
|
|
118
|
+
void 0,
|
|
119
|
+
{ timeout: config.timeout ? Number(config.timeout) : void 0 }
|
|
120
|
+
);
|
|
121
|
+
cdpConnectedCache.add(cdpKey);
|
|
122
|
+
}
|
|
77
123
|
const allTools = await (0, import_utils2.getAllTools)(client.result);
|
|
78
124
|
const mcpTools = (0, import_utils.getSelectedTools)({
|
|
79
125
|
tools: allTools,
|
|
@@ -88,8 +134,8 @@ class McpClientTool {
|
|
|
88
134
|
displayName: "MCP Browser Tool",
|
|
89
135
|
name: "mcpClientTool",
|
|
90
136
|
icon: {
|
|
91
|
-
light: "file
|
|
92
|
-
dark: "file
|
|
137
|
+
light: "file:nodes/assets/mcp.svg",
|
|
138
|
+
dark: "file:nodes/assets/mcp.dark.svg"
|
|
93
139
|
},
|
|
94
140
|
group: ["output"],
|
|
95
141
|
version: [1, 1.1, 1.2],
|
|
@@ -298,7 +344,11 @@ class McpClientTool {
|
|
|
298
344
|
displayName: "cdp Endpoint URL",
|
|
299
345
|
name: "cdp_endpointurl",
|
|
300
346
|
type: "string",
|
|
301
|
-
default: ""
|
|
347
|
+
default: "",
|
|
348
|
+
typeOptions: {
|
|
349
|
+
placeholder: "wss://gridnew.doingerp.com/devtools/02451af47fd279b6a42ff166683ad96f"
|
|
350
|
+
},
|
|
351
|
+
description: "The WebSocket endpoint URL for CDP connection"
|
|
302
352
|
},
|
|
303
353
|
{
|
|
304
354
|
displayName: "Timeout",
|
|
@@ -355,7 +405,19 @@ class McpClientTool {
|
|
|
355
405
|
);
|
|
356
406
|
this.logger.debug(`McpClientTool: Connected to MCP Server with ${tools.length} tools`);
|
|
357
407
|
const toolkit = new import_utils.McpToolkit(tools);
|
|
358
|
-
|
|
408
|
+
const cacheKey = getCacheKey(config.serverTransport, config.endpointUrl, node.type);
|
|
409
|
+
const cdpKey = getCdpKey(cacheKey, config.cdp_endpointurl);
|
|
410
|
+
return {
|
|
411
|
+
response: toolkit,
|
|
412
|
+
closeFunction: async () => {
|
|
413
|
+
try {
|
|
414
|
+
await client.close();
|
|
415
|
+
} finally {
|
|
416
|
+
mcpClientCache.delete(cacheKey);
|
|
417
|
+
if (cdpKey) cdpConnectedCache.delete(cdpKey);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
};
|
|
359
421
|
}
|
|
360
422
|
async execute() {
|
|
361
423
|
const node = this.getNode();
|
|
@@ -371,16 +433,6 @@ class McpClientTool {
|
|
|
371
433
|
if (!mcpTools?.length) {
|
|
372
434
|
throw new import_n8n_workflow.NodeOperationError(node, "MCP Server returned no tools", { itemIndex });
|
|
373
435
|
}
|
|
374
|
-
const result = await client.callTool(
|
|
375
|
-
{
|
|
376
|
-
name: "browser_cdp_connect",
|
|
377
|
-
arguments: { "endpoint": config.cdp_endpointurl }
|
|
378
|
-
},
|
|
379
|
-
void 0,
|
|
380
|
-
{
|
|
381
|
-
timeout: config.timeout ? Number(config.timeout) : void 0
|
|
382
|
-
}
|
|
383
|
-
);
|
|
384
436
|
for (const tool of mcpTools) {
|
|
385
437
|
if (!item.json.tool || typeof item.json.tool !== "string") {
|
|
386
438
|
throw new import_n8n_workflow.NodeOperationError(node, "Tool name not found in item.json.tool or item.tool", {
|
|
@@ -394,12 +446,12 @@ class McpClientTool {
|
|
|
394
446
|
name: tool.name,
|
|
395
447
|
arguments: toolArguments
|
|
396
448
|
};
|
|
397
|
-
const
|
|
449
|
+
const result = await client.callTool(params, import_types.CallToolResultSchema, {
|
|
398
450
|
timeout: config.timeout
|
|
399
451
|
});
|
|
400
452
|
returnData.push({
|
|
401
453
|
json: {
|
|
402
|
-
response:
|
|
454
|
+
response: result.content || result
|
|
403
455
|
},
|
|
404
456
|
pairedItem: {
|
|
405
457
|
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 { Client } from '@modelcontextprotocol/sdk/client/index.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// Simple in-memory cache to avoid creating a new MCP session per call\nconst mcpClientCache: Map<string, Client> = new Map();\nfunction getCacheKey(serverTransport: McpServerTransport, endpointUrl: string, nodeType: string) {\n return `${nodeType}|${serverTransport}|${endpointUrl}`;\n}\n// Track CDP connections per cached client+cdp endpoint so we call once\nconst cdpConnectedCache: Set<string> = new Set();\nfunction getCdpKey(cacheKey: string, cdpEndpointUrl?: string) {\n\tconst ep = typeof cdpEndpointUrl === 'string' ? cdpEndpointUrl.trim() : '';\n\treturn ep ? `${cacheKey}|cdp:${ep}` : null;\n}\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\t// Try to reuse an existing connected client for the same endpoint/transport\n\tconst cacheKey = getCacheKey(config.serverTransport, config.endpointUrl, node.type);\n\tconst cachedClient = mcpClientCache.get(cacheKey);\n\tif (cachedClient) {\n\t\t// Attempt to establish CDP connection once per endpoint/client\n\t\tconst cdpKey = getCdpKey(cacheKey, config.cdp_endpointurl);\n\t\tif (cdpKey && !cdpConnectedCache.has(cdpKey)) {\n\t\t\tawait cachedClient.callTool(\n\t\t\t\t{\n\t\t\t\t\tname: 'browser_connect_cdp',\n\t\t\t\t\targuments: { endpoint: config.cdp_endpointurl as string },\n\t\t\t\t},\n\t\t\t\tundefined,\n\t\t\t\t{ timeout: config.timeout ? Number(config.timeout) : undefined },\n\t\t\t);\n\t\t\tcdpConnectedCache.add(cdpKey);\n\t\t}\n\t\tconst allTools = await getAllTools(cachedClient);\n\t\tconst mcpTools = getSelectedTools({\n\t\t\ttools: allTools,\n\t\t\tmode: config.mode,\n\t\t\tincludeTools: config.includeTools,\n\t\t\texcludeTools: config.excludeTools,\n\t\t});\n\n\t\treturn { client: cachedClient, mcpTools, error: null };\n\t}\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\t// Cache the connected client to prevent creating a new session on subsequent calls\n\tmcpClientCache.set(cacheKey, client.result);\n\n\t// Attempt to establish CDP connection once per endpoint/client on fresh connection\n\tconst cdpKey = getCdpKey(cacheKey, config.cdp_endpointurl);\n\tif (cdpKey && !cdpConnectedCache.has(cdpKey)) {\n\t\tawait client.result.callTool(\n\t\t\t{\n\t\t\t\tname: 'browser_connect_cdp',\n\t\t\t\targuments: { endpoint: config.cdp_endpointurl as string },\n\t\t\t},\n\t\t\tundefined,\n\t\t\t{ timeout: config.timeout ? Number(config.timeout) : undefined },\n\t\t);\n\t\tcdpConnectedCache.add(cdpKey);\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\t// Ensure closing also clears cache for this endpoint/transport\n\t\tconst cacheKey = getCacheKey(config.serverTransport, config.endpointUrl, node.type);\n\t\tconst cdpKey = getCdpKey(cacheKey, config.cdp_endpointurl);\n\t\treturn {\n\t\t\tresponse: toolkit,\n\t\t\tcloseFunction: async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait client.close();\n\t\t\t\t} finally {\n\t\t\t\t\tmcpClientCache.delete(cacheKey);\n\t\t\t\t\tif (cdpKey) cdpConnectedCache.delete(cdpKey);\n\t\t\t\t}\n\t\t\t},\n\t\t};\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// CDP connection handled within connectAndGetTools to ensure single-run per client\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","cdpKey","allTools","mcpTools","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":[]}
|