claude-mpm 3.9.7__py3-none-any.whl → 3.9.9__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/templates/ticketing.json +1 -1
- claude_mpm/cli/__init__.py +3 -1
- claude_mpm/cli/commands/__init__.py +3 -1
- claude_mpm/cli/commands/cleanup.py +21 -1
- claude_mpm/cli/commands/mcp.py +821 -0
- claude_mpm/cli/parser.py +148 -1
- claude_mpm/config/memory_guardian_config.py +325 -0
- claude_mpm/constants.py +13 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +76 -19
- claude_mpm/models/state_models.py +433 -0
- claude_mpm/services/__init__.py +28 -0
- claude_mpm/services/communication/__init__.py +2 -2
- claude_mpm/services/communication/socketio.py +18 -16
- claude_mpm/services/infrastructure/__init__.py +4 -1
- claude_mpm/services/infrastructure/logging.py +3 -3
- claude_mpm/services/infrastructure/memory_guardian.py +770 -0
- claude_mpm/services/mcp_gateway/__init__.py +138 -0
- claude_mpm/services/mcp_gateway/config/__init__.py +17 -0
- claude_mpm/services/mcp_gateway/config/config_loader.py +232 -0
- claude_mpm/services/mcp_gateway/config/config_schema.py +234 -0
- claude_mpm/services/mcp_gateway/config/configuration.py +371 -0
- claude_mpm/services/mcp_gateway/core/__init__.py +51 -0
- claude_mpm/services/mcp_gateway/core/base.py +315 -0
- claude_mpm/services/mcp_gateway/core/exceptions.py +239 -0
- claude_mpm/services/mcp_gateway/core/interfaces.py +476 -0
- claude_mpm/services/mcp_gateway/main.py +326 -0
- claude_mpm/services/mcp_gateway/registry/__init__.py +12 -0
- claude_mpm/services/mcp_gateway/registry/service_registry.py +397 -0
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +477 -0
- claude_mpm/services/mcp_gateway/server/__init__.py +15 -0
- claude_mpm/services/mcp_gateway/server/mcp_server.py +430 -0
- claude_mpm/services/mcp_gateway/server/mcp_server_simple.py +444 -0
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +373 -0
- claude_mpm/services/mcp_gateway/tools/__init__.py +22 -0
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +497 -0
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +729 -0
- claude_mpm/services/mcp_gateway/tools/hello_world.py +551 -0
- claude_mpm/utils/file_utils.py +293 -0
- claude_mpm/utils/platform_memory.py +524 -0
- claude_mpm/utils/subprocess_utils.py +305 -0
- {claude_mpm-3.9.7.dist-info → claude_mpm-3.9.9.dist-info}/METADATA +4 -1
- {claude_mpm-3.9.7.dist-info → claude_mpm-3.9.9.dist-info}/RECORD +49 -26
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/agents/templates/.claude-mpm/memories/engineer_agent.md +0 -39
- claude_mpm/agents/templates/.claude-mpm/memories/qa_agent.md +0 -38
- claude_mpm/agents/templates/.claude-mpm/memories/research_agent.md +0 -39
- claude_mpm/agents/templates/.claude-mpm/memories/version_control_agent.md +0 -38
- /claude_mpm/agents/templates/{research_memory_efficient.json → backup/research_memory_efficient.json} +0 -0
- {claude_mpm-3.9.7.dist-info → claude_mpm-3.9.9.dist-info}/WHEEL +0 -0
- {claude_mpm-3.9.7.dist-info → claude_mpm-3.9.9.dist-info}/entry_points.txt +0 -0
- {claude_mpm-3.9.7.dist-info → claude_mpm-3.9.9.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-3.9.7.dist-info → claude_mpm-3.9.9.dist-info}/top_level.txt +0 -0
| @@ -0,0 +1,326 @@ | |
| 1 | 
            +
            """
         | 
| 2 | 
            +
            MCP Gateway Main Entry Point
         | 
| 3 | 
            +
            =============================
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Main entry point for running the MCP Gateway server.
         | 
| 6 | 
            +
            Orchestrates server initialization, tool registration, and lifecycle management.
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            Part of ISS-0035: MCP Server Implementation - Core Server and Tool Registry
         | 
| 9 | 
            +
            """
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            import asyncio
         | 
