brave-real-browser-mcp-server 2.12.6 → 2.12.8

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/dist/index.js CHANGED
@@ -111,11 +111,8 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
111
111
  console.error("šŸ” [DEBUG] Prompts list requested");
112
112
  return { prompts: [] };
113
113
  });
114
- // Main tool call handler
115
- console.error("šŸ” [DEBUG] Registering tool call handler...");
116
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
117
- const { name, arguments: args } = request.params;
118
- console.error(`šŸ” [DEBUG] Tool call received: ${name} with args: ${JSON.stringify(args)}`);
114
+ // Tool execution function - exported for use in transports
115
+ export async function executeToolByName(name, args) {
119
116
  try {
120
117
  let result;
121
118
  switch (name) {
@@ -492,6 +489,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
492
489
  isError: true,
493
490
  };
494
491
  }
492
+ }
493
+ // Main tool call handler
494
+ console.error("šŸ” [DEBUG] Registering tool call handler...");
495
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
496
+ const { name, arguments: args } = request.params;
497
+ console.error(`šŸ” [DEBUG] Tool call received: ${name} with args: ${JSON.stringify(args)}`);
498
+ return await executeToolByName(name, args);
495
499
  });
496
500
  // Main function - now using multi-protocol launcher
497
501
  import { main as launcherMain } from "./launcher.js";
@@ -1,13 +1,13 @@
1
1
  import express from 'express';
2
2
  import { createServer } from 'http';
3
3
  import { WebSocketServer } from 'ws';
4
- import { TOOLS, TOOL_NAMES } from '../tool-definitions.js';
5
- // Import all handlers
4
+ import { TOOLS } from '../tool-definitions.js';
5
+ import { executeToolByName } from '../index.js';
6
+ // Import specific handlers for direct endpoints (for backward compatibility)
6
7
  import { handleBrowserInit, handleBrowserClose } from '../handlers/browser-handlers.js';
7
- import { handleNavigate, handleWait } from '../handlers/navigation-handlers.js';
8
- import { handleClick, handleType, handleSolveCaptcha, handleRandomScroll } from '../handlers/interaction-handlers.js';
9
- import { handleGetContent, handleFindSelector } from '../handlers/content-handlers.js';
10
- import { handleSaveContentAsMarkdown } from '../handlers/file-handlers.js';
8
+ import { handleNavigate } from '../handlers/navigation-handlers.js';
9
+ import { handleClick, handleType } from '../handlers/interaction-handlers.js';
10
+ import { handleGetContent } from '../handlers/content-handlers.js';
11
11
  export class HttpTransport {
12
12
  app;
13
13
  server = null;
@@ -128,32 +128,8 @@ export class HttpTransport {
128
128
  });
129
129
  }
130
130
  async executeTool(toolName, args) {
131
- switch (toolName) {
132
- case TOOL_NAMES.BROWSER_INIT:
133
- return await handleBrowserInit(args || {});
134
- case TOOL_NAMES.NAVIGATE:
135
- return await handleNavigate(args);
136
- case TOOL_NAMES.GET_CONTENT:
137
- return await handleGetContent(args || {});
138
- case TOOL_NAMES.CLICK:
139
- return await handleClick(args);
140
- case TOOL_NAMES.TYPE:
141
- return await handleType(args);
142
- case TOOL_NAMES.WAIT:
143
- return await handleWait(args);
144
- case TOOL_NAMES.BROWSER_CLOSE:
145
- return await handleBrowserClose();
146
- case TOOL_NAMES.SOLVE_CAPTCHA:
147
- return await handleSolveCaptcha(args);
148
- case TOOL_NAMES.RANDOM_SCROLL:
149
- return await handleRandomScroll();
150
- case TOOL_NAMES.FIND_SELECTOR:
151
- return await handleFindSelector(args);
152
- case TOOL_NAMES.SAVE_CONTENT_AS_MARKDOWN:
153
- return await handleSaveContentAsMarkdown(args);
154
- default:
155
- throw new Error(`Unknown tool: ${toolName}`);
156
- }
131
+ // Use universal tool executor from index.ts (supports all 110 tools)
132
+ return await executeToolByName(toolName, args);
157
133
  }
