Skip to content

Commit 4e84be7

Browse files
refactor(cli): extract MCP remove handlers to cli_mcp
1 parent 4484e67 commit 4e84be7

File tree

2 files changed

+288
-174
lines changed

2 files changed

+288
-174
lines changed

hatch/cli/cli_mcp.py

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)