| 12 | 
            +
            import sys
         | 
| 13 | 
            +
            import signal
         | 
| 14 | 
            +
            from pathlib import Path
         | 
| 15 | 
            +
            from typing import Optional, List
         | 
| 16 | 
            +
            import argparse
         | 
| 17 | 
            +
            import logging
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            from claude_mpm.services.mcp_gateway.server.mcp_server import MCPServer
         | 
| 20 | 
            +
            from claude_mpm.services.mcp_gateway.server.stdio_handler import StdioHandler
         | 
| 21 | 
            +
            from claude_mpm.services.mcp_gateway.registry.tool_registry import ToolRegistry
         | 
| 22 | 
            +
            from claude_mpm.services.mcp_gateway.tools.base_adapter import (
         | 
| 23 | 
            +
                EchoToolAdapter,
         | 
| 24 | 
            +
                CalculatorToolAdapter,
         | 
| 25 | 
            +
                SystemInfoToolAdapter
         | 
| 26 | 
            +
            )
         | 
| 27 | 
            +
            from claude_mpm.services.mcp_gateway.tools.document_summarizer import DocumentSummarizerTool
         | 
| 28 | 
            +
            from claude_mpm.services.mcp_gateway.config.configuration import MCPConfiguration
         | 
| 29 | 
            +
            from claude_mpm.core.logger import get_logger
         | 
| 30 | 
            +
             | 
| 31 | 
            +
             | 
| 32 | 
            +
            class MCPGateway:
         | 
| 33 | 
            +
                """
         | 
| 34 | 
            +
                Main MCP Gateway orchestrator.
         | 
| 35 | 
            +
                
         | 
| 36 | 
            +
                WHY: This class coordinates all MCP components, managing their lifecycle
         | 
| 37 | 
            +
                and ensuring proper initialization, startup, and shutdown sequences.
         | 
| 38 | 
            +
                
         | 
| 39 | 
            +
                DESIGN DECISIONS:
         | 
| 40 | 
            +
                - Use dependency injection to wire components together
         | 
| 41 | 
            +
                - Implement graceful shutdown on SIGINT/SIGTERM
         | 
| 42 | 
            +
                - Support both configuration file and CLI arguments
         | 
| 43 | 
            +
                - Provide comprehensive logging for debugging
         | 
| 44 | 
            +
                """
         | 
| 45 | 
            +
                
         | 
| 46 | 
            +
                def __init__(self, config_path: Optional[Path] = None):
         | 
| 47 | 
            +
                    """
         | 
| 48 | 
            +
                    Initialize the MCP Gateway.
         | 
| 49 | 
            +
                    
         | 
| 50 | 
            +
                    Args:
         | 
| 51 | 
            +
                        config_path: Optional path to configuration file
         | 
| 52 | 
            +
                    """
         | 
| 53 | 
            +
                    self.logger = get_logger(self.__class__.__name__)
         | 
| 54 | 
            +
                    self.config_path = config_path
         | 
| 55 | 
            +
                    
         | 
| 56 | 
            +
                    # Core components
         | 
| 57 | 
            +
                    self.server: Optional[MCPServer] = None
         | 
| 58 | 
            +
                    self.registry: Optional[ToolRegistry] = None
         | 
| 59 | 
            +
                    self.communication: Optional[StdioHandler] = None
         | 
| 60 | 
            +
                    self.configuration: Optional[MCPConfiguration] = None
         | 
| 61 | 
            +
                    
         | 
| 62 | 
            +
                    # Shutdown handling
         | 
| 63 | 
            +
                    self._shutdown_event = asyncio.Event()
         | 
| 64 | 
            +
                    self._setup_signal_handlers()
         | 
| 65 | 
            +
                
         | 
| 66 | 
            +
                def _setup_signal_handlers(self) -> None:
         | 
| 67 | 
            +
                    """Setup signal handlers for graceful shutdown."""
         | 
