hatch-xclam 0.7.0.dev13__py3-none-any.whl → 0.7.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. hatch/cli_hatch.py +120 -18
  2. hatch/mcp_host_config/__init__.py +4 -2
  3. hatch/mcp_host_config/backup.py +62 -31
  4. hatch/mcp_host_config/models.py +125 -1
  5. hatch/mcp_host_config/strategies.py +268 -1
  6. {hatch_xclam-0.7.0.dev13.dist-info → hatch_xclam-0.7.1.dist-info}/METADATA +6 -3
  7. {hatch_xclam-0.7.0.dev13.dist-info → hatch_xclam-0.7.1.dist-info}/RECORD +26 -14
  8. tests/integration/__init__.py +5 -0
  9. tests/integration/test_mcp_kiro_integration.py +153 -0
  10. tests/regression/__init__.py +5 -0
  11. tests/regression/test_mcp_codex_backup_integration.py +162 -0
  12. tests/regression/test_mcp_codex_host_strategy.py +163 -0
  13. tests/regression/test_mcp_codex_model_validation.py +117 -0
  14. tests/regression/test_mcp_kiro_backup_integration.py +241 -0
  15. tests/regression/test_mcp_kiro_cli_integration.py +141 -0
  16. tests/regression/test_mcp_kiro_decorator_registration.py +71 -0
  17. tests/regression/test_mcp_kiro_host_strategy.py +214 -0
  18. tests/regression/test_mcp_kiro_model_validation.py +116 -0
  19. tests/regression/test_mcp_kiro_omni_conversion.py +104 -0
  20. tests/test_data_utils.py +108 -0
  21. tests/test_mcp_cli_all_host_specific_args.py +194 -1
  22. tests/test_mcp_cli_direct_management.py +8 -5
  23. {hatch_xclam-0.7.0.dev13.dist-info → hatch_xclam-0.7.1.dist-info}/WHEEL +0 -0
  24. {hatch_xclam-0.7.0.dev13.dist-info → hatch_xclam-0.7.1.dist-info}/entry_points.txt +0 -0
  25. {hatch_xclam-0.7.0.dev13.dist-info → hatch_xclam-0.7.1.dist-info}/licenses/LICENSE +0 -0
  26. {hatch_xclam-0.7.0.dev13.dist-info → hatch_xclam-0.7.1.dist-info}/top_level.txt +0 -0
@@ -8,12 +8,15 @@ strategies with decorator registration following Hatchling patterns.
8
8
 
9
9
  import platform
10
10
  import json
11
+ import tomllib # Python 3.11+ built-in
12
+ import tomli_w # TOML writing
11
13
  from pathlib import Path
12
- from typing import Optional, Dict, Any
14
+ from typing import Optional, Dict, Any, TextIO
13
15
  import logging
14
16
 
15
17
  from .host_management import MCPHostStrategy, register_host_strategy
16
18
  from .models import MCPHostType, MCPServerConfig, HostConfiguration
19
+ from .backup import MCPHostConfigBackupManager, AtomicFileOperations
17
20
 
18
21
  logger = logging.getLogger(__name__)
19
22
 
@@ -409,6 +412,101 @@ class VSCodeHostStrategy(MCPHostStrategy):
409
412
  return False
410
413
 
411
414
 
