brave-real-browser-mcp-server 2.4.2 → 2.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.
@@ -3,6 +3,7 @@ import { withErrorHandling } from '../system-utils.js';
3
3
  import { validateWorkflow, recordExecution, workflowValidator } from '../workflow-validation.js';
4
4
  import { selfHealingLocators } from '../self-healing-locators.js';
5
5
  import { randomScroll } from '../stealth-actions.js';
6
+ import { setTimeout as sleep } from 'node:timers/promises';
6
7
  // Click handler
7
8
  export async function handleClick(args) {
8
9
  return await withWorkflowValidation('click', args, async () => {
@@ -117,18 +118,62 @@ export async function handleType(args) {
117
118
  try {
118
119
  // Wait for element to be ready and interactable
119
120
  await pageInstance.waitForSelector(usedSelector, { timeout: 5000 });
120
- // Focus on the element first
121
- await element.focus();
122
- // Clear existing content
123
- await pageInstance.evaluate((sel) => {
121
+ // Check if element is a dropdown/select
122
+ const isDropdown = await pageInstance.evaluate((sel) => {
124
123
  const el = document.querySelector(sel);
125
- if (el) {
126
- el.select();
127
- el.value = '';
128
- }
124
+ return el?.tagName.toLowerCase() === 'select';
129
125
  }, usedSelector);
130
- // Type the new text
131
- await pageInstance.type(usedSelector, text, { delay });
126
+ if (isDropdown) {
127
+ // Handle dropdown selection with proper event triggering
128
+ await pageInstance.evaluate((sel, value) => {
129
+ const selectEl = document.querySelector(sel);
130
+ if (!selectEl)
131
+ return;
132
+ // Human-like behavior: Focus first
133
+ selectEl.focus();
134
+ // Find option by text or value
135
+ const options = Array.from(selectEl.options);
136
+ const matchedOption = options.find(opt => opt.text.toLowerCase().includes(value.toLowerCase()) ||
137
+ opt.value.toLowerCase().includes(value.toLowerCase()));
138
+ if (matchedOption) {
139
+ // Set the value
140
+ selectEl.value = matchedOption.value;
141
+ // Fire all relevant events for dynamic dropdowns
142
+ selectEl.dispatchEvent(new Event('input', { bubbles: true }));
143
+ selectEl.dispatchEvent(new Event('change', { bubbles: true }));
144
+ selectEl.dispatchEvent(new Event('blur', { bubbles: true }));
145
+ // Trigger jQuery change event if jQuery exists
146
+ if (typeof window.jQuery !== 'undefined') {
147
+ window.jQuery(selectEl).trigger('change');
148
+ }
149
+ }
150
+ }, usedSelector, text);
151
+ // Wait a bit for dependent dropdowns to load
152
+ await sleep(1500);
153
+ }
154
+ else {
155
+ // Regular input field
156
+ // Focus on the element first
157
+ await element.focus();
158
+ // Clear existing content
159
+ await pageInstance.evaluate((sel) => {
160
+ const el = document.querySelector(sel);
161
+ if (el) {
162
+ el.select();
163
+ el.value = '';
164
+ }
165
+ }, usedSelector);
166
+ // Type the new text with human-like delay
167
+ await pageInstance.type(usedSelector, text, { delay });
168
+ // Fire events for dynamic forms
169
+ await pageInstance.evaluate((sel) => {
170
+ const el = document.querySelector(sel);
171
+ if (el) {
172
+ el.dispatchEvent(new Event('input', { bubbles: true }));
173
+ el.dispatchEvent(new Event('change', { bubbles: true }));
174
+ }
175
+ }, usedSelector);
176
+ }
132
177
  return {
133
178
  content: [
134
179
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-browser-mcp-server",
3
- "version": "2.4.2",
3
+ "version": "2.5.0",
4
4
  "description": "MCP server for brave-real-browser",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",