claude-mpm 5.0.9__py3-none-any.whl → 5.4.41__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.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (263) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +4 -0
  3. claude_mpm/agents/BASE_AGENT.md +164 -0
  4. claude_mpm/agents/{PM_INSTRUCTIONS_TEACH.md → CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md} +721 -41
  5. claude_mpm/agents/MEMORY.md +1 -1
  6. claude_mpm/agents/PM_INSTRUCTIONS.md +468 -468
  7. claude_mpm/agents/WORKFLOW.md +5 -254
  8. claude_mpm/agents/agent_loader.py +13 -44
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/frontmatter_validator.py +70 -2
  11. claude_mpm/agents/templates/circuit-breakers.md +431 -45
  12. claude_mpm/cli/__init__.py +0 -1
  13. claude_mpm/cli/__main__.py +4 -0
  14. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  15. claude_mpm/cli/commands/agent_state_manager.py +18 -27
  16. claude_mpm/cli/commands/agents.py +175 -37
  17. claude_mpm/cli/commands/auto_configure.py +723 -236
  18. claude_mpm/cli/commands/config.py +88 -2
  19. claude_mpm/cli/commands/configure.py +1262 -157
  20. claude_mpm/cli/commands/configure_agent_display.py +25 -6
  21. claude_mpm/cli/commands/mpm_init/core.py +225 -46
  22. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  23. claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
  24. claude_mpm/cli/commands/postmortem.py +1 -1
  25. claude_mpm/cli/commands/profile.py +277 -0
  26. claude_mpm/cli/commands/skills.py +214 -189
  27. claude_mpm/cli/commands/summarize.py +413 -0
  28. claude_mpm/cli/executor.py +21 -3
  29. claude_mpm/cli/interactive/agent_wizard.py +85 -10
  30. claude_mpm/cli/parsers/agents_parser.py +54 -9
  31. claude_mpm/cli/parsers/auto_configure_parser.py +13 -138
  32. claude_mpm/cli/parsers/base_parser.py +12 -0
  33. claude_mpm/cli/parsers/config_parser.py +153 -83
  34. claude_mpm/cli/parsers/profile_parser.py +148 -0
  35. claude_mpm/cli/parsers/skills_parser.py +3 -2
  36. claude_mpm/cli/startup.py +879 -149
  37. claude_mpm/commands/mpm-config.md +28 -0
  38. claude_mpm/commands/mpm-doctor.md +9 -22
  39. claude_mpm/commands/mpm-help.md +5 -287
  40. claude_mpm/commands/mpm-init.md +81 -507
  41. claude_mpm/commands/mpm-monitor.md +15 -402
  42. claude_mpm/commands/mpm-organize.md +120 -0
  43. claude_mpm/commands/mpm-postmortem.md +6 -108
  44. claude_mpm/commands/mpm-session-resume.md +12 -363
  45. claude_mpm/commands/mpm-status.md +5 -69
  46. claude_mpm/commands/mpm-ticket-view.md +52 -495
  47. claude_mpm/commands/mpm-version.md +5 -107
  48. claude_mpm/config/agent_sources.py +27 -0
  49. claude_mpm/core/config.py +2 -4
  50. claude_mpm/core/framework/formatters/content_formatter.py +3 -13
  51. claude_mpm/core/framework/loaders/agent_loader.py +8 -5
  52. claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
  53. claude_mpm/core/framework_loader.py +4 -2
  54. claude_mpm/core/logger.py +13 -0
  55. claude_mpm/core/optimized_startup.py +59 -0
  56. claude_mpm/core/output_style_manager.py +173 -43
  57. claude_mpm/core/shared/config_loader.py +1 -1
  58. claude_mpm/core/socketio_pool.py +3 -3
  59. claude_mpm/core/unified_agent_registry.py +134 -16
  60. claude_mpm/core/unified_config.py +22 -0
  61. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  62. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +1 -0
  63. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +1 -0
  64. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +1 -0
  65. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +1 -0
  66. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +1 -0
  67. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +2 -0
  68. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DjhvlsAc.js +1 -0
  69. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/N4qtv3Hx.js +2 -0
  70. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uj46x2Wr.js +1 -0
  71. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +2 -0
  72. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +1 -0
  73. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.CAGBuiOw.js +1 -0
  74. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +1 -0
  75. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +10 -0
  76. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  77. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  78. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  79. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  80. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  81. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  82. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  83. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  84. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  85. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  86. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  87. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  88. claude_mpm/hooks/claude_hooks/event_handlers.py +211 -78
  89. claude_mpm/hooks/claude_hooks/hook_handler.py +155 -1
  90. claude_mpm/hooks/claude_hooks/installer.py +33 -10
  91. claude_mpm/hooks/claude_hooks/memory_integration.py +28 -0
  92. claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
  93. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  94. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  95. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  96. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  97. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  98. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  99. claude_mpm/hooks/claude_hooks/services/connection_manager.py +30 -6
  100. claude_mpm/hooks/memory_integration_hook.py +46 -1
  101. claude_mpm/init.py +63 -19
  102. claude_mpm/models/agent_definition.py +7 -0
  103. claude_mpm/models/git_repository.py +3 -3
  104. claude_mpm/scripts/claude-hook-handler.sh +58 -18
  105. claude_mpm/scripts/launch_monitor.py +93 -13
  106. claude_mpm/scripts/start_activity_logging.py +0 -0
  107. claude_mpm/services/agents/agent_builder.py +3 -3
  108. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  109. claude_mpm/services/agents/agent_review_service.py +280 -0
  110. claude_mpm/services/agents/cache_git_manager.py +6 -6
  111. claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
  112. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -5
  113. claude_mpm/services/agents/deployment/agent_template_builder.py +5 -3
  114. claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
  115. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +320 -29
  116. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +546 -68
  117. claude_mpm/services/agents/git_source_manager.py +36 -2
  118. claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
  119. claude_mpm/services/agents/recommender.py +5 -3
  120. claude_mpm/services/agents/single_tier_deployment_service.py +2 -2
  121. claude_mpm/services/agents/sources/git_source_sync_service.py +13 -6
  122. claude_mpm/services/agents/startup_sync.py +22 -2
  123. claude_mpm/services/agents/toolchain_detector.py +10 -6
  124. claude_mpm/services/analysis/__init__.py +11 -1
  125. claude_mpm/services/analysis/clone_detector.py +1030 -0
  126. claude_mpm/services/command_deployment_service.py +81 -10
  127. claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
  128. claude_mpm/services/diagnostics/checks/agent_sources_check.py +1 -1
  129. claude_mpm/services/event_bus/config.py +3 -1
  130. claude_mpm/services/git/git_operations_service.py +101 -16
  131. claude_mpm/services/monitor/daemon.py +9 -2
  132. claude_mpm/services/monitor/daemon_manager.py +39 -3
  133. claude_mpm/services/monitor/management/lifecycle.py +8 -1
  134. claude_mpm/services/monitor/server.py +698 -22
  135. claude_mpm/services/pm_skills_deployer.py +676 -0
  136. claude_mpm/services/profile_manager.py +331 -0
  137. claude_mpm/services/project/project_organizer.py +4 -0
  138. claude_mpm/services/self_upgrade_service.py +120 -12
  139. claude_mpm/services/skills/__init__.py +3 -0
  140. claude_mpm/services/skills/git_skill_source_manager.py +130 -2
  141. claude_mpm/services/skills/selective_skill_deployer.py +704 -0
  142. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  143. claude_mpm/services/skills_deployer.py +126 -9
  144. claude_mpm/services/socketio/dashboard_server.py +1 -0
  145. claude_mpm/services/socketio/event_normalizer.py +51 -6
  146. claude_mpm/services/socketio/server/core.py +386 -108
  147. claude_mpm/services/version_control/git_operations.py +103 -0
  148. claude_mpm/skills/skill_manager.py +92 -3
  149. claude_mpm/utils/agent_dependency_loader.py +14 -2
  150. claude_mpm/utils/agent_filters.py +17 -44
  151. claude_mpm/utils/gitignore.py +3 -0
  152. claude_mpm/utils/migration.py +4 -4
  153. claude_mpm/utils/robust_installer.py +47 -3
  154. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/METADATA +57 -87
  155. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/RECORD +160 -211
  156. claude_mpm-5.4.41.dist-info/entry_points.txt +5 -0
  157. claude_mpm-5.4.41.dist-info/licenses/LICENSE +94 -0
  158. claude_mpm-5.4.41.dist-info/licenses/LICENSE-FAQ.md +153 -0
  159. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
  160. claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
  161. claude_mpm/agents/BASE_OPS.md +0 -219
  162. claude_mpm/agents/BASE_PM.md +0 -480
  163. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
  164. claude_mpm/agents/BASE_QA.md +0 -167
  165. claude_mpm/agents/BASE_RESEARCH.md +0 -53
  166. claude_mpm/agents/base_agent_loader.py +0 -601
  167. claude_mpm/cli/commands/agents_detect.py +0 -380
  168. claude_mpm/cli/commands/agents_recommend.py +0 -309
  169. claude_mpm/cli/ticket_cli.py +0 -35
  170. claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
  171. claude_mpm/commands/mpm-agents-detect.md +0 -177
  172. claude_mpm/commands/mpm-agents-list.md +0 -131
  173. claude_mpm/commands/mpm-agents-recommend.md +0 -223
  174. claude_mpm/commands/mpm-config-view.md +0 -150
  175. claude_mpm/commands/mpm-ticket-organize.md +0 -304
  176. claude_mpm/dashboard/analysis_runner.py +0 -455
  177. claude_mpm/dashboard/index.html +0 -13
  178. claude_mpm/dashboard/open_dashboard.py +0 -66
  179. claude_mpm/dashboard/static/css/activity.css +0 -1958
  180. claude_mpm/dashboard/static/css/connection-status.css +0 -370
  181. claude_mpm/dashboard/static/css/dashboard.css +0 -4701
  182. claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
  183. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
  184. claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
  185. claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
  186. claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
  187. claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
  188. claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
  189. claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
  190. claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
  191. claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
  192. claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
  193. claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
  194. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
  195. claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
  196. claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
  197. claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
  198. claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
  199. claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
  200. claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
  201. claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
  202. claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
  203. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
  204. claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
  205. claude_mpm/dashboard/static/js/connection-manager.js +0 -536
  206. claude_mpm/dashboard/static/js/dashboard.js +0 -1914
  207. claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
  208. claude_mpm/dashboard/static/js/socket-client.js +0 -1474
  209. claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
  210. claude_mpm/dashboard/static/socket.io.min.js +0 -7
  211. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
  212. claude_mpm/dashboard/templates/code_simple.html +0 -153
  213. claude_mpm/dashboard/templates/index.html +0 -606
  214. claude_mpm/dashboard/test_dashboard.html +0 -372
  215. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  216. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  217. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  218. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  219. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  220. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  221. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  222. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  223. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  224. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  225. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  226. claude_mpm/scripts/mcp_server.py +0 -75
  227. claude_mpm/scripts/mcp_wrapper.py +0 -39
  228. claude_mpm/services/mcp_gateway/__init__.py +0 -159
  229. claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
  230. claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
  231. claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
  232. claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
  233. claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
  234. claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
  235. claude_mpm/services/mcp_gateway/core/base.py +0 -312
  236. claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
  237. claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
  238. claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
  239. claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
  240. claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
  241. claude_mpm/services/mcp_gateway/main.py +0 -589
  242. claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
  243. claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
  244. claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
  245. claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
  246. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
  247. claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
  248. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
  249. claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
  250. claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
  251. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
  252. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
  253. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
  254. claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
  255. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
  256. claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
  257. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
  258. claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
  259. claude_mpm-5.0.9.dist-info/entry_points.txt +0 -10
  260. claude_mpm-5.0.9.dist-info/licenses/LICENSE +0 -21
  261. /claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +0 -0
  262. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/WHEEL +0 -0
  263. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/top_level.txt +0 -0