415
+ @register_host_strategy(MCPHostType.KIRO)
416
+ class KiroHostStrategy(MCPHostStrategy):
417
+ """Configuration strategy for Kiro IDE."""
418
+
419
+ def get_config_path(self) -> Optional[Path]:
420
+ """Get Kiro configuration path (user-level only per constraint)."""
421
+ return Path.home() / ".kiro" / "settings" / "mcp.json"
422
+
423
+ def get_config_key(self) -> str:
424
+ """Kiro uses 'mcpServers' key."""
425
+ return "mcpServers"
426
+
427
+ def is_host_available(self) -> bool:
428
+ """Check if Kiro is available by checking for settings directory."""
429
+ kiro_dir = Path.home() / ".kiro" / "settings"
430
+ return kiro_dir.exists()
431
+
432
+ def validate_server_config(self, server_config: MCPServerConfig) -> bool:
433
+ """Kiro validation - supports both local and remote servers."""
434
+ return server_config.command is not None or server_config.url is not None
435
+
436
+ def read_configuration(self) -> HostConfiguration:
437
+ """Read Kiro configuration file."""
438
+ config_path_str = self.get_config_path()
439
+ if not config_path_str:
440
+ return HostConfiguration(servers={})
441
+
442
+ config_path = Path(config_path_str)
443
+ if not config_path.exists():
444
+ return HostConfiguration(servers={})
445
+
446
+ try:
447
+ with open(config_path, 'r', encoding='utf-8') as f:
448
+ data = json.load(f)
449
+
450
+ servers = {}
451
+ mcp_servers = data.get(self.get_config_key(), {})
452
+
453
+ for name, config in mcp_servers.items():
454
+ try:
455
+ servers[name] = MCPServerConfig(**config)
456
+ except Exception as e:
457
+ logger.warning(f"Invalid server config for {name}: {e}")
458
+ continue
459
+
460
+ return HostConfiguration(servers=servers)
461
+
462
+ except Exception as e:
463
+ logger.error(f"Failed to read Kiro configuration: {e}")
464
+ return HostConfiguration(servers={})
465
+
466
+ def write_configuration(self, config: HostConfiguration, no_backup: bool = False) -> bool:
467
+ """Write configuration to Kiro with backup support."""
468
+ config_path_str = self.get_config_path()
469
+ if not config_path_str:
470
+ return False
471
+
472
+ config_path = Path(config_path_str)
473
+
474
+ try:
475
+ # Ensure directory exists
476
+ config_path.parent.mkdir(parents=True, exist_ok=True)
477
+
478
+ # Read existing configuration to preserve other settings
479
+ existing_data = {}
480
+ if config_path.exists():
481
+ with open(config_path, 'r', encoding='utf-8') as f:
482
+ existing_data = json.load(f)
483
+
484
+ # Update MCP servers section
485
+ servers_data = {}
486
+ for name, server_config in config.servers.items():
487
+ servers_data[name] = server_config.model_dump(exclude_unset=True)
488
+
489
+ existing_data[self.get_config_key()] = servers_data
490
+
491
+ # Use atomic write with backup support
492
+ backup_manager = MCPHostConfigBackupManager()
493
+ atomic_ops = AtomicFileOperations()
494
+
495
+ atomic_ops.atomic_write_with_backup(
496
+ file_path=config_path,
497
+ data=existing_data,
498
+ backup_manager=backup_manager,
499
+ hostname="kiro",
500
+ skip_backup=no_backup
501
+ )
502
+
503
+ return True
504
+
505
+ except Exception as e:
506
+ logger.error(f"Failed to write Kiro configuration: {e}")
507
+ return False
508
+
509
+
412
510
  @register_host_strategy(MCPHostType.GEMINI)
413
511
  class GeminiHostStrategy(MCPHostStrategy):
414
512
  """Configuration strategy for Google Gemini CLI MCP integration."""
@@ -511,3 +609,172 @@ class GeminiHostStrategy(MCPHostStrategy):
511
609
  except Exception as e:
512
610
  logger.error(f"Failed to write Gemini configuration: {e}")
513
611
  return False
