n8n-nodes-smart-browser-automation 1.3.2 → 1.5.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/nodes/SmartBrowserAutomation/BrowserSessionManager.d.ts +1 -0
- package/dist/nodes/SmartBrowserAutomation/BrowserSessionManager.js +7 -0
- package/dist/nodes/SmartBrowserAutomation/SmartBrowserAutomation.node.d.ts +0 -1
- package/dist/nodes/SmartBrowserAutomation/SmartBrowserAutomation.node.js +138 -157
- package/package.json +1 -1
|
@@ -15,6 +15,7 @@ declare class BrowserSessionManager {
|
|
|
15
15
|
initialize(mcpEndpoint: string, useCDP: boolean, cdpEndpoint?: string): Promise<MCPTool[]>;
|
|
16
16
|
callTool(toolName: string, toolArgs?: any): Promise<any>;
|
|
17
17
|
getTools(): MCPTool[];
|
|
18
|
+
listTools(): Promise<MCPTool[]>;
|
|
18
19
|
close(): Promise<void>;
|
|
19
20
|
isReady(): boolean;
|
|
20
21
|
}
|
|
@@ -67,6 +67,7 @@ class BrowserSessionManager {
|
|
|
67
67
|
this.config = { mcpEndpoint, cdpEndpoint };
|
|
68
68
|
// Fetch available tools from MCP server
|
|
69
69
|
const toolsResponse = await this.mcpClient.listTools();
|
|
70
|
+
await this.mcpClient.callTool({ name: 'browser_connect_cdp', arguments: { cdpEndpoint: cdpEndpoint || '' } });
|
|
70
71
|
this.tools = toolsResponse.tools;
|
|
71
72
|
return this.tools;
|
|
72
73
|
}
|
|
@@ -93,6 +94,12 @@ class BrowserSessionManager {
|
|
|
93
94
|
getTools() {
|
|
94
95
|
return this.tools;
|
|
95
96
|
}
|
|
97
|
+
async listTools() {
|
|
98
|
+
if (!this.mcpClient || !this.isInitialized) {
|
|
99
|
+
throw new Error('MCP session not initialized. Call initialize() first.');
|
|
100
|
+
}
|
|
101
|
+
return this.tools;
|
|
102
|
+
}
|
|
96
103
|
async close() {
|
|
97
104
|
if (this.mcpClient && this.transport) {
|
|
98
105
|
await this.mcpClient.close();
|
|
@@ -6,6 +6,5 @@ export declare class SmartBrowserAutomation implements INodeType {
|
|
|
6
6
|
getAvailableTools(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
7
7
|
};
|
|
8
8
|
};
|
|
9
|
-
getTools(this: IExecuteFunctions): Promise<any[]>;
|
|
10
9
|
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
11
10
|
}
|
|
@@ -4,15 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.SmartBrowserAutomation = void 0;
|
|
7
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
7
8
|
const BrowserSessionManager_1 = __importDefault(require("./BrowserSessionManager"));
|
|
8
|
-
const DynamicBrowserTools_1 = require("./tools/DynamicBrowserTools");
|
|
9
9
|
class SmartBrowserAutomation {
|
|
10
10
|
description = {
|
|
11
11
|
displayName: 'Smart Browser Automation',
|
|
12
12
|
name: 'smartBrowserAutomation',
|
|
13
13
|
group: ['transform'],
|
|
14
14
|
version: 1,
|
|
15
|
-
description: '
|
|
15
|
+
description: 'AI-powered browser automation via MCP Playwright server',
|
|
16
16
|
defaults: {
|
|
17
17
|
name: 'Browser Automation',
|
|
18
18
|
},
|
|
@@ -27,6 +27,14 @@ class SmartBrowserAutomation {
|
|
|
27
27
|
],
|
|
28
28
|
usableAsTool: true,
|
|
29
29
|
properties: [
|
|
30
|
+
{
|
|
31
|
+
displayName: 'CDP Endpoint Override',
|
|
32
|
+
name: 'cdpOverride',
|
|
33
|
+
type: 'string',
|
|
34
|
+
default: '',
|
|
35
|
+
placeholder: 'wss://gridnew.doingerp.com/devtools/...',
|
|
36
|
+
description: 'Override CDP endpoint from credentials. Use this to connect to a specific browser instance.',
|
|
37
|
+
},
|
|
30
38
|
{
|
|
31
39
|
displayName: 'Operation',
|
|
32
40
|
name: 'operation',
|
|
@@ -34,201 +42,174 @@ class SmartBrowserAutomation {
|
|
|
34
42
|
noDataExpression: true,
|
|
35
43
|
options: [
|
|
36
44
|
{
|
|
37
|
-
name: '
|
|
38
|
-
value: '
|
|
39
|
-
description: '
|
|
40
|
-
action: '
|
|
45
|
+
name: 'All Tools',
|
|
46
|
+
value: 'listTools',
|
|
47
|
+
description: 'Get all available browser tools from MCP server',
|
|
48
|
+
action: 'List all browser tools',
|
|
41
49
|
},
|
|
42
50
|
{
|
|
43
|
-
name: '
|
|
44
|
-
value: '
|
|
45
|
-
description: '
|
|
46
|
-
action: '
|
|
51
|
+
name: 'Click',
|
|
52
|
+
value: 'browser_click',
|
|
53
|
+
description: 'Click an element',
|
|
54
|
+
action: 'Click element',
|
|
47
55
|
},
|
|
48
|
-
],
|
|
49
|
-
default: 'initialize',
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
displayName: 'Options',
|
|
53
|
-
name: 'options',
|
|
54
|
-
type: 'collection',
|
|
55
|
-
placeholder: 'Add Option',
|
|
56
|
-
default: {},
|
|
57
|
-
options: [
|
|
58
56
|
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
placeholder: 'wss://gridnew.doingerp.com/devtools/...',
|
|
64
|
-
description: 'Browser CDP endpoint to connect to. If not provided, MCP server will launch a new browser.',
|
|
57
|
+
name: 'Connect to Browser',
|
|
58
|
+
value: 'browser_connect_cdp',
|
|
59
|
+
description: 'Connect to browser via CDP',
|
|
60
|
+
action: 'Connect to browser via CDP',
|
|
65
61
|
},
|
|
66
62
|
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
63
|
+
name: 'Navigate',
|
|
64
|
+
value: 'browser_navigate',
|
|
65
|
+
description: 'Navigate to a URL',
|
|
66
|
+
action: 'Navigate to URL',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'Take Snapshot',
|
|
70
|
+
value: 'browser_snapshot',
|
|
71
|
+
description: 'Capture page accessibility snapshot',
|
|
72
|
+
action: 'Take snapshot',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'Type',
|
|
76
|
+
value: 'browser_type',
|
|
77
|
+
description: 'Type text into an element',
|
|
78
|
+
action: 'Type text',
|
|
72
79
|
},
|
|
73
80
|
],
|
|
81
|
+
default: 'browser_connect_cdp',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
displayName: 'Tool Parameters',
|
|
85
|
+
name: 'toolParameters',
|
|
86
|
+
type: 'json',
|
|
87
|
+
required: true,
|
|
88
|
+
displayOptions: {
|
|
89
|
+
show: {
|
|
90
|
+
operation: [
|
|
91
|
+
'browser_connect_cdp',
|
|
92
|
+
'browser_navigate',
|
|
93
|
+
'browser_click',
|
|
94
|
+
'browser_type',
|
|
95
|
+
'browser_snapshot',
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
default: '{}',
|
|
100
|
+
description: 'Parameters to pass to the browser tool in JSON format',
|
|
74
101
|
},
|
|
75
102
|
],
|
|
76
103
|
};
|
|
77
104
|
methods = {
|
|
78
105
|
loadOptions: {
|
|
79
|
-
// Populate tool dropdown in manual mode
|
|
80
106
|
async getAvailableTools() {
|
|
81
107
|
try {
|
|
82
108
|
const credentials = await this.getCredentials('smartBrowserAutomationApi');
|
|
83
109
|
const sessionManager = BrowserSessionManager_1.default.getInstance();
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
];
|
|
92
|
-
if (tools && tools.length > 0) {
|
|
93
|
-
nodeTools.push(...tools.map((tool) => ({
|
|
94
|
-
name: tool.name.split('_').map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(' '),
|
|
95
|
-
value: tool.name,
|
|
96
|
-
})));
|
|
97
|
-
}
|
|
98
|
-
return nodeTools;
|
|
110
|
+
await sessionManager.initialize(credentials.mcpEndpoint, false, '');
|
|
111
|
+
const tools = await sessionManager.listTools();
|
|
112
|
+
return tools.map((tool) => ({
|
|
113
|
+
name: tool.name.split('_').map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(' '),
|
|
114
|
+
value: tool.name,
|
|
115
|
+
description: tool.description || '',
|
|
116
|
+
}));
|
|
99
117
|
}
|
|
100
118
|
catch (error) {
|
|
101
119
|
return [
|
|
102
|
-
{ name:
|
|
103
|
-
{ name: `Error loading MCP tools: ${error.message}`, value: 'error' }
|
|
120
|
+
{ name: `Error loading tools: ${error.message}`, value: 'error' }
|
|
104
121
|
];
|
|
105
122
|
}
|
|
106
123
|
},
|
|
107
124
|
},
|
|
108
125
|
};
|
|
109
|
-
// Expose tools to AI Agent nodes
|
|
110
|
-
async getTools() {
|
|
111
|
-
const sessionManager = BrowserSessionManager_1.default.getInstance();
|
|
112
|
-
const credentials = await this.getCredentials('smartBrowserAutomationApi');
|
|
113
|
-
console.log('[getTools] Starting to fetch tools...');
|
|
114
|
-
// Check if session is already initialized
|
|
115
|
-
if (!sessionManager.isReady()) {
|
|
116
|
-
console.log('[getTools] Session not ready, initializing...');
|
|
117
|
-
try {
|
|
118
|
-
await sessionManager.initialize(credentials.mcpEndpoint, credentials.browserMode === 'cdp', credentials.cdpEndpoint);
|
|
119
|
-
console.log('[getTools] Session initialized successfully');
|
|
120
|
-
}
|
|
121
|
-
catch (error) {
|
|
122
|
-
console.error('[getTools] Failed to initialize session:', error.message);
|
|
123
|
-
// Return minimal tools if initialization fails
|
|
124
|
-
return [];
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// Get all individual MCP tools
|
|
128
|
-
const mcpTools = await (0, DynamicBrowserTools_1.createDynamicBrowserTools)(credentials);
|
|
129
|
-
console.log(`[getTools] Fetched ${mcpTools.length} MCP tools`);
|
|
130
|
-
// Add custom CDP connection tool
|
|
131
|
-
const connectTool = {
|
|
132
|
-
name: 'browser_connect_cdp',
|
|
133
|
-
displayName: 'Connect to Browser (CDP)',
|
|
134
|
-
description: 'Connect to a specific browser instance using a CDP endpoint URL',
|
|
135
|
-
properties: [
|
|
136
|
-
{
|
|
137
|
-
displayName: 'Endpoint URL',
|
|
138
|
-
name: 'endpoint',
|
|
139
|
-
type: 'string',
|
|
140
|
-
default: '',
|
|
141
|
-
required: true,
|
|
142
|
-
description: 'The wss:// or http:// CDP endpoint',
|
|
143
|
-
},
|
|
144
|
-
],
|
|
145
|
-
async execute(input) {
|
|
146
|
-
const sessionManager = BrowserSessionManager_1.default.getInstance();
|
|
147
|
-
const credentials = await this.getCredentials('smartBrowserAutomationApi');
|
|
148
|
-
await sessionManager.initialize(credentials.mcpEndpoint, true, input.endpoint);
|
|
149
|
-
return {
|
|
150
|
-
content: [{ type: 'text', text: `Connected to browser at ${input.endpoint}.` }],
|
|
151
|
-
isError: false,
|
|
152
|
-
toolName: 'browser_connect_cdp'
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
return [...mcpTools, connectTool];
|
|
157
|
-
}
|
|
158
126
|
async execute() {
|
|
159
|
-
const items = this.getInputData();
|
|
160
127
|
const returnData = [];
|
|
161
128
|
const credentials = await this.getCredentials('smartBrowserAutomationApi');
|
|
162
129
|
const sessionManager = BrowserSessionManager_1.default.getInstance();
|
|
163
|
-
|
|
130
|
+
// Get CDP override or use from credentials
|
|
131
|
+
const cdpOverride = this.getNodeParameter('cdpOverride', 0, '');
|
|
132
|
+
const operation = this.getNodeParameter('operation', 0);
|
|
133
|
+
try {
|
|
134
|
+
// Initialize session if not ready
|
|
135
|
+
if (!sessionManager.isReady()) {
|
|
136
|
+
const cdpUrl = cdpOverride || credentials.cdpEndpoint || '';
|
|
137
|
+
await sessionManager.initialize(credentials.mcpEndpoint, !!cdpUrl, cdpUrl);
|
|
138
|
+
}
|
|
139
|
+
// Handle listTools operation
|
|
140
|
+
if (operation === 'listTools') {
|
|
141
|
+
const tools = await sessionManager.listTools();
|
|
142
|
+
returnData.push({
|
|
143
|
+
json: { tools },
|
|
144
|
+
});
|
|
145
|
+
return [returnData];
|
|
146
|
+
}
|
|
147
|
+
// Handle tool execution
|
|
148
|
+
let toolParams;
|
|
164
149
|
try {
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (options.cdpUrl) {
|
|
173
|
-
if (verbose) {
|
|
174
|
-
console.log(`Auto-calling 'browser_connect_cdp' with endpoint: ${options.cdpUrl}`);
|
|
175
|
-
}
|
|
176
|
-
try {
|
|
177
|
-
const connectionResult = await sessionManager.callTool('browser_connect_cdp', { endpoint: options.cdpUrl });
|
|
178
|
-
// Return only the connection result, no extra messages
|
|
179
|
-
returnData.push({
|
|
180
|
-
json: connectionResult,
|
|
181
|
-
pairedItem: i,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
catch (error) {
|
|
185
|
-
returnData.push({
|
|
186
|
-
json: {
|
|
187
|
-
success: false,
|
|
188
|
-
error: `Failed to connect: ${error.message}`
|
|
189
|
-
},
|
|
190
|
-
pairedItem: i,
|
|
191
|
-
});
|
|
192
|
-
}
|
|
150
|
+
const rawParams = this.getNodeParameter('toolParameters', 0);
|
|
151
|
+
if (rawParams === undefined || rawParams === null) {
|
|
152
|
+
toolParams = {};
|
|
153
|
+
}
|
|
154
|
+
else if (typeof rawParams === 'string') {
|
|
155
|
+
if (!rawParams || rawParams.trim() === '') {
|
|
156
|
+
toolParams = {};
|
|
193
157
|
}
|
|
194
158
|
else {
|
|
195
|
-
|
|
196
|
-
returnData.push({
|
|
197
|
-
json: {
|
|
198
|
-
success: true,
|
|
199
|
-
message: 'MCP session initialized (no browser connection)'
|
|
200
|
-
},
|
|
201
|
-
pairedItem: i,
|
|
202
|
-
});
|
|
159
|
+
toolParams = JSON.parse(rawParams);
|
|
203
160
|
}
|
|
204
161
|
}
|
|
205
|
-
else if (
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
162
|
+
else if (typeof rawParams === 'object') {
|
|
163
|
+
// Handle object input (when used as a tool in AI Agent)
|
|
164
|
+
toolParams = rawParams;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
try {
|
|
168
|
+
toolParams = JSON.parse(JSON.stringify(rawParams));
|
|
169
|
+
}
|
|
170
|
+
catch (parseError) {
|
|
171
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid parameter type: ${typeof rawParams}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Ensure toolParams is an object
|
|
175
|
+
if (typeof toolParams !== 'object' ||
|
|
176
|
+
toolParams === null ||
|
|
177
|
+
Array.isArray(toolParams)) {
|
|
178
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Tool parameters must be a JSON object');
|
|
214
179
|
}
|
|
215
180
|
}
|
|
216
181
|
catch (error) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
throw error;
|
|
182
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to parse tool parameters: ${error.message}. Make sure the parameters are valid JSON.`);
|
|
183
|
+
}
|
|
184
|
+
// Special handling for browser_connect_cdp
|
|
185
|
+
if (operation === 'browser_connect_cdp') {
|
|
186
|
+
const endpoint = toolParams.endpoint || cdpOverride || credentials.cdpEndpoint;
|
|
187
|
+
if (!endpoint) {
|
|
188
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'CDP endpoint is required. Provide it in tool parameters or CDP Endpoint Override field.');
|
|
228
189
|
}
|
|
190
|
+
// Reinitialize with new CDP endpoint
|
|
191
|
+
await sessionManager.close();
|
|
192
|
+
await sessionManager.initialize(credentials.mcpEndpoint, true, endpoint);
|
|
193
|
+
returnData.push({
|
|
194
|
+
json: {
|
|
195
|
+
result: {
|
|
196
|
+
content: [{ type: 'text', text: `Connected to browser at ${endpoint}` }],
|
|
197
|
+
isError: false,
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
return [returnData];
|
|
229
202
|
}
|
|
203
|
+
// Execute the tool via MCP
|
|
204
|
+
const result = await sessionManager.callTool(operation, toolParams);
|
|
205
|
+
returnData.push({
|
|
206
|
+
json: { result },
|
|
207
|
+
});
|
|
208
|
+
return [returnData];
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to execute operation: ${error.message}`);
|
|
230
212
|
}
|
|
231
|
-
return [returnData];
|
|
232
213
|
}
|
|
233
214
|
}
|
|
234
215
|
exports.SmartBrowserAutomation = SmartBrowserAutomation;
|