brave-real-browser-mcp-server 2.14.4 → 2.14.5
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 +8 -535
- package/dist/index.js +18 -51
- package/package.json +4 -15
- package/dist/launcher.js +0 -266
- package/dist/transports/http-transport.js +0 -198
- package/dist/transports/lsp-transport.js +0 -165
- package/dist/transports/sse-transport.js +0 -312
- package/dist/transports/sse-transport.test.js +0 -244
package/dist/index.js
CHANGED
|
@@ -498,29 +498,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
498
498
|
return await executeToolByName(name, args);
|
|
499
499
|
});
|
|
500
500
|
// Main function - now using multi-protocol launcher
|
|
501
|
-
|
|
501
|
+
// Main function
|
|
502
502
|
async function main() {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
console.error("
|
|
512
|
-
console.error("
|
|
513
|
-
|
|
514
|
-
await closeBrowser();
|
|
515
|
-
await forceKillAllBraveProcesses();
|
|
516
|
-
});
|
|
517
|
-
const transport = new StdioServerTransport();
|
|
518
|
-
await withErrorHandling(async () => {
|
|
519
|
-
await server.connect(transport);
|
|
520
|
-
console.error("🚀 Brave Real Browser MCP Server started successfully");
|
|
521
|
-
console.error("📋 Available tools:", TOOLS.map((t) => t.name).join(", "));
|
|
522
|
-
}, "Failed to start MCP server");
|
|
523
|
-
}
|
|
503
|
+
console.error("🔍 [DEBUG] Starting in STDIO mode...");
|
|
504
|
+
setupProcessCleanup(async () => {
|
|
505
|
+
await closeBrowser();
|
|
506
|
+
await forceKillAllBraveProcesses();
|
|
507
|
+
});
|
|
508
|
+
const transport = new StdioServerTransport();
|
|
509
|
+
await withErrorHandling(async () => {
|
|
510
|
+
await server.connect(transport);
|
|
511
|
+
console.error("🚀 Brave Real Browser MCP Server started successfully");
|
|
512
|
+
console.error("📋 Available tools:", TOOLS.map((t) => t.name).join(", "));
|
|
513
|
+
}, "Failed to start MCP server");
|
|
524
514
|
}
|
|
525
515
|
// Enhanced error handling with debug info
|
|
526
516
|
console.error("🔍 [DEBUG] Setting up error handlers...");
|
|
@@ -551,32 +541,9 @@ process.on("SIGINT", () => {
|
|
|
551
541
|
});
|
|
552
542
|
console.error("🔍 [DEBUG] All error handlers registered");
|
|
553
543
|
// Start the server
|
|
554
|
-
|
|
555
|
-
console.error(`🔍 [DEBUG]
|
|
556
|
-
console.error(
|
|
557
|
-
console.error(`🔍 [DEBUG]
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
process.argv[1].includes("brave-real-browser-mcp-server") ||
|
|
561
|
-
process.argv[1].endsWith(".bin/brave-real-browser-mcp-server") ||
|
|
562
|
-
process.argv.some((arg) => arg.includes("brave-real-browser-mcp-server"));
|
|
563
|
-
console.error(`🔍 [DEBUG] Enhanced main detection result: ${isMain}`);
|
|
564
|
-
if (isMain) {
|
|
565
|
-
console.error("🔍 [DEBUG] Module is main - starting server...");
|
|
566
|
-
main().catch((error) => {
|
|
567
|
-
console.error(`🔍 [DEBUG] Main function failed at ${new Date().toISOString()}`);
|
|
568
|
-
console.error("❌ Failed to start server:", error);
|
|
569
|
-
console.error(`🔍 [DEBUG] Error stack:`, error.stack);
|
|
570
|
-
process.exit(1);
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
else {
|
|
574
|
-
console.error("🔍 [DEBUG] Module is not main - not starting server");
|
|
575
|
-
console.error("🔍 [DEBUG] FORCE STARTING - This is likely an npx execution");
|
|
576
|
-
main().catch((error) => {
|
|
577
|
-
console.error(`🔍 [DEBUG] Forced main function failed at ${new Date().toISOString()}`);
|
|
578
|
-
console.error("❌ Failed to start server:", error);
|
|
579
|
-
console.error(`🔍 [DEBUG] Error stack:`, error.stack);
|
|
580
|
-
process.exit(1);
|
|
581
|
-
});
|
|
582
|
-
}
|
|
544
|
+
main().catch((error) => {
|
|
545
|
+
console.error(`🔍 [DEBUG] Main function failed at ${new Date().toISOString()}`);
|
|
546
|
+
console.error("❌ Failed to start server:", error);
|
|
547
|
+
console.error(`🔍 [DEBUG] Error stack:`, error.stack);
|
|
548
|
+
process.exit(1);
|
|
549
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-browser-mcp-server",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.5",
|
|
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",
|
|
@@ -19,12 +19,7 @@
|
|
|
19
19
|
"build": "tsc",
|
|
20
20
|
"rebuild": "npm run clean && npm run build",
|
|
21
21
|
"start": "node dist/index.js",
|
|
22
|
-
"start:http": "node dist/index.js --mode http",
|
|
23
|
-
"start:lsp": "node dist/index.js --mode lsp",
|
|
24
|
-
"start:all": "node dist/index.js --mode all",
|
|
25
22
|
"dev": "tsx src/index.ts",
|
|
26
|
-
"dev:http": "tsx src/index.ts --mode http",
|
|
27
|
-
"dev:lsp": "tsx src/index.ts --mode lsp",
|
|
28
23
|
"test": "vitest",
|
|
29
24
|
"test:watch": "vitest --watch",
|
|
30
25
|
"test:ui": "vitest --ui",
|
|
@@ -44,13 +39,12 @@
|
|
|
44
39
|
"ajv": "^8.12.0",
|
|
45
40
|
"axios": "^1.6.5",
|
|
46
41
|
"brave-real-browser": "^1.5.105",
|
|
47
|
-
"brave-real-launcher": "^1.2.
|
|
48
|
-
"brave-real-puppeteer-core": "^24.
|
|
42
|
+
"brave-real-launcher": "^1.2.28",
|
|
43
|
+
"brave-real-puppeteer-core": "^24.33.0-patch.1",
|
|
49
44
|
"cheerio": "^1.0.0-rc.12",
|
|
50
45
|
"chrono-node": "^2.7.0",
|
|
51
46
|
"compromise": "^14.13.0",
|
|
52
47
|
"dotenv": "^17.2.3",
|
|
53
|
-
"express": "^4.21.2",
|
|
54
48
|
"franc": "^6.2.0",
|
|
55
49
|
"libphonenumber-js": "^1.10.51",
|
|
56
50
|
"natural": "^6.12.0",
|
|
@@ -60,20 +54,15 @@
|
|
|
60
54
|
"sentiment": "^5.0.2",
|
|
61
55
|
"tesseract.js": "^5.0.5",
|
|
62
56
|
"turndown": "^7.2.2",
|
|
63
|
-
"vscode-languageserver": "^9.0.1",
|
|
64
|
-
"vscode-languageserver-textdocument": "^1.0.12",
|
|
65
|
-
"ws": "^8.18.3",
|
|
66
57
|
"xml2js": "^0.6.2"
|
|
67
58
|
},
|
|
68
59
|
"devDependencies": {
|
|
69
60
|
"@types/cheerio": "^0.22.35",
|
|
70
|
-
"@types/express": "^4.17.23",
|
|
71
61
|
"@types/node": "latest",
|
|
72
|
-
"@types/ws": "^8.18.1",
|
|
73
62
|
"@types/xml2js": "^0.4.14",
|
|
74
63
|
"@vitest/coverage-v8": "^3.2.4",
|
|
75
64
|
"@vitest/ui": "^3.2.4",
|
|
76
|
-
"rimraf": "^6.
|
|
65
|
+
"rimraf": "^6.1.2",
|
|
77
66
|
"tsx": "latest",
|
|
78
67
|
"typescript": "^5.5.3",
|
|
79
68
|
"vitest": "^3.2.4"
|
package/dist/launcher.js
DELETED
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
-
import { HttpTransport } from "./transports/http-transport.js";
|
|
4
|
-
import { LspTransport } from "./transports/lsp-transport.js";
|
|
5
|
-
import { SseTransport } from "./transports/sse-transport.js";
|
|
6
|
-
import { closeBrowser, forceKillAllBraveProcesses } from "./browser-manager.js";
|
|
7
|
-
import { setupProcessCleanup } from "./core-infrastructure.js";
|
|
8
|
-
import { UniversalIDEAdapter, ProtocolType, } from "./universal-ide-adapter.js";
|
|
9
|
-
export class MultiProtocolLauncher {
|
|
10
|
-
config;
|
|
11
|
-
httpTransport;
|
|
12
|
-
lspTransport;
|
|
13
|
-
sseTransport;
|
|
14
|
-
mcpServer;
|
|
15
|
-
universalAdapter;
|
|
16
|
-
constructor(config = {}) {
|
|
17
|
-
this.config = {
|
|
18
|
-
mode: config.mode || "auto",
|
|
19
|
-
httpPort: config.httpPort || 3000,
|
|
20
|
-
httpHost: config.httpHost || "0.0.0.0",
|
|
21
|
-
ssePort: config.ssePort || 3001,
|
|
22
|
-
sseHost: config.sseHost || "0.0.0.0",
|
|
23
|
-
enableWebSocket: config.enableWebSocket !== false,
|
|
24
|
-
enableCors: config.enableCors !== false,
|
|
25
|
-
enableAutoDetection: config.enableAutoDetection !== false,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
async start() {
|
|
29
|
-
console.error("🚀 Multi-Protocol Brave Browser Server Starting...");
|
|
30
|
-
console.error(`📡 Mode: ${this.config.mode.toUpperCase()}`);
|
|
31
|
-
// Initialize Universal IDE Adapter if auto-detection is enabled
|
|
32
|
-
if (this.config.enableAutoDetection && this.config.mode === "auto") {
|
|
33
|
-
console.error("🔍 Initializing Universal IDE Adapter...");
|
|
34
|
-
this.universalAdapter = new UniversalIDEAdapter({
|
|
35
|
-
enableAutoDetection: true,
|
|
36
|
-
fallbackToHttp: true,
|
|
37
|
-
httpPort: this.config.httpPort,
|
|
38
|
-
logDetectionDetails: true,
|
|
39
|
-
});
|
|
40
|
-
const detectionResult = await this.universalAdapter.initialize();
|
|
41
|
-
// Override mode based on detection
|
|
42
|
-
if (detectionResult.protocol === ProtocolType.MCP ||
|
|
43
|
-
detectionResult.protocol === ProtocolType.STDIO) {
|
|
44
|
-
this.config.mode = "mcp";
|
|
45
|
-
}
|
|
46
|
-
else if (detectionResult.protocol === ProtocolType.LSP) {
|
|
47
|
-
this.config.mode = "lsp";
|
|
48
|
-
}
|
|
49
|
-
else if (detectionResult.protocol === ProtocolType.HTTP ||
|
|
50
|
-
detectionResult.protocol === ProtocolType.WEBSOCKET) {
|
|
51
|
-
this.config.mode = "http";
|
|
52
|
-
}
|
|
53
|
-
console.error(`✅ Auto-detected mode: ${this.config.mode.toUpperCase()}`);
|
|
54
|
-
}
|
|
55
|
-
// Setup cleanup handlers
|
|
56
|
-
setupProcessCleanup(async () => {
|
|
57
|
-
await this.stop();
|
|
58
|
-
});
|
|
59
|
-
switch (this.config.mode) {
|
|
60
|
-
case "auto":
|
|
61
|
-
// Fallback to MCP if auto-detection didn't override
|
|
62
|
-
await this.startMcp();
|
|
63
|
-
break;
|
|
64
|
-
case "mcp":
|
|
65
|
-
await this.startMcp();
|
|
66
|
-
break;
|
|
67
|
-
case "http":
|
|
68
|
-
await this.startHttp();
|
|
69
|
-
break;
|
|
70
|
-
case "lsp":
|
|
71
|
-
await this.startLsp();
|
|
72
|
-
break;
|
|
73
|
-
case "sse":
|
|
74
|
-
await this.startSse();
|
|
75
|
-
break;
|
|
76
|
-
case "all":
|
|
77
|
-
await this.startAll();
|
|
78
|
-
break;
|
|
79
|
-
default:
|
|
80
|
-
throw new Error(`Unknown mode: ${this.config.mode}`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
async startMcp() {
|
|
84
|
-
console.error("🔵 [MCP] Starting MCP server with STDIO transport...");
|
|
85
|
-
if (this.universalAdapter?.getDetectionResult()) {
|
|
86
|
-
const result = this.universalAdapter.getDetectionResult();
|
|
87
|
-
console.error(`🎯 [MCP] Optimized for: ${result.capabilities.name}`);
|
|
88
|
-
}
|
|
89
|
-
// Import MCP server setup from index.ts
|
|
90
|
-
const { createMcpServer } = await import("./mcp-server.js");
|
|
91
|
-
this.mcpServer = await createMcpServer();
|
|
92
|
-
const transport = new StdioServerTransport();
|
|
93
|
-
await this.mcpServer.connect(transport);
|
|
94
|
-
console.error("✅ [MCP] Server started successfully");
|
|
95
|
-
console.error("💡 [MCP] Compatible with: Claude Desktop, Cursor, Windsurf, Cline, Warp, Roo Coder");
|
|
96
|
-
}
|
|
97
|
-
async startHttp() {
|
|
98
|
-
console.error("🟢 [HTTP] Starting HTTP/WebSocket server...");
|
|
99
|
-
if (this.universalAdapter?.getDetectionResult()) {
|
|
100
|
-
const result = this.universalAdapter.getDetectionResult();
|
|
101
|
-
console.error(`🎯 [HTTP] Optimized for: ${result.capabilities.name}`);
|
|
102
|
-
}
|
|
103
|
-
this.httpTransport = new HttpTransport({
|
|
104
|
-
port: this.config.httpPort,
|
|
105
|
-
host: this.config.httpHost,
|
|
106
|
-
enableWebSocket: this.config.enableWebSocket,
|
|
107
|
-
});
|
|
108
|
-
await this.httpTransport.start();
|
|
109
|
-
console.error("💡 [HTTP] Universal mode - works with ALL AI IDEs");
|
|
110
|
-
}
|
|
111
|
-
async startLsp() {
|
|
112
|
-
console.error("🟣 [LSP] Starting Language Server Protocol...");
|
|
113
|
-
if (this.universalAdapter?.getDetectionResult()) {
|
|
114
|
-
const result = this.universalAdapter.getDetectionResult();
|
|
115
|
-
console.error(`🎯 [LSP] Optimized for: ${result.capabilities.name}`);
|
|
116
|
-
}
|
|
117
|
-
this.lspTransport = new LspTransport();
|
|
118
|
-
await this.lspTransport.start();
|
|
119
|
-
console.error("💡 [LSP] Compatible with: Zed Editor, VSCode, Neovim, Emacs, Sublime Text");
|
|
120
|
-
}
|
|
121
|
-
async startSse() {
|
|
122
|
-
console.error("🟠 [SSE] Starting Server-Sent Events transport...");
|
|
123
|
-
if (this.universalAdapter?.getDetectionResult()) {
|
|
124
|
-
const result = this.universalAdapter.getDetectionResult();
|
|
125
|
-
console.error(`🎯 [SSE] Optimized for: ${result.capabilities.name}`);
|
|
126
|
-
}
|
|
127
|
-
this.sseTransport = new SseTransport({
|
|
128
|
-
port: this.config.ssePort,
|
|
129
|
-
host: this.config.sseHost,
|
|
130
|
-
});
|
|
131
|
-
await this.sseTransport.start();
|
|
132
|
-
console.error("💡 [SSE] Real-time streaming - works with web apps and modern clients");
|
|
133
|
-
}
|
|
134
|
-
async startAll() {
|
|
135
|
-
console.error("🌈 Starting all protocols...");
|
|
136
|
-
// Start HTTP in background
|
|
137
|
-
if (!this.httpTransport) {
|
|
138
|
-
this.httpTransport = new HttpTransport({
|
|
139
|
-
port: this.config.httpPort,
|
|
140
|
-
host: this.config.httpHost,
|
|
141
|
-
enableWebSocket: this.config.enableWebSocket,
|
|
142
|
-
});
|
|
143
|
-
await this.httpTransport.start();
|
|
144
|
-
}
|
|
145
|
-
// Note: LSP and MCP use stdio/IPC, so they can't run simultaneously
|
|
146
|
-
// In 'all' mode, we prioritize HTTP/WebSocket for universal access
|
|
147
|
-
console.error('⚠️ [Note] MCP and LSP use stdio, so only HTTP/WebSocket is active in "all" mode');
|
|
148
|
-
console.error("💡 Use separate instances for MCP or LSP: --mode=mcp or --mode=lsp");
|
|
149
|
-
}
|
|
150
|
-
async stop() {
|
|
151
|
-
console.error("🛑 Stopping servers...");
|
|
152
|
-
await closeBrowser();
|
|
153
|
-
await forceKillAllBraveProcesses();
|
|
154
|
-
if (this.httpTransport) {
|
|
155
|
-
await this.httpTransport.stop();
|
|
156
|
-
}
|
|
157
|
-
if (this.lspTransport) {
|
|
158
|
-
await this.lspTransport.stop();
|
|
159
|
-
}
|
|
160
|
-
if (this.sseTransport) {
|
|
161
|
-
await this.sseTransport.stop();
|
|
162
|
-
}
|
|
163
|
-
console.error("✅ All servers stopped");
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
// Parse CLI arguments
|
|
167
|
-
export function parseArgs() {
|
|
168
|
-
const args = process.argv.slice(2);
|
|
169
|
-
const config = {};
|
|
170
|
-
for (let i = 0; i < args.length; i++) {
|
|
171
|
-
const arg = args[i];
|
|
172
|
-
if (arg === "--mode" || arg === "-m") {
|
|
173
|
-
const mode = args[++i];
|
|
174
|
-
if (["auto", "mcp", "http", "lsp", "sse", "all"].includes(mode)) {
|
|
175
|
-
config.mode = mode;
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
console.error(`❌ Invalid mode: ${mode}. Use: auto, mcp, http, lsp, sse, or all`);
|
|
179
|
-
process.exit(1);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
else if (arg === "--port" || arg === "-p") {
|
|
183
|
-
config.httpPort = parseInt(args[++i]);
|
|
184
|
-
}
|
|
185
|
-
else if (arg === "--sse-port") {
|
|
186
|
-
config.ssePort = parseInt(args[++i]);
|
|
187
|
-
}
|
|
188
|
-
else if (arg === "--host" || arg === "-h") {
|
|
189
|
-
config.httpHost = args[++i];
|
|
190
|
-
}
|
|
191
|
-
else if (arg === "--no-websocket") {
|
|
192
|
-
config.enableWebSocket = false;
|
|
193
|
-
}
|
|
194
|
-
else if (arg === "--no-auto-detect") {
|
|
195
|
-
config.enableAutoDetection = false;
|
|
196
|
-
}
|
|
197
|
-
else if (arg === "--list-ides") {
|
|
198
|
-
UniversalIDEAdapter.printSupportedIDEs();
|
|
199
|
-
process.exit(0);
|
|
200
|
-
}
|
|
201
|
-
else if (arg === "--help") {
|
|
202
|
-
console.log(`
|
|
203
|
-
Brave Real Browser MCP Server - Universal AI IDE Support
|
|
204
|
-
|
|
205
|
-
Usage: brave-real-browser-mcp-server [options]
|
|
206
|
-
|
|
207
|
-
Options:
|
|
208
|
-
--mode, -m <mode> Protocol mode: auto, mcp, http, lsp, sse, or all (default: auto)
|
|
209
|
-
--port, -p <port> HTTP server port (default: 3000)
|
|
210
|
-
--sse-port <port> SSE server port (default: 3001)
|
|
211
|
-
--host, -h <host> HTTP/SSE server host (default: 0.0.0.0)
|
|
212
|
-
--no-websocket Disable WebSocket support in HTTP mode
|
|
213
|
-
--no-auto-detect Disable automatic IDE detection
|
|
214
|
-
--list-ides Show list of all supported AI IDEs
|
|
215
|
-
--help Show this help message
|
|
216
|
-
|
|
217
|
-
Supported AI IDEs (with auto-detection):
|
|
218
|
-
✓ Claude Desktop ✓ Cursor AI ✓ Windsurf
|
|
219
|
-
✓ Cline (VSCode) ✓ Roo Coder ✓ Zed Editor
|
|
220
|
-
✓ Continue.dev ✓ Qoder AI ✓ Warp Terminal
|
|
221
|
-
✓ GitHub Copilot ✓ Amazon CodeWhisperer ✓ Tabnine
|
|
222
|
-
✓ Cody (Sourcegraph) ✓ Aider ✓ Pieces for Developers
|
|
223
|
-
✓ VSCode (Generic) ✓ Any LSP-compatible editor
|
|
224
|
-
|
|
225
|
-
Examples:
|
|
226
|
-
# Auto mode (automatically detects your IDE and uses optimal protocol)
|
|
227
|
-
brave-real-browser-mcp-server --mode auto
|
|
228
|
-
|
|
229
|
-
# Or simply run without arguments (auto is default)
|
|
230
|
-
brave-real-browser-mcp-server
|
|
231
|
-
|
|
232
|
-
# MCP mode (for Claude Desktop, Cursor, Windsurf, Cline, Warp, Roo Coder)
|
|
233
|
-
brave-real-browser-mcp-server --mode mcp
|
|
234
|
-
|
|
235
|
-
# HTTP/WebSocket mode (universal - works with ALL IDEs)
|
|
236
|
-
brave-real-browser-mcp-server --mode http --port 3000
|
|
237
|
-
|
|
238
|
-
# LSP mode (for Zed, VSCode, Neovim, Emacs, Sublime Text)
|
|
239
|
-
brave-real-browser-mcp-server --mode lsp
|
|
240
|
-
|
|
241
|
-
# SSE mode (for real-time streaming, web apps)
|
|
242
|
-
brave-real-browser-mcp-server --mode sse --sse-port 3001
|
|
243
|
-
|
|
244
|
-
# All protocols (HTTP only, MCP/LSP/SSE need separate instances)
|
|
245
|
-
brave-real-browser-mcp-server --mode all
|
|
246
|
-
|
|
247
|
-
# Show all supported IDEs
|
|
248
|
-
brave-real-browser-mcp-server --list-ides
|
|
249
|
-
`);
|
|
250
|
-
process.exit(0);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
return config;
|
|
254
|
-
}
|
|
255
|
-
// Main entry point
|
|
256
|
-
export async function main() {
|
|
257
|
-
const config = parseArgs();
|
|
258
|
-
const launcher = new MultiProtocolLauncher(config);
|
|
259
|
-
try {
|
|
260
|
-
await launcher.start();
|
|
261
|
-
}
|
|
262
|
-
catch (error) {
|
|
263
|
-
console.error("❌ Failed to start server:", error);
|
|
264
|
-
process.exit(1);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import express from 'express';
|
|
2
|
-
import { createServer } from 'http';
|
|
3
|
-
import { WebSocketServer } from 'ws';
|
|
4
|
-
import { TOOLS } from '../tool-definitions.js';
|
|
5
|
-
import { executeToolByName } from '../index.js';
|
|
6
|
-
// Import specific handlers for direct endpoints (for backward compatibility)
|
|
7
|
-
import { handleBrowserInit, handleBrowserClose } from '../handlers/browser-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
|
-
export class HttpTransport {
|
|
12
|
-
app;
|
|
13
|
-
server = null;
|
|
14
|
-
wss = null;
|
|
15
|
-
config;
|
|
16
|
-
constructor(config = {}) {
|
|
17
|
-
this.config = {
|
|
18
|
-
port: config.port || 3000,
|
|
19
|
-
host: config.host || '0.0.0.0',
|
|
20
|
-
enableWebSocket: config.enableWebSocket !== false,
|
|
21
|
-
corsOrigins: config.corsOrigins || ['*'],
|
|
22
|
-
};
|
|
23
|
-
this.app = express();
|
|
24
|
-
this.setupMiddleware();
|
|
25
|
-
this.setupRoutes();
|
|
26
|
-
}
|
|
27
|
-
setupMiddleware() {
|
|
28
|
-
// Body parsing
|
|
29
|
-
this.app.use(express.json());
|
|
30
|
-
this.app.use(express.urlencoded({ extended: true }));
|
|
31
|
-
// CORS
|
|
32
|
-
this.app.use((req, res, next) => {
|
|
33
|
-
res.header('Access-Control-Allow-Origin', this.config.corsOrigins?.[0] || '*');
|
|
34
|
-
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
|
35
|
-
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
36
|
-
if (req.method === 'OPTIONS') {
|
|
37
|
-
return res.sendStatus(200);
|
|
38
|
-
}
|
|
39
|
-
next();
|
|
40
|
-
});
|
|
41
|
-
// Request logging
|
|
42
|
-
this.app.use((req, res, next) => {
|
|
43
|
-
console.error(`📡 [HTTP] ${req.method} ${req.path} - ${new Date().toISOString()}`);
|
|
44
|
-
next();
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
setupRoutes() {
|
|
48
|
-
// Health check
|
|
49
|
-
this.app.get('/health', (req, res) => {
|
|
50
|
-
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
51
|
-
});
|
|
52
|
-
// List all available tools
|
|
53
|
-
this.app.get('/tools', (req, res) => {
|
|
54
|
-
res.json({ tools: TOOLS });
|
|
55
|
-
});
|
|
56
|
-
// Execute tool - Generic endpoint
|
|
57
|
-
this.app.post('/tools/:toolName', async (req, res) => {
|
|
58
|
-
const { toolName } = req.params;
|
|
59
|
-
const args = req.body;
|
|
60
|
-
try {
|
|
61
|
-
const result = await this.executeTool(toolName, args);
|
|
62
|
-
res.json({ success: true, result });
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
66
|
-
res.status(500).json({ success: false, error: errorMessage });
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
// Browser automation endpoints
|
|
70
|
-
this.app.post('/browser/init', async (req, res) => {
|
|
71
|
-
try {
|
|
72
|
-
const result = await handleBrowserInit(req.body);
|
|
73
|
-
res.json({ success: true, result });
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
res.status(500).json({ success: false, error: error.message });
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
this.app.post('/browser/navigate', async (req, res) => {
|
|
80
|
-
try {
|
|
81
|
-
const result = await handleNavigate(req.body);
|
|
82
|
-
res.json({ success: true, result });
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
res.status(500).json({ success: false, error: error.message });
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
this.app.post('/browser/click', async (req, res) => {
|
|
89
|
-
try {
|
|
90
|
-
const result = await handleClick(req.body);
|
|
91
|
-
res.json({ success: true, result });
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
res.status(500).json({ success: false, error: error.message });
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
this.app.post('/browser/type', async (req, res) => {
|
|
98
|
-
try {
|
|
99
|
-
const result = await handleType(req.body);
|
|
100
|
-
res.json({ success: true, result });
|
|
101
|
-
}
|
|
102
|
-
catch (error) {
|
|
103
|
-
res.status(500).json({ success: false, error: error.message });
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
this.app.post('/browser/get-content', async (req, res) => {
|
|
107
|
-
try {
|
|
108
|
-
const result = await handleGetContent(req.body);
|
|
109
|
-
res.json({ success: true, result });
|
|
110
|
-
}
|
|
111
|
-
catch (error) {
|
|
112
|
-
res.status(500).json({ success: false, error: error.message });
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
this.app.post('/browser/close', async (req, res) => {
|
|
116
|
-
try {
|
|
117
|
-
const result = await handleBrowserClose();
|
|
118
|
-
res.json({ success: true, result });
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
res.status(500).json({ success: false, error: error.message });
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
// Error handling
|
|
125
|
-
this.app.use((err, req, res, next) => {
|
|
126
|
-
console.error('❌ [HTTP] Error:', err);
|
|
127
|
-
res.status(500).json({ success: false, error: err.message });
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
async executeTool(toolName, args) {
|
|
131
|
-
// Use universal tool executor from index.ts (supports all 110 tools)
|
|
132
|
-
return await executeToolByName(toolName, args);
|
|
133
|
-
}
|
|
134
|
-
setupWebSocket() {
|
|
135
|
-
if (!this.server || !this.config.enableWebSocket)
|
|
136
|
-
return;
|
|
137
|
-
this.wss = new WebSocketServer({ server: this.server });
|
|
138
|
-
this.wss.on('connection', (ws) => {
|
|
139
|
-
console.error('🔌 [WebSocket] Client connected');
|
|
140
|
-
ws.on('message', async (message) => {
|
|
141
|
-
try {
|
|
142
|
-
const data = JSON.parse(message.toString());
|
|
143
|
-
const { id, tool, args } = data;
|
|
144
|
-
const result = await this.executeTool(tool, args);
|
|
145
|
-
ws.send(JSON.stringify({
|
|
146
|
-
id,
|
|
147
|
-
success: true,
|
|
148
|
-
result,
|
|
149
|
-
}));
|
|
150
|
-
}
|
|
151
|
-
catch (error) {
|
|
152
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
153
|
-
ws.send(JSON.stringify({
|
|
154
|
-
success: false,
|
|
155
|
-
error: errorMessage,
|
|
156
|
-
}));
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
ws.on('close', () => {
|
|
160
|
-
console.error('🔌 [WebSocket] Client disconnected');
|
|
161
|
-
});
|
|
162
|
-
ws.on('error', (error) => {
|
|
163
|
-
console.error('❌ [WebSocket] Error:', error);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
async start() {
|
|
168
|
-
return new Promise((resolve) => {
|
|
169
|
-
this.server = createServer(this.app);
|
|
170
|
-
this.setupWebSocket();
|
|
171
|
-
this.server.listen(this.config.port, this.config.host, () => {
|
|
172
|
-
console.error(`✅ [HTTP] Server running on http://${this.config.host}:${this.config.port}`);
|
|
173
|
-
if (this.config.enableWebSocket) {
|
|
174
|
-
console.error(`✅ [WebSocket] Server running on ws://${this.config.host}:${this.config.port}`);
|
|
175
|
-
}
|
|
176
|
-
resolve();
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
async stop() {
|
|
181
|
-
return new Promise((resolve, reject) => {
|
|
182
|
-
if (this.wss) {
|
|
183
|
-
this.wss.close();
|
|
184
|
-
}
|
|
185
|
-
if (this.server) {
|
|
186
|
-
this.server.close((err) => {
|
|
187
|
-
if (err)
|
|
188
|
-
reject(err);
|
|
189
|
-
else
|
|
190
|
-
resolve();
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
resolve();
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
}
|