@@ -8,6 +8,7 @@ type CliCheck = {
88 command : string
99 add : ( ) => void
1010 run : ( ) => { ok : boolean ; output : string }
11+ cleanup ?: ( ) => void
1112}
1213
1314const requiredEnv = [ 'TRANSLOADIT_KEY' , 'TRANSLOADIT_SECRET' ]
@@ -21,6 +22,7 @@ if (envMissing.length > 0) {
2122const endpoint = process . env . TRANSLOADIT_ENDPOINT ?? 'https://api2.transloadit.com'
2223const commandTimeoutMs = Number ( process . env . MCP_VERIFY_TIMEOUT_MS ?? 60_000 )
2324const serverName = process . env . MCP_SERVER_NAME ?? 'transloadit'
25+ const allowlistedTools = [ 'transloadit_list_templates' ]
2426const serverCommand = [
2527 'npm' ,
2628 'exec' ,
@@ -105,14 +107,17 @@ const runClaude = (prompt: string, expectedTemplateId: string): CliCheck => ({
105107 throw new Error ( `claude mcp add failed: ${ result . stderr || result . stdout } ` )
106108 }
107109 } ,
110+ cleanup : ( ) => {
111+ runCommand ( 'claude' , [ 'mcp' , 'remove' , serverName ] )
112+ } ,
108113 run : ( ) => {
109114 const result = runCommand ( 'claude' , [
110115 '-p' ,
111116 prompt ,
112117 '--output-format' ,
113118 'json' ,
114119 '--allowedTools' ,
115- 'transloadit_list_templates' ,
120+ `mcp__ ${ serverName } ` ,
116121 '--permission-mode' ,
117122 'acceptEdits' ,
118123 ] )
@@ -143,6 +148,10 @@ const runCodex = (prompt: string, expectedTemplateId: string): CliCheck => ({
143148 if ( result . status !== 0 ) {
144149 throw new Error ( `codex mcp add failed: ${ result . stderr || result . stdout } ` )
145150 }
151+ updateCodexEnabledTools ( )
152+ } ,
153+ cleanup : ( ) => {
154+ runCommand ( 'codex' , [ 'mcp' , 'remove' , serverName ] )
146155 } ,
147156 run : ( ) => {
148157 const result = runCommand ( 'codex' , [ 'exec' , '--full-auto' , '--json' , prompt ] )
@@ -181,13 +190,74 @@ const ensureGeminiSettings = (): void => {
181190 TRANSLOADIT_SECRET : process . env . TRANSLOADIT_SECRET ?? '' ,
182191 TRANSLOADIT_ENDPOINT : endpoint ,
183192 } ,
193+ includeTools : allowlistedTools ,
184194 }
185195
186196 settings . mcpServers = mcpServers
187197 console . log ( `Writing Gemini MCP config to ${ settingsPath } using current env credentials.` )
188198 writeFileSync ( settingsPath , `${ JSON . stringify ( settings , null , 2 ) } \n` )
189199}
190200
201+ const cleanupGeminiSettings = ( ) : void => {
202+ const cwd = process . cwd ( )
203+ const settingsPath = join ( homedir ( ) , '.gemini' , 'settings.json' )
204+ if ( settingsPath . startsWith ( `${ cwd } /` ) ) {
205+ return
206+ }
207+ if ( ! existsSync ( settingsPath ) ) {
208+ return
209+ }
210+ let settings : Record < string , unknown > = { }
211+ try {
212+ settings = JSON . parse ( readFileSync ( settingsPath , 'utf8' ) ) as Record < string , unknown >
213+ } catch {
214+ return
215+ }
216+ const mcpServers = ( settings . mcpServers as Record < string , unknown > ) ?? { }
217+ if ( ! ( serverName in mcpServers ) ) {
218+ return
219+ }
220+ delete mcpServers [ serverName ]
221+ settings . mcpServers = mcpServers
222+ writeFileSync ( settingsPath , `${ JSON . stringify ( settings , null , 2 ) } \n` )
223+ }
224+
225+ const updateCodexEnabledTools = ( ) : void => {
226+ const configPath = join ( homedir ( ) , '.codex' , 'config.toml' )
227+ if ( ! existsSync ( configPath ) ) {
228+ return
229+ }
230+ const content = readFileSync ( configPath , 'utf8' )
231+ const header = `[mcp_servers.${ serverName } ]`
232+ const lines = content . split ( '\n' )
233+ const headerIndex = lines . findIndex ( ( line ) => line . trim ( ) === header )
234+ if ( headerIndex === - 1 ) {
235+ return
236+ }
237+ let endIndex = lines . length
238+ for ( let i = headerIndex + 1 ; i < lines . length ; i += 1 ) {
239+ if ( lines [ i ] . startsWith ( '[' ) ) {
240+ endIndex = i
241+ break
242+ }
243+ }
244+
245+ const enabledLine = `enabled_tools = [${ allowlistedTools . map ( ( tool ) => `"${ tool } "` ) . join ( ', ' ) } ]`
246+ let replaced = false
247+ for ( let i = headerIndex + 1 ; i < endIndex ; i += 1 ) {
248+ if ( lines [ i ] . trim ( ) . startsWith ( 'enabled_tools' ) ) {
249+ lines [ i ] = enabledLine
250+ replaced = true
251+ break
252+ }
253+ }
254+ if ( ! replaced ) {
255+ lines . splice ( headerIndex + 1 , 0 , enabledLine )
256+ }
257+
258+ writeFileSync ( configPath , `${ lines . join ( '\n' ) } \n` )
259+ }
260+
191261const runGemini = ( prompt : string , expectedTemplateId : string ) : CliCheck => ( {
192262 name : 'Gemini CLI' ,
193263 command : 'gemini' ,
@@ -217,6 +287,10 @@ const runGemini = (prompt: string, expectedTemplateId: string): CliCheck => ({
217287 return
218288 }
219289 } ,
290+ cleanup : ( ) => {
291+ runCommand ( 'gemini' , [ 'mcp' , 'remove' , serverName ] )
292+ cleanupGeminiSettings ( )
293+ } ,
220294 run : ( ) => {
221295 const result = runCommand ( 'gemini' , [
222296 '--prompt' ,
@@ -261,6 +335,8 @@ const main = async (): Promise<void> => {
261335 ok : false ,
262336 output : error instanceof Error ? error . message : String ( error ) ,
263337 } )
338+ } finally {
339+ check . cleanup ?.( )
264340 }
265341 }
266342
0 commit comments