@@ -273,7 +273,6 @@ def add(server_name, force=False, alias=None, target: str | None = None):
273273 required_args = {}
274274 # Process variables to store in config
275275 processed_variables = {}
276- processed_env = {}
277276
278277 # First, prompt for all defined arguments even if they're not in env_vars
279278 progress .stop ()
@@ -343,28 +342,15 @@ def add(server_name, force=False, alias=None, target: str | None = None):
343342 progress .start ()
344343 progress .add_task (f"Configuring { server_name } ..." , total = None )
345344
346- # Now process the replacement of environment variables
347- for key , value in env_vars .items ():
348- if isinstance (value , str ) and value .startswith ("${" ) and value .endswith ("}" ):
349- # Extract the variable name from ${VAR_NAME}
350- env_var_name = value [2 :- 1 ]
351- # Use empty string as default when key not found
352- processed_env [key ] = processed_variables .get (env_var_name , "" )
353- else :
354- processed_env [key ] = value
355-
356345 # replace arguments with values
357346 processed_args = []
358347 for arg in install_args :
359- # check if the argument contains a variable
360- matched = re .search (r"\$\{([^}]+)\}" , arg )
361- if matched :
362- original , key = matched .group (0 ), matched .group (1 )
363- # Use empty string as default when key not found
364- replaced_arg = arg .replace (original , processed_variables .get (key , "" ))
365- processed_args .append (replaced_arg )
366- else :
367- processed_args .append (arg )
348+ processed_args .append (_replace_variables (arg , processed_variables ))
349+
350+ # process environment variables
351+ processed_env = {}
352+ for key , value in env_vars .items ():
353+ processed_env [key ] = _replace_variables (value , processed_variables )
368354
369355 # Get actual MCP execution command, args, and env from the selected installation method
370356 # This ensures we use the actual server command information instead of placeholders
@@ -425,3 +411,25 @@ def _should_hide_input(arg_name: str) -> bool:
425411 bool: True if input should be hidden, False otherwise
426412 """
427413 return "token" in arg_name .lower () or "key" in arg_name .lower () or "secret" in arg_name .lower ()
414+
415+
416+ def _replace_variables (value : str , variables : dict ) -> str :
417+ """Replace ${VAR} patterns in a string with values from variables dict.
418+
419+ Args:
420+ value: String that may contain ${VAR} patterns
421+ variables: Dictionary of variable names to values
422+
423+ Returns:
424+ String with all variables replaced (empty string for missing variables)
425+ """
426+ if not isinstance (value , str ):
427+ return value
428+
429+ # check if the value contains a variable
430+ matched = re .search (r"\$\{([^}]+)\}" , value )
431+ if matched :
432+ original , var_name = matched .group (0 ), matched .group (1 )
433+ # Use empty string as default when key not found
434+ return value .replace (original , variables .get (var_name , "" ))
435+ return value
0 commit comments