claude-mpm 4.4.5__py3-none-any.whl → 4.4.7__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.
Files changed (32) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/templates/local_ops_agent.json +273 -0
  3. claude_mpm/cli/__init__.py +21 -0
  4. claude_mpm/cli/commands/mcp_external_commands.py +7 -7
  5. claude_mpm/cli/commands/mcp_install_commands.py +9 -9
  6. claude_mpm/cli/commands/mcp_setup_external.py +6 -6
  7. claude_mpm/cli/commands/verify.py +118 -0
  8. claude_mpm/cli/parsers/base_parser.py +5 -0
  9. claude_mpm/hooks/kuzu_memory_hook.py +4 -2
  10. claude_mpm/services/agents/deployment/agent_deployment.py +10 -6
  11. claude_mpm/services/diagnostics/checks/__init__.py +2 -2
  12. claude_mpm/services/diagnostics/checks/{claude_desktop_check.py → claude_code_check.py} +95 -112
  13. claude_mpm/services/diagnostics/checks/mcp_check.py +6 -6
  14. claude_mpm/services/diagnostics/checks/mcp_services_check.py +29 -6
  15. claude_mpm/services/diagnostics/diagnostic_runner.py +5 -5
  16. claude_mpm/services/diagnostics/doctor_reporter.py +4 -4
  17. claude_mpm/services/mcp_config_manager.py +46 -26
  18. claude_mpm/services/mcp_gateway/core/process_pool.py +11 -8
  19. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +4 -4
  20. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +8 -4
  21. claude_mpm/services/mcp_service_verifier.py +690 -0
  22. claude_mpm/services/project/project_organizer.py +8 -1
  23. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +1 -2
  24. claude_mpm/services/unified/config_strategies/context_strategy.py +1 -3
  25. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +3 -1
  26. claude_mpm/validation/frontmatter_validator.py +1 -1
  27. {claude_mpm-4.4.5.dist-info → claude_mpm-4.4.7.dist-info}/METADATA +20 -5
  28. {claude_mpm-4.4.5.dist-info → claude_mpm-4.4.7.dist-info}/RECORD +32 -29
  29. {claude_mpm-4.4.5.dist-info → claude_mpm-4.4.7.dist-info}/WHEEL +0 -0
  30. {claude_mpm-4.4.5.dist-info → claude_mpm-4.4.7.dist-info}/entry_points.txt +0 -0
  31. {claude_mpm-4.4.5.dist-info → claude_mpm-4.4.7.dist-info}/licenses/LICENSE +0 -0
  32. {claude_mpm-4.4.5.dist-info → claude_mpm-4.4.7.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  """
2
- Check Claude Desktop integration.
2
+ Check Claude Code (CLI) integration.
3
3
 
4
- WHY: Verify that Claude Desktop is installed, properly configured,
4
+ WHY: Verify that Claude Code CLI is installed, properly configured,
5
5
  and integrated with claude-mpm.
6
6
  """
7
7
 
@@ -13,24 +13,24 @@ from ..models import DiagnosticResult, DiagnosticStatus
13
13
  from .base_check import BaseDiagnosticCheck
14
14
 
15
15
 
16
- class ClaudeDesktopCheck(BaseDiagnosticCheck):
17
- """Check Claude Desktop installation and integration."""
16
+ class ClaudeCodeCheck(BaseDiagnosticCheck):
17
+ """Check Claude Code CLI installation and integration."""
18
18
 
19
19
  @property
20
20
  def name(self) -> str:
21
- return "claude_desktop_check"
21
+ return "claude_code_check"
22
22
 
23
23
  @property
24
24
  def category(self) -> str:
25
- return "Claude Desktop"
25
+ return "Claude Code"
26
26
 
27
27
  def run(self) -> DiagnosticResult:
28
- """Run Claude Desktop diagnostics."""
28
+ """Run Claude Code CLI diagnostics."""
29
29
  try:
30
30
  sub_results = []
31
31
  details = {}
32
32
 
33
- # Check if Claude Desktop is installed
33
+ # Check if Claude Code CLI is installed
34
34
  install_result = self._check_installation()
35
35
  sub_results.append(install_result)
36
36
  details["installed"] = install_result.status == DiagnosticStatus.OK
@@ -54,13 +54,13 @@ class ClaudeDesktopCheck(BaseDiagnosticCheck):
54
54
  # Determine overall status
55
55
  if any(r.status == DiagnosticStatus.ERROR for r in sub_results):
56
56
  status = DiagnosticStatus.ERROR
57
- message = "Claude Desktop has critical issues"
57
+ message = "Claude Code CLI has critical issues"
58
58
  elif any(r.status == DiagnosticStatus.WARNING for r in sub_results):
59
59
  status = DiagnosticStatus.WARNING
60
- message = "Claude Desktop needs configuration"
60
+ message = "Claude Code CLI needs configuration"
61
61
  else:
62
62
  status = DiagnosticStatus.OK
63
- message = "Claude Desktop properly configured"
63
+ message = "Claude Code CLI properly configured"
64
64
 
65
65
  return DiagnosticResult(
66
66
  category=self.category,
@@ -74,109 +74,102 @@ class ClaudeDesktopCheck(BaseDiagnosticCheck):
74
74
  return DiagnosticResult(
75
75
  category=self.category,
76
76
  status=DiagnosticStatus.ERROR,
77
- message=f"Claude Desktop check failed: {e!s}",
77
+ message=f"Claude Code CLI check failed: {e!s}",
78
78
  details={"error": str(e)},
79
79
  )
80
80
 
81
81
  def _check_installation(self) -> DiagnosticResult:
82
- """Check if Claude Desktop is installed."""
83
- # Check common installation paths
84
- mac_path = Path("/Applications/Claude.app")
85
- linux_paths = [
86
- Path.home() / ".local/share/applications/claude.desktop",
87
- Path("/usr/share/applications/claude.desktop"),
88
- Path("/opt/Claude"),
89
- ]
90
- windows_paths = [
91
- Path("C:/Program Files/Claude/Claude.exe"),
92
- Path.home() / "AppData/Local/Claude/Claude.exe",
93
- ]
94
-
95
- # Check for Claude process
82
+ """Check if Claude Code CLI is installed."""
83
+ # Check if claude command is available
96
84
  try:
97
85
  result = subprocess.run(
98
- ["pgrep", "-f", "Claude"], capture_output=True, timeout=2, check=False
86
+ ["claude", "--version"],
87
+ capture_output=True,
88
+ timeout=5,
89
+ check=False,
90
+ text=True
99
91
  )
100
92
  if result.returncode == 0:
101
93
  return DiagnosticResult(
102
- category="Claude Desktop Installation",
94
+ category="Claude Code CLI Installation",
103
95
  status=DiagnosticStatus.OK,
104
- message="Claude Desktop is running",
105
- details={"running": True},
96
+ message="Claude Code CLI is installed and accessible",
97
+ details={
98
+ "installed": True,
99
+ "path": "claude",
100
+ "version_output": result.stdout.strip()
101
+ },
106
102
  )
107
103
  except (subprocess.SubprocessError, FileNotFoundError):
108
104
  pass
109
105
 
110
- # Check installation paths
111
- if mac_path.exists():
112
- return DiagnosticResult(
113
- category="Claude Desktop Installation",
114
- status=DiagnosticStatus.OK,
115
- message="Claude Desktop installed (macOS)",
116
- details={"path": str(mac_path), "platform": "macos"},
117
- )
118
-
119
- for path in linux_paths:
120
- if path.exists():
121
- return DiagnosticResult(
122
- category="Claude Desktop Installation",
123
- status=DiagnosticStatus.OK,
124
- message="Claude Desktop installed (Linux)",
125
- details={"path": str(path), "platform": "linux"},
126
- )
106
+ # Check common installation paths
107
+ possible_paths = [
108
+ Path("/usr/local/bin/claude"),
109
+ Path.home() / ".local/bin/claude",
110
+ Path("/opt/homebrew/bin/claude"),
111
+ Path("/usr/bin/claude"),
112
+ ]
127
113
 
128
- for path in windows_paths:
129
- if path.exists():
114
+ for path in possible_paths:
115
+ if path.exists() and path.is_file():
130
116
  return DiagnosticResult(
131
- category="Claude Desktop Installation",
117
+ category="Claude Code CLI Installation",
132
118
  status=DiagnosticStatus.OK,
133
- message="Claude Desktop installed (Windows)",
134
- details={"path": str(path), "platform": "windows"},
119
+ message=f"Claude Code CLI found at {path}",
120
+ details={"installed": True, "path": str(path)},
135
121
  )
136
122
 
137
123
  return DiagnosticResult(
138
- category="Claude Desktop Installation",
139
- status=DiagnosticStatus.WARNING,
140
- message="Claude Desktop not found",
124
+ category="Claude Code CLI Installation",
125
+ status=DiagnosticStatus.ERROR,
126
+ message="Claude Code CLI not found",
141
127
  details={"installed": False},
142
- fix_description="Install Claude Desktop from https://claude.ai/download",
128
+ fix_description="Install Claude Code CLI from https://claude.ai/code",
143
129
  )
144
130
 
145
131
  def _check_version(self) -> DiagnosticResult:
146
- """Check Claude Desktop version compatibility."""
147
- # Try to get version from config file
148
- config_paths = [
149
- Path.home() / "Library/Application Support/Claude/config.json", # macOS
150
- Path.home() / ".config/Claude/config.json", # Linux
151
- Path.home() / "AppData/Roaming/Claude/config.json", # Windows
152
- ]
132
+ """Check Claude Code CLI version compatibility."""
133
+ try:
134
+ result = subprocess.run(
135
+ ["claude", "--version"],
136
+ capture_output=True,
137
+ timeout=5,
138
+ check=True,
139
+ text=True
140
+ )
141
+ version_output = result.stdout.strip()
153
142
 
154
- for config_path in config_paths:
155
- if config_path.exists():
156
- try:
157
- with open(config_path) as f:
158
- config = json.load(f)
159
- version = config.get("version", "unknown")
160
-
161
- # Simple version check (would need real version comparison logic)
162
- return DiagnosticResult(
163
- category="Claude Desktop Version",
164
- status=DiagnosticStatus.OK,
165
- message=f"Version: {version}",
166
- details={
167
- "version": version,
168
- "config_path": str(config_path),
169
- },
170
- )
171
- except Exception:
172
- pass
143
+ # Extract version number (basic parsing)
144
+ version = "unknown"
145
+ if "version" in version_output.lower():
146
+ parts = version_output.split()
147
+ for i, part in enumerate(parts):
148
+ if "version" in part.lower() and i + 1 < len(parts):
149
+ version = parts[i + 1]
150
+ break
173
151
 
174
- return DiagnosticResult(
175
- category="Claude Desktop Version",
176
- status=DiagnosticStatus.WARNING,
177
- message="Could not determine version",
178
- details={"version": "unknown"},
179
- )
152
+ # Check minimum version requirement (1.0.60+)
153
+ status = DiagnosticStatus.OK
154
+ message = f"Version: {version}"
155
+
156
+ return DiagnosticResult(
157
+ category="Claude Code CLI Version",
158
+ status=status,
159
+ message=message,
160
+ details={
161
+ "version": version,
162
+ "version_output": version_output,
163
+ },
164
+ )
165
+
166
+ except subprocess.SubprocessError as e:
167
+ return DiagnosticResult(
168
+ category="Claude Code CLI Version",
169
+ status=DiagnosticStatus.WARNING,
170
+ message=f"Could not determine version: {e}",
171
+ details={"version": "unknown", "error": str(e)},
172
+ )
180
173
 
181
174
  def _check_output_style(self) -> DiagnosticResult:
182
175
  """Check if output style is deployed."""
@@ -224,36 +217,26 @@ class ClaudeDesktopCheck(BaseDiagnosticCheck):
224
217
  )
225
218
 
226
219
  def _check_mcp_integration(self) -> DiagnosticResult:
227
- """Check MCP server integration with Claude Desktop."""
228
- config_path = Path.home() / ".config/claude/claude_desktop_config.json"
220
+ """Check MCP server integration with Claude Code CLI."""
221
+ # Claude Code CLI uses ~/.claude.json for configuration
222
+ config_path = Path.home() / ".claude.json"
229
223
 
230
224
  if not config_path.exists():
231
- # Try alternate paths
232
- alt_paths = [
233
- Path.home()
234
- / "Library/Application Support/Claude/claude_desktop_config.json",
235
- Path.home() / "AppData/Roaming/Claude/claude_desktop_config.json",
236
- ]
237
- for alt_path in alt_paths:
238
- if alt_path.exists():
239
- config_path = alt_path
240
- break
241
- else:
242
- return DiagnosticResult(
243
- category="MCP Integration",
244
- status=DiagnosticStatus.WARNING,
245
- message="Claude Desktop config not found",
246
- details={"configured": False},
247
- fix_command="claude-mpm mcp install",
248
- fix_description="Install MCP server integration",
249
- )
225
+ return DiagnosticResult(
226
+ category="MCP Integration",
227
+ status=DiagnosticStatus.WARNING,
228
+ message="Claude Code CLI config not found",
229
+ details={"configured": False, "config_path": str(config_path)},
230
+ fix_command="claude-mpm mcp install",
231
+ fix_description="Install MCP server integration for Claude Code CLI",
232
+ )
250
233
 
251
234
  try:
252
235
  with open(config_path) as f:
253
236
  config = json.load(f)
254
237
 
255
238
  mcp_servers = config.get("mcpServers", {})
256
- if "claude-mpm-gateway" in mcp_servers:
239
+ if "claude-mpm-gateway" in mcp_servers or "claude-mpm" in mcp_servers:
257
240
  return DiagnosticResult(
258
241
  category="MCP Integration",
259
242
  status=DiagnosticStatus.OK,
@@ -274,7 +257,7 @@ class ClaudeDesktopCheck(BaseDiagnosticCheck):
274
257
  "config_path": str(config_path),
275
258
  },
276
259
  fix_command="claude-mpm mcp install",
277
- fix_description="Configure MCP server for Claude Desktop",
260
+ fix_description="Configure MCP server for Claude Code CLI",
278
261
  )
