Skip to content

Commit 1933351

Browse files
author
LittleCoinCoin
committed
fix(mcp): clear type field during transport switching
Fix partial update bug where type field is not cleared when switching between command-based and URL-based server configurations. Ensure type field is updated to match the new transport configuration. When switching from command to URL: type changes from 'stdio' to 'sse' When switching from URL to command: type changes from 'sse' to 'stdio' Includes 2 new tests validating type field updates and 2 modified tests adding type field assertions to existing switching tests. Fixes: Issue 1 - Type field not updated during transport switching
1 parent a7e21d2 commit 1933351

File tree

2 files changed

+114
-4
lines changed

2 files changed

+114
-4
lines changed

hatch/cli_hatch.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,11 +733,13 @@ def handle_mcp_configure(host: str, server_name: str, command: str, args: list,
733733
if url is not None and existing_config.command is not None:
734734
existing_data.pop('command', None)
735735
existing_data.pop('args', None)
736+
existing_data.pop('type', None) # Clear type field when switching transports (Issue 1)
736737

737738
# If switching from URL to command: clear URL-based fields
738739
if command is not None and existing_config.url is not None:
739740
existing_data.pop('url', None)
740741
existing_data.pop('headers', None)
742+
existing_data.pop('type', None) # Clear type field when switching transports (Issue 1)
741743

742744
# Merge: new values override existing values
743745
merged_data = {**existing_data, **omni_config_data}

tests/test_mcp_cli_partial_updates.py

Lines changed: 112 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,9 +460,9 @@ def test_configure_switch_command_to_url(self):
460460
mock_manager.configure_server.return_value = MagicMock(success=True)
461461

462462
with patch('hatch.cli_hatch.print') as mock_print:
463-
# Execute: Switch to URL-based
463+
# Execute: Switch to URL-based (use gemini which supports URL)
464464
result = handle_mcp_configure(
465-
host="claude-desktop",
465+
host="gemini",
466466
server_name="test-server",
467467
command=None,
468468
args=None,
@@ -493,6 +493,8 @@ def test_configure_switch_command_to_url(self):
493493
# Command-based fields cleared
494494
self.assertIsNone(omni_config.command)
495495
self.assertIsNone(omni_config.args)
496+
# Type field updated to 'sse' (Issue 1)
497+
self.assertEqual(omni_config.type, "sse")
496498

497499
@regression_test
498500
def test_configure_switch_url_to_command(self):
@@ -511,9 +513,9 @@ def test_configure_switch_url_to_command(self):
511513
mock_manager.configure_server.return_value = MagicMock(success=True)
512514

513515
with patch('hatch.cli_hatch.print') as mock_print:
514-
# Execute: Switch to command-based
516+
# Execute: Switch to command-based (use gemini which supports both)
515517
result = handle_mcp_configure(
516-
host="claude-desktop",
518+
host="gemini",
517519
server_name="test-server",
518520
command="node", # Provide command
519521
args=["server.js"], # Provide args
@@ -544,6 +546,8 @@ def test_configure_switch_url_to_command(self):
544546
# URL-based fields cleared
545547
self.assertIsNone(omni_config.url)
546548
self.assertIsNone(omni_config.headers)
549+
# Type field updated to 'stdio' (Issue 1)
550+
self.assertEqual(omni_config.type, "stdio")
547551

548552

549553
class TestPartialUpdateIntegration(unittest.TestCase):
@@ -746,6 +750,110 @@ def test_error_messages_remain_clear(self):
746750
)
747751

748752

753+
class TestTypeFieldUpdating(unittest.TestCase):
754+
"""Test suite for type field updates during transport switching (Issue 1)."""
755+
756+
@regression_test
757+
def test_type_field_updates_command_to_url(self):
758+
"""Test type field updates from 'stdio' to 'sse' when switching to URL."""
759+
# Setup: Create existing command-based server with type='stdio'
760+
existing_server = MCPServerConfig(
761+
name="test-server",
762+
type="stdio",
763+
command="python",
764+
args=["server.py"]
765+
)
766+
767+
with patch('hatch.cli_hatch.MCPHostConfigurationManager') as mock_manager_class:
768+
mock_manager = MagicMock()
769+
mock_manager_class.return_value = mock_manager
770+
mock_manager.get_server_config.return_value = existing_server
771+
mock_manager.configure_server.return_value = MagicMock(success=True)
772+
773+
with patch('hatch.cli_hatch.print'):
774+
# Execute: Switch to URL-based configuration
775+
result = handle_mcp_configure(
776+
host='gemini',
777+
server_name='test-server',
778+
command=None,
779+
args=None,
780+
env=None,
781+
url='http://localhost:8080',
782+
headers=None,
783+
timeout=None,
784+
trust=False,
785+
cwd=None,
786+
env_file=None,
787+
http_url=None,
788+
include_tools=None,
789+
exclude_tools=None,
790+
inputs=None,
791+
no_backup=False,
792+
dry_run=False,
793+
auto_approve=True
794+
)
795+
796+
# Validate: Should succeed
797+
self.assertEqual(result, 0)
798+
799+
# Validate: Type field updated to 'sse'
800+
call_args = mock_manager.configure_server.call_args
801+
server_config = call_args.kwargs['server_config']
802+
self.assertEqual(server_config.type, "sse")
803+
self.assertIsNone(server_config.command)
804+
self.assertEqual(server_config.url, "http://localhost:8080")
805+
806+
@regression_test
807+
def test_type_field_updates_url_to_command(self):
808+
"""Test type field updates from 'sse' to 'stdio' when switching to command."""
809+
# Setup: Create existing URL-based server with type='sse'
810+
existing_server = MCPServerConfig(
811+
name="test-server",
812+
type="sse",
813+
url="http://localhost:8080",
814+
headers={"Authorization": "Bearer token"}
815+
)
816+
817+
with patch('hatch.cli_hatch.MCPHostConfigurationManager') as mock_manager_class:
818+
mock_manager = MagicMock()
819+
mock_manager_class.return_value = mock_manager
820+
mock_manager.get_server_config.return_value = existing_server
821+
mock_manager.configure_server.return_value = MagicMock(success=True)
822+
823+
with patch('hatch.cli_hatch.print'):
824+
# Execute: Switch to command-based configuration
825+
result = handle_mcp_configure(
826+
host='gemini',
827+
server_name='test-server',
828+
command='python',
829+
args=['server.py'],
830+
env=None,
831+
url=None,
832+
headers=None,
833+
timeout=None,
834+
trust=False,
835+
cwd=None,
836+
env_file=None,
837+
http_url=None,
838+
include_tools=None,
839+
exclude_tools=None,
840+
inputs=None,
841+
no_backup=False,
842+
dry_run=False,
843+
auto_approve=True
844+
)
845+
846+
# Validate: Should succeed
847+
self.assertEqual(result, 0)
848+
849+
# Validate: Type field updated to 'stdio'
850+
call_args = mock_manager.configure_server.call_args
851+
server_config = call_args.kwargs['server_config']
852+
self.assertEqual(server_config.type, "stdio")
853+
self.assertEqual(server_config.command, "python")
854+
self.assertIsNone(server_config.url)
855+
856+
749857
if __name__ == '__main__':
750858
unittest.main()
751859

0 commit comments

Comments
 (0)