Skip to content

Commit 2a6f754

Browse files
committed
cleaned up code for opening editors
1 parent bc877d8 commit 2a6f754

2 files changed

Lines changed: 89 additions & 39 deletions

File tree

src/setup/aiTool.ts

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import fs from "fs";
33
import path from "path";
44
import os from "os";
55
import { applyEdits, findNodeAtLocation, modify, parseTree } from "jsonc-parser";
6+
import { exec } from "child_process";
67
import type { Platform } from "./setupAiToolsUtils.js";
78
import { formatError, getPlatform } from "./setupAiToolsUtils.js";
89

@@ -11,6 +12,19 @@ export type AIToolType = "cursor" | "vscode" | "windsurf" | "claudeDesktop" | "c
1112
// These are tools that don't have a designated editor to open the config file
1213
export const TOOLS_WITHOUT_EDITORS: AIToolType[] = ["claudeDesktop", "claudeCode", "opencode"];
1314

15+
// Mac: open path in default app, or in editor (e.g. "cursor") if supported
16+
const getOpenCommandMac = (configPath: string, editor: AIToolType): string =>
17+
editor && !TOOLS_WITHOUT_EDITORS.includes(editor) ? `open "${editor}://file${configPath}"` : `open "${configPath}"`;
18+
19+
// Linux: open path in default app, or in editor if supported
20+
const getOpenCommandLinux = (configPath: string, editor: AIToolType): string =>
21+
editor && !TOOLS_WITHOUT_EDITORS.includes(editor)
22+
? `xdg-open "${editor}://file${configPath}"`
23+
: `xdg-open "${configPath}"`;
24+
25+
// Windows: open path in default app (for tools without a dedicated editor)
26+
const getOpenCommandWindowsDefault = (configPath: string): string => `start "" "${configPath}"`;
27+
1428
const MCP_SERVER_KEY = "mongodb-mcp-server";
1529
type EnvironmentKey = "env" | "environment";
1630
type McpConfigEntry = {
@@ -143,7 +157,8 @@ const updateConfigInPlace = (
143157
};
144158

145159
export abstract class AITool {
146-
abstract name: string;
160+
abstract name: string; // readable name for the tool for users
161+
abstract toolType: AIToolType; // used internallly
147162
abstract configFileName: string;
148163
abstract get configPath(): string;
149164
tip?: string;
@@ -217,19 +232,57 @@ export abstract class AITool {
217232
writeConfigFile(configPath, config);
218233
}
219234
}
235+
236+
/**
237+
* Returns the shell command to open the config file. Override in subclasses for editor-specific behavior.
238+
*/
239+
getOpenConfigCommand(configPath: string, platform: Platform, editor: AIToolType): string | null {
240+
switch (platform) {
241+
case "mac":
242+
return getOpenCommandMac(configPath, editor);
243+
case "windows":
244+
return getOpenCommandWindowsDefault(configPath);
245+
case "linux":
246+
return getOpenCommandLinux(configPath, editor);
247+
default:
248+
return null;
249+
}
250+
}
251+
252+
openConfigSettings(): void {
253+
const platform = getPlatform();
254+
if (!platform) return;
255+
const cmd = this.getOpenConfigCommand(this.configPath, platform, this.toolType);
256+
if (cmd) exec(cmd);
257+
}
220258
}
221259

222260
class Cursor extends AITool {
223261
name = "Cursor";
262+
toolType = "cursor" as AIToolType;
224263
configFileName = "mcp.json";
225264
get configPath(): string {
226265
return path.join(getBasePath(), ".cursor", "mcp.json");
227266
}
228267
tip = `Tip: Press ${getPlatform() === "mac" ? "Cmd+I" : "Ctrl+I"} in Cursor to open the Agent panel.\n`;
268+
269+
override getOpenConfigCommand(configPath: string, platform: Platform): string | null {
270+
switch (platform) {
271+
case "mac":
272+
return getOpenCommandMac(configPath, "cursor");
273+
case "windows":
274+
return `cursor "${configPath}"`;
275+
case "linux":
276+
return getOpenCommandLinux(configPath, "cursor");
277+
default:
278+
return null;
279+
}
280+
}
229281
}
230282

