Skip to content

Commit 5d84755

Browse files
author
LittleCoinCoin
committed
refactor(cli): rename --headers to --header for consistency
Rename --headers argument to --header to match singular naming convention used by other parameters. Update all test references and documentation. Changes: - Renamed parse_headers() to parse_header() - Updated function parameter from headers to header - Updated argparse argument from --headers to --header - Updated all test files to use new parameter name - Maintained Pydantic model field name as 'headers' (internal) Test Results: 126/128 tests passing (2 pre-existing failures)
1 parent 49e91bc commit 5d84755

File tree

4 files changed

+63
-63
lines changed

4 files changed

+63
-63
lines changed

hatch/cli_hatch.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -568,13 +568,13 @@ def parse_env_vars(env_list: Optional[list]) -> dict:
568568

569569
return env_dict
570570

571-
def parse_headers(headers_list: Optional[list]) -> dict:
571+
def parse_header(header_list: Optional[list]) -> dict:
572572
"""Parse HTTP headers from command line format."""
573-
if not headers_list:
573+
if not header_list:
574574
return {}
575575

576576
headers_dict = {}
577-
for header in headers_list:
577+
for header in header_list:
578578
if '=' not in header:
579579
print(f"Warning: Invalid header format '{header}'. Expected KEY=VALUE")
580580
continue
@@ -618,7 +618,7 @@ def parse_inputs(inputs_list: Optional[list]) -> Optional[list]:
618618