279
262
 
280
263
  except Exception as e:
@@ -283,4 +266,4 @@ class ClaudeDesktopCheck(BaseDiagnosticCheck):
283
266
  status=DiagnosticStatus.WARNING,
284
267
  message=f"Could not check MCP configuration: {e!s}",
285
268
  details={"error": str(e)},
286
- )
269
+ )
@@ -2,7 +2,7 @@
2
2
  Check MCP (Model Context Protocol) server status.
3
3
 
4
4
  WHY: Verify that the MCP gateway is properly installed, configured,
5
- and functioning for enhanced Claude Desktop capabilities.
5
+ and functioning for enhanced Claude Code capabilities.
6
6
  """
7
7
 
8
8
  import json
@@ -129,7 +129,7 @@ class MCPCheck(BaseDiagnosticCheck):
129
129
  )
130
130
 
131
131
  def _check_configuration(self) -> DiagnosticResult:
132
- """Check MCP configuration in Claude Desktop."""
132
+ """Check MCP configuration in Claude Code."""
133
133
  config_paths = [
134
134
  Path.home() / ".config/claude/claude_desktop_config.json",
135
135
  Path.home()
@@ -147,10 +147,10 @@ class MCPCheck(BaseDiagnosticCheck):
147
147
  return DiagnosticResult(
148
148
  category="MCP Configuration",
149
149
  status=DiagnosticStatus.WARNING,
150
- message="Claude Desktop config not found",
150
+ message="Claude Code config not found",
151
151
  details={"configured": False},
152
152
  fix_command="claude-mpm mcp config",
153
- fix_description="Configure MCP server in Claude Desktop",
153
+ fix_description="Configure MCP server in Claude Code",
154
154
  )
155
155
 
156
156
  try:
@@ -167,7 +167,7 @@ class MCPCheck(BaseDiagnosticCheck):
167
167
  message="MCP gateway not configured",
168
168
  details={"configured": False, "config_path": str(config_path)},
169
169
  fix_command="claude-mpm mcp config",
170
- fix_description="Add MCP gateway to Claude Desktop configuration",
170
+ fix_description="Add MCP gateway to Claude Code configuration",
171
171
  )
172
172
 
173
173
  # Check configuration validity
@@ -203,7 +203,7 @@ class MCPCheck(BaseDiagnosticCheck):
203
203
  status=DiagnosticStatus.ERROR,
204
204
  message="Invalid JSON in config file",
205
205
  details={"error": str(e), "config_path": str(config_path)},
206
- fix_description="Fix JSON syntax in Claude Desktop config",
206
+ fix_description="Fix JSON syntax in Claude Code config",
207
207
  )
208
208
  except Exception as e:
209
209
  return DiagnosticResult(
@@ -2,7 +2,7 @@
2
2
  Check MCP external services installation and health.
3
3
 
4
4
  WHY: Verify that MCP services (mcp-vector-search, mcp-browser, mcp-ticketer, kuzu-memory)
5
- are properly installed and accessible for enhanced Claude Desktop capabilities.
5
+ are properly installed and accessible for enhanced Claude Code capabilities.
6
6
  """