231283
class VSCode extends AITool {
232284
name = "VS Code";
285+
toolType = "vscode" as AIToolType;
233286
configFileName = "mcp.json";
234287
protected override getServersKey(): McpServers {
235288
return "servers";
@@ -252,10 +305,24 @@ class VSCode extends AITool {
252305
return "";
253306
}
254307
tip = `Tip: Press ${getPlatform() === "mac" ? "Cmd+Shift+I" : "Ctrl+Shift+I"} in VS Code to open the Copilot panel.\n`;
308+
309+
override getOpenConfigCommand(configPath: string, platform: Platform): string | null {
310+
switch (platform) {
311+
case "mac":
312+
return getOpenCommandMac(configPath, "vscode");
313+
case "windows":
314+
return `code "${configPath}"`;
315+
case "linux":
316+
return getOpenCommandLinux(configPath, "vscode");
317+
default:
318+
return null;
319+
}
320+
}
255321
}
256322

257323
class Windsurf extends AITool {
258324
name = "Windsurf";
325+
toolType = "windsurf" as AIToolType;
259326
configFileName = "mcp_config.json";
260327
get configPath(): string {
261328
const platform: Platform | null = getPlatform();
@@ -272,10 +339,23 @@ class Windsurf extends AITool {
272339
return "";
273340
}
274341
tip = `Tip: Press ${getPlatform() === "mac" ? "Cmd+L" : "Ctrl+L"} in Windsurf to open the AI panel.\n`;
342+
getOpenConfigCommand(configPath: string, platform: Platform): string | null {
343+
switch (platform) {
344+
case "mac":
345+
return getOpenCommandMac(configPath, "windsurf");
346+
case "windows":
347+
return `windsurf "${configPath}"`;
348+
case "linux":
349+
return getOpenCommandLinux(configPath, "windsurf");
350+
default:
351+
return null;
352+
}
353+
}
275354
}
276355

277356
class ClaudeDesktop extends AITool {
278357
name = "Claude Desktop";
358+
toolType = "claudeDesktop" as AIToolType;
279359
configFileName = "claude_desktop_config.json";
280360
get configPath(): string {
281361
const platform: Platform | null = getPlatform();
@@ -298,6 +378,7 @@ class ClaudeDesktop extends AITool {
298378

299379
class ClaudeCode extends AITool {
300380
name = "Claude Code";
381+
toolType = "claudeCode" as AIToolType;
301382
configFileName = ".claude.json";
302383
get configPath(): string {
303384
return path.join(getBasePath(), ".claude.json");
@@ -306,6 +387,7 @@ class ClaudeCode extends AITool {
306387

307388
class OpenCode extends AITool {
308389
name = "Open Code";
390+
toolType = "opencode" as AIToolType;
309391
configFileName = "opencode.json";
310392
get configPath(): string {
311393
return path.join(getBasePath(), ".config", "opencode", "opencode.json");
@@ -330,6 +412,11 @@ class OpenCode extends AITool {
330412
}
331413
}
332414

415+
// Opens the config file for the given tool using the tool's platform-specific command.
416+
export const openConfigSettings = (tool: AIToolType): void => {
417+
AI_TOOL_REGISTRY[tool].openConfigSettings();
418+
};
419+
333420
export const AI_TOOL_REGISTRY: Record<AIToolType, AITool> = {
334421
["cursor"]: new Cursor(),
335422
["vscode"]: new VSCode(),

src/setup/setupMcpServer.ts

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,53 +2,16 @@
22
import select from "@inquirer/select";
33
import { input, confirm, password } from "@inquirer/prompts";
44
import path from "path";
5-
import { exec } from "child_process";
65
import chalk from "chalk";
76
import semver from "semver";
87
import { NodeDriverServiceProvider } from "@mongosh/service-provider-node-driver";
98
import type { AIToolType } from "./aiTool.js";
10-
import { AI_TOOL_REGISTRY, TOOLS_WITHOUT_EDITORS } from "./aiTool.js";
9+
import { AI_TOOL_REGISTRY, openConfigSettings, TOOLS_WITHOUT_EDITORS } from "./aiTool.js";
1110
import { formatError, getPlatform } from "./setupAiToolsUtils.js";
1211
import { packageInfo } from "../common/packageInfo.js";
1312
import { getAuthType } from "../common/connectionInfo.js";
1413
import { type UserConfig } from "../common/config/userConfig.js";
1514

16-
const openConfigSettings = (tool: AIToolType): void => {
17-
const configPath = AI_TOOL_REGISTRY[tool].configPath;
18-
const platform = getPlatform();
19-
20-
if (TOOLS_WITHOUT_EDITORS.includes(tool)) {
21-
switch (platform) {
22-
case "mac":
23-
exec(`open "${configPath}"`);
24-
break;
25-
case "windows":
26-
exec(`start "" "${configPath}"`);
27-
break;
28-
case "linux":
29-
exec(`xdg-open "${configPath}"`);
30-
break;
31-
default:
32-
break;
33-
}
34-
} else {
35-
const editor = tool;
36-
switch (platform) {
37-
case "mac":
38-
exec(`open "${editor}://file${configPath}"`);
39-
break;
40-
case "windows":
41-
exec(`start "" "${editor}://file${configPath}"`);
42-
break;
43-
case "linux":
44-
exec(`xdg-open "${editor}://file${configPath}"`);
45-
break;
46-
default:
47-
break;
48-
}
49-
}
50-
};
51-
5215
const buildEnvObject = (
5316
connectionString: string,
5417
serviceWorkerId: string,

0 commit comments

Comments
 (0)