claude-mpm 5.1.9__py3-none-any.whl → 5.4.14__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 (162) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +4 -0
  3. claude_mpm/agents/PM_INSTRUCTIONS.md +85 -0
  4. claude_mpm/agents/agent_loader.py +13 -44
  5. claude_mpm/agents/templates/circuit-breakers.md +138 -1
  6. claude_mpm/cli/__main__.py +4 -0
  7. claude_mpm/cli/commands/agent_state_manager.py +8 -17
  8. claude_mpm/cli/commands/auto_configure.py +210 -25
  9. claude_mpm/cli/commands/config.py +88 -2
  10. claude_mpm/cli/commands/configure.py +1097 -158
  11. claude_mpm/cli/commands/configure_agent_display.py +15 -6
  12. claude_mpm/cli/commands/mpm_init/core.py +160 -46
  13. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  14. claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
  15. claude_mpm/cli/commands/skills.py +21 -2
  16. claude_mpm/cli/commands/summarize.py +413 -0
  17. claude_mpm/cli/executor.py +11 -3
  18. claude_mpm/cli/parsers/base_parser.py +5 -0
  19. claude_mpm/cli/parsers/config_parser.py +153 -83
  20. claude_mpm/cli/parsers/skills_parser.py +3 -2
  21. claude_mpm/cli/startup.py +333 -89
  22. claude_mpm/commands/mpm-config.md +266 -0
  23. claude_mpm/commands/{mpm-ticket-organize.md → mpm-organize.md} +4 -5
  24. claude_mpm/config/agent_sources.py +27 -0
  25. claude_mpm/core/framework/formatters/content_formatter.py +3 -13
  26. claude_mpm/core/framework/loaders/agent_loader.py +8 -5
  27. claude_mpm/core/framework_loader.py +4 -2
  28. claude_mpm/core/logger.py +13 -0
  29. claude_mpm/core/socketio_pool.py +3 -3
  30. claude_mpm/core/unified_agent_registry.py +5 -15
  31. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  32. claude_mpm/hooks/claude_hooks/event_handlers.py +206 -78
  33. claude_mpm/hooks/claude_hooks/hook_handler.py +6 -0
  34. claude_mpm/hooks/claude_hooks/installer.py +33 -10
  35. claude_mpm/hooks/claude_hooks/memory_integration.py +26 -9
  36. claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
  37. claude_mpm/hooks/claude_hooks/services/connection_manager.py +4 -0
  38. claude_mpm/hooks/memory_integration_hook.py +46 -1
  39. claude_mpm/init.py +0 -19
  40. claude_mpm/scripts/claude-hook-handler.sh +58 -18
  41. claude_mpm/scripts/launch_monitor.py +93 -13
  42. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  43. claude_mpm/services/agents/agent_review_service.py +280 -0
  44. claude_mpm/services/agents/deployment/agent_discovery_service.py +2 -3
  45. claude_mpm/services/agents/deployment/agent_template_builder.py +4 -2
  46. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +78 -9
  47. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +335 -53
  48. claude_mpm/services/agents/git_source_manager.py +34 -0
  49. claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
  50. claude_mpm/services/agents/sources/git_source_sync_service.py +8 -1
  51. claude_mpm/services/agents/toolchain_detector.py +10 -6
  52. claude_mpm/services/analysis/__init__.py +11 -1
  53. claude_mpm/services/analysis/clone_detector.py +1030 -0
  54. claude_mpm/services/command_deployment_service.py +71 -10
  55. claude_mpm/services/event_bus/config.py +3 -1
  56. claude_mpm/services/git/git_operations_service.py +93 -8
  57. claude_mpm/services/monitor/daemon.py +9 -2
  58. claude_mpm/services/monitor/daemon_manager.py +39 -3
  59. claude_mpm/services/monitor/server.py +225 -19
  60. claude_mpm/services/self_upgrade_service.py +120 -12
  61. claude_mpm/services/skills/__init__.py +3 -0
  62. claude_mpm/services/skills/git_skill_source_manager.py +32 -2
  63. claude_mpm/services/skills/selective_skill_deployer.py +230 -0
  64. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  65. claude_mpm/services/skills_deployer.py +64 -3
  66. claude_mpm/services/socketio/event_normalizer.py +15 -1
  67. claude_mpm/services/socketio/server/core.py +160 -21
  68. claude_mpm/services/version_control/git_operations.py +103 -0
  69. claude_mpm/utils/agent_filters.py +17 -44
  70. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/METADATA +47 -84
  71. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/RECORD +76 -150
  72. claude_mpm-5.4.14.dist-info/entry_points.txt +5 -0
  73. claude_mpm-5.4.14.dist-info/licenses/LICENSE +94 -0
  74. claude_mpm-5.4.14.dist-info/licenses/LICENSE-FAQ.md +153 -0
  75. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
  76. claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
  77. claude_mpm/agents/BASE_ENGINEER.md +0 -658
  78. claude_mpm/agents/BASE_OPS.md +0 -219
  79. claude_mpm/agents/BASE_PM.md +0 -480
  80. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
  81. claude_mpm/agents/BASE_QA.md +0 -167
  82. claude_mpm/agents/BASE_RESEARCH.md +0 -53
  83. claude_mpm/agents/base_agent.json +0 -31
  84. claude_mpm/agents/base_agent_loader.py +0 -601
  85. claude_mpm/cli/ticket_cli.py +0 -35
  86. claude_mpm/commands/mpm-config-view.md +0 -150
  87. claude_mpm/dashboard/analysis_runner.py +0 -455
  88. claude_mpm/dashboard/index.html +0 -13
  89. claude_mpm/dashboard/open_dashboard.py +0 -66
  90. claude_mpm/dashboard/static/css/activity.css +0 -1958
  91. claude_mpm/dashboard/static/css/connection-status.css +0 -370
  92. claude_mpm/dashboard/static/css/dashboard.css +0 -4701
  93. claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
  94. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
  95. claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
  96. claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
  97. claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
  98. claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
  99. claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
  100. claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
  101. claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
  102. claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
  103. claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
  104. claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
  105. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
  106. claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
  107. claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
  108. claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
  109. claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
  110. claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
  111. claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
  112. claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
  113. claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
  114. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
  115. claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
  116. claude_mpm/dashboard/static/js/connection-manager.js +0 -536
  117. claude_mpm/dashboard/static/js/dashboard.js +0 -1914
  118. claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
  119. claude_mpm/dashboard/static/js/socket-client.js +0 -1474
  120. claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
  121. claude_mpm/dashboard/static/socket.io.min.js +0 -7
  122. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
  123. claude_mpm/dashboard/templates/code_simple.html +0 -153
  124. claude_mpm/dashboard/templates/index.html +0 -606
  125. claude_mpm/dashboard/test_dashboard.html +0 -372
  126. claude_mpm/scripts/mcp_server.py +0 -75
  127. claude_mpm/scripts/mcp_wrapper.py +0 -39
  128. claude_mpm/services/mcp_gateway/__init__.py +0 -159
  129. claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
  130. claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
  131. claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
  132. claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
  133. claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
  134. claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
  135. claude_mpm/services/mcp_gateway/core/base.py +0 -312
  136. claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
  137. claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
  138. claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
  139. claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
  140. claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
  141. claude_mpm/services/mcp_gateway/main.py +0 -589
  142. claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
  143. claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
  144. claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
  145. claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
  146. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
  147. claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
  148. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
  149. claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
  150. claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
  151. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
  152. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
  153. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
  154. claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
  155. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
  156. claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
  157. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
  158. claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
  159. claude_mpm-5.1.9.dist-info/entry_points.txt +0 -10
  160. claude_mpm-5.1.9.dist-info/licenses/LICENSE +0 -21
  161. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/WHEEL +0 -0
  162. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/top_level.txt +0 -0