612
+
613
+
614
+ @register_host_strategy(MCPHostType.CODEX)
615
+ class CodexHostStrategy(MCPHostStrategy):
616
+ """Configuration strategy for Codex IDE with TOML support.
617
+
618
+ Codex uses TOML configuration at ~/.codex/config.toml with a unique
619
+ structure using [mcp_servers.<server-name>] tables.
620
+ """
621
+
622
+ def __init__(self):
623
+ self.config_format = "toml"
624
+ self._preserved_features = {} # Preserve [features] section
625
+
626
+ def get_config_path(self) -> Optional[Path]:
627
+ """Get Codex configuration path."""
628
+ return Path.home() / ".codex" / "config.toml"
629
+
630
+ def get_config_key(self) -> str:
631
+ """Codex uses 'mcp_servers' key (note: underscore, not camelCase)."""
632
+ return "mcp_servers"
633
+
634
+ def is_host_available(self) -> bool:
635
+ """Check if Codex is available by checking for config directory."""
636
+ codex_dir = Path.home() / ".codex"
637
+ return codex_dir.exists()
638
+
639
+ def validate_server_config(self, server_config: MCPServerConfig) -> bool:
640
+ """Codex validation - supports both STDIO and HTTP servers."""
641
+ return server_config.command is not None or server_config.url is not None
642
+
643
+ def read_configuration(self) -> HostConfiguration:
644
+ """Read Codex TOML configuration file."""
645
+ config_path = self.get_config_path()
646
+ if not config_path or not config_path.exists():
647
+ return HostConfiguration(servers={})
648
+
649
+ try:
650
+ with open(config_path, 'rb') as f:
651
+ toml_data = tomllib.load(f)
652
+
653
+ # Preserve [features] section for later write
654
+ self._preserved_features = toml_data.get('features', {})
655
+
656
+ # Extract MCP servers from [mcp_servers.*] tables
657
+ mcp_servers = toml_data.get(self.get_config_key(), {})
658
+
659
+ servers = {}
660
+ for name, server_data in mcp_servers.items():
661
+ try:
662
+ # Flatten nested env section if present
663
+ flat_data = self._flatten_toml_server(server_data)
664
+ servers[name] = MCPServerConfig(**flat_data)
665
+ except Exception as e:
666
+ logger.warning(f"Invalid server config for {name}: {e}")
667
+ continue
668
+
669
+ return HostConfiguration(servers=servers)
670
+
671
+ except Exception as e:
672
+ logger.error(f"Failed to read Codex configuration: {e}")
673
+ return HostConfiguration(servers={})
674
+
675
+ def write_configuration(self, config: HostConfiguration, no_backup: bool = False) -> bool:
676
+ """Write Codex TOML configuration file with backup support."""
677
+ config_path = self.get_config_path()
678
+ if not config_path:
679
+ return False
680
+
681
+ try:
682
+ config_path.parent.mkdir(parents=True, exist_ok=True)
683
+
684
+ # Read existing configuration to preserve non-MCP settings
685
+ existing_data = {}
686
+ if config_path.exists():
687
+ try:
688
+ with open(config_path, 'rb') as f:
689
+ existing_data = tomllib.load(f)
690
+ except Exception:
691
+ pass
692
+
693
+ # Preserve [features] section
694
+ if 'features' in existing_data:
695
+ self._preserved_features = existing_data['features']
696
+
697
+ # Convert servers to TOML structure
698
+ servers_data = {}
699
+ for name, server_config in config.servers.items():
700
+ servers_data[name] = self._to_toml_server(server_config)
701
+
702
+ # Build final TOML structure
703
+ final_data = {}
704
+
705
+ # Preserve [features] at top
706
+ if self._preserved_features:
707
+ final_data['features'] = self._preserved_features
708
+
709
+ # Add MCP servers
710
+ final_data[self.get_config_key()] = servers_data
711
+
712
+ # Preserve other top-level keys
713
+ for key, value in existing_data.items():
714
+ if key not in ('features', self.get_config_key()):
715
+ final_data[key] = value
716
+
717
+ # Use atomic write with TOML serializer
718
+ backup_manager = MCPHostConfigBackupManager()
719
+ atomic_ops = AtomicFileOperations()
720
+
721
+ def toml_serializer(data: Any, f: TextIO) -> None:
722
+ # tomli_w.dumps returns a string, write it to the file
723
+ toml_str = tomli_w.dumps(data)
724
+ f.write(toml_str)
725
+
726
+ atomic_ops.atomic_write_with_serializer(
727
+ file_path=config_path,
728
+ data=final_data,
729
+ serializer=toml_serializer,
730
+ backup_manager=backup_manager,
731
+ hostname="codex",
732
+ skip_backup=no_backup
733
+ )
734
+
735
+ return True
736
+
737
+ except Exception as e:
738
+ logger.error(f"Failed to write Codex configuration: {e}")
739
+ return False
740
+
741
+ def _flatten_toml_server(self, server_data: Dict[str, Any]) -> Dict[str, Any]:
742
+ """Flatten nested TOML server structure to flat dict.
743
+
744
+ TOML structure:
745
+ [mcp_servers.name]
746
+ command = "npx"
747
+ args = ["-y", "package"]
748
+ [mcp_servers.name.env]
749
+ VAR = "value"
750
+
751
+ Becomes:
752
+ {"command": "npx", "args": [...], "env": {"VAR": "value"}}
753
+
754
+ Also maps Codex-specific 'http_headers' to universal 'headers' field.
755
+ """
756
+ # TOML already parses nested tables into nested dicts
757
+ # So [mcp_servers.name.env] becomes {"env": {...}}
758
+ data = dict(server_data)
759
+
760
+ # Map Codex 'http_headers' to universal 'headers' for MCPServerConfig
761
+ if 'http_headers' in data:
762
+ data['headers'] = data.pop('http_headers')
763
+
764
+ return data
765
+
766
+ def _to_toml_server(self, server_config: MCPServerConfig) -> Dict[str, Any]:
767
+ """Convert MCPServerConfig to TOML-compatible dict structure.
768
+
769
+ Maps universal 'headers' field back to Codex-specific 'http_headers'.
770
+ """
771
+ data = server_config.model_dump(exclude_unset=True)
772
+
773
+ # Remove 'name' field as it's the table key in TOML
774
+ data.pop('name', None)
775
+
776
+ # Map universal 'headers' to Codex 'http_headers' for TOML
777
+ if 'headers' in data:
778
+ data['http_headers'] = data.pop('headers')
779
+
780
+ return data
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hatch-xclam
3
- Version: 0.7.0.dev13
3
+ Version: 0.7.1
4
4
  Summary: Package manager for the Cracking Shells ecosystem
