claude-mpm 4.1.1__py3-none-any.whl → 4.1.3__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 (389) 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/engineer.json +33 -11
  18. claude_mpm/agents/templates/imagemagick.json +256 -0
  19. claude_mpm/agents/templates/qa.json +41 -2
  20. claude_mpm/agents/templates/ticketing.json +5 -5
  21. claude_mpm/agents/templates/web_qa.json +50 -2
  22. claude_mpm/cli/__init__.py +51 -46
  23. claude_mpm/cli/__main__.py +1 -1
  24. claude_mpm/cli/commands/__init__.py +10 -12
  25. claude_mpm/cli/commands/agent_manager.py +186 -181
  26. claude_mpm/cli/commands/agents.py +648 -1098
  27. claude_mpm/cli/commands/aggregate.py +30 -29
  28. claude_mpm/cli/commands/cleanup.py +50 -44
  29. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  30. claude_mpm/cli/commands/config.py +162 -127
  31. claude_mpm/cli/commands/doctor.py +52 -62
  32. claude_mpm/cli/commands/info.py +37 -25
  33. claude_mpm/cli/commands/mcp.py +3 -7
  34. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  35. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  36. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  37. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  38. claude_mpm/cli/commands/memory.py +339 -967
  39. claude_mpm/cli/commands/monitor.py +117 -88
  40. claude_mpm/cli/commands/run.py +233 -542
  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 +280 -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 +22 -29
  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 +500 -680
  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 -17
  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 +99 -154
  114. claude_mpm/hooks/claude_hooks/hook_handler.py +110 -720
  115. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  116. claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
  117. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
  118. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  119. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  120. claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
  121. claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
  122. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  123. claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
  124. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  125. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  126. claude_mpm/hooks/memory_integration_hook.py +5 -5
  127. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  128. claude_mpm/hooks/validation_hooks.py +4 -4
  129. claude_mpm/init.py +4 -9
  130. claude_mpm/models/__init__.py +2 -2
  131. claude_mpm/models/agent_session.py +11 -14
  132. claude_mpm/scripts/mcp_server.py +20 -11
  133. claude_mpm/scripts/mcp_wrapper.py +5 -5
  134. claude_mpm/scripts/mpm_doctor.py +321 -0
  135. claude_mpm/scripts/socketio_daemon.py +28 -25
  136. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  137. claude_mpm/scripts/socketio_server_manager.py +116 -95
  138. claude_mpm/services/__init__.py +49 -49
  139. claude_mpm/services/agent_capabilities_service.py +12 -18
  140. claude_mpm/services/agents/__init__.py +22 -22
  141. claude_mpm/services/agents/agent_builder.py +140 -119
  142. claude_mpm/services/agents/deployment/__init__.py +3 -3
  143. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  144. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  145. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  146. claude_mpm/services/agents/deployment/agent_deployment.py +129 -511
  147. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  148. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  149. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  150. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  151. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  152. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  153. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  154. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  155. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  156. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  157. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  158. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  159. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  160. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  161. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  162. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  163. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  164. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  165. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  166. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  167. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  168. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  169. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  170. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  171. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  172. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  173. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  174. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  175. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  176. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  177. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  178. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  179. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  180. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  181. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  182. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  183. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  184. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  185. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  186. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  187. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  188. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  189. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  190. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  191. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  192. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  193. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  194. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  195. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  196. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  197. claude_mpm/services/agents/loading/__init__.py +1 -1
  198. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  199. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  200. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  201. claude_mpm/services/agents/management/__init__.py +1 -1
  202. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  203. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  204. claude_mpm/services/agents/memory/__init__.py +4 -4
  205. claude_mpm/services/agents/memory/agent_memory_manager.py +157 -503
  206. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  207. claude_mpm/services/agents/memory/content_manager.py +44 -38
  208. claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
  209. claude_mpm/services/agents/memory/memory_file_service.py +103 -0
  210. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  211. claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
  212. claude_mpm/services/agents/memory/template_generator.py +4 -6
  213. claude_mpm/services/agents/registry/__init__.py +11 -7
  214. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  215. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  216. claude_mpm/services/async_session_logger.py +1 -2
  217. claude_mpm/services/claude_session_logger.py +1 -2
  218. claude_mpm/services/cli/__init__.py +18 -0
  219. claude_mpm/services/cli/agent_cleanup_service.py +407 -0
  220. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  221. claude_mpm/services/cli/agent_listing_service.py +463 -0
  222. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  223. claude_mpm/services/cli/agent_validation_service.py +589 -0
  224. claude_mpm/services/cli/dashboard_launcher.py +424 -0
  225. claude_mpm/services/cli/memory_crud_service.py +617 -0
  226. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  227. claude_mpm/services/cli/session_manager.py +513 -0
  228. claude_mpm/services/cli/socketio_manager.py +498 -0
  229. claude_mpm/services/cli/startup_checker.py +370 -0
  230. claude_mpm/services/command_deployment_service.py +173 -0
  231. claude_mpm/services/command_handler_service.py +20 -22
  232. claude_mpm/services/core/__init__.py +25 -25
  233. claude_mpm/services/core/base.py +0 -5
  234. claude_mpm/services/core/cache_manager.py +311 -0
  235. claude_mpm/services/core/interfaces/__init__.py +32 -32
  236. claude_mpm/services/core/interfaces/agent.py +0 -21
  237. claude_mpm/services/core/interfaces/communication.py +0 -27
  238. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  239. claude_mpm/services/core/interfaces/service.py +0 -29
  240. claude_mpm/services/core/memory_manager.py +637 -0
  241. claude_mpm/services/core/path_resolver.py +498 -0
  242. claude_mpm/services/core/service_container.py +520 -0
  243. claude_mpm/services/core/service_interfaces.py +436 -0
  244. claude_mpm/services/diagnostics/__init__.py +1 -1
  245. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  246. claude_mpm/services/diagnostics/checks/agent_check.py +152 -97
  247. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  248. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  249. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  250. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  251. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  252. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  253. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  254. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  255. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  256. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  257. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  258. claude_mpm/services/diagnostics/models.py +21 -19
  259. claude_mpm/services/event_aggregator.py +10 -17
  260. claude_mpm/services/event_bus/__init__.py +1 -1
  261. claude_mpm/services/event_bus/config.py +54 -35
  262. claude_mpm/services/event_bus/event_bus.py +76 -71
  263. claude_mpm/services/event_bus/relay.py +74 -64
  264. claude_mpm/services/events/__init__.py +11 -11
  265. claude_mpm/services/events/consumers/__init__.py +3 -3
  266. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  267. claude_mpm/services/events/consumers/logging.py +39 -37
  268. claude_mpm/services/events/consumers/metrics.py +56 -57
  269. claude_mpm/services/events/consumers/socketio.py +82 -81
  270. claude_mpm/services/events/core.py +110 -99
  271. claude_mpm/services/events/interfaces.py +56 -72
  272. claude_mpm/services/events/producers/__init__.py +1 -1
  273. claude_mpm/services/events/producers/hook.py +38 -38
  274. claude_mpm/services/events/producers/system.py +46 -44
  275. claude_mpm/services/exceptions.py +81 -80
  276. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  277. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  278. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  279. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  280. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  281. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  283. claude_mpm/services/hook_service.py +6 -9
  284. claude_mpm/services/infrastructure/__init__.py +1 -1
  285. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  286. claude_mpm/services/infrastructure/monitoring.py +21 -23
  287. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  288. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  289. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  290. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  291. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  292. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  293. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  294. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  295. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  296. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  297. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  298. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  299. claude_mpm/services/mcp_gateway/main.py +2 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  302. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  309. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  310. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  311. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  312. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  313. claude_mpm/services/memory/__init__.py +3 -3
  314. claude_mpm/services/memory/builder.py +3 -6
  315. claude_mpm/services/memory/cache/__init__.py +1 -1
  316. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  317. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  318. claude_mpm/services/memory/indexed_memory.py +5 -7
  319. claude_mpm/services/memory/optimizer.py +7 -10
  320. claude_mpm/services/memory/router.py +8 -9
  321. claude_mpm/services/memory_hook_service.py +48 -34
  322. claude_mpm/services/monitor_build_service.py +77 -73
  323. claude_mpm/services/port_manager.py +130 -108
  324. claude_mpm/services/project/analyzer.py +12 -10
  325. claude_mpm/services/project/registry.py +11 -11
  326. claude_mpm/services/recovery_manager.py +10 -19
  327. claude_mpm/services/response_tracker.py +0 -1
  328. claude_mpm/services/runner_configuration_service.py +19 -20
  329. claude_mpm/services/session_management_service.py +7 -11
  330. claude_mpm/services/shared/__init__.py +1 -1
  331. claude_mpm/services/shared/async_service_base.py +58 -50
  332. claude_mpm/services/shared/config_service_base.py +73 -67
  333. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  334. claude_mpm/services/shared/manager_base.py +94 -82
  335. claude_mpm/services/shared/service_factory.py +96 -98
  336. claude_mpm/services/socketio/__init__.py +3 -3
  337. claude_mpm/services/socketio/client_proxy.py +5 -5
  338. claude_mpm/services/socketio/event_normalizer.py +199 -181
  339. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  340. claude_mpm/services/socketio/handlers/base.py +5 -4
  341. claude_mpm/services/socketio/handlers/connection.py +163 -136
  342. claude_mpm/services/socketio/handlers/file.py +13 -14
  343. claude_mpm/services/socketio/handlers/git.py +12 -7
  344. claude_mpm/services/socketio/handlers/hook.py +49 -44
  345. claude_mpm/services/socketio/handlers/memory.py +0 -1
  346. claude_mpm/services/socketio/handlers/project.py +0 -1
  347. claude_mpm/services/socketio/handlers/registry.py +37 -19
  348. claude_mpm/services/socketio/migration_utils.py +98 -84
  349. claude_mpm/services/socketio/server/__init__.py +1 -1
  350. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  351. claude_mpm/services/socketio/server/core.py +65 -54
  352. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  353. claude_mpm/services/socketio/server/main.py +64 -38
  354. claude_mpm/services/socketio_client_manager.py +10 -12
  355. claude_mpm/services/subprocess_launcher_service.py +4 -7
  356. claude_mpm/services/system_instructions_service.py +13 -14
  357. claude_mpm/services/ticket_manager.py +2 -2
  358. claude_mpm/services/utility_service.py +5 -13
  359. claude_mpm/services/version_control/__init__.py +16 -16
  360. claude_mpm/services/version_control/branch_strategy.py +5 -8
  361. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  362. claude_mpm/services/version_control/git_operations.py +5 -7
  363. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  364. claude_mpm/services/version_control/version_parser.py +13 -18
  365. claude_mpm/services/version_service.py +10 -11
  366. claude_mpm/storage/__init__.py +1 -1
  367. claude_mpm/storage/state_storage.py +22 -28
  368. claude_mpm/utils/__init__.py +6 -6
  369. claude_mpm/utils/agent_dependency_loader.py +47 -33
  370. claude_mpm/utils/config_manager.py +11 -14
  371. claude_mpm/utils/dependency_cache.py +1 -1
  372. claude_mpm/utils/dependency_manager.py +13 -17
  373. claude_mpm/utils/dependency_strategies.py +8 -10
  374. claude_mpm/utils/environment_context.py +3 -9
  375. claude_mpm/utils/error_handler.py +3 -13
  376. claude_mpm/utils/file_utils.py +1 -1
  377. claude_mpm/utils/path_operations.py +8 -12
  378. claude_mpm/utils/robust_installer.py +110 -33
  379. claude_mpm/utils/subprocess_utils.py +5 -6
  380. claude_mpm/validation/agent_validator.py +3 -6
  381. claude_mpm/validation/frontmatter_validator.py +1 -1
  382. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/METADATA +1 -1
  383. claude_mpm-4.1.3.dist-info/RECORD +528 -0
  384. claude_mpm/cli/commands/run_config_checker.py +0 -160
  385. claude_mpm-4.1.1.dist-info/RECORD +0 -494
  386. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/WHEEL +0 -0
  387. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/entry_points.txt +0 -0
  388. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/licenses/LICENSE +0 -0
  389. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/top_level.txt +0 -0
