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,414 +0,0 @@
1
- """
2
- MCP Gateway Implementation
3
- ==========================
4
-
5
- MCP protocol gateway using Anthropic's official MCP package.
6
- Handles stdio-based communication, request routing, and tool invocation.
7
- Acts as a bridge between Claude Code and internal tools.
8
-
9
- NOTE: MCP is ONLY for Claude Code - NOT for Claude Code.
10
- Claude Code uses a different system for agent deployment.
11
-
12
- Part of ISS-0035: MCP Gateway Implementation - Core Gateway and Tool Registry
13
- """
14
-
15
- import asyncio
16
- import contextlib
17
- import json
18
- import traceback
19
- from datetime import datetime, timezone
20
- from typing import Any, Callable, Dict, List, Optional, Union
21
-
22
- # Import from the official MCP package
23
- from mcp.server import Server
24
- from mcp.types import EmbeddedResource, ImageContent, TextContent, Tool
25
-
26
- from claude_mpm.services.mcp_gateway.core.base import BaseMCPService
27
- from claude_mpm.services.mcp_gateway.core.interfaces import (
28
- IMCPCommunication,
29
- IMCPGateway,
30
- IMCPToolRegistry,
31
- MCPToolInvocation,
32
- )
33
-
34
-
35
- class MCPGateway(BaseMCPService, IMCPGateway):
36
- """
37
- MCP Protocol Gateway implementation using Anthropic's official MCP package.
38
-
39
- WHY: We use the official MCP package to ensure protocol compliance and
40
- compatibility with Claude Code. The stdio-based communication model allows
41
- seamless integration with Claude Code's MCP client as a protocol bridge.
42
-
43
- DESIGN DECISIONS:
44
- - Use asyncio for all I/O operations to handle concurrent requests efficiently
45
- - Maintain request handlers in a dictionary for extensibility
46
- - Implement comprehensive error handling to prevent gateway crashes
47
- - Use structured logging for debugging and monitoring
48
- """
49
-
50
- def __init__(self, gateway_name: str = "claude-mpm-mcp", version: str = "1.0.0"):
51
- """
52
- Initialize MCP Gateway.
53
-
54
- Args:
55
- gateway_name: Name of the MCP gateway
56
- version: Gateway version
57
- """
58
- super().__init__(f"MCPGateway-{gateway_name}")
59
-
60
- # Gateway configuration
61
- self.gateway_name = gateway_name
62
- self.server_name = gateway_name # Keep for compatibility
63
- self.version = version
64
-
65
- # MCP Server instance from official package
66
- self.mcp_server = Server(gateway_name)
67
-
68
- # Dependencies (injected via setters)
69
- self._tool_registry: Optional[IMCPToolRegistry] = None
70
- self._communication: Optional[IMCPCommunication] = None
71
-
72
- # Request handlers
73
- self._handlers: Dict[str, Callable] = {}
74
-
75
- # Server capabilities
76
- self._capabilities = {
77
- "tools": {},
78
- "prompts": {},
79
- "resources": {},
80
- "experimental": {},
81
- }
82
-
83
- # Metrics
84
- self._metrics = {
85
- "requests_handled": 0,
86
- "errors": 0,
87
- "tool_invocations": 0,
88
- "start_time": None,
89
- "last_request_time": None,
90
- }
91
-
92
- # Running state
93
- self._run_task: Optional[asyncio.Task] = None
94
- self._shutdown_event = asyncio.Event()
95
-
96
- # Setup default handlers
97
- self._setup_default_handlers()
98
-
99
- def _setup_default_handlers(self) -> None:
100
- """
101
- Setup default MCP protocol handlers.
102
-
103
- WHY: The MCP protocol requires specific handlers for initialization,
104
- tool discovery, and tool invocation. We set these up to ensure
105
- protocol compliance.
106
- """
107
-
108
- # Initialize handler
109
- @self.mcp_server.list_tools()
110
- async def handle_list_tools() -> List[Tool]:
111
- """Handle tools/list request."""
112
- self.log_info("Handling tools/list request")
113
-
114
- if not self._tool_registry:
115
- self.log_warning("No tool registry available")
116
- return []
117
-
118
- tools = []
119
- for tool_def in self._tool_registry.list_tools():
120
- tool = Tool(
121
- name=tool_def.name,
122
- description=tool_def.description,
123
- inputSchema=tool_def.input_schema,
124
- )
125
- tools.append(tool)
126
-
127
- self.log_info(f"Returning {len(tools)} tools")
128
- return tools
129
-
130
- @self.mcp_server.call_tool()
131
- async def handle_call_tool(
132
- name: str, arguments: Dict[str, Any]
133
- ) -> List[Union[TextContent, ImageContent, EmbeddedResource]]:
134
- """Handle tools/call request."""
135
- self.log_info(f"Handling tools/call request for tool: {name}")
136
-
137
- if not self._tool_registry:
138
- error_msg = "No tool registry available"
139
- self.log_error(error_msg)
140
- return [TextContent(type="text", text=f"Error: {error_msg}")]
141
-
142
- # Create invocation request
143
- invocation = MCPToolInvocation(
144
- tool_name=name,
145
- parameters=arguments,
146
- request_id=f"req_{datetime.now(timezone.utc).timestamp()}",
147
- )
148
-
149
- try:
150
- # Invoke tool through registry
151
- result = await self._tool_registry.invoke_tool(invocation)
152
-
153
- # Update metrics
154
- self._metrics["tool_invocations"] += 1
155
-
156
- # Log invocation
157
- self.log_tool_invocation(name, result.success, result.execution_time)
158
-
159
- if result.success:
160
- # Return successful result
161
- if isinstance(result.data, str):
162
- return [TextContent(type="text", text=result.data)]
163
- return [
164
- TextContent(type="text", text=json.dumps(result.data, indent=2))
165
- ]
166
- # Return error
167
- return [TextContent(type="text", text=f"Error: {result.error}")]
168
-
169
- except Exception as e:
170
- error_msg = f"Failed to invoke tool {name}: {e!s}"
171
- self.log_error(error_msg)
172
- self._metrics["errors"] += 1
173
- return [TextContent(type="text", text=f"Error: {error_msg}")]
174
-
175
- def set_tool_registry(self, registry: IMCPToolRegistry) -> None:
176
- """
177
- Set the tool registry for the server.
178
-
179
- Args:
180
- registry: Tool registry to use
181
- """
182
- self._tool_registry = registry
183
- self.log_info("Tool registry set")
184
-
185
- def set_communication(self, communication: IMCPCommunication) -> None:
186
- """
187
- Set the communication handler.
188
-
189
- Args:
190
- communication: Communication handler to use
191
- """
192
- self._communication = communication
193
- self.log_info("Communication handler set")
194
-
195
- async def _do_initialize(self) -> bool:
196
- """
197
- Perform server initialization.
198
-
199
- Returns:
200
- True if initialization successful
201
- """
202
- try:
203
- self.log_info("Initializing MCP server components")
204
-
205
- # Validate dependencies
206
- if not self._tool_registry:
207
- self.log_warning("No tool registry set - server will have no tools")
208
-
209
- # Initialize metrics
210
- self._metrics["start_time"] = datetime.now(timezone.utc).isoformat()
211
-
212
- # Update capabilities based on registry
213
- if self._tool_registry:
214
- tools = self._tool_registry.list_tools()
215
- self._capabilities["tools"]["available"] = len(tools)
216
- self._capabilities["tools"]["names"] = [t.name for t in tools]
217
-
218
- self.log_info("MCP server initialization complete")
219
- return True
220
-
221
- except Exception as e:
222
- self.log_error(f"Failed to initialize MCP server: {e}")
223
- return False
224
-
225
- async def _do_start(self) -> bool:
226
- """
227
- Start the MCP server.
228
-
229
- Returns:
230
- True if startup successful
231
- """
232
- try:
233
- self.log_info("Starting MCP server")
234
-
235
- # Clear shutdown event
236
- self._shutdown_event.clear()
237
-
238
- # Start the run task
239
- self._run_task = asyncio.create_task(self.run())
240
-
241
- self.log_info("MCP server started successfully")
242
- return True
243
-
244
- except Exception as e:
245
- self.log_error(f"Failed to start MCP server: {e}")
246
- return False
247
-
248
- async def _do_shutdown(self) -> None:
249
- """
250
- Shutdown the MCP server gracefully.
251
- """
252
- self.log_info("Shutting down MCP server")
253
-
254
- # Signal shutdown
255
- self._shutdown_event.set()
256
-
257
- # Cancel run task if active
258
- if self._run_task and not self._run_task.done():
259
- self._run_task.cancel()
260
- with contextlib.suppress(asyncio.CancelledError):
261
- await self._run_task
262
-
263
- # Clean up resources
264
- if self._tool_registry:
265
- self.log_info("Cleaning up tool registry")
266
- # Tool registry cleanup if needed
267
-
268
- self.log_info("MCP server shutdown complete")
269
-
270
- async def handle_request(self, request: Dict[str, Any]) -> Dict[str, Any]:
271
- """
272
- Handle an MCP request.
273
-
274
- This method routes requests to appropriate handlers based on the method.
275
-
276
- Args:
277
- request: MCP request message
278
-
279
- Returns:
280
- Response message
281
- """
282
- try:
283
- # Update metrics
284
- self._metrics["requests_handled"] += 1
285
- self._metrics["last_request_time"] = datetime.now(timezone.utc).isoformat()
286
-
287
- # Extract request details
288
- method = request.get("method", "")
289
- params = request.get("params", {})
290
- request_id = request.get("id")
291
-
292
- self.log_debug(f"Handling request: {method}")
293
-
294
- # Check for custom handler
295
- if method in self._handlers:
296
- handler = self._handlers[method]
297
- result = await handler(params)
298
-
299
- # Build response
300
- response = {"jsonrpc": "2.0", "id": request_id, "result": result}
301
- else:
302
- # Unknown method
303
- self.log_warning(f"Unknown method: {method}")
304
- response = {
305
- "jsonrpc": "2.0",
306
- "id": request_id,
307
- "error": {"code": -32601, "message": f"Method not found: {method}"},
308
- }
309
-
310
- return response
311
-
312
- except Exception as e:
313
- self.log_error(f"Error handling request: {e}")
314
- self._metrics["errors"] += 1
315
-
316
- return {
317
- "jsonrpc": "2.0",
318
- "id": request.get("id"),
319
- "error": {"code": -32603, "message": f"Internal error: {e!s}"},
320
- }
321
-
322
- async def run(self) -> None:
323
- """
324
- Run the MCP server main loop.
325
-
326
- This method uses the official MCP Server's stdio-based communication
327
- to handle incoming requests from Claude Code.
328
-
329
- WHY: We use stdio (stdin/stdout) as it's the standard communication
330
- method for MCP servers in Claude Code. This ensures compatibility
331
- and allows the server to be launched as a subprocess.
332
- """
333
- try:
334
- self.log_info("Starting MCP server main loop")
335
-
336
- # Import the stdio server function
337
- from mcp.server.lowlevel import NotificationOptions
338
- from mcp.server.models import InitializationOptions
339
- from mcp.server.stdio import stdio_server
340
-
341
- # Create initialization options
342
- init_options = InitializationOptions(
343
- server_name=self.server_name,
344
- server_version=self.version,
345
- capabilities=self.mcp_server.get_capabilities(
346
- notification_options=NotificationOptions(),
347
- experimental_capabilities={},
348
- ),
349
- )
350
-
351
- # Run the MCP server with stdio transport
352
- async with stdio_server() as (read_stream, write_stream):
353
- self.log_info("MCP server stdio connection established")
354
-
355
- # Run the server
356
- await self.mcp_server.run(read_stream, write_stream, init_options)
357
-
358
- self.log_info("MCP server main loop ended")
359
-
360
- except Exception as e:
361
- self.log_error(f"Error in MCP server main loop: {e}")
362
- self.log_error(f"Traceback: {traceback.format_exc()}")
363
- self._metrics["errors"] += 1
364
- raise
365
-
366
- def register_handler(self, method: str, handler: Callable) -> None:
367
- """
368
- Register a custom request handler.
369
-
370
- Args:
371
- method: Method name to handle
372
- handler: Handler function
373
- """
374
- self._handlers[method] = handler
375
- self.log_info(f"Registered handler for method: {method}")
376
-
377
- def get_capabilities(self) -> Dict[str, Any]:
378
- """
379
- Get server capabilities.
380
-
381
- Returns:
382
- Dictionary of server capabilities formatted for MCP protocol
383
- """
384
- capabilities = {}
385
-
386
- # Add tool capabilities if registry is available
387
- if self._tool_registry:
388
- capabilities["tools"] = {}
389
-
390
- # Add experimental features
391
- capabilities["experimental"] = {}
392
-
393
- return capabilities
394
-
395
- def get_metrics(self) -> Dict[str, Any]:
396
- """
397
- Get server metrics.
398
-
399
- Returns:
400
- Server metrics dictionary
401
- """
402
- return self._metrics.copy()
403
-
404
- async def stop(self) -> None:
405
- """
406
- Stop the MCP service gracefully.
407
-
408
- This implements the IMCPLifecycle interface method.
409
- """
410
- await self.shutdown()
411
-
412
-
413
- # Backward compatibility alias
414
- MCPServer = MCPGateway