brave-real-browser-mcp-server 2.23.8 → 2.24.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/README.md CHANGED
@@ -90,6 +90,31 @@ npm run dev
90
90
 
91
91
  ---
92
92
 
93
+ ## šŸ›”ļø Ad Blocking & Stealth (brave-real-blocker)
94
+
95
+ **Auto-enabled on all pages via ecosystem chain:**
96
+
97
+ ```
98
+ brave-real-launcher
99
+ └── brave-real-puppeteer-core
100
+ └── brave-real-browser
101
+ └── brave-real-blocker (auto-enabled)
102
+ └── brave-real-browser-mcp-server
103
+ ```
104
+
105
+ | Feature | Description |
106
+ |---------|-------------|
107
+ | **AdBlocking** | Network-level ad/tracker blocking |
108
+ | **Stealth** | Native function masking (prompt, alert, confirm) |
109
+ | **RedirectBlocking** | Popup, window.open interception, tracking param removal |
110
+ | **ScriptletInjection** | Anti-adblock bypass |
111
+ | **CosmeticFiltering** | Element hiding |
112
+
113
+ > ā„¹ļø No configuration needed - blocker activates automatically on browser launch.
114
+
115
+ ---
116
+
117
+
93
118
  ## šŸ› ļø All 33 MCP Tools
94
119
 
95
120
  ### Browser Management