@@ -20,11 +20,10 @@ import json
20
20
  import os
21
21
  import signal
22
22
  import subprocess
23
- import sys
24
23
  import threading
25
24
  import time
26
25
  from pathlib import Path
27
- from typing import Any, Dict, List, Optional, Tuple
26
+ from typing import Any, Dict, Optional
28
27
 
29
28
  from claude_mpm.config.paths import paths
30
29
  from claude_mpm.core.logger import get_logger
@@ -33,14 +32,14 @@ from claude_mpm.core.logger import get_logger
33
32
  class MCPProcessPool:
34
33
  """
35
34
  Manages a pool of MCP server processes for efficient resource utilization.
36
-
35
+
37
36
  WHY: Prevent multiple MCP server instances from being spawned and
38
37
  reduce startup overhead by reusing existing processes.
39
38
  """
40
-
41
- _instance: Optional['MCPProcessPool'] = None
39
+
40
+ _instance: Optional["MCPProcessPool"] = None
42
41
  _lock = threading.Lock()
43
-
42
+
44
43
  def __new__(cls):
45
44
  """Singleton pattern implementation."""
46
45
  with cls._lock:
@@ -48,97 +47,105 @@ class MCPProcessPool:
48
47
  cls._instance = super().__new__(cls)
49
48
  cls._instance._initialized = False