| 68 | 
            +
                    def signal_handler(sig, frame):
         | 
| 69 | 
            +
                        self.logger.info(f"Received signal {sig}, initiating shutdown...")
         | 
| 70 | 
            +
                        self._shutdown_event.set()
         | 
| 71 | 
            +
                    
         | 
| 72 | 
            +
                    signal.signal(signal.SIGINT, signal_handler)
         | 
| 73 | 
            +
                    signal.signal(signal.SIGTERM, signal_handler)
         | 
| 74 | 
            +
                
         | 
| 75 | 
            +
                async def initialize(self) -> bool:
         | 
| 76 | 
            +
                    """
         | 
| 77 | 
            +
                    Initialize all MCP Gateway components.
         | 
| 78 | 
            +
                    
         | 
| 79 | 
            +
                    Returns:
         | 
| 80 | 
            +
                        True if initialization successful
         | 
| 81 | 
            +
                    """
         | 
| 82 | 
            +
                    try:
         | 
| 83 | 
            +
                        self.logger.info("Initializing MCP Gateway")
         | 
| 84 | 
            +
                        
         | 
| 85 | 
            +
                        # Load configuration
         | 
| 86 | 
            +
                        self.configuration = MCPConfiguration()
         | 
| 87 | 
            +
                        if self.config_path and self.config_path.exists():
         | 
| 88 | 
            +
                            if not self.configuration.load_config(self.config_path):
         | 
| 89 | 
            +
                                self.logger.error("Failed to load configuration")
         | 
| 90 | 
            +
                                return False
         | 
| 91 | 
            +
                        
         | 
| 92 | 
            +
                        # Initialize tool registry
         | 
| 93 | 
            +
                        self.registry = ToolRegistry()
         | 
| 94 | 
            +
                        if not await self.registry.initialize():
         | 
| 95 | 
            +
                            self.logger.error("Failed to initialize tool registry")
         | 
| 96 | 
            +
                            return False
         | 
| 97 | 
            +
                        
         | 
| 98 | 
            +
                        # Register built-in tools
         | 
| 99 | 
            +
                        await self._register_builtin_tools()
         | 
| 100 | 
            +
                        
         | 
| 101 | 
            +
                        # Initialize communication handler
         | 
| 102 | 
            +
                        self.communication = StdioHandler()
         | 
| 103 | 
            +
                        if not await self.communication.initialize():
         | 
| 104 | 
            +
                            self.logger.error("Failed to initialize communication handler")
         | 
| 105 | 
            +
                            return False
         | 
| 106 | 
            +
                        
         | 
| 107 | 
            +
                        # Initialize MCP server
         | 
| 108 | 
            +
                        server_name = self.configuration.get("server.name", "claude-mpm-mcp")
         | 
| 109 | 
            +
                        version = self.configuration.get("server.version", "1.0.0")
         | 
| 110 | 
            +
                        self.server = MCPServer(server_name=server_name, version=version)
         | 
| 111 | 
            +
                        
         | 
| 112 | 
            +
                        # Wire dependencies
         | 
| 113 | 
            +
                        self.server.set_tool_registry(self.registry)
         | 
| 114 | 
            +
                        self.server.set_communication(self.communication)
         | 
| 115 | 
            +
                        
         | 
| 116 | 
            +
                        if not await self.server.initialize():
         | 
| 117 | 
            +
                            self.logger.error("Failed to initialize MCP server")
         | 
| 118 | 
            +
                            return False
         | 
| 119 | 
            +
                        
         | 
| 120 | 
            +
                        self.logger.info("MCP Gateway initialized successfully")
         | 
| 121 | 
            +
                        return True
         | 
| 122 | 
            +
                        
         | 
| 123 | 
            +
                    except Exception as e:
         | 
| 124 | 
            +
                        self.logger.error(f"Failed to initialize MCP Gateway: {e}")
         | 
| 125 | 
            +
                        return False
         | 
| 126 | 
            +
                
         | 
| 127 | 
            +
                async def _register_builtin_tools(self) -> None:
         | 
