claude-mpm 4.1.1__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.
Files changed (357) hide show
  1. claude_mpm/BUILD_NUMBER +1 -1
  2. claude_mpm/VERSION +1 -1
  3. claude_mpm/__main__.py +1 -1
  4. claude_mpm/agents/BASE_PM.md +74 -46
  5. claude_mpm/agents/INSTRUCTIONS.md +11 -153
  6. claude_mpm/agents/WORKFLOW.md +61 -321
  7. claude_mpm/agents/__init__.py +11 -11
  8. claude_mpm/agents/agent_loader.py +23 -20
  9. claude_mpm/agents/agent_loader_integration.py +1 -1
  10. claude_mpm/agents/agents_metadata.py +27 -0
  11. claude_mpm/agents/async_agent_loader.py +5 -8
  12. claude_mpm/agents/base_agent_loader.py +36 -25
  13. claude_mpm/agents/frontmatter_validator.py +6 -6
  14. claude_mpm/agents/schema/agent_schema.json +1 -1
  15. claude_mpm/agents/system_agent_config.py +9 -9
  16. claude_mpm/agents/templates/api_qa.json +47 -2
  17. claude_mpm/agents/templates/imagemagick.json +256 -0
  18. claude_mpm/agents/templates/qa.json +41 -2
  19. claude_mpm/agents/templates/ticketing.json +5 -5
  20. claude_mpm/agents/templates/web_qa.json +50 -2
  21. claude_mpm/cli/__init__.py +51 -46
  22. claude_mpm/cli/__main__.py +1 -1
  23. claude_mpm/cli/commands/__init__.py +10 -12
  24. claude_mpm/cli/commands/agent_manager.py +186 -181
  25. claude_mpm/cli/commands/agents.py +271 -268
  26. claude_mpm/cli/commands/aggregate.py +30 -29
  27. claude_mpm/cli/commands/cleanup.py +50 -44
  28. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  29. claude_mpm/cli/commands/config.py +162 -127
  30. claude_mpm/cli/commands/doctor.py +52 -62
  31. claude_mpm/cli/commands/info.py +37 -25
  32. claude_mpm/cli/commands/mcp.py +3 -7
  33. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  34. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  35. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  36. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  37. claude_mpm/cli/commands/memory.py +192 -141
  38. claude_mpm/cli/commands/monitor.py +117 -88
  39. claude_mpm/cli/commands/run.py +120 -84
  40. claude_mpm/cli/commands/run_config_checker.py +4 -5
  41. claude_mpm/cli/commands/socketio_monitor.py +17 -19
  42. claude_mpm/cli/commands/tickets.py +92 -92
  43. claude_mpm/cli/parser.py +1 -5
  44. claude_mpm/cli/parsers/__init__.py +1 -1
  45. claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
  46. claude_mpm/cli/parsers/agents_parser.py +2 -3
  47. claude_mpm/cli/parsers/base_parser.py +7 -5
  48. claude_mpm/cli/parsers/mcp_parser.py +4 -2
  49. claude_mpm/cli/parsers/monitor_parser.py +26 -18
  50. claude_mpm/cli/shared/__init__.py +10 -10
  51. claude_mpm/cli/shared/argument_patterns.py +57 -71
  52. claude_mpm/cli/shared/base_command.py +61 -53
  53. claude_mpm/cli/shared/error_handling.py +62 -58
  54. claude_mpm/cli/shared/output_formatters.py +78 -77
  55. claude_mpm/cli/startup_logging.py +204 -172
  56. claude_mpm/cli/utils.py +10 -11
  57. claude_mpm/cli_module/__init__.py +1 -1
  58. claude_mpm/cli_module/args.py +1 -1
  59. claude_mpm/cli_module/migration_example.py +5 -5
  60. claude_mpm/config/__init__.py +9 -9
  61. claude_mpm/config/agent_config.py +15 -14
  62. claude_mpm/config/experimental_features.py +4 -4
  63. claude_mpm/config/paths.py +0 -1
  64. claude_mpm/config/socketio_config.py +5 -6
  65. claude_mpm/constants.py +1 -2
  66. claude_mpm/core/__init__.py +8 -8
  67. claude_mpm/core/agent_name_normalizer.py +1 -1
  68. claude_mpm/core/agent_registry.py +20 -23
  69. claude_mpm/core/agent_session_manager.py +3 -3
  70. claude_mpm/core/base_service.py +7 -15
  71. claude_mpm/core/cache.py +4 -6
  72. claude_mpm/core/claude_runner.py +85 -113
  73. claude_mpm/core/config.py +43 -28
  74. claude_mpm/core/config_aliases.py +0 -9
  75. claude_mpm/core/config_constants.py +52 -30
  76. claude_mpm/core/constants.py +0 -1
  77. claude_mpm/core/container.py +18 -27
  78. claude_mpm/core/exceptions.py +2 -2
  79. claude_mpm/core/factories.py +10 -12
  80. claude_mpm/core/framework_loader.py +581 -280
  81. claude_mpm/core/hook_manager.py +26 -22
  82. claude_mpm/core/hook_performance_config.py +58 -47
  83. claude_mpm/core/injectable_service.py +1 -1
  84. claude_mpm/core/interactive_session.py +61 -152
  85. claude_mpm/core/interfaces.py +1 -100
  86. claude_mpm/core/lazy.py +5 -5
  87. claude_mpm/core/log_manager.py +587 -0
  88. claude_mpm/core/logger.py +125 -8
  89. claude_mpm/core/logging_config.py +15 -15
  90. claude_mpm/core/minimal_framework_loader.py +5 -8
  91. claude_mpm/core/oneshot_session.py +15 -33
  92. claude_mpm/core/optimized_agent_loader.py +4 -6
  93. claude_mpm/core/optimized_startup.py +2 -1
  94. claude_mpm/core/output_style_manager.py +147 -106
  95. claude_mpm/core/pm_hook_interceptor.py +0 -1
  96. claude_mpm/core/service_registry.py +11 -8
  97. claude_mpm/core/session_manager.py +1 -2
  98. claude_mpm/core/shared/__init__.py +1 -1
  99. claude_mpm/core/shared/config_loader.py +101 -97
  100. claude_mpm/core/shared/path_resolver.py +72 -68
  101. claude_mpm/core/shared/singleton_manager.py +56 -50
  102. claude_mpm/core/socketio_pool.py +26 -6
  103. claude_mpm/core/tool_access_control.py +4 -5
  104. claude_mpm/core/typing_utils.py +50 -59
  105. claude_mpm/core/unified_agent_registry.py +14 -19
  106. claude_mpm/core/unified_config.py +4 -6
  107. claude_mpm/core/unified_paths.py +197 -109
  108. claude_mpm/dashboard/open_dashboard.py +2 -4
  109. claude_mpm/experimental/cli_enhancements.py +51 -36
  110. claude_mpm/generators/agent_profile_generator.py +2 -4
  111. claude_mpm/hooks/base_hook.py +1 -2
  112. claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
  113. claude_mpm/hooks/claude_hooks/event_handlers.py +93 -38
  114. claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
  115. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  116. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  117. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  118. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  119. claude_mpm/hooks/memory_integration_hook.py +5 -5
  120. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  121. claude_mpm/hooks/validation_hooks.py +4 -4
  122. claude_mpm/init.py +4 -9
  123. claude_mpm/models/__init__.py +2 -2
  124. claude_mpm/models/agent_session.py +11 -14
  125. claude_mpm/scripts/mcp_server.py +20 -11
  126. claude_mpm/scripts/mcp_wrapper.py +5 -5
  127. claude_mpm/scripts/mpm_doctor.py +321 -0
  128. claude_mpm/scripts/socketio_daemon.py +28 -25
  129. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  130. claude_mpm/scripts/socketio_server_manager.py +116 -95
  131. claude_mpm/services/__init__.py +49 -49
  132. claude_mpm/services/agent_capabilities_service.py +12 -18
  133. claude_mpm/services/agents/__init__.py +22 -22
  134. claude_mpm/services/agents/agent_builder.py +140 -119
  135. claude_mpm/services/agents/deployment/__init__.py +3 -3
  136. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  137. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  138. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  139. claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
  140. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  141. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  142. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  143. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  144. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  145. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  146. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  147. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  148. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  149. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  150. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  151. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  152. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  153. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  154. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  155. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  156. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  157. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  158. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  159. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  160. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  161. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  162. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  163. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  164. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  165. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  166. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  167. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  168. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  169. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  170. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  171. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  172. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  173. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  174. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  175. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  176. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  177. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  178. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  179. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  180. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  181. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  182. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  183. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  184. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  185. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  186. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  187. claude_mpm/services/agents/loading/__init__.py +1 -1
  188. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  189. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  190. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  191. claude_mpm/services/agents/management/__init__.py +1 -1
  192. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  193. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  194. claude_mpm/services/agents/memory/__init__.py +4 -4
  195. claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
  196. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  197. claude_mpm/services/agents/memory/content_manager.py +44 -38
  198. claude_mpm/services/agents/memory/template_generator.py +4 -6
  199. claude_mpm/services/agents/registry/__init__.py +10 -6
  200. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  201. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  202. claude_mpm/services/async_session_logger.py +1 -2
  203. claude_mpm/services/claude_session_logger.py +1 -2
  204. claude_mpm/services/command_deployment_service.py +173 -0
  205. claude_mpm/services/command_handler_service.py +20 -22
  206. claude_mpm/services/core/__init__.py +25 -25
  207. claude_mpm/services/core/base.py +0 -5
  208. claude_mpm/services/core/interfaces/__init__.py +32 -32
  209. claude_mpm/services/core/interfaces/agent.py +0 -21
  210. claude_mpm/services/core/interfaces/communication.py +0 -27
  211. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  212. claude_mpm/services/core/interfaces/service.py +0 -29
  213. claude_mpm/services/diagnostics/__init__.py +1 -1
  214. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  215. claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
  216. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  217. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  218. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  219. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  220. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  221. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  222. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  223. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  224. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  225. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  226. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  227. claude_mpm/services/diagnostics/models.py +21 -19
  228. claude_mpm/services/event_aggregator.py +10 -17
  229. claude_mpm/services/event_bus/__init__.py +1 -1
  230. claude_mpm/services/event_bus/config.py +54 -35
  231. claude_mpm/services/event_bus/event_bus.py +76 -71
  232. claude_mpm/services/event_bus/relay.py +74 -64
  233. claude_mpm/services/events/__init__.py +11 -11
  234. claude_mpm/services/events/consumers/__init__.py +3 -3
  235. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  236. claude_mpm/services/events/consumers/logging.py +39 -37
  237. claude_mpm/services/events/consumers/metrics.py +56 -57
  238. claude_mpm/services/events/consumers/socketio.py +82 -81
  239. claude_mpm/services/events/core.py +110 -99
  240. claude_mpm/services/events/interfaces.py +56 -72
  241. claude_mpm/services/events/producers/__init__.py +1 -1
  242. claude_mpm/services/events/producers/hook.py +38 -38
  243. claude_mpm/services/events/producers/system.py +46 -44
  244. claude_mpm/services/exceptions.py +81 -80
  245. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  246. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  247. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  248. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  249. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  250. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  251. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  252. claude_mpm/services/hook_service.py +6 -9
  253. claude_mpm/services/infrastructure/__init__.py +1 -1
  254. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  255. claude_mpm/services/infrastructure/monitoring.py +21 -23
  256. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  257. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  258. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  259. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  260. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  261. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  262. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  263. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  264. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  265. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  266. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  267. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  268. claude_mpm/services/mcp_gateway/main.py +2 -1
  269. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  270. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  271. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  272. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  273. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  274. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  275. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  276. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  277. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  278. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  279. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  280. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  281. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  282. claude_mpm/services/memory/__init__.py +3 -3
  283. claude_mpm/services/memory/builder.py +3 -6
  284. claude_mpm/services/memory/cache/__init__.py +1 -1
  285. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  286. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  287. claude_mpm/services/memory/indexed_memory.py +5 -7
  288. claude_mpm/services/memory/optimizer.py +7 -10
  289. claude_mpm/services/memory/router.py +8 -9
  290. claude_mpm/services/memory_hook_service.py +48 -34
  291. claude_mpm/services/monitor_build_service.py +77 -73
  292. claude_mpm/services/port_manager.py +130 -108
  293. claude_mpm/services/project/analyzer.py +12 -10
  294. claude_mpm/services/project/registry.py +11 -11
  295. claude_mpm/services/recovery_manager.py +10 -19
  296. claude_mpm/services/response_tracker.py +0 -1
  297. claude_mpm/services/runner_configuration_service.py +19 -20
  298. claude_mpm/services/session_management_service.py +7 -11
  299. claude_mpm/services/shared/__init__.py +1 -1
  300. claude_mpm/services/shared/async_service_base.py +58 -50
  301. claude_mpm/services/shared/config_service_base.py +73 -67
  302. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  303. claude_mpm/services/shared/manager_base.py +94 -82
  304. claude_mpm/services/shared/service_factory.py +96 -98
  305. claude_mpm/services/socketio/__init__.py +3 -3
  306. claude_mpm/services/socketio/client_proxy.py +5 -5
  307. claude_mpm/services/socketio/event_normalizer.py +199 -181
  308. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  309. claude_mpm/services/socketio/handlers/base.py +5 -4
  310. claude_mpm/services/socketio/handlers/connection.py +163 -136
  311. claude_mpm/services/socketio/handlers/file.py +13 -14
  312. claude_mpm/services/socketio/handlers/git.py +12 -7
  313. claude_mpm/services/socketio/handlers/hook.py +49 -44
  314. claude_mpm/services/socketio/handlers/memory.py +0 -1
  315. claude_mpm/services/socketio/handlers/project.py +0 -1
  316. claude_mpm/services/socketio/handlers/registry.py +37 -19
  317. claude_mpm/services/socketio/migration_utils.py +98 -84
  318. claude_mpm/services/socketio/server/__init__.py +1 -1
  319. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  320. claude_mpm/services/socketio/server/core.py +65 -54
  321. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  322. claude_mpm/services/socketio/server/main.py +64 -38
  323. claude_mpm/services/socketio_client_manager.py +10 -12
  324. claude_mpm/services/subprocess_launcher_service.py +4 -7
  325. claude_mpm/services/system_instructions_service.py +13 -14
  326. claude_mpm/services/ticket_manager.py +2 -2
  327. claude_mpm/services/utility_service.py +5 -13
  328. claude_mpm/services/version_control/__init__.py +16 -16
  329. claude_mpm/services/version_control/branch_strategy.py +5 -8
  330. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  331. claude_mpm/services/version_control/git_operations.py +5 -7
  332. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  333. claude_mpm/services/version_control/version_parser.py +13 -18
  334. claude_mpm/services/version_service.py +10 -11
  335. claude_mpm/storage/__init__.py +1 -1
  336. claude_mpm/storage/state_storage.py +22 -28
  337. claude_mpm/utils/__init__.py +6 -6
  338. claude_mpm/utils/agent_dependency_loader.py +47 -33
  339. claude_mpm/utils/config_manager.py +11 -14
  340. claude_mpm/utils/dependency_cache.py +1 -1
  341. claude_mpm/utils/dependency_manager.py +13 -17
  342. claude_mpm/utils/dependency_strategies.py +8 -10
  343. claude_mpm/utils/environment_context.py +3 -9
  344. claude_mpm/utils/error_handler.py +3 -13
  345. claude_mpm/utils/file_utils.py +1 -1
  346. claude_mpm/utils/path_operations.py +8 -12
  347. claude_mpm/utils/robust_installer.py +110 -33
  348. claude_mpm/utils/subprocess_utils.py +5 -6
  349. claude_mpm/validation/agent_validator.py +3 -6
  350. claude_mpm/validation/frontmatter_validator.py +1 -1
  351. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
  352. claude_mpm-4.1.2.dist-info/RECORD +498 -0
  353. claude_mpm-4.1.1.dist-info/RECORD +0 -494
  354. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
  355. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
  356. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
  357. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
