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.
- claude_mpm/BUILD_NUMBER +1 -0
- claude_mpm/VERSION +1 -0
- claude_mpm/__init__.py +50 -12
- claude_mpm/__main__.py +7 -2
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +290 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
- claude_mpm/agents/MEMORY.md +72 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1402 -0
- claude_mpm/agents/WORKFLOW.md +111 -0
- claude_mpm/agents/__init__.py +92 -80
- claude_mpm/agents/agent-template.yaml +83 -0
- claude_mpm/agents/agent_loader.py +560 -745
- claude_mpm/agents/agent_loader_integration.py +53 -55
- claude_mpm/agents/agents_metadata.py +186 -27
- claude_mpm/agents/async_agent_loader.py +436 -0
- claude_mpm/agents/base_agent.json +8 -4
- claude_mpm/agents/frontmatter_validator.py +754 -0
- claude_mpm/agents/system_agent_config.py +222 -155
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/__init__.py +17 -13
- claude_mpm/agents/templates/circuit-breakers.md +1391 -0
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/git-file-tracking.md +584 -0
- claude_mpm/agents/templates/pm-examples.md +474 -0
- claude_mpm/agents/templates/pm-red-flags.md +310 -0
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/response-format.md +583 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/agents/templates/validation-templates.md +312 -0
- claude_mpm/cli/__init__.py +90 -128
- claude_mpm/cli/__main__.py +33 -0
- claude_mpm/cli/chrome_devtools_installer.py +175 -0
- claude_mpm/cli/commands/__init__.py +36 -12
- claude_mpm/cli/commands/agent_manager.py +1403 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +335 -0
- claude_mpm/cli/commands/agents.py +2503 -168
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/aggregate.py +540 -0
- claude_mpm/cli/commands/analyze.py +553 -0
- claude_mpm/cli/commands/analyze_code.py +528 -0
- claude_mpm/cli/commands/auto_configure.py +1053 -0
- claude_mpm/cli/commands/cleanup.py +588 -0
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
- claude_mpm/cli/commands/config.py +586 -0
- claude_mpm/cli/commands/configure.py +2654 -0
- claude_mpm/cli/commands/configure_agent_display.py +282 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +184 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/dashboard.py +286 -0
- claude_mpm/cli/commands/debug.py +1386 -0
- claude_mpm/cli/commands/doctor.py +243 -0
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/info.py +195 -74
- claude_mpm/cli/commands/local_deploy.py +534 -0
- claude_mpm/cli/commands/mcp.py +205 -0
- claude_mpm/cli/commands/mcp_command_router.py +161 -0
- claude_mpm/cli/commands/mcp_config.py +154 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_external_commands.py +249 -0
- claude_mpm/cli/commands/mcp_install_commands.py +346 -0
- claude_mpm/cli/commands/mcp_pipx_config.py +208 -0
- claude_mpm/cli/commands/mcp_server_commands.py +155 -0
- claude_mpm/cli/commands/mcp_setup_external.py +868 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +585 -846
- claude_mpm/cli/commands/monitor.py +228 -310
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +759 -0
- claude_mpm/cli/commands/mpm_init/display.py +341 -0
- claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +722 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +195 -0
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/run.py +910 -488
- claude_mpm/cli/commands/search.py +458 -0
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +1246 -0
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/commands/tickets.py +536 -53
- claude_mpm/cli/commands/uninstall.py +176 -0
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/commands/verify.py +119 -0
- claude_mpm/cli/executor.py +297 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +21 -0
- claude_mpm/cli/interactive/agent_wizard.py +1947 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parser.py +87 -563
- claude_mpm/cli/parsers/__init__.py +35 -0
- claude_mpm/cli/parsers/agent_manager_parser.py +393 -0
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +575 -0
- claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
- claude_mpm/cli/parsers/analyze_parser.py +135 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +120 -0
- claude_mpm/cli/parsers/base_parser.py +644 -0
- claude_mpm/cli/parsers/config_parser.py +208 -0
- claude_mpm/cli/parsers/configure_parser.py +138 -0
- claude_mpm/cli/parsers/dashboard_parser.py +113 -0
- claude_mpm/cli/parsers/debug_parser.py +319 -0
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mcp_parser.py +195 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +142 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
- claude_mpm/cli/parsers/profile_parser.py +147 -0
- claude_mpm/cli/parsers/run_parser.py +157 -0
- claude_mpm/cli/parsers/search_parser.py +245 -0
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +277 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/shared/__init__.py +40 -0
- claude_mpm/cli/shared/argument_patterns.py +205 -0
- claude_mpm/cli/shared/base_command.py +242 -0
- claude_mpm/cli/shared/error_handling.py +242 -0
- claude_mpm/cli/shared/output_formatters.py +241 -0
- claude_mpm/cli/startup.py +1743 -0
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/startup_logging.py +839 -0
- claude_mpm/cli/utils.py +136 -47
- claude_mpm/cli_module/__init__.py +6 -6
- claude_mpm/cli_module/args.py +188 -140
- claude_mpm/cli_module/commands.py +79 -70
- claude_mpm/cli_module/migration_example.py +42 -64
- claude_mpm/commands/__init__.py +14 -0
- claude_mpm/commands/mpm-config.md +28 -0
- claude_mpm/commands/mpm-doctor.md +20 -0
- claude_mpm/commands/mpm-help.md +20 -0
- claude_mpm/commands/mpm-init.md +120 -0
- claude_mpm/commands/mpm-monitor.md +31 -0
- claude_mpm/commands/mpm-organize.md +120 -0
- claude_mpm/commands/mpm-postmortem.md +21 -0
- claude_mpm/commands/mpm-session-resume.md +30 -0
- claude_mpm/commands/mpm-status.md +20 -0
- claude_mpm/commands/mpm-ticket-view.md +109 -0
- claude_mpm/commands/mpm-version.md +20 -0
- claude_mpm/commands/mpm.md +31 -0
- claude_mpm/config/__init__.py +42 -2
- claude_mpm/config/agent_config.py +402 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +352 -0
- claude_mpm/config/experimental_features.py +217 -0
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/config/paths.py +258 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/config/socketio_config.py +125 -83
- claude_mpm/constants.py +132 -22
- claude_mpm/core/__init__.py +62 -36
- claude_mpm/core/agent_name_normalizer.py +71 -73
- claude_mpm/core/agent_registry.py +385 -492
- claude_mpm/core/agent_session_manager.py +81 -70
- claude_mpm/core/api_validator.py +330 -0
- claude_mpm/core/base_service.py +159 -122
- claude_mpm/core/cache.py +560 -0
- claude_mpm/core/claude_runner.py +696 -916
- claude_mpm/core/config.py +613 -122
- claude_mpm/core/config_aliases.py +74 -73
- claude_mpm/core/config_constants.py +314 -0
- claude_mpm/core/constants.py +361 -0
- claude_mpm/core/container.py +646 -104
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/error_handler.py +623 -0
- claude_mpm/core/exceptions.py +536 -0
- claude_mpm/core/factories.py +105 -109
- claude_mpm/core/file_utils.py +764 -0
- claude_mpm/core/framework/__init__.py +25 -0
- claude_mpm/core/framework/formatters/__init__.py +11 -0
- claude_mpm/core/framework/formatters/capability_generator.py +367 -0
- claude_mpm/core/framework/formatters/content_formatter.py +278 -0
- claude_mpm/core/framework/formatters/context_generator.py +185 -0
- claude_mpm/core/framework/loaders/__init__.py +13 -0
- claude_mpm/core/framework/loaders/agent_loader.py +213 -0
- claude_mpm/core/framework/loaders/file_loader.py +176 -0
- claude_mpm/core/framework/loaders/instruction_loader.py +222 -0
- claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
- claude_mpm/core/framework/processors/__init__.py +11 -0
- claude_mpm/core/framework/processors/memory_processor.py +230 -0
- claude_mpm/core/framework/processors/metadata_processor.py +146 -0
- claude_mpm/core/framework/processors/template_processor.py +244 -0
- claude_mpm/core/framework_loader.py +485 -414
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +246 -86
- claude_mpm/core/hook_performance_config.py +147 -0
- claude_mpm/core/injectable_service.py +72 -63
- claude_mpm/core/instruction_reinforcement_hook.py +267 -0
- claude_mpm/core/interactive_session.py +670 -0
- claude_mpm/core/interfaces.py +570 -164
- claude_mpm/core/lazy.py +467 -0
- claude_mpm/core/log_manager.py +707 -0
- claude_mpm/core/logger.py +295 -134
- claude_mpm/core/logging_config.py +474 -0
- claude_mpm/core/logging_utils.py +520 -0
- claude_mpm/core/minimal_framework_loader.py +24 -22
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +594 -0
- claude_mpm/core/optimized_agent_loader.py +479 -0
- claude_mpm/core/optimized_startup.py +554 -0
- claude_mpm/core/output_style_manager.py +483 -0
- claude_mpm/core/pm_hook_interceptor.py +197 -82
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/service_registry.py +153 -116
- claude_mpm/core/session_manager.py +179 -64
- claude_mpm/core/shared/__init__.py +17 -0
- claude_mpm/core/shared/config_loader.py +326 -0
- claude_mpm/core/shared/path_resolver.py +281 -0
- claude_mpm/core/shared/singleton_manager.py +221 -0
- claude_mpm/core/socketio_pool.py +400 -137
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/tool_access_control.py +64 -57
- claude_mpm/core/types.py +307 -0
- claude_mpm/core/typing_utils.py +553 -0
- claude_mpm/core/unified_agent_registry.py +969 -0
- claude_mpm/core/unified_config.py +570 -0
- claude_mpm/core/unified_paths.py +941 -0
- claude_mpm/dashboard/__init__.py +12 -0
- claude_mpm/dashboard/api/simple_directory.py +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
- claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
- claude_mpm/dashboard/static/svelte-build/index.html +36 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/__init__.py +10 -0
- claude_mpm/experimental/cli_enhancements.py +104 -89
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +76 -66
- claude_mpm/hooks/__init__.py +37 -1
- claude_mpm/hooks/base_hook.py +37 -32
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/connection_pool.py +250 -0
- claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +888 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +652 -875
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -7
- claude_mpm/hooks/claude_hooks/installer.py +806 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +249 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +412 -0
- claude_mpm/hooks/claude_hooks/services/__init__.py +15 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +229 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +254 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +284 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +224 -0
- claude_mpm/hooks/failure_learning/__init__.py +54 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
- claude_mpm/hooks/instruction_reinforcement.py +301 -0
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +386 -0
- claude_mpm/hooks/kuzu_response_hook.py +179 -0
- claude_mpm/hooks/memory_integration_hook.py +201 -107
- claude_mpm/hooks/session_resume_hook.py +121 -0
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/hooks/tool_call_interceptor.py +92 -76
- claude_mpm/hooks/validation_hooks.py +62 -54
- claude_mpm/init.py +518 -83
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +40 -23
- claude_mpm/models/agent_session.py +538 -0
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/schemas/__init__.py +12 -0
- claude_mpm/scripts/__init__.py +15 -0
- claude_mpm/scripts/claude-hook-handler.sh +227 -0
- claude_mpm/scripts/launch_monitor.py +165 -0
- claude_mpm/scripts/mpm_doctor.py +322 -0
- claude_mpm/scripts/socketio_daemon.py +189 -200
- claude_mpm/scripts/start_activity_logging.py +91 -0
- claude_mpm/services/__init__.py +208 -39
- claude_mpm/services/agent_capabilities_service.py +266 -0
- claude_mpm/services/agents/__init__.py +89 -0
- claude_mpm/services/agents/agent_builder.py +514 -0
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/__init__.py +21 -0
- claude_mpm/services/agents/deployment/agent_config_provider.py +410 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +358 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +80 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +1037 -0
- claude_mpm/services/agents/deployment/agent_discovery_service.py +546 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +288 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +383 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +505 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +160 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +957 -0
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +273 -0
- claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
- claude_mpm/services/agents/deployment/agent_record_service.py +418 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +84 -0
- claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +1369 -0
- claude_mpm/services/agents/deployment/agent_validator.py +376 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +322 -0
- claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +10 -13
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +149 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +768 -0
- claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +181 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +178 -0
- claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +120 -0
- claude_mpm/services/agents/deployment/deployment_wrapper.py +129 -0
- claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
- claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +70 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +269 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +226 -0
- claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
- claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +362 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +1478 -0
- claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +162 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +240 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +110 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +80 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +92 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +101 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +102 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +269 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +311 -0
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +862 -0
- claude_mpm/services/agents/deployment/results/__init__.py +13 -0
- claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +113 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +148 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +131 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +130 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +228 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +21 -0
- claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +319 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +214 -0
- claude_mpm/services/agents/git_source_manager.py +682 -0
- claude_mpm/services/agents/loading/__init__.py +11 -0
- claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +306 -228
- claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +106 -91
- claude_mpm/services/agents/loading/framework_agent_loader.py +433 -0
- claude_mpm/services/agents/local_template_manager.py +784 -0
- claude_mpm/services/agents/management/__init__.py +9 -0
- claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +92 -69
- claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +219 -168
- claude_mpm/services/agents/memory/__init__.py +22 -0
- claude_mpm/services/agents/memory/agent_memory_manager.py +784 -0
- claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +20 -18
- claude_mpm/services/agents/memory/content_manager.py +470 -0
- claude_mpm/services/agents/memory/memory_categorization_service.py +167 -0
- claude_mpm/services/agents/memory/memory_file_service.py +129 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +101 -0
- claude_mpm/services/agents/memory/template_generator.py +83 -0
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +617 -0
- claude_mpm/services/agents/registry/__init__.py +30 -0
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +273 -0
- claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +370 -295
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1202 -0
- claude_mpm/services/agents/startup_sync.py +259 -0
- claude_mpm/services/agents/toolchain_detector.py +478 -0
- claude_mpm/services/analysis/__init__.py +35 -0
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/async_session_logger.py +665 -0
- claude_mpm/services/claude_session_logger.py +321 -0
- claude_mpm/services/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +408 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +590 -0
- claude_mpm/services/cli/memory_crud_service.py +622 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +604 -0
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +372 -0
- claude_mpm/services/cli/startup_checker.py +362 -0
- claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
- claude_mpm/services/command_deployment_service.py +446 -0
- claude_mpm/services/command_handler_service.py +221 -0
- claude_mpm/services/communication/__init__.py +22 -0
- claude_mpm/services/core/__init__.py +108 -0
- claude_mpm/services/core/base.py +269 -0
- claude_mpm/services/core/cache_manager.py +309 -0
- claude_mpm/services/core/interfaces/__init__.py +273 -0
- claude_mpm/services/core/interfaces/agent.py +514 -0
- claude_mpm/services/core/interfaces/communication.py +316 -0
- claude_mpm/services/core/interfaces/health.py +169 -0
- claude_mpm/services/core/interfaces/infrastructure.py +357 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/project.py +121 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/service.py +405 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/interfaces.py +81 -0
- claude_mpm/services/core/memory_manager.py +682 -0
- claude_mpm/services/core/models/__init__.py +70 -0
- claude_mpm/services/core/models/agent_config.py +384 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +239 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/models/toolchain.py +306 -0
- claude_mpm/services/core/path_resolver.py +517 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- claude_mpm/services/diagnostics/__init__.py +18 -0
- claude_mpm/services/diagnostics/checks/__init__.py +38 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +370 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/base_check.py +60 -0
- claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
- claude_mpm/services/diagnostics/checks/common_issues_check.py +363 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +306 -0
- claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +520 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +415 -0
- claude_mpm/services/diagnostics/checks/mcp_check.py +330 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
- claude_mpm/services/diagnostics/checks/monitor_check.py +281 -0
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/checks/startup_log_check.py +319 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +286 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +578 -0
- claude_mpm/services/diagnostics/models.py +138 -0
- claude_mpm/services/event_aggregator.py +582 -0
- claude_mpm/services/event_bus/__init__.py +18 -0
- claude_mpm/services/event_bus/config.py +186 -0
- claude_mpm/services/event_bus/direct_relay.py +312 -0
- claude_mpm/services/event_bus/event_bus.py +396 -0
- claude_mpm/services/event_bus/relay.py +326 -0
- claude_mpm/services/events/__init__.py +44 -0
- claude_mpm/services/events/consumers/__init__.py +18 -0
- claude_mpm/services/events/consumers/dead_letter.py +306 -0
- claude_mpm/services/events/consumers/logging.py +184 -0
- claude_mpm/services/events/consumers/metrics.py +241 -0
- claude_mpm/services/events/consumers/socketio.py +377 -0
- claude_mpm/services/events/core.py +480 -0
- claude_mpm/services/events/interfaces.py +214 -0
- claude_mpm/services/events/producers/__init__.py +14 -0
- claude_mpm/services/events/producers/hook.py +269 -0
- claude_mpm/services/events/producers/system.py +329 -0
- claude_mpm/services/exceptions.py +433 -353
- claude_mpm/services/framework_claude_md_generator/__init__.py +81 -80
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +74 -67
- claude_mpm/services/framework_claude_md_generator/content_validator.py +66 -62
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +82 -60
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +36 -37
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +41 -40
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +15 -15
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +26 -30
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +31 -30
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +579 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/hook_installer_service.py +506 -0
- claude_mpm/services/hook_service.py +159 -111
- claude_mpm/services/infrastructure/__init__.py +52 -0
- claude_mpm/services/infrastructure/context_preservation.py +569 -0
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +209 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +39 -0
- claude_mpm/services/infrastructure/monitoring/aggregator.py +432 -0
- claude_mpm/services/infrastructure/monitoring/base.py +122 -0
- claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
- claude_mpm/services/infrastructure/monitoring/network.py +219 -0
- claude_mpm/services/infrastructure/monitoring/process.py +343 -0
- claude_mpm/services/infrastructure/monitoring/resources.py +244 -0
- claude_mpm/services/infrastructure/monitoring/service.py +368 -0
- claude_mpm/services/infrastructure/monitoring.py +71 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +155 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +26 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +427 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +1542 -0
- claude_mpm/services/mcp_service_verifier.py +732 -0
- claude_mpm/services/memory/__init__.py +19 -0
- claude_mpm/services/{memory_builder.py → memory/builder.py} +465 -373
- claude_mpm/services/memory/cache/__init__.py +14 -0
- claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +237 -200
- claude_mpm/services/memory/cache/simple_cache.py +331 -0
- claude_mpm/services/memory/failure_tracker.py +578 -0
- claude_mpm/services/memory/indexed_memory.py +648 -0
- claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +272 -243
- claude_mpm/services/memory/router.py +951 -0
- claude_mpm/services/memory_hook_service.py +470 -0
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +452 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/__init__.py +20 -0
- claude_mpm/services/monitor/daemon.py +698 -0
- claude_mpm/services/monitor/daemon_manager.py +1076 -0
- claude_mpm/services/monitor/event_emitter.py +350 -0
- claude_mpm/services/monitor/handlers/__init__.py +21 -0
- claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
- claude_mpm/services/monitor/handlers/dashboard.py +299 -0
- claude_mpm/services/monitor/handlers/file.py +264 -0
- claude_mpm/services/monitor/handlers/hooks.py +512 -0
- claude_mpm/services/monitor/management/__init__.py +18 -0
- claude_mpm/services/monitor/management/health.py +124 -0
- claude_mpm/services/monitor/management/lifecycle.py +730 -0
- claude_mpm/services/monitor/server.py +1493 -0
- claude_mpm/services/monitor_build_service.py +349 -0
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/orphan_detection.py +786 -0
- claude_mpm/services/pm_skills_deployer.py +707 -0
- claude_mpm/services/port_manager.py +597 -0
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/project/__init__.py +44 -0
- claude_mpm/services/{project_analyzer.py → project/analyzer.py} +541 -291
- claude_mpm/services/project/analyzer_v2.py +566 -0
- claude_mpm/services/project/architecture_analyzer.py +461 -0
- claude_mpm/services/project/archive_manager.py +1045 -0
- claude_mpm/services/project/dependency_analyzer.py +462 -0
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/documentation_manager.py +554 -0
- claude_mpm/services/project/enhanced_analyzer.py +572 -0
- claude_mpm/services/project/language_analyzer.py +265 -0
- claude_mpm/services/project/metrics_collector.py +407 -0
- claude_mpm/services/project/project_organizer.py +1009 -0
- claude_mpm/services/project/registry.py +636 -0
- claude_mpm/services/project/toolchain_analyzer.py +583 -0
- claude_mpm/services/project_port_allocator.py +596 -0
- claude_mpm/services/recovery_manager.py +293 -240
- claude_mpm/services/response_tracker.py +267 -0
- claude_mpm/services/runner_configuration_service.py +605 -0
- claude_mpm/services/self_upgrade_service.py +608 -0
- claude_mpm/services/session_management_service.py +314 -0
- claude_mpm/services/session_manager.py +380 -0
- claude_mpm/services/shared/__init__.py +21 -0
- claude_mpm/services/shared/async_service_base.py +216 -0
- claude_mpm/services/shared/config_service_base.py +301 -0
- claude_mpm/services/shared/lifecycle_service_base.py +308 -0
- claude_mpm/services/shared/manager_base.py +315 -0
- claude_mpm/services/shared/service_factory.py +309 -0
- claude_mpm/services/skills/__init__.py +21 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1324 -0
- claude_mpm/services/skills/selective_skill_deployer.py +744 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +1168 -0
- claude_mpm/services/socketio/__init__.py +25 -0
- claude_mpm/services/socketio/client_proxy.py +229 -0
- claude_mpm/services/socketio/dashboard_server.py +362 -0
- claude_mpm/services/socketio/event_normalizer.py +798 -0
- claude_mpm/services/socketio/handlers/__init__.py +30 -0
- claude_mpm/services/socketio/handlers/base.py +136 -0
- claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
- claude_mpm/services/socketio/handlers/connection.py +643 -0
- claude_mpm/services/socketio/handlers/connection_handler.py +333 -0
- claude_mpm/services/socketio/handlers/file.py +263 -0
- claude_mpm/services/socketio/handlers/git.py +962 -0
- claude_mpm/services/socketio/handlers/hook.py +211 -0
- claude_mpm/services/socketio/handlers/memory.py +26 -0
- claude_mpm/services/socketio/handlers/project.py +24 -0
- claude_mpm/services/socketio/handlers/registry.py +214 -0
- claude_mpm/services/socketio/migration_utils.py +343 -0
- claude_mpm/services/socketio/monitor_client.py +364 -0
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +569 -0
- claude_mpm/services/socketio/server/connection_manager.py +579 -0
- claude_mpm/services/socketio/server/core.py +1079 -0
- claude_mpm/services/socketio/server/eventbus_integration.py +245 -0
- claude_mpm/services/socketio/server/main.py +501 -0
- claude_mpm/services/socketio_client_manager.py +173 -143
- claude_mpm/services/socketio_server.py +38 -1657
- claude_mpm/services/subprocess_launcher_service.py +322 -0
- claude_mpm/services/system_instructions_service.py +270 -0
- claude_mpm/services/ticket_manager.py +25 -209
- claude_mpm/services/ticket_services/__init__.py +26 -0
- claude_mpm/services/ticket_services/crud_service.py +328 -0
- claude_mpm/services/ticket_services/formatter_service.py +290 -0
- claude_mpm/services/ticket_services/search_service.py +324 -0
- claude_mpm/services/ticket_services/validation_service.py +303 -0
- claude_mpm/services/ticket_services/workflow_service.py +244 -0
- claude_mpm/services/unified/__init__.py +65 -0
- claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
- claude_mpm/services/unified/config_strategies/__init__.py +175 -0
- claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
- claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
- claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
- claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
- claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
- claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
- claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
- claude_mpm/services/unified/deployment_strategies/base.py +553 -0
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
- claude_mpm/services/unified/deployment_strategies/local.py +607 -0
- claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
- claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
- claude_mpm/services/unified/interfaces.py +475 -0
- claude_mpm/services/unified/migration.py +509 -0
- claude_mpm/services/unified/strategies.py +534 -0
- claude_mpm/services/unified/unified_analyzer.py +542 -0
- claude_mpm/services/unified/unified_config.py +691 -0
- claude_mpm/services/unified/unified_deployment.py +466 -0
- claude_mpm/services/utility_service.py +280 -0
- claude_mpm/services/version_control/__init__.py +34 -37
- claude_mpm/services/version_control/branch_strategy.py +26 -17
- claude_mpm/services/version_control/conflict_resolution.py +52 -36
- claude_mpm/services/version_control/git_operations.py +183 -49
- claude_mpm/services/version_control/semantic_versioning.py +172 -61
- claude_mpm/services/version_control/version_parser.py +546 -0
- claude_mpm/services/version_service.py +379 -0
- claude_mpm/services/visualization/__init__.py +15 -0
- claude_mpm/services/visualization/mermaid_generator.py +937 -0
- claude_mpm/skills/__init__.py +42 -0
- claude_mpm/skills/agent_skills_injector.py +324 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +573 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +439 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +405 -0
- claude_mpm/skills/skills_registry.py +347 -0
- claude_mpm/skills/skills_service.py +739 -0
- claude_mpm/storage/__init__.py +9 -0
- claude_mpm/storage/state_storage.py +546 -0
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/tools/__init__.py +10 -0
- claude_mpm/tools/__main__.py +208 -0
- claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
- claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
- claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
- claude_mpm/tools/code_tree_analyzer/core.py +380 -0
- claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
- claude_mpm/tools/code_tree_analyzer/events.py +168 -0
- claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
- claude_mpm/tools/code_tree_analyzer/models.py +39 -0
- claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
- claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
- claude_mpm/tools/code_tree_builder.py +631 -0
- claude_mpm/tools/code_tree_events.py +420 -0
- claude_mpm/tools/socketio_debug.py +671 -0
- claude_mpm/utils/__init__.py +8 -8
- claude_mpm/utils/agent_dependency_loader.py +1090 -0
- claude_mpm/utils/agent_filters.py +261 -0
- claude_mpm/utils/common.py +544 -0
- claude_mpm/utils/config_manager.py +168 -126
- claude_mpm/utils/console.py +11 -0
- claude_mpm/utils/database_connector.py +298 -0
- claude_mpm/utils/dependency_cache.py +373 -0
- claude_mpm/utils/dependency_manager.py +60 -59
- claude_mpm/utils/dependency_strategies.py +381 -0
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/environment_context.py +313 -0
- claude_mpm/utils/error_handler.py +78 -66
- claude_mpm/utils/file_utils.py +305 -0
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/gitignore.py +244 -0
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/log_cleanup.py +627 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/path_operations.py +110 -104
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +823 -0
- claude_mpm/utils/session_logging.py +121 -0
- claude_mpm/utils/structured_questions.py +619 -0
- claude_mpm/utils/subprocess_utils.py +343 -0
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +214 -108
- claude_mpm/validation/frontmatter_validator.py +252 -0
- claude_mpm-5.4.55.dist-info/METADATA +999 -0
- claude_mpm-5.4.55.dist-info/RECORD +868 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/entry_points.txt +1 -3
- claude_mpm-5.4.55.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.55.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -88
- claude_mpm/agents/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/base_agent_loader.py +0 -529
- claude_mpm/agents/schema/agent_schema.json +0 -314
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/data_engineer.json +0 -110
- claude_mpm/agents/templates/documentation.json +0 -109
- claude_mpm/agents/templates/engineer.json +0 -113
- claude_mpm/agents/templates/ops.json +0 -109
- claude_mpm/agents/templates/pm.json +0 -25
- claude_mpm/agents/templates/qa.json +0 -111
- claude_mpm/agents/templates/research.json +0 -65
- claude_mpm/agents/templates/security.json +0 -113
- claude_mpm/agents/templates/test_integration.json +0 -112
- claude_mpm/agents/templates/version_control.json +0 -107
- claude_mpm/cli/commands/ui.py +0 -57
- claude_mpm/core/simple_runner.py +0 -1046
- claude_mpm/dashboard/open_dashboard.py +0 -34
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/builtin/__init__.py +0 -1
- claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
- claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
- claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
- claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
- claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
- claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
- claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
- claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
- claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
- claude_mpm/orchestration/__init__.py +0 -6
- claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
- claude_mpm/orchestration/archive/factory.py +0 -215
- claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
- claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
- claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
- claude_mpm/orchestration/archive/orchestrator.py +0 -501
- claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
- claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
- claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
- claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
- claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
- claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
- claude_mpm/schemas/workflow_validator.py +0 -411
- claude_mpm/services/agent_deployment.py +0 -1534
- claude_mpm/services/agent_lifecycle_manager.py +0 -1169
- claude_mpm/services/agent_memory_manager.py +0 -1415
- claude_mpm/services/agent_registry.py +0 -676
- claude_mpm/services/deployed_agent_discovery.py +0 -226
- claude_mpm/services/framework_agent_loader.py +0 -337
- claude_mpm/services/framework_claude_md_generator.py +0 -621
- claude_mpm/services/health_monitor.py +0 -892
- claude_mpm/services/memory_router.py +0 -538
- claude_mpm/services/parent_directory_manager/__init__.py +0 -577
- claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
- claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
- claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
- claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
- claude_mpm/services/parent_directory_manager/operations.py +0 -186
- claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
- claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
- claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
- claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
- claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
- claude_mpm/services/standalone_socketio_server.py +0 -1300
- claude_mpm/services/ticket_manager_di.py +0 -318
- claude_mpm/services/ticketing_service_original.py +0 -508
- claude_mpm/ui/__init__.py +0 -1
- claude_mpm/ui/rich_terminal_ui.py +0 -295
- claude_mpm/ui/terminal_ui.py +0 -328
- claude_mpm/utils/paths.py +0 -289
- claude_mpm-3.4.10.dist-info/METADATA +0 -183
- claude_mpm-3.4.10.dist-info/RECORD +0 -201
- claude_mpm-3.4.10.dist-info/licenses/LICENSE +0 -21
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/WHEEL +0 -0
- {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
|