1- import { confirm , select } from "@inquirer/prompts" ;
1+ import { select } from "@inquirer/prompts" ;
22import chalk from "chalk" ;
33import { Command } from "commander" ;
4- import JSON5 from "json5 " ;
4+ import { parse as parseJSON , stringify as stringifyJSON } from "comment-json " ;
55import { mkdir , readFile , writeFile } from "node:fs/promises" ;
66import { dirname , join , relative } from "node:path" ;
77import ora , { type Ora } from "ora" ;
@@ -117,50 +117,31 @@ export const mcpAction = async (options: {
117117 `Reading configuration file: ${ chalk . cyan ( displayConfigPath ) } ...` ,
118118 ) . start ( ) ;
119119 let editorConfig : any = { } ;
120- try {
121- if ( await fileExists ( configPath ) ) {
122- const content = await readFile ( configPath , "utf-8" ) ;
123- // Attempt to parse JSON, handle potential comments if needed
124- try {
125- editorConfig = JSON5 . parse ( content ) ;
126- } catch ( parseError ) {
127- spinner . fail (
128- `Failed to parse configuration file ${ chalk . cyan ( displayConfigPath ) } .` ,
129- ) ;
130- throw parseError ; // Re-throw original error if cleaning fails
131- }
132- spinner . succeed ( "Configuration file read." ) ;
133- } else {
134- spinner . info ( "Configuration file not found, will create a new one." ) ;
135- editorConfig = { } ; // Initialize empty config if file doesn't exist
136- }
137- } catch ( error : any ) {
138- // Handle file access errors separately from parsing errors
139- if ( error . code !== "ENOENT" ) {
140- // ENOENT means file not found, which is handled above
141- spinner . fail ( "Failed to read configuration file." ) ;
142- console . error (
143- chalk . red ( `Error reading ${ displayConfigPath } : ${ error . message } ` ) ,
120+ if ( await fileExists ( configPath ) ) {
121+ const content = await readFile ( configPath , "utf-8" ) ;
122+ // Attempt to parse JSON, handle potential comments if needed
123+ try {
124+ editorConfig = parseJSON ( content ) ;
125+ } catch {
126+ spinner . fail (
127+ `Failed to parse configuration file ${ chalk . cyan ( displayConfigPath ) } .` ,
144128 ) ;
145- const proceed = await confirm ( {
146- message : "Reading failed. Attempt to overwrite the file?" ,
147- default : false ,
148- } ) ;
149- if ( ! proceed ) return ;
150- editorConfig = { } ; // Start fresh if reading failed and user agreed
151- } else {
152- // This case should ideally be caught by the fileExists check, but handle defensively
153- spinner . info ( "Configuration file not found, creating a new one." ) ;
154- editorConfig = { } ;
155129 }
130+ spinner . succeed (
131+ `Read configuration file ${ chalk . cyan ( displayConfigPath ) } .` ,
132+ ) ;
133+ } else {
134+ spinner . info ( "Configuration file not found, will create a new one." ) ;
135+ editorConfig = { } ; // Initialize empty config if file doesn't exist
156136 }
157137
158- // Ensure mcpServers object exists and get existing Bucket entries
138+ // Ensure MCP servers object exists
159139 const serversConfig = getServersConfig (
160140 editorConfig ,
161141 selectedEditor ,
162142 configPathType ,
163143 ) ;
144+ // Check for existing Bucket servers
164145 const existingBucketEntries = Object . keys ( serversConfig ) . filter ( ( key ) =>
165146 / b u c k e t / i. test ( key ) ,
166147 ) ;
@@ -203,10 +184,10 @@ export const mcpAction = async (options: {
203184
204185 const newEntryValue = {
205186 type : "stdio" ,
206- command : "npx" , // Assuming npx is standard
187+ command : "npx" ,
207188 args : [
208- "mcp-remote@next" , // Use the specified package
209- mcpUrlWithAppId , // Always include appId explicitly
189+ "mcp-remote@next" , // todo: remove next once stable
190+ mcpUrlWithAppId , // Always include appId explicitly as that is more stable
210191 ] ,
211192 } ;
212193
@@ -220,7 +201,7 @@ export const mcpAction = async (options: {
220201 try {
221202 // Ensure the directory exists before writing
222203 await mkdir ( dirname ( configPath ) , { recursive : true } ) ;
223- const configString = JSON . stringify ( editorConfig , null , 2 ) ; // Pretty print JSON
204+ const configString = stringifyJSON ( editorConfig , null , 2 ) ;
224205 await writeFile ( configPath , configString ) ;
225206 spinner . succeed (
226207 `Configuration updated successfully in ${ chalk . cyan ( displayConfigPath ) } .` ,
@@ -231,7 +212,9 @@ export const mcpAction = async (options: {
231212 ) ,
232213 ) ;
233214 } catch ( error ) {
234- spinner . fail ( "Failed to write configuration file." ) ;
215+ spinner . fail (
216+ `Failed to write configuration file ${ chalk . cyan ( displayConfigPath ) } .` ,
217+ ) ;
235218 void handleError ( error , "MCP Configuration" ) ;
236219 }
237220} ;
0 commit comments