claude-mpm 4.4.4__py3-none-any.whl → 4.4.5__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +73 -21
- claude_mpm/services/mcp_config_manager.py +292 -45
- {claude_mpm-4.4.4.dist-info → claude_mpm-4.4.5.dist-info}/METADATA +30 -16
- {claude_mpm-4.4.4.dist-info → claude_mpm-4.4.5.dist-info}/RECORD +9 -9
- {claude_mpm-4.4.4.dist-info → claude_mpm-4.4.5.dist-info}/WHEEL +0 -0
- {claude_mpm-4.4.4.dist-info → claude_mpm-4.4.5.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.4.4.dist-info → claude_mpm-4.4.5.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.4.4.dist-info → claude_mpm-4.4.5.dist-info}/top_level.txt +0 -0
claude_mpm/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.4.
|
1
|
+
4.4.5
|
@@ -21,30 +21,35 @@ class MCPServicesCheck(BaseDiagnosticCheck):
|
|
21
21
|
MCP_SERVICES = {
|
22
22
|
"mcp-vector-search": {
|
23
23
|
"package": "mcp-vector-search",
|
24
|
-
"command": ["mcp-vector-search", "--
|
24
|
+
"command": ["mcp-vector-search", "--version"], # Use --version for proper check
|
25
25
|
"description": "Vector search for semantic code navigation",
|
26
26
|
"check_health": True,
|
27
27
|
"health_command": ["mcp-vector-search", "--version"],
|
28
|
+
"pipx_run_command": ["pipx", "run", "mcp-vector-search", "--version"],
|
28
29
|
},
|
29
30
|
"mcp-browser": {
|
30
31
|
"package": "mcp-browser",
|
31
|
-
"command": ["mcp-browser", "--
|
32
|
+
"command": ["mcp-browser", "--version"], # Use --version for proper check
|
32
33
|
"description": "Browser automation and web interaction",
|
33
34
|
"check_health": True,
|
34
35
|
"health_command": ["mcp-browser", "--version"],
|
36
|
+
"pipx_run_command": ["pipx", "run", "mcp-browser", "--version"],
|
35
37
|
},
|
36
38
|
"mcp-ticketer": {
|
37
39
|
"package": "mcp-ticketer",
|
38
|
-
"command": ["mcp-ticketer", "--
|
40
|
+
"command": ["mcp-ticketer", "--version"], # Use --version for proper check
|
39
41
|
"description": "Ticket and task management",
|
40
42
|
"check_health": True,
|
41
43
|
"health_command": ["mcp-ticketer", "--version"],
|
44
|
+
"pipx_run_command": ["pipx", "run", "mcp-ticketer", "--version"],
|
42
45
|
},
|
43
46
|
"kuzu-memory": {
|
44
47
|
"package": "kuzu-memory",
|
45
|
-
"command": ["kuzu-memory", "--
|
48
|
+
"command": ["kuzu-memory", "--version"], # Use --version for proper check
|
46
49
|
"description": "Graph-based memory system",
|
47
|
-
"check_health":
|
50
|
+
"check_health": True, # v1.1.0+ has version command
|
51
|
+
"health_command": ["kuzu-memory", "--version"],
|
52
|
+
"pipx_run_command": ["pipx", "run", "kuzu-memory", "--version"],
|
48
53
|
},
|
49
54
|
}
|
50
55
|
|
@@ -143,6 +148,13 @@ class MCPServicesCheck(BaseDiagnosticCheck):
|
|
143
148
|
if command_path:
|
144
149
|
details["command_path"] = command_path
|
145
150
|
|
151
|
+
# If not directly accessible, try pipx run command
|
152
|
+
if not accessible and "pipx_run_command" in config:
|
153
|
+
if self._verify_command_works(config["pipx_run_command"]):
|
154
|
+
accessible = True
|
155
|
+
details["accessible_via_pipx_run"] = True
|
156
|
+
details["pipx_run_available"] = True
|
157
|
+
|
146
158
|
# Check for installation in various locations
|
147
159
|
if not pipx_installed and not accessible:
|
148
160
|
# Try common installation locations
|
@@ -157,11 +169,19 @@ class MCPServicesCheck(BaseDiagnosticCheck):
|
|
157
169
|
|
158
170
|
# Check service health/version if accessible
|
159
171
|
if accessible and config.get("check_health"):
|
160
|
-
version
|
161
|
-
|
162
|
-
)
|
163
|
-
|
164
|
-
|
172
|
+
# Try different version commands in order of preference
|
173
|
+
version_commands = []
|
174
|
+
if details.get("accessible_via_pipx_run") and "pipx_run_command" in config:
|
175
|
+
version_commands.append(config["pipx_run_command"])
|
176
|
+
if "health_command" in config:
|
177
|
+
version_commands.append(config["health_command"])
|
178
|
+
version_commands.append(config["command"])
|
179
|
+
|
180
|
+
for cmd in version_commands:
|
181
|
+
version = self._get_service_version(cmd)
|
182
|
+
if version:
|
183
|
+
details["version"] = version
|
184
|
+
break
|
165
185
|
|
166
186
|
# Determine status
|
167
187
|
if not (pipx_installed or accessible):
|
@@ -175,6 +195,14 @@ class MCPServicesCheck(BaseDiagnosticCheck):
|
|
175
195
|
)
|
176
196
|
|
177
197
|
if pipx_installed and not accessible:
|
198
|
+
# Check if pipx run works
|
199
|
+
if details.get("pipx_run_available"):
|
200
|
+
return DiagnosticResult(
|
201
|
+
category=f"MCP Service: {service_name}",
|
202
|
+
status=DiagnosticStatus.OK,
|
203
|
+
message="Installed via pipx (use 'pipx run' to execute)",
|
204
|
+
details=details,
|
205
|
+
)
|
178
206
|
return DiagnosticResult(
|
179
207
|
category=f"MCP Service: {service_name}",
|
180
208
|
status=DiagnosticStatus.WARNING,
|
@@ -247,29 +275,53 @@ class MCPServicesCheck(BaseDiagnosticCheck):
|
|
247
275
|
|
248
276
|
if result.returncode == 0:
|
249
277
|
path = result.stdout.strip()
|
250
|
-
|
278
|
+
# Verify the command actually works with --version
|
279
|
+
if self._verify_command_works(command):
|
280
|
+
return True, path
|
281
|
+
return False, path
|
251
282
|
except (subprocess.SubprocessError, FileNotFoundError):
|
252
283
|
pass
|
253
284
|
|
254
|
-
# Try direct execution
|
285
|
+
# Try direct execution with --version
|
286
|
+
if self._verify_command_works(command):
|
287
|
+
return True, None
|
288
|
+
|
289
|
+
return False, None
|
290
|
+
|
291
|
+
def _verify_command_works(self, command: List[str]) -> bool:
|
292
|
+
"""Verify a command actually works by checking its --version output."""
|
255
293
|
try:
|
256
294
|
result = subprocess.run(
|
257
295
|
command,
|
258
296
|
capture_output=True,
|
259
297
|
text=True,
|
260
|
-
timeout=
|
298
|
+
timeout=5,
|
261
299
|
check=False,
|
262
300
|
)
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
301
|
+
|
302
|
+
# Check for successful execution or version output
|
303
|
+
# Don't accept error messages containing "help" or "usage" as success
|
304
|
+
if result.returncode == 0:
|
305
|
+
# Look for actual version information
|
306
|
+
output = (result.stdout + result.stderr).lower()
|
307
|
+
# Check for version indicators
|
308
|
+
if any(keyword in output for keyword in ["version", "v1.", "v0.", "1.", "0."]):
|
309
|
+
# But reject if it's an error message
|
310
|
+
if not any(error in output for error in ["error", "not found", "no such", "command not found"]):
|
311
|
+
return True
|
312
|
+
|
313
|
+
# For some tools, non-zero return code is OK if version is shown
|
314
|
+
elif "--version" in command or "--help" in command:
|
315
|
+
output = (result.stdout + result.stderr).lower()
|
316
|
+
# Must have version info and no error indicators
|
317
|
+
if ("version" in output or "v1." in output or "v0." in output):
|
318
|
+
if not any(error in output for error in ["error", "not found", "no such", "command not found", "traceback"]):
|
319
|
+
return True
|
320
|
+
|
321
|
+
except (subprocess.SubprocessError, FileNotFoundError, OSError):
|
270
322
|
pass
|
271
323
|
|
272
|
-
return False
|
324
|
+
return False
|
273
325
|
|
274
326
|
def _check_alternative_installations(
|
275
327
|
self, service_name: str
|
@@ -11,6 +11,7 @@ MCP service installations.
|
|
11
11
|
|
12
12
|
import json
|
13
13
|
import subprocess
|
14
|
+
import sys
|
14
15
|
from datetime import datetime, timezone
|
15
16
|
from enum import Enum
|
16
17
|
from pathlib import Path
|
@@ -194,56 +195,161 @@ class MCPConfigManager:
|
|
194
195
|
"""
|
195
196
|
Generate configuration for a specific MCP service.
|
196
197
|
|
198
|
+
Prefers 'pipx run' or 'uvx' commands over direct execution for better isolation.
|
199
|
+
|
197
200
|
Args:
|
198
201
|
service_name: Name of the MCP service
|
199
202
|
|
200
203
|
Returns:
|
201
204
|
Service configuration dict or None if service not found
|
202
205
|
"""
|
203
|
-
|
204
|
-
if not service_path:
|
205
|
-
return None
|
206
|
+
import shutil
|
206
207
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
208
|
+
# Check for pipx run first (preferred for isolation)
|
209
|
+
use_pipx_run = False
|
210
|
+
use_uvx = False
|
211
|
+
|
212
|
+
# Try pipx run test
|
213
|
+
if shutil.which("pipx"):
|
214
|
+
try:
|
215
|
+
result = subprocess.run(
|
216
|
+
["pipx", "run", service_name, "--version"],
|
217
|
+
capture_output=True,
|
218
|
+
text=True,
|
219
|
+
timeout=5,
|
220
|
+
check=False,
|
221
|
+
)
|
222
|
+
if result.returncode == 0 or "version" in result.stdout.lower():
|
223
|
+
use_pipx_run = True
|
224
|
+
self.logger.debug(f"Will use 'pipx run' for {service_name}")
|
225
|
+
except:
|
226
|
+
pass
|
227
|
+
|
228
|
+
# Try uvx if pipx run not available
|
229
|
+
if not use_pipx_run and shutil.which("uvx"):
|
230
|
+
try:
|
231
|
+
result = subprocess.run(
|
232
|
+
["uvx", service_name, "--version"],
|
233
|
+
capture_output=True,
|
234
|
+
text=True,
|
235
|
+
timeout=5,
|
236
|
+
check=False,
|
237
|
+
)
|
238
|
+
if result.returncode == 0 or "version" in result.stdout.lower():
|
239
|
+
use_uvx = True
|
240
|
+
self.logger.debug(f"Will use 'uvx' for {service_name}")
|
241
|
+
except:
|
242
|
+
pass
|
243
|
+
|
244
|
+
# If neither work, try to find direct path
|
245
|
+
service_path = None
|
246
|
+
if not use_pipx_run and not use_uvx:
|
247
|
+
service_path = self.detect_service_path(service_name)
|
248
|
+
if not service_path:
|
249
|
+
return None
|
250
|
+
|
251
|
+
# Build configuration
|
252
|
+
config = {"type": "stdio"}
|
211
253
|
|
212
254
|
# Service-specific configurations
|
213
255
|
if service_name == "mcp-vector-search":
|
214
|
-
|
215
|
-
"
|
216
|
-
"
|
217
|
-
|
218
|
-
|
256
|
+
if use_pipx_run:
|
257
|
+
config["command"] = "pipx"
|
258
|
+
config["args"] = [
|
259
|
+
"run",
|
260
|
+
"mcp-vector-search",
|
261
|
+
"-m",
|
262
|
+
"mcp_vector_search.mcp.server",
|
263
|
+
str(self.project_root),
|
264
|
+
]
|
265
|
+
elif use_uvx:
|
266
|
+
config["command"] = "uvx"
|
267
|
+
config["args"] = [
|
268
|
+
"mcp-vector-search",
|
269
|
+
"-m",
|
270
|
+
"mcp_vector_search.mcp.server",
|
271
|
+
str(self.project_root),
|
272
|
+
]
|
273
|
+
else:
|
274
|
+
config["command"] = service_path
|
275
|
+
config["args"] = [
|
276
|
+
"-m",
|
277
|
+
"mcp_vector_search.mcp.server",
|
278
|
+
str(self.project_root),
|
279
|
+
]
|
219
280
|
config["env"] = {}
|
281
|
+
|
220
282
|
elif service_name == "mcp-browser":
|
221
|
-
|
283
|
+
if use_pipx_run:
|
284
|
+
config["command"] = "pipx"
|
285
|
+
config["args"] = ["run", "mcp-browser", "mcp"]
|
286
|
+
elif use_uvx:
|
287
|
+
config["command"] = "uvx"
|
288
|
+
config["args"] = ["mcp-browser", "mcp"]
|
289
|
+
else:
|
290
|
+
config["command"] = service_path
|
291
|
+
config["args"] = ["mcp"]
|
222
292
|
config["env"] = {"MCP_BROWSER_HOME": str(Path.home() / ".mcp-browser")}
|
293
|
+
|
223
294
|
elif service_name == "mcp-ticketer":
|
224
|
-
|
295
|
+
if use_pipx_run:
|
296
|
+
config["command"] = "pipx"
|
297
|
+
config["args"] = ["run", "mcp-ticketer", "mcp"]
|
298
|
+
elif use_uvx:
|
299
|
+
config["command"] = "uvx"
|
300
|
+
config["args"] = ["mcp-ticketer", "mcp"]
|
301
|
+
else:
|
302
|
+
config["command"] = service_path
|
303
|
+
config["args"] = ["mcp"]
|
304
|
+
|
225
305
|
elif service_name == "kuzu-memory":
|
226
|
-
#
|
227
|
-
|
228
|
-
|
306
|
+
# Determine kuzu-memory command version
|
307
|
+
kuzu_args = []
|
308
|
+
test_cmd = None
|
309
|
+
|
310
|
+
if use_pipx_run:
|
311
|
+
test_cmd = ["pipx", "run", "kuzu-memory", "--help"]
|
312
|
+
elif use_uvx:
|
313
|
+
test_cmd = ["uvx", "kuzu-memory", "--help"]
|
314
|
+
elif service_path:
|
315
|
+
test_cmd = [service_path, "--help"]
|
316
|
+
|
317
|
+
if test_cmd:
|
318
|
+
try:
|
319
|
+
result = subprocess.run(
|
320
|
+
test_cmd, capture_output=True, text=True, timeout=10, check=False
|
321
|
+
)
|
322
|
+
if "claude" in result.stdout:
|
323
|
+
# v1.1.0+ with claude command
|
324
|
+
kuzu_args = ["claude", "mcp-server"]
|
325
|
+
else:
|
326
|
+
# v1.0.0 with serve command
|
327
|
+
kuzu_args = ["serve"]
|
328
|
+
except:
|
329
|
+
# Default to newer version command
|
330
|
+
kuzu_args = ["claude", "mcp-server"]
|
331
|
+
|
332
|
+
if use_pipx_run:
|
333
|
+
config["command"] = "pipx"
|
334
|
+
config["args"] = ["run", "kuzu-memory"] + kuzu_args
|
335
|
+
elif use_uvx:
|
336
|
+
config["command"] = "uvx"
|
337
|
+
config["args"] = ["kuzu-memory"] + kuzu_args
|
338
|
+
else:
|
339
|
+
config["command"] = service_path
|
340
|
+
config["args"] = kuzu_args
|
229
341
|
|
230
|
-
try:
|
231
|
-
result = subprocess.run(
|
232
|
-
[service_path, "--help"], capture_output=True, text=True, timeout=10, check=False
|
233
|
-
)
|
234
|
-
if "claude" in result.stdout:
|
235
|
-
# v1.1.0+ with claude command
|
236
|
-
config["args"] = ["claude", "mcp-server"]
|
237
|
-
else:
|
238
|
-
# v1.0.0 with serve command
|
239
|
-
config["args"] = ["serve"]
|
240
|
-
except:
|
241
|
-
# Default to older version command
|
242
|
-
config["args"] = ["serve"]
|
243
|
-
# kuzu-memory works with project-specific databases, no custom path needed
|
244
342
|
else:
|
245
343
|
# Generic config for unknown services
|
246
|
-
|
344
|
+
if use_pipx_run:
|
345
|
+
config["command"] = "pipx"
|
346
|
+
config["args"] = ["run", service_name]
|
347
|
+
elif use_uvx:
|
348
|
+
config["command"] = "uvx"
|
349
|
+
config["args"] = [service_name]
|
350
|
+
else:
|
351
|
+
config["command"] = service_path
|
352
|
+
config["args"] = []
|
247
353
|
|
248
354
|
return config
|
249
355
|
|
@@ -464,7 +570,7 @@ class MCPConfigManager:
|
|
464
570
|
|
465
571
|
def install_missing_services(self) -> Tuple[bool, str]:
|
466
572
|
"""
|
467
|
-
Install missing MCP services via pipx.
|
573
|
+
Install missing MCP services via pipx with verification and fallbacks.
|
468
574
|
|
469
575
|
Returns:
|
470
576
|
Tuple of (success, message)
|
@@ -481,22 +587,163 @@ class MCPConfigManager:
|
|
481
587
|
failed = []
|
482
588
|
|
483
589
|
for service_name in missing:
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
check=True,
|
491
|
-
)
|
492
|
-
installed.append(service_name)
|
493
|
-
self.logger.info(f"Successfully installed {service_name}")
|
494
|
-
except subprocess.CalledProcessError as e:
|
590
|
+
# Try pipx install first
|
591
|
+
success, method = self._install_service_with_fallback(service_name)
|
592
|
+
if success:
|
593
|
+
installed.append(f"{service_name} ({method})")
|
594
|
+
self.logger.info(f"Successfully installed {service_name} via {method}")
|
595
|
+
else:
|
495
596
|
failed.append(service_name)
|
496
|
-
self.logger.error(f"Failed to install {service_name}
|
597
|
+
self.logger.error(f"Failed to install {service_name}")
|
497
598
|
|
498
599
|
if failed:
|
499
600
|
return False, f"Failed to install: {', '.join(failed)}"
|
500
601
|
if installed:
|
501
602
|
return True, f"Successfully installed: {', '.join(installed)}"
|
502
603
|
return True, "No services needed installation"
|
604
|
+
|
605
|
+
def _install_service_with_fallback(self, service_name: str) -> Tuple[bool, str]:
|
606
|
+
"""
|
607
|
+
Install a service with multiple fallback methods.
|
608
|
+
|
609
|
+
Returns:
|
610
|
+
Tuple of (success, installation_method)
|
611
|
+
"""
|
612
|
+
import shutil
|
613
|
+
|
614
|
+
# Method 1: Try pipx install
|
615
|
+
if shutil.which("pipx"):
|
616
|
+
try:
|
617
|
+
self.logger.debug(f"Attempting to install {service_name} via pipx...")
|
618
|
+
result = subprocess.run(
|
619
|
+
["pipx", "install", service_name],
|
620
|
+
capture_output=True,
|
621
|
+
text=True,
|
622
|
+
timeout=120, # 2 minute timeout
|
623
|
+
check=False,
|
624
|
+
)
|
625
|
+
|
626
|
+
if result.returncode == 0:
|
627
|
+
# Verify installation worked
|
628
|
+
if self._verify_service_installed(service_name, "pipx"):
|
629
|
+
return True, "pipx"
|
630
|
+
|
631
|
+
self.logger.warning(
|
632
|
+
f"pipx install succeeded but verification failed for {service_name}"
|
633
|
+
)
|
634
|
+
else:
|
635
|
+
self.logger.debug(
|
636
|
+
f"pipx install failed: {result.stderr}"
|
637
|
+
)
|
638
|
+
except subprocess.TimeoutExpired:
|
639
|
+
self.logger.warning(f"pipx install timed out for {service_name}")
|
640
|
+
except Exception as e:
|
641
|
+
self.logger.debug(f"pipx install error: {e}")
|
642
|
+
|
643
|
+
# Method 2: Try uvx (if available)
|
644
|
+
if shutil.which("uvx"):
|
645
|
+
try:
|
646
|
+
self.logger.debug(f"Attempting to install {service_name} via uvx...")
|
647
|
+
result = subprocess.run(
|
648
|
+
["uvx", "install", service_name],
|
649
|
+
capture_output=True,
|
650
|
+
text=True,
|
651
|
+
timeout=120,
|
652
|
+
check=False,
|
653
|
+
)
|
654
|
+
|
655
|
+
if result.returncode == 0:
|
656
|
+
if self._verify_service_installed(service_name, "uvx"):
|
657
|
+
return True, "uvx"
|
658
|
+
except Exception as e:
|
659
|
+
self.logger.debug(f"uvx install error: {e}")
|
660
|
+
|
661
|
+
# Method 3: Try pip install --user
|
662
|
+
try:
|
663
|
+
self.logger.debug(f"Attempting to install {service_name} via pip --user...")
|
664
|
+
result = subprocess.run(
|
665
|
+
[sys.executable, "-m", "pip", "install", "--user", service_name],
|
666
|
+
capture_output=True,
|
667
|
+
text=True,
|
668
|
+
timeout=120,
|
669
|
+
check=False,
|
670
|
+
)
|
671
|
+
|
672
|
+
if result.returncode == 0:
|
673
|
+
if self._verify_service_installed(service_name, "pip"):
|
674
|
+
return True, "pip --user"
|
675
|
+
|
676
|
+
self.logger.warning(
|
677
|
+
f"pip install succeeded but verification failed for {service_name}"
|
678
|
+
)
|
679
|
+
except Exception as e:
|
680
|
+
self.logger.debug(f"pip install error: {e}")
|
681
|
+
|
682
|
+
return False, "none"
|
683
|
+
|
684
|
+
def _verify_service_installed(self, service_name: str, method: str) -> bool:
|
685
|
+
"""
|
686
|
+
Verify that a service was successfully installed and is functional.
|
687
|
+
|
688
|
+
Args:
|
689
|
+
service_name: Name of the service
|
690
|
+
method: Installation method used
|
691
|
+
|
692
|
+
Returns:
|
693
|
+
True if service is installed and functional
|
694
|
+
"""
|
695
|
+
import time
|
696
|
+
|
697
|
+
# Give the installation a moment to settle
|
698
|
+
time.sleep(1)
|
699
|
+
|
700
|
+
# Check if we can find the service
|
701
|
+
service_path = self.detect_service_path(service_name)
|
702
|
+
if not service_path:
|
703
|
+
# Try pipx run as fallback for pipx installations
|
704
|
+
if method == "pipx":
|
705
|
+
try:
|
706
|
+
result = subprocess.run(
|
707
|
+
["pipx", "run", service_name, "--version"],
|
708
|
+
capture_output=True,
|
709
|
+
text=True,
|
710
|
+
timeout=10,
|
711
|
+
check=False,
|
712
|
+
)
|
713
|
+
if result.returncode == 0 or "version" in result.stdout.lower():
|
714
|
+
self.logger.debug(f"{service_name} accessible via 'pipx run'")
|
715
|
+
return True
|
716
|
+
except:
|
717
|
+
pass
|
718
|
+
return False
|
719
|
+
|
720
|
+
# Try to verify it works
|
721
|
+
try:
|
722
|
+
# Different services may need different verification
|
723
|
+
test_commands = [
|
724
|
+
[service_path, "--version"],
|
725
|
+
[service_path, "--help"],
|
726
|
+
]
|
727
|
+
|
728
|
+
for cmd in test_commands:
|
729
|
+
result = subprocess.run(
|
730
|
+
cmd,
|
731
|
+
capture_output=True,
|
732
|
+
text=True,
|
733
|
+
timeout=10,
|
734
|
+
check=False,
|
735
|
+
)
|
736
|
+
|
737
|
+
output = (result.stdout + result.stderr).lower()
|
738
|
+
# Check for signs of success
|
739
|
+
if result.returncode == 0:
|
740
|
+
return True
|
741
|
+
# Some tools return non-zero but still work
|
742
|
+
elif any(indicator in output for indicator in ["version", "usage", "help", service_name.lower()]):
|
743
|
+
# Make sure it's not an error message
|
744
|
+
if not any(error in output for error in ["error", "not found", "traceback", "no such"]):
|
745
|
+
return True
|
746
|
+
except Exception as e:
|
747
|
+
self.logger.debug(f"Verification error for {service_name}: {e}")
|
748
|
+
|
749
|
+
return False
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: claude-mpm
|
3
|
-
Version: 4.4.
|
3
|
+
Version: 4.4.5
|
4
4
|
Summary: Claude Multi-Agent Project Manager - Orchestrate Claude with agent delegation and ticket tracking
|
5
5
|
Author-email: Bob Matsuoka <bob@matsuoka.com>
|
6
6
|
Maintainer: Claude MPM Team
|
@@ -41,11 +41,6 @@ Requires-Dist: python-frontmatter>=1.0.0
|
|
41
41
|
Requires-Dist: mistune>=3.0.0
|
42
42
|
Requires-Dist: tree-sitter>=0.21.0
|
43
43
|
Requires-Dist: ijson>=3.2.0
|
44
|
-
Requires-Dist: kuzu-memory>=1.1.1
|
45
|
-
Requires-Dist: mcp>=0.1.0
|
46
|
-
Requires-Dist: mcp-vector-search>=0.1.0
|
47
|
-
Requires-Dist: mcp-browser>=0.1.0
|
48
|
-
Requires-Dist: mcp-ticketer>=0.1.0
|
49
44
|
Requires-Dist: toml>=0.10.2
|
50
45
|
Requires-Dist: packaging>=21.0
|
51
46
|
Requires-Dist: pydantic>=2.0.0
|
@@ -54,6 +49,12 @@ Requires-Dist: rich>=13.0.0
|
|
54
49
|
Requires-Dist: pyee>=13.0.0
|
55
50
|
Requires-Dist: importlib-resources>=5.0; python_version < "3.9"
|
56
51
|
Requires-Dist: pathspec>=0.11.0
|
52
|
+
Provides-Extra: mcp
|
53
|
+
Requires-Dist: mcp>=0.1.0; extra == "mcp"
|
54
|
+
Requires-Dist: mcp-vector-search>=0.1.0; extra == "mcp"
|
55
|
+
Requires-Dist: mcp-browser>=0.1.0; extra == "mcp"
|
56
|
+
Requires-Dist: mcp-ticketer>=0.1.0; extra == "mcp"
|
57
|
+
Requires-Dist: kuzu-memory>=1.1.1; extra == "mcp"
|
57
58
|
Provides-Extra: dev
|
58
59
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
59
60
|
Requires-Dist: pytest-asyncio; extra == "dev"
|
@@ -157,7 +158,7 @@ A powerful orchestration framework for Claude Code that enables multi-agent work
|
|
157
158
|
- 🧠 **Persistent Knowledge System**: Project-specific kuzu-memory integration for intelligent context retention
|
158
159
|
- 🔄 **Session Management**: Resume previous sessions with `--resume`
|
159
160
|
- 📊 **Real-Time Monitoring**: Live dashboard with `--monitor` flag
|
160
|
-
- 🔌 **
|
161
|
+
- 🔌 **Optional MCP Services**: mcp-vector-search and kuzu-memory with automatic fallback installation
|
161
162
|
- 📁 **Multi-Project Support**: Per-session working directories with persistent knowledge graphs
|
162
163
|
- 🔍 **Git Integration**: View diffs and track changes across projects
|
163
164
|
- 🎯 **Smart Task Orchestration**: PM agent intelligently routes work to specialists
|
@@ -167,22 +168,32 @@ A powerful orchestration framework for Claude Code that enables multi-agent work
|
|
167
168
|
## Quick Installation
|
168
169
|
|
169
170
|
```bash
|
171
|
+
# Basic installation
|
170
172
|
pip install claude-mpm
|
173
|
+
|
174
|
+
# Install with optional MCP services (recommended)
|
175
|
+
pip install "claude-mpm[mcp]"
|
171
176
|
```
|
172
177
|
|
173
178
|
Or with pipx (recommended for isolated installation):
|
174
179
|
```bash
|
175
|
-
#
|
176
|
-
pipx install "claude-mpm[monitor]"
|
177
|
-
|
178
|
-
# Basic installation without monitor
|
180
|
+
# Basic installation
|
179
181
|
pipx install claude-mpm
|
180
182
|
|
183
|
+
# Install with optional MCP services (recommended)
|
184
|
+
pipx install "claude-mpm[mcp]"
|
185
|
+
|
186
|
+
# Install with all features
|
187
|
+
pipx install "claude-mpm[mcp,monitor]"
|
188
|
+
|
181
189
|
# Configure MCP for pipx users:
|
182
190
|
claude-mpm mcp-pipx-config
|
183
191
|
```
|
184
192
|
|
185
|
-
**💡
|
193
|
+
**💡 Optional Dependencies**:
|
194
|
+
- `[mcp]` - Include MCP services (mcp-vector-search, kuzu-memory) as dependencies
|
195
|
+
- `[monitor]` - Full monitoring dashboard with Socket.IO and async web server components
|
196
|
+
- Without optional dependencies, services auto-install on first use via pipx
|
186
197
|
|
187
198
|
**🎉 Pipx Support Now Fully Functional!** Recent improvements ensure complete compatibility:
|
188
199
|
- ✅ Socket.IO daemon script path resolution (fixed)
|
@@ -207,11 +218,14 @@ claude-mpm mcp
|
|
207
218
|
# Run comprehensive health diagnostics
|
208
219
|
claude-mpm doctor
|
209
220
|
|
210
|
-
# Generate detailed diagnostic report
|
221
|
+
# Generate detailed diagnostic report with MCP service analysis
|
211
222
|
claude-mpm doctor --verbose --output-file doctor-report.md
|
212
223
|
|
213
|
-
# Run specific diagnostic checks
|
214
|
-
claude-mpm doctor --checks installation configuration agents
|
224
|
+
# Run specific diagnostic checks including MCP services
|
225
|
+
claude-mpm doctor --checks installation configuration agents mcp
|
226
|
+
|
227
|
+
# Check MCP service status specifically
|
228
|
+
claude-mpm doctor --checks mcp --verbose
|
215
229
|
|
216
230
|
# Manage memory for large conversation histories
|
217
231
|
claude-mpm cleanup-memory
|
@@ -225,7 +239,7 @@ See [QUICKSTART.md](QUICKSTART.md) for complete usage examples.
|
|
225
239
|
Following Phase 3 architectural simplification in v4.4.1, Claude MPM features:
|
226
240
|
|
227
241
|
- **Streamlined Rich Interface**: Removed complex TUI system (~2,500 lines) for cleaner user experience
|
228
|
-
- **
|
242
|
+
- **Optional MCP Services**: mcp-vector-search and kuzu-memory with automatic fallback installation
|
229
243
|
- **Persistent Knowledge System**: Project-specific kuzu-memory databases with intelligent prompt enrichment
|
230
244
|
- **Service-Oriented Architecture**: Simplified five specialized service domains
|
231
245
|
- **Interface-Based Contracts**: All services implement explicit interfaces
|
@@ -1,5 +1,5 @@
|
|
1
1
|
claude_mpm/BUILD_NUMBER,sha256=toytnNjkIKPgQaGwDqQdC1rpNTAdSEc6Vja50d7Ovug,4
|
2
|
-
claude_mpm/VERSION,sha256=
|
2
|
+
claude_mpm/VERSION,sha256=QzI5UiXbP6p_y2Z1w55VG-4c0j2s4tK81yJ4t45IDyg,6
|
3
3
|
claude_mpm/__init__.py,sha256=lyTZAYGH4DTaFGLRNWJKk5Q5oTjzN5I6AXmfVX-Jff0,1512
|
4
4
|
claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
|
5
5
|
claude_mpm/constants.py,sha256=cChN3myrAcF3jC-6DvHnBFTEnwlDk-TAsIXPvUZr_yw,5953
|
@@ -409,7 +409,7 @@ claude_mpm/services/event_aggregator.py,sha256=DDcehIZVpiEDzs9o18gDZyvjMBHCq2H8H
|
|
409
409
|
claude_mpm/services/exceptions.py,sha256=5lVZETr_6-xk0ItH7BTfYUiX5RlckS1e8ah_UalYG9c,26475
|
410
410
|
claude_mpm/services/hook_installer_service.py,sha256=z3kKeriEY1Y9bFesuGlHBxhCtc0Wzd3Zv02k2_rEyGo,19727
|
411
411
|
claude_mpm/services/hook_service.py,sha256=rZnMn_4qxX5g9KAn0IQdoG50WmySNfsTmfG0XHuRHXk,15737
|
412
|
-
claude_mpm/services/mcp_config_manager.py,sha256=
|
412
|
+
claude_mpm/services/mcp_config_manager.py,sha256=jEmgtyElE5zaIfC8r6jD7aKT-iOGaf8Fo-r11RD_tHQ,28013
|
413
413
|
claude_mpm/services/memory_hook_service.py,sha256=pRlTClkRcw30Jhwbha4BC8IMdzKZxF8aWqf52JlntgY,11600
|
414
414
|
claude_mpm/services/monitor_build_service.py,sha256=8gWR9CaqgXdG6-OjOFXGpk28GCcJTlHhojkUYnMCebI,12160
|
415
415
|
claude_mpm/services/port_manager.py,sha256=CYqLh8Ss_-aoYEXV3G6uZkGexpsRK_XTBL0bV4P3tSI,22838
|
@@ -557,7 +557,7 @@ claude_mpm/services/diagnostics/checks/filesystem_check.py,sha256=V5HoHDYlSuoK2l
|
|
557
557
|
claude_mpm/services/diagnostics/checks/installation_check.py,sha256=WoTt15R8Wg-6k2JZFAtmffFuih1AIyCX71QOHEFH-Ro,19562
|
558
558
|
claude_mpm/services/diagnostics/checks/instructions_check.py,sha256=VbgBorl0RpFvxKQ_SC1gibTmGSiXaKSp-vVZt6hbH1g,16290
|
559
559
|
claude_mpm/services/diagnostics/checks/mcp_check.py,sha256=_eM210SIyHwAcWi1AxUeRoessxumpTrSeVdHVJK5ja0,12191
|
560
|
-
claude_mpm/services/diagnostics/checks/mcp_services_check.py,sha256=
|
560
|
+
claude_mpm/services/diagnostics/checks/mcp_services_check.py,sha256=kWrQ_IKWV6z4WYmzZ5g2pGrh9uEYKRQK12yyS9dLj4Q,18461
|
561
561
|
claude_mpm/services/diagnostics/checks/monitor_check.py,sha256=NUx5G1yjHWlukZmwhUz4o8STRWgsQEx01YjIMReNC0A,10096
|
562
562
|
claude_mpm/services/diagnostics/checks/startup_log_check.py,sha256=DrXdml2rHvmhFBdb_sntE3xmwaP_DZIKjdVbCn8Dy7E,12258
|
563
563
|
claude_mpm/services/event_bus/__init__.py,sha256=ETCo4a6puIeyVWAv55uCDjjhzNyUwbVAHEcAVkVapx8,688
|
@@ -770,9 +770,9 @@ claude_mpm/utils/subprocess_utils.py,sha256=D0izRT8anjiUb_JG72zlJR_JAw1cDkb7kalN
|
|
770
770
|
claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
|
771
771
|
claude_mpm/validation/agent_validator.py,sha256=Nm2WmcbCb0EwOG4nFcikc3wVdiiAfjGBBI3YoR6ainQ,20915
|
772
772
|
claude_mpm/validation/frontmatter_validator.py,sha256=u8g4Eyd_9O6ugj7Un47oSGh3kqv4wMkuks2i_CtWRvM,7028
|
773
|
-
claude_mpm-4.4.
|
774
|
-
claude_mpm-4.4.
|
775
|
-
claude_mpm-4.4.
|
776
|
-
claude_mpm-4.4.
|
777
|
-
claude_mpm-4.4.
|
778
|
-
claude_mpm-4.4.
|
773
|
+
claude_mpm-4.4.5.dist-info/licenses/LICENSE,sha256=lpaivOlPuBZW1ds05uQLJJswy8Rp_HMNieJEbFlqvLk,1072
|
774
|
+
claude_mpm-4.4.5.dist-info/METADATA,sha256=VkuECGtrJPRYkQ4lnwvJ6lT2C6QiMxDmdchcuW3gx3E,16999
|
775
|
+
claude_mpm-4.4.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
776
|
+
claude_mpm-4.4.5.dist-info/entry_points.txt,sha256=FDPZgz8JOvD-6iuXY2l9Zbo9zYVRuE4uz4Qr0vLeGOk,471
|
777
|
+
claude_mpm-4.4.5.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
|
778
|
+
claude_mpm-4.4.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|