5
5
  Author: Cracking Shells Team
6
6
  Project-URL: Homepage, https://github.com/CrackingShells/Hatch
@@ -17,6 +17,7 @@ Requires-Dist: packaging>=20.0
17
17
  Requires-Dist: docker>=7.1.0
18
18
  Requires-Dist: pydantic>=2.0.0
19
19
  Requires-Dist: hatch-validator>=0.8.0
20
+ Requires-Dist: tomli-w>=1.0.0
20
21
  Provides-Extra: docs
21
22
  Requires-Dist: mkdocs>=1.4.0; extra == "docs"
22
23
  Requires-Dist: mkdocstrings[python]>=0.20.0; extra == "docs"
@@ -30,7 +31,7 @@ Dynamic: license-file
30
31
 
31
32
  ## Introduction
32
33
 
33
- Hatch is the package manager for managing Model Context Protocol (MCP) servers with environment isolation, multi-type dependency resolution, and multi-host deployment. Deploy MCP servers to Claude Desktop, VS Code, Cursor, and other platforms with automatic dependency management.
34
+ Hatch is the package manager for managing Model Context Protocol (MCP) servers with environment isolation, multi-type dependency resolution, and multi-host deployment. Deploy MCP servers to Claude Desktop, VS Code, Cursor, Kiro, Codex, and other platforms with automatic dependency management.
34
35
 
35
36
  The canonical documentation is at `docs/index.md` and published at <https://hatch.readthedocs.io/en/latest/>.
36
37
 
@@ -38,7 +39,7 @@ The canonical documentation is at `docs/index.md` and published at <https://hatc
38
39
 
39
40
  - **Environment Isolation** — Create separate, isolated workspaces for different projects without conflicts
40
41
  - **Multi-Type Dependency Resolution** — Automatically resolve and install system packages, Python packages, Docker containers, and Hatch packages
41
- - **Multi-Host Deployment** — Deploy MCP servers to Claude Desktop, Claude Code, VS Code, Cursor, LM Studio, and Google Gemini CLI
42
+ - **Multi-Host Deployment** — Configure MCP servers on multiple host platforms
42
43
  - **Package Validation** — Ensure packages meet schema requirements before distribution
43
44
  - **Development-Focused** — Optimized for rapid development and testing of MCP server ecosystems
44
45
 
@@ -50,6 +51,8 @@ Hatch supports deployment to the following MCP host platforms:
50
51
  - **Claude Code** — Claude integration for VS Code with MCP capabilities
51
52
  - **VS Code** — Visual Studio Code with the MCP extension for tool integration
52
53
  - **Cursor** — AI-first code editor with built-in MCP server support
54
+ - **Kiro** — Kiro IDE with MCP support
55
+ - **Codex** — OpenAI Codex with MCP server configuration support
53
56
  - **LM Studio** — Local LLM inference platform with MCP server integration
54
57
  - **Google Gemini CLI** — Command-line interface for Google's Gemini model with MCP support
55
58
 
@@ -1,5 +1,5 @@
1
1
  hatch/__init__.py,sha256=5JFQZiaZQewEWg8WktQKEdT8IeH0KstndZf27VH7sq4,594
2
- hatch/cli_hatch.py,sha256=kwTUTUqwI0SbAmyjeRFoj5ppLG90hJf7Pb4chPb7jvI,108041
2
+ hatch/cli_hatch.py,sha256=Z7-N0DdWT1xK23EL0Gr5mx2wjqhDFzFROt1nUxPAnZM,112093
3
3
  hatch/environment_manager.py,sha256=9R9PJYPKQLmWeGXBrOzXxty20la33LgCCYY8o2aMFBQ,60757
4
4
  hatch/package_loader.py,sha256=Sa2JIoio1QlMT2tOGwZhC6pFJIs419cYyoodzyaTDl4,11269
5
5
  hatch/python_environment_manager.py,sha256=guU3zz4_WG3ptuX_ATGCRIi_fDxNHlaQtMv3kiRSo8k,28894
@@ -15,17 +15,17 @@ hatch/installers/installer_base.py,sha256=mId6Q_DLOQPZriq3wu3BCU-ckouom3EZgbWJQq
15
15
  hatch/installers/python_installer.py,sha256=MS9Q8wKjMAy7MEWk7zcAAiFgN0KzOVJFmMzXt1MSH8g,13632