7
7
 
8
8
  import json
@@ -21,7 +21,10 @@ class MCPServicesCheck(BaseDiagnosticCheck):
21
21
  MCP_SERVICES = {
22
22
  "mcp-vector-search": {
23
23
  "package": "mcp-vector-search",
24
- "command": ["mcp-vector-search", "--version"], # Use --version for proper check
24
+ "command": [
25
+ "mcp-vector-search",
26
+ "--version",
27
+ ], # Use --version for proper check
25
28
  "description": "Vector search for semantic code navigation",
26
29
  "check_health": True,
27
30
  "health_command": ["mcp-vector-search", "--version"],
@@ -305,17 +308,37 @@ class MCPServicesCheck(BaseDiagnosticCheck):
305
308
  # Look for actual version information
306
309
  output = (result.stdout + result.stderr).lower()
307
310
  # Check for version indicators
308
- if any(keyword in output for keyword in ["version", "v1.", "v0.", "1.", "0."]):
311
+ if any(
312
+ keyword in output
313
+ for keyword in ["version", "v1.", "v0.", "1.", "0."]
314
+ ):
309
315
  # 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"]):
316
+ if not any(
317
+ error in output
318
+ for error in [
319
+ "error",
320
+ "not found",
321
+ "no such",
322
+ "command not found",
323
+ ]
324
+ ):
311
325
  return True
312
326
 
313
327
  # For some tools, non-zero return code is OK if version is shown
314
328
  elif "--version" in command or "--help" in command:
315
329
  output = (result.stdout + result.stderr).lower()
316
330
  # 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"]):
331
+ if "version" in output or "v1." in output or "v0." in output:
332
+ if not any(
333
+ error in output
334
+ for error in [
335
+ "error",
336
+ "not found",
337
+ "no such",
338
+ "command not found",
339
+ "traceback",
340
+ ]
341
+ ):
319
342
  return True
320
343
 
321
344
  except (subprocess.SubprocessError, FileNotFoundError, OSError):
@@ -14,7 +14,7 @@ from claude_mpm.core.logging_utils import get_logger
14
14
  from .checks import (
15
15
  AgentCheck,
16
16
  BaseDiagnosticCheck,
17
- ClaudeDesktopCheck,
17
+ ClaudeCodeCheck,
18
18
  CommonIssuesCheck,
19
19
  ConfigurationCheck,
20
20
  FilesystemCheck,
@@ -53,7 +53,7 @@ class DiagnosticRunner:
53
53
  ConfigurationCheck,
54
54
  FilesystemCheck,
55
55
  InstructionsCheck, # Check instruction files early
56
- ClaudeDesktopCheck,
56
+ ClaudeCodeCheck,
57
57
  AgentCheck,
58
58
  MCPCheck,
59
59
  MCPServicesCheck, # Check external MCP services
@@ -121,7 +121,7 @@ class DiagnosticRunner:
121
121
  ]
122
122
  # Level 2: May depend on level 1
123
123
  level2 = [
124
- ClaudeDesktopCheck,
124
+ ClaudeCodeCheck,
125
125
  AgentCheck,
126
126
  MCPCheck,
127
127
  MCPServicesCheck,
@@ -209,8 +209,8 @@ class DiagnosticRunner:
209
209
  "config": ConfigurationCheck,
210
210
  "filesystem": FilesystemCheck,
211
211
  "fs": FilesystemCheck,
212
- "claude": ClaudeDesktopCheck,
213
- "claude_desktop": ClaudeDesktopCheck,
212
+ "claude": ClaudeCodeCheck,
213
+ "claude_code": ClaudeCodeCheck,
214
214
  "agents": AgentCheck,
215
215
  "agent": AgentCheck,
216
216
  "mcp": MCPCheck,
@@ -385,9 +385,9 @@ class DoctorReporter:
385
385
  print(
386
386
  f"| Installation Method | {result.details['installation_method']} |"
387
387
  )
388
- elif result.category == "Claude Desktop":
388
+ elif result.category == "Claude Code":
389
389
  if result.details.get("version"):
390
- print(f"| Claude Desktop | {result.details['version']} |")
390
+ print(f"| Claude Code (CLI) | {result.details['version']} |")
391
391
 
392
392
  def _print_mcp_services_markdown(self, summary: DiagnosticSummary):
393
393
  """Print MCP services status table in markdown."""
@@ -533,11 +533,11 @@ class DoctorReporter:
533
533
  )
534
534
 
535
535
  if (
536
- result.category == "Claude Desktop"
536
+ result.category == "Claude Code"
537
537
  and result.status == DiagnosticStatus.WARNING
538
538
  ):
539
539
  recommendations.append(
540
- "Update Claude Desktop to the latest version for best compatibility"
540
+ "Update Claude Code (CLI) to the latest version for best compatibility"
541
541
  )
542
542
 
543
543
  if recommendations:
@@ -86,7 +86,11 @@ class MCPConfigManager:
86
86
  for path in candidates:
87
87
  try:
88
88
  result = subprocess.run(
89
- [path, "--help"], capture_output=True, text=True, timeout=5, check=False
89
+ [path, "--help"],
90
+ capture_output=True,
91
+ text=True,
92
+ timeout=5,
93
+ check=False,
90
94
  )
91
95
  # Check if this version has MCP support
92
96
  if "claude" in result.stdout or "mcp" in result.stdout:
@@ -304,7 +308,7 @@ class MCPConfigManager:
304
308
 
305
309
  elif service_name == "kuzu-memory":
306
310
  # Determine kuzu-memory command version
307
- kuzu_args = []
311
+ kuzu_args = ["mcp", "serve"] # Default to the correct modern format
308
312
  test_cmd = None
309
313
 
310
314
  if use_pipx_run:
@@ -317,17 +321,30 @@ class MCPConfigManager:
317
321
  if test_cmd:
318
322
  try:
319
323
  result = subprocess.run(
320
- test_cmd, capture_output=True, text=True, timeout=10, check=False
324
+ test_cmd,
325
+ capture_output=True,
326
+ text=True,
327
+ timeout=10,
328
+ check=False,
321
329
  )
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
330
+ # Check for MCP support in help output
331
+ help_output = result.stdout.lower() + result.stderr.lower()
332
+
333
+ # Modern version detection - look for "mcp serve" command
334
+ if "mcp serve" in help_output or ("mcp" in help_output and "serve" in help_output):
335
+ # Modern version with mcp serve command
336
+ kuzu_args = ["mcp", "serve"]
337
+ # Legacy version detection - only "serve" without "mcp"
338
+ elif "serve" in help_output and "mcp" not in help_output:
339
+ # Very old version that only has serve command
327
340
  kuzu_args = ["serve"]
328
- except:
329
- # Default to newer version command
330
- kuzu_args = ["claude", "mcp-server"]
341
+ # Note: "claude mcp-server" format is deprecated and not used
342
+ else:
343
+ # Default to the correct modern format
344
+ kuzu_args = ["mcp", "serve"]
345
+ except Exception:
346
+ # Default to the correct mcp serve command on any error
347
+ kuzu_args = ["mcp", "serve"]
331
348
 
332
349
  if use_pipx_run:
333
350
  config["command"] = "pipx"
@@ -339,17 +356,16 @@ class MCPConfigManager:
339
356
  config["command"] = service_path
340
357
  config["args"] = kuzu_args
341
358
 
359
+ # Generic config for unknown services
360
+ elif use_pipx_run:
361
+ config["command"] = "pipx"
362
+ config["args"] = ["run", service_name]
363
+ elif use_uvx:
364
+ config["command"] = "uvx"
365
+ config["args"] = [service_name]
342
366
  else:
343
- # Generic config for unknown services
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"] = []
367
+ config["command"] = service_path
368
+ config["args"] = []
353
369
 
354
370
  return config
355
371
 
@@ -632,9 +648,7 @@ class MCPConfigManager:
632
648
  f"pipx install succeeded but verification failed for {service_name}"
633
649
  )
634
650
  else:
635
- self.logger.debug(
636
- f"pipx install failed: {result.stderr}"
637
- )
651
+ self.logger.debug(f"pipx install failed: {result.stderr}")
638
652
  except subprocess.TimeoutExpired:
639
653
  self.logger.warning(f"pipx install timed out for {service_name}")
640
654
  except Exception as e:
@@ -739,9 +753,15 @@ class MCPConfigManager:
739
753
  if result.returncode == 0:
740
754
  return True
741
755
  # Some tools return non-zero but still work
742
- elif any(indicator in output for indicator in ["version", "usage", "help", service_name.lower()]):
756
+ if any(
757
+ indicator in output
758
+ for indicator in ["version", "usage", "help", service_name.lower()]
759
+ ):
743
760
  # Make sure it's not an error message
744
- if not any(error in output for error in ["error", "not found", "traceback", "no such"]):
761
+ if not any(
762
+ error in output
763
+ for error in ["error", "not found", "traceback", "no such"]
764
+ ):
745
765
  return True
746
766
  except Exception as e:
747
767
  self.logger.debug(f"Verification error for {service_name}: {e}")
@@ -423,7 +423,8 @@ async def auto_initialize_vector_search():
423
423
  ["pipx", "install", "mcp-vector-search"],
424
424
  capture_output=True,
425
425
  text=True,
426
- timeout=60, check=False, # 1 minute timeout for installation
426
+ timeout=60,
427
+ check=False, # 1 minute timeout for installation
427
428
  )