50
49
  return cls._instance
51
-
50
+
52
51
  def __init__(self):
53
52
  """Initialize the process pool manager."""
54
53
  if self._initialized:
55
54
  return
56
-
55
+
57
56
  self.logger = get_logger("MCPProcessPool")
58
57
  self._initialized = True
59
-
58
+
60
59
  # Process tracking
61
60
  self._processes: Dict[str, subprocess.Popen] = {}
62
61
  self._process_info: Dict[str, Dict] = {}
63
62
  self._startup_times: Dict[str, float] = {}
64
-
63
+
65
64
  # Configuration
66
65
  self.max_processes = 3 # Maximum number of pooled processes
67
66
  self.process_timeout = 300 # 5 minutes idle timeout
68
67
  self.health_check_interval = 30 # Check process health every 30s
69
-
68
+
70
69
  # Paths
71
70
  self.pool_dir = paths.claude_mpm_dir_hidden / "mcp" / "pool"
72
71
  self.pool_dir.mkdir(parents=True, exist_ok=True)
73
-
72
+
74
73
  # Pre-warming flag
75
74
  self._pre_warmed = False
76
-
75
+
77
76
  # Background health check task
78
77
  self._health_check_task: Optional[asyncio.Task] = None
79
-
78
+
80
79
  # Setup cleanup handlers
