n8n-nodes-browser-smart-automation 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/McpClient/McpClient.node.js +333 -0
- package/dist/McpClient/McpClient.node.js.map +1 -0
- package/dist/McpClient/listSearch.js +58 -0
- package/dist/McpClient/listSearch.js.map +1 -0
- package/dist/McpClient/resourceMapping.js +61 -0
- package/dist/McpClient/resourceMapping.js.map +1 -0
- package/dist/McpClient/utils.js +248 -0
- package/dist/McpClient/utils.js.map +1 -0
- package/dist/McpClientTool/McpClientTool.node.js +417 -0
- package/dist/McpClientTool/McpClientTool.node.js.map +1 -0
- package/dist/McpClientTool/loadOptions.js +61 -0
- package/dist/McpClientTool/loadOptions.js.map +1 -0
- package/dist/McpClientTool/types.js +17 -0
- package/dist/McpClientTool/types.js.map +1 -0
- package/dist/McpClientTool/utils.js +120 -0
- package/dist/McpClientTool/utils.js.map +1 -0
- package/dist/McpTrigger/FlushingTransport.js +61 -0
- package/dist/McpTrigger/FlushingTransport.js.map +1 -0
- package/dist/McpTrigger/McpServer.js +246 -0
- package/dist/McpTrigger/McpServer.js.map +1 -0
- package/dist/McpTrigger/McpTrigger.node.js +196 -0
- package/dist/McpTrigger/McpTrigger.node.js.map +1 -0
- package/dist/shared/descriptions.js +89 -0
- package/dist/shared/descriptions.js.map +1 -0
- package/dist/shared/helpers.js +47 -0
- package/dist/shared/helpers.js.map +1 -0
- package/dist/shared/httpProxyAgent.js +31 -0
- package/dist/shared/httpProxyAgent.js.map +1 -0
- package/dist/shared/logWrapper.js +31 -0
- package/dist/shared/logWrapper.js.map +1 -0
- package/dist/shared/schemaParsing.js +32 -0
- package/dist/shared/schemaParsing.js.map +1 -0
- package/dist/shared/sharedFields.js +41 -0
- package/dist/shared/sharedFields.js.map +1 -0
- package/dist/shared/types.js +17 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/shared/utils.js +231 -0
- package/dist/shared/utils.js.map +1 -0
- package/jest.config.js +24 -0
- package/nodes/McpClient/McpClient.node.ts +327 -0
- package/nodes/McpClient/__test__/McpClient.node.test.ts +221 -0
- package/nodes/McpClient/__test__/utils.test.ts +302 -0
- package/nodes/McpClient/listSearch.ts +48 -0
- package/nodes/McpClient/resourceMapping.ts +48 -0
- package/nodes/McpClient/utils.ts +281 -0
- package/nodes/McpClientTool/McpClientTool.node.ts +468 -0
- package/nodes/McpClientTool/__test__/McpClientTool.node.test.ts +730 -0
- package/nodes/McpClientTool/loadOptions.ts +45 -0
- package/nodes/McpClientTool/types.ts +1 -0
- package/nodes/McpClientTool/utils.ts +116 -0
- package/nodes/McpTrigger/FlushingTransport.ts +61 -0
- package/nodes/McpTrigger/McpServer.ts +317 -0
- package/nodes/McpTrigger/McpTrigger.node.ts +204 -0
- package/nodes/McpTrigger/__test__/FlushingTransport.test.ts +102 -0
- package/nodes/McpTrigger/__test__/McpServer.test.ts +532 -0
- package/nodes/McpTrigger/__test__/McpTrigger.node.test.ts +171 -0
- package/nodes/mcp.dark.svg +7 -0
- package/nodes/mcp.svg +7 -0
- package/nodes/shared/__test__/utils.test.ts +318 -0
- package/nodes/shared/descriptions.ts +65 -0
- package/nodes/shared/helpers.ts +31 -0
- package/nodes/shared/httpProxyAgent.ts +11 -0
- package/nodes/shared/logWrapper.ts +13 -0
- package/nodes/shared/schemaParsing.ts +9 -0
- package/nodes/shared/sharedFields.ts +20 -0
- package/nodes/shared/types.ts +12 -0
- package/nodes/shared/utils.ts +296 -0
- package/officail/package.json +255 -0
- package/package.json +46 -0
- package/tsconfig.json +32 -0
- package/tsup.config.ts +11 -0
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
import { CallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import {
|
|
3
|
+
type IDataObject,
|
|
4
|
+
type IExecuteFunctions,
|
|
5
|
+
type INodeExecutionData,
|
|
6
|
+
NodeConnectionTypes,
|
|
7
|
+
NodeOperationError,
|
|
8
|
+
type INodeType,
|
|
9
|
+
type INodeTypeDescription,
|
|
10
|
+
type ISupplyDataFunctions,
|
|
11
|
+
type SupplyData,
|
|
12
|
+
} from 'n8n-workflow';
|
|
13
|
+
|
|
14
|
+
import { logWrapper } from '@utils/logWrapper';
|
|
15
|
+
import { getConnectionHintNoticeField } from '@utils/sharedFields';
|
|
16
|
+
|
|
17
|
+
import { getTools } from './loadOptions';
|
|
18
|
+
import type { McpToolIncludeMode } from './types';
|
|
19
|
+
import { createCallTool, getSelectedTools, McpToolkit, mcpToolToDynamicTool } from './utils';
|
|
20
|
+
import { credentials, transportSelect } from '../shared/descriptions';
|
|
21
|
+
import type { McpAuthenticationOption, McpServerTransport } from '../shared/types';
|
|
22
|
+
import {
|
|
23
|
+
connectMcpClient,
|
|
24
|
+
getAllTools,
|
|
25
|
+
getAuthHeaders,
|
|
26
|
+
mapToNodeOperationError,
|
|
27
|
+
tryRefreshOAuth2Token,
|
|
28
|
+
} from '../shared/utils';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get node parameters for MCP client configuration
|
|
32
|
+
*/
|
|
33
|
+
function getNodeConfig(
|
|
34
|
+
ctx: ISupplyDataFunctions | IExecuteFunctions,
|
|
35
|
+
itemIndex: number,
|
|
36
|
+
): {
|
|
37
|
+
authentication: McpAuthenticationOption;
|
|
38
|
+
timeout: number;
|
|
39
|
+
serverTransport: McpServerTransport;
|
|
40
|
+
endpointUrl: string;
|
|
41
|
+
cdp_endpointUrl?: string;
|
|
42
|
+
mode: McpToolIncludeMode;
|
|
43
|
+
includeTools: string[];
|
|
44
|
+
excludeTools: string[];
|
|
45
|
+
} {
|
|
46
|
+
const node = ctx.getNode();
|
|
47
|
+
const authentication = ctx.getNodeParameter(
|
|
48
|
+
'authentication',
|
|
49
|
+
itemIndex,
|
|
50
|
+
) as McpAuthenticationOption;
|
|
51
|
+
const timeout = ctx.getNodeParameter('options.timeout', itemIndex, 60000) as number;
|
|
52
|
+
|
|
53
|
+
let serverTransport: McpServerTransport;
|
|
54
|
+
let endpointUrl: string;
|
|
55
|
+
if (node.typeVersion === 1) {
|
|
56
|
+
serverTransport = 'sse';
|
|
57
|
+
endpointUrl = ctx.getNodeParameter('sseEndpoint', itemIndex) as string;
|
|
58
|
+
} else {
|
|
59
|
+
serverTransport = ctx.getNodeParameter('serverTransport', itemIndex) as McpServerTransport;
|
|
60
|
+
endpointUrl = ctx.getNodeParameter('endpointUrl', itemIndex) as string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const mode = ctx.getNodeParameter('include', itemIndex) as McpToolIncludeMode;
|
|
64
|
+
const includeTools = ctx.getNodeParameter('includeTools', itemIndex, []) as string[];
|
|
65
|
+
const excludeTools = ctx.getNodeParameter('excludeTools', itemIndex, []) as string[];
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
authentication,
|
|
69
|
+
timeout,
|
|
70
|
+
serverTransport,
|
|
71
|
+
endpointUrl,
|
|
72
|
+
mode,
|
|
73
|
+
includeTools,
|
|
74
|
+
excludeTools,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Connect to MCP server and get filtered tools
|
|
80
|
+
*/
|
|
81
|
+
async function connectAndGetTools(
|
|
82
|
+
ctx: ISupplyDataFunctions | IExecuteFunctions,
|
|
83
|
+
config: ReturnType<typeof getNodeConfig>,
|
|
84
|
+
) {
|
|
85
|
+
const node = ctx.getNode();
|
|
86
|
+
const { headers } = await getAuthHeaders(ctx, config.authentication);
|
|
87
|
+
|
|
88
|
+
const client = await connectMcpClient({
|
|
89
|
+
serverTransport: config.serverTransport,
|
|
90
|
+
endpointUrl: config.endpointUrl,
|
|
91
|
+
headers,
|
|
92
|
+
name: node.type,
|
|
93
|
+
version: node.typeVersion,
|
|
94
|
+
onUnauthorized: async (headers) =>
|
|
95
|
+
await tryRefreshOAuth2Token(ctx, config.authentication, headers),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (!client.ok) {
|
|
99
|
+
return { client, mcpTools: null, error: client.error };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const allTools = await getAllTools(client.result);
|
|
103
|
+
const mcpTools = getSelectedTools({
|
|
104
|
+
tools: allTools,
|
|
105
|
+
mode: config.mode,
|
|
106
|
+
includeTools: config.includeTools,
|
|
107
|
+
excludeTools: config.excludeTools,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return { client: client.result, mcpTools, error: null };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export class McpClientTool implements INodeType {
|
|
114
|
+
description: INodeTypeDescription = {
|
|
115
|
+
displayName: 'MCP Client Tool',
|
|
116
|
+
name: 'mcpClientTool',
|
|
117
|
+
icon: {
|
|
118
|
+
light: 'file:../mcp.svg',
|
|
119
|
+
dark: 'file:../mcp.dark.svg',
|
|
120
|
+
},
|
|
121
|
+
group: ['output'],
|
|
122
|
+
version: [1, 1.1, 1.2],
|
|
123
|
+
description: 'Connect tools from an MCP Server',
|
|
124
|
+
defaults: {
|
|
125
|
+
name: 'MCP Client',
|
|
126
|
+
},
|
|
127
|
+
codex: {
|
|
128
|
+
categories: ['AI'],
|
|
129
|
+
subcategories: {
|
|
130
|
+
AI: ['Model Context Protocol', 'Tools'],
|
|
131
|
+
},
|
|
132
|
+
alias: ['Model Context Protocol', 'MCP Client'],
|
|
133
|
+
resources: {
|
|
134
|
+
primaryDocumentation: [
|
|
135
|
+
{
|
|
136
|
+
url: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolmcp/',
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
inputs: [],
|
|
142
|
+
outputs: [{ type: NodeConnectionTypes.AiTool, displayName: 'Tools' }],
|
|
143
|
+
credentials,
|
|
144
|
+
properties: [
|
|
145
|
+
getConnectionHintNoticeField([NodeConnectionTypes.AiAgent]),
|
|
146
|
+
{
|
|
147
|
+
displayName: 'SSE Endpoint',
|
|
148
|
+
name: 'sseEndpoint',
|
|
149
|
+
type: 'string',
|
|
150
|
+
description: 'SSE Endpoint of your MCP server',
|
|
151
|
+
placeholder: 'e.g. https://my-mcp-server.ai/sse',
|
|
152
|
+
default: '',
|
|
153
|
+
required: true,
|
|
154
|
+
displayOptions: {
|
|
155
|
+
show: {
|
|
156
|
+
'@version': [1],
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
displayName: 'Endpoint',
|
|
162
|
+
name: 'endpointUrl',
|
|
163
|
+
type: 'string',
|
|
164
|
+
description: 'Endpoint of your MCP server',
|
|
165
|
+
placeholder: 'e.g. https://my-mcp-server.ai/mcp',
|
|
166
|
+
default: '',
|
|
167
|
+
required: true,
|
|
168
|
+
displayOptions: {
|
|
169
|
+
show: {
|
|
170
|
+
'@version': [{ _cnd: { gte: 1.1 } }],
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
transportSelect({
|
|
175
|
+
defaultOption: 'sse',
|
|
176
|
+
displayOptions: {
|
|
177
|
+
show: {
|
|
178
|
+
'@version': [1.1],
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
}),
|
|
182
|
+
transportSelect({
|
|
183
|
+
defaultOption: 'httpStreamable',
|
|
184
|
+
displayOptions: {
|
|
185
|
+
show: {
|
|
186
|
+
'@version': [{ _cnd: { gte: 1.2 } }],
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
}),
|
|
190
|
+
{
|
|
191
|
+
displayName: 'Authentication',
|
|
192
|
+
name: 'authentication',
|
|
193
|
+
type: 'options',
|
|
194
|
+
options: [
|
|
195
|
+
{
|
|
196
|
+
name: 'Bearer Auth',
|
|
197
|
+
value: 'bearerAuth',
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
name: 'Header Auth',
|
|
201
|
+
value: 'headerAuth',
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
name: 'None',
|
|
205
|
+
value: 'none',
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
default: 'none',
|
|
209
|
+
description: 'The way to authenticate with your endpoint',
|
|
210
|
+
displayOptions: {
|
|
211
|
+
show: {
|
|
212
|
+
'@version': [{ _cnd: { lt: 1.2 } }],
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
displayName: 'Authentication',
|
|
218
|
+
name: 'authentication',
|
|
219
|
+
type: 'options',
|
|
220
|
+
options: [
|
|
221
|
+
{
|
|
222
|
+
name: 'Bearer Auth',
|
|
223
|
+
value: 'bearerAuth',
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
name: 'Header Auth',
|
|
227
|
+
value: 'headerAuth',
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
name: 'MCP OAuth2',
|
|
231
|
+
value: 'mcpOAuth2Api',
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
name: 'Multiple Headers Auth',
|
|
235
|
+
value: 'multipleHeadersAuth',
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: 'None',
|
|
239
|
+
value: 'none',
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
default: 'none',
|
|
243
|
+
description: 'The way to authenticate with your endpoint',
|
|
244
|
+
displayOptions: {
|
|
245
|
+
show: {
|
|
246
|
+
'@version': [{ _cnd: { gte: 1.2 } }],
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
displayName: 'Credentials',
|
|
252
|
+
name: 'credentials',
|
|
253
|
+
type: 'credentials',
|
|
254
|
+
default: '',
|
|
255
|
+
displayOptions: {
|
|
256
|
+
show: {
|
|
257
|
+
authentication: ['headerAuth', 'bearerAuth', 'mcpOAuth2Api', 'multipleHeadersAuth'],
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
displayName: 'Tools to Include',
|
|
263
|
+
name: 'include',
|
|
264
|
+
type: 'options',
|
|
265
|
+
description: 'How to select the tools you want to be exposed to the AI Agent',
|
|
266
|
+
default: 'all',
|
|
267
|
+
options: [
|
|
268
|
+
{
|
|
269
|
+
name: 'All',
|
|
270
|
+
value: 'all',
|
|
271
|
+
description: 'Also include all unchanged fields from the input',
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
name: 'Selected',
|
|
275
|
+
value: 'selected',
|
|
276
|
+
description: 'Also include the tools listed in the parameter "Tools to Include"',
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: 'All Except',
|
|
280
|
+
value: 'except',
|
|
281
|
+
description: 'Exclude the tools listed in the parameter "Tools to Exclude"',
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
displayName: 'Tools to Include',
|
|
287
|
+
name: 'includeTools',
|
|
288
|
+
type: 'multiOptions',
|
|
289
|
+
default: [],
|
|
290
|
+
description:
|
|
291
|
+
'Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
292
|
+
typeOptions: {
|
|
293
|
+
loadOptionsMethod: 'getTools',
|
|
294
|
+
loadOptionsDependsOn: ['sseEndpoint'],
|
|
295
|
+
},
|
|
296
|
+
displayOptions: {
|
|
297
|
+
show: {
|
|
298
|
+
include: ['selected'],
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
displayName: 'Tools to Exclude',
|
|
304
|
+
name: 'excludeTools',
|
|
305
|
+
type: 'multiOptions',
|
|
306
|
+
default: [],
|
|
307
|
+
description:
|
|
308
|
+
'Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
309
|
+
typeOptions: {
|
|
310
|
+
loadOptionsMethod: 'getTools',
|
|
311
|
+
},
|
|
312
|
+
displayOptions: {
|
|
313
|
+
show: {
|
|
314
|
+
include: ['except'],
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
displayName: 'Options',
|
|
320
|
+
name: 'options',
|
|
321
|
+
placeholder: 'Add Option',
|
|
322
|
+
description: 'Additional options to add',
|
|
323
|
+
type: 'collection',
|
|
324
|
+
default: {},
|
|
325
|
+
options: [
|
|
326
|
+
{
|
|
327
|
+
displayName: 'cdp_endpointUrl',
|
|
328
|
+
name: 'cdp_endpointUrl',
|
|
329
|
+
type: 'string',
|
|
330
|
+
default: '',
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
displayName: 'Timeout',
|
|
334
|
+
name: 'timeout',
|
|
335
|
+
type: 'number',
|
|
336
|
+
typeOptions: {
|
|
337
|
+
minValue: 1,
|
|
338
|
+
},
|
|
339
|
+
default: 60000,
|
|
340
|
+
description: 'Time in ms to wait for tool calls to finish',
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
displayName: 'Timeout',
|
|
344
|
+
name: 'timeout',
|
|
345
|
+
type: 'number',
|
|
346
|
+
typeOptions: {
|
|
347
|
+
minValue: 1,
|
|
348
|
+
},
|
|
349
|
+
default: 60000,
|
|
350
|
+
description: 'Time in ms to wait for tool calls to finish',
|
|
351
|
+
}
|
|
352
|
+
],
|
|
353
|
+
},
|
|
354
|
+
],
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
methods = {
|
|
358
|
+
loadOptions: {
|
|
359
|
+
getTools,
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
async supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData> {
|
|
364
|
+
const node = this.getNode();
|
|
365
|
+
const config = getNodeConfig(this, itemIndex);
|
|
366
|
+
const setError = (error: NodeOperationError): SupplyData => {
|
|
367
|
+
this.addOutputData(NodeConnectionTypes.AiTool, itemIndex, error);
|
|
368
|
+
throw error;
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
const { client, mcpTools, error } = await connectAndGetTools(this, config);
|
|
372
|
+
|
|
373
|
+
if (error) {
|
|
374
|
+
this.logger.error('McpClientTool: Failed to connect to MCP Server', { error });
|
|
375
|
+
return setError(mapToNodeOperationError(node, error));
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
this.logger.debug('McpClientTool: Successfully connected to MCP Server');
|
|
379
|
+
|
|
380
|
+
if (!mcpTools?.length) {
|
|
381
|
+
return setError(
|
|
382
|
+
new NodeOperationError(node, 'MCP Server returned no tools', {
|
|
383
|
+
itemIndex,
|
|
384
|
+
description:
|
|
385
|
+
'Connected successfully to your MCP server but it returned an empty list of tools.',
|
|
386
|
+
}),
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const tools = mcpTools.map((tool) =>
|
|
391
|
+
logWrapper(
|
|
392
|
+
mcpToolToDynamicTool(
|
|
393
|
+
tool,
|
|
394
|
+
createCallTool(tool.name, client, config.timeout, (errorMessage) => {
|
|
395
|
+
const error = new NodeOperationError(node, errorMessage, { itemIndex });
|
|
396
|
+
void this.addOutputData(NodeConnectionTypes.AiTool, itemIndex, error);
|
|
397
|
+
this.logger.error(`McpClientTool: Tool "${tool.name}" failed to execute`, { error });
|
|
398
|
+
}),
|
|
399
|
+
),
|
|
400
|
+
this,
|
|
401
|
+
),
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
this.logger.debug(`McpClientTool: Connected to MCP Server with ${tools.length} tools`);
|
|
405
|
+
|
|
406
|
+
const toolkit = new McpToolkit(tools);
|
|
407
|
+
|
|
408
|
+
return { response: toolkit, closeFunction: async () => await client.close() };
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
|
412
|
+
const node = this.getNode();
|
|
413
|
+
const items = this.getInputData();
|
|
414
|
+
const returnData: INodeExecutionData[] = [];
|
|
415
|
+
|
|
416
|
+
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
|
417
|
+
const item = items[itemIndex];
|
|
418
|
+
const config = getNodeConfig(this, itemIndex);
|
|
419
|
+
|
|
420
|
+
const { client, mcpTools, error } = await connectAndGetTools(this, config);
|
|
421
|
+
|
|
422
|
+
if (error) {
|
|
423
|
+
throw new NodeOperationError(node, error.error, { itemIndex });
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if (!mcpTools?.length) {
|
|
427
|
+
throw new NodeOperationError(node, 'MCP Server returned no tools', { itemIndex });
|
|
428
|
+
}
|
|
429
|
+
await client.callTool({name:"browser_cdp_endpoint",arguments:{endpoint:config.cdp_endpointUrl}},CallToolResultSchema,{timeout:config.timeout});
|
|
430
|
+
|
|
431
|
+
for (const tool of mcpTools) {
|
|
432
|
+
// Check for tool name in item.json.tool (for toolkit execution from agent)
|
|
433
|
+
// or item.tool (for direct execution)
|
|
434
|
+
if (!item.json.tool || typeof item.json.tool !== 'string') {
|
|
435
|
+
throw new NodeOperationError(node, 'Tool name not found in item.json.tool or item.tool', {
|
|
436
|
+
itemIndex,
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const toolName = item.json.tool;
|
|
441
|
+
if (toolName === tool.name) {
|
|
442
|
+
// Extract the tool name from arguments before passing to MCP
|
|
443
|
+
const { tool: _, ...toolArguments } = item.json;
|
|
444
|
+
const params: {
|
|
445
|
+
name: string;
|
|
446
|
+
arguments: IDataObject;
|
|
447
|
+
} = {
|
|
448
|
+
name: tool.name,
|
|
449
|
+
arguments: toolArguments,
|
|
450
|
+
};
|
|
451
|
+
const result = await client.callTool(params, CallToolResultSchema, {
|
|
452
|
+
timeout: config.timeout,
|
|
453
|
+
});
|
|
454
|
+
returnData.push({
|
|
455
|
+
json: {
|
|
456
|
+
response: (result.content || result) as IDataObject,
|
|
457
|
+
},
|
|
458
|
+
pairedItem: {
|
|
459
|
+
item: itemIndex,
|
|
460
|
+
},
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return [returnData];
|
|
467
|
+
}
|
|
468
|
+
}
|