n8n-nodes-smart-browser-automation 1.3.1 → 1.4.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.
@@ -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
  }
@@ -93,6 +93,12 @@ class BrowserSessionManager {
93
93
  getTools() {
94
94
  return this.tools;
95
95
  }
96
+ async listTools() {
97
+ if (!this.mcpClient || !this.isInitialized) {
98
+ throw new Error('MCP session not initialized. Call initialize() first.');
99
+ }
100
+ return this.tools;
101
+ }
96
102
  async close() {
97
103
  if (this.mcpClient && this.transport) {
98
104
  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: 'Browser automation with AI Agent mode (auto) or Manual mode (user choice)',
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,185 +42,174 @@ class SmartBrowserAutomation {
34
42
  noDataExpression: true,
35
43
  options: [
36
44
  {
37
- name: 'Initialize Session',
38
- value: 'initialize',
39
- description: 'Initialize browser session and load available tools',
40
- action: 'Initialize browser session and load available tools',
45
+ name: 'Click',
46
+ value: 'browser_click',
47
+ description: 'Click an element',
48
+ action: 'Click element',
41
49
  },
42
50
  {
43
- name: 'Close Session',
44
- value: 'close',
45
- description: 'Close browser session and cleanup',
46
- action: 'Close browser session and cleanup',
51
+ name: 'Connect to Browser',
52
+ value: 'browser_connect_cdp',
53
+ description: 'Connect to browser via CDP',
54
+ action: 'Connect to browser via CDP',
55
+ },
56
+ {
57
+ name: 'List All Tools',
58
+ value: 'listTools',
59
+ description: 'Get all available browser tools from MCP server',
60
+ action: 'List all browser tools',
61
+ },
62
+ {
63
+ name: 'Navigate',
64
+ value: 'browser_navigate',
65
+ description: 'Navigate to a URL',
66
+ action: 'Navigate to URL',
47
67
  },
48
- ],
49
- default: 'initialize',
50
- },
51
- {
52
- displayName: 'Options',
53
- name: 'options',
54
- type: 'collection',
55
- placeholder: 'Add Option',
56
- default: {},
57
- options: [
58
68
  {
59
- displayName: 'CDP Endpoint',
60
- name: 'cdpUrl',
61
- type: 'string',
62
- default: '',
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.',
69
+ name: 'Take Snapshot',
70
+ value: 'browser_snapshot',
71
+ description: 'Capture page accessibility snapshot',
72
+ action: 'Take snapshot',
65
73
  },
66
74
  {
67
- displayName: 'Verbose Logging',
68
- name: 'verbose',
69
- type: 'boolean',
70
- default: false,
71
- description: 'Whether to enable detailed logging',
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
- const tools = await sessionManager.initialize(credentials.mcpEndpoint, credentials.browserMode === 'cdp', credentials.cdpEndpoint);
85
- const nodeTools = [
86
- {
87
- name: 'Connect to Browser (CDP)',
88
- value: 'browser_connect_cdp',
89
- description: 'Connect to a browser via CDP URL',
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: 'Connect to Browser (CDP)', value: 'browser_connect_cdp' },
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 credentials = await this.getCredentials('smartBrowserAutomationApi');
112
- // Get all individual MCP tools
113
- const mcpTools = await (0, DynamicBrowserTools_1.createDynamicBrowserTools)(credentials);
114
- // Add custom CDP connection tool
115
- const connectTool = {
116
- name: 'browser_connect_cdp',
117
- displayName: 'Connect to Browser (CDP)',
118
- description: 'Connect to a specific browser instance using a CDP endpoint URL',
119
- properties: [
120
- {
121
- displayName: 'Endpoint URL',
122
- name: 'endpoint',
123
- type: 'string',
124
- default: '',
125
- required: true,
126
- description: 'The wss:// or http:// CDP endpoint',
127
- },
128
- ],
129
- async execute(input) {
130
- const sessionManager = BrowserSessionManager_1.default.getInstance();
131
- const credentials = await this.getCredentials('smartBrowserAutomationApi');
132
- await sessionManager.initialize(credentials.mcpEndpoint, true, input.endpoint);
133
- return {
134
- content: [{ type: 'text', text: `Connected to browser at ${input.endpoint}.` }],
135
- isError: false,
136
- toolName: 'browser_connect_cdp'
137
- };
138
- }
139
- };
140
- return [...mcpTools, connectTool];
141
- }
142
126
  async execute() {
143
- const items = this.getInputData();
144
127
  const returnData = [];
145
128
  const credentials = await this.getCredentials('smartBrowserAutomationApi');
146
129
  const sessionManager = BrowserSessionManager_1.default.getInstance();
147
- for (let i = 0; i < items.length; i++) {
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;
148
149
  try {
149
- const options = this.getNodeParameter('options', i, {});
150
- const verbose = options.verbose || false;
151
- const operation = this.getNodeParameter('operation', i);
152
- if (operation === 'initialize') {
153
- const cdpUrl = credentials.cdpEndpoint;
154
- await sessionManager.initialize(credentials.mcpEndpoint, true, cdpUrl);
155
- // New logic: Auto-call browser_connect_cdp tool if a URL is provided
156
- if (options.cdpUrl) {
157
- if (verbose) {
158
- console.log(`Auto-calling 'browser_connect_cdp' with endpoint: ${options.cdpUrl}`);
159
- }
160
- try {
161
- const connectionResult = await sessionManager.callTool('browser_connect_cdp', { endpoint: options.cdpUrl });
162
- // Return only the connection result, no extra messages
163
- returnData.push({
164
- json: connectionResult,
165
- pairedItem: i,
166
- });
167
- }
168
- catch (error) {
169
- returnData.push({
170
- json: {
171
- success: false,
172
- error: `Failed to connect: ${error.message}`
173
- },
174
- pairedItem: i,
175
- });
176
- }
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 = {};
177
157
  }
178
158
  else {
179
- // No CDP URL provided
180
- returnData.push({
181
- json: {
182
- success: true,
183
- message: 'MCP session initialized (no browser connection)'
184
- },
185
- pairedItem: i,
186
- });
159
+ toolParams = JSON.parse(rawParams);
187
160
  }
188
161
  }
189
- else if (operation === 'close') {
190
- await sessionManager.close();
191
- returnData.push({
192
- json: {
193
- success: true,
194
- message: 'Browser session closed',
195
- },
196
- pairedItem: i,
197
- });
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');
198
179
  }
199
180
  }
200
181
  catch (error) {
201
- if (this.continueOnFail()) {
202
- returnData.push({
203
- json: {
204
- success: false,
205
- error: error.message
206
- },
207
- pairedItem: i,
208
- });
209
- }
210
- else {
211
- 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.');
212
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];
213
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}`);
214
212
  }
215
- return [returnData];
216
213
  }
217
214
  }
218
215
  exports.SmartBrowserAutomation = SmartBrowserAutomation;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-smart-browser-automation",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "n8n node for AI-driven browser automation using MCP",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",