@@ -297,31 +297,16 @@ export async function initializeBrowser(options) {
297
297
  else {
298
298
  // console.(' Mode: GUI (visible browser)');
299
299
  }
300
- // Brave-real-browser handles everything automatically
301
- // Enable uBlock Origin for ad/popup blocking
302
- // Add adblocker plugin for additional protection
303
- // Dynamically import adblocker plugin
304
- let adblockerPlugin = null;
305
- try {
306
- const adblockerModule = await import('puppeteer-extra-plugin-adblocker');
307
- const AdblockerPlugin = (adblockerModule.default || adblockerModule);
308
- if (typeof AdblockerPlugin === 'function') {
309
- adblockerPlugin = AdblockerPlugin({
310
- blockTrackers: true,
311
- blockTrackersAndAnnoyances: true,
312
- });
313
- }
314
- }
315
- catch (e) {
316
- // Adblocker plugin not available, continue without it
317
- }
300
+ // Note: brave-real-blocker is automatically loaded by brave-real-browser
301
+ // It provides: AdBlocking, Stealth, RedirectBlocking, Scriptlets, CosmeticFiltering
302
+ // No need for additional puppeteer-extra-plugin-adblocker
318
303
  const connectOptions = {
319
304
  headless: headlessMode,
320
305
  turnstile: true,
321
306
  connectOption: {
322
307
  defaultViewport: null // Full window content, no viewport restriction
323
308
  },
324
- plugins: adblockerPlugin ? [adblockerPlugin] : [], // Add adblocker plugin
309
+ plugins: [], // brave-real-blocker handles ad blocking internally
325
310
  customConfig: {
326
311
  autoLoadUBlock: true, // Enable uBlock Origin in brave-real-launcher
327
312
  },
@@ -44,15 +44,31 @@ export async function handleClick(args) {
44
44
  strategyMessage = `\nšŸ”„ Self-healing: Used ${strategy} fallback selector: ${usedSelector}`;
45
45
  tracker.setProgress(50, `šŸ”„ Using fallback selector: ${usedSelector}`);
46
46
  }
47
+ // Text-based strategies have special __TEXT__: prefix or are strategy-identified
48
+ // These have invalid CSS selectors, so we skip waitForSelector and use element directly
49
+ const isTextBasedStrategy = ['text-content', 'implicit-text-match', 'text', 'text-exact', 'text-partial', 'tag-text'].includes(strategy) ||
50
+ usedSelector.startsWith('__TEXT__:');
51
+ // Clean display selector for output (remove __TEXT__: prefix)
52
+ const displaySelector = usedSelector.startsWith('__TEXT__:')
53
+ ? usedSelector.replace('__TEXT__:', 'text:')
54
+ : usedSelector;
47
55
  try {
48
56
  tracker.setProgress(60, 'ā³ Waiting for element to be ready...');
49
- // Wait for element to be ready
50
- await pageInstance.waitForSelector(usedSelector, { timeout: 5000 });
57
+ // Only wait for selector if it's a valid CSS selector (not text-based)
58
+ if (!isTextBasedStrategy) {
59
+ await pageInstance.waitForSelector(usedSelector, { timeout: 5000 });
60
+ }
51
61
  // Check element visibility and interaction options
52
62
  const boundingBox = await element.boundingBox();
53
63
  if (!boundingBox) {
54
64
  tracker.setProgress(70, 'šŸ”§ No bounding box, using JavaScript click...');
55
- await pageInstance.$eval(usedSelector, (el) => el.click());
65
+ // For text-based strategies, use element.evaluate to click
66
+ if (isTextBasedStrategy) {
67
+ await element.evaluate((el) => el.click());
68
+ }
69
+ else {
70
+ await pageInstance.$eval(usedSelector, (el) => el.click());
71
+ }
56
72
  }
57
73
  else {
58
74
  tracker.setProgress(70, 'šŸ–±ļø Clicking element...');
@@ -60,12 +76,13 @@ export async function handleClick(args) {
60
76
  tracker.setProgress(75, 'šŸ”„ Clicking and waiting for navigation...');
61
77
  await Promise.all([
62
78
  pageInstance.waitForNavigation({ waitUntil: 'networkidle2' }),
63
- pageInstance.click(usedSelector),
79
+ element.click(), // Use element.click() for all strategies
64
80
  ]);
65
81
  tracker.setProgress(90, 'āœ… Navigation completed');
66
82
  }
67
83
  else {
68
- await pageInstance.click(usedSelector);
84
+ // Use element.click() directly - works for all strategies
85
+ await element.click();
69
86
  }
70
87
  }
71
88
  tracker.complete('šŸŽ‰ Click completed successfully');
@@ -82,7 +99,13 @@ export async function handleClick(args) {
82
99
  tracker.setProgress(85, 'āš ļø Click failed, trying JavaScript fallback...');
83
100
  // Final fallback: JavaScript click
84
101
  try {
85
- await pageInstance.$eval(usedSelector, (el) => el.click());
102
+ // For text-based strategies, use element.evaluate instead of $eval
103
+ if (isTextBasedStrategy) {
104
+ await element.evaluate((el) => el.click());
105
+ }
106
+ else {
107
+ await pageInstance.$eval(usedSelector, (el) => el.click());
108
+ }
86
109
  tracker.complete('šŸŽ‰ Click completed via JavaScript fallback');
87
110
  return {
88
111
  content: [
@@ -145,7 +145,7 @@ export class SelfHealingLocators {
145
145
  if (element) {
146
146
  return {
147
147
  element,
148
- usedSelector: `${textSelector.tagName || '*'}[text*="${textSelector.text}"]`,
148
+ usedSelector: `__TEXT__:${textSelector.tagName || '*'}:${textSelector.text}`,
149
149
  strategy: 'text-content'
150
150
  };
151
151
  }
@@ -171,7 +171,7 @@ export class SelfHealingLocators {
171
171
  if (textElement) {
172
172
  return {
173
173
  element: textElement,
174
- usedSelector: `//*[text()[contains(., "${primarySelector}")]]`,
174
+ usedSelector: `__TEXT__:*:${primarySelector}`,
175
175
  strategy: 'implicit-text-match'
176
176
  };
177
177
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-browser-mcp-server",
3
- "version": "2.23.8",
3
+ "version": "2.24.0",
4
4
  "description": "🦁 MCP server for Brave Real Browser - NPM Workspaces Monorepo with anti-detection features, SSE streaming, and LSP compatibility",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -50,7 +50,7 @@
50
50
  "dependencies": {
51
51
  "@modelcontextprotocol/sdk": "latest",
52
52
  "@types/turndown": "latest",
53
- "brave-real-browser": "^2.4.8",
53
+ "brave-real-browser": "^2.5.0",
54
54
  "turndown": "latest",
55
55
  "vscode-languageserver": "^9.0.1",
56
56
  "vscode-languageserver-textdocument": "^1.0.12"