brave-real-browser-mcp-server 2.41.12 → 2.41.14

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-browser-mcp-server",
3
- "version": "2.41.12",
3
+ "version": "2.41.14",
4
4
  "description": "MCP Server for Brave Real Browser - Puppeteer with Brave Browser, Stealth Mode, Ad Blocker, and Turnstile Auto-Solver for undetectable web automation.",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/esm/index.mjs",
@@ -74,7 +74,7 @@
74
74
  "license": "ISC",
75
75
  "dependencies": {
76
76
  "@modelcontextprotocol/sdk": "^1.25.3",
77
- "brave-real-puppeteer-core": "^24.37.1-brave.11",
77
+ "brave-real-puppeteer-core": "^24.37.2-brave.2",
78
78
  "ghost-cursor": "^1.4.2",
79
79
  "puppeteer-extra": "^3.3.6",
80
80
  "puppeteer-extra-plugin-stealth": "^2.11.2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-blocker",
3
- "version": "1.17.12",
3
+ "version": "1.17.14",
4
4
  "description": "Advanced uBlock Origin management and stealth features for Brave Real Browser",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -64,7 +64,7 @@
64
64
  "@types/adm-zip": "^0.5.5",
65
65
  "@types/fs-extra": "^11.0.4",
66
66
  "@types/node": "^20.0.0",
67
- "brave-real-puppeteer-core": "^24.37.1-brave.11",
67
+ "brave-real-puppeteer-core": "^24.37.2-brave.2",
68
68
  "mocha": "^10.4.0",
69
69
  "puppeteer-core": ">=24.0.0",
70
70
  "sinon": "^17.0.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-launcher",
3
- "version": "1.23.12",
3
+ "version": "1.23.14",
4
4
  "description": "Launch Brave Browser with ease from node. Based on chrome-launcher with Brave-specific support.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -54,7 +54,7 @@
54
54
  "typescript": "^5.0.0"
55
55
  },
