n8n-nodes-smart-browser-automation 1.1.12 → 1.2.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.
|
@@ -75,12 +75,14 @@ class BrowserSessionManager {
|
|
|
75
75
|
throw new Error('MCP client not initialized. Please configure credentials first.');
|
|
76
76
|
}
|
|
77
77
|
try {
|
|
78
|
-
// Log
|
|
78
|
+
// Log tool call for debugging
|
|
79
79
|
console.log(`[MCP] Calling tool "${toolName}" with args:`, JSON.stringify(toolArgs || {}));
|
|
80
80
|
const result = await this.mcpClient.callTool({
|
|
81
81
|
name: toolName,
|
|
82
82
|
arguments: toolArgs || {}
|
|
83
83
|
});
|
|
84
|
+
// Log the response for debugging
|
|
85
|
+
console.log(`[MCP] Tool "${toolName}" response:`, JSON.stringify(result, null, 2));
|
|
84
86
|
return result;
|
|
85
87
|
}
|
|
86
88
|
catch (error) {
|
|
@@ -27,81 +27,11 @@ class SmartBrowserAutomation {
|
|
|
27
27
|
],
|
|
28
28
|
usableAsTool: true,
|
|
29
29
|
properties: [
|
|
30
|
-
{
|
|
31
|
-
displayName: 'Mode',
|
|
32
|
-
name: 'mode',
|
|
33
|
-
type: 'options',
|
|
34
|
-
noDataExpression: true,
|
|
35
|
-
options: [
|
|
36
|
-
{
|
|
37
|
-
name: 'AI Agent (Auto)',
|
|
38
|
-
value: 'aiAgent',
|
|
39
|
-
description: 'Let AI decide which tools to use - use this with AI Agent node',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: 'Manual',
|
|
43
|
-
value: 'manual',
|
|
44
|
-
description: 'Manually select tool and provide arguments',
|
|
45
|
-
},
|
|
46
|
-
],
|
|
47
|
-
default: 'aiAgent',
|
|
48
|
-
description: 'How to execute browser automation',
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
displayName: 'Tool Name or ID',
|
|
52
|
-
name: 'toolName',
|
|
53
|
-
type: 'options',
|
|
54
|
-
typeOptions: {
|
|
55
|
-
loadOptionsMethod: 'getAvailableTools',
|
|
56
|
-
},
|
|
57
|
-
displayOptions: {
|
|
58
|
-
show: {
|
|
59
|
-
mode: ['manual'],
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
default: 'browser_connect_cdp',
|
|
63
|
-
description: 'Select the browser automation tool to execute. Choose "Connect to Browser (CDP)" to initialize/switch browser sessions. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
|
64
|
-
required: true,
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
displayName: 'CDP Endpoint',
|
|
68
|
-
name: 'cdpUrl',
|
|
69
|
-
type: 'string',
|
|
70
|
-
displayOptions: {
|
|
71
|
-
show: {
|
|
72
|
-
mode: ['manual'],
|
|
73
|
-
toolName: ['browser_connect_cdp'],
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
default: '',
|
|
77
|
-
placeholder: 'wss://gridnew.doingerp.com/devtools/...',
|
|
78
|
-
description: 'The wss:// or http:// endpoint for the browser CDP connection',
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
displayName: 'Tool Arguments',
|
|
82
|
-
name: 'toolArgs',
|
|
83
|
-
type: 'json',
|
|
84
|
-
displayOptions: {
|
|
85
|
-
show: {
|
|
86
|
-
mode: ['manual'],
|
|
87
|
-
},
|
|
88
|
-
hide: {
|
|
89
|
-
toolName: ['browser_connect_cdp'],
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
default: '{}',
|
|
93
|
-
description: 'Arguments for the selected tool in JSON format',
|
|
94
|
-
},
|
|
95
30
|
{
|
|
96
31
|
displayName: 'Operation',
|
|
97
32
|
name: 'operation',
|
|
98
33
|
type: 'options',
|
|
99
34
|
noDataExpression: true,
|
|
100
|
-
displayOptions: {
|
|
101
|
-
show: {
|
|
102
|
-
mode: ['aiAgent'],
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
35
|
options: [
|
|
106
36
|
{
|
|
107
37
|
name: 'Initialize Session',
|
|
@@ -124,11 +54,6 @@ class SmartBrowserAutomation {
|
|
|
124
54
|
type: 'collection',
|
|
125
55
|
placeholder: 'Add Option',
|
|
126
56
|
default: {},
|
|
127
|
-
displayOptions: {
|
|
128
|
-
show: {
|
|
129
|
-
mode: ['aiAgent'],
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
57
|
options: [
|
|
133
58
|
{
|
|
134
59
|
displayName: 'CDP Endpoint',
|
|
@@ -198,17 +123,27 @@ class SmartBrowserAutomation {
|
|
|
198
123
|
const routerTool = {
|
|
199
124
|
name: 'browser_tool',
|
|
200
125
|
displayName: 'Browser Action',
|
|
201
|
-
description: `
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
126
|
+
description: `Execute browser automation actions. ALWAYS use this tool for browser interactions.
|
|
127
|
+
|
|
128
|
+
WHEN TO USE:
|
|
129
|
+
✓ User wants to visit/open/go to a website → action='navigate'
|
|
130
|
+
✓ User wants to click something → action='click'
|
|
131
|
+
✓ User wants to type/enter text → action='type'
|
|
132
|
+
✓ User wants to read/get text from page → action='snapshot' or action='get_text'
|
|
133
|
+
✓ User wants a screenshot → action='take_screenshot'
|
|
134
|
+
|
|
135
|
+
REQUIRED PARAMETERS:
|
|
136
|
+
• action: The action name (navigate, click, type, snapshot, take_screenshot, etc.)
|
|
137
|
+
• params: JSON object with action-specific parameters
|
|
138
|
+
|
|
139
|
+
EXAMPLES:
|
|
140
|
+
1. Navigate: { "action": "navigate", "params": { "url": "https://example.com" } }
|
|
141
|
+
2. Click: { "action": "click", "params": { "element": "button text", "ref": "..." } }
|
|
142
|
+
3. Type: { "action": "type", "params": { "element": "input field", "ref": "...", "text": "hello" } }
|
|
143
|
+
4. Snapshot: { "action": "snapshot", "params": {} }
|
|
144
|
+
5. Screenshot: { "action": "take_screenshot", "params": {} }
|
|
145
|
+
|
|
146
|
+
IMPORTANT: For navigate action, params must include "url" key.`,
|
|
212
147
|
properties: [
|
|
213
148
|
{
|
|
214
149
|
displayName: 'Action Name',
|
|
@@ -234,17 +169,20 @@ class SmartBrowserAutomation {
|
|
|
234
169
|
if (input.action === 'connect_cdp' || input.action === 'browser_connect_cdp') {
|
|
235
170
|
const endpoint = input.params?.endpoint;
|
|
236
171
|
if (endpoint) {
|
|
172
|
+
console.log(`[Router] Connecting to CDP: ${endpoint}`);
|
|
237
173
|
await sessionManager.initialize(credentials.mcpEndpoint, true, endpoint);
|
|
238
174
|
return {
|
|
239
175
|
content: [{ type: 'text', text: `Connected to browser at ${endpoint}.` }],
|
|
240
|
-
isError: false
|
|
176
|
+
isError: false,
|
|
177
|
+
toolName: 'browser_connect_cdp',
|
|
178
|
+
requestedAction: input.action
|
|
241
179
|
};
|
|
242
180
|
}
|
|
243
181
|
}
|
|
244
|
-
//
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// Normalize action name
|
|
182
|
+
// Session not ready and no explicit connection requested
|
|
183
|
+
// This shouldn't happen - session should be initialized first
|
|
184
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Browser session not initialized. Please connect to browser first using Initialize Session or connect_cdp action.');
|
|
185
|
+
} // Normalize action name
|
|
248
186
|
let toolName = input.action;
|
|
249
187
|
if (!toolName.startsWith('browser_') && toolName !== 'connect_cdp') {
|
|
250
188
|
toolName = `browser_${toolName}`;
|
|
@@ -262,12 +200,19 @@ class SmartBrowserAutomation {
|
|
|
262
200
|
console.log(`[Router] Routing '${input.action}' to '${toolName}' with args:`, toolArgs);
|
|
263
201
|
try {
|
|
264
202
|
const result = await sessionManager.callTool(toolName, toolArgs);
|
|
203
|
+
// Add tool name to result for visibility
|
|
204
|
+
if (result && typeof result === 'object') {
|
|
205
|
+
result.toolName = toolName;
|
|
206
|
+
result.requestedAction = input.action;
|
|
207
|
+
}
|
|
265
208
|
return result;
|
|
266
209
|
}
|
|
267
210
|
catch (error) {
|
|
268
211
|
return {
|
|
269
212
|
content: [{ type: 'text', text: `Error executing ${toolName}: ${error.message}` }],
|
|
270
|
-
isError: true
|
|
213
|
+
isError: true,
|
|
214
|
+
toolName: toolName,
|
|
215
|
+
requestedAction: input.action
|
|
271
216
|
};
|
|
272
217
|
}
|
|
273
218
|
}
|
|
@@ -293,7 +238,8 @@ class SmartBrowserAutomation {
|
|
|
293
238
|
await sessionManager.initialize(credentials.mcpEndpoint, true, input.endpoint);
|
|
294
239
|
return {
|
|
295
240
|
content: [{ type: 'text', text: `Connected to browser at ${input.endpoint}.` }],
|
|
296
|
-
isError: false
|
|
241
|
+
isError: false,
|
|
242
|
+
toolName: 'browser_connect_cdp'
|
|
297
243
|
};
|
|
298
244
|
}
|
|
299
245
|
};
|
|
@@ -304,112 +250,58 @@ class SmartBrowserAutomation {
|
|
|
304
250
|
const returnData = [];
|
|
305
251
|
const credentials = await this.getCredentials('smartBrowserAutomationApi');
|
|
306
252
|
const sessionManager = BrowserSessionManager_1.default.getInstance();
|
|
307
|
-
const mode = this.getNodeParameter('mode', 0);
|
|
308
253
|
for (let i = 0; i < items.length; i++) {
|
|
309
254
|
try {
|
|
310
255
|
const options = this.getNodeParameter('options', i, {});
|
|
311
256
|
const verbose = options.verbose || false;
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
if (!endpoint) {
|
|
319
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'CDP Endpoint URL is required for browser_connect_cdp');
|
|
320
|
-
}
|
|
257
|
+
const operation = this.getNodeParameter('operation', i);
|
|
258
|
+
if (operation === 'initialize') {
|
|
259
|
+
const cdpUrl = credentials.cdpEndpoint;
|
|
260
|
+
await sessionManager.initialize(credentials.mcpEndpoint, true, cdpUrl);
|
|
261
|
+
// New logic: Auto-call browser_connect_cdp tool if a URL is provided
|
|
262
|
+
if (options.cdpUrl) {
|
|
321
263
|
if (verbose) {
|
|
322
|
-
console.log(`
|
|
264
|
+
console.log(`Auto-calling 'browser_connect_cdp' with endpoint: ${options.cdpUrl}`);
|
|
265
|
+
}
|
|
266
|
+
try {
|
|
267
|
+
const connectionResult = await sessionManager.callTool('browser_connect_cdp', { endpoint: options.cdpUrl });
|
|
268
|
+
// Return only the connection result, no extra messages
|
|
269
|
+
returnData.push({
|
|
270
|
+
json: connectionResult,
|
|
271
|
+
pairedItem: i,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
returnData.push({
|
|
276
|
+
json: {
|
|
277
|
+
success: false,
|
|
278
|
+
error: `Failed to connect: ${error.message}`
|
|
279
|
+
},
|
|
280
|
+
pairedItem: i,
|
|
281
|
+
});
|
|
323
282
|
}
|
|
324
|
-
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
// No CDP URL provided
|
|
325
286
|
returnData.push({
|
|
326
287
|
json: {
|
|
327
288
|
success: true,
|
|
328
|
-
message:
|
|
329
|
-
timestamp: new Date().toISOString()
|
|
289
|
+
message: 'MCP session initialized (no browser connection)'
|
|
330
290
|
},
|
|
331
291
|
pairedItem: i,
|
|
332
292
|
});
|
|
333
|
-
continue;
|
|
334
|
-
}
|
|
335
|
-
const toolArgsStr = this.getNodeParameter('toolArgs', i);
|
|
336
|
-
let toolArgs;
|
|
337
|
-
try {
|
|
338
|
-
toolArgs = JSON.parse(toolArgsStr);
|
|
339
|
-
}
|
|
340
|
-
catch (error) {
|
|
341
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid JSON in Tool Arguments: ${error.message}`);
|
|
342
293
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
}
|
|
347
|
-
if (verbose) {
|
|
348
|
-
console.log(`Executing tool: ${toolName} with args:`, toolArgs);
|
|
349
|
-
}
|
|
350
|
-
const result = await sessionManager.callTool(toolName, toolArgs);
|
|
294
|
+
}
|
|
295
|
+
else if (operation === 'close') {
|
|
296
|
+
await sessionManager.close();
|
|
351
297
|
returnData.push({
|
|
352
|
-
json:
|
|
298
|
+
json: {
|
|
299
|
+
success: true,
|
|
300
|
+
message: 'Browser session closed',
|
|
301
|
+
},
|
|
353
302
|
pairedItem: i,
|
|
354
303
|
});
|
|
355
304
|
}
|
|
356
|
-
else {
|
|
357
|
-
// AI Agent mode: Just initialize or close
|
|
358
|
-
const operation = this.getNodeParameter('operation', i);
|
|
359
|
-
if (operation === 'initialize') {
|
|
360
|
-
const cdpUrl = credentials.cdpEndpoint;
|
|
361
|
-
await sessionManager.initialize(credentials.mcpEndpoint, true, cdpUrl);
|
|
362
|
-
let connectionStatus = 'Skipped (No CDP URL provided)';
|
|
363
|
-
let connectionResult = null;
|
|
364
|
-
// New logic: Auto-call browser_connect_cdp tool if a URL is provided
|
|
365
|
-
if (options.cdpUrl) {
|
|
366
|
-
if (verbose) {
|
|
367
|
-
console.log(`Auto-calling 'browser_connect_cdp' with endpoint: ${options.cdpUrl}`);
|
|
368
|
-
}
|
|
369
|
-
try {
|
|
370
|
-
connectionResult = await sessionManager.callTool('browser_connect_cdp', { endpoint: options.cdpUrl });
|
|
371
|
-
connectionStatus = 'Successfully connected';
|
|
372
|
-
}
|
|
373
|
-
catch (error) {
|
|
374
|
-
connectionStatus = `Failed to connect: ${error.message}`;
|
|
375
|
-
console.warn(`Failed to auto-connect browser via tool: ${error.message}`);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
// Guide for the Router Tool
|
|
379
|
-
const actionGuide = `
|
|
380
|
-
Actions available via 'browser_tool':
|
|
381
|
-
- navigate: { "url": "https://..." }
|
|
382
|
-
- click: { "selector": "..." }
|
|
383
|
-
- type: { "selector": "...", "text": "..." }
|
|
384
|
-
- press_key: { "key": "Enter" }
|
|
385
|
-
- scroll_to: { "selector": "..." }
|
|
386
|
-
- get_text: { "selector": "..." }
|
|
387
|
-
- take_screenshot: {}
|
|
388
|
-
- evaluate: { "script": "return document.title;" }
|
|
389
|
-
...and all other MCP tools.
|
|
390
|
-
`;
|
|
391
|
-
returnData.push({
|
|
392
|
-
json: {
|
|
393
|
-
success: true,
|
|
394
|
-
message: `MCP session initialized at ${credentials.mcpEndpoint}`,
|
|
395
|
-
browserConnection: connectionStatus,
|
|
396
|
-
browserResponse: connectionResult,
|
|
397
|
-
toolGuide: actionGuide,
|
|
398
|
-
},
|
|
399
|
-
pairedItem: i,
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
else if (operation === 'close') {
|
|
403
|
-
await sessionManager.close();
|
|
404
|
-
returnData.push({
|
|
405
|
-
json: {
|
|
406
|
-
success: true,
|
|
407
|
-
message: 'Browser session closed',
|
|
408
|
-
},
|
|
409
|
-
pairedItem: i,
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
305
|
}
|
|
414
306
|
catch (error) {
|
|
415
307
|
if (this.continueOnFail()) {
|