@@ -184,31 +184,65 @@ def handle_mcp_discover_servers(env_manager: HatchEnvironmentManager, env_name:
184184 print (f"Error discovering servers: { e } " )
185185 return 1
186186
187- def handle_mcp_list_hosts ():
188- """Handle 'hatch mcp list hosts' command."""
187+ def handle_mcp_list_hosts (env_manager : HatchEnvironmentManager , env_name : Optional [ str ] = None , detailed : bool = False ):
188+ """Handle 'hatch mcp list hosts' command - shows configured hosts in environment ."""
189189 try :
190- # Import strategies to trigger registration
191- import hatch .mcp_host_config .strategies
190+ from collections import defaultdict
192191
193- available_hosts = MCPHostRegistry . detect_available_hosts ()
194- all_hosts = list ( MCPHostType )
192+ # Resolve environment name
193+ target_env = env_name or env_manager . get_current_environment ( )
195194
196- print ("MCP host platforms status:" )
197- print (f"{ 'Host Platform' :<20} { 'Status' :<15} { 'Config Path' } " )
198- print ("-" * 70 )
195+ # Validate environment exists
196+ if not env_manager .environment_exists (target_env ):
197+ available_envs = env_manager .list_environments ()
198+ print (f"Error: Environment '{ target_env } ' does not exist." )
199+ if available_envs :
200+ print (f"Available environments: { ', ' .join (available_envs )} " )
201+ return 1
199202
200- for host_type in all_hosts :
201- try :
202- strategy = MCPHostRegistry .get_strategy (host_type )
203- config_path = strategy .get_config_path ()
204- is_available = host_type in available_hosts
203+ # Collect hosts from configured_hosts across all packages in environment
204+ hosts = defaultdict (int )
205+ host_details = defaultdict (list )
205206
206- status = "Available" if is_available else "Not detected"
207- config_display = str (config_path ) if config_path else "N/A"
207+ try :
208+ env_data = env_manager .get_environment_data (target_env )
209+ packages = env_data .get ("packages" , [])
208210
209- print (f"{ host_type .value :<20} { status :<15} { config_display } " )
210- except Exception as e :
211- print (f"{ host_type .value :<20} { 'Error' :<15} { str (e )} " )
211+ for package in packages :
212+ package_name = package .get ("name" , "unknown" )
213+ configured_hosts = package .get ("configured_hosts" , {})
214+
215+ for host_name , host_config in configured_hosts .items ():
216+ hosts [host_name ] += 1
217+ if detailed :
218+ config_path = host_config .get ("config_path" , "N/A" )
219+ configured_at = host_config .get ("configured_at" , "N/A" )
220+ host_details [host_name ].append ({
221+ "package" : package_name ,
222+ "config_path" : config_path ,
223+ "configured_at" : configured_at
224+ })
225+
226+ except Exception as e :
227+ print (f"Error reading environment data: { e } " )
228+ return 1
229+
230+ # Display results
231+ if not hosts :
232+ print (f"No configured hosts for environment '{ target_env } '" )
233+ return 0
234+
235+ print (f"Configured hosts for environment '{ target_env } ':" )
236+
237+ for host_name , package_count in sorted (hosts .items ()):
238+ if detailed :
239+ print (f"\n { host_name } ({ package_count } packages):" )
240+ for detail in host_details [host_name ]:
241+ print (f" - Package: { detail ['package' ]} " )
242+ print (f" Config path: { detail ['config_path' ]} " )
243+ print (f" Configured at: { detail ['configured_at' ]} " )
244+ else :
245+ print (f" - { host_name } ({ package_count } packages)" )
212246
213247 return 0
214248 except Exception as e :
@@ -303,7 +337,7 @@ def __init__(self, data):
303337 print (f"Error listing servers: { e } " )
304338 return 1
305339
306- def handle_mcp_backup_restore (host : str , backup_file : Optional [str ] = None , dry_run : bool = False , auto_approve : bool = False ):
340+ def handle_mcp_backup_restore (env_manager : HatchEnvironmentManager , host : str , backup_file : Optional [str ] = None , dry_run : bool = False , auto_approve : bool = False ):
307341 """Handle 'hatch mcp backup restore' command."""
308342 try :
309343 from hatch .mcp_host_config .backup import MCPHostConfigBackupManager
@@ -349,6 +383,34 @@ def handle_mcp_backup_restore(host: str, backup_file: Optional[str] = None, dry_
349383
350384 if success :
351385 print (f"[SUCCESS] Successfully restored backup '{ backup_file } ' for host '{ host } '" )
386+
387+ # Read restored configuration to get actual server list
388+ try :
389+ # Import strategies to trigger registration
390+ import hatch .mcp_host_config .strategies
391+
392+ host_type = MCPHostType (host )
393+ strategy = MCPHostRegistry .get_strategy (host_type )
394+ restored_config = strategy .read_configuration ()
395+
396+ # Get servers dict from restored configuration
397+ if hasattr (restored_config , 'get_servers_dict' ):
398+ restored_servers = restored_config .get_servers_dict ()
399+ elif hasattr (restored_config , 'mcpServers' ):
400+ # Handle Claude Desktop format
401+ restored_servers = restored_config .mcpServers or {}
402+ else :
403+ # Fallback - try to get servers as dict
404+ restored_servers = getattr (restored_config , 'servers' , {})
405+
406+ # Update environment tracking to match restored state
407+ updates_count = env_manager .apply_restored_host_configuration_to_environments (host , restored_servers )
408+ if updates_count > 0 :
409+ print (f"Synchronized { updates_count } package entries with restored configuration" )
410+
411+ except Exception as e :
412+ print (f"Warning: Could not synchronize environment tracking: { e } " )
413+
352414 return 0
353415 else :
354416 print (f"[ERROR] Failed to restore backup '{ backup_file } ' for host '{ host } '" )
@@ -663,7 +725,7 @@ def parse_host_list(host_arg: str) -> List[str]:
663725
664726 return hosts
665727
666- def handle_mcp_remove_server (server_name : str , hosts : Optional [str ] = None ,
728+ def handle_mcp_remove_server (env_manager : HatchEnvironmentManager , server_name : str , hosts : Optional [str ] = None ,
667729 env : Optional [str ] = None , no_backup : bool = False ,
668730 dry_run : bool = False , auto_approve : bool = False ):
669731 """Handle 'hatch mcp remove server' command."""
@@ -714,6 +776,11 @@ def handle_mcp_remove_server(server_name: str, hosts: Optional[str] = None,
714776 if result .backup_path :
715777 print (f" Backup created: { result .backup_path } " )
716778 success_count += 1
779+
780+ # Update environment tracking for current environment only
781+ current_env = env_manager .get_current_environment ()
782+ if current_env :
783+ env_manager .remove_package_host_configuration (current_env , server_name , host )
717784 else :
718785 print (f"[ERROR] Failed to remove '{ server_name } ' from '{ host } ': { result .error_message } " )
719786
@@ -732,7 +799,7 @@ def handle_mcp_remove_server(server_name: str, hosts: Optional[str] = None,
732799 print (f"Error removing MCP server: { e } " )
733800 return 1
734801
735- def handle_mcp_remove_host (host_name : str , no_backup : bool = False ,
802+ def handle_mcp_remove_host (env_manager : HatchEnvironmentManager , host_name : str , no_backup : bool = False ,
736803 dry_run : bool = False , auto_approve : bool = False ):
737804 """Handle 'hatch mcp remove host' command."""
738805 try :
@@ -767,6 +834,12 @@ def handle_mcp_remove_host(host_name: str, no_backup: bool = False,
767834 print (f"[SUCCESS] Successfully removed host configuration for '{ host_name } '" )
768835 if result .backup_path :
769836 print (f" Backup created: { result .backup_path } " )
837+
838+ # Update environment tracking across all environments
839+ updates_count = env_manager .clear_host_from_all_packages_all_envs (host_name )
840+ if updates_count > 0 :
841+ print (f"Updated { updates_count } package entries across environments" )
842+
770843 return 0
771844 else :
772845 print (f"[ERROR] Failed to remove host configuration for '{ host_name } ': { result .error_message } " )
@@ -982,7 +1055,9 @@ def main():
9821055 )
9831056
9841057 # List hosts command
985- mcp_list_hosts_parser = mcp_list_subparsers .add_parser ("hosts" , help = "List detected MCP host platforms with status" )
1058+ mcp_list_hosts_parser = mcp_list_subparsers .add_parser ("hosts" , help = "List configured MCP hosts from environment" )
1059+ mcp_list_hosts_parser .add_argument ("--env" , "-e" , default = None , help = "Environment name (default: current environment)" )
1060+ mcp_list_hosts_parser .add_argument ("--detailed" , action = "store_true" , help = "Show detailed host configuration information" )
9861061
9871062 # List servers command
9881063 mcp_list_servers_parser = mcp_list_subparsers .add_parser ("servers" , help = "List configured MCP servers from environment" )
@@ -1541,7 +1616,7 @@ def main():
15411616
15421617 elif args .mcp_command == "list" :
15431618 if args .list_command == "hosts" :
1544- return handle_mcp_list_hosts ()
1619+ return handle_mcp_list_hosts (env_manager , args . env , args . detailed )
15451620 elif args .list_command == "servers" :
15461621 return handle_mcp_list_servers (env_manager , args .env )
15471622 else :
@@ -1551,7 +1626,7 @@ def main():
15511626 elif args .mcp_command == "backup" :
15521627 if args .backup_command == "restore" :
15531628 return handle_mcp_backup_restore (
1554- args .host , args .backup_file , args .dry_run , args .auto_approve
1629+ env_manager , args .host , args .backup_file , args .dry_run , args .auto_approve
15551630 )
15561631 elif args .backup_command == "list" :
15571632 return handle_mcp_backup_list (args .host , args .detailed )
@@ -1574,12 +1649,12 @@ def main():
15741649 elif args .mcp_command == "remove" :
15751650 if args .remove_command == "server" :
15761651 return handle_mcp_remove_server (
1577- args .server_name , args .host , args .env , args .no_backup ,
1652+ env_manager , args .server_name , args .host , args .env , args .no_backup ,
15781653 args .dry_run , args .auto_approve
15791654 )
15801655 elif args .remove_command == "host" :
15811656 return handle_mcp_remove_host (
1582- args .host_name , args .no_backup ,
1657+ env_manager , args .host_name , args .no_backup ,
15831658 args .dry_run , args .auto_approve
15841659 )
15851660 else :
0 commit comments