claude-mpm 5.1.9__py3-none-any.whl → 5.4.48__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 (248) 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/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +1 -1
  5. claude_mpm/agents/MEMORY.md +1 -1
  6. claude_mpm/agents/PM_INSTRUCTIONS.md +843 -900
  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 +2 -2
  11. claude_mpm/agents/templates/circuit-breakers.md +138 -1
  12. claude_mpm/cli/__main__.py +4 -0
  13. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  14. claude_mpm/cli/commands/agent_state_manager.py +18 -27
  15. claude_mpm/cli/commands/agents.py +9 -40
  16. claude_mpm/cli/commands/auto_configure.py +210 -25
  17. claude_mpm/cli/commands/config.py +88 -2
  18. claude_mpm/cli/commands/configure.py +1098 -159
  19. claude_mpm/cli/commands/configure_agent_display.py +25 -6
  20. claude_mpm/cli/commands/mpm_init/core.py +225 -46
  21. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  22. claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
  23. claude_mpm/cli/commands/postmortem.py +1 -1
  24. claude_mpm/cli/commands/profile.py +277 -0
  25. claude_mpm/cli/commands/skills.py +218 -197
  26. claude_mpm/cli/commands/summarize.py +413 -0
  27. claude_mpm/cli/executor.py +21 -3
  28. claude_mpm/cli/interactive/agent_wizard.py +2 -2
  29. claude_mpm/cli/parsers/agents_parser.py +0 -9
  30. claude_mpm/cli/parsers/auto_configure_parser.py +0 -138
  31. claude_mpm/cli/parsers/base_parser.py +12 -0
  32. claude_mpm/cli/parsers/config_parser.py +153 -83
  33. claude_mpm/cli/parsers/profile_parser.py +148 -0
  34. claude_mpm/cli/parsers/skills_parser.py +0 -5
  35. claude_mpm/cli/startup.py +876 -149
  36. claude_mpm/commands/mpm-config.md +28 -0
  37. claude_mpm/commands/mpm-doctor.md +9 -22
  38. claude_mpm/commands/mpm-help.md +5 -287
  39. claude_mpm/commands/mpm-init.md +81 -507
  40. claude_mpm/commands/mpm-monitor.md +15 -402
  41. claude_mpm/commands/mpm-organize.md +120 -0
  42. claude_mpm/commands/mpm-postmortem.md +6 -108
  43. claude_mpm/commands/mpm-session-resume.md +12 -363
  44. claude_mpm/commands/mpm-status.md +5 -69
  45. claude_mpm/commands/mpm-ticket-view.md +52 -495
  46. claude_mpm/commands/mpm-version.md +5 -107
  47. claude_mpm/config/agent_sources.py +27 -0
  48. claude_mpm/core/config.py +2 -4
  49. claude_mpm/core/framework/formatters/content_formatter.py +3 -13
  50. claude_mpm/core/framework/loaders/agent_loader.py +8 -5
  51. claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
  52. claude_mpm/core/framework_loader.py +4 -2
  53. claude_mpm/core/logger.py +13 -0
  54. claude_mpm/core/optimized_startup.py +59 -0
  55. claude_mpm/core/shared/config_loader.py +1 -1
  56. claude_mpm/core/socketio_pool.py +3 -3
  57. claude_mpm/core/unified_agent_registry.py +5 -15
  58. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  59. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +1 -0
  60. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +1 -0
  61. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +1 -0
  62. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +1 -0
  63. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +1 -0
  64. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +2 -0
  65. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DjhvlsAc.js +1 -0
  66. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/N4qtv3Hx.js +2 -0
  67. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uj46x2Wr.js +1 -0
  68. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +2 -0
  69. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +1 -0
  70. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.CAGBuiOw.js +1 -0
  71. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +1 -0
  72. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +10 -0
  73. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  74. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  75. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  76. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  77. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  78. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  79. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  80. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  81. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  82. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  83. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  84. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  85. claude_mpm/hooks/claude_hooks/event_handlers.py +211 -78
  86. claude_mpm/hooks/claude_hooks/hook_handler.py +155 -1
  87. claude_mpm/hooks/claude_hooks/installer.py +33 -10
  88. claude_mpm/hooks/claude_hooks/memory_integration.py +26 -9
  89. claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
  90. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  91. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  92. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  93. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  94. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  95. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  96. claude_mpm/hooks/claude_hooks/services/connection_manager.py +30 -6
  97. claude_mpm/hooks/kuzu_memory_hook.py +5 -5
  98. claude_mpm/hooks/memory_integration_hook.py +46 -1
  99. claude_mpm/init.py +63 -19
  100. claude_mpm/models/git_repository.py +3 -3
  101. claude_mpm/scripts/claude-hook-handler.sh +58 -18
  102. claude_mpm/scripts/launch_monitor.py +93 -13
  103. claude_mpm/services/agents/agent_builder.py +3 -3
  104. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  105. claude_mpm/services/agents/agent_review_service.py +280 -0
  106. claude_mpm/services/agents/cache_git_manager.py +6 -6
  107. claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
  108. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -5
  109. claude_mpm/services/agents/deployment/agent_format_converter.py +23 -13
  110. claude_mpm/services/agents/deployment/agent_template_builder.py +32 -20
  111. claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
  112. claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
  113. claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
  114. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +247 -35
  115. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +392 -87
  116. claude_mpm/services/agents/git_source_manager.py +53 -4
  117. claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
  118. claude_mpm/services/agents/recommender.py +5 -3
  119. claude_mpm/services/agents/single_tier_deployment_service.py +2 -2
  120. claude_mpm/services/agents/sources/git_source_sync_service.py +120 -7
  121. claude_mpm/services/agents/startup_sync.py +22 -2
  122. claude_mpm/services/agents/toolchain_detector.py +10 -6
  123. claude_mpm/services/analysis/__init__.py +11 -1
  124. claude_mpm/services/analysis/clone_detector.py +1030 -0
  125. claude_mpm/services/command_deployment_service.py +81 -10
  126. claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
  127. claude_mpm/services/diagnostics/checks/agent_sources_check.py +1 -1
  128. claude_mpm/services/event_bus/config.py +3 -1
  129. claude_mpm/services/git/git_operations_service.py +101 -16
  130. claude_mpm/services/monitor/daemon.py +9 -2
  131. claude_mpm/services/monitor/daemon_manager.py +39 -3
  132. claude_mpm/services/monitor/management/lifecycle.py +8 -1
  133. claude_mpm/services/monitor/server.py +698 -22
  134. claude_mpm/services/pm_skills_deployer.py +711 -0
  135. claude_mpm/services/profile_manager.py +331 -0
  136. claude_mpm/services/self_upgrade_service.py +120 -12
  137. claude_mpm/services/skills/__init__.py +3 -0
  138. claude_mpm/services/skills/git_skill_source_manager.py +130 -2
  139. claude_mpm/services/skills/selective_skill_deployer.py +704 -0
  140. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  141. claude_mpm/services/skills_deployer.py +127 -9
  142. claude_mpm/services/socketio/dashboard_server.py +1 -0
  143. claude_mpm/services/socketio/event_normalizer.py +51 -6
  144. claude_mpm/services/socketio/server/core.py +386 -108
  145. claude_mpm/services/version_control/git_operations.py +103 -0
  146. claude_mpm/skills/skill_manager.py +92 -3
  147. claude_mpm/utils/agent_dependency_loader.py +14 -2
  148. claude_mpm/utils/agent_filters.py +17 -44
  149. claude_mpm/utils/migration.py +4 -4
  150. claude_mpm/utils/robust_installer.py +47 -3
  151. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.48.dist-info}/METADATA +53 -87
  152. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.48.dist-info}/RECORD +157 -197
  153. claude_mpm-5.4.48.dist-info/entry_points.txt +5 -0
  154. claude_mpm-5.4.48.dist-info/licenses/LICENSE +94 -0
  155. claude_mpm-5.4.48.dist-info/licenses/LICENSE-FAQ.md +153 -0
  156. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
  157. claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
  158. claude_mpm/agents/BASE_OPS.md +0 -219
  159. claude_mpm/agents/BASE_PM.md +0 -480
  160. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
  161. claude_mpm/agents/BASE_QA.md +0 -167
  162. claude_mpm/agents/BASE_RESEARCH.md +0 -53
  163. claude_mpm/agents/base_agent_loader.py +0 -601
  164. claude_mpm/cli/commands/agents_detect.py +0 -380
  165. claude_mpm/cli/commands/agents_recommend.py +0 -309
  166. claude_mpm/cli/ticket_cli.py +0 -35
  167. claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
  168. claude_mpm/commands/mpm-agents-detect.md +0 -177
  169. claude_mpm/commands/mpm-agents-list.md +0 -131
  170. claude_mpm/commands/mpm-agents-recommend.md +0 -223
  171. claude_mpm/commands/mpm-config-view.md +0 -150
  172. claude_mpm/commands/mpm-ticket-organize.md +0 -304
  173. claude_mpm/dashboard/analysis_runner.py +0 -455
  174. claude_mpm/dashboard/index.html +0 -13
  175. claude_mpm/dashboard/open_dashboard.py +0 -66
  176. claude_mpm/dashboard/static/css/activity.css +0 -1958
  177. claude_mpm/dashboard/static/css/connection-status.css +0 -370
  178. claude_mpm/dashboard/static/css/dashboard.css +0 -4701
  179. claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
  180. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
  181. claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
  182. claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
  183. claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
  184. claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
  185. claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
  186. claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
  187. claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
  188. claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
  189. claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
  190. claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
  191. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
  192. claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
  193. claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
  194. claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
  195. claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
  196. claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
  197. claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
  198. claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
  199. claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
  200. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
  201. claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
  202. claude_mpm/dashboard/static/js/connection-manager.js +0 -536
  203. claude_mpm/dashboard/static/js/dashboard.js +0 -1914
  204. claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
  205. claude_mpm/dashboard/static/js/socket-client.js +0 -1474
  206. claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
  207. claude_mpm/dashboard/static/socket.io.min.js +0 -7
  208. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
  209. claude_mpm/dashboard/templates/code_simple.html +0 -153
  210. claude_mpm/dashboard/templates/index.html +0 -606
  211. claude_mpm/dashboard/test_dashboard.html +0 -372
  212. claude_mpm/scripts/mcp_server.py +0 -75
  213. claude_mpm/scripts/mcp_wrapper.py +0 -39
  214. claude_mpm/services/mcp_gateway/__init__.py +0 -159
  215. claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
  216. claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
  217. claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
  218. claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
  219. claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
  220. claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
  221. claude_mpm/services/mcp_gateway/core/base.py +0 -312
  222. claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
  223. claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
  224. claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
  225. claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
  226. claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
  227. claude_mpm/services/mcp_gateway/main.py +0 -589
  228. claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
  229. claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
  230. claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
  231. claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
  232. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
  233. claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
  234. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
  235. claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
  236. claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
  237. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
  238. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
  239. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
  240. claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
  241. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
  242. claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
  243. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
  244. claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
  245. claude_mpm-5.1.9.dist-info/entry_points.txt +0 -10
  246. claude_mpm-5.1.9.dist-info/licenses/LICENSE +0 -21
  247. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.48.dist-info}/WHEEL +0 -0
  248. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.48.dist-info}/top_level.txt +0 -0
