Skip to main content
Glama

Agent MCP

worktree_integration.py9.68 kB
# Agent-MCP/agent_mcp/features/worktree_integration.py """ Worktree integration for Agent-MCP. This module provides the integration layer between the core agent system and Git worktrees for isolated parallel development. """ import os import logging from typing import Dict, Any, Optional, List from dataclasses import dataclass from ..utils.worktree_utils import ( is_git_repository, validate_worktree_requirements, create_git_worktree, cleanup_git_worktree, detect_project_setup_commands, run_setup_commands, generate_worktree_path, generate_branch_name ) logger = logging.getLogger(__name__) @dataclass class WorktreeConfig: """Configuration for agent worktree setup.""" enabled: bool = False branch_name: Optional[str] = None base_branch: str = "main" auto_setup: bool = True setup_commands: Optional[List[str]] = None cleanup_strategy: str = "on_terminate" # "manual", "on_terminate", "smart" class WorktreeManager: """ Manager for agent worktree operations. This class handles the creation, tracking, and cleanup of Git worktrees for agent isolation. """ def __init__(self): self.enabled = False self.agent_worktrees: Dict[str, Dict[str, Any]] = {} def enable(self) -> bool: """ Enable worktree support if requirements are met. Returns: True if worktree support is enabled, False otherwise """ if not is_git_repository(): logger.warning("Worktree support requires a Git repository") return False validation = validate_worktree_requirements() if not validation["valid"]: logger.error(f"Worktree requirements not met: {validation['issues']}") return False self.enabled = True logger.info("✅ Worktree support enabled") return True def is_enabled(self) -> bool: """Check if worktree support is enabled.""" return self.enabled def create_agent_worktree( self, agent_id: str, admin_token_suffix: str, config: WorktreeConfig ) -> Dict[str, Any]: """ Create a worktree for an agent. Args: agent_id: Agent identifier admin_token_suffix: Last 4 characters of admin token config: Worktree configuration Returns: Result dictionary with worktree details """ if not self.enabled: return { "success": False, "error": "Worktree support not enabled" } try: # Generate paths and names worktree_path = generate_worktree_path(agent_id, admin_token_suffix) branch_name = generate_branch_name(agent_id, config.branch_name) logger.info(f"Creating worktree for agent {agent_id}: {worktree_path}") # Create the worktree create_result = create_git_worktree( path=worktree_path, branch=branch_name, base_branch=config.base_branch ) if not create_result["success"]: return create_result # Set up the environment if requested setup_result = None if config.auto_setup: setup_commands = config.setup_commands or detect_project_setup_commands(worktree_path) if setup_commands: logger.info(f"Running setup commands for {agent_id}: {setup_commands}") setup_result = run_setup_commands(worktree_path, setup_commands) if not setup_result["success"]: logger.warning(f"Setup failed for {agent_id}, but continuing: {setup_result}") # Track the worktree worktree_info = { "path": worktree_path, "branch": branch_name, "base_branch": config.base_branch, "cleanup_strategy": config.cleanup_strategy, "setup_commands": config.setup_commands or detect_project_setup_commands(worktree_path), "created_at": create_result.get("created_at"), "setup_result": setup_result } self.agent_worktrees[agent_id] = worktree_info logger.info(f"✅ Worktree created for agent {agent_id}") return { "success": True, "worktree_path": worktree_path, "branch": branch_name, "worktree_info": worktree_info, "create_result": create_result, "setup_result": setup_result } except Exception as e: logger.error(f"Failed to create worktree for agent {agent_id}: {e}") return { "success": False, "error": str(e) } def cleanup_agent_worktree( self, agent_id: str, force: bool = False ) -> Dict[str, Any]: """ Clean up an agent's worktree. Args: agent_id: Agent identifier force: Force cleanup even with uncommitted changes Returns: Cleanup result dictionary """ if agent_id not in self.agent_worktrees: return { "success": True, # Nothing to clean up "message": f"No worktree found for agent {agent_id}" } worktree_info = self.agent_worktrees[agent_id] worktree_path = worktree_info["path"] logger.info(f"Cleaning up worktree for agent {agent_id}: {worktree_path}") try: cleanup_result = cleanup_git_worktree(worktree_path, force=force) if cleanup_result["success"]: # Remove from tracking del self.agent_worktrees[agent_id] logger.info(f"✅ Worktree cleaned up for agent {agent_id}") else: logger.error(f"Failed to cleanup worktree for agent {agent_id}: {cleanup_result['error']}") return cleanup_result except Exception as e: logger.error(f"Exception cleaning up worktree for agent {agent_id}: {e}") return { "success": False, "error": str(e) } def get_agent_worktree_info(self, agent_id: str) -> Optional[Dict[str, Any]]: """ Get worktree information for an agent. Args: agent_id: Agent identifier Returns: Worktree information or None if not found """ return self.agent_worktrees.get(agent_id) def list_agent_worktrees(self) -> Dict[str, Dict[str, Any]]: """ List all tracked agent worktrees. Returns: Dictionary of agent_id -> worktree_info """ return self.agent_worktrees.copy() def get_status(self) -> Dict[str, Any]: """ Get overall worktree manager status. Returns: Status dictionary with worktree information """ return { "enabled": self.enabled, "tracked_worktrees": len(self.agent_worktrees), "agent_worktrees": { agent_id: { "path": info["path"], "branch": info["branch"], "exists": os.path.exists(info["path"]) } for agent_id, info in self.agent_worktrees.items() } } # Global worktree manager instance worktree_manager = WorktreeManager() def enable_worktree_support() -> bool: """ Enable worktree support globally. Returns: True if enabled successfully, False otherwise """ return worktree_manager.enable() def is_worktree_enabled() -> bool: """Check if worktree support is enabled globally.""" return worktree_manager.is_enabled() def create_agent_worktree( agent_id: str, admin_token_suffix: str, config: WorktreeConfig ) -> Dict[str, Any]: """ Create a worktree for an agent using the global manager. Args: agent_id: Agent identifier admin_token_suffix: Last 4 characters of admin token config: Worktree configuration Returns: Result dictionary with worktree details """ return worktree_manager.create_agent_worktree(agent_id, admin_token_suffix, config) def cleanup_agent_worktree(agent_id: str, force: bool = False) -> Dict[str, Any]: """ Clean up an agent's worktree using the global manager. Args: agent_id: Agent identifier force: Force cleanup even with uncommitted changes Returns: Cleanup result dictionary """ return worktree_manager.cleanup_agent_worktree(agent_id, force) def get_worktree_status() -> Dict[str, Any]: """Get overall worktree status.""" return worktree_manager.get_status() def get_agent_worktree_path(agent_id: str) -> Optional[str]: """ Get the worktree path for an agent. Args: agent_id: Agent identifier Returns: Worktree path or None if not found """ info = worktree_manager.get_agent_worktree_info(agent_id) return info["path"] if info else None

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rinadelph/Agent-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server