@@ -15,14 +15,13 @@ DESIGN DECISIONS:
15
15
  - Thread-safe singleton pattern
16
16
  """
17
17
 
18
- import asyncio
18
+ import contextlib
19
19
  import fcntl
20
20
  import json
21
21
  import os
22
22
  import signal
23
23
  import threading
24
24
  import time
25
- from pathlib import Path
26
25
  from typing import Any, Dict, Optional
27
26
 
28
27
  from claude_mpm.config.paths import paths
@@ -32,14 +31,14 @@ from claude_mpm.core.logger import get_logger
32
31
  class MCPGatewayManager:
33
32
  """
34
33
  Singleton manager for MCP Gateway instances.
35
-
34
+
36
35
  Ensures only one gateway instance is running per installation using
37
36
  file-based locking and PID tracking.
38
37
  """
39
-
40
- _instance: Optional['MCPGatewayManager'] = None
38
+
39
+ _instance: Optional["MCPGatewayManager"] = None
41
40
  _lock = threading.Lock()
42
-
41
+
43
42
  def __new__(cls):
44
43
  """Singleton pattern implementation."""
45
44
  with cls._lock:
@@ -47,71 +46,72 @@ class MCPGatewayManager:
47
46
  cls._instance = super().__new__(cls)
48
47
  cls._instance._initialized = False
49
48
  return cls._instance
50
-
49
+
51
50
  def __init__(self):
52
51
  """Initialize the gateway manager."""
53
52
  if self._initialized:
54
53
  return
55
-
54
+
56
55
  self.logger = get_logger("MCPGatewayManager")
57
56
  self._initialized = True
58
-
57
+
59
58
  # Paths for coordination
60
59
  self.mcp_dir = paths.claude_mpm_dir_hidden / "mcp"
61
60
  self.lock_file = self.mcp_dir / "gateway.lock"
62
61
  self.instance_file = self.mcp_dir / "gateway.json"
63
-
62
+
64
63
  # Ensure directory exists
65
64
  self.mcp_dir.mkdir(parents=True, exist_ok=True)
66
-
65
+
67
66
  # Lock file handle
68
67
  self._lock_fd: Optional[int] = None
69
68
  self._current_instance: Optional[Dict[str, Any]] = None
70
-
69
+
71
70
  # Setup cleanup handlers
72
71
  self._setup_cleanup_handlers()
73
-
72
+
74
73
  def _setup_cleanup_handlers(self):
75
74
  """Setup signal handlers for cleanup on termination."""
75
+
76
76
  def cleanup_handler(signum, frame):
77
77
  self.logger.info(f"Received signal {signum}, cleaning up gateway")
78
78
  self.cleanup()
79
-
79
+
80
80
  signal.signal(signal.SIGTERM, cleanup_handler)
81
81
  signal.signal(signal.SIGINT, cleanup_handler)
82
-
82
+
83
83
  def acquire_lock(self) -> bool:
84
84
  """