619619
def handle_mcp_configure(host: str, server_name: str, command: str, args: list,
620620
env: Optional[list] = None, url: Optional[str] = None,
621-
headers: Optional[list] = None, timeout: Optional[int] = None,
621+
header: Optional[list] = None, timeout: Optional[int] = None,
622622
trust: bool = False, cwd: Optional[str] = None,
623623
env_file: Optional[str] = None, http_url: Optional[str] = None,
624624
include_tools: Optional[list] = None, exclude_tools: Optional[list] = None,
@@ -645,8 +645,8 @@ def handle_mcp_configure(host: str, server_name: str, command: str, args: list,
645645
return 1
646646

647647
# Validate argument dependencies
648-
if command and headers:
649-
print("Error: --headers can only be used with --url or --http-url (remote servers), not with --command (local servers)")
648+
if command and header:
649+
print("Error: --header can only be used with --url or --http-url (remote servers), not with --command (local servers)")
650650
return 1
651651

652652
if (url or http_url) and args:
@@ -671,7 +671,7 @@ def handle_mcp_configure(host: str, server_name: str, command: str, args: list,
671671

672672
# Parse environment variables, headers, and inputs
673673
env_dict = parse_env_vars(env)
674-
headers_dict = parse_headers(headers)
674+
headers_dict = parse_header(header)
675675
inputs_list = parse_inputs(inputs)
676676

677677
# Create Omni configuration (universal model)
@@ -1268,7 +1268,7 @@ def main():
12681268

12691269
mcp_configure_parser.add_argument("--args", nargs="*", help="Arguments for the MCP server command (only with --command)")
12701270
mcp_configure_parser.add_argument("--env-var", action="append", help="Environment variables (format: KEY=VALUE)")
1271-
mcp_configure_parser.add_argument("--headers", action="append", help="HTTP headers for remote servers (format: KEY=VALUE, only with --url)")
1271+
mcp_configure_parser.add_argument("--header", action="append", help="HTTP headers for remote servers (format: KEY=VALUE, only with --url)")
12721272

12731273
# Host-specific arguments (Gemini)
12741274
mcp_configure_parser.add_argument("--timeout", type=int, help="Request timeout in milliseconds (Gemini)")
@@ -2077,7 +2077,7 @@ def main():
20772077
elif args.mcp_command == "configure":
20782078
return handle_mcp_configure(
20792079
args.host, args.server_name, args.server_command, args.args,
2080-
getattr(args, 'env_var', None), args.url, args.headers,
2080+
getattr(args, 'env_var', None), args.url, args.header,
20812081
getattr(args, 'timeout', None), getattr(args, 'trust', False),
20822082
getattr(args, 'cwd', None), getattr(args, 'env_file', None),
20832083
getattr(args, 'http_url', None), getattr(args, 'include_tools', None),

tests/test_mcp_cli_direct_management.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
from hatch.cli_hatch import (
2121
main, handle_mcp_configure, handle_mcp_remove, handle_mcp_remove_server,
22-
handle_mcp_remove_host, parse_env_vars, parse_headers
22+
handle_mcp_remove_host, parse_env_vars, parse_header
2323
)
2424
from hatch.mcp_host_config.models import MCPHostType, MCPServerConfig
2525
from wobble import regression_test, integration_test
@@ -61,7 +61,7 @@ def test_configure_argument_parsing_with_options(self):
6161
test_args = [
6262
'hatch', 'mcp', 'configure', 'file-server', '--host', 'cursor', '--url', 'http://localhost:8080',
6363
'--env-var', 'API_KEY=secret', '--env-var', 'DEBUG=true',
64-
'--headers', 'Authorization=Bearer token',
64+
'--header', 'Authorization=Bearer token',
6565
'--no-backup', '--dry-run', '--auto-approve'
6666
]
6767

@@ -104,21 +104,21 @@ def test_parse_env_vars(self):
104104
mock_print.assert_called()
105105

106106
@regression_test
107-
def test_parse_headers(self):
107+
def test_parse_header(self):
108108
"""Test HTTP headers parsing utility."""
109109
# Valid headers
110110
headers_list = ['Authorization=Bearer token', 'Content-Type=application/json']
111-
result = parse_headers(headers_list)
112-
111+
result = parse_header(headers_list)
112+
113113
expected = {
114114
'Authorization': 'Bearer token',
115115
'Content-Type': 'application/json'
116116
}
117117
self.assertEqual(result, expected)
118-
118+
119119
# Empty list
120-
self.assertEqual(parse_headers(None), {})
121-
self.assertEqual(parse_headers([]), {})
120+
self.assertEqual(parse_header(None), {})
121+
self.assertEqual(parse_header([]), {})
122122

123123
@integration_test(scope="component")
124124
def test_configure_invalid_host(self):

tests/test_mcp_cli_host_config_integration.py

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def decorator(func):
3131
from hatch.cli_hatch import (
3232
handle_mcp_configure,
3333
parse_env_vars,
34-
parse_headers,
34+
parse_header,
3535
parse_host_list,
3636
)
3737
from hatch.mcp_host_config.models import (
@@ -68,7 +68,7 @@ def test_configure_creates_omni_model_basic(self):
6868
args=['server.py'],
6969
env=None,
7070
url=None,
71-
headers=None,
71+
header=None,
7272
no_backup=True,
7373
dry_run=False,
7474
auto_approve=False
@@ -90,7 +90,7 @@ def test_configure_creates_omni_with_env_vars(self):
9090
args=['server.py'],
9191
env=['API_KEY=secret', 'DEBUG=true'],
9292
url=None,
93-
headers=None,
93+
header=None,
9494
no_backup=True,
9595
dry_run=False,
9696
auto_approve=False
@@ -111,7 +111,7 @@ def test_configure_creates_omni_with_headers(self):
111111
args=None,
112112
env=None,
113113
url='https://api.example.com',
114-
headers=['Authorization=Bearer token', 'Content-Type=application/json'],
114+
header=['Authorization=Bearer token', 'Content-Type=application/json'],
115115
no_backup=True,
116116
dry_run=False,
117117
auto_approve=False
@@ -132,7 +132,7 @@ def test_configure_creates_omni_remote_server(self):
132132
args=None,
133133
env=None,
134134
url='https://api.example.com',
135-
headers=['Auth=token'],
135+
header=['Auth=token'],
136136
no_backup=True,
137137
dry_run=False,
138138
auto_approve=False
@@ -154,7 +154,7 @@ def test_configure_omni_with_all_universal_fields(self):
154154
args=['server.py', '--port', '8080'],
155155
env=['API_KEY=secret', 'DEBUG=true', 'LOG_LEVEL=info'],
156156
url=None,
157-
headers=None,
157+
header=None,
158158
no_backup=True,
159159
dry_run=False,
160160
auto_approve=False
@@ -176,7 +176,7 @@ def test_configure_omni_with_optional_fields_none(self):
176176
args=['server.py'],
177177
env=None,
178178
url=None,
179-
headers=None,
179+
header=None,
180180
no_backup=True,
181181
dry_run=False,
182182
auto_approve=False
@@ -202,7 +202,7 @@ def test_configure_uses_host_model_registry(self):
202202
args=['server.py'],
203203
env=None,
204204
url=None,
205-
headers=None,
205+
header=None,
206206
no_backup=True,
207207
dry_run=False,
208208
auto_approve=False
@@ -224,7 +224,7 @@ def test_configure_calls_from_omni_conversion(self):
224224
args=['server.py'],
225225
env=None,
226226
url=None,
227-
headers=None,
227+
header=None,
228228
no_backup=True,
229229
dry_run=False,
230230
auto_approve=False
@@ -250,7 +250,7 @@ def test_configure_passes_host_specific_model_to_manager(self):
250250
args=['server.py'],
251251
env=None,
252252
url=None,
253-
headers=None,
253+
header=None,
254254
no_backup=True,
255255
dry_run=False,
256256
auto_approve=False
@@ -282,7 +282,7 @@ def test_configure_dry_run_displays_report_only(self):
282282
args=['server.py'],
283283
env=None,
284284
url=None,
285-
headers=None,
285+
header=None,
286286
no_backup=True,
287287
dry_run=True,
288288
auto_approve=False
@@ -312,7 +312,7 @@ def test_configure_accepts_all_universal_fields(self):
312312
args=['server.py', '--port', '8080'],
313313
env=['API_KEY=secret', 'DEBUG=true'],
314314
url=None,
315-
headers=None,
315+
header=None,
316316
no_backup=True,
317317
dry_run=False,
318318
auto_approve=False
@@ -334,7 +334,7 @@ def test_configure_multiple_env_vars(self):
334334
args=['server.py'],
335335
env=['VAR1=value1', 'VAR2=value2', 'VAR3=value3'],
336336
url=None,
337-
headers=None,
337+
header=None,
338338
no_backup=True,
339339
dry_run=False,
340340
auto_approve=False
@@ -359,7 +359,7 @@ def test_configure_different_hosts(self):
359359
args=['server.py'],
360360
env=None,
361361
url=None,
362-
headers=None,
362+
header=None,
363363
no_backup=True,
364364
dry_run=False,
365365
auto_approve=False
@@ -383,7 +383,7 @@ def test_configure_invalid_host_type_error(self):
383383
args=['server.py'],
384384
env=None,
385385
url=None,
386-
headers=None,
386+
header=None,
387387
no_backup=True,
388388
dry_run=False,
389389
auto_approve=False
@@ -404,7 +404,7 @@ def test_configure_invalid_field_value_error(self):
404404
args=None, # Must be None for remote server
405405
env=None,
406406
url='not-a-url', # Invalid URL format
407-
headers=None,
407+
header=None,
408408
no_backup=True,
409409
dry_run=False,
410410
auto_approve=False
@@ -424,7 +424,7 @@ def test_configure_pydantic_validation_error_handling(self):
424424
args=['server.py'],
425425
env=None,
426426
url=None,
427-
headers=['Auth=token'], # Headers not allowed with command
427+
header=['Auth=token'], # Headers not allowed with command
428428
no_backup=True,
429429
dry_run=False,
430430
auto_approve=False
@@ -446,7 +446,7 @@ def test_configure_missing_command_url_error(self):
446446
args=None,
447447
env=None,
448448
url=None,
449-
headers=None,
449+
header=None,
450450
no_backup=True,
451451
dry_run=False,
452452
auto_approve=False
@@ -476,7 +476,7 @@ def test_existing_configure_command_still_works(self):
476476
args=['-m', 'my_package.server'],
477477
env=['API_KEY=secret'],
478478
url=None,
479-
headers=None,
479+
header=None,
480480
no_backup=False,
481481
dry_run=False,
482482
auto_approve=False
@@ -509,21 +509,21 @@ def test_parse_env_vars_empty(self):
509509
self.assertEqual(result, {})
510510

511511
@regression_test
512-
def test_parse_headers_basic(self):
512+
def test_parse_header_basic(self):
513513
"""Test parsing headers from KEY=VALUE format."""
514514
headers_list = ['Authorization=Bearer token', 'Content-Type=application/json']
515-
result = parse_headers(headers_list)
515+
result = parse_header(headers_list)
516516

517517
expected = {'Authorization': 'Bearer token', 'Content-Type': 'application/json'}
518518
self.assertEqual(result, expected)
519519

520520
@regression_test
521-
def test_parse_headers_empty(self):
521+
def test_parse_header_empty(self):
522522
"""Test parsing empty headers list."""
523-
result = parse_headers(None)
523+
result = parse_header(None)
524524
self.assertEqual(result, {})
525525

526-
result = parse_headers([])
526+
result = parse_header([])
527527
self.assertEqual(result, {})
528528

529529

@@ -638,7 +638,7 @@ def test_claude_desktop_rejects_url_configuration(self):
638638
args=None,
639639
env=None,
640640
url='http://localhost:8080', # Should be rejected
641-
headers=None,
641+
header=None,
642642
no_backup=True,
643643
dry_run=False,
644644
auto_approve=True
@@ -663,7 +663,7 @@ def test_claude_code_rejects_url_configuration(self):
663663
args=None,
664664
env=None,
665665
url='http://localhost:8080',
666-
headers=None,
666+
header=None,
667667
no_backup=True,
668668
dry_run=False,
669669
auto_approve=True
@@ -691,7 +691,7 @@ def test_args_quoted_string_splitting(self):
691691
args=['-r --name aName'], # Single string with quoted content
692692
env=None,
693693
url=None,
694-
headers=None,
694+
header=None,
695695
no_backup=True,
696696
dry_run=False,
697697
auto_approve=False
@@ -720,7 +720,7 @@ def test_args_multiple_quoted_strings(self):
720720
args=['-r', '--name aName'], # Two separate args
721721
env=None,
722722
url=None,
723-
headers=None,
723+
header=None,
724724
no_backup=True,
725725
dry_run=False,
726726
auto_approve=False
@@ -749,7 +749,7 @@ def test_args_empty_string_handling(self):
749749
args=['', 'server.py'], # Empty string should be filtered
750750
env=None,
751751
url=None,
752-
headers=None,
752+
header=None,
753753
no_backup=True,
754754
dry_run=False,
755755
auto_approve=False
@@ -779,7 +779,7 @@ def test_args_invalid_quote_handling(self):
779779
args=['unclosed "quote'], # Invalid quote
780780
env=None,
781781
url=None,
782-
headers=None,
782+
header=None,
783783
no_backup=True,
784784
dry_run=False,
785785
auto_approve=False
@@ -811,7 +811,7 @@ def test_cli_handler_signature_compatible(self):
811811
# Verify expected parameters exist
812812
expected_params = [
813813
'host', 'server_name', 'command', 'args',
814-
'env', 'url', 'headers', 'no_backup', 'dry_run', 'auto_approve'
814+
'env', 'url', 'header', 'no_backup', 'dry_run', 'auto_approve'
815815
]
816816

817817
for param in expected_params:

0 commit comments

Comments
 (0)