From 79c063304b97c3bc172085c4dcccc155e3b7f363 Mon Sep 17 00:00:00 2001 From: Olivia Date: Mon, 21 Apr 2025 14:45:53 -0400 Subject: [PATCH 1/8] Add VS Code support --- README.md | 1 + src/config.ts | 26 ++++++++++++++++++++------ src/index.ts | 2 +- src/types.ts | 9 +++++++-- src/utils.ts | 51 ++++++++++++++++++++++++++++++++++++++++----------- 5 files changed, 69 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 7aeba31..109bd36 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ npx @magicuidesign/cli@latest install ### Supported Clients +- [x] vscode - [x] cursor - [x] windsurf - [x] claude diff --git a/src/config.ts b/src/config.ts index 4e725b1..72cdf5b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -39,6 +39,12 @@ export const clientPaths: Record = { ), windsurf: path.join(homeDir, ".codeium", "windsurf", "mcp_config.json"), cursor: path.join(homeDir, ".cursor", "mcp.json"), + vscode: path.join( + baseDir, + vscodePath, + "..", + "settings.json", + ), }; export const createPlatformCommand = (passedArgs: string[]) => { @@ -54,13 +60,21 @@ export const createPlatformCommand = (passedArgs: string[]) => { }; }; -export const getDefaultConfig = () => { +export const getDefaultConfig = (client?: string) => { const args = ["-y", "@magicuidesign/mcp@latest"]; const command = createPlatformCommand(args); - return { - mcpServers: { - "@magicuidesign/mcp": command, - }, - }; + return client === "vscode" + ? { + mcp: { + servers: { + "@magicuidesign/mcp": command, + }, + }, + } + : { + mcpServers: { + "@magicuidesign/mcp": command, + }, + }; }; diff --git a/src/index.ts b/src/index.ts index 6b980c7..5d27623 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,7 @@ export async function install(client: ValidClient): Promise { ).start(); try { - const config = { ...getDefaultConfig() }; + const config = getDefaultConfig(client); writeConfig(client, config); spinner.succeed( diff --git a/src/types.ts b/src/types.ts index 841db21..aeb3445 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,7 +3,8 @@ export type ValidClient = | "cline" | "roo-cline" | "windsurf" - | "cursor"; + | "cursor" + | "vscode"; export const VALID_CLIENTS: ValidClient[] = [ "claude", @@ -11,6 +12,7 @@ export const VALID_CLIENTS: ValidClient[] = [ "roo-cline", "windsurf", "cursor", + "vscode", ]; export interface ServerConfig { @@ -19,7 +21,10 @@ export interface ServerConfig { } export interface ClientConfig { - mcpServers: Record; + mcpServers?: Record; + mcp?: { + servers: Record; + }; } export interface InstallOptions { diff --git a/src/utils.ts b/src/utils.ts index bfbecad..47a26af 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -15,17 +15,24 @@ export function readConfig(client: ValidClient): ClientConfig { const configPath = getConfigPath(client); if (!fs.existsSync(configPath)) { - return { mcpServers: {} }; + return client === "vscode" ? { mcp: { servers: {} } } : { mcpServers: {} }; } try { const rawConfig = JSON.parse(fs.readFileSync(configPath, "utf8")); + if (client === "vscode") { + return { + mcp: { + servers: (rawConfig.mcp && rawConfig.mcp.servers) || {}, + }, + }; + } return { ...rawConfig, mcpServers: rawConfig.mcpServers || {}, }; } catch (error) { - return { mcpServers: {} }; + return client === "vscode" ? { mcp: { servers: {} } } : { mcpServers: {} }; } } @@ -37,11 +44,19 @@ export function writeConfig(client: ValidClient, config: ClientConfig): void { fs.mkdirSync(configDir, { recursive: true }); } - if (!config.mcpServers || typeof config.mcpServers !== "object") { + // Validate config structure + if (client === "vscode") { + if (!config.mcp?.servers || typeof config.mcp.servers !== "object") { + throw new Error("Invalid mcp.servers structure for vscode"); + } + } else if (!config.mcpServers || typeof config.mcpServers !== "object") { throw new Error("Invalid mcpServers structure"); } - let existingConfig: ClientConfig = { mcpServers: {} }; + let existingConfig: ClientConfig = client === "vscode" + ? { mcp: { servers: {} } } + : { mcpServers: {} }; + try { if (fs.existsSync(configPath)) { existingConfig = JSON.parse(fs.readFileSync(configPath, "utf8")); @@ -50,13 +65,27 @@ export function writeConfig(client: ValidClient, config: ClientConfig): void { // If reading fails, continue with empty existing config } - const mergedConfig = { - ...existingConfig, - mcpServers: { - ...existingConfig.mcpServers, - ...config.mcpServers, - }, - }; + let mergedConfig; + if (client === "vscode" && config.mcp?.servers) { + mergedConfig = { + ...existingConfig, + mcp: { + ...existingConfig.mcp, + servers: { + ...(existingConfig.mcp?.servers || {}), + ...config.mcp.servers, + }, + }, + }; + } else if (config.mcpServers) { + mergedConfig = { + ...existingConfig, + mcpServers: { + ...existingConfig.mcpServers, + ...config.mcpServers, + }, + }; + } fs.writeFileSync(configPath, JSON.stringify(mergedConfig, null, 2)); } From 9dc87944d6884cf242c84e29f2bc5ca377ea53a6 Mon Sep 17 00:00:00 2001 From: Olivia Date: Thu, 24 Apr 2025 15:46:56 -0400 Subject: [PATCH 2/8] cleaner refactor --- src/config.ts | 21 +++++----------- src/index.ts | 2 +- src/types.ts | 5 +--- src/utils.ts | 67 ++++++++++++++++++--------------------------------- 4 files changed, 32 insertions(+), 63 deletions(-) diff --git a/src/config.ts b/src/config.ts index 72cdf5b..561a554 100644 --- a/src/config.ts +++ b/src/config.ts @@ -60,21 +60,12 @@ export const createPlatformCommand = (passedArgs: string[]) => { }; }; -export const getDefaultConfig = (client?: string) => { +export const getDefaultConfig = () => { const args = ["-y", "@magicuidesign/mcp@latest"]; const command = createPlatformCommand(args); - - return client === "vscode" - ? { - mcp: { - servers: { - "@magicuidesign/mcp": command, - }, - }, - } - : { - mcpServers: { - "@magicuidesign/mcp": command, - }, - }; + return { + mcpServers: { + "@magicuidesign/mcp": command, + }, + }; }; diff --git a/src/index.ts b/src/index.ts index 5d27623..a972eaa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,7 @@ export async function install(client: ValidClient): Promise { ).start(); try { - const config = getDefaultConfig(client); + const config = getDefaultConfig(); writeConfig(client, config); spinner.succeed( diff --git a/src/types.ts b/src/types.ts index aeb3445..098cb37 100644 --- a/src/types.ts +++ b/src/types.ts @@ -21,10 +21,7 @@ export interface ServerConfig { } export interface ClientConfig { - mcpServers?: Record; - mcp?: { - servers: Record; - }; + mcpServers: Record; } export interface InstallOptions { diff --git a/src/utils.ts b/src/utils.ts index 47a26af..770bdb9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -15,24 +15,23 @@ export function readConfig(client: ValidClient): ClientConfig { const configPath = getConfigPath(client); if (!fs.existsSync(configPath)) { - return client === "vscode" ? { mcp: { servers: {} } } : { mcpServers: {} }; + return { mcpServers: {} }; } try { const rawConfig = JSON.parse(fs.readFileSync(configPath, "utf8")); - if (client === "vscode") { + // Convert VS Code format to internal format if needed + if (client === "vscode" && rawConfig.mcp?.servers) { return { - mcp: { - servers: (rawConfig.mcp && rawConfig.mcp.servers) || {}, - }, + mcpServers: rawConfig.mcp.servers }; } + // For all other clients or if VS Code config is already in mcpServers format return { - ...rawConfig, - mcpServers: rawConfig.mcpServers || {}, + mcpServers: rawConfig.mcpServers || {} }; } catch (error) { - return client === "vscode" ? { mcp: { servers: {} } } : { mcpServers: {} }; + return { mcpServers: {} }; } } @@ -44,19 +43,7 @@ export function writeConfig(client: ValidClient, config: ClientConfig): void { fs.mkdirSync(configDir, { recursive: true }); } - // Validate config structure - if (client === "vscode") { - if (!config.mcp?.servers || typeof config.mcp.servers !== "object") { - throw new Error("Invalid mcp.servers structure for vscode"); - } - } else if (!config.mcpServers || typeof config.mcpServers !== "object") { - throw new Error("Invalid mcpServers structure"); - } - - let existingConfig: ClientConfig = client === "vscode" - ? { mcp: { servers: {} } } - : { mcpServers: {} }; - + let existingConfig: any = {}; try { if (fs.existsSync(configPath)) { existingConfig = JSON.parse(fs.readFileSync(configPath, "utf8")); @@ -65,27 +52,21 @@ export function writeConfig(client: ValidClient, config: ClientConfig): void { // If reading fails, continue with empty existing config } - let mergedConfig; - if (client === "vscode" && config.mcp?.servers) { - mergedConfig = { - ...existingConfig, - mcp: { - ...existingConfig.mcp, - servers: { - ...(existingConfig.mcp?.servers || {}), - ...config.mcp.servers, - }, - }, - }; - } else if (config.mcpServers) { - mergedConfig = { - ...existingConfig, - mcpServers: { - ...existingConfig.mcpServers, - ...config.mcpServers, - }, - }; - } + const mergedServers = { + ...existingConfig.mcpServers, + ...config.mcpServers + }; + + // For VS Code, preserve all existing settings and just update mcp.servers + const finalConfig = client === "vscode" + ? { + ...existingConfig, + mcp: { + ...(existingConfig.mcp || {}), + servers: mergedServers + } + } + : { mcpServers: mergedServers }; - fs.writeFileSync(configPath, JSON.stringify(mergedConfig, null, 2)); + fs.writeFileSync(configPath, JSON.stringify(finalConfig, null, 2)); } From 3da49e0d23ab9eb8b26f309bc24121d7a43de93c Mon Sep 17 00:00:00 2001 From: Olivia Date: Thu, 24 Apr 2025 15:54:54 -0400 Subject: [PATCH 3/8] more refactoring --- src/config.ts | 1 + src/index.ts | 2 +- src/utils.ts | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/config.ts b/src/config.ts index 561a554..abbf428 100644 --- a/src/config.ts +++ b/src/config.ts @@ -63,6 +63,7 @@ export const createPlatformCommand = (passedArgs: string[]) => { export const getDefaultConfig = () => { const args = ["-y", "@magicuidesign/mcp@latest"]; const command = createPlatformCommand(args); + return { mcpServers: { "@magicuidesign/mcp": command, diff --git a/src/index.ts b/src/index.ts index a972eaa..6b980c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,7 @@ export async function install(client: ValidClient): Promise { ).start(); try { - const config = getDefaultConfig(); + const config = { ...getDefaultConfig() }; writeConfig(client, config); spinner.succeed( diff --git a/src/utils.ts b/src/utils.ts index 770bdb9..6181786 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -26,9 +26,9 @@ export function readConfig(client: ValidClient): ClientConfig { mcpServers: rawConfig.mcp.servers }; } - // For all other clients or if VS Code config is already in mcpServers format return { - mcpServers: rawConfig.mcpServers || {} + ...rawConfig, + mcpServers: rawConfig.mcpServers || {}, }; } catch (error) { return { mcpServers: {} }; From 01f4528cdf2d27bf986eacb68e756874a17e9074 Mon Sep 17 00:00:00 2001 From: Olivia Date: Thu, 24 Apr 2025 15:56:37 -0400 Subject: [PATCH 4/8] spacing difference --- src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index abbf428..91b0f8a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -63,7 +63,7 @@ export const createPlatformCommand = (passedArgs: string[]) => { export const getDefaultConfig = () => { const args = ["-y", "@magicuidesign/mcp@latest"]; const command = createPlatformCommand(args); - + return { mcpServers: { "@magicuidesign/mcp": command, From 7aa99396e42edb3d4d991f21c67b0276b6fbb2e6 Mon Sep 17 00:00:00 2001 From: Olivia Date: Fri, 25 Apr 2025 10:34:09 -0400 Subject: [PATCH 5/8] fix for merging servers --- src/utils.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 6181786..743f173 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -52,8 +52,16 @@ export function writeConfig(client: ValidClient, config: ClientConfig): void { // If reading fails, continue with empty existing config } + const mergedConfig = { + ...existingConfig, + mcpServers: { + ...existingConfig.mcpServers, + ...config.mcpServers, + }, + }; + const mergedServers = { - ...existingConfig.mcpServers, + ...existingConfig.mcp?.servers, ...config.mcpServers }; @@ -66,7 +74,7 @@ export function writeConfig(client: ValidClient, config: ClientConfig): void { servers: mergedServers } } - : { mcpServers: mergedServers }; + : mergedConfig; fs.writeFileSync(configPath, JSON.stringify(finalConfig, null, 2)); } From 309cfe279f6941dcaec62c93fb6782efcd55cc81 Mon Sep 17 00:00:00 2001 From: Olivia Date: Fri, 25 Apr 2025 10:36:52 -0400 Subject: [PATCH 6/8] remove unnecessary check --- src/utils.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 743f173..3dc3527 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -20,12 +20,6 @@ export function readConfig(client: ValidClient): ClientConfig { try { const rawConfig = JSON.parse(fs.readFileSync(configPath, "utf8")); - // Convert VS Code format to internal format if needed - if (client === "vscode" && rawConfig.mcp?.servers) { - return { - mcpServers: rawConfig.mcp.servers - }; - } return { ...rawConfig, mcpServers: rawConfig.mcpServers || {}, From e1fa222d0ddf0a81a0dca0c4b9ba7dc2fe20330c Mon Sep 17 00:00:00 2001 From: Olivia Date: Fri, 25 Apr 2025 10:40:03 -0400 Subject: [PATCH 7/8] add in structure check --- src/utils.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils.ts b/src/utils.ts index 3dc3527..db11898 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -37,6 +37,10 @@ export function writeConfig(client: ValidClient, config: ClientConfig): void { fs.mkdirSync(configDir, { recursive: true }); } + if (!config.mcpServers || typeof config.mcpServers !== "object") { + throw new Error("Invalid mcpServers structure"); + } + let existingConfig: any = {}; try { if (fs.existsSync(configPath)) { From b9053aff418177379b40e52f4e809465a67d84cd Mon Sep 17 00:00:00 2001 From: Olivia Date: Fri, 25 Apr 2025 10:42:52 -0400 Subject: [PATCH 8/8] minor fix --- src/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index db11898..9da17f4 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -68,7 +68,7 @@ export function writeConfig(client: ValidClient, config: ClientConfig): void { ? { ...existingConfig, mcp: { - ...(existingConfig.mcp || {}), + ...existingConfig.mcp, servers: mergedServers } }