158
134
  setupWebSocket() {
159
135
  if (!this.server || !this.config.enableWebSocket)
@@ -1,12 +1,12 @@
1
1
  import express from 'express';
2
2
  import { createServer } from 'http';
3
- import { TOOLS, TOOL_NAMES } from '../tool-definitions.js';
4
- // Import all handlers
3
+ import { TOOLS } from '../tool-definitions.js';
4
+ import { executeToolByName } from '../index.js';
5
+ // Import specific handlers for direct endpoints (for backward compatibility)
5
6
  import { handleBrowserInit, handleBrowserClose } from '../handlers/browser-handlers.js';
6
- import { handleNavigate, handleWait } from '../handlers/navigation-handlers.js';
7
- import { handleClick, handleType, handleSolveCaptcha, handleRandomScroll } from '../handlers/interaction-handlers.js';
8
- import { handleGetContent, handleFindSelector } from '../handlers/content-handlers.js';
9
- import { handleSaveContentAsMarkdown } from '../handlers/file-handlers.js';
7
+ import { handleNavigate } from '../handlers/navigation-handlers.js';
8
+ import { handleClick, handleType } from '../handlers/interaction-handlers.js';
9
+ import { handleGetContent } from '../handlers/content-handlers.js';
10
10
  export class SseTransport {
11
11
  app;
12
12
  server = null;
@@ -207,32 +207,8 @@ export class SseTransport {
207
207
  });
208
208
  }
209
209
  async executeTool(toolName, args) {
210
- switch (toolName) {
211
- case TOOL_NAMES.BROWSER_INIT:
212
- return await handleBrowserInit(args || {});
213
- case TOOL_NAMES.NAVIGATE:
214
- return await handleNavigate(args);
215
- case TOOL_NAMES.GET_CONTENT:
216
- return await handleGetContent(args || {});
217
- case TOOL_NAMES.CLICK:
218
- return await handleClick(args);
219
- case TOOL_NAMES.TYPE:
220
- return await handleType(args);
221
- case TOOL_NAMES.WAIT:
222
- return await handleWait(args);
223
- case TOOL_NAMES.BROWSER_CLOSE:
224
- return await handleBrowserClose();
225
- case TOOL_NAMES.SOLVE_CAPTCHA:
226
- return await handleSolveCaptcha(args);
227
- case TOOL_NAMES.RANDOM_SCROLL:
228
- return await handleRandomScroll();
229
- case TOOL_NAMES.FIND_SELECTOR:
230
- return await handleFindSelector(args);
231
- case TOOL_NAMES.SAVE_CONTENT_AS_MARKDOWN:
232
- return await handleSaveContentAsMarkdown(args);
233
- default:
234
- throw new Error(`Unknown tool: ${toolName}`);
235
- }
210
+ // Use universal tool executor from index.ts (supports all 110 tools)
211
+ return await executeToolByName(toolName, args);
236
212
  }
237
213
  sendEvent(res, eventType, data) {
238
214
  const eventData = `event: ${eventType}\ndata: ${JSON.stringify(data)}\n\n`;
@@ -111,9 +111,11 @@ describe('SSE Transport', () => {
111
111
  body: JSON.stringify({}),
112
112
  });
113
113
  const data = await response.json();
114
- expect(response.status).toBe(500);
115
- expect(data.success).toBe(false);
116
- expect(data.error).toContain('Unknown tool');
114
+ // MCP format: errors are returned in content with isError flag
115
+ expect(response.status).toBe(200);
116
+ expect(data.success).toBe(true);
117
+ expect(data.result.isError).toBe(true);
118
+ expect(data.result.content[0].text).toContain('Unknown tool');
117
119
  });
118
120
  it('should validate tool arguments', async () => {
119
121
  const response = await fetch(`http://${TEST_HOST}:${TEST_PORT}/tools/navigate`, {
@@ -124,8 +126,10 @@ describe('SSE Transport', () => {
124
126
  body: JSON.stringify({ /* missing url */}),
125
127
  });
126
128
  const data = await response.json();
127
- expect(response.status).toBe(500);
128
- expect(data.success).toBe(false);
129
+ // MCP format: validation errors are returned with success=true but result.isError=true
130
+ expect(response.status).toBe(200);
131
+ expect(data.success).toBe(true);
132
+ expect(data.result.isError).toBe(true);
129
133
  });
130
134
  });