81
80
  self._setup_cleanup_handlers()
82
-
81
+
83
82
  self.logger.info("MCP Process Pool initialized")
84
-
83
+
85
84
  def _setup_cleanup_handlers(self):
86
85
  """Setup signal handlers for cleanup on termination."""
86
+
87
87
  def cleanup_handler(signum, frame):
88
88
  self.logger.info(f"Received signal {signum}, cleaning up process pool")
89
89
  self.cleanup_all()
90
-
90
+
91
91
  signal.signal(signal.SIGTERM, cleanup_handler)
92
92
  signal.signal(signal.SIGINT, cleanup_handler)
93
-
94
- def get_or_create_process(self, server_name: str, config: Dict) -> Optional[subprocess.Popen]:
93
+
94
+ def get_or_create_process(
95
+ self, server_name: str, config: Dict
96
+ ) -> Optional[subprocess.Popen]:
95
97
  """
96
98
  Get an existing process or create a new one for the given server.
97
-
99
+
98
100
  Args:
99
101
  server_name: Name of the MCP server
100
102
  config: Server configuration including command and args
101
-
103
+
102
104
  Returns:
103
105
  Process handle or None if failed
104
106
  """
105
107
  start_time = time.time()
106
-
108
+
107
109
  # Check if we have a healthy existing process
108
110
  if server_name in self._processes:
109
111
  process = self._processes[server_name]
110
112
  if self._is_process_healthy(process):
111
- self.logger.info(f"Reusing existing process for {server_name} (PID: {process.pid})")
113
+ self.logger.info(
114
+ f"Reusing existing process for {server_name} (PID: {process.pid})"
115
+ )
112
116
  return process