| 128 | 
            +
                    """Register built-in tools with the registry."""
         | 
| 129 | 
            +
                    self.logger.info("Registering built-in tools")
         | 
| 130 | 
            +
                    
         | 
| 131 | 
            +
                    # Create tool adapters
         | 
| 132 | 
            +
                    tools = [
         | 
| 133 | 
            +
                        EchoToolAdapter(),
         | 
| 134 | 
            +
                        CalculatorToolAdapter(),
         | 
| 135 | 
            +
                        SystemInfoToolAdapter(),
         | 
| 136 | 
            +
                        DocumentSummarizerTool()  # ISS-0037: Document summarizer for memory optimization
         | 
| 137 | 
            +
                    ]
         | 
| 138 | 
            +
                    
         | 
| 139 | 
            +
                    # Register each tool
         | 
| 140 | 
            +
                    for tool in tools:
         | 
| 141 | 
            +
                        try:
         | 
| 142 | 
            +
                            # Initialize the tool
         | 
| 143 | 
            +
                            if await tool.initialize():
         | 
| 144 | 
            +
                                # Register with the registry
         | 
| 145 | 
            +
                                if self.registry.register_tool(tool, category="builtin"):
         | 
| 146 | 
            +
                                    self.logger.info(f"Registered tool: {tool.get_definition().name}")
         | 
| 147 | 
            +
                                else:
         | 
| 148 | 
            +
                                    self.logger.warning(f"Failed to register tool: {tool.get_definition().name}")
         | 
| 149 | 
            +
                            else:
         | 
| 150 | 
            +
                                self.logger.warning(f"Failed to initialize tool: {tool.get_definition().name}")
         | 
| 151 | 
            +
                        except Exception as e:
         | 
| 152 | 
            +
                            self.logger.error(f"Error registering tool {tool.get_definition().name}: {e}")
         | 
| 153 | 
            +
                
         | 
| 154 | 
            +
                async def start(self) -> bool:
         | 
| 155 | 
            +
                    """
         | 
| 156 | 
            +
                    Start the MCP Gateway server.
         | 
| 157 | 
            +
                    
         | 
| 158 | 
            +
                    Returns:
         | 
| 159 | 
            +
                        True if startup successful
         | 
| 160 | 
            +
                    """
         | 
| 161 | 
            +
                    try:
         | 
| 162 | 
            +
                        self.logger.info("Starting MCP Gateway")
         | 
| 163 | 
            +
                        
         | 
| 164 | 
            +
                        if not self.server:
         | 
| 165 | 
            +
                            self.logger.error("Server not initialized")
         | 
| 166 | 
            +
                            return False
         | 
| 167 | 
            +
                        
         | 
| 168 | 
            +
                        if not await self.server.start():
         | 
| 169 | 
            +
                            self.logger.error("Failed to start MCP server")
         | 
| 170 | 
            +
                            return False
         | 
| 171 | 
            +
                        
         | 
| 172 | 
            +
                        self.logger.info("MCP Gateway started successfully")
         | 
| 173 | 
            +
                        return True
         | 
| 174 | 
            +
                        
         | 
| 175 | 
            +
                    except Exception as e:
         | 
| 176 | 
            +
                        self.logger.error(f"Failed to start MCP Gateway: {e}")
         | 
| 177 | 
            +
                        return False
         | 
| 178 | 
            +
                
         | 
| 179 | 
            +
                async def run(self) -> None:
         | 
| 180 | 
            +
                    """
         | 
| 181 | 
            +
                    Run the MCP Gateway main loop.
         | 
| 182 | 
            +
                    
         | 
| 183 | 
            +
                    This method blocks until shutdown is requested.
         | 
| 184 | 
            +
                    """
         | 
| 185 | 
            +
                    try:
         | 
| 186 | 
            +
                        self.logger.info("MCP Gateway running")
         | 
| 187 | 
            +
                        
         | 
| 188 | 
            +
                        # Wait for shutdown signal
         | 
| 189 | 
            +
                        await self._shutdown_event.wait()
         | 
| 190 | 
            +
                        
         | 