85
85
  Acquire exclusive lock for gateway instance.
86
-
86
+
87
87
  Returns:
88
88
  True if lock acquired successfully, False otherwise
89
89
  """
90
90
  try:
91
91
  # Open lock file
92
- self._lock_fd = os.open(self.lock_file, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
93
-
92
+ self._lock_fd = os.open(
93
+ self.lock_file, os.O_CREAT | os.O_WRONLY | os.O_TRUNC
94
+ )
95
+
94
96
  # Try to acquire exclusive lock (non-blocking)
95
97
  fcntl.flock(self._lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
96
-
98
+
97
99
  # Write current PID to lock file
98
100
  os.write(self._lock_fd, str(os.getpid()).encode())
99
101
  os.fsync(self._lock_fd)
100
-
102
+
101
103
  self.logger.info(f"Acquired gateway lock (PID: {os.getpid()})")
102
104
  return True
103
-
104
- except (OSError, IOError) as e:
105
+
106
+ except OSError as e:
105
107
  if self._lock_fd:
106
- try:
108
+ with contextlib.suppress(Exception):
107
109
  os.close(self._lock_fd)
108
- except:
109
- pass
110
110
  self._lock_fd = None
111
-
111
+
112
112
  self.logger.debug(f"Failed to acquire gateway lock: {e}")
113
113
  return False
114
-
114
+
115
115
  def release_lock(self):
116
116
  """Release the gateway lock."""
117
117
  if self._lock_fd:
@@ -119,52 +119,51 @@ class MCPGatewayManager:
119
119
  fcntl.flock(self._lock_fd, fcntl.LOCK_UN)
120
120
  os.close(self._lock_fd)
121
121
  self._lock_fd = None
122
-
122
+
123
123
  # Remove lock file
124
124
  if self.lock_file.exists():
125
125
  self.lock_file.unlink()
126
-
126
+
127
127
  self.logger.info("Released gateway lock")
128
128
  except Exception as e:
129
129
  self.logger.warning(f"Error releasing lock: {e}")
130
-
130
+
131
131
  def is_gateway_running(self) -> bool:
132
132
  """
