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,43 +0,0 @@
1
- """
2
- MCP Gateway Core Module
3
- =======================
4
-
5
- Core interfaces and base classes for the MCP Gateway service.
6
- """
7
-
8
- from .base import BaseMCPService
9
- from .exceptions import (
10
- MCPCommunicationError,
11
- MCPConfigurationError,
12
- MCPException,
13
- MCPServerError,
14
- MCPToolNotFoundError,
15
- MCPValidationError,
16
- )
17
- from .interfaces import (
18
- IMCPCommunication,
19
- IMCPConfiguration,
20
- IMCPGateway,
21
- IMCPLifecycle,
22
- IMCPToolAdapter,
23
- IMCPToolRegistry,
24
- )
25
-
26
- __all__ = [
27
- # Base classes
28
- "BaseMCPService",
29
- "IMCPCommunication",
30
- "IMCPConfiguration",
31
- # Interfaces
32
- "IMCPGateway",
33
- "IMCPLifecycle",
34
- "IMCPToolAdapter",
35
- "IMCPToolRegistry",
36
- "MCPCommunicationError",
37
- "MCPConfigurationError",
38
- # Exceptions
39
- "MCPException",
40
- "MCPServerError",
41
- "MCPToolNotFoundError",
42
- "MCPValidationError",
43
- ]
@@ -1,312 +0,0 @@
1
- """
2
- MCP Gateway Base Classes
3
- ========================
4
-
5
- Base implementations for MCP Gateway services.
6
-
7
- Part of ISS-0034: Infrastructure Setup - MCP Gateway Project Foundation
8
- """
9
-
10
- import asyncio
11
- from typing import Any, Dict, Optional
12
-
13
- from claude_mpm.core.enums import ServiceState
14
- from claude_mpm.services.core.base import BaseService
15
-
16
-
17
- class BaseMCPService(BaseService):
18
- """
19
- Base class for all MCP Gateway services.
20
-
21
- Extends the claude-mpm BaseService with MCP-specific functionality
22
- including state management, health monitoring, and async lifecycle support.
23
-
24
- WHY: We extend BaseService to maintain consistency with the claude-mpm
25
- architecture while adding MCP-specific capabilities. This ensures all
26
- MCP services integrate seamlessly with the existing service container
27
- and dependency injection system.
28
- """
29
-
30
- def __init__(
31
- self,
32
- service_name: Optional[str] = None,
33
- config: Optional[Dict[str, Any]] = None,
34
- ):
35
- """
36
- Initialize MCP service.
37
-
38
- Args:
39
- service_name: Name of the service for logging
40
- config: Service-specific configuration
41
- """
42
- super().__init__(service_name or "MCPService", config)
43
- self._state = ServiceState.UNINITIALIZED
44
- self._health_status = {
45
- "healthy": False,
46
- "state": self._state.value,
47
- "last_check": None,
48
- "details": {},
49
- }
50
- self._state_lock = asyncio.Lock()
51
- self._initialization_task = None
52
- self._shutdown_task = None
53
-
54
- async def initialize(self) -> bool:
55
- """
56
- Initialize the MCP service.
57
-
58
- This method manages state transitions and ensures thread-safe initialization.
59
- Subclasses should override _do_initialize() for custom initialization logic.
60
-
61
- Returns:
62
- True if initialization successful, False otherwise
63
- """
64
- async with self._state_lock:
65
- if self._state not in [
66
- ServiceState.UNINITIALIZED,
67
- ServiceState.STOPPED,
68
- ]:
69
- self.log_warning(f"Cannot initialize from state {self._state.value}")
70
- return False
71
-
72
- self._state = ServiceState.INITIALIZING
73
- self.log_info("Initializing MCP service")
74
-
75
- try:
76
- # Call subclass initialization
77
- success = await self._do_initialize()
78
-
79
- async with self._state_lock:
80
- if success:
81
- self._state = ServiceState.INITIALIZED
82
- self._initialized = True
83
- self._health_status["healthy"] = True
84
- self._health_status["state"] = self._state.value
85
- self.log_info("MCP service initialized successfully")
86
- else:
87
- self._state = ServiceState.ERROR
88
- self._health_status["healthy"] = False
89
- self._health_status["state"] = self._state.value
90
- self.log_error("MCP service initialization failed")
91
-
92
- return success
93
-
94
- except Exception as e:
95
- async with self._state_lock:
96
- self._state = ServiceState.ERROR
97
- self._health_status["healthy"] = False
98
- self._health_status["state"] = self._state.value
99
- self._health_status["details"]["error"] = str(e)
100
-
101
- self.log_error(f"Exception during initialization: {e}")
102
- return False
103
-
104
- async def _do_initialize(self) -> bool:
105
- """
106
- Perform actual initialization logic.
107
-
108
- Subclasses should override this method to implement custom initialization.
109
-
110
- Returns:
111
- True if initialization successful
112
- """
113
- # Default implementation - subclasses should override
114
- return True
115
-
116
- async def start(self) -> bool:
117
- """
118
- Start the MCP service.
119
-
120
- Returns:
121
- True if startup successful
122
- """
123
- async with self._state_lock:
124
- if self._state != ServiceState.INITIALIZED:
125
- self.log_warning(f"Cannot start from state {self._state.value}")
126
- return False
127
-
128
- self._state = ServiceState.STARTING
129
- self.log_info("Starting MCP service")
130
-
131
- try:
132
- success = await self._do_start()
133
-
134
- async with self._state_lock:
135
- if success:
136
- self._state = ServiceState.RUNNING
137
- self._health_status["healthy"] = True
138
- self._health_status["state"] = self._state.value
139
- self.log_info("MCP service started successfully")
140
- else:
141
- self._state = ServiceState.ERROR
142
- self._health_status["healthy"] = False
143
- self._health_status["state"] = self._state.value
144
- self.log_error("MCP service startup failed")
145
-
146
- return success
147
-
148
- except Exception as e:
149
- async with self._state_lock:
150
- self._state = ServiceState.ERROR
151
- self._health_status["healthy"] = False
152
- self._health_status["state"] = self._state.value
153
- self._health_status["details"]["error"] = str(e)
154
-
155
- self.log_error(f"Exception during startup: {e}")
156
- return False
157
-
158
- async def _do_start(self) -> bool:
159
- """
160
- Perform actual startup logic.
161
-
162
- Subclasses should override this method to implement custom startup.
163
-
164
- Returns:
165
- True if startup successful
166
- """
167
- # Default implementation - subclasses should override
168
- return True
169
-
170
- async def shutdown(self) -> None:
171
- """
172
- Shutdown the MCP service gracefully.
173
-
174
- This method manages state transitions and ensures clean shutdown.
175
- Subclasses should override _do_shutdown() for custom shutdown logic.
176
- """
177
- async with self._state_lock:
178
- if self._state in [ServiceState.STOPPED, ServiceState.STOPPING]:
179
- self.log_warning(f"Already in state {self._state.value}")
180
- return
181
-
182
- self._state = ServiceState.STOPPING
183
- self.log_info("Shutting down MCP service")
184
-
185
- try:
186
- await self._do_shutdown()
187
-
188
- async with self._state_lock:
189
- self._state = ServiceState.STOPPED
190
- self._shutdown = True
191
- self._health_status["healthy"] = False
192
- self._health_status["state"] = self._state.value
193
- self.log_info("MCP service shutdown complete")
194
-
195
- except Exception as e:
196
- async with self._state_lock:
197
- self._state = ServiceState.ERROR
198
- self._health_status["healthy"] = False
199
- self._health_status["state"] = self._state.value
200
- self._health_status["details"]["error"] = str(e)
201
-
202
- self.log_error(f"Exception during shutdown: {e}")
203
-
204
- async def _do_shutdown(self) -> None:
205
- """
206
- Perform actual shutdown logic.
207
-
208
- Subclasses should override this method to implement custom shutdown.
209
- """
210
- # Default implementation - subclasses should override
211
-
212
- async def restart(self) -> bool:
213
- """
214
- Restart the MCP service.
215
-
216
- Returns:
217
- True if restart successful
218
- """
219
- self.log_info("Restarting MCP service")
220
-
221
- # Shutdown if running
222
- if self._state == ServiceState.RUNNING:
223
- await self.shutdown()
224
-
225
- # Re-initialize
226
- if not await self.initialize():
227
- return False
228
-
229
- # Start again
230
- return await self.start()
231
-
232
- def get_state(self) -> str:
233
- """
234
- Get current service state.
235
-
236
- Returns:
237
- Service state string
238
- """
239
- return self._state.value
240
-
241
- def is_healthy(self) -> bool:
242
- """
243
- Check if service is healthy.
244
-
245
- Returns:
246
- True if service is healthy
247
- """
248
- return self._health_status["healthy"]
249
-
250
- def get_health_status(self) -> Dict[str, Any]:
251
- """
252
- Get detailed health status.
253
-
254
- Returns:
255
- Health status information
256
- """
257
- return self._health_status.copy()
258
-
259
- def update_health_status(
260
- self, healthy: bool, details: Optional[Dict[str, Any]] = None
261
- ) -> None:
262
- """
263
- Update health status.
264
-
265
- Args:
266
- healthy: Whether service is healthy
267
- details: Additional health details
268
- """
269
- from datetime import datetime, timezone
270
-
271
- self._health_status["healthy"] = healthy
272
- self._health_status["last_check"] = datetime.now(timezone.utc).isoformat()
273
-
274
- if details:
275
- self._health_status["details"].update(details)
276
-
277
- # Additional logging methods for MCP-specific events
278
- def log_mcp_event(
279
- self, event_type: str, data: Optional[Dict[str, Any]] = None
280
- ) -> None:
281
- """
282
- Log an MCP-specific event.
283
-
284
- Args:
285
- event_type: Type of MCP event
286
- data: Event data
287
- """
288
- message = f"MCP Event: {event_type}"
289
- if data:
290
- message += f" - {data}"
291
- self.log_info(message)
292
-
293
- def log_tool_invocation(
294
- self, tool_name: str, success: bool, duration: Optional[float] = None
295
- ) -> None:
296
- """
297
- Log a tool invocation.
298
-
299
- Args:
300
- tool_name: Name of the tool invoked
301
- success: Whether invocation was successful
302
- duration: Execution duration in seconds
303
- """
304
- status = "successful" if success else "failed"
305
- message = f"Tool invocation: {tool_name} {status}"
306
- if duration:
307
- message += f" ({duration:.3f}s)"
308
-
309
- if success:
310
- self.log_info(message)
311
- else:
312
- self.log_warning(message)
@@ -1,253 +0,0 @@
1
- """
2
- MCP Gateway Exception Classes
3
- =============================
4
-
5
- Custom exceptions for MCP Gateway operations.
6
-
7
- Part of ISS-0034: Infrastructure Setup - MCP Gateway Project Foundation
8
- """
9
-
10
- from typing import Any, Dict, Optional
11
-
12
-
13
- class MCPException(Exception):
14
- """
15
- Base exception for all MCP Gateway errors.
16
-
17
- WHY: We create a base exception to allow catching all MCP-related
18
- errors in a single except block while still being able to handle
19
- specific error types when needed.
20
- """
21
-
22
- def __init__(self, message: str, details: Optional[Dict[str, Any]] = None):
23
- """
24
- Initialize MCP exception.
25
-
26
- Args:
27
- message: Error message
28
- details: Additional error details
29
- """
30
- super().__init__(message)
31
- self.message = message
32
- self.details = details or {}
33
-
34
- def __str__(self) -> str:
35
- """String representation of the exception."""
36
- if self.details:
37
- return f"{self.message} - Details: {self.details}"
38
- return self.message
39
-
40
-
41
- class MCPConfigurationError(MCPException):
42
- """
43
- Raised when MCP configuration is invalid or cannot be loaded.
44
-
45
- Common scenarios:
46
- - Missing required configuration fields
47
- - Invalid configuration values
48
- - Configuration file not found
49
- - YAML parsing errors
50
- """
51
-
52
- def __init__(
53
- self,
54
- message: str,
55
- config_key: Optional[str] = None,
56
- expected_type: Optional[str] = None,
57
- ):
58
- """
59
- Initialize configuration error.
60
-
61
- Args:
62
- message: Error message
63
- config_key: Configuration key that caused the error
64
- expected_type: Expected type for the configuration value
65
- """
66
- details = {}
67
- if config_key:
68
- details["config_key"] = config_key
69
- if expected_type:
70
- details["expected_type"] = expected_type
71
-
72
- super().__init__(message, details)
73
-
74
-
75
- class MCPToolNotFoundError(MCPException):
76
- """
77
- Raised when a requested tool is not found in the registry.
78
-
79
- This error occurs when:
80
- - Attempting to invoke a non-existent tool
81
- - Trying to unregister a tool that isn't registered
82
- - Searching for a tool that doesn't exist
83
- """
84
-
85
- def __init__(self, tool_name: str, available_tools: Optional[list] = None):
86
- """
87
- Initialize tool not found error.
88
-
89
- Args:
90
- tool_name: Name of the tool that wasn't found
91
- available_tools: List of available tool names for reference
92
- """
93
- message = f"Tool '{tool_name}' not found in registry"
94
- details = {"tool_name": tool_name}
95
-
96
- if available_tools:
97
- details["available_tools"] = available_tools
98
- message += f". Available tools: {', '.join(available_tools)}"
99
-
100
- super().__init__(message, details)
101
-
102
-
103
- class MCPServerError(MCPException):
104
- """
105
- Raised when MCP server encounters an error.
106
-
107
- Common scenarios:
108
- - Server initialization failure
109
- - Port binding issues
110
- - Server crash during operation
111
- - Invalid server state transitions
112
- """
113
-
114
- def __init__(
115
- self,
116
- message: str,
117
- server_state: Optional[str] = None,
118
- error_code: Optional[int] = None,
119
- ):
120
- """
121
- Initialize server error.
122
-
123
- Args:
124
- message: Error message
125
- server_state: Current server state when error occurred
126
- error_code: Numeric error code if applicable
127
- """
128
- details = {}
129
- if server_state:
130
- details["server_state"] = server_state
131
- if error_code:
132
- details["error_code"] = error_code
133
-
134
- super().__init__(message, details)
135
-
136
-
137
- class MCPCommunicationError(MCPException):
138
- """
139
- Raised when communication with MCP client fails.
140
-
141
- This includes:
142
- - Stdio communication failures
143
- - Message parsing errors
144
- - Protocol violations
145
- - Timeout errors
146
- """
147
-
148
- def __init__(
149
- self,
150
- message: str,
151
- direction: Optional[str] = None,
152
- raw_data: Optional[str] = None,
153
- ):
154
- """
155
- Initialize communication error.
156
-
157
- Args:
158
- message: Error message
159
- direction: Direction of communication ("send" or "receive")
160
- raw_data: Raw data that caused the error (for debugging)
161
- """
162
- details = {}
163
- if direction:
164
- details["direction"] = direction
165
- if raw_data and len(raw_data) < 1000: # Limit raw data size in exceptions
166
- details["raw_data"] = raw_data
167
- elif raw_data:
168
- details["raw_data"] = raw_data[:1000] + "... (truncated)"
169
-
170
- super().__init__(message, details)
171
-
172
-
173
- class MCPValidationError(MCPException):
174
- """
175
- Raised when validation fails.
176
-
177
- Used for:
178
- - Tool parameter validation
179
- - Schema validation
180
- - Input validation
181
- - Response validation
182
- """
183
-
184
- def __init__(
185
- self,
186
- message: str,
187
- field: Optional[str] = None,
188
- expected: Optional[Any] = None,
189
- actual: Optional[Any] = None,
190
- ):
191
- """
192
- Initialize validation error.
193
-
194
- Args:
195
- message: Error message
196
- field: Field that failed validation
197
- expected: Expected value or type
198
- actual: Actual value received
199
- """
200
- details = {}
201
- if field:
202
- details["field"] = field
203
- if expected is not None:
204
- details["expected"] = str(expected)
205
- if actual is not None:
206
- details["actual"] = str(actual)
207
-
208
- super().__init__(message, details)
209
-
210
-
211
- class MCPTimeoutError(MCPException):
212
- """
213
- Raised when an operation times out.
214
-
215
- Common scenarios:
216
- - Tool invocation timeout
217
- - Server startup timeout
218
- - Communication timeout
219
- """
220
-
221
- def __init__(self, operation: str, timeout_seconds: float):
222
- """
223
- Initialize timeout error.
224
-
225
- Args:
226
- operation: Operation that timed out
227
- timeout_seconds: Timeout duration in seconds
228
- """
229
- message = f"Operation '{operation}' timed out after {timeout_seconds} seconds"
230
- details = {"operation": operation, "timeout_seconds": timeout_seconds}
231
- super().__init__(message, details)
232
-
233
-
234
- class MCPAuthenticationError(MCPException):
235
- """
236
- Raised when authentication fails.
237
-
238
- For future use when MCP supports authentication.
239
- """
240
-
241
- def __init__(self, message: str, auth_method: Optional[str] = None):
242
- """
243
- Initialize authentication error.
244
-
245
- Args:
246
- message: Error message
247
- auth_method: Authentication method that failed
248
- """
249
- details = {}
250
- if auth_method:
251
- details["auth_method"] = auth_method
252
-
253
- super().__init__(message, details)