@@ -1,372 +0,0 @@
1
- """
2
- STDIO Communication Handler for MCP
3
- ====================================
4
-
5
- Handles stdio-based communication for the MCP server.
6
- Manages JSON-RPC message exchange over stdin/stdout.
7
-
8
- Part of ISS-0035: MCP Server Implementation - Core Server and Tool Registry
9
- """
10
-
11
- import asyncio
12
- import json
13
- import sys
14
- from typing import TYPE_CHECKING, Any, Dict, Optional
15
-
16
- from claude_mpm.services.mcp_gateway.core.base import BaseMCPService
17
- from claude_mpm.services.mcp_gateway.core.interfaces import IMCPCommunication
18
-
19
- if TYPE_CHECKING:
20
- from asyncio import StreamReader, StreamWriter
21
-
22
-
23
- class StdioHandler(BaseMCPService, IMCPCommunication):
24
- """
25
- STDIO-based communication handler for MCP.
26
-
27
- WHY: The MCP protocol uses stdio (stdin/stdout) for communication between
28
- Claude Code and MCP servers. This handler manages the low-level
29
- message exchange, ensuring proper JSON-RPC formatting and error handling.
30
-
31
- DESIGN DECISIONS:
32
- - Use asyncio streams for non-blocking I/O
33
- - Implement message framing with Content-Length headers (LSP-style)
34
- - Handle both notification and request/response patterns
35
- - Provide robust error recovery and logging
36
- """
37
-
38
- def __init__(self):
39
- """Initialize the STDIO handler."""
40
- super().__init__("StdioHandler")
41
-
42
- # Async streams
43
- self._reader: Optional[StreamReader] = None
44
- self._writer: Optional[StreamWriter] = None
45
-
46
- # Connection state
47
- self._connected = False
48
-
49
- # Message buffer for partial reads
50
- self._buffer = b""
51
-
52
- # Metrics
53
- self._metrics = {
54
- "messages_sent": 0,
55
- "messages_received": 0,
56
- "errors": 0,
57
- "bytes_sent": 0,
58
- "bytes_received": 0,
59
- }
60
-
61
- async def _do_initialize(self) -> bool:
62
- """
63
- Initialize the STDIO handler.
64
-
65
- Returns:
66
- True if initialization successful
67
- """
68
- try:
69
- self.log_info("Initializing STDIO handler")
70
-
71
- # Create async streams for stdin/stdout
72
- loop = asyncio.get_event_loop()
73
-
74
- # For stdin
75
- self._reader = asyncio.StreamReader()
76
- stdin_protocol = asyncio.StreamReaderProtocol(self._reader)
77
- await loop.connect_read_pipe(lambda: stdin_protocol, sys.stdin)
78
-
79
- # For stdout (we'll write directly to sys.stdout)
80
- # Note: stdout doesn't need async handling for writes
81
-
82
- self._connected = True
83
- self.log_info("STDIO handler initialized")
84
- return True
85
-
86
- except Exception as e:
87
- self.log_error(f"Failed to initialize STDIO handler: {e}")
88
- return False
89
-
90
- async def _do_shutdown(self) -> None:
91
- """Shutdown the STDIO handler."""
92
- self.log_info("Shutting down STDIO handler")
93
-
94
- self._connected = False
95
-
96
- # Close streams if needed
97
- if self._reader:
98
- self._reader = None
99
-
100
- self.log_info("STDIO handler shutdown complete")
101
-
102
- async def send_message(self, message: Dict[str, Any]) -> None:
103
- """
104
- Send a message to the MCP client via stdout.
105
-
106
- Uses Content-Length header for message framing (LSP-style).
107
-
108
- Args:
109
- message: Message to send
110
- """
111
- try:
112
- if not self._connected:
113
- raise RuntimeError("STDIO handler not connected")
114
-
115
- # Convert message to JSON
116
- json_str = json.dumps(message, separators=(",", ":"))
117
- json_bytes = json_str.encode("utf-8")
118
-
119
- # Create Content-Length header
120
- content_length = len(json_bytes)
121
- header = f"Content-Length: {content_length}\r\n\r\n"
122
- header_bytes = header.encode("ascii")
123
-
124
- # Write header and content to stdout
125
- sys.stdout.buffer.write(header_bytes)
126
- sys.stdout.buffer.write(json_bytes)
127
- sys.stdout.buffer.flush()
128
-
129
- # Update metrics
130
- self._metrics["messages_sent"] += 1
131
- self._metrics["bytes_sent"] += len(header_bytes) + len(json_bytes)
132
-
133
- self.log_debug(
134
- f"Sent message: {message.get('method', message.get('id', 'unknown'))}"
135
- )
136
-
137
- except Exception as e:
138
- self.log_error(f"Error sending message: {e}")
139
- self._metrics["errors"] += 1
140
- raise
141
-
142
- async def receive_message(self) -> Optional[Dict[str, Any]]:
143
- """
144
- Receive a message from the MCP client via stdin.
145
-
146
- Handles Content-Length based message framing.
147
-
148
- Returns:
149
- Received message or None if no message available
150
- """
151
- try:
152
- if not self._connected or not self._reader:
153
- return None
154
-
155
- # Read header to get content length
156
- headers = {}
157
- while True:
158
- line_bytes = await self._reader.readline()
159
- if not line_bytes:
160
- # EOF reached
161
- self._connected = False
162
- return None
163
-
164
- line = line_bytes.decode("utf-8").rstrip("\r\n")
165
-
166
- if not line:
167
- # Empty line indicates end of headers
168
- break
169
-
170
- # Parse header
171
- if ":" in line:
172
- key, value = line.split(":", 1)
173
- headers[key.strip()] = value.strip()
174
-
175
- # Get content length
176
- content_length = headers.get("Content-Length")
177
- if not content_length:
178
- self.log_warning("No Content-Length header found")
179
- return None
180
-
181
- content_length = int(content_length)
182
-
183
- # Read content
184
- content_bytes = await self._reader.readexactly(content_length)
185
-
186
- # Parse JSON
187
- message = json.loads(content_bytes.decode("utf-8"))
188
-
189
- # Update metrics
190
- self._metrics["messages_received"] += 1
191
- self._metrics["bytes_received"] += len(line_bytes) + content_length
192
-
193
- self.log_debug(
194
- f"Received message: {message.get('method', message.get('id', 'unknown'))}"
195
- )
196
-
197
- return message
198
-
199
- except asyncio.IncompleteReadError:
200
- self.log_warning("Incomplete read - client may have disconnected")
201
- self._connected = False
202
- return None
203
- except json.JSONDecodeError as e:
204
- self.log_error(f"Invalid JSON received: {e}")
205
- self._metrics["errors"] += 1
206
- return None
207
- except Exception as e:
208
- self.log_error(f"Error receiving message: {e}")
209
- self._metrics["errors"] += 1
210
- return None
211
-
212
- async def send_response(self, request_id: str, result: Any) -> None:
213
- """
214
- Send a response to a request.
215
-
216
- Args:
217
- request_id: ID of the request being responded to
218
- result: Result data
219
- """
220
- response = {"jsonrpc": "2.0", "id": request_id, "result": result}
221
- await self.send_message(response)
222
-
223
- async def send_error(self, request_id: str, error: str, code: int = -1) -> None:
224
- """
225
- Send an error response.
226
-
227
- Args:
228
- request_id: ID of the request that caused the error
229
- error: Error message
230
- code: Error code (default -1 for generic error)
231
- """
232
- response = {
233
- "jsonrpc": "2.0",
234
- "id": request_id,
235
- "error": {"code": code, "message": error},
236
- }
237
- await self.send_message(response)
238
-
239
- async def send_notification(
240
- self, method: str, params: Optional[Dict[str, Any]] = None
241
- ) -> None:
242
- """
243
- Send a notification (no response expected).
244
-
245
- Args:
246
- method: Notification method
247
- params: Optional parameters
248
- """
249
- notification = {"jsonrpc": "2.0", "method": method}
250
- if params:
251
- notification["params"] = params
252
-
253
- await self.send_message(notification)
254
-
255
- def is_connected(self) -> bool:
256
- """
257
- Check if communication channel is connected.
258
-
259
- Returns:
260
- True if connected
261
- """
262
- return self._connected
263
-
264
- def get_metrics(self) -> Dict[str, Any]:
265
- """
266
- Get communication metrics.
267
-
268
- Returns:
269
- Metrics dictionary
270
- """
271
- return self._metrics.copy()
272
-
273
-
274
- class AlternativeStdioHandler(StdioHandler):
275
- """
276
- Alternative STDIO handler using direct sys.stdin/stdout.
277
-
278
- This implementation doesn't use asyncio streams but instead
279
- reads directly from sys.stdin in a blocking manner, which
280
- can be simpler for some use cases.
281
-
282
- WHY: Some MCP implementations may work better with simpler
283
- blocking I/O, especially when running as a subprocess.
284
- """
285
-
286
- async def _do_initialize(self) -> bool:
287
- """
288
- Initialize the alternative STDIO handler.
289
-
290
- Returns:
291
- True if initialization successful
292
- """
293
- try:
294
- self.log_info("Initializing alternative STDIO handler")
295
- self._connected = True
296
- self.log_info("Alternative STDIO handler initialized")
297
- return True
298
-
299
- except Exception as e:
300
- self.log_error(f"Failed to initialize alternative STDIO handler: {e}")
301
- return False
302
-
303
- async def receive_message(self) -> Optional[Dict[str, Any]]:
304
- """
305
- Receive a message using blocking I/O with asyncio executor.
306
-
307
- Returns:
308
- Received message or None if no message available
309
- """
310
- try:
311
- if not self._connected:
312
- return None
313
-
314
- # Run blocking I/O in executor
315
- loop = asyncio.get_event_loop()
316
- message = await loop.run_in_executor(None, self._blocking_receive)
317
-
318
- if message:
319
- self._metrics["messages_received"] += 1
320
- self.log_debug(
321
- f"Received message: {message.get('method', message.get('id', 'unknown'))}"
322
- )
323
-
324
- return message
325
-
326
- except Exception as e:
327
- self.log_error(f"Error receiving message: {e}")
328
- self._metrics["errors"] += 1
329
- return None
330
-
331
- def _blocking_receive(self) -> Optional[Dict[str, Any]]:
332
- """
333
- Blocking receive implementation.
334
-
335
- Returns:
336
- Received message or None
337
- """
338
- try:
339
- # Read headers
340
- headers = {}
341
- while True:
342
- line = sys.stdin.readline()
343
- if not line:
344
- # EOF
345
- self._connected = False
346
- return None
347
-
348
- line = line.rstrip("\r\n")
349
- if not line:
350
- # End of headers
351
- break
352
-
353
- if ":" in line:
354
- key, value = line.split(":", 1)
355
- headers[key.strip()] = value.strip()
356
-
357
- # Get content length
358
- content_length = headers.get("Content-Length")
359
- if not content_length:
360
- return None
361
-
362
- content_length = int(content_length)
363
-
364
- # Read content
365
- content = sys.stdin.read(content_length)
366
-
367
- # Parse JSON
368
- return json.loads(content)
369
-
370
- except Exception as e:
371
- self.log_error(f"Error in blocking receive: {e}")
372
- return None