428
429
 
429
430
  if result.returncode == 0:
@@ -492,9 +493,7 @@ async def auto_initialize_vector_search():
492
493
  if chroma_db.exists() and chroma_db.stat().st_size > 0:
493
494
  logger.info("✓ Vector search index is healthy and ready")
494
495
  return
495
- logger.info(
496
- "⚠️ Vector search index may be corrupted, rebuilding..."
497
- )
496
+ logger.info("⚠️ Vector search index may be corrupted, rebuilding...")
498
497
  except Exception as e:
499
498
  logger.debug(
500
499
  f"Vector search health check failed: {e}, will attempt to rebuild"
@@ -512,7 +511,8 @@ async def auto_initialize_vector_search():
512
511
  capture_output=True,
513
512
  text=True,
514
513
  timeout=30,
515
- cwd=str(current_dir), check=False, # Run in the project directory
514
+ cwd=str(current_dir),
515
+ check=False, # Run in the project directory
516
516
  )
517
517
 
518
518
  if proc.returncode == 0:
@@ -527,7 +527,8 @@ async def auto_initialize_vector_search():
527
527
  capture_output=True,
528
528
  text=True,
529
529
  timeout=300, # 5 minute timeout for indexing
530
- cwd=str(current_dir), check=False, # Run in the project directory
530
+ cwd=str(current_dir),
531
+ check=False, # Run in the project directory
531
532
  )
532
533
  if index_proc.returncode == 0:
533
534
  logger.info("✅ Project indexing completed successfully")
@@ -610,7 +611,8 @@ async def auto_initialize_kuzu_memory():
610
611
  ["pipx", "install", "kuzu-memory"],
611
612
  capture_output=True,
612
613
  text=True,
613
- timeout=60, check=False, # 1 minute timeout for installation
614
+ timeout=60,
615
+ check=False, # 1 minute timeout for installation
614
616
  )
615
617
 
616
618
  if result.returncode == 0:
@@ -679,7 +681,8 @@ async def auto_initialize_kuzu_memory():
679
681
  capture_output=True,
680
682
  text=True,
681
683
  timeout=30,
682
- cwd=str(current_dir), check=False,
684
+ cwd=str(current_dir),
685
+ check=False,
683
686
  )
684
687
 
685
688
  if proc.returncode == 0: