brave-real-browser-mcp-server 2.23.8 → 2.23.9

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.
@@ -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.23.9",
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.4.9",
54
54
  "turndown": "latest",
55
55
  "vscode-languageserver": "^9.0.1",
56
56
  "vscode-languageserver-textdocument": "^1.0.12"