133
133
  Check if a gateway instance is currently running.
134
-
134
+
135
135
  Returns:
136
136
  True if gateway is running, False otherwise
137
137
  """
138
138
  instance_info = self.get_running_instance_info()
139
139
  return instance_info is not None
140
-
140
+
141
141
  def get_running_instance_info(self) -> Optional[Dict[str, Any]]:
142
142
  """
143
143
  Get information about the currently running gateway instance.
144
-
144
+
145
145
  Returns:
146
146
  Instance information dict or None if no instance running
147
147
  """
148
148
  if not self.instance_file.exists():
149
149
  return None
150
-
150
+
151
151
  try:
152
- with open(self.instance_file, 'r') as f:
152
+ with open(self.instance_file) as f:
153
153
  instance_info = json.load(f)
154
-
154
+
155
155
  # Validate PID is still running
156
- pid = instance_info.get('pid')
156
+ pid = instance_info.get("pid")
157
157
  if pid and self._is_pid_running(pid):
158
158
  return instance_info
159
- else:
160
- # Stale instance file, remove it
161
- self.instance_file.unlink()
162
- return None
163
-
159
+ # Stale instance file, remove it
160
+ self.instance_file.unlink()
161
+ return None
162
+
164
163
  except (json.JSONDecodeError, OSError) as e:
165
164
  self.logger.warning(f"Error reading instance file: {e}")
166
165
  return None
167
-
166
+
168
167
  def _is_pid_running(self, pid: int) -> bool:
169
168
  """Check if a PID is currently running."""
170
169
  try:
@@ -172,55 +171,55 @@ class MCPGatewayManager:
172
171
  return True
173
172
  except (OSError, ProcessLookupError):
174
173
  return False
175
-
174
+
176
175
  def register_instance(self, gateway_name: str, version: str) -> bool:
177
176
  """
