Skip to content

Commit 4268d4e

Browse files
author
LittleCoinCoin
committed
feat: implement partial update merge logic in CLI handler
- Add server existence check before validation in handle_mcp_configure() - Implement conditional validation: create requires command/url, update does not - Add partial update merge logic that preserves unspecified fields - Implement command/URL switching behavior with auto-clear of opposite field type - When switching command→url: clear command and args - When switching url→command: clear url and headers - Fix headers condition to allow updates without requiring url parameter - Pass old_config to reporting system for UNCHANGED field detection - Dynamically set operation type ('update' vs 'create') based on server existence - Maintains backward compatibility with existing create operations
1 parent 7b53e42 commit 4268d4e

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

hatch/cli_hatch.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,18 @@ def handle_mcp_configure(host: str, server_name: str, command: str, args: list,
650650
# The reporting system will show unsupported fields as "UNSUPPORTED" in the conversion report.
651651
# This allows users to see which fields are not supported by their target host without blocking the operation.
652652

653+
# Check if server exists (for partial update support)
654+
manager = MCPHostConfigurationManager()
655+
existing_config = manager.get_server_config(host, server_name)
656+
is_update = existing_config is not None
657+
658+
# Conditional validation: Create requires command OR url, update does not
659+
if not is_update:
660+
# Create operation: require command or url
661+
if not command and not url:
662+
print(f"Error: When creating a new server, you must provide either --command (for local servers) or --url (for remote servers)")
663+
return 1
664+
653665
# Parse environment variables, headers, and inputs
654666
env_dict = parse_env_vars(env)
655667
headers_dict = parse_headers(headers)
@@ -667,7 +679,7 @@ def handle_mcp_configure(host: str, server_name: str, command: str, args: list,
667679
omni_config_data['env'] = env_dict
668680
if url is not None:
669681
omni_config_data['url'] = url
670-
if url and headers_dict:
682+
if headers_dict:
671683
omni_config_data['headers'] = headers_dict
672684

673685
# Host-specific fields (Gemini)
@@ -692,6 +704,26 @@ def handle_mcp_configure(host: str, server_name: str, command: str, args: list,
692704
if inputs_list is not None:
693705
omni_config_data['inputs'] = inputs_list
694706

707+
# Partial update merge logic
708+
if is_update:
709+
# Merge with existing configuration
710+
existing_data = existing_config.model_dump(exclude_unset=True, exclude={'name'})
711+
712+
# Handle command/URL switching behavior
713+
# If switching from command to URL: clear command-based fields
714+
if url is not None and existing_config.command is not None:
715+
existing_data.pop('command', None)
716+
existing_data.pop('args', None)
717+
718+
# If switching from URL to command: clear URL-based fields
719+
if command is not None and existing_config.url is not None:
720+
existing_data.pop('url', None)
721+
existing_data.pop('headers', None)
722+
723+
# Merge: new values override existing values
724+
merged_data = {**existing_data, **omni_config_data}
725+
omni_config_data = merged_data
726+
695727
# Create Omni model
696728
omni_config = MCPServerConfigOmni(**omni_config_data)
697729

@@ -706,10 +738,11 @@ def handle_mcp_configure(host: str, server_name: str, command: str, args: list,
706738

707739
# Generate conversion report
708740
report = generate_conversion_report(
709-
operation='create',
741+
operation='update' if is_update else 'create',
710742
server_name=server_name,
711743
target_host=host_type,
712744
omni=omni_config,
745+
old_config=existing_config if is_update else None,
713746
dry_run=dry_run
714747
)
715748

0 commit comments

Comments
 (0)