131
135
  describe('CORS Headers', () => {
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "brave-real-browser-mcp-server",
3
- "version": "2.12.6",
3
+ "version": "2.12.8",
4
4
  "description": "Universal AI IDE MCP Server - Auto-detects and supports all AI IDEs (Claude Desktop, Cursor, Windsurf, Cline, Zed, VSCode, Qoder AI, etc.) with Brave browser automation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "scripts": {
8
- "postinstall": "node scripts/update-to-latest.cjs || echo 'Auto-update skipped'",
8
+ "postinstall": "node scripts/patch-puppeteer-screen-recorder.cjs && node scripts/update-to-latest.cjs || echo 'Auto-update skipped'",
9
9
  "clean": "rimraf dist",
10
10
  "clean:cache": "npm cache clean --force",
11
11
  "fix-cache-permissions": "echo 'Run: sudo chown -R $(whoami):$(id -gn) ~/.npm' && echo 'This fixes npm cache permission issues'",
@@ -42,7 +42,7 @@
42
42
  "axios": "^1.6.5",
43
43
  "brave-real-browser": "^1.5.102",
44
44
  "brave-real-launcher": "^1.2.18",
45
- "brave-real-puppeteer-core": "^24.25.0",
45
+ "brave-real-puppeteer-core": "^24.26.1",
46
46
  "cheerio": "^1.0.0-rc.12",
47
47
  "chrono-node": "^2.7.0",
48
48
  "compromise": "^14.13.0",
@@ -53,10 +53,10 @@
53
53
  "natural": "^6.12.0",
54
54
  "pixelmatch": "^5.3.0",
55
55
  "pngjs": "^7.0.0",
56
- "puppeteer-screen-recorder": "^3.0.5",
56
+ "puppeteer-screen-recorder": "^3.0.6",
57
57
  "sentiment": "^5.0.2",
58
58
  "tesseract.js": "^5.0.5",
59
- "turndown": "^7.2.1",
59
+ "turndown": "^7.2.2",
60
60
  "vscode-languageserver": "^9.0.1",
61
61
  "vscode-languageserver-textdocument": "^1.0.12",
62
62
  "ws": "^8.18.3",
@@ -117,6 +117,8 @@
117
117
  },
118
118
  "files": [
119
119
  "dist/**/*",
120
+ "scripts/**/*",
121
+ ".npmrc",
120
122
  "README.md",
121
123
  "LICENSE"
122
124
  ],
@@ -132,7 +134,13 @@
132
134
  "overrides": {
133
135
  "puppeteer": "npm:brave-real-puppeteer-core@latest",
134
136
  "puppeteer-core": "npm:brave-real-puppeteer-core@latest",
135
- "tar-fs": "^3.0.0",
136
- "ws": "^8.18.3"
137
+ "puppeteer-screen-recorder": {
138
+ "puppeteer": "npm:brave-real-puppeteer-core@latest",
139
+ "fluent-ffmpeg": "latest"
140
+ },
141
+ "fluent-ffmpeg": "latest",
142
+ "glob": "latest",
143
+ "inflight": "latest",
144
+ "tar-fs": "latest"
137
145
  }
138
146
  }
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Patch script for puppeteer-screen-recorder
5
+ *
6
+ * This script patches the peerDependencies in puppeteer-screen-recorder's package.json
7
+ * to use brave-real-puppeteer-core instead of the old puppeteer@19.0.0
8
+ *
9
+ * Runs automatically after npm install via postinstall hook
10
+ */
11
+
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+
15
+ // Path to puppeteer-screen-recorder's package.json
16
+ const packagePath = path.join(
17
+ process.cwd(),
18
+ 'node_modules',
19
+ 'puppeteer-screen-recorder',
20
+ 'package.json'
21
+ );
22
+
23
+ // Skip if package doesn't exist
24
+ if (!fs.existsSync(packagePath)) {
25
+ console.log('ā„¹ļø puppeteer-screen-recorder not found, skipping patch');
26
+ process.exit(0);
27
+ }
28
+
29
+ try {
30
+ console.log('šŸ”§ Patching puppeteer-screen-recorder peerDependencies...');
31
+
32
+ // Read the package.json
33
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
34
+
35
+ // Check if patch is needed
36
+ if (packageJson.peerDependencies && packageJson.peerDependencies.puppeteer) {
37
+ const currentValue = packageJson.peerDependencies.puppeteer;
38
+
39
+ // Only patch if it's the old version
40
+ if (currentValue === '19.0.0' || !currentValue.includes('brave-real-puppeteer-core')) {
41
+ // Update to brave-real-puppeteer-core
42
+ packageJson.peerDependencies.puppeteer = 'npm:brave-real-puppeteer-core@>=24.0.0';
43
+
44
+ // Write back to file
45
+ fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2), 'utf8');
46
+
47
+ console.log(' āœ“ puppeteer-screen-recorder patched successfully');
48
+ console.log(' āœ“ peerDependencies.puppeteer: npm:brave-real-puppeteer-core@>=24.0.0');
49
+ } else {
50
+ console.log(' āœ“ puppeteer-screen-recorder already patched');
51
+ }
52
+ } else {
53
+ console.log(' āš ļø No puppeteer peerDependency found');
54
+ }
55
+
56
+ } catch (error) {
57
+ console.error('āš ļø Failed to patch puppeteer-screen-recorder:', error.message);
58
+ console.log('ā„¹ļø Continuing anyway...');
59
+ process.exit(0); // Don't fail the install
60
+ }
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Auto-update script for brave-real-browser-mcp-server
5
+ *
6
+ * This script automatically updates all dependencies to their latest versions
7
+ * when npm install is run. It ensures the project always uses the most recent
8
+ * compatible versions while maintaining all functionality.
9
+ *
10
+ * Features:
11
+ * - Updates brave-real-browser to latest
12
+ * - Updates @modelcontextprotocol/sdk to latest
13
+ * - Skips in CI environments to prevent infinite loops
14
+ * - Silent mode to avoid cluttering install output
15
+ */
16
+
17
+ const { execSync } = require('child_process');
18
+ const path = require('path');
19
+ const fs = require('fs');
20
+
21
+ // Skip in CI environments to prevent recursive installs
22
+ const isCIEnvironment = process.env.CI === 'true' ||
23
+ process.env.GITHUB_ACTIONS === 'true' ||
24
+ process.env.SKIP_AUTO_UPDATE === 'true';
25
+
26
+ if (isCIEnvironment) {
27
+ console.log('ā„¹ļø Auto-update skipped in CI environment');
28
+ process.exit(0);
29
+ }
30
+
31
+ // Check if we're in the root of the package
32
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
33
+ if (!fs.existsSync(packageJsonPath)) {
34
+ console.log('ā„¹ļø Not in package root, skipping auto-update');
35
+ process.exit(0);
36
+ }
37
+
38
+ console.log('\nšŸ”„ Auto-updating dependencies to latest versions...\n');
39
+
40
+ // List of packages to always keep at latest version
41
+ const packagesToUpdate = [
42
+ 'brave-real-browser',
43
+ 'brave-real-launcher',
44
+ 'brave-real-puppeteer-core',
45
+ '@modelcontextprotocol/sdk',
46
+ 'turndown',
47
+ '@types/turndown',
48
+ 'puppeteer-screen-recorder',
49
+ 'rimraf'
50
+ ];
51
+
52
+ try {
53
+ // Update each package to latest
54
+ for (const pkg of packagesToUpdate) {
55
+ try {
56
+ console.log(` Updating ${pkg}...`);
57
+ execSync(`npm install ${pkg}@latest --save --no-audit --no-fund`, {
58
+ stdio: 'pipe',
59
+ cwd: process.cwd()
60
+ });
61
+ console.log(` āœ“ ${pkg} updated to latest`);
62
+ } catch (error) {
63
+ console.log(` āš ļø Could not update ${pkg} (non-critical)`);
64
+ }
65
+ }
66
+
67
+ console.log('\nāœ… All dependencies updated to latest versions!\n');
68
+
69
+ // Show current versions
70
+ console.log('šŸ“¦ Current versions:');
71
+ for (const pkg of packagesToUpdate) {
72
+ try {
73
+ const version = execSync(`npm list ${pkg} --depth=0 --json`, {
74
+ stdio: 'pipe',
75
+ encoding: 'utf8'
76
+ });
77
+ const parsed = JSON.parse(version);
78
+ const installedVersion = parsed.dependencies?.[pkg]?.version || 'not found';
79
+ console.log(` ${pkg}: ${installedVersion}`);
80
+ } catch (error) {
81
+ // Ignore errors
82
+ }
83
+ }
84
+
85
+ // Step 4: Run npm audit fix to resolve security vulnerabilities
86
+ console.log('\nšŸ”’ Running security audit fix...');
87
+ try {
88
+ execSync('npm audit fix --force', {
89
+ stdio: 'pipe',
90
+ cwd: process.cwd()
91
+ });
92
+ console.log(' āœ“ Security vulnerabilities fixed');
93
+ } catch (error) {
94
+ // Check if there are still vulnerabilities
95
+ try {
96
+ const auditResult = execSync('npm audit --json', {
97
+ stdio: 'pipe',
98
+ encoding: 'utf8'
99
+ });
100
+ const audit = JSON.parse(auditResult);
101
+ if (audit.metadata && audit.metadata.vulnerabilities) {
102
+ const total = audit.metadata.vulnerabilities.total || 0;
103
+ if (total === 0) {
104
+ console.log(' āœ“ No security vulnerabilities found');
105
+ } else {
106
+ console.log(` āš ļø ${total} vulnerabilities remaining (may require manual review)`);
107
+ }
108
+ }
109
+ } catch (auditError) {
110
+ console.log(' ā„¹ļø Security audit completed');
111
+ }
112
+ }
113
+
114
+ console.log('');
115
+
116
+ } catch (error) {
117
+ console.error('āš ļø Auto-update encountered an error:', error.message);
118
+ console.log('ā„¹ļø Continuing with current versions...\n');
119
+ process.exit(0); // Don't fail the install
120
+ }