16
16
  hatch/installers/registry.py,sha256=ZOEEMJy_kL5LVj5Mf7s1_CIovDnUVag6nB01dEU9Xeg,6831
17
17
  hatch/installers/system_installer.py,sha256=bdrmw3I9g2EU2E94-4vtJj01RhmekX9GxylU1RPT3Lk,22869
18
- hatch/mcp_host_config/__init__.py,sha256=WtN_wZVqSrzgcSzmL00I4Qh7_MKjtRlNhWLQ4JinP1o,1683
19
- hatch/mcp_host_config/backup.py,sha256=h3jssjEQxIsEPcpW07WSEJNcPvQ5ps-83_YtVuek-eg,16867
18
+ hatch/mcp_host_config/__init__.py,sha256=STHzYwcyO6blKSwcMRibcD_4VKHgpEjru-uY1OQM9yA,1781
19
+ hatch/mcp_host_config/backup.py,sha256=X6wnLkPFYv4e5ObrWQSgQ_a_6rcmsFgysQwBZF_osWM,17831
20
20
  hatch/mcp_host_config/host_management.py,sha256=sXyGluFQpfXKggxAVvV9riGRis29JnoEM2dTWSIwb24,23905
21
- hatch/mcp_host_config/models.py,sha256=WLAdeJc-t4zyiiHByQHYGpC55t6ViggBAs4N1ksJ6W8,24548
21
+ hatch/mcp_host_config/models.py,sha256=1Nd3PDyGGbBm4oTgMEQ67j4b_qy23iibv9N4Tm4d9oE,29110
22
22
  hatch/mcp_host_config/reporting.py,sha256=Q8UKBJRfvJTbb5PM9xwLEOh3OJjf19AKpWKxs-2622k,6889
23
- hatch/mcp_host_config/strategies.py,sha256=deFdAbj8G6Mzs7W8fBlPMPnijxzSnQ2SS5AAx0JR6oY,20293
24
- hatch_xclam-0.7.0.dev13.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
23
+ hatch/mcp_host_config/strategies.py,sha256=NdA8hcbAi5xGkFRy51csmdEJESg25L8JkwTDVg2AeMw,30302
24
+ hatch_xclam-0.7.1.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
25
25
  tests/__init__.py,sha256=4I3aQWv143Y1QY_nRIBWnY9MIL-aoQOJuVlpoPQz24E,53
26
26
  tests/run_environment_tests.py,sha256=bWCr8UsPgU80SM8f_VSi0TCwDI6JNqZpvZ2W9-b2Lqk,7302
27
27
  tests/test_cli_version.py,sha256=lU8TBZfzn_8AenFNXYrLMARht91fI5twBN13L-iJebc,4778
28
- tests/test_data_utils.py,sha256=OjT4rVUxHAe-d1fIuG-4iMicM1uuadsWsKjqRzYlGtY,17752
28
+ tests/test_data_utils.py,sha256=ROexE3H4Cjk8maR-r6x8s5507d0vWF5xJteO_YN78SU,21876
29
29
  tests/test_dependency_orchestrator_consent.py,sha256=lA9Qu-3dFdXKmU8mzOS0tjM8j0yy9qMQXJJcgEoy12g,12652
30
30
  tests/test_docker_installer.py,sha256=pcWev4fGf1p-pR5T8tDswGVZqIprC86puLEl6t8yY2w,22305
31
31
  tests/test_env_manip.py,sha256=f3LjBX0y0wzTDjc52QDan3Fgcgtld7CvuzH5gYKxGhs,47941
@@ -33,9 +33,9 @@ tests/test_hatch_installer.py,sha256=qHCEcKpbe0fHvkzib2rcUJUw1Z-PCRBBJhbjoyOYiVM
33
33
  tests/test_installer_base.py,sha256=0xZiPDMf8LeFJs2SmnYhbIgL7mgvG_HKwL1myQovEZI,11818
34
34
  tests/test_mcp_atomic_operations.py,sha256=QmwUDRNZUz6b2i50yRAMBntRDaMMYZt6flHFJfVkzNE,10563
35
35
  tests/test_mcp_backup_integration.py,sha256=Auw6Bx1EXGwmCA-mRIy31DRLuRWyV33eB7GJiOvIPXQ,12360