56
56
  "dependencies": {
57
- "brave-real-blocker": "^1.17.12",
57
+ "brave-real-blocker": "^1.17.14",
58
58
  "escape-string-regexp": "^5.0.0",
59
59
  "is-wsl": "^3.1.0",
60
60
  "which": "^6.0.0"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-playwright-core",
3
- "version": "1.59.12",
3
+ "version": "1.59.14",
4
4
  "description": "Brave-optimized Playwright Core (v1.57.0) with comprehensive stealth patches and error stack sanitization",
5
5
  "keywords": [
6
6
  "playwright",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-puppeteer-core",
3
- "version": "24.37.1-brave.11",
3
+ "version": "24.37.2-brave.2",
4
4
  "description": "🦁 Brave Real-World Optimized Puppeteer & Playwright Core with 1-5ms ultra-fast timing, 50+ professional stealth features, intelligent browser auto-detection, and 100% bot detection bypass. Features cross-platform Brave browser integration, comprehensive anti-detection, and breakthrough performance improvements.",
5
5
  "keywords": [
6
6
  "automation",
@@ -134,13 +134,20 @@
134
134
  "test-version": "node ./scripts/test-version-management.js"
135
135
  },
136
136
  "dependencies": {
137
- "brave-real-launcher": "^1.23.12",
137
+ "@puppeteer/browsers": "2.12.0",
138
+ "brave-real-launcher": "^1.23.14",
139
+ "chromium-bidi": "13.1.1",
140
+ "debug": "^4.4.3",
141
+ "devtools-protocol": "0.0.1566079",
138
142
  "get-east-asian-width": "^1.4.0",
143
+ "typed-query-selector": "^2.12.0",
144
+ "webdriver-bidi-protocol": "0.4.0",
145
+ "ws": "^8.19.0",
139
146
  "yargs": "^18.0.0"
140
147
  },
141
148
  "optionalDependencies": {
142
- "playwright-core": "^1.58.1",
143
- "puppeteer-core": "^24.37.1"
149
+ "playwright-core": "^1.58.2",
150
+ "puppeteer-core": "^24.37.2"
144
151
  },
145
152
  "devDependencies": {
146
153
  "test": "^3.3.0"
@@ -148,7 +155,7 @@
148
155
  "brave": {
149
156
  "optimized": true,
150
157
  "basedOn": {
151
- "puppeteer-core": "24.36.1"
158
+ "puppeteer-core": "24.37.2"
152
159
  },
153
160
  "features": [
154
161
  "stealth-injection",
@@ -157,6 +164,7 @@
157
164
  "fingerprint-spoofing",
158
165
  "ultra-fast-timing"
159
166
  ],
160
- "versionScheme": "upstream-aligned"
167
+ "versionScheme": "upstream-aligned",
168
+ "patchedVersion": "24.37.2-brave.1"
161
169
  }
162
170
  }
@@ -240,6 +240,67 @@ const decoders = {
240
240
  * Tool Handlers Object
241
241
  */
242
242
  const handlers = {
243
+ // ═══════════════════════════════════════════════════════════════
244
+ // HELPER: Auto-Close Blocking Modals/Popups
245
+ // ═══════════════════════════════════════════════════════════════
246
+ async _handleBlockingModals(page) {
247
+ try {
248
+ const closed = await page.evaluate(() => {
249
+ // Selectors for common modal close buttons
250
+ const closeSelectors = [
251
+ // Bootstrap/Standard Modals
252
+ '.modal.show .btn-close',
253
+ '.modal.show .close',
254
+ '.modal.in .close',
255
+ '.modal-footer .btn-primary', // "OK" button usually
256
+ '.modal-footer .btn-secondary', // "Close" button
257
+ // Custom Overlays
258
+ '#modal-close',
259
+ '.popup-close',
260
+ '.overlay-close',
261
+ // Generic "X" buttons in overlays
262
+ 'div[role="dialog"] button[aria-label="Close"]',
263
+ 'div[role="dialog"] .close',
264
+ // SweetAlert / specific libraries
265
+ '.swal2-confirm',
266
+ '.swal2-cancel',
267
+ '.ui-dialog-titlebar-close',
268
+ // eCourts specific if known (generic fallback)
269
+ '.modal-header .close',
270
+ 'button[data-dismiss="modal"]'
271
+ ];
272
+
273
+ let clicked = false;
274
+ // Check if any modal is visible (display block/flex and opacity > 0)
275
+ const modals = document.querySelectorAll('.modal, .popup, .overlay, .dialog, [role="dialog"]');
276
+ for (const modal of modals) {
277
+ const style = window.getComputedStyle(modal);
278
+ if (style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0') {
279
+ // Modal is visible, find a close button inside
280
+ for (const selector of closeSelectors) {
281
+ const btn = modal.querySelector(selector);
282
+ if (btn && btn.offsetParent !== null) { // Visible button
283
+ btn.click();
284
+ clicked = true;
285
+ break; // Clicked one, break inner loop
286
+ }
287
+ }
288
+ if (clicked) break; // Handled one modal, break outer loop
289
+ }
290
+ }
291
+ return clicked;
292
+ });
293
+
294
+ if (closed) {
295
+ // notifyProgress('helper', 'progress', '🧹 Auto-closed a blocking modal/popup');
296
+ await new Promise(r => setTimeout(r, 500)); // Wait for animation
297
+ }
298
+ return closed;
299
+ } catch (e) {
300
+ return false;
301
+ }
302
+ },
303
+
243
304
  // ═══════════════════════════════════════════════════════════════
244
305
  // HELPER: Full Page Analyzer - Detect ALL inputs on page
245
306
  // ═══════════════════════════════════════════════════════════════
@@ -305,7 +366,7 @@ const handlers = {
305
366
  const unfilledFields = [];
306
367
 
307
368
  // First, analyze the full page
308
- const pageInfo = await this._analyzeFullPage(page);
369
+ const pageInfo = await handlers._analyzeFullPage(page);
309
370
  notifyProgress('solve_captcha', 'progress', `🔍 Page analyzed: ${pageInfo.totalInputs} inputs found`);
310
371
 
311
372
  for (const [field, value] of Object.entries(formData || {})) {
@@ -504,25 +565,63 @@ const handlers = {
504
565
  blockerInstance = result.blocker;
505
566
 
506
567
  // ═══════════════════════════════════════════════════════════════
507
- // GLOBAL DIALOG HANDLER - Auto-accept all dialogs (alerts/confirms/prompts)
508
- // This prevents browser from getting stuck on JavaScript dialogs
568
+ // GLOBAL DIALOG HANDLER - Auto-handle dialogs
569
+ // Logic: BLOCK redirects to external sites, ACCEPT everything else
509
570
  // ═══════════════════════════════════════════════════════════════
510
571
  pageInstance.on('dialog', async (dialog) => {
511
572
  const dialogType = dialog.type();
512
- const dialogMessage = dialog.message();
573
+ const msg = dialog.message().toLowerCase();
513
574
 
514
575
  notifyProgress('browser_init', 'progress',
515
- `🔔 Auto-accepting ${dialogType}: ${dialogMessage.substring(0, 100)}...`);
576
+ `🔔 Handling dialog: ${dialogType} - ${dialog.message().substring(0, 100)}...`);
516
577
 
517
578
  try {
518
- await dialog.accept();
519
- notifyProgress('browser_init', 'progress', `✅ Dialog accepted: ${dialogType}`);
579
+ // Critical Fix: BLOCK redirects to external sites (e.g., eCommittee)
580
+ // These redirects take the user away from the search page
581
+ if (msg.includes('redirect') || msg.includes('external') || msg.includes('leaving')) {
582
+ console.log('🚫 Blocking redirect dialog (Dismiss)');
583
+ await dialog.dismiss(); // Simulate clicking 'Cancel'
584
+ } else {
585
+ // Auto-accept other dialogs (like alerts or simple confirmations)
586
+ await dialog.accept(); // Simulate clicking 'OK'
587
+ }
520
588
  } catch (e) {
521
- // Dialog might already be handled
522
- console.error(`Dialog handling error: ${e.message}`);
589
+ // Ignore errors (dialog might be closed by injected script)
523
590
  }
524
591
  });
525
592
 
593
+ // ═══════════════════════════════════════════════════════════════
594
+ // INJECTED SCRIPT - Silent Handling of Popups
595
+ // Override window.confirm/alert to handle them inside the page context
596
+ // Note: Using evaluateOnNewDocument (Puppeteer) instead of addInitScript (Playwright)
597
+ // ═══════════════════════════════════════════════════════════════
598
+ await pageInstance.evaluateOnNewDocument(() => {
599
+ window.originalConfirm = window.confirm;
600
+ window.originalAlert = window.alert;
601
+
602
+ // Smart Confirm Handler
603
+ window.confirm = (msg) => {
604
+ console.log('Intercepted Confirm Dialog:', msg);
605
+ if (msg && (msg.toLowerCase().includes('redirect') || msg.toLowerCase().includes('external'))) {
606
+ console.log('🚫 Blocking redirect confirmation inside page');
607
+ return false; // Return FALSE = Click Cancel
608
+ }
609
+ return true; // Return TRUE = Click OK
610
+ };
611
+
612
+ // Silently ignore alerts (always OK)
613
+ window.alert = (msg) => {
614
+ console.log('Blocked Alert Dialog:', msg);
615
+ return true;
616
+ };
617
+
618
+ // Silently return null for prompts
619
+ window.prompt = (msg) => {
620
+ console.log('Blocked Prompt Dialog:', msg);
621
+ return null;
622
+ };
623
+ });
624
+
526
625
  const pid = browserInstance.process()?.pid;
527
626
 
528
627
  notifyProgress('browser_init', 'completed', `Browser started (PID: ${pid})`, {
@@ -701,6 +800,9 @@ const handlers = {
701
800
 
702
801
  notifyProgress('click', 'started', `Clicking: ${selector}`);
703
802
 
803
+ // Auto-close any blocking modals before clicking
804
+ await handlers._handleBlockingModals(page);
805
+
704
806
  // Auto-handle dialogs (alerts, confirms, prompts) to prevent blocking
705
807
  let dialogHandled = false;
706
808
  const dialogHandler = async (dialog) => {
@@ -754,6 +856,9 @@ const handlers = {
754
856
 
755
857
  notifyProgress('type', 'started', `Typing ${text.length} characters into ${selector}`);
756
858
 
859
+ // Auto-close any blocking modals before typing
860
+ await handlers._handleBlockingModals(page);
861
+
757
862
  if (clear) {
758
863
  await page.click(selector, { clickCount: 3 });
759
864
  await page.keyboard.press('Backspace');
@@ -825,7 +930,7 @@ const handlers = {
825
930
  let formResult = null;
826
931
  if (formData && Object.keys(formData).length > 0) {
827
932
  notifyProgress('solve_captcha', 'started', `📋 Smart Form + Captcha Mode: Filling ${Object.keys(formData).length} fields...`);
828
- formResult = await this._fillFormFields(page, formData, formSelector, humanLike, aiMatch);
933
+ formResult = await handlers._fillFormFields(page, formData, formSelector, humanLike, aiMatch);
829
934
  } else {
830
935
  notifyProgress('solve_captcha', 'started', `🎯 100% Accuracy Mode: Solving ${type} captcha...`);
831
936
  }
@@ -1028,7 +1133,7 @@ const handlers = {
1028
1133
  // MERGED: Handle form submission if requested
1029
1134
  if (submit) {
1030
1135
  notifyProgress('solve_captcha', 'progress', '🚀 Submitting form...');
1031
- const submitResult = await this._submitForm(page);
1136
+ const submitResult = await handlers._submitForm(page);
1032
1137
  return {
1033
1138
  success: true,
1034
1139
  type: 'ocr',
@@ -1111,7 +1216,7 @@ const handlers = {
1111
1216
  // MERGED: Handle form submission if requested
1112
1217
  if (submit) {
1113
1218
  notifyProgress('solve_captcha', 'progress', '🚀 Submitting form...');
1114
- const submitResult = await this._submitForm(page);
1219
+ const submitResult = await handlers._submitForm(page);
1115
1220
  return {
1116
1221
  success: true,
1117
1222
  type: 'turnstile',
@@ -1141,7 +1246,7 @@ const handlers = {
1141
1246
  try {
1142
1247
  // Pre-submit validation
1143
1248
  if (validateFirst) {
1144
- const validation = await this._validateBeforeSubmit(page);
1249
+ const validation = await handlers._validateBeforeSubmit(page);
1145
1250
  if (!validation.valid) {
1146
1251
  notifyProgress('solve_captcha', 'warn', `⚠️ Validation failed: ${validation.errors.length} issue(s)`);
1147
1252
  return { success: false, message: 'Pre-submit validation failed', errors: validation.errors };
@@ -1187,7 +1292,7 @@ const handlers = {
1187
1292
  return { success: true, message: 'Form submitted and navigation complete', navigated: true };
1188
1293
  } catch (e) {
1189
1294
  // No navigation - check for errors on same page
1190
- const postErrors = await this._detectPostSubmitErrors(page);
1295
+ const postErrors = await handlers._detectPostSubmitErrors(page);
1191
1296
 
1192
1297
  if (postErrors.hasErrors) {
1193
1298
  notifyProgress('solve_captcha', 'warn', `⚠️ Submit detected errors: ${postErrors.errors[0]}`);