113
- else:
114
- # Process is dead, clean it up
115
- self.logger.warning(f"Process for {server_name} is dead, cleaning up")
116
- self._cleanup_process(server_name)
117
-
117
+ # Process is dead, clean it up
118
+ self.logger.warning(f"Process for {server_name} is dead, cleaning up")
119
+ self._cleanup_process(server_name)
120
+
118
121
  # Check if we've hit the process limit
119
122
  if len(self._processes) >= self.max_processes:
120
123
  # Find and clean up the oldest idle process
121
124
  self._cleanup_oldest_idle_process()
122
-
125
+
123
126
  # Create new process
124
127
  self.logger.info(f"Creating new process for {server_name}")
125
128
  process = self._create_process(server_name, config)
126
-
129
+
127
130
  if process:
128
131
  create_time = time.time() - start_time
129
- self.logger.info(f"Process created for {server_name} in {create_time:.2f}s (PID: {process.pid})")
132
+ self.logger.info(
133
+ f"Process created for {server_name} in {create_time:.2f}s (PID: {process.pid})"
134
+ )
130
135
  self._startup_times[server_name] = create_time
131
-
136
+
132
137
  return process
133
-
134
- def _create_process(self, server_name: str, config: Dict) -> Optional[subprocess.Popen]:
138
+
139
+ def _create_process(
140
+ self, server_name: str, config: Dict
141
+ ) -> Optional[subprocess.Popen]:
135
142
  """
136
143
  Create a new MCP server process.
137
-
144
+
138
145
  Args:
139
146
  server_name: Name of the MCP server
140
147
  config: Server configuration
141
-
148
+
142
149
  Returns:
143
150
  Process handle or None if failed
144
151
  """
@@ -148,18 +155,18 @@ class MCPProcessPool:
148
155
  args = config.get("args", [])
149
156
  env = config.get("env", {})
150
157
  cwd = config.get("cwd")
151
-
158
+
152
159
  # Build full command
153
- full_command = [command] + args
154
-
160
+ full_command = [command, *args]
161
+
155
162
  # Merge environment variables
156
163
  process_env = os.environ.copy()
157
164
  process_env.update(env)
158
-
165
+
159
166
  # Add timing instrumentation
160
167
  process_env["MCP_STARTUP_TRACKING"] = "1"
161
168
  process_env["MCP_SERVER_NAME"] = server_name
162
-
169
+
163
170
  # Start the process
164
171
  process = subprocess.Popen(
165
172
  full_command,
@@ -168,49 +175,49 @@ class MCPProcessPool:
168
175
  stderr=subprocess.PIPE,
169
176
  env=process_env,
170
177
  cwd=cwd,
171
- bufsize=0 # Unbuffered for real-time communication
178
+ bufsize=0, # Unbuffered for real-time communication
172
179
  )
173
-
180
+
174
181
  # Store process info
175
182
  self._processes[server_name] = process
176
183
  self._process_info[server_name] = {
177
184
  "pid": process.pid,
178
185
  "started_at": time.time(),
179
186
  "last_used": time.time(),
180
- "config": config
187
+ "config": config,
181
188
  }
182
-
189
+
183
190
  # Write process info to file for debugging
184
191
  info_file = self.pool_dir / f"{server_name}_{process.pid}.json"
185
- with open(info_file, 'w') as f:
192
+ with open(info_file, "w") as f:
186
193
  json.dump(self._process_info[server_name], f, indent=2)
187
-
194
+
188
195
  return process
189
-
196
+
190
197
  except Exception as e:
191
198
  self.logger.error(f"Failed to create process for {server_name}: {e}")
192
199
  return None
193
-
200
+
194
201
  def _is_process_healthy(self, process: subprocess.Popen) -> bool:
195
202
  """Check if a process is still running and healthy."""
196
203
  if process.poll() is not None:
197
204
  # Process has terminated
198
205
  return False
199
-
206
+
200
207
  try:
201
208
  # Send signal 0 to check if process is alive
202
209
  os.kill(process.pid, 0)
203
210
  return True
204
211
  except (OSError, ProcessLookupError):
205
212
  return False
