claude-mpm 3.4.10__py3-none-any.whl → 5.4.55__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 (950) hide show
  1. claude_mpm/BUILD_NUMBER +1 -0
  2. claude_mpm/VERSION +1 -0
  3. claude_mpm/__init__.py +50 -12
  4. claude_mpm/__main__.py +7 -2
  5. claude_mpm/agents/BASE_AGENT.md +164 -0
  6. claude_mpm/agents/BASE_ENGINEER.md +658 -0
  7. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +290 -0
  8. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
  9. claude_mpm/agents/MEMORY.md +72 -0
  10. claude_mpm/agents/PM_INSTRUCTIONS.md +1402 -0
  11. claude_mpm/agents/WORKFLOW.md +111 -0
  12. claude_mpm/agents/__init__.py +92 -80
  13. claude_mpm/agents/agent-template.yaml +83 -0
  14. claude_mpm/agents/agent_loader.py +560 -745
  15. claude_mpm/agents/agent_loader_integration.py +53 -55
  16. claude_mpm/agents/agents_metadata.py +186 -27
  17. claude_mpm/agents/async_agent_loader.py +436 -0
  18. claude_mpm/agents/base_agent.json +8 -4
  19. claude_mpm/agents/frontmatter_validator.py +754 -0
  20. claude_mpm/agents/system_agent_config.py +222 -155
  21. claude_mpm/agents/templates/README.md +465 -0
  22. claude_mpm/agents/templates/__init__.py +17 -13
  23. claude_mpm/agents/templates/circuit-breakers.md +1391 -0
  24. claude_mpm/agents/templates/context-management-examples.md +544 -0
  25. claude_mpm/agents/templates/git-file-tracking.md +584 -0
  26. claude_mpm/agents/templates/pm-examples.md +474 -0
  27. claude_mpm/agents/templates/pm-red-flags.md +310 -0
  28. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  29. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  30. claude_mpm/agents/templates/response-format.md +583 -0
  31. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  32. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  33. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  34. claude_mpm/agents/templates/validation-templates.md +312 -0
  35. claude_mpm/cli/__init__.py +90 -128
  36. claude_mpm/cli/__main__.py +33 -0
  37. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  38. claude_mpm/cli/commands/__init__.py +36 -12
  39. claude_mpm/cli/commands/agent_manager.py +1403 -0
  40. claude_mpm/cli/commands/agent_source.py +774 -0
  41. claude_mpm/cli/commands/agent_state_manager.py +335 -0
  42. claude_mpm/cli/commands/agents.py +2503 -168
  43. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  44. claude_mpm/cli/commands/agents_discover.py +338 -0
  45. claude_mpm/cli/commands/aggregate.py +540 -0
  46. claude_mpm/cli/commands/analyze.py +553 -0
  47. claude_mpm/cli/commands/analyze_code.py +528 -0
  48. claude_mpm/cli/commands/auto_configure.py +1053 -0
  49. claude_mpm/cli/commands/cleanup.py +588 -0
  50. claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
  51. claude_mpm/cli/commands/config.py +586 -0
  52. claude_mpm/cli/commands/configure.py +2654 -0
  53. claude_mpm/cli/commands/configure_agent_display.py +282 -0
  54. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  55. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  56. claude_mpm/cli/commands/configure_models.py +18 -0
  57. claude_mpm/cli/commands/configure_navigation.py +184 -0
  58. claude_mpm/cli/commands/configure_paths.py +104 -0
  59. claude_mpm/cli/commands/configure_persistence.py +254 -0
  60. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  61. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  62. claude_mpm/cli/commands/configure_validators.py +73 -0
  63. claude_mpm/cli/commands/dashboard.py +286 -0
  64. claude_mpm/cli/commands/debug.py +1386 -0
  65. claude_mpm/cli/commands/doctor.py +243 -0
  66. claude_mpm/cli/commands/hook_errors.py +277 -0
  67. claude_mpm/cli/commands/info.py +195 -74
  68. claude_mpm/cli/commands/local_deploy.py +534 -0
  69. claude_mpm/cli/commands/mcp.py +205 -0
  70. claude_mpm/cli/commands/mcp_command_router.py +161 -0
  71. claude_mpm/cli/commands/mcp_config.py +154 -0
  72. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  73. claude_mpm/cli/commands/mcp_external_commands.py +249 -0
  74. claude_mpm/cli/commands/mcp_install_commands.py +346 -0
  75. claude_mpm/cli/commands/mcp_pipx_config.py +208 -0
  76. claude_mpm/cli/commands/mcp_server_commands.py +155 -0
  77. claude_mpm/cli/commands/mcp_setup_external.py +868 -0
  78. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  79. claude_mpm/cli/commands/memory.py +585 -846
  80. claude_mpm/cli/commands/monitor.py +228 -310
  81. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  82. claude_mpm/cli/commands/mpm_init/core.py +759 -0
  83. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  84. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  85. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  86. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  87. claude_mpm/cli/commands/mpm_init/prompts.py +722 -0
  88. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  89. claude_mpm/cli/commands/mpm_init_handler.py +195 -0
  90. claude_mpm/cli/commands/postmortem.py +401 -0
  91. claude_mpm/cli/commands/profile.py +276 -0
  92. claude_mpm/cli/commands/run.py +910 -488
  93. claude_mpm/cli/commands/search.py +458 -0
  94. claude_mpm/cli/commands/skill_source.py +694 -0
  95. claude_mpm/cli/commands/skills.py +1246 -0
  96. claude_mpm/cli/commands/summarize.py +413 -0
  97. claude_mpm/cli/commands/tickets.py +536 -53
  98. claude_mpm/cli/commands/uninstall.py +176 -0
  99. claude_mpm/cli/commands/upgrade.py +152 -0
  100. claude_mpm/cli/commands/verify.py +119 -0
  101. claude_mpm/cli/executor.py +297 -0
  102. claude_mpm/cli/helpers.py +105 -0
  103. claude_mpm/cli/interactive/__init__.py +21 -0
  104. claude_mpm/cli/interactive/agent_wizard.py +1947 -0
  105. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  106. claude_mpm/cli/parser.py +87 -563
  107. claude_mpm/cli/parsers/__init__.py +35 -0
  108. claude_mpm/cli/parsers/agent_manager_parser.py +393 -0
  109. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  110. claude_mpm/cli/parsers/agents_parser.py +575 -0
  111. claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
  112. claude_mpm/cli/parsers/analyze_parser.py +135 -0
  113. claude_mpm/cli/parsers/auto_configure_parser.py +120 -0
  114. claude_mpm/cli/parsers/base_parser.py +644 -0
  115. claude_mpm/cli/parsers/config_parser.py +208 -0
  116. claude_mpm/cli/parsers/configure_parser.py +138 -0
  117. claude_mpm/cli/parsers/dashboard_parser.py +113 -0
  118. claude_mpm/cli/parsers/debug_parser.py +319 -0
  119. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  120. claude_mpm/cli/parsers/mcp_parser.py +195 -0
  121. claude_mpm/cli/parsers/memory_parser.py +138 -0
  122. claude_mpm/cli/parsers/monitor_parser.py +142 -0
  123. claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
  124. claude_mpm/cli/parsers/profile_parser.py +147 -0
  125. claude_mpm/cli/parsers/run_parser.py +157 -0
  126. claude_mpm/cli/parsers/search_parser.py +245 -0
  127. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  128. claude_mpm/cli/parsers/skills_parser.py +277 -0
  129. claude_mpm/cli/parsers/source_parser.py +138 -0
  130. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  131. claude_mpm/cli/shared/__init__.py +40 -0
  132. claude_mpm/cli/shared/argument_patterns.py +205 -0
  133. claude_mpm/cli/shared/base_command.py +242 -0
  134. claude_mpm/cli/shared/error_handling.py +242 -0
  135. claude_mpm/cli/shared/output_formatters.py +241 -0
  136. claude_mpm/cli/startup.py +1743 -0
  137. claude_mpm/cli/startup_display.py +480 -0
  138. claude_mpm/cli/startup_logging.py +839 -0
  139. claude_mpm/cli/utils.py +136 -47
  140. claude_mpm/cli_module/__init__.py +6 -6
  141. claude_mpm/cli_module/args.py +188 -140
  142. claude_mpm/cli_module/commands.py +79 -70
  143. claude_mpm/cli_module/migration_example.py +42 -64
  144. claude_mpm/commands/__init__.py +14 -0
  145. claude_mpm/commands/mpm-config.md +28 -0
  146. claude_mpm/commands/mpm-doctor.md +20 -0
  147. claude_mpm/commands/mpm-help.md +20 -0
  148. claude_mpm/commands/mpm-init.md +120 -0
  149. claude_mpm/commands/mpm-monitor.md +31 -0
  150. claude_mpm/commands/mpm-organize.md +120 -0
  151. claude_mpm/commands/mpm-postmortem.md +21 -0
  152. claude_mpm/commands/mpm-session-resume.md +30 -0
  153. claude_mpm/commands/mpm-status.md +20 -0
  154. claude_mpm/commands/mpm-ticket-view.md +109 -0
  155. claude_mpm/commands/mpm-version.md +20 -0
  156. claude_mpm/commands/mpm.md +31 -0
  157. claude_mpm/config/__init__.py +42 -2
  158. claude_mpm/config/agent_config.py +402 -0
  159. claude_mpm/config/agent_presets.py +488 -0
  160. claude_mpm/config/agent_sources.py +352 -0
  161. claude_mpm/config/experimental_features.py +217 -0
  162. claude_mpm/config/model_config.py +428 -0
  163. claude_mpm/config/paths.py +258 -0
  164. claude_mpm/config/skill_presets.py +392 -0
  165. claude_mpm/config/skill_sources.py +590 -0
  166. claude_mpm/config/socketio_config.py +125 -83
  167. claude_mpm/constants.py +132 -22
  168. claude_mpm/core/__init__.py +62 -36
  169. claude_mpm/core/agent_name_normalizer.py +71 -73
  170. claude_mpm/core/agent_registry.py +385 -492
  171. claude_mpm/core/agent_session_manager.py +81 -70
  172. claude_mpm/core/api_validator.py +330 -0
  173. claude_mpm/core/base_service.py +159 -122
  174. claude_mpm/core/cache.py +560 -0
  175. claude_mpm/core/claude_runner.py +696 -916
  176. claude_mpm/core/config.py +613 -122
  177. claude_mpm/core/config_aliases.py +74 -73
  178. claude_mpm/core/config_constants.py +314 -0
  179. claude_mpm/core/constants.py +361 -0
  180. claude_mpm/core/container.py +646 -104
  181. claude_mpm/core/enums.py +452 -0
  182. claude_mpm/core/error_handler.py +623 -0
  183. claude_mpm/core/exceptions.py +536 -0
  184. claude_mpm/core/factories.py +105 -109
  185. claude_mpm/core/file_utils.py +764 -0
  186. claude_mpm/core/framework/__init__.py +25 -0
  187. claude_mpm/core/framework/formatters/__init__.py +11 -0
  188. claude_mpm/core/framework/formatters/capability_generator.py +367 -0
  189. claude_mpm/core/framework/formatters/content_formatter.py +278 -0
  190. claude_mpm/core/framework/formatters/context_generator.py +185 -0
  191. claude_mpm/core/framework/loaders/__init__.py +13 -0
  192. claude_mpm/core/framework/loaders/agent_loader.py +213 -0
  193. claude_mpm/core/framework/loaders/file_loader.py +176 -0
  194. claude_mpm/core/framework/loaders/instruction_loader.py +222 -0
  195. claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
  196. claude_mpm/core/framework/processors/__init__.py +11 -0
  197. claude_mpm/core/framework/processors/memory_processor.py +230 -0
  198. claude_mpm/core/framework/processors/metadata_processor.py +146 -0
  199. claude_mpm/core/framework/processors/template_processor.py +244 -0
  200. claude_mpm/core/framework_loader.py +485 -414
  201. claude_mpm/core/hook_error_memory.py +381 -0
  202. claude_mpm/core/hook_manager.py +246 -86
  203. claude_mpm/core/hook_performance_config.py +147 -0
  204. claude_mpm/core/injectable_service.py +72 -63
  205. claude_mpm/core/instruction_reinforcement_hook.py +267 -0
  206. claude_mpm/core/interactive_session.py +670 -0
  207. claude_mpm/core/interfaces.py +570 -164
  208. claude_mpm/core/lazy.py +467 -0
  209. claude_mpm/core/log_manager.py +707 -0
  210. claude_mpm/core/logger.py +295 -134
  211. claude_mpm/core/logging_config.py +474 -0
  212. claude_mpm/core/logging_utils.py +520 -0
  213. claude_mpm/core/minimal_framework_loader.py +24 -22
  214. claude_mpm/core/mixins.py +30 -29
  215. claude_mpm/core/oneshot_session.py +594 -0
  216. claude_mpm/core/optimized_agent_loader.py +479 -0
  217. claude_mpm/core/optimized_startup.py +554 -0
  218. claude_mpm/core/output_style_manager.py +483 -0
  219. claude_mpm/core/pm_hook_interceptor.py +197 -82
  220. claude_mpm/core/protocols/__init__.py +23 -0
  221. claude_mpm/core/protocols/runner_protocol.py +103 -0
  222. claude_mpm/core/protocols/session_protocol.py +131 -0
  223. claude_mpm/core/service_registry.py +153 -116
  224. claude_mpm/core/session_manager.py +179 -64
  225. claude_mpm/core/shared/__init__.py +17 -0
  226. claude_mpm/core/shared/config_loader.py +326 -0
  227. claude_mpm/core/shared/path_resolver.py +281 -0
  228. claude_mpm/core/shared/singleton_manager.py +221 -0
  229. claude_mpm/core/socketio_pool.py +400 -137
  230. claude_mpm/core/system_context.py +38 -0
  231. claude_mpm/core/tool_access_control.py +64 -57
  232. claude_mpm/core/types.py +307 -0
  233. claude_mpm/core/typing_utils.py +553 -0
  234. claude_mpm/core/unified_agent_registry.py +969 -0
  235. claude_mpm/core/unified_config.py +570 -0
  236. claude_mpm/core/unified_paths.py +941 -0
  237. claude_mpm/dashboard/__init__.py +12 -0
  238. claude_mpm/dashboard/api/simple_directory.py +261 -0
  239. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  240. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
  241. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
  242. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
  243. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
  244. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
  245. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
  246. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
  247. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
  248. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
  249. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
  250. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  251. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
  252. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
  253. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
  254. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
  255. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
  256. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
  257. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
  258. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
  259. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
  260. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
  261. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
  262. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
  263. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
  264. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  265. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
  266. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
  267. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  268. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
  269. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
  270. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
  271. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
  272. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
  273. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
  274. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
  275. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
  276. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
  277. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  278. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
  279. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
  280. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
  281. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
  282. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
  283. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
  284. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
  285. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
  286. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
  287. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
  288. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  289. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
  290. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
  291. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
  292. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
  293. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
  294. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
  295. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
  296. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
  297. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
  298. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
  299. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
  300. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
  301. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
  302. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
  303. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
  304. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  305. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  306. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  307. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  308. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  309. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  310. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  311. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  312. claude_mpm/experimental/__init__.py +10 -0
  313. claude_mpm/experimental/cli_enhancements.py +104 -89
  314. claude_mpm/generators/__init__.py +1 -1
  315. claude_mpm/generators/agent_profile_generator.py +76 -66
  316. claude_mpm/hooks/__init__.py +37 -1
  317. claude_mpm/hooks/base_hook.py +37 -32
  318. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  319. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  320. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  321. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  322. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  323. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  324. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  325. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  326. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  327. claude_mpm/hooks/claude_hooks/connection_pool.py +250 -0
  328. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  329. claude_mpm/hooks/claude_hooks/event_handlers.py +888 -0
  330. claude_mpm/hooks/claude_hooks/hook_handler.py +652 -875
  331. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -7
  332. claude_mpm/hooks/claude_hooks/installer.py +806 -0
  333. claude_mpm/hooks/claude_hooks/memory_integration.py +249 -0
  334. claude_mpm/hooks/claude_hooks/response_tracking.py +412 -0
  335. claude_mpm/hooks/claude_hooks/services/__init__.py +15 -0
  336. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  337. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  338. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  339. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  340. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  341. claude_mpm/hooks/claude_hooks/services/connection_manager.py +229 -0
  342. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +254 -0
  343. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  344. claude_mpm/hooks/claude_hooks/services/state_manager.py +284 -0
  345. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  346. claude_mpm/hooks/claude_hooks/tool_analysis.py +224 -0
  347. claude_mpm/hooks/failure_learning/__init__.py +54 -0
  348. claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
  349. claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
  350. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
  351. claude_mpm/hooks/instruction_reinforcement.py +301 -0
  352. claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
  353. claude_mpm/hooks/kuzu_memory_hook.py +386 -0
  354. claude_mpm/hooks/kuzu_response_hook.py +179 -0
  355. claude_mpm/hooks/memory_integration_hook.py +201 -107
  356. claude_mpm/hooks/session_resume_hook.py +121 -0
  357. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  358. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  359. claude_mpm/hooks/tool_call_interceptor.py +92 -76
  360. claude_mpm/hooks/validation_hooks.py +62 -54
  361. claude_mpm/init.py +518 -83
  362. claude_mpm/models/__init__.py +9 -9
  363. claude_mpm/models/agent_definition.py +40 -23
  364. claude_mpm/models/agent_session.py +538 -0
  365. claude_mpm/models/git_repository.py +198 -0
  366. claude_mpm/models/resume_log.py +340 -0
  367. claude_mpm/schemas/__init__.py +12 -0
  368. claude_mpm/scripts/__init__.py +15 -0
  369. claude_mpm/scripts/claude-hook-handler.sh +227 -0
  370. claude_mpm/scripts/launch_monitor.py +165 -0
  371. claude_mpm/scripts/mpm_doctor.py +322 -0
  372. claude_mpm/scripts/socketio_daemon.py +189 -200
  373. claude_mpm/scripts/start_activity_logging.py +91 -0
  374. claude_mpm/services/__init__.py +208 -39
  375. claude_mpm/services/agent_capabilities_service.py +266 -0
  376. claude_mpm/services/agents/__init__.py +89 -0
  377. claude_mpm/services/agents/agent_builder.py +514 -0
  378. claude_mpm/services/agents/agent_preset_service.py +238 -0
  379. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  380. claude_mpm/services/agents/agent_review_service.py +280 -0
  381. claude_mpm/services/agents/agent_selection_service.py +484 -0
  382. claude_mpm/services/agents/auto_config_manager.py +796 -0
  383. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  384. claude_mpm/services/agents/cache_git_manager.py +621 -0
  385. claude_mpm/services/agents/deployment/__init__.py +21 -0
  386. claude_mpm/services/agents/deployment/agent_config_provider.py +410 -0
  387. claude_mpm/services/agents/deployment/agent_configuration_manager.py +358 -0
  388. claude_mpm/services/agents/deployment/agent_definition_factory.py +80 -0
  389. claude_mpm/services/agents/deployment/agent_deployment.py +1037 -0
  390. claude_mpm/services/agents/deployment/agent_discovery_service.py +546 -0
  391. claude_mpm/services/agents/deployment/agent_environment_manager.py +288 -0
  392. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +383 -0
  393. claude_mpm/services/agents/deployment/agent_format_converter.py +505 -0
  394. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +160 -0
  395. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +957 -0
  396. claude_mpm/services/agents/deployment/agent_metrics_collector.py +273 -0
  397. claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
  398. claude_mpm/services/agents/deployment/agent_record_service.py +418 -0
  399. claude_mpm/services/agents/deployment/agent_restore_handler.py +84 -0
  400. claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
  401. claude_mpm/services/agents/deployment/agent_template_builder.py +1369 -0
  402. claude_mpm/services/agents/deployment/agent_validator.py +376 -0
  403. claude_mpm/services/agents/deployment/agent_version_manager.py +322 -0
  404. claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +10 -13
  405. claude_mpm/services/agents/deployment/agents_directory_resolver.py +149 -0
  406. claude_mpm/services/agents/deployment/async_agent_deployment.py +768 -0
  407. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  408. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  409. claude_mpm/services/agents/deployment/config/deployment_config.py +181 -0
  410. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  411. claude_mpm/services/agents/deployment/deployment_config_loader.py +178 -0
  412. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  413. claude_mpm/services/agents/deployment/deployment_type_detector.py +120 -0
  414. claude_mpm/services/agents/deployment/deployment_wrapper.py +129 -0
  415. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  416. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  417. claude_mpm/services/agents/deployment/facade/deployment_executor.py +70 -0
  418. claude_mpm/services/agents/deployment/facade/deployment_facade.py +269 -0
  419. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  420. claude_mpm/services/agents/deployment/interface_adapter.py +226 -0
  421. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  422. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  423. claude_mpm/services/agents/deployment/local_template_deployment.py +362 -0
  424. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +1478 -0
  425. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  426. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  427. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +162 -0
  428. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  429. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  430. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +240 -0
  431. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +110 -0
  432. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +80 -0
  433. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +92 -0
  434. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +101 -0
  435. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  436. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +102 -0
  437. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  438. claude_mpm/services/agents/deployment/processors/agent_processor.py +269 -0
  439. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +311 -0
  440. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +862 -0
  441. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  442. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  443. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  444. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  445. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  446. claude_mpm/services/agents/deployment/strategies/base_strategy.py +113 -0
  447. claude_mpm/services/agents/deployment/strategies/project_strategy.py +148 -0
  448. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  449. claude_mpm/services/agents/deployment/strategies/system_strategy.py +131 -0
  450. claude_mpm/services/agents/deployment/strategies/user_strategy.py +130 -0
  451. claude_mpm/services/agents/deployment/system_instructions_deployer.py +228 -0
  452. claude_mpm/services/agents/deployment/validation/__init__.py +21 -0
  453. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  454. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  455. claude_mpm/services/agents/deployment/validation/template_validator.py +319 -0
  456. claude_mpm/services/agents/deployment/validation/validation_result.py +214 -0
  457. claude_mpm/services/agents/git_source_manager.py +682 -0
  458. claude_mpm/services/agents/loading/__init__.py +11 -0
  459. claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +306 -228
  460. claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +106 -91
  461. claude_mpm/services/agents/loading/framework_agent_loader.py +433 -0
  462. claude_mpm/services/agents/local_template_manager.py +784 -0
  463. claude_mpm/services/agents/management/__init__.py +9 -0
  464. claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +92 -69
  465. claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +219 -168
  466. claude_mpm/services/agents/memory/__init__.py +22 -0
  467. claude_mpm/services/agents/memory/agent_memory_manager.py +784 -0
  468. claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +20 -18
  469. claude_mpm/services/agents/memory/content_manager.py +470 -0
  470. claude_mpm/services/agents/memory/memory_categorization_service.py +167 -0
  471. claude_mpm/services/agents/memory/memory_file_service.py +129 -0
  472. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  473. claude_mpm/services/agents/memory/memory_limits_service.py +101 -0
  474. claude_mpm/services/agents/memory/template_generator.py +83 -0
  475. claude_mpm/services/agents/observers.py +547 -0
  476. claude_mpm/services/agents/recommender.py +617 -0
  477. claude_mpm/services/agents/registry/__init__.py +30 -0
  478. claude_mpm/services/agents/registry/deployed_agent_discovery.py +273 -0
  479. claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +370 -295
  480. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  481. claude_mpm/services/agents/sources/__init__.py +13 -0
  482. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  483. claude_mpm/services/agents/sources/git_source_sync_service.py +1202 -0
  484. claude_mpm/services/agents/startup_sync.py +259 -0
  485. claude_mpm/services/agents/toolchain_detector.py +478 -0
  486. claude_mpm/services/analysis/__init__.py +35 -0
  487. claude_mpm/services/analysis/clone_detector.py +1030 -0
  488. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  489. claude_mpm/services/analysis/postmortem_service.py +765 -0
  490. claude_mpm/services/async_session_logger.py +665 -0
  491. claude_mpm/services/claude_session_logger.py +321 -0
  492. claude_mpm/services/cli/__init__.py +18 -0
  493. claude_mpm/services/cli/agent_cleanup_service.py +408 -0
  494. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  495. claude_mpm/services/cli/agent_listing_service.py +463 -0
  496. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  497. claude_mpm/services/cli/agent_validation_service.py +590 -0
  498. claude_mpm/services/cli/memory_crud_service.py +622 -0
  499. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  500. claude_mpm/services/cli/resume_service.py +617 -0
  501. claude_mpm/services/cli/session_manager.py +604 -0
  502. claude_mpm/services/cli/session_pause_manager.py +504 -0
  503. claude_mpm/services/cli/session_resume_helper.py +372 -0
  504. claude_mpm/services/cli/startup_checker.py +362 -0
  505. claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
  506. claude_mpm/services/command_deployment_service.py +446 -0
  507. claude_mpm/services/command_handler_service.py +221 -0
  508. claude_mpm/services/communication/__init__.py +22 -0
  509. claude_mpm/services/core/__init__.py +108 -0
  510. claude_mpm/services/core/base.py +269 -0
  511. claude_mpm/services/core/cache_manager.py +309 -0
  512. claude_mpm/services/core/interfaces/__init__.py +273 -0
  513. claude_mpm/services/core/interfaces/agent.py +514 -0
  514. claude_mpm/services/core/interfaces/communication.py +316 -0
  515. claude_mpm/services/core/interfaces/health.py +169 -0
  516. claude_mpm/services/core/interfaces/infrastructure.py +357 -0
  517. claude_mpm/services/core/interfaces/model.py +281 -0
  518. claude_mpm/services/core/interfaces/process.py +372 -0
  519. claude_mpm/services/core/interfaces/project.py +121 -0
  520. claude_mpm/services/core/interfaces/restart.py +307 -0
  521. claude_mpm/services/core/interfaces/service.py +405 -0
  522. claude_mpm/services/core/interfaces/stability.py +260 -0
  523. claude_mpm/services/core/interfaces.py +81 -0
  524. claude_mpm/services/core/memory_manager.py +682 -0
  525. claude_mpm/services/core/models/__init__.py +70 -0
  526. claude_mpm/services/core/models/agent_config.py +384 -0
  527. claude_mpm/services/core/models/health.py +162 -0
  528. claude_mpm/services/core/models/process.py +239 -0
  529. claude_mpm/services/core/models/restart.py +302 -0
  530. claude_mpm/services/core/models/stability.py +264 -0
  531. claude_mpm/services/core/models/toolchain.py +306 -0
  532. claude_mpm/services/core/path_resolver.py +517 -0
  533. claude_mpm/services/core/service_container.py +520 -0
  534. claude_mpm/services/core/service_interfaces.py +436 -0
  535. claude_mpm/services/diagnostics/__init__.py +18 -0
  536. claude_mpm/services/diagnostics/checks/__init__.py +38 -0
  537. claude_mpm/services/diagnostics/checks/agent_check.py +370 -0
  538. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  539. claude_mpm/services/diagnostics/checks/base_check.py +60 -0
  540. claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
  541. claude_mpm/services/diagnostics/checks/common_issues_check.py +363 -0
  542. claude_mpm/services/diagnostics/checks/configuration_check.py +306 -0
  543. claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
  544. claude_mpm/services/diagnostics/checks/installation_check.py +520 -0
  545. claude_mpm/services/diagnostics/checks/instructions_check.py +415 -0
  546. claude_mpm/services/diagnostics/checks/mcp_check.py +330 -0
  547. claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
  548. claude_mpm/services/diagnostics/checks/monitor_check.py +281 -0
  549. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  550. claude_mpm/services/diagnostics/checks/startup_log_check.py +319 -0
  551. claude_mpm/services/diagnostics/diagnostic_runner.py +286 -0
  552. claude_mpm/services/diagnostics/doctor_reporter.py +578 -0
  553. claude_mpm/services/diagnostics/models.py +138 -0
  554. claude_mpm/services/event_aggregator.py +582 -0
  555. claude_mpm/services/event_bus/__init__.py +18 -0
  556. claude_mpm/services/event_bus/config.py +186 -0
  557. claude_mpm/services/event_bus/direct_relay.py +312 -0
  558. claude_mpm/services/event_bus/event_bus.py +396 -0
  559. claude_mpm/services/event_bus/relay.py +326 -0
  560. claude_mpm/services/events/__init__.py +44 -0
  561. claude_mpm/services/events/consumers/__init__.py +18 -0
  562. claude_mpm/services/events/consumers/dead_letter.py +306 -0
  563. claude_mpm/services/events/consumers/logging.py +184 -0
  564. claude_mpm/services/events/consumers/metrics.py +241 -0
  565. claude_mpm/services/events/consumers/socketio.py +377 -0
  566. claude_mpm/services/events/core.py +480 -0
  567. claude_mpm/services/events/interfaces.py +214 -0
  568. claude_mpm/services/events/producers/__init__.py +14 -0
  569. claude_mpm/services/events/producers/hook.py +269 -0
  570. claude_mpm/services/events/producers/system.py +329 -0
  571. claude_mpm/services/exceptions.py +433 -353
  572. claude_mpm/services/framework_claude_md_generator/__init__.py +81 -80
  573. claude_mpm/services/framework_claude_md_generator/content_assembler.py +74 -67
  574. claude_mpm/services/framework_claude_md_generator/content_validator.py +66 -62
  575. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +82 -60
  576. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +36 -37
  577. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +41 -40
  578. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +15 -15
  579. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +5 -4
  580. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  581. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  582. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  583. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  584. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +5 -4
  585. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  586. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  587. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +26 -30
  588. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +6 -5
  589. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  590. claude_mpm/services/framework_claude_md_generator/version_manager.py +31 -30
  591. claude_mpm/services/git/__init__.py +21 -0
  592. claude_mpm/services/git/git_operations_service.py +579 -0
  593. claude_mpm/services/github/__init__.py +21 -0
  594. claude_mpm/services/github/github_cli_service.py +397 -0
  595. claude_mpm/services/hook_installer_service.py +506 -0
  596. claude_mpm/services/hook_service.py +159 -111
  597. claude_mpm/services/infrastructure/__init__.py +52 -0
  598. claude_mpm/services/infrastructure/context_preservation.py +569 -0
  599. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  600. claude_mpm/services/infrastructure/logging.py +209 -0
  601. claude_mpm/services/infrastructure/monitoring/__init__.py +39 -0
  602. claude_mpm/services/infrastructure/monitoring/aggregator.py +432 -0
  603. claude_mpm/services/infrastructure/monitoring/base.py +122 -0
  604. claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
  605. claude_mpm/services/infrastructure/monitoring/network.py +219 -0
  606. claude_mpm/services/infrastructure/monitoring/process.py +343 -0
  607. claude_mpm/services/infrastructure/monitoring/resources.py +244 -0
  608. claude_mpm/services/infrastructure/monitoring/service.py +368 -0
  609. claude_mpm/services/infrastructure/monitoring.py +71 -0
  610. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  611. claude_mpm/services/instructions/__init__.py +9 -0
  612. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  613. claude_mpm/services/local_ops/__init__.py +155 -0
  614. claude_mpm/services/local_ops/crash_detector.py +257 -0
  615. claude_mpm/services/local_ops/health_checks/__init__.py +26 -0
  616. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  617. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  618. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  619. claude_mpm/services/local_ops/health_manager.py +427 -0
  620. claude_mpm/services/local_ops/log_monitor.py +396 -0
  621. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  622. claude_mpm/services/local_ops/process_manager.py +595 -0
  623. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  624. claude_mpm/services/local_ops/restart_manager.py +401 -0
  625. claude_mpm/services/local_ops/restart_policy.py +387 -0
  626. claude_mpm/services/local_ops/state_manager.py +372 -0
  627. claude_mpm/services/local_ops/unified_manager.py +600 -0
  628. claude_mpm/services/mcp_config_manager.py +1542 -0
  629. claude_mpm/services/mcp_service_verifier.py +732 -0
  630. claude_mpm/services/memory/__init__.py +19 -0
  631. claude_mpm/services/{memory_builder.py → memory/builder.py} +465 -373
  632. claude_mpm/services/memory/cache/__init__.py +14 -0
  633. claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +237 -200
  634. claude_mpm/services/memory/cache/simple_cache.py +331 -0
  635. claude_mpm/services/memory/failure_tracker.py +578 -0
  636. claude_mpm/services/memory/indexed_memory.py +648 -0
  637. claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +272 -243
  638. claude_mpm/services/memory/router.py +951 -0
  639. claude_mpm/services/memory_hook_service.py +470 -0
  640. claude_mpm/services/model/__init__.py +147 -0
  641. claude_mpm/services/model/base_provider.py +365 -0
  642. claude_mpm/services/model/claude_provider.py +412 -0
  643. claude_mpm/services/model/model_router.py +452 -0
  644. claude_mpm/services/model/ollama_provider.py +415 -0
  645. claude_mpm/services/monitor/__init__.py +20 -0
  646. claude_mpm/services/monitor/daemon.py +698 -0
  647. claude_mpm/services/monitor/daemon_manager.py +1076 -0
  648. claude_mpm/services/monitor/event_emitter.py +350 -0
  649. claude_mpm/services/monitor/handlers/__init__.py +21 -0
  650. claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
  651. claude_mpm/services/monitor/handlers/dashboard.py +299 -0
  652. claude_mpm/services/monitor/handlers/file.py +264 -0
  653. claude_mpm/services/monitor/handlers/hooks.py +512 -0
  654. claude_mpm/services/monitor/management/__init__.py +18 -0
  655. claude_mpm/services/monitor/management/health.py +124 -0
  656. claude_mpm/services/monitor/management/lifecycle.py +730 -0
  657. claude_mpm/services/monitor/server.py +1493 -0
  658. claude_mpm/services/monitor_build_service.py +349 -0
  659. claude_mpm/services/native_agent_converter.py +356 -0
  660. claude_mpm/services/orphan_detection.py +786 -0
  661. claude_mpm/services/pm_skills_deployer.py +707 -0
  662. claude_mpm/services/port_manager.py +597 -0
  663. claude_mpm/services/pr/__init__.py +14 -0
  664. claude_mpm/services/pr/pr_template_service.py +329 -0
  665. claude_mpm/services/profile_manager.py +337 -0
  666. claude_mpm/services/project/__init__.py +44 -0
  667. claude_mpm/services/{project_analyzer.py → project/analyzer.py} +541 -291
  668. claude_mpm/services/project/analyzer_v2.py +566 -0
  669. claude_mpm/services/project/architecture_analyzer.py +461 -0
  670. claude_mpm/services/project/archive_manager.py +1045 -0
  671. claude_mpm/services/project/dependency_analyzer.py +462 -0
  672. claude_mpm/services/project/detection_strategies.py +719 -0
  673. claude_mpm/services/project/documentation_manager.py +554 -0
  674. claude_mpm/services/project/enhanced_analyzer.py +572 -0
  675. claude_mpm/services/project/language_analyzer.py +265 -0
  676. claude_mpm/services/project/metrics_collector.py +407 -0
  677. claude_mpm/services/project/project_organizer.py +1009 -0
  678. claude_mpm/services/project/registry.py +636 -0
  679. claude_mpm/services/project/toolchain_analyzer.py +583 -0
  680. claude_mpm/services/project_port_allocator.py +596 -0
  681. claude_mpm/services/recovery_manager.py +293 -240
  682. claude_mpm/services/response_tracker.py +267 -0
  683. claude_mpm/services/runner_configuration_service.py +605 -0
  684. claude_mpm/services/self_upgrade_service.py +608 -0
  685. claude_mpm/services/session_management_service.py +314 -0
  686. claude_mpm/services/session_manager.py +380 -0
  687. claude_mpm/services/shared/__init__.py +21 -0
  688. claude_mpm/services/shared/async_service_base.py +216 -0
  689. claude_mpm/services/shared/config_service_base.py +301 -0
  690. claude_mpm/services/shared/lifecycle_service_base.py +308 -0
  691. claude_mpm/services/shared/manager_base.py +315 -0
  692. claude_mpm/services/shared/service_factory.py +309 -0
  693. claude_mpm/services/skills/__init__.py +21 -0
  694. claude_mpm/services/skills/git_skill_source_manager.py +1324 -0
  695. claude_mpm/services/skills/selective_skill_deployer.py +744 -0
  696. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  697. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  698. claude_mpm/services/skills_config.py +547 -0
  699. claude_mpm/services/skills_deployer.py +1168 -0
  700. claude_mpm/services/socketio/__init__.py +25 -0
  701. claude_mpm/services/socketio/client_proxy.py +229 -0
  702. claude_mpm/services/socketio/dashboard_server.py +362 -0
  703. claude_mpm/services/socketio/event_normalizer.py +798 -0
  704. claude_mpm/services/socketio/handlers/__init__.py +30 -0
  705. claude_mpm/services/socketio/handlers/base.py +136 -0
  706. claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
  707. claude_mpm/services/socketio/handlers/connection.py +643 -0
  708. claude_mpm/services/socketio/handlers/connection_handler.py +333 -0
  709. claude_mpm/services/socketio/handlers/file.py +263 -0
  710. claude_mpm/services/socketio/handlers/git.py +962 -0
  711. claude_mpm/services/socketio/handlers/hook.py +211 -0
  712. claude_mpm/services/socketio/handlers/memory.py +26 -0
  713. claude_mpm/services/socketio/handlers/project.py +24 -0
  714. claude_mpm/services/socketio/handlers/registry.py +214 -0
  715. claude_mpm/services/socketio/migration_utils.py +343 -0
  716. claude_mpm/services/socketio/monitor_client.py +364 -0
  717. claude_mpm/services/socketio/server/__init__.py +18 -0
  718. claude_mpm/services/socketio/server/broadcaster.py +569 -0
  719. claude_mpm/services/socketio/server/connection_manager.py +579 -0
  720. claude_mpm/services/socketio/server/core.py +1079 -0
  721. claude_mpm/services/socketio/server/eventbus_integration.py +245 -0
  722. claude_mpm/services/socketio/server/main.py +501 -0
  723. claude_mpm/services/socketio_client_manager.py +173 -143
  724. claude_mpm/services/socketio_server.py +38 -1657
  725. claude_mpm/services/subprocess_launcher_service.py +322 -0
  726. claude_mpm/services/system_instructions_service.py +270 -0
  727. claude_mpm/services/ticket_manager.py +25 -209
  728. claude_mpm/services/ticket_services/__init__.py +26 -0
  729. claude_mpm/services/ticket_services/crud_service.py +328 -0
  730. claude_mpm/services/ticket_services/formatter_service.py +290 -0
  731. claude_mpm/services/ticket_services/search_service.py +324 -0
  732. claude_mpm/services/ticket_services/validation_service.py +303 -0
  733. claude_mpm/services/ticket_services/workflow_service.py +244 -0
  734. claude_mpm/services/unified/__init__.py +65 -0
  735. claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
  736. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
  737. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
  738. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
  739. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
  740. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
  741. claude_mpm/services/unified/config_strategies/__init__.py +175 -0
  742. claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
  743. claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
  744. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
  745. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
  746. claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
  747. claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
  748. claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
  749. claude_mpm/services/unified/deployment_strategies/base.py +553 -0
  750. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
  751. claude_mpm/services/unified/deployment_strategies/local.py +607 -0
  752. claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
  753. claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
  754. claude_mpm/services/unified/interfaces.py +475 -0
  755. claude_mpm/services/unified/migration.py +509 -0
  756. claude_mpm/services/unified/strategies.py +534 -0
  757. claude_mpm/services/unified/unified_analyzer.py +542 -0
  758. claude_mpm/services/unified/unified_config.py +691 -0
  759. claude_mpm/services/unified/unified_deployment.py +466 -0
  760. claude_mpm/services/utility_service.py +280 -0
  761. claude_mpm/services/version_control/__init__.py +34 -37
  762. claude_mpm/services/version_control/branch_strategy.py +26 -17
  763. claude_mpm/services/version_control/conflict_resolution.py +52 -36
  764. claude_mpm/services/version_control/git_operations.py +183 -49
  765. claude_mpm/services/version_control/semantic_versioning.py +172 -61
  766. claude_mpm/services/version_control/version_parser.py +546 -0
  767. claude_mpm/services/version_service.py +379 -0
  768. claude_mpm/services/visualization/__init__.py +15 -0
  769. claude_mpm/services/visualization/mermaid_generator.py +937 -0
  770. claude_mpm/skills/__init__.py +42 -0
  771. claude_mpm/skills/agent_skills_injector.py +324 -0
  772. claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
  773. claude_mpm/skills/bundled/__init__.py +6 -0
  774. claude_mpm/skills/bundled/api-documentation.md +393 -0
  775. claude_mpm/skills/bundled/async-testing.md +571 -0
  776. claude_mpm/skills/bundled/code-review.md +143 -0
  777. claude_mpm/skills/bundled/database-migration.md +199 -0
  778. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  779. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  780. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  781. claude_mpm/skills/bundled/git-workflow.md +414 -0
  782. claude_mpm/skills/bundled/imagemagick.md +204 -0
  783. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  784. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  785. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
  786. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
  787. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
  788. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
  789. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
  790. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  791. claude_mpm/skills/bundled/pdf.md +141 -0
  792. claude_mpm/skills/bundled/performance-profiling.md +573 -0
  793. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  794. claude_mpm/skills/bundled/security-scanning.md +439 -0
  795. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  796. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  797. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
  798. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
  799. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
  800. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
  801. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  802. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  803. claude_mpm/skills/bundled/xlsx.md +157 -0
  804. claude_mpm/skills/registry.py +286 -0
  805. claude_mpm/skills/skill_manager.py +405 -0
  806. claude_mpm/skills/skills_registry.py +347 -0
  807. claude_mpm/skills/skills_service.py +739 -0
  808. claude_mpm/storage/__init__.py +9 -0
  809. claude_mpm/storage/state_storage.py +546 -0
  810. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  811. claude_mpm/templates/questions/__init__.py +38 -0
  812. claude_mpm/templates/questions/base.py +193 -0
  813. claude_mpm/templates/questions/pr_strategy.py +311 -0
  814. claude_mpm/templates/questions/project_init.py +385 -0
  815. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  816. claude_mpm/ticket_wrapper.py +2 -2
  817. claude_mpm/tools/__init__.py +10 -0
  818. claude_mpm/tools/__main__.py +208 -0
  819. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  820. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  821. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  822. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  823. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  824. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  825. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  826. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  827. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  828. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  829. claude_mpm/tools/code_tree_builder.py +631 -0
  830. claude_mpm/tools/code_tree_events.py +420 -0
  831. claude_mpm/tools/socketio_debug.py +671 -0
  832. claude_mpm/utils/__init__.py +8 -8
  833. claude_mpm/utils/agent_dependency_loader.py +1090 -0
  834. claude_mpm/utils/agent_filters.py +261 -0
  835. claude_mpm/utils/common.py +544 -0
  836. claude_mpm/utils/config_manager.py +168 -126
  837. claude_mpm/utils/console.py +11 -0
  838. claude_mpm/utils/database_connector.py +298 -0
  839. claude_mpm/utils/dependency_cache.py +373 -0
  840. claude_mpm/utils/dependency_manager.py +60 -59
  841. claude_mpm/utils/dependency_strategies.py +381 -0
  842. claude_mpm/utils/display_helper.py +260 -0
  843. claude_mpm/utils/environment_context.py +313 -0
  844. claude_mpm/utils/error_handler.py +78 -66
  845. claude_mpm/utils/file_utils.py +305 -0
  846. claude_mpm/utils/framework_detection.py +12 -11
  847. claude_mpm/utils/git_analyzer.py +407 -0
  848. claude_mpm/utils/gitignore.py +244 -0
  849. claude_mpm/utils/import_migration_example.py +12 -60
  850. claude_mpm/utils/imports.py +48 -45
  851. claude_mpm/utils/log_cleanup.py +627 -0
  852. claude_mpm/utils/migration.py +372 -0
  853. claude_mpm/utils/path_operations.py +110 -104
  854. claude_mpm/utils/progress.py +387 -0
  855. claude_mpm/utils/robust_installer.py +823 -0
  856. claude_mpm/utils/session_logging.py +121 -0
  857. claude_mpm/utils/structured_questions.py +619 -0
  858. claude_mpm/utils/subprocess_utils.py +343 -0
  859. claude_mpm/validation/__init__.py +1 -1
  860. claude_mpm/validation/agent_validator.py +214 -108
  861. claude_mpm/validation/frontmatter_validator.py +252 -0
  862. claude_mpm-5.4.55.dist-info/METADATA +999 -0
  863. claude_mpm-5.4.55.dist-info/RECORD +868 -0
  864. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/entry_points.txt +1 -3
  865. claude_mpm-5.4.55.dist-info/licenses/LICENSE +94 -0
  866. claude_mpm-5.4.55.dist-info/licenses/LICENSE-FAQ.md +153 -0
  867. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -88
  868. claude_mpm/agents/INSTRUCTIONS.md +0 -352
  869. claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
  870. claude_mpm/agents/base_agent_loader.py +0 -529
  871. claude_mpm/agents/schema/agent_schema.json +0 -314
  872. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
  873. claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -46
  874. claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -45
  875. claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -49
  876. claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -46
  877. claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -45
  878. claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -49
  879. claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -46
  880. claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -46
  881. claude_mpm/agents/templates/data_engineer.json +0 -110
  882. claude_mpm/agents/templates/documentation.json +0 -109
  883. claude_mpm/agents/templates/engineer.json +0 -113
  884. claude_mpm/agents/templates/ops.json +0 -109
  885. claude_mpm/agents/templates/pm.json +0 -25
  886. claude_mpm/agents/templates/qa.json +0 -111
  887. claude_mpm/agents/templates/research.json +0 -65
  888. claude_mpm/agents/templates/security.json +0 -113
  889. claude_mpm/agents/templates/test_integration.json +0 -112
  890. claude_mpm/agents/templates/version_control.json +0 -107
  891. claude_mpm/cli/commands/ui.py +0 -57
  892. claude_mpm/core/simple_runner.py +0 -1046
  893. claude_mpm/dashboard/open_dashboard.py +0 -34
  894. claude_mpm/deployment_paths.py +0 -261
  895. claude_mpm/hooks/builtin/__init__.py +0 -1
  896. claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
  897. claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
  898. claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
  899. claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
  900. claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
  901. claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
  902. claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
  903. claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
  904. claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
  905. claude_mpm/orchestration/__init__.py +0 -6
  906. claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
  907. claude_mpm/orchestration/archive/factory.py +0 -215
  908. claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
  909. claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
  910. claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
  911. claude_mpm/orchestration/archive/orchestrator.py +0 -501
  912. claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
  913. claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
  914. claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
  915. claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
  916. claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
  917. claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
  918. claude_mpm/schemas/workflow_validator.py +0 -411
  919. claude_mpm/services/agent_deployment.py +0 -1534
  920. claude_mpm/services/agent_lifecycle_manager.py +0 -1169
  921. claude_mpm/services/agent_memory_manager.py +0 -1415
  922. claude_mpm/services/agent_registry.py +0 -676
  923. claude_mpm/services/deployed_agent_discovery.py +0 -226
  924. claude_mpm/services/framework_agent_loader.py +0 -337
  925. claude_mpm/services/framework_claude_md_generator.py +0 -621
  926. claude_mpm/services/health_monitor.py +0 -892
  927. claude_mpm/services/memory_router.py +0 -538
  928. claude_mpm/services/parent_directory_manager/__init__.py +0 -577
  929. claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
  930. claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
  931. claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
  932. claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
  933. claude_mpm/services/parent_directory_manager/operations.py +0 -186
  934. claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
  935. claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
  936. claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
  937. claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
  938. claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
  939. claude_mpm/services/standalone_socketio_server.py +0 -1300
  940. claude_mpm/services/ticket_manager_di.py +0 -318
  941. claude_mpm/services/ticketing_service_original.py +0 -508
  942. claude_mpm/ui/__init__.py +0 -1
  943. claude_mpm/ui/rich_terminal_ui.py +0 -295
  944. claude_mpm/ui/terminal_ui.py +0 -328
  945. claude_mpm/utils/paths.py +0 -289
  946. claude_mpm-3.4.10.dist-info/METADATA +0 -183
  947. claude_mpm-3.4.10.dist-info/RECORD +0 -201
  948. claude_mpm-3.4.10.dist-info/licenses/LICENSE +0 -21
  949. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/WHEEL +0 -0
  950. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1058 @@
