n8n-nodes-smart-browser-automation 1.0.0 → 1.0.6
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.js +11 -2
- package/dist/nodes/SmartBrowserAutomation/SmartBrowserAutomation.node.d.ts +1 -1
- package/dist/nodes/SmartBrowserAutomation/SmartBrowserAutomation.node.js +86 -17
- package/dist/nodes/SmartBrowserAutomation/smartBrowserAutomation.svg +11 -0
- package/package.json +1 -1
|
@@ -33,9 +33,18 @@ class BrowserSessionManager {
|
|
|
33
33
|
this.transport = new stdio_js_1.StdioClientTransport({
|
|
34
34
|
command: 'node',
|
|
35
35
|
args: [mcpEndpoint],
|
|
36
|
-
env:
|
|
36
|
+
env: {
|
|
37
|
+
...process.env,
|
|
38
|
+
...(useCDP && cdpEndpoint ? { CDP_URL: cdpEndpoint } : {})
|
|
39
|
+
}
|
|
37
40
|
});
|
|
38
|
-
|
|
41
|
+
try {
|
|
42
|
+
await this.mcpClient.connect(this.transport);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
this.isInitialized = false;
|
|
46
|
+
throw new Error(`Failed to connect to MCP server at ${mcpEndpoint}. Ensure the path is correct and accessible within your n8n environment. Error: ${error.message}`);
|
|
47
|
+
}
|
|
39
48
|
// Fetch available tools from MCP server
|
|
40
49
|
const toolsResponse = await this.mcpClient.listTools();
|
|
41
50
|
this.tools = toolsResponse.tools || [];
|
|
@@ -6,6 +6,6 @@ export declare class SmartBrowserAutomation implements INodeType {
|
|
|
6
6
|
getAvailableTools(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
7
7
|
};
|
|
8
8
|
};
|
|
9
|
-
getTools
|
|
9
|
+
getTools(this: IExecuteFunctions): Promise<any[]>;
|
|
10
10
|
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
11
11
|
}
|
|
@@ -19,12 +19,14 @@ class SmartBrowserAutomation {
|
|
|
19
19
|
},
|
|
20
20
|
inputs: ['main'],
|
|
21
21
|
outputs: ['main'],
|
|
22
|
+
icon: 'file:smartBrowserAutomation.svg',
|
|
22
23
|
credentials: [
|
|
23
24
|
{
|
|
24
25
|
name: 'smartBrowserAutomationApi',
|
|
25
26
|
required: true,
|
|
26
27
|
},
|
|
27
28
|
],
|
|
29
|
+
usableAsTool: true,
|
|
28
30
|
properties: [
|
|
29
31
|
{
|
|
30
32
|
displayName: 'Mode',
|
|
@@ -101,11 +103,38 @@ class SmartBrowserAutomation {
|
|
|
101
103
|
default: 'initialize',
|
|
102
104
|
},
|
|
103
105
|
{
|
|
104
|
-
displayName: '
|
|
105
|
-
name: '
|
|
106
|
-
type: '
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
displayName: 'Options',
|
|
107
|
+
name: 'options',
|
|
108
|
+
type: 'collection',
|
|
109
|
+
placeholder: 'Add Option',
|
|
110
|
+
default: {},
|
|
111
|
+
options: [
|
|
112
|
+
{
|
|
113
|
+
displayName: 'CDP Endpoint',
|
|
114
|
+
name: 'cdpUrl',
|
|
115
|
+
type: 'string',
|
|
116
|
+
default: '',
|
|
117
|
+
placeholder: 'wss://...',
|
|
118
|
+
description: 'The CDP URL to connect to. Overrides the one in credentials if provided.',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
displayName: 'Enabled Tool Names or IDs',
|
|
122
|
+
name: 'enabledTools',
|
|
123
|
+
type: 'multiOptions',
|
|
124
|
+
typeOptions: {
|
|
125
|
+
loadOptionsMethod: 'getAvailableTools',
|
|
126
|
+
},
|
|
127
|
+
default: [],
|
|
128
|
+
description: 'Select which tools to expose to the AI Agent or Manual list. Leave empty for all. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
displayName: 'Verbose',
|
|
132
|
+
name: 'verbose',
|
|
133
|
+
type: 'boolean',
|
|
134
|
+
default: false,
|
|
135
|
+
description: 'Whether to enable detailed logging',
|
|
136
|
+
},
|
|
137
|
+
],
|
|
109
138
|
},
|
|
110
139
|
],
|
|
111
140
|
};
|
|
@@ -113,20 +142,57 @@ class SmartBrowserAutomation {
|
|
|
113
142
|
loadOptions: {
|
|
114
143
|
// Populate tool dropdown in manual mode
|
|
115
144
|
async getAvailableTools() {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
145
|
+
try {
|
|
146
|
+
const credentials = await this.getCredentials('smartBrowserAutomationApi');
|
|
147
|
+
const sessionManager = BrowserSessionManager_1.default.getInstance();
|
|
148
|
+
const tools = await sessionManager.initialize(credentials.mcpEndpoint, credentials.browserMode === 'cdp', credentials.cdpEndpoint);
|
|
149
|
+
if (!tools || tools.length === 0) {
|
|
150
|
+
return [{ name: 'No Tools Found - Check MCP Server', value: 'none' }];
|
|
151
|
+
}
|
|
152
|
+
return tools.map((tool) => ({
|
|
153
|
+
name: tool.name.split('_').map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(' '),
|
|
154
|
+
value: tool.name,
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
return [{ name: `Error: ${error.message}`, value: 'error' }];
|
|
159
|
+
}
|
|
123
160
|
},
|
|
124
161
|
},
|
|
125
162
|
};
|
|
126
163
|
// Expose tools to AI Agent nodes
|
|
127
164
|
async getTools() {
|
|
128
165
|
const credentials = await this.getCredentials('smartBrowserAutomationApi');
|
|
129
|
-
|
|
166
|
+
const options = this.getNodeParameter('options', 0, {});
|
|
167
|
+
const enabledTools = options.enabledTools || [];
|
|
168
|
+
let tools = await (0, DynamicBrowserTools_1.createDynamicBrowserTools)(credentials);
|
|
169
|
+
// Filter tools if a selection was made
|
|
170
|
+
if (enabledTools.length > 0) {
|
|
171
|
+
tools = tools.filter(tool => enabledTools.includes(tool.name));
|
|
172
|
+
}
|
|
173
|
+
// Add a custom tool for the AI to connect to a specific CDP URL
|
|
174
|
+
const connectTool = {
|
|
175
|
+
name: 'browser_cdp_connect',
|
|
176
|
+
displayName: 'Connect to Browser (CDP)',
|
|
177
|
+
description: 'Connect to a specific browser instance using a CDP URL (wss://...)',
|
|
178
|
+
properties: [
|
|
179
|
+
{
|
|
180
|
+
displayName: 'Endpoint URL',
|
|
181
|
+
name: 'endpoint',
|
|
182
|
+
type: 'string',
|
|
183
|
+
default: '',
|
|
184
|
+
required: true,
|
|
185
|
+
description: 'The wss:// or http:// endpoint for the browser CDP connection',
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
async execute(input) {
|
|
189
|
+
const sessionManager = BrowserSessionManager_1.default.getInstance();
|
|
190
|
+
const credentials = await this.getCredentials('smartBrowserAutomationApi');
|
|
191
|
+
await sessionManager.initialize(credentials.mcpEndpoint, true, input.endpoint);
|
|
192
|
+
return { success: true, message: `Connected to browser at ${input.endpoint}` };
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
return [connectTool, ...tools];
|
|
130
196
|
}
|
|
131
197
|
async execute() {
|
|
132
198
|
const items = this.getInputData();
|
|
@@ -136,11 +202,12 @@ class SmartBrowserAutomation {
|
|
|
136
202
|
const mode = this.getNodeParameter('mode', 0);
|
|
137
203
|
for (let i = 0; i < items.length; i++) {
|
|
138
204
|
try {
|
|
205
|
+
const options = this.getNodeParameter('options', i, {});
|
|
206
|
+
const verbose = options.verbose || false;
|
|
139
207
|
if (mode === 'manual') {
|
|
140
208
|
// Manual mode: User selects tool and provides arguments
|
|
141
209
|
const toolName = this.getNodeParameter('toolName', i);
|
|
142
210
|
const toolArgsStr = this.getNodeParameter('toolArgs', i);
|
|
143
|
-
const verbose = this.getNodeParameter('verbose', i, false);
|
|
144
211
|
// Initialize session if not ready
|
|
145
212
|
if (!sessionManager.isReady()) {
|
|
146
213
|
await sessionManager.initialize(credentials.mcpEndpoint, credentials.browserMode === 'cdp', credentials.cdpEndpoint);
|
|
@@ -150,10 +217,10 @@ class SmartBrowserAutomation {
|
|
|
150
217
|
toolArgs = JSON.parse(toolArgsStr);
|
|
151
218
|
}
|
|
152
219
|
catch (error) {
|
|
153
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid JSON in Tool Arguments: ${error.message}
|
|
220
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid JSON in Tool Arguments: ${error.message}`);
|
|
154
221
|
}
|
|
155
222
|
if (verbose) {
|
|
156
|
-
console.log(`Executing tool: ${toolName} with args
|
|
223
|
+
console.log(`Executing tool: ${toolName} with args:`, toolArgs);
|
|
157
224
|
}
|
|
158
225
|
const result = await sessionManager.callTool(toolName, toolArgs);
|
|
159
226
|
returnData.push({
|
|
@@ -169,7 +236,9 @@ class SmartBrowserAutomation {
|
|
|
169
236
|
// AI Agent mode: Just initialize or close
|
|
170
237
|
const operation = this.getNodeParameter('operation', i);
|
|
171
238
|
if (operation === 'initialize') {
|
|
172
|
-
const
|
|
239
|
+
const cdpUrl = options.cdpUrl || credentials.cdpEndpoint;
|
|
240
|
+
const tools = await sessionManager.initialize(credentials.mcpEndpoint, true, // Force CDP if using initialize in AI mode
|
|
241
|
+
cdpUrl);
|
|
173
242
|
returnData.push({
|
|
174
243
|
json: {
|
|
175
244
|
success: true,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect x="4" y="10" width="56" height="44" rx="4" fill="#6366F1"/>
|
|
3
|
+
<rect x="4" y="10" width="56" height="10" rx="4" fill="#4F46E5"/>
|
|
4
|
+
<circle cx="10" cy="15" r="2" fill="#F87171"/>
|
|
5
|
+
<circle cx="16" cy="15" r="2" fill="#FBBF24"/>
|
|
6
|
+
<circle cx="22" cy="15" r="2" fill="#34D399"/>
|
|
7
|
+
<path d="M32 28C38.6274 28 44 33.3726 44 40C44 46.6274 38.6274 52 32 52C25.3726 52 20 46.6274 20 40C20 33.3726 25.3726 28 32 28Z" fill="white" fill-opacity="0.2"/>
|
|
8
|
+
<path d="M32 32C36.4183 32 40 35.5817 40 40C40 44.4183 36.4183 48 32 48C27.5817 48 24 44.4183 24 40C24 35.5817 27.5817 32 32 32Z" fill="white"/>
|
|
9
|
+
<path d="M32 37L35 40L32 43" stroke="#4F46E5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
10
|
+
<path d="M29 37L32 40L29 43" stroke="#4F46E5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" transform="rotate(180 30.5 40) translate(-3 0)"/>
|
|
11
|
+
</svg>
|