n8n-nodes-smart-browser-automation 1.0.6 → 1.1.2
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.
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
4
4
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
5
|
+
const sse_js_1 = require("@modelcontextprotocol/sdk/client/sse.js");
|
|
5
6
|
class BrowserSessionManager {
|
|
6
7
|
static instance;
|
|
7
8
|
mcpClient = null;
|
|
@@ -29,21 +30,30 @@ class BrowserSessionManager {
|
|
|
29
30
|
}
|
|
30
31
|
// Initialize MCP client
|
|
31
32
|
this.mcpClient = new index_js_1.Client({ name: 'n8n-browser-automation', version: '1.0.0' }, { capabilities: {} });
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
// Determine transport based on endpoint type
|
|
34
|
+
const isUrl = mcpEndpoint.startsWith('http://') || mcpEndpoint.startsWith('https://');
|
|
35
|
+
if (isUrl) {
|
|
36
|
+
// Connect via SSE
|
|
37
|
+
this.transport = new sse_js_1.SSEClientTransport(new URL(mcpEndpoint));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// Connect via Stdio
|
|
41
|
+
this.transport = new stdio_js_1.StdioClientTransport({
|
|
42
|
+
command: 'node',
|
|
43
|
+
args: [mcpEndpoint],
|
|
44
|
+
env: {
|
|
45
|
+
...process.env,
|
|
46
|
+
...(useCDP && cdpEndpoint ? { CDP_URL: cdpEndpoint } : {})
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
41
50
|
try {
|
|
42
51
|
await this.mcpClient.connect(this.transport);
|
|
43
52
|
}
|
|
44
53
|
catch (error) {
|
|
45
54
|
this.isInitialized = false;
|
|
46
|
-
|
|
55
|
+
const transportType = isUrl ? 'SSE' : 'Stdio';
|
|
56
|
+
throw new Error(`Failed to connect to MCP server via ${transportType} at ${mcpEndpoint}. Error: ${error.message}`);
|
|
47
57
|
}
|
|
48
58
|
// Fetch available tools from MCP server
|
|
49
59
|
const toolsResponse = await this.mcpClient.listTools();
|
|
@@ -56,11 +66,20 @@ class BrowserSessionManager {
|
|
|
56
66
|
if (!this.mcpClient || !this.isInitialized) {
|
|
57
67
|
throw new Error('MCP client not initialized. Please configure credentials first.');
|
|
58
68
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
try {
|
|
70
|
+
if (this.config.mcpEndpoint?.includes('http')) {
|
|
71
|
+
console.log(`Calling remote tool: ${toolName} on ${this.config.mcpEndpoint}`);
|
|
72
|
+
}
|
|
73
|
+
const result = await this.mcpClient.callTool({
|
|
74
|
+
name: toolName,
|
|
75
|
+
arguments: toolArgs || {}
|
|
76
|
+
});
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error(`MCP Tool Call Error (${toolName}):`, error);
|
|
81
|
+
throw new Error(`MCP Tool Error: ${error.message}${error.data ? ' - ' + JSON.stringify(error.data) : ''}`);
|
|
82
|
+
}
|
|
64
83
|
}
|
|
65
84
|
getTools() {
|
|
66
85
|
return this.tools;
|
|
@@ -60,10 +60,24 @@ class SmartBrowserAutomation {
|
|
|
60
60
|
mode: ['manual'],
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
|
-
default: '',
|
|
64
|
-
description: 'Select the browser automation tool to execute. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
|
63
|
+
default: 'browser_connect_cdp',
|
|
64
|
+
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>.',
|
|
65
65
|
required: true,
|
|
66
66
|
},
|
|
67
|
+
{
|
|
68
|
+
displayName: 'CDP Endpoint',
|
|
69
|
+
name: 'cdpUrl',
|
|
70
|
+
type: 'string',
|
|
71
|
+
displayOptions: {
|
|
72
|
+
show: {
|
|
73
|
+
mode: ['manual'],
|
|
74
|
+
toolName: ['browser_connect_cdp'],
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
default: '',
|
|
78
|
+
placeholder: 'wss://gridnew.doingerp.com/devtools/...',
|
|
79
|
+
description: 'The wss:// or http:// endpoint for the browser CDP connection',
|
|
80
|
+
},
|
|
67
81
|
{
|
|
68
82
|
displayName: 'Tool Arguments',
|
|
69
83
|
name: 'toolArgs',
|
|
@@ -72,6 +86,9 @@ class SmartBrowserAutomation {
|
|
|
72
86
|
show: {
|
|
73
87
|
mode: ['manual'],
|
|
74
88
|
},
|
|
89
|
+
hide: {
|
|
90
|
+
toolName: ['browser_connect_cdp'],
|
|
91
|
+
},
|
|
75
92
|
},
|
|
76
93
|
default: '{}',
|
|
77
94
|
description: 'Arguments for the selected tool in JSON format',
|
|
@@ -108,14 +125,19 @@ class SmartBrowserAutomation {
|
|
|
108
125
|
type: 'collection',
|
|
109
126
|
placeholder: 'Add Option',
|
|
110
127
|
default: {},
|
|
128
|
+
displayOptions: {
|
|
129
|
+
show: {
|
|
130
|
+
mode: ['aiAgent'],
|
|
131
|
+
},
|
|
132
|
+
},
|
|
111
133
|
options: [
|
|
112
134
|
{
|
|
113
135
|
displayName: 'CDP Endpoint',
|
|
114
136
|
name: 'cdpUrl',
|
|
115
137
|
type: 'string',
|
|
116
138
|
default: '',
|
|
117
|
-
placeholder: 'wss
|
|
118
|
-
description: 'The
|
|
139
|
+
placeholder: 'wss://gridnew.doingerp.com/devtools/...',
|
|
140
|
+
description: 'The wss:// or http:// endpoint for the browser CDP connection',
|
|
119
141
|
},
|
|
120
142
|
{
|
|
121
143
|
displayName: 'Enabled Tool Names or IDs',
|
|
@@ -146,16 +168,26 @@ class SmartBrowserAutomation {
|
|
|
146
168
|
const credentials = await this.getCredentials('smartBrowserAutomationApi');
|
|
147
169
|
const sessionManager = BrowserSessionManager_1.default.getInstance();
|
|
148
170
|
const tools = await sessionManager.initialize(credentials.mcpEndpoint, credentials.browserMode === 'cdp', credentials.cdpEndpoint);
|
|
149
|
-
|
|
150
|
-
|
|
171
|
+
const nodeTools = [
|
|
172
|
+
{
|
|
173
|
+
name: 'Connect to Browser (CDP)',
|
|
174
|
+
value: 'browser_connect_cdp',
|
|
175
|
+
description: 'Connect to a browser via CDP URL',
|
|
176
|
+
},
|
|
177
|
+
];
|
|
178
|
+
if (tools && tools.length > 0) {
|
|
179
|
+
nodeTools.push(...tools.map((tool) => ({
|
|
180
|
+
name: tool.name.split('_').map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(' '),
|
|
181
|
+
value: tool.name,
|
|
182
|
+
})));
|
|
151
183
|
}
|
|
152
|
-
return
|
|
153
|
-
name: tool.name.split('_').map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(' '),
|
|
154
|
-
value: tool.name,
|
|
155
|
-
}));
|
|
184
|
+
return nodeTools;
|
|
156
185
|
}
|
|
157
186
|
catch (error) {
|
|
158
|
-
return [
|
|
187
|
+
return [
|
|
188
|
+
{ name: 'Connect to Browser (CDP)', value: 'browser_connect_cdp' },
|
|
189
|
+
{ name: `Error loading MCP tools: ${error.message}`, value: 'error' }
|
|
190
|
+
];
|
|
159
191
|
}
|
|
160
192
|
},
|
|
161
193
|
},
|
|
@@ -172,7 +204,7 @@ class SmartBrowserAutomation {
|
|
|
172
204
|
}
|
|
173
205
|
// Add a custom tool for the AI to connect to a specific CDP URL
|
|
174
206
|
const connectTool = {
|
|
175
|
-
name: '
|
|
207
|
+
name: 'browser_connect_cdp',
|
|
176
208
|
displayName: 'Connect to Browser (CDP)',
|
|
177
209
|
description: 'Connect to a specific browser instance using a CDP URL (wss://...)',
|
|
178
210
|
properties: [
|
|
@@ -207,11 +239,27 @@ class SmartBrowserAutomation {
|
|
|
207
239
|
if (mode === 'manual') {
|
|
208
240
|
// Manual mode: User selects tool and provides arguments
|
|
209
241
|
const toolName = this.getNodeParameter('toolName', i);
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
242
|
+
// Special case: Manual Browser Connection
|
|
243
|
+
if (toolName === 'browser_connect_cdp') {
|
|
244
|
+
const endpoint = this.getNodeParameter('cdpUrl', i);
|
|
245
|
+
if (!endpoint) {
|
|
246
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'CDP Endpoint URL is required for browser_connect_cdp');
|
|
247
|
+
}
|
|
248
|
+
if (verbose) {
|
|
249
|
+
console.log(`Connecting to browser CDP: ${endpoint}`);
|
|
250
|
+
}
|
|
251
|
+
await sessionManager.initialize(credentials.mcpEndpoint, true, endpoint);
|
|
252
|
+
returnData.push({
|
|
253
|
+
json: {
|
|
254
|
+
success: true,
|
|
255
|
+
message: `Connected to browser at ${endpoint}`,
|
|
256
|
+
timestamp: new Date().toISOString()
|
|
257
|
+
},
|
|
258
|
+
pairedItem: i,
|
|
259
|
+
});
|
|
260
|
+
continue;
|
|
214
261
|
}
|
|
262
|
+
const toolArgsStr = this.getNodeParameter('toolArgs', i);
|
|
215
263
|
let toolArgs;
|
|
216
264
|
try {
|
|
217
265
|
toolArgs = JSON.parse(toolArgsStr);
|
|
@@ -219,6 +267,10 @@ class SmartBrowserAutomation {
|
|
|
219
267
|
catch (error) {
|
|
220
268
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid JSON in Tool Arguments: ${error.message}`);
|
|
221
269
|
}
|
|
270
|
+
// Initialize session if not ready
|
|
271
|
+
if (!sessionManager.isReady()) {
|
|
272
|
+
await sessionManager.initialize(credentials.mcpEndpoint, credentials.browserMode === 'cdp', credentials.cdpEndpoint);
|
|
273
|
+
}
|
|
222
274
|
if (verbose) {
|
|
223
275
|
console.log(`Executing tool: ${toolName} with args:`, toolArgs);
|
|
224
276
|
}
|
|
@@ -236,13 +288,29 @@ class SmartBrowserAutomation {
|
|
|
236
288
|
// AI Agent mode: Just initialize or close
|
|
237
289
|
const operation = this.getNodeParameter('operation', i);
|
|
238
290
|
if (operation === 'initialize') {
|
|
291
|
+
// Pull CDP URL from options if available, fallback to credentials
|
|
239
292
|
const cdpUrl = options.cdpUrl || credentials.cdpEndpoint;
|
|
240
|
-
|
|
241
|
-
|
|
293
|
+
if (verbose) {
|
|
294
|
+
console.log(`Initializing AI session with CDP: ${cdpUrl}`);
|
|
295
|
+
}
|
|
296
|
+
const tools = await sessionManager.initialize(credentials.mcpEndpoint, true, cdpUrl);
|
|
297
|
+
// New logic: Auto-call browser_connect tool if a URL is provided
|
|
298
|
+
if (options.cdpUrl) {
|
|
299
|
+
if (verbose) {
|
|
300
|
+
console.log(`Auto-calling 'browser_connect' with endpoint: ${options.cdpUrl}`);
|
|
301
|
+
}
|
|
302
|
+
try {
|
|
303
|
+
await sessionManager.callTool('browser_connect', { endpoint: options.cdpUrl });
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
console.warn(`Failed to auto-connect browser via tool: ${error.message}`);
|
|
307
|
+
// We don't throw here to allow the AI to potentially fix it or show the error
|
|
308
|
+
}
|
|
309
|
+
}
|
|
242
310
|
returnData.push({
|
|
243
311
|
json: {
|
|
244
312
|
success: true,
|
|
245
|
-
message:
|
|
313
|
+
message: `MCP session initialized. Browser connect tool called for ${cdpUrl}.`,
|
|
246
314
|
toolsCount: tools.length,
|
|
247
315
|
tools: tools.map((t) => ({
|
|
248
316
|
name: t.name,
|