36
- tests/test_mcp_cli_all_host_specific_args.py,sha256=xLmWCgvupfYo5Z107rYyuz4VJdgWFAWBAw7eKokSscw,11302
36
+ tests/test_mcp_cli_all_host_specific_args.py,sha256=hvXUetFyoZFtHsEjpzZ0GNdEuvci3Hv8P8thVjBPm-A,18748
37
37
  tests/test_mcp_cli_backup_management.py,sha256=GlUUNu5K1w8S2jTQ6YISp5KeXH5c-H9F0lJX2SG0JWM,14019
38
- tests/test_mcp_cli_direct_management.py,sha256=NOlRGP7M3CJ6dzR9JNtqIswJaCT8WIOoy2PhKXlGqSM,21906
38
+ tests/test_mcp_cli_direct_management.py,sha256=7GRwHXezmImCUfpHhVjvSkGfT-OBi1tMMLgExMXjals,22184
39
39
  tests/test_mcp_cli_discovery_listing.py,sha256=kdrCU6POLyGW9ejowNV-dUVDFVseMd_vibvgIDjZUCM,26595
40
40
  tests/test_mcp_cli_host_config_integration.py,sha256=dD6maHP0wHWnFZwxJ5LgSK1GsrYqB4WdicZkotqIANo,32512
41
41
  tests/test_mcp_cli_package_management.py,sha256=YFMhyh3dueel1f2R5_VMNr9AewDmVrqGbU1kj5bhdeo,14590
@@ -56,6 +56,18 @@ tests/test_python_installer.py,sha256=DXBy7hNJk5313_dDXiHTLEH7UJSPUnyGs4IEr7Hn_5
56
56
  tests/test_registry.py,sha256=nFHwRIx9n8y0nHwW9j8X3DZ07Y0BLYZMKduTXo-xXTc,2261
57
57
  tests/test_registry_retriever.py,sha256=6mQQuqy2tQdw4j3VOkC_DxWqtKwaCjGPgXsdL-w48Yw,10775
58
58
  tests/test_system_installer.py,sha256=bWuyEKakhvi51iM8xHJh62zv83HUTd8QnPlqUUMWx9c,28102
59
+ tests/integration/__init__.py,sha256=2mG53dv1VqjxZYHuglneK9VgDMoWCxpfmPByXXd3zVM,125
60
+ tests/integration/test_mcp_kiro_integration.py,sha256=9y2XPacd3Y6zkqUUcCDjzj8Jv2Humby2LZ5CLSeFYCg,5566
61
+ tests/regression/__init__.py,sha256=0pFnFuEaMf7gPFFXMv-b_vNRNyLV-wU2lYspZHFH_Uo,127
62
+ tests/regression/test_mcp_codex_backup_integration.py,sha256=15G8tCPFtukEcZvE5NBI8BvxlD27KwmE3z8-8ZZ3GxM,7107
63
+ tests/regression/test_mcp_codex_host_strategy.py,sha256=6ehG8IruT9U-fO7kDMoJfogXbpq7JV4XYl-Ho68nt1U,6413
64
+ tests/regression/test_mcp_codex_model_validation.py,sha256=LkGexJrDusxRg_5Bpsm7sXRt7LYwhqqj4Y7VIynslyw,4512
65
+ tests/regression/test_mcp_kiro_backup_integration.py,sha256=oBEnSSLrnHIurkrBtjSG-HT6DyODV2z9tZeZotnsR1k,9584
66
+ tests/regression/test_mcp_kiro_cli_integration.py,sha256=jDQE73yJTRb2e6MPShxLHmLDtN5VBMHMAUBojPEnVBI,5123
67
+ tests/regression/test_mcp_kiro_decorator_registration.py,sha256=_H9FdKdKCv__IYBS0tfnZGUP574KoDjqKInmFiDEKPc,2556
68
+ tests/regression/test_mcp_kiro_host_strategy.py,sha256=t3EbNgUkDC-tF_Ztrjlrx8aDkmML2zZiPnl3iLvKWcg,8235
69
+ tests/regression/test_mcp_kiro_model_validation.py,sha256=bCWzkP6gDxD4tJ6bXnyC6BNGPk3FwX5MQVJt_kK-Hsg,3877
70
+ tests/regression/test_mcp_kiro_omni_conversion.py,sha256=u0g-NFKDpyVxguNHc_RxJXhBvUvABljx-IZqeOjpJZw,3559
59
71
  tests/test_data/packages/basic/base_pkg/hatch_mcp_server.py,sha256=nn9XJQz7Owq_AKZ35bUV-l5eThauxTvIQZdQmcZqbQg,350
60
72
  tests/test_data/packages/basic/base_pkg/mcp_server.py,sha256=gzXj-n0NbcS1TF-ebKOdXQRyuVIC0Gn_b8ZB-9RckrM,422