| 191 | 
            +
                        self.logger.info("Shutdown signal received")
         | 
| 192 | 
            +
                        
         | 
| 193 | 
            +
                    except Exception as e:
         | 
| 194 | 
            +
                        self.logger.error(f"Error in MCP Gateway main loop: {e}")
         | 
| 195 | 
            +
                        raise
         | 
| 196 | 
            +
                
         | 
| 197 | 
            +
                async def shutdown(self) -> None:
         | 
| 198 | 
            +
                    """Shutdown the MCP Gateway gracefully."""
         | 
| 199 | 
            +
                    try:
         | 
| 200 | 
            +
                        self.logger.info("Shutting down MCP Gateway")
         | 
| 201 | 
            +
                        
         | 
| 202 | 
            +
                        # Shutdown server
         | 
| 203 | 
            +
                        if self.server:
         | 
| 204 | 
            +
                            await self.server.shutdown()
         | 
| 205 | 
            +
                        
         | 
| 206 | 
            +
                        # Shutdown registry (which will shutdown all tools)
         | 
| 207 | 
            +
                        if self.registry:
         | 
| 208 | 
            +
                            await self.registry.shutdown()
         | 
| 209 | 
            +
                        
         | 
| 210 | 
            +
                        # Shutdown communication handler
         | 
| 211 | 
            +
                        if self.communication:
         | 
| 212 | 
            +
                            await self.communication.shutdown()
         | 
| 213 | 
            +
                        
         | 
| 214 | 
            +
                        self.logger.info("MCP Gateway shutdown complete")
         | 
| 215 | 
            +
                        
         | 
| 216 | 
            +
                    except Exception as e:
         | 
| 217 | 
            +
                        self.logger.error(f"Error during shutdown: {e}")
         | 
| 218 | 
            +
             | 
| 219 | 
            +
             | 
| 220 | 
            +
            async def main(args: argparse.Namespace) -> int:
         | 
| 221 | 
            +
                """
         | 
| 222 | 
            +
                Main entry point for the MCP Gateway.
         | 
| 223 | 
            +
                
         | 
| 224 | 
            +
                Args:
         | 
| 225 | 
            +
                    args: Command line arguments
         | 
| 226 | 
            +
                    
         | 
| 227 | 
            +
                Returns:
         | 
| 228 | 
            +
                    Exit code (0 for success, 1 for failure)
         | 
| 229 | 
            +
                """
         | 
| 230 | 
            +
                # Setup logging
         | 
| 231 | 
            +
                log_level = logging.DEBUG if args.debug else logging.INFO
         | 
| 232 | 
            +
                logging.basicConfig(
         | 
| 233 | 
            +
                    level=log_level,
         | 
| 234 | 
            +
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
         | 
| 235 | 
            +
                )
         | 
| 236 | 
            +
                
         | 
| 237 | 
            +
                # Create gateway instance
         | 
| 238 | 
            +
                config_path = Path(args.config) if args.config else None
         | 
| 239 | 
            +
                gateway = MCPGateway(config_path=config_path)
         | 
| 240 | 
            +
                
         | 
| 241 | 
            +
                try:
         | 
| 242 | 
            +
                    # Initialize
         | 
| 243 | 
            +
                    if not await gateway.initialize():
         | 
| 244 | 
            +
                        logging.error("Failed to initialize MCP Gateway")
         | 
| 245 | 
            +
                        return 1
         | 
| 246 | 
            +
                    
         | 
| 247 | 
            +
                    # Start
         | 
| 248 | 
            +
                    if not await gateway.start():
         | 
| 249 | 
            +
                        logging.error("Failed to start MCP Gateway")
         | 
| 250 | 
            +
                        return 1
         | 
| 251 | 
            +
                    
         | 
| 252 | 
            +
                    # Run until shutdown
         | 
| 253 | 
            +
                    await gateway.run()
         | 
| 254 | 
            +
                    
         | 
| 255 | 
            +
                    # Graceful shutdown
         | 
| 256 | 
            +
                    await gateway.shutdown()
         | 
| 257 | 
            +
                    
         | 