@@ -1,456 +0,0 @@
1
- """
2
- Health Check Tool for MCP Gateway
3
- =================================
4
-
5
- Provides comprehensive health checking and diagnostic capabilities for the
6
- MCP Gateway and claude-mpm system.
7
-
8
- WHY: A dedicated health check tool provides centralized diagnostics for
9
- troubleshooting and system monitoring, essential for maintaining a reliable
10
- MCP gateway service.
11
-
12
- DESIGN DECISIONS:
13
- - Comprehensive system checks (gateway, tools, configuration)
14
- - Structured output for easy parsing
15
- - Non-blocking checks with timeouts
16
- - Detailed error reporting for troubleshooting
17
- """
18
-
19
- import asyncio
20
- import os
21
- import platform
22
- import sys
23
- from datetime import datetime, timezone
24
- from typing import Any, Dict
25
-
26
- import psutil
27
-
28
- from claude_mpm.config.paths import paths
29
- from claude_mpm.core.enums import HealthStatus, OperationResult, ServiceState
30
- from claude_mpm.core.logger import get_logger
31
- from claude_mpm.services.mcp_gateway.core.interfaces import (
32
- MCPToolDefinition,
33
- MCPToolInvocation,
34
- MCPToolResult,
35
- )
36
- from claude_mpm.services.mcp_gateway.tools.base_adapter import BaseToolAdapter
37
-
38
-
39
- class HealthCheckTool(BaseToolAdapter):
40
- """
41
- Comprehensive health check tool for MCP Gateway diagnostics.
42
-
43
- Provides system health, gateway status, tool availability, and
44
- configuration validation checks.
45
- """
46
-
47
- def __init__(self):
48
- """Initialize the health check tool."""
49
- definition = MCPToolDefinition(
50
- name="health_check",
51
- description="Comprehensive health check and diagnostics for MCP Gateway and claude-mpm system",
52
- input_schema={
53
- "type": "object",
54
- "properties": {
55
- "check_type": {
56
- "type": "string",
57
- "enum": ["all", "system", "gateway", "tools", "config"],
58
- "description": "Type of health check to perform",
59
- "default": "all",
60
- },
61
- "detailed": {
62
- "type": "boolean",
63
- "description": "Include detailed diagnostic information",
64
- "default": False,
65
- },
66
- "timeout": {
67
- "type": "integer",
68
- "description": "Timeout for checks in seconds",
69
- "default": 30,
70
- "minimum": 5,
71
- "maximum": 120,
72
- },
73
- },
74
- "required": [],
75
- },
76
- )
77
- super().__init__(definition)
78
- self.logger = get_logger("HealthCheckTool")
79
-
80
- async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
81
- """
82
- Perform health checks based on the requested type.
83
-
84
- Args:
85
- invocation: Tool invocation request
86
-
87
- Returns:
88
- Tool execution result with health check results
89
- """
90
- start_time = datetime.now(timezone.utc)
91
-
92
- try:
93
- # Get parameters
94
- check_type = invocation.parameters.get("check_type", "all")
95
- detailed = invocation.parameters.get("detailed", False)
96
- timeout = invocation.parameters.get("timeout", 30)
97
-
98
- # Perform health checks
99
- results = await self._perform_health_checks(check_type, detailed, timeout)
100
-
101
- # Calculate execution time
102
- execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
103
-
104
- # Update metrics
105
- self._update_metrics(True, execution_time)
106
-
107
- return MCPToolResult(
108
- success=True,
109
- data=results,
110
- execution_time=execution_time,
111
- metadata={
112
- "tool": "health_check",
113
- "check_type": check_type,
114
- "detailed": detailed,
115
- },
116
- )
117
-
118
- except Exception as e:
119
- execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
120
- self._update_metrics(False, execution_time)
121
-
122
- return MCPToolResult(
123
- success=False,
124
- error=f"Health check failed: {e!s}",
125
- execution_time=execution_time,
126
- metadata={"tool": "health_check", "error": str(e)},
127
- )
128
-
129
- async def _perform_health_checks(
130
- self, check_type: str, detailed: bool, timeout: int
131
- ) -> Dict[str, Any]:
132
- """Perform the requested health checks."""
133
- results = {
134
- "timestamp": datetime.now(timezone.utc).isoformat(),
135
- "check_type": check_type,
136
- "detailed": detailed,
137
- "overall_status": "unknown",
138
- "checks": {},
139
- "summary": {},
140
- }
141
-
142
- # Determine which checks to run
143
- checks_to_run = []
144
- if check_type == "all":
145
- checks_to_run = ["system", "gateway", "tools", "config"]
146
- else:
147
- checks_to_run = [check_type]
148
-
149
- # Run checks with timeout
150
- try:
151
- check_tasks = []
152
- for check in checks_to_run:
153
- if check == "system":
154
- check_tasks.append(self._check_system_health(detailed))
155
- elif check == "gateway":
156
- check_tasks.append(self._check_gateway_health(detailed))
157
- elif check == "tools":
158
- check_tasks.append(self._check_tools_health(detailed))
159
- elif check == "config":
160
- check_tasks.append(self._check_config_health(detailed))
161
-
162
- # Run all checks concurrently with timeout
163
- check_results = await asyncio.wait_for(
164
- asyncio.gather(*check_tasks, return_exceptions=True), timeout=timeout
165
- )
166
-
167
- # Process results
168
- for i, check_name in enumerate(checks_to_run):
169
- if i < len(check_results):
170
- if isinstance(check_results[i], Exception):
171
- results["checks"][check_name] = {
172
- "status": OperationResult.ERROR,
173
- "error": str(check_results[i]),
174
- }
175
- else:
176
- results["checks"][check_name] = check_results[i]
177
- else:
178
- results["checks"][check_name] = {
179
- "status": OperationResult.TIMEOUT,
180
- "error": "Check timed out",
181
- }
182
-
183
- except asyncio.TimeoutError:
184
- results["checks"]["timeout"] = {
185
- "status": OperationResult.ERROR,
186
- "error": f"Health checks timed out after {timeout} seconds",
187
- }
188
-
189
- # Calculate overall status and summary
190
- results["overall_status"] = self._calculate_overall_status(results["checks"])
191
- results["summary"] = self._generate_summary(results["checks"])
192
-
193
- return results
194
-
195
- async def _check_system_health(self, detailed: bool) -> Dict[str, Any]:
196
- """Check system health (CPU, memory, disk, etc.)."""
197
- check_result = {
198
- "status": ServiceState.RUNNING,
199
- "checks": {},
200
- "warnings": [],
201
- "errors": [],
202
- }
203
-
204
- try:
205
- # Basic system info
206
- check_result["checks"]["platform"] = {
207
- "system": platform.system(),
208
- "release": platform.release(),
209
- "python_version": sys.version,
210
- }
211
-
212
- # Memory check
213
- memory = psutil.virtual_memory()
214
- memory_usage = memory.percent
215
- check_result["checks"]["memory"] = {
216
- "usage_percent": memory_usage,
217
- "available_gb": round(memory.available / (1024**3), 2),
218
- "total_gb": round(memory.total / (1024**3), 2),
219
- }
220
-
221
- if memory_usage > 90:
222
- check_result["errors"].append("High memory usage detected")
223
- check_result["status"] = HealthStatus.UNHEALTHY
224
- elif memory_usage > 80:
225
- check_result["warnings"].append("Elevated memory usage")
226
-
227
- # CPU check
228
- cpu_usage = psutil.cpu_percent(interval=1)
229
- check_result["checks"]["cpu"] = {
230
- "usage_percent": cpu_usage,
231
- "count": psutil.cpu_count(),
232
- }
233
-
234
- if cpu_usage > 95:
235
- check_result["errors"].append("High CPU usage detected")
236
- check_result["status"] = HealthStatus.UNHEALTHY
237
- elif cpu_usage > 80:
238
- check_result["warnings"].append("Elevated CPU usage")
239
-
240
- # Disk check for claude-mpm data directory
241
- if paths.data_dir.exists():
242
- disk_usage = psutil.disk_usage(str(paths.data_dir))
243
- disk_usage_percent = (disk_usage.used / disk_usage.total) * 100
244
- check_result["checks"]["disk"] = {
245
- "usage_percent": round(disk_usage_percent, 2),
246
- "free_gb": round(disk_usage.free / (1024**3), 2),
247
- "total_gb": round(disk_usage.total / (1024**3), 2),
248
- }
249
-
250
- if disk_usage_percent > 95:
251
- check_result["errors"].append("Disk space critically low")
252
- check_result["status"] = HealthStatus.UNHEALTHY
253
- elif disk_usage_percent > 85:
254
- check_result["warnings"].append("Disk space running low")
255
-
256
- # Process check
257
- current_process = psutil.Process()
258
- check_result["checks"]["process"] = {
259
- "pid": current_process.pid,
260
- "memory_mb": round(current_process.memory_info().rss / (1024**2), 2),
261
- "cpu_percent": current_process.cpu_percent(),
262
- "threads": current_process.num_threads(),
263
- }
264
-
265
- except Exception as e:
266
- check_result["status"] = HealthStatus.UNHEALTHY
267
- check_result["errors"].append(f"System health check failed: {e}")
268
-
269
- return check_result
270
-
271
- async def _check_gateway_health(self, detailed: bool) -> Dict[str, Any]:
272
- """Check MCP Gateway health."""
273
- check_result = {
274
- "status": ServiceState.RUNNING,
275
- "checks": {},
276
- "warnings": [],
277
- "errors": [],
278
- }
279
-
280
- try:
281
- # Check singleton manager
282
- from ..core.singleton_manager import get_gateway_manager, is_gateway_running
283
-
284
- manager = get_gateway_manager()
285
- check_result["checks"]["singleton_manager"] = {
286
- "available": True,
287
- "gateway_running": is_gateway_running(),
288
- }
289
-
290
- # Check gateway instance info
291
- instance_info = manager.get_running_instance_info()
292
- if instance_info:
293
- check_result["checks"]["instance"] = instance_info
294
- else:
295
- check_result["warnings"].append("No gateway instance currently running")
296
-
297
- # Check MCP directories
298
- mcp_dir = paths.data_dir / "mcp"
299
- check_result["checks"]["directories"] = {
300
- "mcp_dir_exists": mcp_dir.exists(),
301
- "mcp_dir_writable": mcp_dir.exists() and os.access(mcp_dir, os.W_OK),
302
- }
303
-
304
- if not mcp_dir.exists():
305
- check_result["errors"].append("MCP directory does not exist")
306
- check_result["status"] = HealthStatus.UNHEALTHY
307
-
308
- except Exception as e:
309
- check_result["status"] = HealthStatus.UNHEALTHY
310
- check_result["errors"].append(f"Gateway health check failed: {e}")
311
-
312
- return check_result
313
-
314
- async def _check_tools_health(self, detailed: bool) -> Dict[str, Any]:
315
- """Check MCP tools health."""
316
- check_result = {
317
- "status": ServiceState.RUNNING,
318
- "checks": {},
319
- "warnings": [],
320
- "errors": [],
321
- }
322
-
323
- try:
324
- # Try to import and check tool registry
325
- from ..registry.tool_registry import ToolRegistry
326
-
327
- registry = ToolRegistry()
328
- await registry.initialize()
329
-
330
- # Get tool list
331
- tools = registry.list_tools()
332
- check_result["checks"]["tool_count"] = len(tools)
333
- check_result["checks"]["tools"] = [tool.name for tool in tools]
334
-
335
- # Check essential tools
336
- essential_tools = ["echo", "calculator", "system_info"]
337
- available_essential = []
338
- missing_essential = []
339
-
340
- for tool_name in essential_tools:
341
- if registry.get_tool(tool_name):
342
- available_essential.append(tool_name)
343
- else:
344
- missing_essential.append(tool_name)
345
-
346
- check_result["checks"]["essential_tools"] = {
347
- "available": available_essential,
348
- "missing": missing_essential,
349
- }
350
-
351
- if missing_essential:
352
- check_result["warnings"].append(
353
- f"Missing essential tools: {missing_essential}"
354
- )
355
-
356
- if len(available_essential) == 0:
357
- check_result["status"] = HealthStatus.UNHEALTHY
358
- check_result["errors"].append("No essential tools available")
359
-
360
- except Exception as e:
361
- check_result["status"] = HealthStatus.UNHEALTHY
362
- check_result["errors"].append(f"Tools health check failed: {e}")
363
-
364
- return check_result
365
-
366
- async def _check_config_health(self, detailed: bool) -> Dict[str, Any]:
367
- """Check configuration health."""
368
- check_result = {
369
- "status": ServiceState.RUNNING,
370
- "checks": {},
371
- "warnings": [],
372
- "errors": [],
373
- }
374
-
375
- try:
376
- # Check configuration files
377
- config_dir = paths.data_dir / "mcp"
378
- config_file = config_dir / "gateway_config.json"
379
-
380
- check_result["checks"]["config_dir"] = config_dir.exists()
381
- check_result["checks"]["config_file"] = config_file.exists()
382
-
383
- if config_file.exists():
384
- # Try to load configuration
385
- import json
386
-
387
- with config_file.open() as f:
388
- config_data = json.load(f)
389
-
390
- check_result["checks"]["config_valid"] = True
391
- if detailed:
392
- check_result["checks"]["config_content"] = config_data
393
- else:
394
- check_result["warnings"].append("Gateway configuration file not found")
395
-
396
- # Check paths
397
- check_result["checks"]["paths"] = {
398
- "data_dir": str(paths.data_dir),
399
- "logs_dir": str(paths.logs_dir),
400
- "data_dir_exists": paths.data_dir.exists(),
401
- "logs_dir_exists": paths.logs_dir.exists(),
402
- }
403
-
404
- except Exception as e:
405
- check_result["status"] = HealthStatus.UNHEALTHY
406
- check_result["errors"].append(f"Config health check failed: {e}")
407
-
408
- return check_result
409
-
410
- def _calculate_overall_status(self, checks: Dict[str, Any]) -> str:
411
- """Calculate overall health status from individual checks."""
412
- if not checks:
413
- return "unknown"
414
-
415
- statuses = [check.get("status", "unknown") for check in checks.values()]
416
-
417
- # Check for unhealthy (handle both string and enum)
418
- if HealthStatus.UNHEALTHY in statuses or "unhealthy" in statuses:
419
- return "unhealthy"
420
- if "warning" in statuses:
421
- return "warning"
422
- # Check for healthy (handle both string and enum)
423
- if all(status in (HealthStatus.HEALTHY, "healthy") for status in statuses):
424
- return "healthy"
425
- return "unknown"
426
-
427
- def _generate_summary(self, checks: Dict[str, Any]) -> Dict[str, Any]:
428
- """Generate a summary of health check results."""
429
- summary = {
430
- "total_checks": len(checks),
431
- "healthy": 0,
432
- "warnings": 0,
433
- "errors": 0,
434
- "issues": [],
435
- }
436
-
437
- for check_name, check_result in checks.items():
438
- status = check_result.get("status", "unknown")
439
-
440
- # Check for healthy (handle both string and enum)
441
- if status in (HealthStatus.HEALTHY, "healthy"):
442
- summary["healthy"] += 1
443
- elif status in ["warning", HealthStatus.UNHEALTHY, "unhealthy"]:
444
- summary["warnings"] += 1
445
- # Collect warning messages
446
- warnings = check_result.get("warnings", [])
447
- for warning in warnings:
448
- summary["issues"].append(f"{check_name}: {warning}")
449
- # Collect error messages if status is unhealthy
450
- if status in (HealthStatus.UNHEALTHY, "unhealthy"):
451
- summary["errors"] += 1
452
- errors = check_result.get("errors", [])
453
- for error in errors:
454
- summary["issues"].append(f"{check_name}: {error}")
455
-
456
- return summary