@@ -1,412 +0,0 @@
1
- """
2
- MCP Service Registry Implementation
3
- ====================================
4
-
5
- Service registry for MCP Gateway components.
6
- Provides service discovery, registration, and dependency resolution.
7
-
8
- Part of ISS-0035: MCP Server Implementation - Core Server and Tool Registry
9
- """
10
-
11
- import logging
12
- from threading import RLock
13
- from typing import Any, Dict, List, Optional, Type, TypeVar
14
-
15
- from claude_mpm.services.mcp_gateway.core.interfaces import (
16
- IMCPCommunication,
17
- IMCPConfiguration,
18
- IMCPGateway,
19
- IMCPLifecycle,
20
- IMCPToolRegistry,
21
- )
22
- from claude_mpm.services.shared import ManagerBase
23
-
24
- T = TypeVar("T")
25
-
26
-
27
- class MCPServiceRegistry(ManagerBase):
28
- """
29
- Service registry for MCP Gateway components.
30
-
31
- WHY: We need a centralized registry for managing MCP services,
32
- enabling dependency injection and service discovery patterns.
33
- This aligns with the claude-mpm service-oriented architecture.
34
-
35
- DESIGN DECISIONS:
36
- - Use interface-based registration for loose coupling
37
- - Support singleton and transient service lifetimes
38
- - Provide thread-safe service resolution
39
- - Enable service health monitoring
40
- - Support service dependency chains
41
- """
42
-
43
- def __init__(self, config: Optional[Dict[str, Any]] = None):
44
- """Initialize the service registry."""
45
- super().__init__("mcp_service_registry", config=config)
46
-
47
- # Thread safety
48
- self._lock = RLock()
49
-
50
- # Service storage (in addition to base class _items)
51
- self._services: Dict[Type, Any] = {}
52
- self._singletons: Dict[Type, Any] = {}
53
- self._factories: Dict[Type, callable] = {}
54
-
55
- # Service metadata (note: base class has _item_metadata, this is for service-specific metadata)
56
- self._metadata: Dict[Type, Dict[str, Any]] = {}
57
-
58
- # Service health tracking
59
- self._health_checks: Dict[Type, callable] = {}
60
-
61
- def register(
62
- self,
63
- interface: Type[T],
64
- implementation: Optional[Type[T]] = None,
65
- factory: Optional[callable] = None,
66
- singleton: bool = True,
67
- metadata: Optional[Dict[str, Any]] = None,
68
- ) -> None:
69
- """
70
- Register a service in the registry.
71
-
72
- Args:
73
- interface: Service interface type
74
- implementation: Service implementation class
75
- factory: Factory function to create service instances
76
- singleton: Whether to create a single instance
77
- metadata: Additional service metadata
78
-
79
- WHY: We support both direct implementation and factory patterns
80
- to provide flexibility in service instantiation. Singleton support
81
- enables efficient resource management.
82
- """
83
- with self._lock:
84
- if implementation is None and factory is None:
85
- raise ValueError("Either implementation or factory must be provided")
86
-
87
- if implementation and factory:
88
- raise ValueError("Cannot provide both implementation and factory")
89
-
90
- self.logger.info(f"Registering service: {interface.__name__}")
91
-
92
- # Store service registration
93
- if implementation:
94
- self._services[interface] = implementation
95
- elif factory:
96
- self._factories[interface] = factory
97
-
98
- # Store metadata
99
- if metadata:
100
- self._metadata[interface] = metadata
101
- else:
102
- self._metadata[interface] = {"singleton": singleton}
103
-
104
- self._metadata[interface]["singleton"] = singleton
105
-
106
- def register_instance(self, interface: Type[T], instance: T) -> None:
107
- """
108
- Register a pre-created service instance.
109
-
110
- Args:
111
- interface: Service interface type
112
- instance: Service instance
113
-
114
- WHY: Sometimes we need to register pre-configured instances,
115
- especially for services with complex initialization.
116
- """
117
- with self._lock:
118
- self.logger.info(f"Registering instance: {interface.__name__}")
119
- self._singletons[interface] = instance
120
- self._metadata[interface] = {"singleton": True, "instance": True}
121
-
122
- def resolve(self, interface: Type[T]) -> Optional[T]:
123
- """
124
- Resolve a service from the registry.
125
-
126
- Args:
127
- interface: Service interface type
128
-
129
- Returns:
130
- Service instance or None if not found
131
-
132
- WHY: We use lazy instantiation for non-singleton services
133
- and cache singletons for performance.
134
- """
135
- with self._lock:
136
- # Check for existing singleton
137
- if interface in self._singletons:
138
- return self._singletons[interface]
139
-
140
- # Check for factory
141
- if interface in self._factories:
142
- factory = self._factories[interface]
143
- instance = factory()
144
-
145
- # Cache if singleton
146
- if self._metadata.get(interface, {}).get("singleton", False):
147
- self._singletons[interface] = instance
148
-
149
- return instance
150
-
151
- # Check for implementation class
152
- if interface in self._services:
153
- implementation = self._services[interface]
154
-
155
- # Create instance
156
- try:
157
- instance = implementation()
158
-
159
- # Cache if singleton
160
- if self._metadata.get(interface, {}).get("singleton", True):
161
- self._singletons[interface] = instance
162
-
163
- return instance
164
-
165
- except Exception as e:
166
- self.logger.error(
167
- f"Failed to create service {interface.__name__}: {e}"
168
- )
169
- return None
170
-
171
- self.logger.warning(f"Service not found: {interface.__name__}")
172
- return None
173
-
174
- def resolve_all(self, interface: Type[T]) -> List[T]:
175
- """
176
- Resolve all services implementing an interface.
177
-
178
- Args:
179
- interface: Service interface type
180
-
181
- Returns:
182
- List of service instances
183
-
184
- WHY: Some scenarios require multiple implementations of
185
- the same interface (e.g., multiple tool adapters).
186
- """
187
- with self._lock:
188
- instances = []
189
-
190
- # Add singleton if exists
191
- if interface in self._singletons:
192
- instances.append(self._singletons[interface])
193
-
194
- # Note: In a full implementation, we'd track multiple
195
- # registrations per interface
196
-
197
- return instances
198
-
199
- def unregister(self, interface: Type) -> bool:
200
- """
201
- Unregister a service from the registry.
202
-
203
- Args:
204
- interface: Service interface type
205
-
206
- Returns:
207
- True if unregistration successful
208
- """
209
- with self._lock:
210
- found = False
211
-
212
- if interface in self._services:
213
- del self._services[interface]
214
- found = True
215
-
216
- if interface in self._factories:
217
- del self._factories[interface]
218
- found = True
219
-
220
- if interface in self._singletons:
221
- # Shutdown if it's a lifecycle service
222
- instance = self._singletons[interface]
223
- if isinstance(instance, IMCPLifecycle):
224
- try:
225
- import asyncio
226
-
227
- _task = asyncio.create_task(instance.stop())
228
- # Fire-and-forget shutdown during unregister
229
- except Exception as e:
230
- self.logger.warning(
231
- f"Error stopping service {interface.__name__}: {e}"
232
- )
233
-
234
- del self._singletons[interface]
235
- found = True
236
-
237
- if interface in self._metadata:
238
- del self._metadata[interface]
239
-
240
- if interface in self._health_checks:
241
- del self._health_checks[interface]
242
-
243
- if found:
244
- self.logger.info(f"Unregistered service: {interface.__name__}")
245
-
246
- return found
247
-
248
- def register_health_check(self, interface: Type, health_check: callable) -> None:
249
- """
250
- Register a health check for a service.
251
-
252
- Args:
253
- interface: Service interface type
254
- health_check: Health check function
255
- """
256
- with self._lock:
257
- self._health_checks[interface] = health_check
258
-
259
- async def check_health(self) -> Dict[str, Any]:
260
- """
261
- Check health of all registered services.
262
-
263
- Returns:
264
- Dictionary of service health statuses
265
- """
266
- health_status = {}
267
-
268
- with self._lock:
269
- # Check singleton services
270
- for interface, instance in self._singletons.items():
271
- service_name = interface.__name__
272
-
273
- try:
274
- # Use custom health check if available
275
- if interface in self._health_checks:
276
- health_check = self._health_checks[interface]
277
- if asyncio.iscoroutinefunction(health_check):
278
- health = await health_check(instance)
279
- else:
280
- health = health_check(instance)
281
- health_status[service_name] = health
282
-
283
- # Use built-in health check for lifecycle services
284
- elif isinstance(instance, IMCPLifecycle):
285
- health_status[service_name] = {
286
- "healthy": instance.is_healthy(),
287
- "state": instance.get_state(),
288
- "details": instance.get_health_status(),
289
- }
290
-
291
- # Basic health check
292
- else:
293
- health_status[service_name] = {
294
- "healthy": True,
295
- "state": "unknown",
296
- }
297
-
298
- except Exception as e:
299
- health_status[service_name] = {"healthy": False, "error": str(e)}
300
-
301
- return health_status
302
-
303
- def get_metadata(self, interface: Type) -> Optional[Dict[str, Any]]:
304
- """
305
- Get metadata for a service.
306
-
307
- Args:
308
- interface: Service interface type
309
-
310
- Returns:
311
- Service metadata or None
312
- """
313
- with self._lock:
314
- return self._metadata.get(interface)
315
-
316
- def list_services(self) -> List[str]:
317
- """
318
- List all registered services.
319
-
320
- Returns:
321
- List of service interface names
322
- """
323
- with self._lock:
324
- services = set()
325
- services.update(interface.__name__ for interface in self._services)
326
- services.update(interface.__name__ for interface in self._factories)
327
- services.update(interface.__name__ for interface in self._singletons)
328
- return sorted(services)
329
-
330
- def clear(self) -> None:
331
- """Clear all service registrations."""
332
- with self._lock:
333
- # Shutdown lifecycle services
334
- for instance in self._singletons.values():
335
- if isinstance(instance, IMCPLifecycle):
336
- try:
337
- import asyncio
338
-
339
- _task = asyncio.create_task(instance.stop())
340
- # Fire-and-forget shutdown during clear
341
- except Exception as e:
342
- self.logger.warning(f"Error stopping service: {e}")
343
-
344
- # Clear all registrations
345
- self._services.clear()
346
- self._factories.clear()
347
- self._singletons.clear()
348
- self._metadata.clear()
349
- self._health_checks.clear()
350
-
351
- self.logger.info("Service registry cleared")
352
-
353
- # Abstract methods required by ManagerBase
354
- def _do_initialize(self) -> bool:
355
- """Initialize the service registry."""
356
- self.logger.info("MCP Service Registry initialized")
357
- return True
358
-
359
- def _validate_item(self, item_id: str, item: Any) -> bool:
360
- """Validate a service before registration."""
361
- # For services, we validate that they implement the expected interface
362
- return item is not None
363
-
364
- def _do_scan_items(self) -> int:
365
- """Scan for available services."""
366
- # For service registry, we don't auto-scan - services are explicitly registered
367
- return len(self._services)
368
-
369
-
370
- # Global service registry instance
371
- _service_registry: Optional[MCPServiceRegistry] = None
372
-
373
-
374
- def get_service_registry() -> MCPServiceRegistry:
375
- """
376
- Get the global MCP service registry instance.
377
-
378
- Returns:
379
- Service registry instance
380
- """
381
- global _service_registry
382
- if _service_registry is None:
383
- _service_registry = MCPServiceRegistry()
384
- return _service_registry
385
-
386
-
387
- def register_mcp_services() -> None:
388
- """
389
- Register all default MCP services.
390
-
391
- This function sets up the standard MCP service configuration.
392
- """
393
- registry = get_service_registry()
394
-
395
- # Register core services
396
- # Use the official MCP gateway implementation
397
- from claude_mpm.services.mcp_gateway.server.mcp_gateway import MCPGateway
398
-
399
- registry.register(IMCPGateway, MCPGateway, singleton=True)
400
-
401
- from claude_mpm.services.mcp_gateway.config.configuration import MCPConfiguration
402
- from claude_mpm.services.mcp_gateway.registry.tool_registry import ToolRegistry
403
- from claude_mpm.services.mcp_gateway.server.stdio_handler import StdioHandler
404
-
405
- registry.register(IMCPCommunication, StdioHandler, singleton=True)
406
- registry.register(IMCPToolRegistry, ToolRegistry, singleton=True)
407
- registry.register(IMCPConfiguration, MCPConfiguration, singleton=True)
408
-
409
- logging.info("MCP services registered")
410
-
411
-
412
- import asyncio