claude-mpm 4.1.0__py3-none-any.whl → 4.1.2__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/BUILD_NUMBER +1 -1
- claude_mpm/VERSION +1 -1
- claude_mpm/__main__.py +1 -1
- claude_mpm/agents/BASE_PM.md +74 -46
- claude_mpm/agents/INSTRUCTIONS.md +11 -153
- claude_mpm/agents/WORKFLOW.md +61 -321
- claude_mpm/agents/__init__.py +11 -11
- claude_mpm/agents/agent_loader.py +23 -20
- claude_mpm/agents/agent_loader_integration.py +1 -1
- claude_mpm/agents/agents_metadata.py +27 -0
- claude_mpm/agents/async_agent_loader.py +5 -8
- claude_mpm/agents/base_agent_loader.py +36 -25
- claude_mpm/agents/frontmatter_validator.py +6 -6
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +9 -9
- claude_mpm/agents/templates/api_qa.json +47 -2
- claude_mpm/agents/templates/imagemagick.json +256 -0
- claude_mpm/agents/templates/qa.json +41 -2
- claude_mpm/agents/templates/ticketing.json +5 -5
- claude_mpm/agents/templates/web_qa.json +133 -58
- claude_mpm/agents/templates/web_ui.json +3 -3
- claude_mpm/cli/__init__.py +51 -46
- claude_mpm/cli/__main__.py +1 -1
- claude_mpm/cli/commands/__init__.py +10 -12
- claude_mpm/cli/commands/agent_manager.py +186 -181
- claude_mpm/cli/commands/agents.py +271 -268
- claude_mpm/cli/commands/aggregate.py +30 -29
- claude_mpm/cli/commands/cleanup.py +50 -44
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
- claude_mpm/cli/commands/config.py +162 -127
- claude_mpm/cli/commands/doctor.py +52 -62
- claude_mpm/cli/commands/info.py +37 -25
- claude_mpm/cli/commands/mcp.py +3 -7
- claude_mpm/cli/commands/mcp_command_router.py +14 -18
- claude_mpm/cli/commands/mcp_install_commands.py +28 -23
- claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
- claude_mpm/cli/commands/mcp_server_commands.py +23 -17
- claude_mpm/cli/commands/memory.py +192 -141
- claude_mpm/cli/commands/monitor.py +117 -88
- claude_mpm/cli/commands/run.py +120 -84
- claude_mpm/cli/commands/run_config_checker.py +4 -5
- claude_mpm/cli/commands/socketio_monitor.py +17 -19
- claude_mpm/cli/commands/tickets.py +92 -92
- claude_mpm/cli/parser.py +1 -5
- claude_mpm/cli/parsers/__init__.py +1 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
- claude_mpm/cli/parsers/agents_parser.py +2 -3
- claude_mpm/cli/parsers/base_parser.py +7 -5
- claude_mpm/cli/parsers/mcp_parser.py +4 -2
- claude_mpm/cli/parsers/monitor_parser.py +26 -18
- claude_mpm/cli/shared/__init__.py +10 -10
- claude_mpm/cli/shared/argument_patterns.py +57 -71
- claude_mpm/cli/shared/base_command.py +61 -53
- claude_mpm/cli/shared/error_handling.py +62 -58
- claude_mpm/cli/shared/output_formatters.py +78 -77
- claude_mpm/cli/startup_logging.py +204 -172
- claude_mpm/cli/utils.py +10 -11
- claude_mpm/cli_module/__init__.py +1 -1
- claude_mpm/cli_module/args.py +1 -1
- claude_mpm/cli_module/migration_example.py +5 -5
- claude_mpm/config/__init__.py +9 -9
- claude_mpm/config/agent_config.py +15 -14
- claude_mpm/config/experimental_features.py +4 -4
- claude_mpm/config/paths.py +0 -1
- claude_mpm/config/socketio_config.py +5 -6
- claude_mpm/constants.py +1 -2
- claude_mpm/core/__init__.py +8 -8
- claude_mpm/core/agent_name_normalizer.py +1 -1
- claude_mpm/core/agent_registry.py +20 -23
- claude_mpm/core/agent_session_manager.py +3 -3
- claude_mpm/core/base_service.py +7 -15
- claude_mpm/core/cache.py +4 -6
- claude_mpm/core/claude_runner.py +85 -113
- claude_mpm/core/config.py +43 -28
- claude_mpm/core/config_aliases.py +0 -9
- claude_mpm/core/config_constants.py +52 -30
- claude_mpm/core/constants.py +0 -1
- claude_mpm/core/container.py +18 -27
- claude_mpm/core/exceptions.py +2 -2
- claude_mpm/core/factories.py +10 -12
- claude_mpm/core/framework_loader.py +581 -280
- claude_mpm/core/hook_manager.py +26 -22
- claude_mpm/core/hook_performance_config.py +58 -47
- claude_mpm/core/injectable_service.py +1 -1
- claude_mpm/core/interactive_session.py +61 -152
- claude_mpm/core/interfaces.py +1 -100
- claude_mpm/core/lazy.py +5 -5
- claude_mpm/core/log_manager.py +587 -0
- claude_mpm/core/logger.py +125 -8
- claude_mpm/core/logging_config.py +15 -15
- claude_mpm/core/minimal_framework_loader.py +5 -8
- claude_mpm/core/oneshot_session.py +15 -33
- claude_mpm/core/optimized_agent_loader.py +4 -6
- claude_mpm/core/optimized_startup.py +2 -1
- claude_mpm/core/output_style_manager.py +147 -106
- claude_mpm/core/pm_hook_interceptor.py +0 -1
- claude_mpm/core/service_registry.py +11 -8
- claude_mpm/core/session_manager.py +1 -2
- claude_mpm/core/shared/__init__.py +1 -1
- claude_mpm/core/shared/config_loader.py +101 -97
- claude_mpm/core/shared/path_resolver.py +72 -68
- claude_mpm/core/shared/singleton_manager.py +56 -50
- claude_mpm/core/socketio_pool.py +26 -6
- claude_mpm/core/tool_access_control.py +4 -5
- claude_mpm/core/typing_utils.py +50 -59
- claude_mpm/core/unified_agent_registry.py +14 -19
- claude_mpm/core/unified_config.py +4 -6
- claude_mpm/core/unified_paths.py +197 -109
- claude_mpm/dashboard/open_dashboard.py +2 -4
- claude_mpm/experimental/cli_enhancements.py +51 -36
- claude_mpm/generators/agent_profile_generator.py +2 -4
- claude_mpm/hooks/base_hook.py +1 -2
- claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
- claude_mpm/hooks/claude_hooks/event_handlers.py +93 -38
- claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
- claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
- claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
- claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
- claude_mpm/hooks/memory_integration_hook.py +5 -5
- claude_mpm/hooks/tool_call_interceptor.py +1 -1
- claude_mpm/hooks/validation_hooks.py +4 -4
- claude_mpm/init.py +4 -9
- claude_mpm/models/__init__.py +2 -2
- claude_mpm/models/agent_session.py +11 -14
- claude_mpm/scripts/mcp_server.py +20 -11
- claude_mpm/scripts/mcp_wrapper.py +5 -5
- claude_mpm/scripts/mpm_doctor.py +321 -0
- claude_mpm/scripts/socketio_daemon.py +28 -25
- claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
- claude_mpm/scripts/socketio_server_manager.py +116 -95
- claude_mpm/services/__init__.py +49 -49
- claude_mpm/services/agent_capabilities_service.py +12 -18
- claude_mpm/services/agents/__init__.py +22 -22
- claude_mpm/services/agents/agent_builder.py +140 -119
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
- claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
- claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
- claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
- claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
- claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
- claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
- claude_mpm/services/agents/deployment/agent_validator.py +0 -1
- claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
- claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
- claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
- claude_mpm/services/agents/deployment/config/__init__.py +1 -1
- claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
- claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
- claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
- claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
- claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
- claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
- claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
- claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
- claude_mpm/services/agents/deployment/results/__init__.py +1 -1
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
- claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
- claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
- claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
- claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
- claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
- claude_mpm/services/agents/loading/__init__.py +1 -1
- claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
- claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
- claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
- claude_mpm/services/agents/management/__init__.py +1 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
- claude_mpm/services/agents/management/agent_management_service.py +5 -9
- claude_mpm/services/agents/memory/__init__.py +4 -4
- claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
- claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
- claude_mpm/services/agents/memory/content_manager.py +44 -38
- claude_mpm/services/agents/memory/template_generator.py +4 -6
- claude_mpm/services/agents/registry/__init__.py +10 -6
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
- claude_mpm/services/agents/registry/modification_tracker.py +3 -6
- claude_mpm/services/async_session_logger.py +1 -2
- claude_mpm/services/claude_session_logger.py +1 -2
- claude_mpm/services/command_deployment_service.py +173 -0
- claude_mpm/services/command_handler_service.py +20 -22
- claude_mpm/services/core/__init__.py +25 -25
- claude_mpm/services/core/base.py +0 -5
- claude_mpm/services/core/interfaces/__init__.py +32 -32
- claude_mpm/services/core/interfaces/agent.py +0 -21
- claude_mpm/services/core/interfaces/communication.py +0 -27
- claude_mpm/services/core/interfaces/infrastructure.py +0 -56
- claude_mpm/services/core/interfaces/service.py +0 -29
- claude_mpm/services/diagnostics/__init__.py +1 -1
- claude_mpm/services/diagnostics/checks/__init__.py +6 -6
- claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
- claude_mpm/services/diagnostics/checks/base_check.py +12 -16
- claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
- claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
- claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
- claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
- claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
- claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
- claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
- claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
- claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
- claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
- claude_mpm/services/diagnostics/models.py +21 -19
- claude_mpm/services/event_aggregator.py +10 -17
- claude_mpm/services/event_bus/__init__.py +1 -1
- claude_mpm/services/event_bus/config.py +54 -35
- claude_mpm/services/event_bus/event_bus.py +76 -71
- claude_mpm/services/event_bus/relay.py +74 -64
- claude_mpm/services/events/__init__.py +11 -11
- claude_mpm/services/events/consumers/__init__.py +3 -3
- claude_mpm/services/events/consumers/dead_letter.py +71 -63
- claude_mpm/services/events/consumers/logging.py +39 -37
- claude_mpm/services/events/consumers/metrics.py +56 -57
- claude_mpm/services/events/consumers/socketio.py +82 -81
- claude_mpm/services/events/core.py +110 -99
- claude_mpm/services/events/interfaces.py +56 -72
- claude_mpm/services/events/producers/__init__.py +1 -1
- claude_mpm/services/events/producers/hook.py +38 -38
- claude_mpm/services/events/producers/system.py +46 -44
- claude_mpm/services/exceptions.py +81 -80
- claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
- claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
- claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
- claude_mpm/services/hook_service.py +6 -9
- claude_mpm/services/infrastructure/__init__.py +1 -1
- claude_mpm/services/infrastructure/context_preservation.py +8 -12
- claude_mpm/services/infrastructure/monitoring.py +21 -23
- claude_mpm/services/mcp_gateway/__init__.py +37 -37
- claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
- claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
- claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
- claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
- claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
- claude_mpm/services/mcp_gateway/core/base.py +0 -3
- claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
- claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
- claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
- claude_mpm/services/mcp_gateway/main.py +2 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
- claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
- claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
- claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
- claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
- claude_mpm/services/memory/__init__.py +3 -3
- claude_mpm/services/memory/builder.py +3 -6
- claude_mpm/services/memory/cache/__init__.py +1 -1
- claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
- claude_mpm/services/memory/cache/simple_cache.py +1 -1
- claude_mpm/services/memory/indexed_memory.py +5 -7
- claude_mpm/services/memory/optimizer.py +7 -10
- claude_mpm/services/memory/router.py +8 -9
- claude_mpm/services/memory_hook_service.py +48 -34
- claude_mpm/services/monitor_build_service.py +77 -73
- claude_mpm/services/port_manager.py +130 -108
- claude_mpm/services/project/analyzer.py +12 -10
- claude_mpm/services/project/registry.py +11 -11
- claude_mpm/services/recovery_manager.py +10 -19
- claude_mpm/services/response_tracker.py +0 -1
- claude_mpm/services/runner_configuration_service.py +19 -20
- claude_mpm/services/session_management_service.py +7 -11
- claude_mpm/services/shared/__init__.py +1 -1
- claude_mpm/services/shared/async_service_base.py +58 -50
- claude_mpm/services/shared/config_service_base.py +73 -67
- claude_mpm/services/shared/lifecycle_service_base.py +82 -78
- claude_mpm/services/shared/manager_base.py +94 -82
- claude_mpm/services/shared/service_factory.py +96 -98
- claude_mpm/services/socketio/__init__.py +3 -3
- claude_mpm/services/socketio/client_proxy.py +5 -5
- claude_mpm/services/socketio/event_normalizer.py +199 -181
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +5 -4
- claude_mpm/services/socketio/handlers/connection.py +163 -136
- claude_mpm/services/socketio/handlers/file.py +13 -14
- claude_mpm/services/socketio/handlers/git.py +12 -7
- claude_mpm/services/socketio/handlers/hook.py +49 -44
- claude_mpm/services/socketio/handlers/memory.py +0 -1
- claude_mpm/services/socketio/handlers/project.py +0 -1
- claude_mpm/services/socketio/handlers/registry.py +37 -19
- claude_mpm/services/socketio/migration_utils.py +98 -84
- claude_mpm/services/socketio/server/__init__.py +1 -1
- claude_mpm/services/socketio/server/broadcaster.py +81 -87
- claude_mpm/services/socketio/server/core.py +65 -54
- claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
- claude_mpm/services/socketio/server/main.py +64 -38
- claude_mpm/services/socketio_client_manager.py +10 -12
- claude_mpm/services/subprocess_launcher_service.py +4 -7
- claude_mpm/services/system_instructions_service.py +13 -14
- claude_mpm/services/ticket_manager.py +2 -2
- claude_mpm/services/utility_service.py +5 -13
- claude_mpm/services/version_control/__init__.py +16 -16
- claude_mpm/services/version_control/branch_strategy.py +5 -8
- claude_mpm/services/version_control/conflict_resolution.py +9 -23
- claude_mpm/services/version_control/git_operations.py +5 -7
- claude_mpm/services/version_control/semantic_versioning.py +16 -17
- claude_mpm/services/version_control/version_parser.py +13 -18
- claude_mpm/services/version_service.py +10 -11
- claude_mpm/storage/__init__.py +1 -1
- claude_mpm/storage/state_storage.py +22 -28
- claude_mpm/utils/__init__.py +6 -6
- claude_mpm/utils/agent_dependency_loader.py +47 -33
- claude_mpm/utils/config_manager.py +11 -14
- claude_mpm/utils/dependency_cache.py +1 -1
- claude_mpm/utils/dependency_manager.py +13 -17
- claude_mpm/utils/dependency_strategies.py +8 -10
- claude_mpm/utils/environment_context.py +3 -9
- claude_mpm/utils/error_handler.py +3 -13
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/path_operations.py +8 -12
- claude_mpm/utils/robust_installer.py +110 -33
- claude_mpm/utils/subprocess_utils.py +5 -6
- claude_mpm/validation/agent_validator.py +3 -6
- claude_mpm/validation/frontmatter_validator.py +1 -1
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
- claude_mpm-4.1.2.dist-info/RECORD +498 -0
- claude_mpm-4.1.0.dist-info/RECORD +0 -494
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
|
@@ -19,11 +19,11 @@ DESIGN DECISIONS:
|
|
|
19
19
|
import asyncio
|
|
20
20
|
import os
|
|
21
21
|
import platform
|
|
22
|
-
import psutil
|
|
23
22
|
import sys
|
|
24
23
|
from datetime import datetime
|
|
25
|
-
from
|
|
26
|
-
|
|
24
|
+
from typing import Any, Dict
|
|
25
|
+
|
|
26
|
+
import psutil
|
|
27
27
|
|
|
28
28
|
from claude_mpm.config.paths import paths
|
|
29
29
|
from claude_mpm.core.logger import get_logger
|
|
@@ -38,11 +38,11 @@ from claude_mpm.services.mcp_gateway.tools.base_adapter import BaseToolAdapter
|
|
|
38
38
|
class HealthCheckTool(BaseToolAdapter):
|
|
39
39
|
"""
|
|
40
40
|
Comprehensive health check tool for MCP Gateway diagnostics.
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
Provides system health, gateway status, tool availability, and
|
|
43
43
|
configuration validation checks.
|
|
44
44
|
"""
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
def __init__(self):
|
|
47
47
|
"""Initialize the health check tool."""
|
|
48
48
|
definition = MCPToolDefinition(
|
|
@@ -75,34 +75,34 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
75
75
|
)
|
|
76
76
|
super().__init__(definition)
|
|
77
77
|
self.logger = get_logger("HealthCheckTool")
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
|
|
80
80
|
"""
|
|
81
81
|
Perform health checks based on the requested type.
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
Args:
|
|
84
84
|
invocation: Tool invocation request
|
|
85
|
-
|
|
85
|
+
|
|
86
86
|
Returns:
|
|
87
87
|
Tool execution result with health check results
|
|
88
88
|
"""
|
|
89
89
|
start_time = datetime.now()
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
try:
|
|
92
92
|
# Get parameters
|
|
93
93
|
check_type = invocation.parameters.get("check_type", "all")
|
|
94
94
|
detailed = invocation.parameters.get("detailed", False)
|
|
95
95
|
timeout = invocation.parameters.get("timeout", 30)
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
# Perform health checks
|
|
98
98
|
results = await self._perform_health_checks(check_type, detailed, timeout)
|
|
99
|
-
|
|
99
|
+
|
|
100
100
|
# Calculate execution time
|
|
101
101
|
execution_time = (datetime.now() - start_time).total_seconds()
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
# Update metrics
|
|
104
104
|
self._update_metrics(True, execution_time)
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
return MCPToolResult(
|
|
107
107
|
success=True,
|
|
108
108
|
data=results,
|
|
@@ -113,18 +113,18 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
113
113
|
"detailed": detailed,
|
|
114
114
|
},
|
|
115
115
|
)
|
|
116
|
-
|
|
116
|
+
|
|
117
117
|
except Exception as e:
|
|
118
118
|
execution_time = (datetime.now() - start_time).total_seconds()
|
|
119
119
|
self._update_metrics(False, execution_time)
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
return MCPToolResult(
|
|
122
122
|
success=False,
|
|
123
|
-
error=f"Health check failed: {
|
|
123
|
+
error=f"Health check failed: {e!s}",
|
|
124
124
|
execution_time=execution_time,
|
|
125
125
|
metadata={"tool": "health_check", "error": str(e)},
|
|
126
126
|
)
|
|
127
|
-
|
|
127
|
+
|
|
128
128
|
async def _perform_health_checks(
|
|
129
129
|
self, check_type: str, detailed: bool, timeout: int
|
|
130
130
|
) -> Dict[str, Any]:
|
|
@@ -137,14 +137,14 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
137
137
|
"checks": {},
|
|
138
138
|
"summary": {},
|
|
139
139
|
}
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
# Determine which checks to run
|
|
142
142
|
checks_to_run = []
|
|
143
143
|
if check_type == "all":
|
|
144
144
|
checks_to_run = ["system", "gateway", "tools", "config"]
|
|
145
145
|
else:
|
|
146
146
|
checks_to_run = [check_type]
|
|
147
|
-
|
|
147
|
+
|
|
148
148
|
# Run checks with timeout
|
|
149
149
|
try:
|
|
150
150
|
check_tasks = []
|
|
@@ -157,13 +157,12 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
157
157
|
check_tasks.append(self._check_tools_health(detailed))
|
|
158
158
|
elif check == "config":
|
|
159
159
|
check_tasks.append(self._check_config_health(detailed))
|
|
160
|
-
|
|
160
|
+
|
|
161
161
|
# Run all checks concurrently with timeout
|
|
162
162
|
check_results = await asyncio.wait_for(
|
|
163
|
-
asyncio.gather(*check_tasks, return_exceptions=True),
|
|
164
|
-
timeout=timeout
|
|
163
|
+
asyncio.gather(*check_tasks, return_exceptions=True), timeout=timeout
|
|
165
164
|
)
|
|
166
|
-
|
|
165
|
+
|
|
167
166
|
# Process results
|
|
168
167
|
for i, check_name in enumerate(checks_to_run):
|
|
169
168
|
if i < len(check_results):
|
|
@@ -179,19 +178,19 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
179
178
|
"status": "timeout",
|
|
180
179
|
"error": "Check timed out",
|
|
181
180
|
}
|
|
182
|
-
|
|
181
|
+
|
|
183
182
|
except asyncio.TimeoutError:
|
|
184
183
|
results["checks"]["timeout"] = {
|
|
185
184
|
"status": "error",
|
|
186
185
|
"error": f"Health checks timed out after {timeout} seconds",
|
|
187
186
|
}
|
|
188
|
-
|
|
187
|
+
|
|
189
188
|
# Calculate overall status and summary
|
|
190
189
|
results["overall_status"] = self._calculate_overall_status(results["checks"])
|
|
191
190
|
results["summary"] = self._generate_summary(results["checks"])
|
|
192
|
-
|
|
191
|
+
|
|
193
192
|
return results
|
|
194
|
-
|
|
193
|
+
|
|
195
194
|
async def _check_system_health(self, detailed: bool) -> Dict[str, Any]:
|
|
196
195
|
"""Check system health (CPU, memory, disk, etc.)."""
|
|
197
196
|
check_result = {
|
|
@@ -200,7 +199,7 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
200
199
|
"warnings": [],
|
|
201
200
|
"errors": [],
|
|
202
201
|
}
|
|
203
|
-
|
|
202
|
+
|
|
204
203
|
try:
|
|
205
204
|
# Basic system info
|
|
206
205
|
check_result["checks"]["platform"] = {
|
|
@@ -208,7 +207,7 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
208
207
|
"release": platform.release(),
|
|
209
208
|
"python_version": sys.version,
|
|
210
209
|
}
|
|
211
|
-
|
|
210
|
+
|
|
212
211
|
# Memory check
|
|
213
212
|
memory = psutil.virtual_memory()
|
|
214
213
|
memory_usage = memory.percent
|
|
@@ -217,26 +216,26 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
217
216
|
"available_gb": round(memory.available / (1024**3), 2),
|
|
218
217
|
"total_gb": round(memory.total / (1024**3), 2),
|
|
219
218
|
}
|
|
220
|
-
|
|
219
|
+
|
|
221
220
|
if memory_usage > 90:
|
|
222
221
|
check_result["errors"].append("High memory usage detected")
|
|
223
222
|
check_result["status"] = "unhealthy"
|
|
224
223
|
elif memory_usage > 80:
|
|
225
224
|
check_result["warnings"].append("Elevated memory usage")
|
|
226
|
-
|
|
225
|
+
|
|
227
226
|
# CPU check
|
|
228
227
|
cpu_usage = psutil.cpu_percent(interval=1)
|
|
229
228
|
check_result["checks"]["cpu"] = {
|
|
230
229
|
"usage_percent": cpu_usage,
|
|
231
230
|
"count": psutil.cpu_count(),
|
|
232
231
|
}
|
|
233
|
-
|
|
232
|
+
|
|
234
233
|
if cpu_usage > 95:
|
|
235
234
|
check_result["errors"].append("High CPU usage detected")
|
|
236
235
|
check_result["status"] = "unhealthy"
|
|
237
236
|
elif cpu_usage > 80:
|
|
238
237
|
check_result["warnings"].append("Elevated CPU usage")
|
|
239
|
-
|
|
238
|
+
|
|
240
239
|
# Disk check for claude-mpm data directory
|
|
241
240
|
if paths.data_dir.exists():
|
|
242
241
|
disk_usage = psutil.disk_usage(str(paths.data_dir))
|
|
@@ -246,13 +245,13 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
246
245
|
"free_gb": round(disk_usage.free / (1024**3), 2),
|
|
247
246
|
"total_gb": round(disk_usage.total / (1024**3), 2),
|
|
248
247
|
}
|
|
249
|
-
|
|
248
|
+
|
|
250
249
|
if disk_usage_percent > 95:
|
|
251
250
|
check_result["errors"].append("Disk space critically low")
|
|
252
251
|
check_result["status"] = "unhealthy"
|
|
253
252
|
elif disk_usage_percent > 85:
|
|
254
253
|
check_result["warnings"].append("Disk space running low")
|
|
255
|
-
|
|
254
|
+
|
|
256
255
|
# Process check
|
|
257
256
|
current_process = psutil.Process()
|
|
258
257
|
check_result["checks"]["process"] = {
|
|
@@ -261,13 +260,13 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
261
260
|
"cpu_percent": current_process.cpu_percent(),
|
|
262
261
|
"threads": current_process.num_threads(),
|
|
263
262
|
}
|
|
264
|
-
|
|
263
|
+
|
|
265
264
|
except Exception as e:
|
|
266
265
|
check_result["status"] = "error"
|
|
267
266
|
check_result["errors"].append(f"System health check failed: {e}")
|
|
268
|
-
|
|
267
|
+
|
|
269
268
|
return check_result
|
|
270
|
-
|
|
269
|
+
|
|
271
270
|
async def _check_gateway_health(self, detailed: bool) -> Dict[str, Any]:
|
|
272
271
|
"""Check MCP Gateway health."""
|
|
273
272
|
check_result = {
|
|
@@ -276,41 +275,41 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
276
275
|
"warnings": [],
|
|
277
276
|
"errors": [],
|
|
278
277
|
}
|
|
279
|
-
|
|
278
|
+
|
|
280
279
|
try:
|
|
281
280
|
# Check singleton manager
|
|
282
281
|
from ..core.singleton_manager import get_gateway_manager, is_gateway_running
|
|
283
|
-
|
|
282
|
+
|
|
284
283
|
manager = get_gateway_manager()
|
|
285
284
|
check_result["checks"]["singleton_manager"] = {
|
|
286
285
|
"available": True,
|
|
287
286
|
"gateway_running": is_gateway_running(),
|
|
288
287
|
}
|
|
289
|
-
|
|
288
|
+
|
|
290
289
|
# Check gateway instance info
|
|
291
290
|
instance_info = manager.get_running_instance_info()
|
|
292
291
|
if instance_info:
|
|
293
292
|
check_result["checks"]["instance"] = instance_info
|
|
294
293
|
else:
|
|
295
294
|
check_result["warnings"].append("No gateway instance currently running")
|
|
296
|
-
|
|
295
|
+
|
|
297
296
|
# Check MCP directories
|
|
298
297
|
mcp_dir = paths.data_dir / "mcp"
|
|
299
298
|
check_result["checks"]["directories"] = {
|
|
300
299
|
"mcp_dir_exists": mcp_dir.exists(),
|
|
301
300
|
"mcp_dir_writable": mcp_dir.exists() and os.access(mcp_dir, os.W_OK),
|
|
302
301
|
}
|
|
303
|
-
|
|
302
|
+
|
|
304
303
|
if not mcp_dir.exists():
|
|
305
304
|
check_result["errors"].append("MCP directory does not exist")
|
|
306
305
|
check_result["status"] = "unhealthy"
|
|
307
|
-
|
|
306
|
+
|
|
308
307
|
except Exception as e:
|
|
309
308
|
check_result["status"] = "error"
|
|
310
309
|
check_result["errors"].append(f"Gateway health check failed: {e}")
|
|
311
|
-
|
|
310
|
+
|
|
312
311
|
return check_result
|
|
313
|
-
|
|
312
|
+
|
|
314
313
|
async def _check_tools_health(self, detailed: bool) -> Dict[str, Any]:
|
|
315
314
|
"""Check MCP tools health."""
|
|
316
315
|
check_result = {
|
|
@@ -319,48 +318,50 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
319
318
|
"warnings": [],
|
|
320
319
|
"errors": [],
|
|
321
320
|
}
|
|
322
|
-
|
|
321
|
+
|
|
323
322
|
try:
|
|
324
323
|
# Try to import and check tool registry
|
|
325
324
|
from ..registry.tool_registry import ToolRegistry
|
|
326
|
-
|
|
325
|
+
|
|
327
326
|
registry = ToolRegistry()
|
|
328
327
|
await registry.initialize()
|
|
329
|
-
|
|
328
|
+
|
|
330
329
|
# Get tool list
|
|
331
330
|
tools = registry.list_tools()
|
|
332
331
|
check_result["checks"]["tool_count"] = len(tools)
|
|
333
332
|
check_result["checks"]["tools"] = [tool.name for tool in tools]
|
|
334
|
-
|
|
333
|
+
|
|
335
334
|
# Check essential tools
|
|
336
335
|
essential_tools = ["echo", "calculator", "system_info"]
|
|
337
336
|
available_essential = []
|
|
338
337
|
missing_essential = []
|
|
339
|
-
|
|
338
|
+
|
|
340
339
|
for tool_name in essential_tools:
|
|
341
340
|
if registry.get_tool(tool_name):
|
|
342
341
|
available_essential.append(tool_name)
|
|
343
342
|
else:
|
|
344
343
|
missing_essential.append(tool_name)
|
|
345
|
-
|
|
344
|
+
|
|
346
345
|
check_result["checks"]["essential_tools"] = {
|
|
347
346
|
"available": available_essential,
|
|
348
347
|
"missing": missing_essential,
|
|
349
348
|
}
|
|
350
|
-
|
|
349
|
+
|
|
351
350
|
if missing_essential:
|
|
352
|
-
check_result["warnings"].append(
|
|
353
|
-
|
|
351
|
+
check_result["warnings"].append(
|
|
352
|
+
f"Missing essential tools: {missing_essential}"
|
|
353
|
+
)
|
|
354
|
+
|
|
354
355
|
if len(available_essential) == 0:
|
|
355
356
|
check_result["status"] = "unhealthy"
|
|
356
357
|
check_result["errors"].append("No essential tools available")
|
|
357
|
-
|
|
358
|
+
|
|
358
359
|
except Exception as e:
|
|
359
360
|
check_result["status"] = "error"
|
|
360
361
|
check_result["errors"].append(f"Tools health check failed: {e}")
|
|
361
|
-
|
|
362
|
+
|
|
362
363
|
return check_result
|
|
363
|
-
|
|
364
|
+
|
|
364
365
|
async def _check_config_health(self, detailed: bool) -> Dict[str, Any]:
|
|
365
366
|
"""Check configuration health."""
|
|
366
367
|
check_result = {
|
|
@@ -369,27 +370,28 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
369
370
|
"warnings": [],
|
|
370
371
|
"errors": [],
|
|
371
372
|
}
|
|
372
|
-
|
|
373
|
+
|
|
373
374
|
try:
|
|
374
375
|
# Check configuration files
|
|
375
376
|
config_dir = paths.data_dir / "mcp"
|
|
376
377
|
config_file = config_dir / "gateway_config.json"
|
|
377
|
-
|
|
378
|
+
|
|
378
379
|
check_result["checks"]["config_dir"] = config_dir.exists()
|
|
379
380
|
check_result["checks"]["config_file"] = config_file.exists()
|
|
380
|
-
|
|
381
|
+
|
|
381
382
|
if config_file.exists():
|
|
382
383
|
# Try to load configuration
|
|
383
384
|
import json
|
|
384
|
-
|
|
385
|
+
|
|
386
|
+
with open(config_file) as f:
|
|
385
387
|
config_data = json.load(f)
|
|
386
|
-
|
|
388
|
+
|
|
387
389
|
check_result["checks"]["config_valid"] = True
|
|
388
390
|
if detailed:
|
|
389
391
|
check_result["checks"]["config_content"] = config_data
|
|
390
392
|
else:
|
|
391
393
|
check_result["warnings"].append("Gateway configuration file not found")
|
|
392
|
-
|
|
394
|
+
|
|
393
395
|
# Check paths
|
|
394
396
|
check_result["checks"]["paths"] = {
|
|
395
397
|
"data_dir": str(paths.data_dir),
|
|
@@ -397,31 +399,30 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
397
399
|
"data_dir_exists": paths.data_dir.exists(),
|
|
398
400
|
"logs_dir_exists": paths.logs_dir.exists(),
|
|
399
401
|
}
|
|
400
|
-
|
|
402
|
+
|
|
401
403
|
except Exception as e:
|
|
402
404
|
check_result["status"] = "error"
|
|
403
405
|
check_result["errors"].append(f"Config health check failed: {e}")
|
|
404
|
-
|
|
406
|
+
|
|
405
407
|
return check_result
|
|
406
|
-
|
|
408
|
+
|
|
407
409
|
def _calculate_overall_status(self, checks: Dict[str, Any]) -> str:
|
|
408
410
|
"""Calculate overall health status from individual checks."""
|
|
409
411
|
if not checks:
|
|
410
412
|
return "unknown"
|
|
411
|
-
|
|
413
|
+
|
|
412
414
|
statuses = [check.get("status", "unknown") for check in checks.values()]
|
|
413
|
-
|
|
415
|
+
|
|
414
416
|
if "error" in statuses:
|
|
415
417
|
return "error"
|
|
416
|
-
|
|
418
|
+
if "unhealthy" in statuses:
|
|
417
419
|
return "unhealthy"
|
|
418
|
-
|
|
420
|
+
if "warning" in statuses:
|
|
419
421
|
return "warning"
|
|
420
|
-
|
|
422
|
+
if all(status == "healthy" for status in statuses):
|
|
421
423
|
return "healthy"
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
424
|
+
return "unknown"
|
|
425
|
+
|
|
425
426
|
def _generate_summary(self, checks: Dict[str, Any]) -> Dict[str, Any]:
|
|
426
427
|
"""Generate a summary of health check results."""
|
|
427
428
|
summary = {
|
|
@@ -431,10 +432,10 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
431
432
|
"errors": 0,
|
|
432
433
|
"issues": [],
|
|
433
434
|
}
|
|
434
|
-
|
|
435
|
+
|
|
435
436
|
for check_name, check_result in checks.items():
|
|
436
437
|
status = check_result.get("status", "unknown")
|
|
437
|
-
|
|
438
|
+
|
|
438
439
|
if status == "healthy":
|
|
439
440
|
summary["healthy"] += 1
|
|
440
441
|
elif status in ["warning", "unhealthy"]:
|
|
@@ -449,5 +450,5 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
449
450
|
errors = check_result.get("errors", [])
|
|
450
451
|
for error in errors:
|
|
451
452
|
summary["issues"].append(f"{check_name}: {error}")
|
|
452
|
-
|
|
453
|
+
|
|
453
454
|
return summary
|
|
@@ -395,7 +395,7 @@ class HelloWorldTool(BaseToolAdapter):
|
|
|
395
395
|
|
|
396
396
|
return MCPToolResult(
|
|
397
397
|
success=False,
|
|
398
|
-
error=f"Hello World tool failed: {
|
|
398
|
+
error=f"Hello World tool failed: {e!s}",
|
|
399
399
|
execution_time=execution_time,
|
|
400
400
|
)
|
|
401
401
|
|
|
@@ -426,8 +426,7 @@ class HelloWorldTool(BaseToolAdapter):
|
|
|
426
426
|
if name:
|
|
427
427
|
# Add name if provided (works for most languages)
|
|
428
428
|
return f"{greeting_word}, {name}!"
|
|
429
|
-
|
|
430
|
-
return f"{greeting_word}, World!"
|
|
429
|
+
return f"{greeting_word}, World!"
|
|
431
430
|
|
|
432
431
|
async def _system_info_greeting(self) -> str:
|
|
433
432
|
"""Generate a greeting with system information."""
|
|
@@ -458,21 +457,20 @@ class HelloWorldTool(BaseToolAdapter):
|
|
|
458
457
|
error="Simulated validation error: Invalid input parameters",
|
|
459
458
|
execution_time=0.001,
|
|
460
459
|
)
|
|
461
|
-
|
|
460
|
+
if error_type == "runtime":
|
|
462
461
|
# Simulate a runtime error
|
|
463
462
|
raise RuntimeError("Simulated runtime error during greeting generation")
|
|
464
|
-
|
|
463
|
+
if error_type == "timeout":
|
|
465
464
|
# Simulate a timeout by sleeping longer than reasonable
|
|
466
465
|
await asyncio.sleep(10) # This would typically trigger a timeout
|
|
467
466
|
return MCPToolResult(
|
|
468
467
|
success=False, error="Operation timed out", execution_time=10.0
|
|
469
468
|
)
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
)
|
|
469
|
+
return MCPToolResult(
|
|
470
|
+
success=False,
|
|
471
|
+
error=f"Unknown error type: {error_type}",
|
|
472
|
+
execution_time=0.001,
|
|
473
|
+
)
|
|
476
474
|
|
|
477
475
|
def _add_to_history(self, mode: str, greeting: str, execution_time: float) -> None:
|
|
478
476
|
"""
|
|
@@ -524,9 +522,9 @@ class HelloWorldTool(BaseToolAdapter):
|
|
|
524
522
|
"total_greetings": len(self.greeting_history),
|
|
525
523
|
"modes_used": modes_used,
|
|
526
524
|
"average_execution_time": total_time / len(self.greeting_history),
|
|
527
|
-
"last_greeting":
|
|
528
|
-
|
|
529
|
-
|
|
525
|
+
"last_greeting": (
|
|
526
|
+
self.greeting_history[-1] if self.greeting_history else None
|
|
527
|
+
),
|
|
530
528
|
"metrics": self.get_metrics(),
|
|
531
529
|
}
|
|
532
530
|
|