206
-
213
+
207
214
  def _cleanup_process(self, server_name: str):
208
215
  """Clean up a specific process."""
209
216
  if server_name not in self._processes:
210
217
  return
211
-
218
+
212
219
  process = self._processes[server_name]
213
-
220
+
214
221
  try:
215
222
  # Try graceful shutdown first
216
223
  if self._is_process_healthy(process):
@@ -221,50 +228,49 @@ class MCPProcessPool:
221
228
  # Force kill if graceful shutdown fails
222
229
  process.kill()
223
230
  process.wait()
224
-
231
+
225
232
  # Remove from tracking
226
233
  del self._processes[server_name]
227
234
  del self._process_info[server_name]
228
-
235
+
229
236
  # Clean up info file
230
237
  for info_file in self.pool_dir.glob(f"{server_name}_*.json"):
231
238
  info_file.unlink()
232
-
239
+
233
240
  self.logger.info(f"Cleaned up process for {server_name}")
234
-
241
+
235
242
  except Exception as e:
236
243
  self.logger.warning(f"Error cleaning up process for {server_name}: {e}")
237
-
244
+
238
245
  def _cleanup_oldest_idle_process(self):
239
246
  """Find and clean up the oldest idle process."""
240
247
  if not self._process_info:
241
248
  return
242
-
249
+
243
250
  # Find process with oldest last_used time
244
251
  oldest_server = min(
245
252
  self._process_info.keys(),
246
- key=lambda k: self._process_info[k].get("last_used", 0)
253
+ key=lambda k: self._process_info[k].get("last_used", 0),
247
254
  )
248
-
255
+
249
256
  self.logger.info(f"Cleaning up oldest idle process: {oldest_server}")
250
257
  self._cleanup_process(oldest_server)
251
-
258
+
252
259
  async def pre_warm_servers(self, configs: Dict[str, Dict]):
253
260
  """
254
261
  Pre-warm MCP servers during framework initialization.
255
-
262
+
256
263
  Args:
257
264
  configs: Dictionary of server configurations
258
265
  """
259
266
  if self._pre_warmed:
260
267
  self.logger.info("Servers already pre-warmed")
261
268
  return
262
-
269
+
263
270
  self.logger.info(f"Pre-warming {len(configs)} MCP servers")
264
271
  start_time = time.time()
265
-
272
+
266
273
  # Start all servers in parallel
267
- tasks = []
268
274
  for server_name, config in configs.items():
269
275
  # Only pre-warm critical servers (like vector search)
270
276
  if "vector" in server_name.lower() or config.get("pre_warm", False):
@@ -272,36 +278,36 @@ class MCPProcessPool:
272
278
  process = self.get_or_create_process(server_name, config)
273
279
  if process:
274
280
  self.logger.info(f"Pre-warmed {server_name} (PID: {process.pid})")
275
-
281
+
276
282
  self._pre_warmed = True
277
283
  total_time = time.time() - start_time
278
284
  self.logger.info(f"Pre-warming completed in {total_time:.2f}s")
279
-
285
+
280
286
  async def start_health_monitoring(self):
281
287
  """Start background health monitoring of processes."""
282
288
  if self._health_check_task and not self._health_check_task.done():
283
289
  return
284
-
290
+
285
291
  self._health_check_task = asyncio.create_task(self._health_check_loop())
286
292
  self.logger.info("Started health monitoring")
287
-
293
+
288
294
  async def _health_check_loop(self):
289
295
  """Background loop to check process health."""
290
296
  while True:
291
297
  try:
292
298
  await asyncio.sleep(self.health_check_interval)
293
-
299
+
294
300
  # Check each process
295
301
  dead_processes = []
296
302
  for server_name, process in self._processes.items():
297
303
  if not self._is_process_healthy(process):
298
304
  dead_processes.append(server_name)
299
-
305
+
300
306
  # Clean up dead processes
301
307
  for server_name in dead_processes:
302
308
  self.logger.warning(f"Process {server_name} is dead, cleaning up")
303
309
  self._cleanup_process(server_name)
304
-
310
+
305
311
  # Check for idle timeout
306
312
  current_time = time.time()
307
313
  idle_processes = []