1
+ """
2
+ Check MCP external services installation and health.
3
+
4
+ WHY: Verify that MCP services (mcp-vector-search, mcp-browser, mcp-ticketer, kuzu-memory)
5
+ are properly installed and accessible for enhanced Claude Code capabilities.
6
+ """
7
+
8
+ import asyncio
9
+ import json
10
+ import subprocess
11
+ import time
12
+ from pathlib import Path
13
+ from typing import Dict, List, Optional, Tuple
14
+
15
+ from claude_mpm.core.logger import get_logger
16
+
17
+ from ....core.enums import OperationResult, ValidationSeverity
18
+ from ..models import DiagnosticResult
19
+ from .base_check import BaseDiagnosticCheck
20
+
21
+
22
+ class MCPServicesCheck(BaseDiagnosticCheck):
23
+ """Check MCP external services installation and health."""
24
+
25
+ def __init__(self, verbose: bool = False):
26
+ """Initialize the MCP services check."""
27
+ super().__init__(verbose)
28
+ self.logger = get_logger(self.__class__.__name__)
29
+
30
+ # Define MCP services to check
31
+ MCP_SERVICES = {
32
+ "mcp-vector-search": {
33
+ "package": "mcp-vector-search",
34
+ "command": [
35
+ "mcp-vector-search",
36
+ "--version",
37
+ ], # Use --version for proper check
38
+ "description": "Vector search for semantic code navigation",
39
+ "check_health": True,
40
+ "health_command": ["mcp-vector-search", "--version"],
41
+ "pipx_run_command": ["pipx", "run", "mcp-vector-search", "--version"],
42
+ "mcp_command": [
43
+ "python",
44
+ "-m",
45
+ "mcp_vector_search.mcp.server",
46
+ ], # Command to run as MCP server
47
+ "pipx_mcp_command": [
48
+ "pipx",
49
+ "run",
50
+ "--spec",
51
+ "mcp-vector-search",
52
+ "python",
53
+ "-m",
54
+ "mcp_vector_search.mcp.server",
55
+ ],
56
+ },
57
+ "mcp-browser": {
58
+ "package": "mcp-browser",
59
+ "command": ["mcp-browser", "--version"], # Use --version for proper check
60
+ "description": "Browser automation and web interaction",
61
+ "check_health": True,
62
+ "health_command": ["mcp-browser", "--version"],
63
+ "pipx_run_command": ["pipx", "run", "mcp-browser", "--version"],
64
+ "mcp_command": ["mcp-browser", "mcp"], # Command to run as MCP server
65
+ },
66
+ "mcp-ticketer": {
67
+ "package": "mcp-ticketer",
68
+ "command": ["mcp-ticketer", "--version"], # Use --version for proper check
69
+ "description": "Ticket and task management",
70
+ "check_health": True,
71
+ "health_command": ["mcp-ticketer", "--version"],
72
+ "pipx_run_command": ["pipx", "run", "mcp-ticketer", "--version"],
73
+ "mcp_command": ["mcp-ticketer", "mcp"], # Command to run as MCP server
74
+ },
75
+ "kuzu-memory": {
76
+ "package": "kuzu-memory",
77
+ "command": ["kuzu-memory", "--version"], # Use --version for proper check
78
+ "description": "Graph-based memory system",
79
+ "check_health": True, # v1.1.0+ has version command
80
+ "health_command": ["kuzu-memory", "--version"],
81
+ "pipx_run_command": ["pipx", "run", "kuzu-memory", "--version"],
82
+ "mcp_command": [
83
+ "kuzu-memory",
84
+ "mcp",
85
+ "serve",
86
+ ], # v1.1.0+ uses 'mcp serve' args
87
+ },
88
+ }
89
+
90
+ @property
91
+ def name(self) -> str:
92
+ return "mcp_services_check"
93
+
94
+ @property
95
+ def category(self) -> str:
96
+ return "MCP Services"
97
+
98
+ def run(self) -> DiagnosticResult:
99
+ """Run MCP services diagnostics."""
100
+ try:
101
+ details = {}
102
+ sub_results = []
103
+ services_status = {}
104
+
105
+ # Use MCPConfigManager to detect and fix corrupted installations
106
+ from claude_mpm.services.mcp_config_manager import MCPConfigManager
107
+
108
+ mcp_manager = MCPConfigManager()
109
+
110
+ # Run comprehensive fix for all MCP service issues
111
+ fix_success, fix_message = mcp_manager.fix_mcp_service_issues()
112
+ if (
113
+ fix_message
114
+ and fix_message != "All MCP services are functioning correctly"
115
+ ):
116
+ # Create diagnostic result for the fixes
117
+ fix_result = DiagnosticResult(
118
+ category="MCP Service Fixes",
119
+ status=(
120
+ OperationResult.SUCCESS
121
+ if fix_success
122
+ else ValidationSeverity.WARNING
123
+ ),
124
+ message=fix_message,
125
+ details={"auto_fix_applied": True},
126
+ )
127
+ sub_results.append(fix_result)
128
+
129
+ # Check if MCP services are available (read-only check)
130
+ available, availability_message = mcp_manager.check_mcp_services_available()
131
+ if not available:
132
+ # Services not configured - provide installation instructions
133
+ config_result = DiagnosticResult(
134
+ category="MCP Service Availability",
135
+ status=ValidationSeverity.WARNING,
136
+ message=availability_message,
137
+ details={"auto_config_applied": True},
138
+ )
139
+ sub_results.append(config_result)
140
+
141
+ # Check for kuzu-memory configuration issues and offer auto-fix
142
+ kuzu_config_result = self._check_and_fix_kuzu_memory_config()
143
+ if kuzu_config_result:
144
+ sub_results.append(kuzu_config_result)
145
+
146
+ # Check each MCP service
147
+ for service_name, service_config in self.MCP_SERVICES.items():
148
+ service_result = self._check_service(service_name, service_config)
149
+ sub_results.append(service_result)
150
+
151
+ # Extract connection test info if available
152
+ connection_test = service_result.details.get("connection_test", {})
153
+
154
+ services_status[service_name] = {
155
+ "status": service_result.status.value,
156
+ "installed": service_result.details.get("installed", False),
157
+ "accessible": service_result.details.get("accessible", False),
158
+ "version": service_result.details.get("version"),
159
+ "connection_tested": bool(connection_test),
160
+ "connected": connection_test.get("connected", False),
161
+ "response_time_ms": connection_test.get("response_time_ms"),
162
+ "tools_discovered": connection_test.get("tools_discovered", 0),
163
+ "connection_error": connection_test.get("error"),
164
+ }
165
+
166
+ # Check MCP gateway configuration for services
167
+ gateway_result = self._check_gateway_configuration()
168
+ sub_results.append(gateway_result)
169
+
170
+ # Count service statuses
171
+ installed_count = sum(1 for s in services_status.values() if s["installed"])
172
+ accessible_count = sum(
173
+ 1 for s in services_status.values() if s["accessible"]
174
+ )
175
+ connected_count = sum(1 for s in services_status.values() if s["connected"])
176
+ total_services = len(self.MCP_SERVICES)
177
+
178
+ # Calculate total tools discovered
179
+ total_tools = sum(
180
+ s.get("tools_discovered", 0) for s in services_status.values()
181
+ )
182
+
183
+ details["services"] = services_status
184
+ details["installed_count"] = installed_count
185
+ details["accessible_count"] = accessible_count
186
+ details["connected_count"] = connected_count
187
+ details["total_services"] = total_services
188
+ details["total_tools_discovered"] = total_tools
189
+ details["gateway_configured"] = (
190
+ gateway_result.status == OperationResult.SUCCESS
191
+ )
192
+
193
+ # Determine overall status
194
+ errors = [r for r in sub_results if r.status == ValidationSeverity.ERROR]
195
+ [r for r in sub_results if r.status == ValidationSeverity.WARNING]
196
+
197
+ if errors:
198
+ status = ValidationSeverity.ERROR
199
+ message = f"Critical issues with {len(errors)} MCP service(s)"
200
+ elif installed_count == 0:
201
+ status = ValidationSeverity.WARNING
202
+ message = "No MCP services installed"
203
+ elif connected_count == total_services:
204
+ status = OperationResult.SUCCESS
205
+ message = f"All {total_services} MCP services connected ({total_tools} tools available)"
206
+ elif connected_count > 0:
207
+ status = ValidationSeverity.WARNING
208
+ message = f"{connected_count}/{total_services} MCP services connected, {installed_count} installed"
209
+ elif accessible_count < installed_count:
210
+ status = ValidationSeverity.WARNING
211
+ message = f"{installed_count}/{total_services} services installed, {accessible_count} accessible"
212
+ elif installed_count < total_services:
213
+ status = ValidationSeverity.WARNING
214
+ message = f"{installed_count}/{total_services} MCP services installed"
215
+ else:
216
+ status = ValidationSeverity.WARNING
217
+ message = f"All {total_services} MCP services installed but connections not tested"
218
+
219
+ return DiagnosticResult(
220
+ category=self.category,
221
+ status=status,
222
+ message=message,
223
+ details=details,
224
+ sub_results=sub_results if self.verbose else [],
225
+ )
226
+
227
+ except Exception as e:
228
+ return DiagnosticResult(
229
+ category=self.category,
230
+ status=ValidationSeverity.ERROR,
231
+ message=f"MCP services check failed: {e!s}",
232
+ details={"error": str(e)},
233
+ )
234
+
235
+ async def _test_mcp_connection(self, service_name: str, command: List[str]) -> Dict:
236
+ """Test MCP server connection by sending JSON-RPC requests."""
237
+ result = {
238
+ "connected": False,
239
+ "response_time": None,
240
+ "tools_count": 0,
241
+ "tools": [],
242
+ "error": None,
243
+ }
244
+
245
+ process = None
246
+ try:
247
+ # Start the MCP server process
248
+ start_time = time.time()
249
+ process = await asyncio.create_subprocess_exec(
250
+ *command,
251
+ stdin=asyncio.subprocess.PIPE,
252
+ stdout=asyncio.subprocess.PIPE,
253
+ stderr=asyncio.subprocess.PIPE,
254
+ )
255
+
256
+ # Give the server a moment to initialize
257
+ await asyncio.sleep(0.1)
258
+
259
+ # Prepare initialize request
260
+ init_request = {
261
+ "jsonrpc": "2.0",
262
+ "method": "initialize",
263
+ "params": {
264
+ "protocolVersion": "2024-11-05",
265
+ "capabilities": {},
266
+ "clientInfo": {"name": "mpm-doctor", "version": "1.0.0"},
267
+ },
268
+ "id": 1,
269
+ }
270
+
271
+ # Send initialize request
272
+ request_line = json.dumps(init_request) + "\n"
273
+ process.stdin.write(request_line.encode())
274
+ await process.stdin.drain()
275
+
276
+ # Read response with timeout
277
+ try:
278
+ response_line = await asyncio.wait_for(
279
+ process.stdout.readline(), timeout=5.0
280
+ )
281
+ response_time = time.time() - start_time
282
+
283
+ if response_line:
284
+ # Some MCP servers may output non-JSON before the actual response
285
+ # Try to find JSON in the response
286
+ response_text = response_line.decode().strip()
287
+
288
+ # Skip empty lines or non-JSON lines
289
+ while response_text and not response_text.startswith("{"):
290
+ # Try to read the next line
291
+ try:
292
+ response_line = await asyncio.wait_for(
293
+ process.stdout.readline(), timeout=1.0
294
+ )
295
+ if response_line:
296
+ response_text = response_line.decode().strip()
297
+ else:
298
+ break
299
+ except asyncio.TimeoutError:
300
+ break
301
+
302
+ if not response_text or not response_text.startswith("{"):
303
+ result["error"] = "No valid JSON response received"
304
+ return result
305
+
306
+ response = json.loads(response_text)
307
+
308
+ # Check for valid JSON-RPC response
309
+ if "result" in response and response.get("id") == 1:
310
+ result["connected"] = True
311
+ result["response_time"] = round(response_time * 1000, 2) # ms
312
+
313
+ # Send tools/list request
314
+ tools_request = {
315
+ "jsonrpc": "2.0",
316
+ "method": "tools/list",
317
+ "params": {},
318
+ "id": 2,
319
+ }
320
+
321
+ request_line = json.dumps(tools_request) + "\n"
322
+ process.stdin.write(request_line.encode())
323
+ await process.stdin.drain()
324
+
325
+ # Read tools response
326
+ try:
327
+ tools_response_line = await asyncio.wait_for(
328
+ process.stdout.readline(), timeout=3.0
329
+ )
330
+
331
+ if tools_response_line:
332
+ tools_response = json.loads(
333
+ tools_response_line.decode()
334
+ )
335
+ if "result" in tools_response:
336
+ tools = tools_response["result"].get("tools", [])
337
+ result["tools_count"] = len(tools)
338
+ # Store first 5 tool names for display
339
+ result["tools"] = [
340
+ tool.get("name", "unknown")
341
+ for tool in tools[:5]
342
+ ]
343
+ except asyncio.TimeoutError:
344
+ # Connection successful but tools query timed out
345
+ pass
346
+ except (json.JSONDecodeError, KeyError):
347
+ # Connection successful but tools response invalid
348
+ pass
349
+
350
+ elif "error" in response:
351
+ result["error"] = (
352
+ f"MCP error: {response['error'].get('message', 'Unknown error')}"
353
+ )
354
+ else:
355
+ result["error"] = "Invalid JSON-RPC response format"
356
+
357
+ except asyncio.TimeoutError:
358
+ # Try to get any error output from stderr
359
+ stderr_output = ""
360
+ if process and process.stderr:
361
+ try:
362
+ stderr_data = await asyncio.wait_for(
363
+ process.stderr.read(1000), timeout=0.5
364
+ )
365
+ if stderr_data:
366
+ stderr_output = stderr_data.decode(
367
+ "utf-8", errors="ignore"
368
+ )[:200]
369
+ except (asyncio.TimeoutError, OSError):
370
+ pass
371
+
372
+ if stderr_output:
373
+ result["error"] = (
374
+ f"Connection timeout (5s). Server output: {stderr_output}"
375
+ )
376
+ else:
377
+ result["error"] = "Connection timeout (5s)"
378
+
379
+ except json.JSONDecodeError as e:
380
+ # Try to get stderr for more context
381
+ stderr_output = ""
382
+ if process and process.stderr:
383
+ try:
384
+ stderr_data = await asyncio.wait_for(
385
+ process.stderr.read(1000), timeout=0.5
386
+ )
387
+ if stderr_data:
388
+ stderr_output = stderr_data.decode(
389
+ "utf-8", errors="ignore"
390
+ )[:200]
391
+ except (asyncio.TimeoutError, OSError):
392
+ pass
393
+
394
+ if stderr_output:
395
+ result["error"] = (
396
+ f"Invalid JSON response: {e!s}. Server error: {stderr_output}"
397
+ )
398
+ else:
399
+ result["error"] = f"Invalid JSON response: {e!s}"
400
+
401
+ except FileNotFoundError:
402
+ result["error"] = f"Command not found: {command[0]}"
403
+ except PermissionError:
404
+ result["error"] = f"Permission denied: {command[0]}"
405
+ except Exception as e:
406
+ result["error"] = f"Connection failed: {e!s}"
407
+ finally:
408
+ # Clean up process
409
+ if process:
410
+ try:
411
+ process.terminate()
412
+ await asyncio.wait_for(process.wait(), timeout=2.0)
413
+ except asyncio.TimeoutError:
414
+ process.kill()
415
+ await process.wait()
416
+ except Exception:
417
+ pass
418
+
419
+ return result
420
+
421
+ def _check_service(self, service_name: str, config: Dict) -> DiagnosticResult:
422
+ """Check a specific MCP service."""
423
+ details = {"service": service_name}
424
+
425
+ # Check if installed via pipx
426
+ pipx_installed, pipx_path = self._check_pipx_installation(config["package"])
427
+ details["pipx_installed"] = pipx_installed
428
+ if pipx_path:
429
+ details["pipx_path"] = pipx_path
430
+
431
+ # Special check for mcp-ticketer: ensure gql dependency
432
+ if service_name == "mcp-ticketer" and pipx_installed:
433
+ gql_fixed = self._ensure_mcp_ticketer_gql_dependency()
434
+ if gql_fixed:
435
+ details["gql_dependency_fixed"] = True
436
+
437
+ # Check if accessible in PATH
438
+ accessible, command_path = self._check_command_accessible(config["command"])
439
+ details["accessible"] = accessible
440
+ if command_path:
441
+ details["command_path"] = command_path
442
+
443
+ # If not directly accessible, try pipx run command
444
+ if (
445
+ not accessible
446
+ and "pipx_run_command" in config
447
+ and self._verify_command_works(config["pipx_run_command"])
448
+ ):
449
+ accessible = True
450
+ details["accessible_via_pipx_run"] = True
451
+ details["pipx_run_available"] = True
452
+
453
+ # Check for installation in various locations
454
+ if not pipx_installed and not accessible:
455
+ # Try common installation locations
456
+ alt_installed, alt_path = self._check_alternative_installations(
457
+ service_name
458
+ )
459
+ if alt_installed:
460
+ details["alternative_installation"] = alt_path
461
+ accessible = alt_installed
462
+
463
+ details["installed"] = pipx_installed or accessible
464
+
465
+ # Check service health/version if accessible
466
+ if accessible and config.get("check_health"):
467
+ # Try different version commands in order of preference
468
+ version_commands = []
469
+ if details.get("accessible_via_pipx_run") and "pipx_run_command" in config:
470
+ version_commands.append(config["pipx_run_command"])
471
+ if "health_command" in config:
472
+ version_commands.append(config["health_command"])
473
+ version_commands.append(config["command"])
474
+
475
+ for cmd in version_commands:
476
+ version = self._get_service_version(cmd)
477
+ if version:
478
+ details["version"] = version
479
+ break
480
+
481
+ # Test MCP connection if installed (accessible or pipx) and has mcp_command
482
+ if (accessible or pipx_installed) and "mcp_command" in config:
483
+ # Determine which command to use for MCP connection test
484
+ mcp_command = None
485
+ if pipx_installed and not accessible:
486
+ # Service is installed via pipx but not in PATH
487
+ if "pipx_mcp_command" in config:
488
+ # Use special pipx MCP command if available (e.g., for mcp-vector-search)
489
+ mcp_command = config["pipx_mcp_command"]
490
+ else:
491
+ # Build pipx run command based on package
492
+ base_cmd = config["mcp_command"]
493
+ if len(base_cmd) > 0 and base_cmd[0] == config["package"]:
494
+ # Simple case where first command is the package name
495
+ mcp_command = ["pipx", "run", config["package"], *base_cmd[1:]]
496
+ else:
497
+ # Complex case - just try running the package with mcp arg
498
+ mcp_command = ["pipx", "run", config["package"], "mcp"]
499
+ elif details.get("accessible_via_pipx_run"):
500
+ # Use pipx run for the MCP command
501
+ if "pipx_mcp_command" in config:
502
+ # Use special pipx MCP command if available (e.g., for mcp-vector-search)
503
+ mcp_command = config["pipx_mcp_command"]
504
+ else:
505
+ # Build pipx run command
506
+ base_cmd = config["mcp_command"]
507
+ if service_name == "kuzu-memory":
508
+ # Special case for kuzu-memory with args
509
+ mcp_command = ["pipx", "run", base_cmd[0], *base_cmd[1:]]
510
+ else:
511
+ mcp_command = ["pipx", "run", *base_cmd]
512
+ else:
513
+ mcp_command = config["mcp_command"]
514
+
515
+ if mcp_command:
516
+ # Run async connection test
517
+ try:
518
+ loop = asyncio.new_event_loop()
519
+ asyncio.set_event_loop(loop)
520
+ connection_result = loop.run_until_complete(
521
+ self._test_mcp_connection(service_name, mcp_command)
522
+ )
523
+ loop.close()
524
+
525
+ # Add connection test results to details
526
+ details["connection_test"] = {
527
+ "connected": connection_result["connected"],
528
+ "response_time_ms": connection_result["response_time"],
529
+ "tools_discovered": connection_result["tools_count"],
530
+ "tools_sample": connection_result["tools"],
531
+ "error": connection_result["error"],
532
+ }
533
+ except Exception as e:
534
+ details["connection_test"] = {
535
+ "connected": False,
536
+ "error": f"Test failed: {e!s}",
537
+ }
538
+
539
+ # Determine status
540
+ if not (pipx_installed or accessible):
541
+ return DiagnosticResult(
542
+ category=f"MCP Service: {service_name}",
543
+ status=ValidationSeverity.WARNING,
544
+ message=f"Not installed: {config['description']}",
545
+ details=details,
546
+ fix_command=f"pipx install {config['package']}",
547
+ fix_description=f"Install {service_name} for {config['description']}",
548
+ )
549
+
550
+ if pipx_installed and not accessible:
551
+ # Check if pipx run works
552
+ if details.get("pipx_run_available"):
553
+ # Include connection test info if available
554
+ connection_info = details.get("connection_test", {})
555
+ if connection_info.get("connected"):
556
+ message = f"Installed via pipx, connection OK ({connection_info.get('tools_discovered', 0)} tools)"
557
+ elif connection_info.get("error"):
558
+ message = f"Installed via pipx, connection failed: {connection_info['error']}"
559
+ else:
560
+ message = "Installed via pipx (use 'pipx run' to execute)"
561
+
562
+ return DiagnosticResult(
563
+ category=f"MCP Service: {service_name}",
564
+ status=(
565
+ OperationResult.SUCCESS
566
+ if connection_info.get("connected")
567
+ else ValidationSeverity.WARNING
568
+ ),
569
+ message=message,
570
+ details=details,
571
+ )
572
+ return DiagnosticResult(
573
+ category=f"MCP Service: {service_name}",
574
+ status=ValidationSeverity.WARNING,
575
+ message="Installed via pipx but not in PATH",
576
+ details=details,
577
+ fix_command="pipx ensurepath",
578
+ fix_description="Ensure pipx bin directory is in PATH",
579
+ )
580
+
581
+ # Service is accessible - check connection test results
582
+ connection_info = details.get("connection_test", {})
583
+ if connection_info:
584
+ if connection_info.get("connected"):
585
+ response_time = connection_info.get("response_time_ms")
586
+ tools_count = connection_info.get("tools_discovered", 0)
587
+ message = f"Installed, accessible, connection OK ({tools_count} tools, {response_time}ms)"
588
+ status = OperationResult.SUCCESS
589
+ else:
590
+ error = connection_info.get("error", "Unknown error")
591
+ message = f"Installed but connection failed: {error}"
592
+ status = ValidationSeverity.WARNING
593
+ else:
594
+ message = "Installed and accessible"
595
+ status = OperationResult.SUCCESS
596
+
597
+ return DiagnosticResult(
598
+ category=f"MCP Service: {service_name}",
599
+ status=status,
600
+ message=message,
601
+ details=details,
602
+ )
603
+
604
+ def _check_pipx_installation(self, package_name: str) -> Tuple[bool, Optional[str]]:
605
+ """Check if a package is installed via pipx."""
606
+ try:
607
+ result = subprocess.run(
608
+ ["pipx", "list", "--json"],
609
+ capture_output=True,
610
+ text=True,
611
+ timeout=5,
612
+ check=False,
613
+ )
614
+
615
+ if result.returncode == 0:
616
+ try:
617
+ data = json.loads(result.stdout)
618
+ venvs = data.get("venvs", {})
619
+
620
+ if package_name in venvs:
621
+ venv_info = venvs[package_name]
622
+ # Get the main app path
623
+ apps = (
624
+ venv_info.get("metadata", {})
625
+ .get("main_package", {})
626
+ .get("apps", [])
627
+ )
628
+ if apps:
629
+ app_path = (
630
+ venv_info.get("metadata", {})
631
+ .get("main_package", {})
632
+ .get("app_paths", [])
633
+ )
634
+ if app_path:
635
+ return True, app_path[0]
636
+ return True, None
637
+ except json.JSONDecodeError:
638
+ pass
639
+ except (subprocess.SubprocessError, FileNotFoundError):
640
+ pass
641
+
642
+ return False, None
643
+
644
+ def _check_command_accessible(
645
+ self, command: List[str]
646
+ ) -> Tuple[bool, Optional[str]]:
647
+ """Check if a command is accessible in PATH."""
648
+ try:
649
+ # Use 'which' on Unix-like systems
650
+ result = subprocess.run(
651
+ ["which", command[0]],
652
+ capture_output=True,
653
+ text=True,
654
+ timeout=2,
655
+ check=False,
656
+ )
657
+
658
+ if result.returncode == 0:
659
+ path = result.stdout.strip()
660
+ # Verify the command actually works with --version
661
+ if self._verify_command_works(command):
662
+ return True, path
663
+ return False, path
664
+ except (subprocess.SubprocessError, FileNotFoundError):
665
+ pass
666
+
667
+ # Try direct execution with --version
668
+ if self._verify_command_works(command):
669
+ return True, None
670
+
671
+ return False, None
672
+
673
+ def _verify_command_works(self, command: List[str]) -> bool:
674
+ """Verify a command actually works by checking its --version output."""
675
+ try:
676
+ result = subprocess.run(
677
+ command,
678
+ capture_output=True,
679
+ text=True,
680
+ timeout=5,
681
+ check=False,
682
+ )
683
+
684
+ # Check for successful execution or version output
685
+ # Don't accept error messages containing "help" or "usage" as success
686
+ if result.returncode == 0:
687
+ # Look for actual version information
688
+ output = (result.stdout + result.stderr).lower()
689
+ # Check for version indicators
690
+ if any(
691
+ keyword in output
692
+ for keyword in ["version", "v1.", "v0.", "1.", "0."]
693
+ ) and not any(
694
+ error in output
695
+ for error in [
696
+ "error",
697
+ "not found",
698
+ "no such",
699
+ "command not found",
700
+ ]
701
+ ):
702
+ return True
703
+
704
+ # For some tools, non-zero return code is OK if version is shown
705
+ elif "--version" in command or "--help" in command:
706
+ output = (result.stdout + result.stderr).lower()
707
+ # Must have version info and no error indicators
708
+ if (
709
+ "version" in output or "v1." in output or "v0." in output
710
+ ) and not any(
711
+ error in output
712
+ for error in [
713
+ "error",
714
+ "not found",
715
+ "no such",
716
+ "command not found",
717
+ "traceback",
718
+ ]
719
+ ):
720
+ return True
721
+
722
+ except (subprocess.SubprocessError, FileNotFoundError, OSError):
723
+ pass
724
+
725
+ return False
726
+
727
+ def _check_alternative_installations(
728
+ self, service_name: str
729
+ ) -> Tuple[bool, Optional[str]]:
730
+ """Check for alternative installation locations."""
731
+ # Common installation paths
732
+ paths_to_check = [
733
+ Path.home() / ".local" / "bin" / service_name,
734
+ Path("/usr/local/bin") / service_name,
735
+ Path("/opt") / service_name / "bin" / service_name,
736
+ Path.home() / ".npm" / "bin" / service_name, # For npm-based services
737
+ Path.home() / ".cargo" / "bin" / service_name, # For Rust-based services
738
+ ]
739
+
740
+ for path in paths_to_check:
741
+ if path.exists():
742
+ return True, str(path)
743
+
744
+ return False, None
745
+
746
+ def _get_service_version(self, command: List[str]) -> Optional[str]:
747
+ """Get version information for a service."""
748
+ try:
749
+ result = subprocess.run(
750
+ command,
751
+ capture_output=True,
752
+ text=True,
753
+ timeout=2,
754
+ check=False,
755
+ )
756
+
757
+ if result.returncode == 0:
758
+ output = result.stdout.strip()
759
+ # Try to extract version from output
760
+ lines = output.split("\n")
761
+ for line in lines:
762
+ if "version" in line.lower() or "v" in line.lower():
763
+ return line.strip()
764
+ # Return first line if no version line found
765
+ if lines:
766
+ return lines[0].strip()
767
+ except (subprocess.SubprocessError, FileNotFoundError):
768
+ pass
769
+
770
+ return None
771
+
772
+ def _check_and_fix_kuzu_memory_config(self) -> Optional[DiagnosticResult]:
773
+ """Check for incorrect kuzu-memory configuration in .claude.json and offer auto-fix."""
774
+ claude_config_path = Path.home() / ".claude.json"
775
+
776
+ if not claude_config_path.exists():
777
+ return None
778
+
779
+ try:
780
+ with claude_config_path.open() as f:
781
+ config = json.load(f)
782
+
783
+ mcp_servers = config.get("mcpServers", {})
784
+ kuzu_config = mcp_servers.get("kuzu-memory")
785
+
786
+ if not kuzu_config:
787
+ return None
788
+
789
+ # Check if kuzu-memory has incorrect args
790
+ args = kuzu_config.get("args", [])
791
+ needs_fix = False
792
+ fix_reason = ""
793
+ # The correct args for kuzu-memory v1.1.0+ are ["mcp", "serve"]
794
+ correct_args = ["mcp", "serve"]
795
+
796
+ # Check for any configuration that is NOT the correct one
797
+ if args != correct_args:
798
+ needs_fix = True
799
+ # Identify the specific issue
800
+ if args == ["claude", "mcp-server"]:
801
+ fix_reason = "Outdated 'claude mcp-server' format (pre-v1.1.0)"
802
+ elif args == ["serve"]:
803
+ fix_reason = "Legacy 'serve' format"
804
+ elif args == ["mcp-server"]:
805
+ fix_reason = "Incorrect 'mcp-server' format"
806
+ elif args == []:
807
+ fix_reason = "Empty args list"
808
+ else:
809
+ fix_reason = f"Incorrect args format: {args}"
810
+
811
+ if needs_fix:
812
+ # Log the issue for debugging
813
+ self.logger.warning(
814
+ f"Found incorrect kuzu-memory configuration: {fix_reason}. "
815
+ f"Current args: {args}, should be: {correct_args}"
816
+ )
817
+
818
+ # Auto-fix the configuration
819
+ fixed = self._fix_kuzu_memory_args(
820
+ claude_config_path, config, correct_args
821
+ )
822
+
823
+ if fixed:
824
+ return DiagnosticResult(
825
+ category="kuzu-memory Configuration Fix",
826
+ status=OperationResult.SUCCESS,
827
+ message="Fixed kuzu-memory configuration to use correct args",
828
+ details={
829
+ "old_args": args,
830
+ "new_args": correct_args,
831
+ "reason": fix_reason,
832
+ "auto_fixed": True,
833
+ },
834
+ )
835
+ return DiagnosticResult(
836
+ category="kuzu-memory Configuration",
837
+ status=ValidationSeverity.WARNING,
838
+ message="kuzu-memory has incorrect configuration",
839
+ details={
840
+ "current_args": args,
841
+ "correct_args": correct_args,
842
+ "reason": fix_reason,
843
+ "auto_fix_failed": True,
844
+ },
845
+ fix_command="claude-mpm configure --mcp --fix-kuzu",
846
+ fix_description="Fix kuzu-memory configuration manually",
847
+ )
848
+
849
+ # Configuration is correct - args match ["mcp", "serve"]
850
+ return None
851
+
852
+ except (json.JSONDecodeError, Exception) as e:
853
+ self.logger.debug(f"Could not check kuzu-memory config: {e}")
854
+ return None
855
+
856
+ def _fix_kuzu_memory_args(
857
+ self, config_path: Path, config: Dict, new_args: List[str]
858
+ ) -> bool:
859
+ """Fix kuzu-memory args in the configuration."""
860
+ try:
861
+ # Save old args before updating
862
+ old_args = config["mcpServers"]["kuzu-memory"].get("args", [])
863
+
864
+ # Log the exact change we're about to make
865
+ self.logger.debug(
866
+ f"Fixing kuzu-memory args: old={old_args}, new={new_args}"
867
+ )
868
+
869
+ # Create backup
870
+ backup_path = config_path.with_suffix(".json.backup")
871
+ with backup_path.open("w") as f:
872
+ json.dump(config, f, indent=2)
873
+
874
+ # Update the configuration - ensure we're setting the exact new_args
875
+ config["mcpServers"]["kuzu-memory"]["args"] = new_args
876
+
877
+ # Verify the update in memory before writing
878
+ if config["mcpServers"]["kuzu-memory"]["args"] != new_args:
879
+ self.logger.error(
880
+ f"Failed to update args in memory! "
881
+ f"Expected {new_args}, got {config['mcpServers']['kuzu-memory']['args']}"
882
+ )
883
+ return False
884
+
885
+ # Write updated configuration
886
+ with config_path.open("w") as f:
887
+ json.dump(config, f, indent=2)
888
+
889
+ # Verify the file was written correctly
890
+ with config_path.open() as f:
891
+ verify_config = json.load(f)
892
+ verify_args = (
893
+ verify_config.get("mcpServers", {})
894
+ .get("kuzu-memory", {})
895
+ .get("args", [])
896
+ )
897
+
898
+ if verify_args != new_args:
899
+ self.logger.error(
900
+ f"Configuration write verification failed! "
901
+ f"Expected {new_args}, got {verify_args}"
902
+ )
903
+ # Restore backup
904
+ with backup_path.open() as bf:
905
+ backup_config = json.load(bf)
906
+ with config_path.open("w") as f:
907
+ json.dump(backup_config, f, indent=2)
908
+ return False
909
+
910
+ self.logger.info(
911
+ f"✅ Fixed kuzu-memory configuration in {config_path}\n"
912
+ f" Changed args from {old_args} to {new_args}\n"
913
+ f" Backup saved to {backup_path}"
914
+ )
915
+
916
+ return True
917
+
918
+ except Exception as e:
919
+ self.logger.error(f"Failed to fix kuzu-memory configuration: {e}")
920
+ return False
921
+
922
+ def _check_gateway_configuration(self) -> DiagnosticResult:
923
+ """Check if MCP services are configured in the gateway."""
924
+ try:
925
+ # Check Claude config file (the correct location for Claude Code)
926
+ config_file = Path.home() / ".claude.json"
927
+
928
+ if not config_file.exists():
929
+ return DiagnosticResult(
930
+ category="MCP Gateway Configuration",
931
+ status=ValidationSeverity.WARNING,
932
+ message="Claude configuration file not found",
933
+ details={"config_path": str(config_file), "exists": False},
934
+ fix_command="claude-mpm configure --mcp",
935
+ fix_description="Initialize Claude configuration",
936
+ )
937
+
938
+ with config_file.open() as f:
939
+ config = json.load(f)
940
+
941
+ # Get the current project configuration
942
+ from pathlib import Path
943
+
944
+ current_project = str(Path.cwd())
945
+
946
+ # Check if current project has MCP servers configured
947
+ projects = config.get("projects", {})
948
+ if current_project not in projects:
949
+ return DiagnosticResult(
950
+ category="MCP Gateway Configuration",
951
+ status=ValidationSeverity.WARNING,
952
+ message="Current project not configured in Claude",
953
+ details={
954
+ "config_path": str(config_file),
955
+ "project": current_project,
956
+ },
957
+ fix_command="claude-mpm configure --mcp",
958
+ fix_description="Configure MCP services for current project",
959
+ )
960
+
961
+ project_config = projects[current_project]
962
+ mcp_servers = project_config.get("mcpServers", {})
963
+
964
+ configured_services = []
965
+ missing_services = []
966
+
967
+ for service_name in self.MCP_SERVICES:
968
+ if service_name in mcp_servers:
969
+ configured_services.append(service_name)
970
+ else:
971
+ missing_services.append(service_name)
972
+
973
+ details = {
974
+ "config_path": str(config_file),
975
+ "configured_services": configured_services,
976
+ "missing_services": missing_services,
977
+ }
978
+
979
+ if not configured_services:
980
+ return DiagnosticResult(
981
+ category="MCP Gateway Configuration",
982
+ status=ValidationSeverity.WARNING,
983
+ message="No MCP services configured in gateway",
984
+ details=details,
985
+ fix_command="claude-mpm configure --mcp --add-services",
986
+ fix_description="Add MCP services to gateway configuration",
987
+ )
988
+
989
+ if missing_services:
990
+ return DiagnosticResult(
991
+ category="MCP Gateway Configuration",
992
+ status=ValidationSeverity.WARNING,
993
+ message=f"{len(configured_services)} services configured, {len(missing_services)} missing",
994
+ details=details,
995
+ )
996
+
997
+ return DiagnosticResult(
998
+ category="MCP Gateway Configuration",
999
+ status=OperationResult.SUCCESS,
1000
+ message=f"All {len(configured_services)} services configured",
1001
+ details=details,
1002
+ )
1003
+
1004
+ except json.JSONDecodeError as e:
1005
+ return DiagnosticResult(
1006
+ category="MCP Gateway Configuration",
1007
+ status=ValidationSeverity.ERROR,
1008
+ message="Invalid JSON in MCP configuration",
1009
+ details={"error": str(e)},
1010
+ )
1011
+ except Exception as e:
1012
+ return DiagnosticResult(
1013
+ category="MCP Gateway Configuration",
1014
+ status=ValidationSeverity.WARNING,
1015
+ message=f"Could not check configuration: {e!s}",
1016
+ details={"error": str(e)},
1017
+ )
1018
+
1019
+ def _ensure_mcp_ticketer_gql_dependency(self) -> bool:
1020
+ """Ensure mcp-ticketer has the gql dependency injected."""
1021
+ try:
1022
+ # First check if mcp-ticketer can import gql
1023
+ result = subprocess.run(
1024
+ ["pipx", "run", "--spec", "mcp-ticketer", "python", "-c", "import gql"],
1025
+ capture_output=True,
1026
+ text=True,
1027
+ timeout=5,
1028
+ check=False,
1029
+ )
1030
+
1031
+ # If import fails, inject the dependency
1032
+ if result.returncode != 0:
1033
+ self.logger.info("🔧 mcp-ticketer missing gql dependency, fixing...")
1034
+
1035
+ inject_result = subprocess.run(
1036
+ ["pipx", "inject", "mcp-ticketer", "gql"],
1037
+ capture_output=True,
1038
+ text=True,
1039
+ timeout=30,
1040
+ check=False,
1041
+ )
1042
+
1043
+ if inject_result.returncode == 0:
1044
+ self.logger.info(
1045
+ "✅ Successfully injected gql dependency into mcp-ticketer"
1046
+ )
1047
+ return True
1048
+ self.logger.warning(
1049
+ f"Failed to inject gql dependency: {inject_result.stderr}"
1050
+ )
1051
+ return False
1052
+
1053
+ # Dependency already present
1054
+ return False
1055
+
1056
+ except Exception as e:
1057
+ self.logger.debug(f"Could not check/fix mcp-ticketer gql dependency: {e}")
1058
+ return False