178
177
  Register a new gateway instance.
179
-
178
+
180
179
  Args:
181
180
  gateway_name: Name of the gateway
182
181
  version: Gateway version
183
-
182
+
184
183
  Returns:
185
184
  True if registration successful, False otherwise
186
185
  """
187
186
  if not self.acquire_lock():
188
187
  return False
189
-
188
+
190
189
  try:
191
190
  instance_info = {
192
- 'pid': os.getpid(),
193
- 'gateway_name': gateway_name,
194
- 'version': version,
195
- 'started_at': time.time(),
196
- 'lock_file': str(self.lock_file),
191
+ "pid": os.getpid(),
192
+ "gateway_name": gateway_name,
193
+ "version": version,
194
+ "started_at": time.time(),
195
+ "lock_file": str(self.lock_file),
197
196
  }
198
-
199
- with open(self.instance_file, 'w') as f:
197
+
198
+ with open(self.instance_file, "w") as f:
200
199
  json.dump(instance_info, f, indent=2)
201
-
200
+
202
201
  self._current_instance = instance_info
203
202
  self.logger.info(f"Registered gateway instance: {gateway_name} v{version}")
204
203
  return True
205
-
204
+
206
205
  except Exception as e:
207
206
  self.logger.error(f"Failed to register instance: {e}")
208
207
  self.release_lock()
209
208
  return False
210
-
209
+
211
210
  def cleanup(self):
212
211
  """Clean up gateway instance and release resources."""
213
212
  try:
214
213
  # Remove instance file
215
214
  if self.instance_file.exists():
216
215
  self.instance_file.unlink()
217
-
216
+
218
217
  # Release lock
219
218
  self.release_lock()
220
-
219
+
221
220
  self._current_instance = None
222
221
  self.logger.info("Gateway cleanup completed")
223
-
222
+
224
223
  except Exception as e:
225
224
  self.logger.warning(f"Error during cleanup: {e}")
226
225
 
@@ -247,7 +246,9 @@ def get_gateway_status() -> Optional[Dict[str, Any]]:
247
246
  return get_gateway_manager().get_running_instance_info()
248
247
 
249
248
 
250
- async def start_global_gateway(gateway_name: str = "claude-mpm-mcp", version: str = "1.0.0") -> bool:
249
+ async def start_global_gateway(
250
+ gateway_name: str = "claude-mpm-mcp", version: str = "1.0.0"
251
+ ) -> bool:
251
252
  """
