@@ -857,3 +857,253 @@ def handle_mcp_configure(args: Namespace) -> int:
857857 except Exception as e :
858858 print (f"Error configuring MCP server: { e } " )
859859 return EXIT_ERROR
860+
861+
862+ def handle_mcp_remove (
863+ host : str ,
864+ server_name : str ,
865+ no_backup : bool = False ,
866+ dry_run : bool = False ,
867+ auto_approve : bool = False ,
868+ ) -> int :
869+ """Handle 'hatch mcp remove' command.
870+
871+ Removes an MCP server configuration from a specific host.
872+
873+ Args:
874+ host: Target host identifier (e.g., 'claude-desktop', 'vscode')
875+ server_name: Name of the server to remove
876+ no_backup: If True, skip creating backup before removal
877+ dry_run: If True, show what would be done without making changes
878+ auto_approve: If True, skip confirmation prompt
879+
880+ Returns:
881+ int: EXIT_SUCCESS (0) on success, EXIT_ERROR (1) on failure
882+ """
883+ from hatch .cli .cli_utils import request_confirmation
884+
885+ try :
886+ # Validate host type
887+ try :
888+ host_type = MCPHostType (host )
889+ except ValueError :
890+ print (
891+ f"Error: Invalid host '{ host } '. Supported hosts: { [h .value for h in MCPHostType ]} "
892+ )
893+ return EXIT_ERROR
894+
895+ if dry_run :
896+ print (
897+ f"[DRY RUN] Would remove MCP server '{ server_name } ' from host '{ host } '"
898+ )
899+ print (f"[DRY RUN] Backup: { 'Disabled' if no_backup else 'Enabled' } " )
900+ return EXIT_SUCCESS
901+
902+ # Confirm operation unless auto-approved
903+ if not request_confirmation (
904+ f"Remove MCP server '{ server_name } ' from host '{ host } '?" , auto_approve
905+ ):
906+ print ("Operation cancelled." )
907+ return EXIT_SUCCESS
908+
909+ # Perform removal
910+ mcp_manager = MCPHostConfigurationManager ()
911+ result = mcp_manager .remove_server (
912+ server_name = server_name , hostname = host , no_backup = no_backup
913+ )
914+
915+ if result .success :
916+ print (
917+ f"[SUCCESS] Successfully removed MCP server '{ server_name } ' from host '{ host } '"
918+ )
919+ if result .backup_path :
920+ print (f" Backup created: { result .backup_path } " )
921+ return EXIT_SUCCESS
922+ else :
923+ print (
924+ f"[ERROR] Failed to remove MCP server '{ server_name } ' from host '{ host } ': { result .error_message } "
925+ )
926+ return EXIT_ERROR
927+
928+ except Exception as e :
929+ print (f"Error removing MCP server: { e } " )
930+ return EXIT_ERROR
931+
932+
933+ def handle_mcp_remove_server (
934+ env_manager : HatchEnvironmentManager ,
935+ server_name : str ,
936+ hosts : Optional [str ] = None ,
937+ env : Optional [str ] = None ,
938+ no_backup : bool = False ,
939+ dry_run : bool = False ,
940+ auto_approve : bool = False ,
941+ ) -> int :
942+ """Handle 'hatch mcp remove server' command.
943+
944+ Removes an MCP server from multiple hosts.
945+
946+ Args:
947+ env_manager: Environment manager instance for tracking
948+ server_name: Name of the server to remove
949+ hosts: Comma-separated list of target hosts
950+ env: Environment name (for environment-based removal)
951+ no_backup: If True, skip creating backups
952+ dry_run: If True, show what would be done without making changes
953+ auto_approve: If True, skip confirmation prompt
954+
955+ Returns:
956+ int: EXIT_SUCCESS (0) on success, EXIT_ERROR (1) on failure
957+ """
958+ from hatch .cli .cli_utils import request_confirmation , parse_host_list
959+
960+ try :
961+ # Determine target hosts
962+ if hosts :
963+ target_hosts = parse_host_list (hosts )
964+ elif env :
965+ # TODO: Implement environment-based server removal
966+ print ("Error: Environment-based removal not yet implemented" )
967+ return EXIT_ERROR
968+ else :
969+ print ("Error: Must specify either --host or --env" )
970+ return EXIT_ERROR
971+
972+ if not target_hosts :
973+ print ("Error: No valid hosts specified" )
974+ return EXIT_ERROR
975+
976+ if dry_run :
977+ print (
978+ f"[DRY RUN] Would remove MCP server '{ server_name } ' from hosts: { ', ' .join (target_hosts )} "
979+ )
980+ print (f"[DRY RUN] Backup: { 'Disabled' if no_backup else 'Enabled' } " )
981+ return EXIT_SUCCESS
982+
983+ # Confirm operation unless auto-approved
984+ hosts_str = ", " .join (target_hosts )
985+ if not request_confirmation (
986+ f"Remove MCP server '{ server_name } ' from hosts: { hosts_str } ?" , auto_approve
987+ ):
988+ print ("Operation cancelled." )
989+ return EXIT_SUCCESS
990+
991+ # Perform removal on each host
992+ mcp_manager = MCPHostConfigurationManager ()
993+ success_count = 0
994+ total_count = len (target_hosts )
995+
996+ for host in target_hosts :
997+ result = mcp_manager .remove_server (
998+ server_name = server_name , hostname = host , no_backup = no_backup
999+ )
1000+
1001+ if result .success :
1002+ print (f"[SUCCESS] Successfully removed '{ server_name } ' from '{ host } '" )
1003+ if result .backup_path :
1004+ print (f" Backup created: { result .backup_path } " )
1005+ success_count += 1
1006+
1007+ # Update environment tracking for current environment only
1008+ current_env = env_manager .get_current_environment ()
1009+ if current_env :
1010+ env_manager .remove_package_host_configuration (
1011+ current_env , server_name , host
1012+ )
1013+ else :
1014+ print (
1015+ f"[ERROR] Failed to remove '{ server_name } ' from '{ host } ': { result .error_message } "
1016+ )
1017+
1018+ # Summary
1019+ if success_count == total_count :
1020+ print (f"[SUCCESS] Removed '{ server_name } ' from all { total_count } hosts" )
1021+ return EXIT_SUCCESS
1022+ elif success_count > 0 :
1023+ print (
1024+ f"[PARTIAL SUCCESS] Removed '{ server_name } ' from { success_count } /{ total_count } hosts"
1025+ )
1026+ return EXIT_ERROR
1027+ else :
1028+ print (f"[ERROR] Failed to remove '{ server_name } ' from any hosts" )
1029+ return EXIT_ERROR
1030+
1031+ except Exception as e :
1032+ print (f"Error removing MCP server: { e } " )
1033+ return EXIT_ERROR
1034+
1035+
1036+ def handle_mcp_remove_host (
1037+ env_manager : HatchEnvironmentManager ,
1038+ host_name : str ,
1039+ no_backup : bool = False ,
1040+ dry_run : bool = False ,
1041+ auto_approve : bool = False ,
1042+ ) -> int :
1043+ """Handle 'hatch mcp remove host' command.
1044+
1045+ Removes entire host configuration (all MCP servers from a host).
1046+
1047+ Args:
1048+ env_manager: Environment manager instance for tracking
1049+ host_name: Name of the host to remove configuration from
1050+ no_backup: If True, skip creating backup
1051+ dry_run: If True, show what would be done without making changes
1052+ auto_approve: If True, skip confirmation prompt
1053+
1054+ Returns:
1055+ int: EXIT_SUCCESS (0) on success, EXIT_ERROR (1) on failure
1056+ """
1057+ from hatch .cli .cli_utils import request_confirmation
1058+
1059+ try :
1060+ # Validate host type
1061+ try :
1062+ host_type = MCPHostType (host_name )
1063+ except ValueError :
1064+ print (
1065+ f"Error: Invalid host '{ host_name } '. Supported hosts: { [h .value for h in MCPHostType ]} "
1066+ )
1067+ return EXIT_ERROR
1068+
1069+ if dry_run :
1070+ print (f"[DRY RUN] Would remove entire host configuration for '{ host_name } '" )
1071+ print (f"[DRY RUN] Backup: { 'Disabled' if no_backup else 'Enabled' } " )
1072+ return EXIT_SUCCESS
1073+
1074+ # Confirm operation unless auto-approved
1075+ if not request_confirmation (
1076+ f"Remove entire host configuration for '{ host_name } '? This will remove ALL MCP servers from this host." ,
1077+ auto_approve ,
1078+ ):
1079+ print ("Operation cancelled." )
1080+ return EXIT_SUCCESS
1081+
1082+ # Perform host configuration removal
1083+ mcp_manager = MCPHostConfigurationManager ()
1084+ result = mcp_manager .remove_host_configuration (
1085+ hostname = host_name , no_backup = no_backup
1086+ )
1087+
1088+ if result .success :
1089+ print (
1090+ f"[SUCCESS] Successfully removed host configuration for '{ host_name } '"
1091+ )
1092+ if result .backup_path :
1093+ print (f" Backup created: { result .backup_path } " )
1094+
1095+ # Update environment tracking across all environments
1096+ updates_count = env_manager .clear_host_from_all_packages_all_envs (host_name )
1097+ if updates_count > 0 :
1098+ print (f"Updated { updates_count } package entries across environments" )
1099+
1100+ return EXIT_SUCCESS
1101+ else :
1102+ print (
1103+ f"[ERROR] Failed to remove host configuration for '{ host_name } ': { result .error_message } "
1104+ )
1105+ return EXIT_ERROR
1106+
1107+ except Exception as e :
1108+ print (f"Error removing host configuration: { e } " )
1109+ return EXIT_ERROR
0 commit comments