@@ -309,24 +315,24 @@ class MCPProcessPool:
309
315
  last_used = info.get("last_used", current_time)
310
316
  if current_time - last_used > self.process_timeout:
311
317
  idle_processes.append(server_name)
312
-
318
+
313
319
  # Clean up idle processes
314
320
  for server_name in idle_processes:
315
321
  self.logger.info(f"Process {server_name} idle timeout, cleaning up")
316
322
  self._cleanup_process(server_name)
317
-
323
+
318
324
  except Exception as e:
319
325
  self.logger.error(f"Error in health check loop: {e}")
320
-
326
+
321
327
  def mark_process_used(self, server_name: str):
322
328
  """Mark a process as recently used."""
323
329
  if server_name in self._process_info:
324
330
  self._process_info[server_name]["last_used"] = time.time()
325
-
331
+
326
332
  def get_startup_metrics(self) -> Dict[str, float]:
327
333
  """Get startup time metrics for all servers."""
328
334
  return self._startup_times.copy()
329
-
335
+
330
336
  def get_pool_status(self) -> Dict[str, Any]:
331
337
  """Get current status of the process pool."""
332
338
  return {
@@ -337,25 +343,25 @@ class MCPProcessPool:
337
343
  name: {
338
344
  "pid": info.get("pid"),
339
345
  "uptime": time.time() - info.get("started_at", time.time()),
340
- "idle_time": time.time() - info.get("last_used", time.time())
346
+ "idle_time": time.time() - info.get("last_used", time.time()),
341
347
  }
342
348
  for name, info in self._process_info.items()
343
349
  },
344
- "startup_metrics": self._startup_times
350
+ "startup_metrics": self._startup_times,
345
351
  }
346
-
352
+
347
353
  def cleanup_all(self):
348
354
  """Clean up all processes in the pool."""
349
355
  self.logger.info("Cleaning up all processes in pool")
350
-
356
+
351
357
  # Stop health monitoring
352
358
  if self._health_check_task:
353
359
  self._health_check_task.cancel()
354
-
360
+
355
361
  # Clean up all processes
356
362
  for server_name in list(self._processes.keys()):
357
363
  self._cleanup_process(server_name)
358
-
364
+
359
365
  self.logger.info("Process pool cleanup completed")
360
366
 
361
367
 
@@ -374,38 +380,38 @@ def get_process_pool() -> MCPProcessPool:
374
380
  async def pre_warm_mcp_servers():
375
381
  """Pre-warm MCP servers from configuration."""
376
382
  pool = get_process_pool()
377
-
383
+
378
384
  # Load MCP configurations
379
385
  configs = {}
380
-
386
+
381
387
  # Check .claude.json for MCP server configs
382
388
  claude_config_path = Path.home() / ".claude.json"
383
389
  if not claude_config_path.exists():
384
390
  # Try project-local config
385
391
  claude_config_path = Path.cwd() / ".claude.json"
386
-
392
+
387
393
  if claude_config_path.exists():
388
394
  try:
389
- with open(claude_config_path, 'r') as f:
395
+ with open(claude_config_path) as f:
390
396
  config_data = json.load(f)
391
397
  mcp_servers = config_data.get("mcpServers", {})
392
398
  configs.update(mcp_servers)
393
399
  except Exception as e:
394
400
  get_logger("MCPProcessPool").warning(f"Failed to load Claude config: {e}")
395
-
401
+
396
402
  # Check .mcp.json for additional configs
397
403
  mcp_config_path = Path.cwd() / ".mcp.json"
398
404
  if mcp_config_path.exists():
399
405
  try:
400
- with open(mcp_config_path, 'r') as f:
406
+ with open(mcp_config_path) as f:
401
407
  config_data = json.load(f)
402
408
  mcp_servers = config_data.get("mcpServers", {})
403
409
  configs.update(mcp_servers)
404
410
  except Exception as e:
405
411
  get_logger("MCPProcessPool").warning(f"Failed to load MCP config: {e}")
406
-
412
+
407
413
  if configs:
408
414
  await pool.pre_warm_servers(configs)
409
415
  await pool.start_health_monitoring()
410
-
411
- return pool
416
+
417
+ return pool