252
253
  Start the global MCP gateway instance.
253
254
 
@@ -263,7 +264,9 @@ async def start_global_gateway(gateway_name: str = "claude-mpm-mcp", version: st
263
264
  # Check if already running
264
265
  if manager.is_gateway_running():
265
266
  instance_info = manager.get_running_instance_info()
266
- manager.logger.info(f"Gateway already running (PID: {instance_info.get('pid')})")
267
+ manager.logger.info(
268
+ f"Gateway already running (PID: {instance_info.get('pid')})"
269
+ )
267
270
  return True
268
271
 
269
272
  # Register new instance
@@ -16,9 +16,7 @@ DESIGN DECISIONS:
16
16
  - Non-blocking startup (warnings instead of failures)
17
17
  """
18
18
 
19
- import asyncio
20
- from pathlib import Path
21
- from typing import Any, Dict, List, Optional, Tuple
19
+ from typing import Any, Dict
22
20
 
23
21
  from claude_mpm.config.paths import paths
24
22
  from claude_mpm.core.logger import get_logger
@@ -29,17 +27,17 @@ from .singleton_manager import get_gateway_manager, is_gateway_running
29
27
  class MCPGatewayStartupVerifier:
30
28
  """
31
29
  Verifies and configures MCP Gateway on startup.
32
-
30
+
33
31
  Ensures the gateway is properly configured with essential tools and
34
32
  provides diagnostic information about the gateway state.
35
33
  """
36
-
34
+
37
35
  def __init__(self):
38
36
  """Initialize the startup verifier."""
39
37
  self.logger = get_logger("MCPGatewayStartupVerifier")
40
38
  self.config_dir = paths.claude_mpm_dir_hidden / "mcp"
41
39
  self.config_file = self.config_dir / "gateway_config.json"
42
-
40
+
43
41
  # Essential tools that should be available
44
42
  self.essential_tools = [
45
43
  "echo", # Basic diagnostic tool
@@ -49,16 +47,16 @@ class MCPGatewayStartupVerifier:
49
47
  "document_summarizer", # File summarizer
50
48
  "ticket", # Ticket service (unified)
51
49
  ]
52
-
50
+
53
51
  async def verify_and_configure(self) -> Dict[str, Any]:
54
52
  """
55
53
  Verify MCP gateway configuration and configure if needed.
56
-
54
+
57
55
  Returns:
58
56
  Dictionary with verification results and status
59
57
  """
60
58
  self.logger.info("Starting MCP Gateway verification")
61
-
59
+
62
60
  results = {
63
61
  "gateway_configured": False,
64
62
  "singleton_manager": False,
@@ -67,73 +65,78 @@ class MCPGatewayStartupVerifier:
67
65
  "warnings": [],
68
66
  "errors": [],
69
67
  }
70
-
68
+
71
69
  try:
72
70
  # 1. Verify singleton manager
73
71
  results["singleton_manager"] = self._verify_singleton_manager()
74
-
72
+
75
73
  # 2. Ensure configuration directory exists
76
74
  self._ensure_config_directory()
77
-
75
+
78
76
  # 3. Verify or create gateway configuration
79
77
  config_created = await self._verify_gateway_configuration()
80
78
  results["configuration_created"] = config_created
81
-
79
+
82
80
  # 4. Verify essential tools
83
81
  tools_status = await self._verify_essential_tools()
84
82
  results["essential_tools"] = tools_status
85
-
83
+
86
84
  # 5. Check overall gateway status
87
85
  results["gateway_configured"] = self._assess_gateway_status(results)
88
-
86
+
89
87
  # Log summary
90
88
  self._log_verification_summary(results)
91
-
89
+
92
90
  return results
93
-
91
+
94
92
  except Exception as e:
95
93
  self.logger.error(f"Error during MCP Gateway verification: {e}")
96
94
  results["errors"].append(f"Verification failed: {e}")
97
95
  return results
98
-
96
+
99
97
  def _verify_singleton_manager(self) -> bool:
100
98
  """Verify singleton manager is working."""
101
99
  try:
102
- manager = get_gateway_manager()
100
+ get_gateway_manager()
103
101
  # Test basic functionality
104
102
  running = is_gateway_running()
105
- self.logger.debug(f"Singleton manager operational, gateway running: {running}")
103
+ self.logger.debug(
104
+ f"Singleton manager operational, gateway running: {running}"
105
+ )
106
106
  return True
107
107
  except Exception as e:
108
108
  self.logger.warning(f"Singleton manager issue: {e}")
109
109
  return False
110
-
110
+
111
111
  def _ensure_config_directory(self):
112
112
  """Ensure MCP configuration directory exists."""
113
113
  self.config_dir.mkdir(parents=True, exist_ok=True)
114
114
  self.logger.debug(f"MCP config directory: {self.config_dir}")
115
-
115
+
116
116
  async def _verify_gateway_configuration(self) -> bool:
117
117
  """Verify or create gateway configuration."""
118
118
  if self.config_file.exists():
119
119
  self.logger.debug("Gateway configuration file exists")
120
120
  return False
121
-
121
+
122
122
  # Create default configuration
123
123
  default_config = self._create_default_configuration()
124
-
124
+
125
125
  try:
126
126
  import json
127
- with open(self.config_file, 'w') as f:
127
+
128
+ with open(self.config_file, "w") as f:
128
129
  json.dump(default_config, f, indent=2)
129
-
130
- self.logger.info(f"Created default gateway configuration: {self.config_file}")
130
+
131
+ self.logger.info(
132
+ f"Created default gateway configuration: {self.config_file}"
133
+ )
131
134
  return True
132
-
135
+
133
136
  except Exception as e:
134
137
  self.logger.warning(f"Failed to create configuration: {e}")
135
138
  return False
136
-
139
+
137
140
  def _create_default_configuration(self) -> Dict[str, Any]:
138
141
  """Create default MCP gateway configuration."""
139
142
  return {
@@ -141,36 +144,33 @@ class MCPGatewayStartupVerifier:
141
144
  "server": {
142
145
  "name": "claude-mpm-mcp-gateway",
143
146
  "version": "1.0.0",
144
- "description": "Claude MPM MCP Gateway with essential tools"
147
+ "description": "Claude MPM MCP Gateway with essential tools",
145
148
  },
146
149
  "tools": {
147
150
  "enabled": True,
148
151
  "auto_discover": True,
149
152
  "timeout_default": 30,
150
153
  "max_concurrent": 10,
151
- "essential_tools": self.essential_tools
154
+ "essential_tools": self.essential_tools,
152
155
  },
153
156
  "logging": {
154
157
  "level": "INFO",
155
- "file": str(paths.logs_dir / "mcp_gateway.log")
158
+ "file": str(paths.logs_dir / "mcp_gateway.log"),
156
159
  },
157
- "security": {
158
- "validate_schemas": True,
159
- "sanitize_inputs": True
160
- }
160
+ "security": {"validate_schemas": True, "sanitize_inputs": True},
161
161
  }
162
162
  }
163
-
163
+
164
164
  async def _verify_essential_tools(self) -> Dict[str, Dict[str, Any]]:
165
165
  """Verify essential tools are available."""
166
166
  tools_status = {}
167
-
167
+
168
168
  for tool_name in self.essential_tools:
169
169
  status = await self._verify_tool(tool_name)
170
170
  tools_status[tool_name] = status
171
-
171
+
172
172
  return tools_status
173
-
173
+
174
174
  async def _verify_tool(self, tool_name: str) -> Dict[str, Any]:
175
175
  """Verify a specific tool is available."""
176
176
  status = {
@@ -178,27 +178,27 @@ class MCPGatewayStartupVerifier:
178
178
  "initialized": False,
179
179
  "error": None,
180
180
  }
181
-
181
+
182
182
  try:
183
183
  # Try to import and initialize the tool
184
184
  tool_instance = await self._create_tool_instance(tool_name)
185
-
185
+
186
186
  if tool_instance:
187
187
  status["available"] = True
188
-
188
+
189
189
  # Try to initialize
190
- if hasattr(tool_instance, 'initialize'):
190
+ if hasattr(tool_instance, "initialize"):
191
191
  initialized = await tool_instance.initialize()
192
192
  status["initialized"] = initialized
193
193
  else:
194
194
  status["initialized"] = True
195
-
195
+
196
196
  except Exception as e:
197
197
  status["error"] = str(e)
198
198
  self.logger.debug(f"Tool {tool_name} verification failed: {e}")
199
-
199
+
200
200
  return status
201
-
201
+
202
202
  async def _create_tool_instance(self, tool_name: str):
203
203
  """Create an instance of the specified tool."""
204
204
  tool_map = {
@@ -206,74 +206,78 @@ class MCPGatewayStartupVerifier:
206
206
  "calculator": ("..tools.base_adapter", "CalculatorToolAdapter"),
207
207
  "system_info": ("..tools.base_adapter", "SystemInfoToolAdapter"),
208
208
  "health_check": ("..tools.health_check_tool", "HealthCheckTool"),
209
- "document_summarizer": ("..tools.document_summarizer", "DocumentSummarizerTool"),
209
+ "document_summarizer": (
210
+ "..tools.document_summarizer",
211
+ "DocumentSummarizerTool",
212
+ ),
210
213
  "ticket": ("..tools.unified_ticket_tool", "UnifiedTicketTool"),
211
214
  }
212
-
215
+
213
216
  if tool_name not in tool_map:
214
217
  return None
215
-
218
+
216
219
  module_path, class_name = tool_map[tool_name]
217
-
220
+
218
221
  try:
219
222
  # Dynamic import
220
223
  from importlib import import_module
224
+
221
225
  module = import_module(module_path, package=__package__)
222
226
  tool_class = getattr(module, class_name)
223
227
  return tool_class()
224
228
  except (ImportError, AttributeError) as e:
225
229
  self.logger.debug(f"Could not import {tool_name}: {e}")
226
230
  return None
227
-
231
+
228
232
  def _assess_gateway_status(self, results: Dict[str, Any]) -> bool:
229
233
  """Assess overall gateway configuration status."""
230
234
  # Gateway is considered configured if:
231
235
  # 1. Singleton manager works
232
236
  # 2. At least basic tools are available
233
237
  # 3. No critical errors
234
-
238
+
235
239
  if not results["singleton_manager"]:
236
240
  return False
237
-
241
+
238
242
  if results["errors"]:
239
243
  return False
240
-
244
+
241
245
  # Check if at least basic diagnostic tools are available
242
246
  essential_available = 0
243
- for tool_name, status in results["essential_tools"].items():
247
+ for _tool_name, status in results["essential_tools"].items():
244
248
  if status.get("available", False):
245
249
  essential_available += 1
246
-
250
+
247
251
  # Consider configured if at least 3 essential tools are available
248
252
  return essential_available >= 3
249
-
253
+
250
254
  def _log_verification_summary(self, results: Dict[str, Any]):
251
255
  """Log verification summary."""
252
256
  if results["gateway_configured"]:
253
257
  self.logger.info("✅ MCP Gateway verification completed successfully")
254
258
  else:
255
259
  self.logger.warning("⚠️ MCP Gateway verification completed with issues")
256
-
260
+
257
261
  # Log tool status
258
262
  available_tools = []
259
263
  unavailable_tools = []
260
-
264
+
261
265
  for tool_name, status in results["essential_tools"].items():
262
266
  if status.get("available", False):
263
267
  available_tools.append(tool_name)
264
268
  else:
265
269
  unavailable_tools.append(tool_name)
266
-
270
+
267
271
  if available_tools:
268
272
  self.logger.info(f"Available tools: {', '.join(available_tools)}")
269
-
273
+
270
274
  if unavailable_tools:
271
275
  self.logger.warning(f"Unavailable tools: {', '.join(unavailable_tools)}")
272
-
276
+
273
277
  # Log warnings and errors
274
278
  for warning in results.get("warnings", []):
275
279
  self.logger.warning(warning)
276
-
280
+
277
281
  for error in results.get("errors", []):
278
282
  self.logger.error(error)
279
283
 
@@ -282,10 +286,10 @@ class MCPGatewayStartupVerifier:
282
286
  async def verify_mcp_gateway_on_startup() -> Dict[str, Any]:
283
287
  """
284
288
  Verify MCP Gateway configuration on startup.
285
-
289
+
286
290
  This function should be called during application startup to ensure
287
291
  the MCP gateway is properly configured.
288
-
292
+
289
293
  Returns:
290
294
  Dictionary with verification results
291
295
  """
@@ -296,20 +300,17 @@ async def verify_mcp_gateway_on_startup() -> Dict[str, Any]:
296
300
  def is_mcp_gateway_configured() -> bool:
297
301
  """
298
302
  Quick check if MCP gateway appears to be configured.
299
-
303
+
300
304
  Returns:
301
305
  True if gateway appears configured, False otherwise
302
306
  """
303
307
  try:
304
308
  # Check if singleton manager works
305
- manager = get_gateway_manager()
306
-
309
+ get_gateway_manager()
310
+
307
311
  # Check if config directory exists
308
312
  config_dir = paths.claude_mpm_dir_hidden / "mcp"
309
- if not config_dir.exists():
310
- return False
311
-
312
- return True
313
-
313
+ return config_dir.exists()
314
+
314
315
  except Exception:
315
316
  return False
@@ -15,7 +15,7 @@ import asyncio
15
15
  import logging
16
16
  import signal
17
17
  import sys
18
- from typing import List, Optional
18
+ from typing import Optional
19
19
 
20
20
  # Import with fallback handling for missing dependencies
21
21
  try:
@@ -259,6 +259,7 @@ class MCPGatewayOrchestrator:
259
259
  # Optional: Health check tool
260
260
  try:
261
261
  from .tools.health_check_tool import HealthCheckTool
262
+
262
263
  tools.append(HealthCheckTool())
263
264
  except Exception as e:
264
265
  self.logger.warning(f"Could not load health check tool: {e}")