61
73
  tests/test_data/packages/basic/base_pkg_v2/hatch_mcp_server.py,sha256=VmGpeLPpsNyFyePNtcRQCSscLOHdZgXsGDulA4_9CJA,356
@@ -86,8 +98,8 @@ tests/test_data/packages/schema_versions/schema_v1_1_0_pkg/main.py,sha256=_B5aqX
86
98
  tests/test_data/packages/schema_versions/schema_v1_2_0_pkg/main.py,sha256=rinhVySJpjXKd2sRCS0ps7xTrVqImWcZ8l4aYbidYR8,238
87
99
  tests/test_data/packages/schema_versions/schema_v1_2_1_pkg/hatch_mcp_server.py,sha256=FT14llzHlA4i8I__8GugzBRowhg_CbLmsOwjq0IWFsY,368
88
100
  tests/test_data/packages/schema_versions/schema_v1_2_1_pkg/mcp_server.py,sha256=BRPAyyAseE2CGR3W647SwjlluYfi7ejhZck0An5581I,467
89
- hatch_xclam-0.7.0.dev13.dist-info/METADATA,sha256=kPUoyD_oOKbFW6zIP8iepiZ217Tk9LG13Vv3pgnt0Vw,5849
90
- hatch_xclam-0.7.0.dev13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
91
- hatch_xclam-0.7.0.dev13.dist-info/entry_points.txt,sha256=6xbkwFUtr7nRa56vUFMyJk2wjwFQ_XVaU53ruecWKI0,47
92
- hatch_xclam-0.7.0.dev13.dist-info/top_level.txt,sha256=GZP3Ivciwal8jVITQkQr7dSNlLJRzfNOhA76VN7Jp4Y,12
93
- hatch_xclam-0.7.0.dev13.dist-info/RECORD,,
101
+ hatch_xclam-0.7.1.dist-info/METADATA,sha256=RfpwtyksekYsi6tz0Jsd36Ssgo789woFnpjyhnam8hA,5942
102
+ hatch_xclam-0.7.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
103
+ hatch_xclam-0.7.1.dist-info/entry_points.txt,sha256=6xbkwFUtr7nRa56vUFMyJk2wjwFQ_XVaU53ruecWKI0,47
104
+ hatch_xclam-0.7.1.dist-info/top_level.txt,sha256=GZP3Ivciwal8jVITQkQr7dSNlLJRzfNOhA76VN7Jp4Y,12
105
+ hatch_xclam-0.7.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ """
2
+ Integration tests for Hatch MCP functionality.
3
+
4
+ These tests validate component interactions and end-to-end workflows.
5
+ """
@@ -0,0 +1,153 @@
1
+ """
2
+ Kiro MCP Integration Tests
3
+
4
+ End-to-end integration tests combining CLI, model conversion, and strategy operations.
5
+ """
6
+
7
+ import unittest
8
+ from unittest.mock import patch, MagicMock
9
+
10
+ from wobble.decorators import integration_test
11
+
12
+ from hatch.cli_hatch import handle_mcp_configure
13
+ from hatch.mcp_host_config.models import (
14
+ HOST_MODEL_REGISTRY,
15
+ MCPHostType,
16
+ MCPServerConfigKiro
17
+ )
18
+
19
+
20
+ class TestKiroIntegration(unittest.TestCase):
21
+ """Test suite for end-to-end Kiro integration."""
22
+
23
+ @integration_test(scope="component")
24
+ @patch('hatch.cli_hatch.MCPHostConfigurationManager')
25
+ def test_kiro_end_to_end_configuration(self, mock_manager_class):
26
+ """Test complete Kiro configuration workflow."""
27
+ # Setup mocks
28
+ mock_manager = MagicMock()
29
+ mock_manager_class.return_value = mock_manager
30
+
31
+ mock_result = MagicMock()
32
+ mock_result.success = True
33
+ mock_manager.configure_server.return_value = mock_result
34
+
35
+ # Execute CLI command with Kiro-specific arguments
36
+ result = handle_mcp_configure(
37
+ host='kiro',
38
+ server_name='augment-server',
39
+ command='auggie',
40
+ args=['--mcp', '-m', 'default'],
41
+ disabled=False,
42
+ auto_approve_tools=['codebase-retrieval', 'fetch'],
43
+ disable_tools=['dangerous-tool'],
44
+ auto_approve=True
45
+ )
46
+
47
+ # Verify success
48
+ self.assertEqual(result, 0)
49
+
50
+ # Verify configuration manager was called
51
+ mock_manager.configure_server.assert_called_once()
52
+
53
+ # Verify server configuration
54
+ call_args = mock_manager.configure_server.call_args
55
+ server_config = call_args.kwargs['server_config']
56
+
57
+ # Verify all Kiro-specific fields
58
+ self.assertFalse(server_config.disabled)
59
+ self.assertEqual(len(server_config.autoApprove), 2)
60
+ self.assertEqual(len(server_config.disabledTools), 1)
61
+ self.assertIn('codebase-retrieval', server_config.autoApprove)
62
+ self.assertIn('dangerous-tool', server_config.disabledTools)
63
+
64
+ @integration_test(scope="system")
65
+ def test_kiro_host_model_registry_integration(self):
66
+ """Test Kiro integration with HOST_MODEL_REGISTRY."""
67
+ # Verify Kiro is in registry
68
+ self.assertIn(MCPHostType.KIRO, HOST_MODEL_REGISTRY)
69
+
70
+ # Verify correct model class
71
+ model_class = HOST_MODEL_REGISTRY[MCPHostType.KIRO]
72
+ self.assertEqual(model_class.__name__, "MCPServerConfigKiro")
73
+
74
+ # Test model instantiation
75
+ model_instance = model_class(
76
+ name="test-server",
77
+ command="auggie",
78
+ disabled=True
79
+ )
80
+ self.assertTrue(model_instance.disabled)
81
+
82
+ @integration_test(scope="component")
83
+ def test_kiro_model_to_strategy_workflow(self):
84
+ """Test workflow from model creation to strategy operations."""
85
+ # Import to trigger registration
86
+ import hatch.mcp_host_config.strategies
87
+ from hatch.mcp_host_config.host_management import MCPHostRegistry
88
+
89
+ # Create Kiro model
90
+ kiro_model = MCPServerConfigKiro(
91
+ name="workflow-test",
92
+ command="auggie",
93
+ args=["--mcp"],
94
+ disabled=False,
95
+ autoApprove=["codebase-retrieval"]
96
+ )
97
+
98
+ # Get Kiro strategy
99
+ strategy = MCPHostRegistry.get_strategy(MCPHostType.KIRO)
100
+
101
+ # Verify strategy can validate the model
102
+ self.assertTrue(strategy.validate_server_config(kiro_model))
103
+
104
+ # Verify model fields are accessible
105
+ self.assertEqual(kiro_model.command, "auggie")
106
+ self.assertFalse(kiro_model.disabled)
107
+ self.assertIn("codebase-retrieval", kiro_model.autoApprove)
108
+
109
+ @integration_test(scope="end_to_end")
110
+ @patch('hatch.cli_hatch.MCPHostConfigurationManager')
111
+ def test_kiro_complete_lifecycle(self, mock_manager_class):
112
+ """Test complete Kiro server lifecycle: create, configure, validate."""
113
+ # Setup mocks
114
+ mock_manager = MagicMock()
115
+ mock_manager_class.return_value = mock_manager
116
+
117
+ mock_result = MagicMock()
118
+ mock_result.success = True
119
+ mock_manager.configure_server.return_value = mock_result
120
+
121
+ # Step 1: Configure server via CLI
122
+ result = handle_mcp_configure(
123
+ host='kiro',
124
+ server_name='lifecycle-test',
125
+ command='auggie',
126
+ args=['--mcp', '-w', '.'],
127
+ disabled=False,
128
+ auto_approve_tools=['codebase-retrieval'],
129
+ auto_approve=True
130
+ )
131
+
132
+ # Verify CLI success
133
+ self.assertEqual(result, 0)
134
+
135
+ # Step 2: Verify configuration manager interaction
136
+ mock_manager.configure_server.assert_called_once()
137
+ call_args = mock_manager.configure_server.call_args
138
+
139
+ # Step 3: Verify server configuration structure
140
+ server_config = call_args.kwargs['server_config']
141
+ self.assertEqual(server_config.name, 'lifecycle-test')
142
+ self.assertEqual(server_config.command, 'auggie')
143
+ self.assertIn('--mcp', server_config.args)
144
+ self.assertIn('-w', server_config.args)
145
+ self.assertFalse(server_config.disabled)
146
+ self.assertIn('codebase-retrieval', server_config.autoApprove)
147
+
148
+ # Step 4: Verify model type
149
+ self.assertIsInstance(server_config, MCPServerConfigKiro)
150
+
151
+
152
+ if __name__ == '__main__':
153
+ unittest.main()
@@ -0,0 +1,5 @@
1
+ """
2
+ Regression tests for Hatch MCP functionality.
3
+
4
+ These tests validate existing functionality to prevent breaking changes.
5
+ """