| 258 | 
            +
                    return 0
         | 
| 259 | 
            +
                    
         | 
| 260 | 
            +
                except Exception as e:
         | 
| 261 | 
            +
                    logging.error(f"Unhandled exception: {e}")
         | 
| 262 | 
            +
                    await gateway.shutdown()
         | 
| 263 | 
            +
                    return 1
         | 
| 264 | 
            +
             | 
| 265 | 
            +
             | 
| 266 | 
            +
            def parse_arguments() -> argparse.Namespace:
         | 
| 267 | 
            +
                """
         | 
| 268 | 
            +
                Parse command line arguments.
         | 
| 269 | 
            +
                
         | 
| 270 | 
            +
                Returns:
         | 
| 271 | 
            +
                    Parsed arguments
         | 
| 272 | 
            +
                """
         | 
| 273 | 
            +
                parser = argparse.ArgumentParser(
         | 
| 274 | 
            +
                    description="Claude MPM MCP Gateway Server",
         | 
| 275 | 
            +
                    formatter_class=argparse.RawDescriptionHelpFormatter,
         | 
| 276 | 
            +
                    epilog="""
         | 
| 277 | 
            +
            Examples:
         | 
| 278 | 
            +
              # Run with default configuration
         | 
| 279 | 
            +
              python -m claude_mpm.services.mcp_gateway.main
         | 
| 280 | 
            +
              
         | 
| 281 | 
            +
              # Run with custom configuration file
         | 
| 282 | 
            +
              python -m claude_mpm.services.mcp_gateway.main --config /path/to/config.yaml
         | 
| 283 | 
            +
              
         | 
| 284 | 
            +
              # Run with debug logging
         | 
| 285 | 
            +
              python -m claude_mpm.services.mcp_gateway.main --debug
         | 
| 286 | 
            +
              
         | 
| 287 | 
            +
              # Run as MCP server for Claude Desktop
         | 
| 288 | 
            +
              python -m claude_mpm.services.mcp_gateway.main --stdio
         | 
| 289 | 
            +
                    """
         | 
| 290 | 
            +
                )
         | 
| 291 | 
            +
                
         | 
| 292 | 
            +
                parser.add_argument(
         | 
| 293 | 
            +
                    "--config",
         | 
| 294 | 
            +
                    type=str,
         | 
| 295 | 
            +
                    help="Path to configuration file"
         | 
| 296 | 
            +
                )
         | 
| 297 | 
            +
                
         | 
| 298 | 
            +
                parser.add_argument(
         | 
| 299 | 
            +
                    "--debug",
         | 
| 300 | 
            +
                    action="store_true",
         | 
| 301 | 
            +
                    help="Enable debug logging"
         | 
| 302 | 
            +
                )
         | 
| 303 | 
            +
                
         | 
| 304 | 
            +
                parser.add_argument(
         | 
| 305 | 
            +
                    "--stdio",
         | 
| 306 | 
            +
                    action="store_true",
         | 
| 307 | 
            +
                    default=True,
         | 
| 308 | 
            +
                    help="Use stdio for communication (default)"
         | 
| 309 | 
            +
                )
         | 
| 310 | 
            +
                
         | 
| 311 | 
            +
                parser.add_argument(
         | 
| 312 | 
            +
                    "--version",
         | 
| 313 | 
            +
                    action="version",
         | 
| 314 | 
            +
                    version="Claude MPM MCP Gateway 1.0.0"
         | 
| 315 | 
            +
                )
         | 
| 316 | 
            +
                
         | 
| 317 | 
            +
                return parser.parse_args()
         | 
| 318 | 
            +
             | 
| 319 | 
            +
             | 
| 320 | 
            +
            if __name__ == "__main__":
         | 
| 321 | 
            +
                # Parse arguments
         | 
| 322 | 
            +
                args = parse_arguments()
         | 
| 323 | 
            +
                
         | 
| 324 | 
            +
                # Run the gateway
         | 
| 325 | 
            +
                exit_code = asyncio.run(main(args))
         | 
| 326 | 
            +
                sys.exit(exit_code)
         |