brave-real-browser-mcp-server 2.14.5 → 2.14.6
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 +15 -25
- package/dist/index.js +1 -26
- package/dist/tool-definitions.js +0 -45
- package/package.json +1 -1
- package/dist/handlers/api-integration-handlers.js +0 -335
- package/dist/universal-ide-adapter.js +0 -855
|
@@ -1,855 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Universal AI IDE Adapter
|
|
3
|
-
* Automatically detects and configures for all AI-powered IDEs
|
|
4
|
-
*
|
|
5
|
-
* Supported IDEs:
|
|
6
|
-
* - Claude Desktop
|
|
7
|
-
* - Cursor AI
|
|
8
|
-
* - Windsurf
|
|
9
|
-
* - Cline (VSCode Extension)
|
|
10
|
-
* - Roo Coder
|
|
11
|
-
* - Zed Editor
|
|
12
|
-
* - Continue.dev
|
|
13
|
-
* - Qoder AI
|
|
14
|
-
* - Warp Terminal
|
|
15
|
-
* - GitHub Copilot Chat
|
|
16
|
-
* - Amazon CodeWhisperer
|
|
17
|
-
* - Tabnine
|
|
18
|
-
* - Cody (Sourcegraph)
|
|
19
|
-
* - Aider
|
|
20
|
-
* - Pieces for Developers
|
|
21
|
-
*/
|
|
22
|
-
import * as os from "os";
|
|
23
|
-
import * as path from "path";
|
|
24
|
-
export var AIIDEType;
|
|
25
|
-
(function (AIIDEType) {
|
|
26
|
-
AIIDEType["CLAUDE_DESKTOP"] = "claude-desktop";
|
|
27
|
-
AIIDEType["CURSOR"] = "cursor";
|
|
28
|
-
AIIDEType["WINDSURF"] = "windsurf";
|
|
29
|
-
AIIDEType["CLINE"] = "cline";
|
|
30
|
-
AIIDEType["ROO_CODER"] = "roo-coder";
|
|
31
|
-
AIIDEType["ZED"] = "zed";
|
|
32
|
-
AIIDEType["CONTINUE"] = "continue";
|
|
33
|
-
AIIDEType["QODER"] = "qoder";
|
|
34
|
-
AIIDEType["WARP"] = "warp";
|
|
35
|
-
AIIDEType["COPILOT"] = "copilot";
|
|
36
|
-
AIIDEType["CODEWHISPERER"] = "codewhisperer";
|
|
37
|
-
AIIDEType["TABNINE"] = "tabnine";
|
|
38
|
-
AIIDEType["CODY"] = "cody";
|
|
39
|
-
AIIDEType["AIDER"] = "aider";
|
|
40
|
-
AIIDEType["PIECES"] = "pieces";
|
|
41
|
-
AIIDEType["VSCODE_GENERIC"] = "vscode-generic";
|
|
42
|
-
AIIDEType["UNKNOWN"] = "unknown";
|
|
43
|
-
})(AIIDEType || (AIIDEType = {}));
|
|
44
|
-
export var ProtocolType;
|
|
45
|
-
(function (ProtocolType) {
|
|
46
|
-
ProtocolType["MCP"] = "mcp";
|
|
47
|
-
ProtocolType["LSP"] = "lsp";
|
|
48
|
-
ProtocolType["HTTP"] = "http";
|
|
49
|
-
ProtocolType["WEBSOCKET"] = "ws";
|
|
50
|
-
ProtocolType["STDIO"] = "stdio";
|
|
51
|
-
ProtocolType["JSONRPC"] = "jsonrpc";
|
|
52
|
-
})(ProtocolType || (ProtocolType = {}));
|
|
53
|
-
/**
|
|
54
|
-
* All supported AI IDEs with their capabilities
|
|
55
|
-
*/
|
|
56
|
-
export const AI_IDE_REGISTRY = {
|
|
57
|
-
[AIIDEType.CLAUDE_DESKTOP]: {
|
|
58
|
-
type: AIIDEType.CLAUDE_DESKTOP,
|
|
59
|
-
name: "Claude Desktop",
|
|
60
|
-
supportedProtocols: [ProtocolType.MCP, ProtocolType.STDIO],
|
|
61
|
-
preferredProtocol: ProtocolType.STDIO,
|
|
62
|
-
configPath: os.platform() === "win32"
|
|
63
|
-
? path.join(os.homedir(), "AppData", "Roaming", "Claude", "claude_desktop_config.json")
|
|
64
|
-
: path.join(os.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json"),
|
|
65
|
-
autoDetectable: true,
|
|
66
|
-
requiresManualSetup: false,
|
|
67
|
-
},
|
|
68
|
-
[AIIDEType.CURSOR]: {
|
|
69
|
-
type: AIIDEType.CURSOR,
|
|
70
|
-
name: "Cursor AI",
|
|
71
|
-
supportedProtocols: [
|
|
72
|
-
ProtocolType.MCP,
|
|
73
|
-
ProtocolType.STDIO,
|
|
74
|
-
ProtocolType.HTTP,
|
|
75
|
-
],
|
|
76
|
-
preferredProtocol: ProtocolType.STDIO,
|
|
77
|
-
configPath: os.platform() === "win32"
|
|
78
|
-
? path.join(os.homedir(), "AppData", "Roaming", "Cursor", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json")
|
|
79
|
-
: path.join(os.homedir(), ".cursor", "mcp_settings.json"),
|
|
80
|
-
autoDetectable: true,
|
|
81
|
-
requiresManualSetup: false,
|
|
82
|
-
},
|
|
83
|
-
[AIIDEType.WINDSURF]: {
|
|
84
|
-
type: AIIDEType.WINDSURF,
|
|
85
|
-
name: "Windsurf Editor",
|
|
86
|
-
supportedProtocols: [
|
|
87
|
-
ProtocolType.MCP,
|
|
88
|
-
ProtocolType.STDIO,
|
|
89
|
-
ProtocolType.HTTP,
|
|
90
|
-
],
|
|
91
|
-
preferredProtocol: ProtocolType.STDIO,
|
|
92
|
-
configPath: os.platform() === "win32"
|
|
93
|
-
? path.join(os.homedir(), "AppData", "Roaming", "Windsurf", "mcp.json")
|
|
94
|
-
: path.join(os.homedir(), ".windsurf", "mcp.json"),
|
|
95
|
-
autoDetectable: true,
|
|
96
|
-
requiresManualSetup: false,
|
|
97
|
-
},
|
|
98
|
-
[AIIDEType.CLINE]: {
|
|
99
|
-
type: AIIDEType.CLINE,
|
|
100
|
-
name: "Cline (VSCode Extension)",
|
|
101
|
-
supportedProtocols: [
|
|
102
|
-
ProtocolType.MCP,
|
|
103
|
-
ProtocolType.STDIO,
|
|
104
|
-
ProtocolType.HTTP,
|
|
105
|
-
],
|
|
106
|
-
preferredProtocol: ProtocolType.STDIO,
|
|
107
|
-
configPath: os.platform() === "win32"
|
|
108
|
-
? path.join(os.homedir(), "AppData", "Roaming", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json")
|
|
109
|
-
: path.join(os.homedir(), "Library", "Application Support", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json"),
|
|
110
|
-
autoDetectable: true,
|
|
111
|
-
requiresManualSetup: false,
|
|
112
|
-
},
|
|
113
|
-
[AIIDEType.ROO_CODER]: {
|
|
114
|
-
type: AIIDEType.ROO_CODER,
|
|
115
|
-
name: "Roo Coder",
|
|
116
|
-
supportedProtocols: [
|
|
117
|
-
ProtocolType.MCP,
|
|
118
|
-
ProtocolType.STDIO,
|
|
119
|
-
ProtocolType.HTTP,
|
|
120
|
-
],
|
|
121
|
-
preferredProtocol: ProtocolType.STDIO,
|
|
122
|
-
autoDetectable: true,
|
|
123
|
-
requiresManualSetup: false,
|
|
124
|
-
},
|
|
125
|
-
[AIIDEType.ZED]: {
|
|
126
|
-
type: AIIDEType.ZED,
|
|
127
|
-
name: "Zed Editor",
|
|
128
|
-
supportedProtocols: [ProtocolType.LSP, ProtocolType.MCP, ProtocolType.HTTP],
|
|
129
|
-
preferredProtocol: ProtocolType.LSP,
|
|
130
|
-
configPath: os.platform() === "win32"
|
|
131
|
-
? path.join(os.homedir(), "AppData", "Roaming", "Zed", "settings.json")
|
|
132
|
-
: path.join(os.homedir(), ".config", "zed", "settings.json"),
|
|
133
|
-
autoDetectable: true,
|
|
134
|
-
requiresManualSetup: false,
|
|
135
|
-
},
|
|
136
|
-
[AIIDEType.CONTINUE]: {
|
|
137
|
-
type: AIIDEType.CONTINUE,
|
|
138
|
-
name: "Continue.dev",
|
|
139
|
-
supportedProtocols: [
|
|
140
|
-
ProtocolType.MCP,
|
|
141
|
-
ProtocolType.HTTP,
|
|
142
|
-
ProtocolType.STDIO,
|
|
143
|
-
],
|
|
144
|
-
preferredProtocol: ProtocolType.HTTP,
|
|
145
|
-
configPath: path.join(os.homedir(), ".continue", "config.json"),
|
|
146
|
-
autoDetectable: true,
|
|
147
|
-
requiresManualSetup: false,
|
|
148
|
-
},
|
|
149
|
-
[AIIDEType.QODER]: {
|
|
150
|
-
type: AIIDEType.QODER,
|
|
151
|
-
name: "Qoder AI Editor",
|
|
152
|
-
supportedProtocols: [
|
|
153
|
-
ProtocolType.HTTP,
|
|
154
|
-
ProtocolType.WEBSOCKET,
|
|
155
|
-
ProtocolType.MCP,
|
|
156
|
-
],
|
|
157
|
-
preferredProtocol: ProtocolType.HTTP,
|
|
158
|
-
autoDetectable: true,
|
|
159
|
-
requiresManualSetup: false,
|
|
160
|
-
},
|
|
161
|
-
[AIIDEType.WARP]: {
|
|
162
|
-
type: AIIDEType.WARP,
|
|
163
|
-
name: "Warp Terminal",
|
|
164
|
-
supportedProtocols: [ProtocolType.MCP, ProtocolType.STDIO],
|
|
165
|
-
preferredProtocol: ProtocolType.STDIO,
|
|
166
|
-
autoDetectable: true,
|
|
167
|
-
requiresManualSetup: false,
|
|
168
|
-
},
|
|
169
|
-
[AIIDEType.COPILOT]: {
|
|
170
|
-
type: AIIDEType.COPILOT,
|
|
171
|
-
name: "GitHub Copilot Chat",
|
|
172
|
-
supportedProtocols: [ProtocolType.HTTP, ProtocolType.LSP],
|
|
173
|
-
preferredProtocol: ProtocolType.HTTP,
|
|
174
|
-
autoDetectable: true,
|
|
175
|
-
requiresManualSetup: false,
|
|
176
|
-
},
|
|
177
|
-
[AIIDEType.CODEWHISPERER]: {
|
|
178
|
-
type: AIIDEType.CODEWHISPERER,
|
|
179
|
-
name: "Amazon CodeWhisperer",
|
|
180
|
-
supportedProtocols: [ProtocolType.HTTP, ProtocolType.LSP],
|
|
181
|
-
preferredProtocol: ProtocolType.HTTP,
|
|
182
|
-
autoDetectable: true,
|
|
183
|
-
requiresManualSetup: false,
|
|
184
|
-
},
|
|
185
|
-
[AIIDEType.TABNINE]: {
|
|
186
|
-
type: AIIDEType.TABNINE,
|
|
187
|
-
name: "Tabnine",
|
|
188
|
-
supportedProtocols: [ProtocolType.HTTP, ProtocolType.WEBSOCKET],
|
|
189
|
-
preferredProtocol: ProtocolType.HTTP,
|
|
190
|
-
autoDetectable: true,
|
|
191
|
-
requiresManualSetup: false,
|
|
192
|
-
},
|
|
193
|
-
[AIIDEType.CODY]: {
|
|
194
|
-
type: AIIDEType.CODY,
|
|
195
|
-
name: "Cody (Sourcegraph)",
|
|
196
|
-
supportedProtocols: [ProtocolType.HTTP, ProtocolType.LSP, ProtocolType.MCP],
|
|
197
|
-
preferredProtocol: ProtocolType.HTTP,
|
|
198
|
-
autoDetectable: true,
|
|
199
|
-
requiresManualSetup: false,
|
|
200
|
-
},
|
|
201
|
-
[AIIDEType.AIDER]: {
|
|
202
|
-
type: AIIDEType.AIDER,
|
|
203
|
-
name: "Aider",
|
|
204
|
-
supportedProtocols: [ProtocolType.STDIO, ProtocolType.HTTP],
|
|
205
|
-
preferredProtocol: ProtocolType.STDIO,
|
|
206
|
-
autoDetectable: true,
|
|
207
|
-
requiresManualSetup: false,
|
|
208
|
-
},
|
|
209
|
-
[AIIDEType.PIECES]: {
|
|
210
|
-
type: AIIDEType.PIECES,
|
|
211
|
-
name: "Pieces for Developers",
|
|
212
|
-
supportedProtocols: [ProtocolType.HTTP, ProtocolType.WEBSOCKET],
|
|
213
|
-
preferredProtocol: ProtocolType.HTTP,
|
|
214
|
-
autoDetectable: true,
|
|
215
|
-
requiresManualSetup: false,
|
|
216
|
-
},
|
|
217
|
-
[AIIDEType.VSCODE_GENERIC]: {
|
|
218
|
-
type: AIIDEType.VSCODE_GENERIC,
|
|
219
|
-
name: "VSCode (Generic)",
|
|
220
|
-
supportedProtocols: [ProtocolType.LSP, ProtocolType.HTTP, ProtocolType.MCP],
|
|
221
|
-
preferredProtocol: ProtocolType.LSP,
|
|
222
|
-
autoDetectable: true,
|
|
223
|
-
requiresManualSetup: false,
|
|
224
|
-
},
|
|
225
|
-
[AIIDEType.UNKNOWN]: {
|
|
226
|
-
type: AIIDEType.UNKNOWN,
|
|
227
|
-
name: "Unknown/Generic IDE",
|
|
228
|
-
supportedProtocols: [
|
|
229
|
-
ProtocolType.HTTP,
|
|
230
|
-
ProtocolType.STDIO,
|
|
231
|
-
ProtocolType.MCP,
|
|
232
|
-
],
|
|
233
|
-
preferredProtocol: ProtocolType.HTTP,
|
|
234
|
-
autoDetectable: false,
|
|
235
|
-
requiresManualSetup: true,
|
|
236
|
-
},
|
|
237
|
-
};
|
|
238
|
-
/**
|
|
239
|
-
* Universal AI IDE Detector
|
|
240
|
-
*/
|
|
241
|
-
export class UniversalIDEDetector {
|
|
242
|
-
/**
|
|
243
|
-
* Detect from command line arguments
|
|
244
|
-
*/
|
|
245
|
-
static async detectFromCommandLineArgs() {
|
|
246
|
-
const args = process.argv.join(" ").toLowerCase();
|
|
247
|
-
const cwd = process.cwd().toLowerCase();
|
|
248
|
-
// Check for IDE-specific paths in arguments
|
|
249
|
-
if (args.includes("claude") &&
|
|
250
|
-
(args.includes("desktop") || cwd.includes("claude"))) {
|
|
251
|
-
return {
|
|
252
|
-
detected: true,
|
|
253
|
-
ide: AIIDEType.CLAUDE_DESKTOP,
|
|
254
|
-
protocol: ProtocolType.STDIO,
|
|
255
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CLAUDE_DESKTOP],
|
|
256
|
-
confidence: 95,
|
|
257
|
-
detectionMethod: "command-line-args",
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
if (args.includes("cursor") || cwd.includes("cursor")) {
|
|
261
|
-
return {
|
|
262
|
-
detected: true,
|
|
263
|
-
ide: AIIDEType.CURSOR,
|
|
264
|
-
protocol: ProtocolType.STDIO,
|
|
265
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CURSOR],
|
|
266
|
-
confidence: 95,
|
|
267
|
-
detectionMethod: "command-line-args",
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
if (args.includes("windsurf") || cwd.includes("windsurf")) {
|
|
271
|
-
return {
|
|
272
|
-
detected: true,
|
|
273
|
-
ide: AIIDEType.WINDSURF,
|
|
274
|
-
protocol: ProtocolType.STDIO,
|
|
275
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.WINDSURF],
|
|
276
|
-
confidence: 95,
|
|
277
|
-
detectionMethod: "command-line-args",
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
if (args.includes("cline") ||
|
|
281
|
-
args.includes("claude-dev") ||
|
|
282
|
-
cwd.includes("claude-dev")) {
|
|
283
|
-
return {
|
|
284
|
-
detected: true,
|
|
285
|
-
ide: AIIDEType.CLINE,
|
|
286
|
-
protocol: ProtocolType.STDIO,
|
|
287
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CLINE],
|
|
288
|
-
confidence: 90,
|
|
289
|
-
detectionMethod: "command-line-args",
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
return { detected: false };
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Detect from working directory
|
|
296
|
-
*/
|
|
297
|
-
static async detectFromWorkingDirectory() {
|
|
298
|
-
const cwd = process.cwd().toLowerCase();
|
|
299
|
-
const homeDir = os.homedir().toLowerCase();
|
|
300
|
-
// Check for IDE-specific directories
|
|
301
|
-
if (cwd.includes(".claude") || cwd.includes("claude")) {
|
|
302
|
-
return {
|
|
303
|
-
detected: true,
|
|
304
|
-
ide: AIIDEType.CLAUDE_DESKTOP,
|
|
305
|
-
protocol: ProtocolType.STDIO,
|
|
306
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CLAUDE_DESKTOP],
|
|
307
|
-
confidence: 80,
|
|
308
|
-
detectionMethod: "working-directory",
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
if (cwd.includes(".cursor") || cwd.includes("cursor")) {
|
|
312
|
-
return {
|
|
313
|
-
detected: true,
|
|
314
|
-
ide: AIIDEType.CURSOR,
|
|
315
|
-
protocol: ProtocolType.STDIO,
|
|
316
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CURSOR],
|
|
317
|
-
confidence: 80,
|
|
318
|
-
detectionMethod: "working-directory",
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
if (cwd.includes(".windsurf") || cwd.includes("windsurf")) {
|
|
322
|
-
return {
|
|
323
|
-
detected: true,
|
|
324
|
-
ide: AIIDEType.WINDSURF,
|
|
325
|
-
protocol: ProtocolType.STDIO,
|
|
326
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.WINDSURF],
|
|
327
|
-
confidence: 80,
|
|
328
|
-
detectionMethod: "working-directory",
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
return { detected: false };
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* Detect which AI IDE is currently running this server
|
|
335
|
-
*/
|
|
336
|
-
static async detectIDE() {
|
|
337
|
-
console.error("🔍 [Universal Adapter] Starting AI IDE detection...");
|
|
338
|
-
// Detection strategies (in order of priority)
|
|
339
|
-
const detectionStrategies = [
|
|
340
|
-
this.detectFromCommandLineArgs.bind(this),
|
|
341
|
-
this.detectFromEnvironment.bind(this),
|
|
342
|
-
this.detectFromParentProcess.bind(this),
|
|
343
|
-
this.detectFromWorkingDirectory.bind(this),
|
|
344
|
-
this.detectFromStdio.bind(this),
|
|
345
|
-
this.detectFromConfigFiles.bind(this),
|
|
346
|
-
this.detectFromNetworkPorts.bind(this),
|
|
347
|
-
];
|
|
348
|
-
for (const strategy of detectionStrategies) {
|
|
349
|
-
const result = await strategy();
|
|
350
|
-
if (result.detected) {
|
|
351
|
-
console.error(`✅ [Universal Adapter] Detected: ${result.capabilities.name} (${result.confidence}% confidence)`);
|
|
352
|
-
console.error(`📡 [Universal Adapter] Using protocol: ${result.protocol}`);
|
|
353
|
-
return result;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
// Fallback to HTTP (universal protocol)
|
|
357
|
-
console.error("⚠️ [Universal Adapter] Could not detect specific IDE, using universal HTTP protocol");
|
|
358
|
-
return {
|
|
359
|
-
detected: true,
|
|
360
|
-
ide: AIIDEType.UNKNOWN,
|
|
361
|
-
protocol: ProtocolType.HTTP,
|
|
362
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.UNKNOWN],
|
|
363
|
-
confidence: 50,
|
|
364
|
-
detectionMethod: "fallback",
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
/**
|
|
368
|
-
* Detect from environment variables
|
|
369
|
-
*/
|
|
370
|
-
static async detectFromEnvironment() {
|
|
371
|
-
const env = process.env;
|
|
372
|
-
// Claude Desktop
|
|
373
|
-
if (env.CLAUDE_DESKTOP || env.ANTHROPIC_API_KEY || env.CLAUDE_APP) {
|
|
374
|
-
return {
|
|
375
|
-
detected: true,
|
|
376
|
-
ide: AIIDEType.CLAUDE_DESKTOP,
|
|
377
|
-
protocol: ProtocolType.STDIO,
|
|
378
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CLAUDE_DESKTOP],
|
|
379
|
-
confidence: 90,
|
|
380
|
-
detectionMethod: "environment-variables",
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
// Cursor AI
|
|
384
|
-
if (env.CURSOR_IDE || env.CURSOR_SESSION || env.CURSOR_USER_DATA) {
|
|
385
|
-
return {
|
|
386
|
-
detected: true,
|
|
387
|
-
ide: AIIDEType.CURSOR,
|
|
388
|
-
protocol: ProtocolType.STDIO,
|
|
389
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CURSOR],
|
|
390
|
-
confidence: 90,
|
|
391
|
-
detectionMethod: "environment-variables",
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
// Windsurf
|
|
395
|
-
if (env.WINDSURF_IDE || env.WINDSURF_SESSION || env.WINDSURF_CONFIG) {
|
|
396
|
-
return {
|
|
397
|
-
detected: true,
|
|
398
|
-
ide: AIIDEType.WINDSURF,
|
|
399
|
-
protocol: ProtocolType.STDIO,
|
|
400
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.WINDSURF],
|
|
401
|
-
confidence: 90,
|
|
402
|
-
detectionMethod: "environment-variables",
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
// Cline
|
|
406
|
-
if (env.CLINE_MODE || env.CLAUDE_DEV || env.CLINE_MCP_SERVER) {
|
|
407
|
-
return {
|
|
408
|
-
detected: true,
|
|
409
|
-
ide: AIIDEType.CLINE,
|
|
410
|
-
protocol: ProtocolType.STDIO,
|
|
411
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CLINE],
|
|
412
|
-
confidence: 90,
|
|
413
|
-
detectionMethod: "environment-variables",
|
|
414
|
-
};
|
|
415
|
-
}
|
|
416
|
-
// Warp Terminal
|
|
417
|
-
if (env.WARP ||
|
|
418
|
-
env.TERM_PROGRAM === "WarpTerminal" ||
|
|
419
|
-
env.TERM === "warp") {
|
|
420
|
-
return {
|
|
421
|
-
detected: true,
|
|
422
|
-
ide: AIIDEType.WARP,
|
|
423
|
-
protocol: ProtocolType.STDIO,
|
|
424
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.WARP],
|
|
425
|
-
confidence: 85,
|
|
426
|
-
detectionMethod: "environment-variables",
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
// Zed Editor
|
|
430
|
-
if (env.ZED_EDITOR || env.ZED || env.ZED_TERM) {
|
|
431
|
-
return {
|
|
432
|
-
detected: true,
|
|
433
|
-
ide: AIIDEType.ZED,
|
|
434
|
-
protocol: ProtocolType.LSP,
|
|
435
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.ZED],
|
|
436
|
-
confidence: 85,
|
|
437
|
-
detectionMethod: "environment-variables",
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
// VSCode (generic)
|
|
441
|
-
if (env.VSCODE_PID || env.VSCODE_IPC_HOOK || env.VSCODE_CWD) {
|
|
442
|
-
return {
|
|
443
|
-
detected: true,
|
|
444
|
-
ide: AIIDEType.VSCODE_GENERIC,
|
|
445
|
-
protocol: ProtocolType.LSP,
|
|
446
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.VSCODE_GENERIC],
|
|
447
|
-
confidence: 80,
|
|
448
|
-
detectionMethod: "environment-variables",
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
return { detected: false };
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* Detect from parent process
|
|
455
|
-
*/
|
|
456
|
-
static async detectFromParentProcess() {
|
|
457
|
-
try {
|
|
458
|
-
const ppid = process.ppid;
|
|
459
|
-
if (!ppid)
|
|
460
|
-
return { detected: false };
|
|
461
|
-
// Try to get parent process name and full command line
|
|
462
|
-
let parentName = "";
|
|
463
|
-
let commandLine = "";
|
|
464
|
-
if (os.platform() === "win32") {
|
|
465
|
-
try {
|
|
466
|
-
const { execSync } = await import("child_process");
|
|
467
|
-
const output = execSync(`wmic process where processid=${ppid} get name,commandline`, { encoding: "utf8" });
|
|
468
|
-
const lines = output.split("\n").filter((line) => line.trim());
|
|
469
|
-
if (lines.length > 1) {
|
|
470
|
-
commandLine = lines[1].trim().toLowerCase();
|
|
471
|
-
parentName = commandLine.split(/\s+/)[0].toLowerCase();
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
catch {
|
|
475
|
-
// Ignore errors
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
else {
|
|
479
|
-
try {
|
|
480
|
-
const { execSync } = await import("child_process");
|
|
481
|
-
commandLine = execSync(`ps -p ${ppid} -o command=`, {
|
|
482
|
-
encoding: "utf8",
|
|
483
|
-
})
|
|
484
|
-
.trim()
|
|
485
|
-
.toLowerCase();
|
|
486
|
-
parentName = execSync(`ps -p ${ppid} -o comm=`, { encoding: "utf8" })
|
|
487
|
-
.trim()
|
|
488
|
-
.toLowerCase();
|
|
489
|
-
}
|
|
490
|
-
catch {
|
|
491
|
-
// Ignore errors
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
// Match command line first (more accurate)
|
|
495
|
-
if (commandLine) {
|
|
496
|
-
if (commandLine.includes("claude") && commandLine.includes("desktop")) {
|
|
497
|
-
return {
|
|
498
|
-
detected: true,
|
|
499
|
-
ide: AIIDEType.CLAUDE_DESKTOP,
|
|
500
|
-
protocol: ProtocolType.STDIO,
|
|
501
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CLAUDE_DESKTOP],
|
|
502
|
-
confidence: 90,
|
|
503
|
-
detectionMethod: "parent-process-cmdline",
|
|
504
|
-
};
|
|
505
|
-
}
|
|
506
|
-
if (commandLine.includes("cursor")) {
|
|
507
|
-
return {
|
|
508
|
-
detected: true,
|
|
509
|
-
ide: AIIDEType.CURSOR,
|
|
510
|
-
protocol: ProtocolType.STDIO,
|
|
511
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CURSOR],
|
|
512
|
-
confidence: 90,
|
|
513
|
-
detectionMethod: "parent-process-cmdline",
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
if (commandLine.includes("windsurf")) {
|
|
517
|
-
return {
|
|
518
|
-
detected: true,
|
|
519
|
-
ide: AIIDEType.WINDSURF,
|
|
520
|
-
protocol: ProtocolType.STDIO,
|
|
521
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.WINDSURF],
|
|
522
|
-
confidence: 90,
|
|
523
|
-
detectionMethod: "parent-process-cmdline",
|
|
524
|
-
};
|
|
525
|
-
}
|
|
526
|
-
if (commandLine.includes("cline") ||
|
|
527
|
-
commandLine.includes("claude-dev")) {
|
|
528
|
-
return {
|
|
529
|
-
detected: true,
|
|
530
|
-
ide: AIIDEType.CLINE,
|
|
531
|
-
protocol: ProtocolType.STDIO,
|
|
532
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CLINE],
|
|
533
|
-
confidence: 85,
|
|
534
|
-
detectionMethod: "parent-process-cmdline",
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
// Match parent process name to IDE
|
|
539
|
-
if (parentName.includes("claude")) {
|
|
540
|
-
return {
|
|
541
|
-
detected: true,
|
|
542
|
-
ide: AIIDEType.CLAUDE_DESKTOP,
|
|
543
|
-
protocol: ProtocolType.STDIO,
|
|
544
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CLAUDE_DESKTOP],
|
|
545
|
-
confidence: 85,
|
|
546
|
-
detectionMethod: "parent-process",
|
|
547
|
-
};
|
|
548
|
-
}
|
|
549
|
-
if (parentName.includes("cursor")) {
|
|
550
|
-
return {
|
|
551
|
-
detected: true,
|
|
552
|
-
ide: AIIDEType.CURSOR,
|
|
553
|
-
protocol: ProtocolType.STDIO,
|
|
554
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CURSOR],
|
|
555
|
-
confidence: 85,
|
|
556
|
-
detectionMethod: "parent-process",
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
if (parentName.includes("windsurf")) {
|
|
560
|
-
return {
|
|
561
|
-
detected: true,
|
|
562
|
-
ide: AIIDEType.WINDSURF,
|
|
563
|
-
protocol: ProtocolType.STDIO,
|
|
564
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.WINDSURF],
|
|
565
|
-
confidence: 85,
|
|
566
|
-
detectionMethod: "parent-process",
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
if (parentName.includes("zed")) {
|
|
570
|
-
return {
|
|
571
|
-
detected: true,
|
|
572
|
-
ide: AIIDEType.ZED,
|
|
573
|
-
protocol: ProtocolType.LSP,
|
|
574
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.ZED],
|
|
575
|
-
confidence: 85,
|
|
576
|
-
detectionMethod: "parent-process",
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
if (parentName.includes("code") || parentName.includes("vscode")) {
|
|
580
|
-
return {
|
|
581
|
-
detected: true,
|
|
582
|
-
ide: AIIDEType.VSCODE_GENERIC,
|
|
583
|
-
protocol: ProtocolType.LSP,
|
|
584
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.VSCODE_GENERIC],
|
|
585
|
-
confidence: 80,
|
|
586
|
-
detectionMethod: "parent-process",
|
|
587
|
-
};
|
|
588
|
-
}
|
|
589
|
-
if (parentName.includes("warp")) {
|
|
590
|
-
return {
|
|
591
|
-
detected: true,
|
|
592
|
-
ide: AIIDEType.WARP,
|
|
593
|
-
protocol: ProtocolType.STDIO,
|
|
594
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.WARP],
|
|
595
|
-
confidence: 85,
|
|
596
|
-
detectionMethod: "parent-process",
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
catch (error) {
|
|
601
|
-
// Ignore errors in process detection
|
|
602
|
-
}
|
|
603
|
-
return { detected: false };
|
|
604
|
-
}
|
|
605
|
-
/**
|
|
606
|
-
* Detect from stdio characteristics
|
|
607
|
-
*/
|
|
608
|
-
static async detectFromStdio() {
|
|
609
|
-
// Check if stdin/stdout are TTY or pipes
|
|
610
|
-
const isStdinPiped = !process.stdin.isTTY;
|
|
611
|
-
const isStdoutPiped = !process.stdout.isTTY;
|
|
612
|
-
// MCP servers typically use piped stdio
|
|
613
|
-
if (isStdinPiped && isStdoutPiped) {
|
|
614
|
-
// This is likely an MCP client, but we can't determine which one
|
|
615
|
-
// Default to generic MCP with STDIO protocol
|
|
616
|
-
return {
|
|
617
|
-
detected: true,
|
|
618
|
-
ide: AIIDEType.UNKNOWN,
|
|
619
|
-
protocol: ProtocolType.STDIO,
|
|
620
|
-
capabilities: {
|
|
621
|
-
...AI_IDE_REGISTRY[AIIDEType.UNKNOWN],
|
|
622
|
-
supportedProtocols: [ProtocolType.STDIO, ProtocolType.MCP],
|
|
623
|
-
preferredProtocol: ProtocolType.STDIO,
|
|
624
|
-
},
|
|
625
|
-
confidence: 70,
|
|
626
|
-
detectionMethod: "stdio-analysis",
|
|
627
|
-
};
|
|
628
|
-
}
|
|
629
|
-
return { detected: false };
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* Detect from configuration files
|
|
633
|
-
*/
|
|
634
|
-
static async detectFromConfigFiles() {
|
|
635
|
-
try {
|
|
636
|
-
const fs = await import("fs");
|
|
637
|
-
const { promisify } = await import("util");
|
|
638
|
-
const readFile = promisify(fs.readFile);
|
|
639
|
-
const exists = promisify(fs.exists);
|
|
640
|
-
// Check for Claude Desktop config and verify it contains our server
|
|
641
|
-
const claudeConfigPath = AI_IDE_REGISTRY[AIIDEType.CLAUDE_DESKTOP].configPath;
|
|
642
|
-
if (claudeConfigPath) {
|
|
643
|
-
try {
|
|
644
|
-
const configContent = await readFile(claudeConfigPath, "utf8");
|
|
645
|
-
if (configContent.includes("brave-real-browser-mcp-server") ||
|
|
646
|
-
configContent.includes("brave-browser")) {
|
|
647
|
-
return {
|
|
648
|
-
detected: true,
|
|
649
|
-
ide: AIIDEType.CLAUDE_DESKTOP,
|
|
650
|
-
protocol: ProtocolType.STDIO,
|
|
651
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CLAUDE_DESKTOP],
|
|
652
|
-
confidence: 85,
|
|
653
|
-
detectionMethod: "config-file-content",
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
catch {
|
|
658
|
-
// File might not exist or not readable
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
// Check for Cursor config and verify it contains our server
|
|
662
|
-
const cursorConfigPath = AI_IDE_REGISTRY[AIIDEType.CURSOR].configPath;
|
|
663
|
-
if (cursorConfigPath) {
|
|
664
|
-
try {
|
|
665
|
-
const configContent = await readFile(cursorConfigPath, "utf8");
|
|
666
|
-
if (configContent.includes("brave-real-browser-mcp-server") ||
|
|
667
|
-
configContent.includes("brave-browser")) {
|
|
668
|
-
return {
|
|
669
|
-
detected: true,
|
|
670
|
-
ide: AIIDEType.CURSOR,
|
|
671
|
-
protocol: ProtocolType.STDIO,
|
|
672
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CURSOR],
|
|
673
|
-
confidence: 85,
|
|
674
|
-
detectionMethod: "config-file-content",
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
catch {
|
|
679
|
-
// File might not exist or not readable
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
// Check for Windsurf config
|
|
683
|
-
const windsurfConfigPath = AI_IDE_REGISTRY[AIIDEType.WINDSURF].configPath;
|
|
684
|
-
if (windsurfConfigPath) {
|
|
685
|
-
try {
|
|
686
|
-
const configContent = await readFile(windsurfConfigPath, "utf8");
|
|
687
|
-
if (configContent.includes("brave-real-browser-mcp-server") ||
|
|
688
|
-
configContent.includes("brave-browser")) {
|
|
689
|
-
return {
|
|
690
|
-
detected: true,
|
|
691
|
-
ide: AIIDEType.WINDSURF,
|
|
692
|
-
protocol: ProtocolType.STDIO,
|
|
693
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.WINDSURF],
|
|
694
|
-
confidence: 85,
|
|
695
|
-
detectionMethod: "config-file-content",
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
catch {
|
|
700
|
-
// File might not exist or not readable
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
// Check for Cline config
|
|
704
|
-
const clineConfigPath = AI_IDE_REGISTRY[AIIDEType.CLINE].configPath;
|
|
705
|
-
if (clineConfigPath) {
|
|
706
|
-
try {
|
|
707
|
-
const configContent = await readFile(clineConfigPath, "utf8");
|
|
708
|
-
if (configContent.includes("brave-real-browser-mcp-server") ||
|
|
709
|
-
configContent.includes("brave-browser")) {
|
|
710
|
-
return {
|
|
711
|
-
detected: true,
|
|
712
|
-
ide: AIIDEType.CLINE,
|
|
713
|
-
protocol: ProtocolType.STDIO,
|
|
714
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.CLINE],
|
|
715
|
-
confidence: 85,
|
|
716
|
-
detectionMethod: "config-file-content",
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
catch {
|
|
721
|
-
// File might not exist or not readable
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
catch (error) {
|
|
726
|
-
// Ignore errors in config file detection
|
|
727
|
-
}
|
|
728
|
-
return { detected: false };
|
|
729
|
-
}
|
|
730
|
-
/**
|
|
731
|
-
* Detect from network ports (if HTTP/WebSocket mode)
|
|
732
|
-
*/
|
|
733
|
-
static async detectFromNetworkPorts() {
|
|
734
|
-
// Check if we're listening on a port (HTTP mode)
|
|
735
|
-
// This would mean we're being used as an HTTP API server
|
|
736
|
-
return { detected: false };
|
|
737
|
-
}
|
|
738
|
-
/**
|
|
739
|
-
* Get recommended protocol for detected IDE
|
|
740
|
-
*/
|
|
741
|
-
static getRecommendedProtocol(ideType) {
|
|
742
|
-
return AI_IDE_REGISTRY[ideType].preferredProtocol;
|
|
743
|
-
}
|
|
744
|
-
/**
|
|
745
|
-
* Check if IDE supports a specific protocol
|
|
746
|
-
*/
|
|
747
|
-
static supportsProtocol(ideType, protocol) {
|
|
748
|
-
return AI_IDE_REGISTRY[ideType].supportedProtocols.includes(protocol);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
/**
|
|
752
|
-
* Universal AI IDE Adapter
|
|
753
|
-
* Automatically adapts to any AI IDE
|
|
754
|
-
*/
|
|
755
|
-
export class UniversalIDEAdapter {
|
|
756
|
-
config;
|
|
757
|
-
detectionResult;
|
|
758
|
-
constructor(config = {}) {
|
|
759
|
-
this.config = {
|
|
760
|
-
enableAutoDetection: config.enableAutoDetection !== false,
|
|
761
|
-
fallbackToHttp: config.fallbackToHttp !== false,
|
|
762
|
-
httpPort: config.httpPort || 3000,
|
|
763
|
-
logDetectionDetails: config.logDetectionDetails !== false,
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
/**
|
|
767
|
-
* Initialize and detect IDE
|
|
768
|
-
*/
|
|
769
|
-
async initialize() {
|
|
770
|
-
if (!this.config.enableAutoDetection) {
|
|
771
|
-
// Use default fallback
|
|
772
|
-
this.detectionResult = {
|
|
773
|
-
detected: true,
|
|
774
|
-
ide: AIIDEType.UNKNOWN,
|
|
775
|
-
protocol: ProtocolType.HTTP,
|
|
776
|
-
capabilities: AI_IDE_REGISTRY[AIIDEType.UNKNOWN],
|
|
777
|
-
confidence: 50,
|
|
778
|
-
detectionMethod: "disabled",
|
|
779
|
-
};
|
|
780
|
-
return this.detectionResult;
|
|
781
|
-
}
|
|
782
|
-
this.detectionResult = await UniversalIDEDetector.detectIDE();
|
|
783
|
-
if (this.config.logDetectionDetails) {
|
|
784
|
-
this.logDetectionInfo(this.detectionResult);
|
|
785
|
-
}
|
|
786
|
-
return this.detectionResult;
|
|
787
|
-
}
|
|
788
|
-
/**
|
|
789
|
-
* Get detection result
|
|
790
|
-
*/
|
|
791
|
-
getDetectionResult() {
|
|
792
|
-
return this.detectionResult;
|
|
793
|
-
}
|
|
794
|
-
/**
|
|
795
|
-
* Check if adapter is ready
|
|
796
|
-
*/
|
|
797
|
-
isReady() {
|
|
798
|
-
return !!this.detectionResult;
|
|
799
|
-
}
|
|
800
|
-
/**
|
|
801
|
-
* Log detection information
|
|
802
|
-
*/
|
|
803
|
-
logDetectionInfo(result) {
|
|
804
|
-
console.error("");
|
|
805
|
-
console.error("═══════════════════════════════════════════════════════════");
|
|
806
|
-
console.error("🤖 Universal AI IDE Adapter - Detection Results");
|
|
807
|
-
console.error("═══════════════════════════════════════════════════════════");
|
|
808
|
-
console.error(`✓ IDE: ${result.capabilities.name}`);
|
|
809
|
-
console.error(`✓ Type: ${result.ide}`);
|
|
810
|
-
console.error(`✓ Protocol: ${result.protocol.toUpperCase()}`);
|
|
811
|
-
console.error(`✓ Confidence: ${result.confidence}%`);
|
|
812
|
-
console.error(`✓ Method: ${result.detectionMethod}`);
|
|
813
|
-
console.error(`✓ Supported Protocols: ${result.capabilities.supportedProtocols.join(", ")}`);
|
|
814
|
-
console.error(`✓ Auto-detectable: ${result.capabilities.autoDetectable ? "Yes" : "No"}`);
|
|
815
|
-
if (result.confidence >= 85) {
|
|
816
|
-
console.error("✓ Status: ✅ HIGH CONFIDENCE - Auto-detected successfully");
|
|
817
|
-
}
|
|
818
|
-
else if (result.confidence >= 70) {
|
|
819
|
-
console.error("✓ Status: ⚠️ MEDIUM CONFIDENCE - Likely detected correctly");
|
|
820
|
-
}
|
|
821
|
-
else {
|
|
822
|
-
console.error("✓ Status: ℹ️ LOW CONFIDENCE - Using fallback protocol");
|
|
823
|
-
}
|
|
824
|
-
console.error("═══════════════════════════════════════════════════════════");
|
|
825
|
-
console.error("");
|
|
826
|
-
}
|
|
827
|
-
/**
|
|
828
|
-
* Get supported IDEs list
|
|
829
|
-
*/
|
|
830
|
-
static getSupportedIDEs() {
|
|
831
|
-
return Object.values(AI_IDE_REGISTRY)
|
|
832
|
-
.filter((ide) => ide.type !== AIIDEType.UNKNOWN)
|
|
833
|
-
.map((ide) => ide.name);
|
|
834
|
-
}
|
|
835
|
-
/**
|
|
836
|
-
* Print supported IDEs
|
|
837
|
-
*/
|
|
838
|
-
static printSupportedIDEs() {
|
|
839
|
-
console.error("");
|
|
840
|
-
console.error("═══════════════════════════════════════════════════════════");
|
|
841
|
-
console.error("🌐 Supported AI IDEs (Universal Compatibility)");
|
|
842
|
-
console.error("═══════════════════════════════════════════════════════════");
|
|
843
|
-
Object.values(AI_IDE_REGISTRY)
|
|
844
|
-
.filter((ide) => ide.type !== AIIDEType.UNKNOWN)
|
|
845
|
-
.forEach((ide) => {
|
|
846
|
-
console.error(`✓ ${ide.name.padEnd(30)} [${ide.supportedProtocols.join(", ")}]`);
|
|
847
|
-
});
|
|
848
|
-
console.error("═══════════════════════════════════════════════════════════");
|
|
849
|
-
console.error("💡 All IDEs supported with automatic protocol detection!");
|
|
850
|
-
console.error("═══════════════════════════════════════════════════════════");
|
|
851
|
-
console.error("");
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
// Export for use in other modules
|
|
855
|
-
export default UniversalIDEAdapter;
|