claude-mpm 4.6.1__py3-none-any.whl → 4.7.1__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 (111) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_ENGINEER.md +206 -48
  3. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +787 -0
  4. claude_mpm/agents/base_agent_loader.py +3 -1
  5. claude_mpm/agents/templates/engineer.json +10 -4
  6. claude_mpm/agents/templates/prompt-engineer.json +517 -87
  7. claude_mpm/cli/commands/cleanup.py +1 -1
  8. claude_mpm/cli/commands/mcp_setup_external.py +2 -2
  9. claude_mpm/cli/commands/memory.py +1 -1
  10. claude_mpm/cli/commands/mpm_init.py +5 -4
  11. claude_mpm/cli/commands/run.py +4 -4
  12. claude_mpm/cli/shared/argument_patterns.py +18 -11
  13. claude_mpm/cli/shared/base_command.py +1 -1
  14. claude_mpm/config/experimental_features.py +3 -3
  15. claude_mpm/config/socketio_config.py +1 -1
  16. claude_mpm/core/cache.py +2 -2
  17. claude_mpm/core/claude_runner.py +5 -7
  18. claude_mpm/core/container.py +10 -4
  19. claude_mpm/core/file_utils.py +10 -8
  20. claude_mpm/core/framework/formatters/context_generator.py +3 -2
  21. claude_mpm/core/framework/loaders/agent_loader.py +11 -7
  22. claude_mpm/core/injectable_service.py +11 -8
  23. claude_mpm/core/interactive_session.py +5 -4
  24. claude_mpm/core/oneshot_session.py +3 -2
  25. claude_mpm/core/pm_hook_interceptor.py +15 -9
  26. claude_mpm/core/unified_paths.py +6 -5
  27. claude_mpm/dashboard/api/simple_directory.py +16 -17
  28. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -2
  29. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +2 -2
  30. claude_mpm/hooks/claude_hooks/hook_handler_original.py +2 -2
  31. claude_mpm/hooks/claude_hooks/installer.py +10 -10
  32. claude_mpm/hooks/claude_hooks/response_tracking.py +3 -2
  33. claude_mpm/hooks/claude_hooks/services/state_manager.py +3 -2
  34. claude_mpm/hooks/tool_call_interceptor.py +6 -3
  35. claude_mpm/models/agent_session.py +3 -1
  36. claude_mpm/scripts/mcp_server.py +3 -5
  37. claude_mpm/services/agents/agent_builder.py +4 -4
  38. claude_mpm/services/agents/deployment/deployment_type_detector.py +10 -14
  39. claude_mpm/services/agents/deployment/local_template_deployment.py +6 -3
  40. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +15 -11
  41. claude_mpm/services/agents/deployment/system_instructions_deployer.py +9 -6
  42. claude_mpm/services/agents/loading/agent_profile_loader.py +1 -2
  43. claude_mpm/services/agents/memory/agent_memory_manager.py +27 -27
  44. claude_mpm/services/agents/memory/content_manager.py +9 -4
  45. claude_mpm/services/claude_session_logger.py +5 -8
  46. claude_mpm/services/cli/memory_crud_service.py +1 -1
  47. claude_mpm/services/cli/memory_output_formatter.py +1 -1
  48. claude_mpm/services/cli/startup_checker.py +13 -10
  49. claude_mpm/services/cli/unified_dashboard_manager.py +10 -6
  50. claude_mpm/services/command_deployment_service.py +9 -7
  51. claude_mpm/services/core/path_resolver.py +8 -5
  52. claude_mpm/services/diagnostics/checks/agent_check.py +4 -7
  53. claude_mpm/services/diagnostics/checks/installation_check.py +19 -16
  54. claude_mpm/services/diagnostics/checks/mcp_services_check.py +30 -28
  55. claude_mpm/services/diagnostics/checks/startup_log_check.py +5 -3
  56. claude_mpm/services/events/core.py +2 -3
  57. claude_mpm/services/framework_claude_md_generator/content_validator.py +2 -2
  58. claude_mpm/services/hook_installer_service.py +2 -3
  59. claude_mpm/services/hook_service.py +5 -6
  60. claude_mpm/services/mcp_gateway/auto_configure.py +4 -5
  61. claude_mpm/services/mcp_gateway/main.py +7 -4
  62. claude_mpm/services/mcp_gateway/server/stdio_server.py +3 -4
  63. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -2
  64. claude_mpm/services/mcp_service_verifier.py +18 -17
  65. claude_mpm/services/memory/builder.py +1 -2
  66. claude_mpm/services/memory/indexed_memory.py +1 -1
  67. claude_mpm/services/memory/optimizer.py +1 -2
  68. claude_mpm/services/monitor/daemon_manager.py +3 -3
  69. claude_mpm/services/monitor/handlers/file.py +5 -4
  70. claude_mpm/services/monitor/management/lifecycle.py +1 -1
  71. claude_mpm/services/monitor/server.py +14 -12
  72. claude_mpm/services/project/architecture_analyzer.py +5 -5
  73. claude_mpm/services/project/metrics_collector.py +4 -4
  74. claude_mpm/services/project/project_organizer.py +4 -4
  75. claude_mpm/services/project/registry.py +9 -3
  76. claude_mpm/services/shared/config_service_base.py +10 -11
  77. claude_mpm/services/socketio/handlers/file.py +5 -4
  78. claude_mpm/services/socketio/handlers/git.py +7 -7
  79. claude_mpm/services/socketio/server/core.py +10 -10
  80. claude_mpm/services/subprocess_launcher_service.py +5 -10
  81. claude_mpm/services/ticket_services/formatter_service.py +1 -1
  82. claude_mpm/services/ticket_services/validation_service.py +5 -5
  83. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +5 -5
  84. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +4 -4
  85. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +4 -4
  86. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +4 -4
  87. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +4 -4
  88. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +6 -2
  89. claude_mpm/services/unified/config_strategies/unified_config_service.py +24 -13
  90. claude_mpm/services/version_control/conflict_resolution.py +6 -2
  91. claude_mpm/services/version_control/git_operations.py +1 -1
  92. claude_mpm/services/version_control/version_parser.py +1 -1
  93. claude_mpm/storage/state_storage.py +3 -3
  94. claude_mpm/tools/__main__.py +1 -1
  95. claude_mpm/tools/code_tree_analyzer.py +17 -14
  96. claude_mpm/tools/socketio_debug.py +7 -7
  97. claude_mpm/utils/common.py +6 -2
  98. claude_mpm/utils/config_manager.py +9 -3
  99. claude_mpm/utils/database_connector.py +4 -4
  100. claude_mpm/utils/dependency_strategies.py +1 -1
  101. claude_mpm/utils/environment_context.py +3 -2
  102. claude_mpm/utils/file_utils.py +1 -2
  103. claude_mpm/utils/path_operations.py +3 -1
  104. claude_mpm/utils/robust_installer.py +3 -4
  105. claude_mpm/validation/frontmatter_validator.py +4 -4
  106. {claude_mpm-4.6.1.dist-info → claude_mpm-4.7.1.dist-info}/METADATA +1 -1
  107. {claude_mpm-4.6.1.dist-info → claude_mpm-4.7.1.dist-info}/RECORD +111 -110
  108. {claude_mpm-4.6.1.dist-info → claude_mpm-4.7.1.dist-info}/WHEEL +0 -0
  109. {claude_mpm-4.6.1.dist-info → claude_mpm-4.7.1.dist-info}/entry_points.txt +0 -0
  110. {claude_mpm-4.6.1.dist-info → claude_mpm-4.7.1.dist-info}/licenses/LICENSE +0 -0
  111. {claude_mpm-4.6.1.dist-info → claude_mpm-4.7.1.dist-info}/top_level.txt +0 -0
@@ -246,7 +246,7 @@ class StartupCheckerService(IStartupChecker):
246
246
 
247
247
  # Display info last
248
248
  for warning in info:
249
- print(f"ℹ️ {warning.message}")
249
+ print(f"[INFO]️ {warning.message}")
250
250
  if warning.suggestion:
251
251
  print(f" {warning.suggestion}")
252
252
 
@@ -314,16 +314,19 @@ class StartupCheckerService(IStartupChecker):
314
314
  try:
315
315
  # Try to get config file path from config service
316
316
  config_file = getattr(self.config_service, "config_file", None)
317
- if config_file and Path(config_file).exists():
318
- if not os.access(config_file, os.R_OK):
319
- warnings.append(
320
- StartupWarning(
321
- category="config",
322
- message=f"Configuration file is not readable: {config_file}",
323
- suggestion=f"Run: chmod 644 {config_file}",
324
- severity="warning",
325
- )
317
+ if (
318
+ config_file
319
+ and Path(config_file).exists()
320
+ and not os.access(config_file, os.R_OK)
321
+ ):
322
+ warnings.append(
323
+ StartupWarning(
324
+ category="config",
325
+ message=f"Configuration file is not readable: {config_file}",
326
+ suggestion=f"Run: chmod 644 {config_file}",
327
+ severity="warning",
326
328
  )
329
+ )
327
330
  except Exception as e:
328
331
  self.logger.debug(f"Config file access check failed: {e}")
329
332
 
@@ -334,14 +334,18 @@ class UnifiedDashboardManager(IUnifiedDashboardManager):
334
334
  Returns:
335
335
  Tuple of (dependencies_ok, error_message)
336
336
  """
337
- try:
338
- import aiohttp
339
- import socketio
337
+ import importlib.util
338
+
339
+ missing = []
340
+ if importlib.util.find_spec("aiohttp") is None:
341
+ missing.append("aiohttp")
342
+ if importlib.util.find_spec("socketio") is None:
343
+ missing.append("socketio")
340
344
 
341
- return True, None
342
- except ImportError as e:
343
- error_msg = f"Required dependencies missing: {e}"
345
+ if missing:
346
+ error_msg = f"Required dependencies missing: {', '.join(missing)}"
344
347
  return False, error_msg
348
+ return True, None
345
349
 
346
350
  def find_available_port(self, preferred_port: int = 8765) -> int:
347
351
  """
@@ -84,13 +84,15 @@ class CommandDeploymentService(BaseService):
84
84
 
85
85
  try:
86
86
  # Check if file exists and if we should overwrite
87
- if target_file.exists() and not force:
88
- # Check if source is newer
89
- if source_file.stat().st_mtime <= target_file.stat().st_mtime:
90
- self.logger.debug(
91
- f"Skipping {source_file.name} - target is up to date"
92
- )
93
- continue
87
+ if (
88
+ target_file.exists()
89
+ and not force
90
+ and source_file.stat().st_mtime <= target_file.stat().st_mtime
91
+ ):
92
+ self.logger.debug(
93
+ f"Skipping {source_file.name} - target is up to date"
94
+ )
95
+ continue
94
96
 
95
97
  # Copy the file
96
98
  shutil.copy2(source_file, target_file)
@@ -431,11 +431,14 @@ class PathResolver(IPathResolver):
431
431
  ]
432
432
 
433
433
  for candidate in candidates:
434
- if candidate and candidate.exists():
435
- # Check for claude-mpm agents directory
436
- if (candidate / "src" / "claude_mpm" / "agents").exists():
437
- self.logger.info(f"Found claude-mpm at: {candidate}")
438
- return candidate
434
+ if (
435
+ candidate
436
+ and candidate.exists()
437
+ and (candidate / "src" / "claude_mpm" / "agents").exists()
438
+ ):
439
+ # Found claude-mpm agents directory
440
+ self.logger.info(f"Found claude-mpm at: {candidate}")
441
+ return candidate
439
442
 
440
443
  return None
441
444
 
@@ -111,10 +111,9 @@ class AgentCheck(BaseDiagnosticCheck):
111
111
 
112
112
  def _check_deployed_agents(self) -> DiagnosticResult:
113
113
  """Check deployed agents in both project and user directories."""
114
- import os
115
114
 
116
115
  # Check project-level agents first (preferred in development)
117
- project_agents_dir = Path(os.getcwd()) / ".claude" / "agents"
116
+ project_agents_dir = Path(Path.cwd()) / ".claude" / "agents"
118
117
  user_agents_dir = Path.home() / ".claude" / "agents"
119
118
 
120
119
  # Determine which directory to check
@@ -188,7 +187,6 @@ class AgentCheck(BaseDiagnosticCheck):
188
187
  def _check_agent_versions(self) -> DiagnosticResult:
189
188
  """Check if deployed agents are up-to-date."""
190
189
  try:
191
- import os
192
190
 
193
191
  from ....services.agents.deployment.agent_version_manager import (
194
192
  AgentVersionManager,
@@ -197,7 +195,7 @@ class AgentCheck(BaseDiagnosticCheck):
197
195
  version_manager = AgentVersionManager()
198
196
 
199
197
  # Check both project and user directories
200
- project_agents_dir = Path(os.getcwd()) / ".claude" / "agents"
198
+ project_agents_dir = Path(Path.cwd()) / ".claude" / "agents"
201
199
  user_agents_dir = Path.home() / ".claude" / "agents"
202
200
 
203
201
  if project_agents_dir.exists():
@@ -259,14 +257,13 @@ class AgentCheck(BaseDiagnosticCheck):
259
257
  def _validate_agents(self) -> DiagnosticResult:
260
258
  """Validate agent configurations."""
261
259
  try:
262
- import os
263
260
 
264
261
  from ....services.agents.deployment.agent_validator import AgentValidator
265
262
 
266
263
  AgentValidator()
267
264
 
268
265
  # Check both project and user directories
269
- project_agents_dir = Path(os.getcwd()) / ".claude" / "agents"
266
+ project_agents_dir = Path(Path.cwd()) / ".claude" / "agents"
270
267
  user_agents_dir = Path.home() / ".claude" / "agents"
271
268
 
272
269
  if project_agents_dir.exists():
@@ -331,7 +328,7 @@ class AgentCheck(BaseDiagnosticCheck):
331
328
  issues = []
332
329
 
333
330
  # Check both project and user directories
334
- project_agents_dir = Path(os.getcwd()) / ".claude" / "agents"
331
+ project_agents_dir = Path(Path.cwd()) / ".claude" / "agents"
335
332
  user_agents_dir = Path.home() / ".claude" / "agents"
336
333
 
337
334
  if project_agents_dir.exists():
@@ -176,10 +176,11 @@ class InstallationCheck(BaseDiagnosticCheck):
176
176
 
177
177
  # 5. Check if running from source (development mode)
178
178
  claude_mpm_path = Path(__file__).parent.parent.parent.parent.parent
179
- if (claude_mpm_path / "pyproject.toml").exists():
180
- if (claude_mpm_path / ".git").exists():
181
- methods_found.append("development")
182
- details["source_path"] = str(claude_mpm_path)
179
+ if (claude_mpm_path / "pyproject.toml").exists() and (
180
+ claude_mpm_path / ".git"
181
+ ).exists():
182
+ methods_found.append("development")
183
+ details["source_path"] = str(claude_mpm_path)
183
184
 
184
185
  # 6. Check Homebrew Python
185
186
  if not in_venv and "/opt/homebrew" in exe_path:
@@ -191,21 +192,23 @@ class InstallationCheck(BaseDiagnosticCheck):
191
192
  details["homebrew_python"] = exe_path
192
193
 
193
194
  # 7. Check for system Python
194
- if not in_venv and not methods_found:
195
- if "/usr/bin/python" in exe_path or "/usr/local/bin/python" in exe_path:
196
- methods_found.append("system")
197
- details["system_python"] = exe_path
195
+ if (
196
+ not in_venv
197
+ and not methods_found
198
+ and ("/usr/bin/python" in exe_path or "/usr/local/bin/python" in exe_path)
199
+ ):
200
+ methods_found.append("system")
201
+ details["system_python"] = exe_path
198
202
 
199
203
  # 8. Additional check for pipx if not detected via venv
200
204
  if "pipx" not in methods_found:
201
205
  pipx_check = self._check_pipx_installation_status()
202
- if pipx_check:
203
- if not is_pipx_venv:
204
- # Pipx is installed but we're not running from it
205
- details["pipx_installed"] = True
206
- details["pipx_not_active"] = (
207
- "claude-mpm is installed via pipx but not currently running from pipx environment"
208
- )
206
+ if pipx_check and not is_pipx_venv:
207
+ # Pipx is installed but we're not running from it
208
+ details["pipx_installed"] = True
209
+ details["pipx_not_active"] = (
210
+ "claude-mpm is installed via pipx but not currently running from pipx environment"
211
+ )
209
212
 
210
213
  # 9. Check pip installation status
211
214
  try:
@@ -445,7 +448,7 @@ class InstallationCheck(BaseDiagnosticCheck):
445
448
 
446
449
  # Check cgroup for container indicators
447
450
  try:
448
- with open("/proc/1/cgroup") as f:
451
+ with Path("/proc/1/cgroup").open() as f:
449
452
  cgroup = f.read()
450
453
  if "docker" in cgroup:
451
454
  return "Docker"
@@ -444,11 +444,14 @@ class MCPServicesCheck(BaseDiagnosticCheck):
444
444
  details["command_path"] = command_path
445
445
 
446
446
  # If not directly accessible, try pipx run command
447
- if not accessible and "pipx_run_command" in config:
448
- if self._verify_command_works(config["pipx_run_command"]):
449
- accessible = True
450
- details["accessible_via_pipx_run"] = True
451
- details["pipx_run_available"] = True
447
+ if (
448
+ not accessible
449
+ and "pipx_run_command" in config
450
+ and self._verify_command_works(config["pipx_run_command"])
451
+ ):
452
+ accessible = True
453
+ details["accessible_via_pipx_run"] = True
454
+ details["pipx_run_available"] = True
452
455
 
453
456
  # Check for installation in various locations
454
457
  if not pipx_installed and not accessible:
@@ -690,35 +693,34 @@ class MCPServicesCheck(BaseDiagnosticCheck):
690
693
  if any(
691
694
  keyword in output
692
695
  for keyword in ["version", "v1.", "v0.", "1.", "0."]
696
+ ) and not any(
697
+ error in output
698
+ for error in [
699
+ "error",
700
+ "not found",
701
+ "no such",
702
+ "command not found",
703
+ ]
693
704
  ):
694
- # But reject if it's an error message
695
- if not any(
696
- error in output
697
- for error in [
698
- "error",
699
- "not found",
700
- "no such",
701
- "command not found",
702
- ]
703
- ):
704
- return True
705
+ return True
705
706
 
706
707
  # For some tools, non-zero return code is OK if version is shown
707
708
  elif "--version" in command or "--help" in command:
708
709
  output = (result.stdout + result.stderr).lower()
709
710
  # Must have version info and no error indicators
710
- if "version" in output or "v1." in output or "v0." in output:
711
- if not any(
712
- error in output
713
- for error in [
714
- "error",
715
- "not found",
716
- "no such",
717
- "command not found",
718
- "traceback",
719
- ]
720
- ):
721
- return True
711
+ if (
712
+ "version" in output or "v1." in output or "v0." in output
713
+ ) and not any(
714
+ error in output
715
+ for error in [
716
+ "error",
717
+ "not found",
718
+ "no such",
719
+ "command not found",
720
+ "traceback",
721
+ ]
722
+ ):
723
+ return True
722
724
 
723
725
  except (subprocess.SubprocessError, FileNotFoundError, OSError):
724
726
  pass
@@ -15,7 +15,7 @@ DESIGN DECISIONS:
15
15
  import re
16
16
  from datetime import datetime
17
17
  from pathlib import Path
18
- from typing import Any, Dict, Optional
18
+ from typing import Any, ClassVar, Dict, Optional
19
19
 
20
20
  from ..models import DiagnosticResult, DiagnosticStatus
21
21
  from .base_check import BaseDiagnosticCheck
@@ -25,7 +25,7 @@ class StartupLogCheck(BaseDiagnosticCheck):
25
25
  """Analyze startup logs for errors and issues."""
26
26
 
27
27
  # Common error patterns and their fixes
28
- ERROR_PATTERNS = {
28
+ ERROR_PATTERNS: ClassVar[dict[str, dict[str, Any]]] = {
29
29
  r"Agent deployment.*failed": (
30
30
  "Agent deployment failure",
31
31
  "Check agent configuration in .claude/agents/ and run 'claude-mpm deploy'",
@@ -186,7 +186,9 @@ class StartupLogCheck(BaseDiagnosticCheck):
186
186
  }
187
187
 
188
188
  try:
189
- with open(log_file, encoding="utf-8") as f:
189
+ with Path(log_file).open(
190
+ encoding="utf-8",
191
+ ) as f:
190
192
  lines = f.readlines()
191
193
 
192
194
  # Extract timestamp from filename or first line
@@ -412,9 +412,8 @@ class EventBus(IEventBus):
412
412
  """
413
413
  try:
414
414
  # Apply filter if configured
415
- if consumer.config.filter_func:
416
- if not consumer.config.filter_func(event):
417
- return
415
+ if consumer.config.filter_func and not consumer.config.filter_func(event):
416
+ return
418
417
 
419
418
  # Apply transformation if configured
420
419
  if consumer.config.transform_func:
@@ -5,14 +5,14 @@ Validates generated content structure and completeness.
5
5
  """
6
6
 
7
7
  import re
8
- from typing import List, Tuple
8
+ from typing import ClassVar, List, Tuple
9
9
 
10
10
 
11
11
  class ContentValidator:
12
12
  """Validates framework CLAUDE.md content for completeness and correctness."""
13
13
 
14
14
  # Required sections that must be present
15
- REQUIRED_SECTIONS = [
15
+ REQUIRED_SECTIONS: ClassVar[list[str]] = [
16
16
  (r"CLAUDE_MD_VERSION:", "Version metadata"),
17
17
  (r"## 🤖 AI ASSISTANT ROLE DESIGNATION", "Role designation section"),
18
18
  (r"## A\) AGENTS", "Agents section"),
@@ -5,7 +5,6 @@ to enable monitor event forwarding via Socket.IO.
5
5
  """
6
6
 
7
7
  import json
8
- import os
9
8
  import shutil
10
9
  import stat
11
10
  import sys
@@ -280,8 +279,8 @@ class HookInstallerService:
280
279
  return False
281
280
 
282
281
  # Make sure the script is executable
283
- st = os.stat(hook_script)
284
- os.chmod(hook_script, st.st_mode | stat.S_IEXEC)
282
+ st = Path(hook_script).stat()
283
+ Path(hook_script).chmod(st.st_mode | stat.S_IEXEC)
285
284
  self.logger.debug(f"Made hook script executable: {hook_script}")
286
285
 
287
286
  hook_script_path = str(hook_script.absolute())
@@ -278,12 +278,11 @@ class HookService(HookServiceInterface):
278
278
  if hook_type in ["pre_delegation", "post_delegation"]:
279
279
  # If any registered hooks are memory-related, check memory.enabled
280
280
  for hook in getattr(self, f"{hook_type}_hooks", []):
281
- if "memory" in hook.name.lower():
282
- if not self.config.get("memory.enabled", True):
283
- self.logger.debug(
284
- "Memory hooks disabled via memory.enabled config"
285
- )
286
- return False
281
+ if "memory" in hook.name.lower() and not self.config.get(
282
+ "memory.enabled", True
283
+ ):
284
+ self.logger.debug("Memory hooks disabled via memory.enabled config")
285
+ return False
287
286
 
288
287
  return True
289
288
 
@@ -176,13 +176,12 @@ class MCPAutoConfigurator:
176
176
  print(f"(Auto-declining in {timeout} seconds)")
177
177
 
178
178
  # Use threading for cross-platform timeout support
179
+ # Python 3.7+ has queue built-in - no need to check, we require 3.10+
180
+ import importlib.util
179
181
  import threading
180
182
 
181
- try:
182
- # Python 3.7+ has queue built-in
183
- import queue
184
- except ImportError:
185
- # Python 2.x fallback
183
+ if importlib.util.find_spec("queue") is None:
184
+ # Extremely unlikely in Python 3.10+, but for completeness
186
185
  pass
187
186
 
188
187
  user_input = None
@@ -179,10 +179,13 @@ class MCPGatewayOrchestrator:
179
179
 
180
180
  # Load configuration
181
181
  self.configuration = MCPConfiguration()
182
- if self.config_path and self.config_path.exists():
183
- if not self.configuration.load_config(self.config_path):
184
- self.logger.error("Failed to load configuration")
185
- return False
182
+ if (
183
+ self.config_path
184
+ and self.config_path.exists()
185
+ and not self.configuration.load_config(self.config_path)
186
+ ):
187
+ self.logger.error("Failed to load configuration")
188
+ return False
186
189
 
187
190
  # Initialize tool registry with error handling
188
191
  try:
@@ -18,6 +18,7 @@ import os
18
18
  import sys
19
19
  import time
20
20
  from datetime import timezone
21
+ from pathlib import Path
21
22
  from typing import Any, Dict
22
23
 
23
24
  # Import MCP SDK components
@@ -541,12 +542,10 @@ class SimpleMCPServer:
541
542
 
542
543
  result = f"Python: {sys.version}"
543
544
  elif info_type == "cwd":
544
- import os
545
545
 
546
- result = f"Working Directory: {os.getcwd()}"
546
+ result = f"Working Directory: {Path.cwd()}"
547
547
  elif info_type == "all":
548
548
  import datetime
549
- import os
550
549
  import platform
551
550
  import sys
552
551
 
@@ -554,7 +553,7 @@ class SimpleMCPServer:
554
553
  f"=== System Status ===\n"
555
554
  f"Platform: {platform.system()} {platform.release()}\n"
556
555
  f"Python: {sys.version.split()[0]}\n"
557
- f"Working Directory: {os.getcwd()}\n"
556
+ f"Working Directory: {Path.cwd()}\n"
558
557
  f"Server: {self.name} v{self.version}\n"
559
558
  f"Timestamp: {datetime.datetime.now(timezone.utc).isoformat()}\n"
560
559
  f"Tools Available: status, document_summarizer{', ticket' if self.unified_ticket_tool else ''}"
@@ -10,7 +10,6 @@ Part of ISS-0037: Document Summarizer Tool - Intelligent Document Processing
10
10
 
11
11
  import hashlib
12
12
  import mimetypes
13
- import os
14
13
  import re
15
14
  from collections import OrderedDict
16
15
  from datetime import datetime, timezone
@@ -240,7 +239,7 @@ class DocumentSummarizerTool(BaseToolAdapter):
240
239
 
241
240
  def _get_file_hash(self, file_path: str) -> str:
242
241
  """Generate hash for file caching."""
243
- stat = os.stat(file_path)
242
+ stat = Path(file_path).stat()
244
243
  hash_input = f"{file_path}:{stat.st_size}:{stat.st_mtime}"
245
244
  return hashlib.md5(hash_input.encode()).hexdigest()
246
245
 
@@ -328,13 +328,11 @@ class MCPServiceVerifier:
328
328
  if any(
329
329
  word in output
330
330
  for word in ["version", "usage", "help", service_name.lower()]
331
+ ) and not any(
332
+ error in output
333
+ for error in ["error", "not found", "traceback", "no module"]
331
334
  ):
332
- # Make sure it's not an error
333
- if not any(
334
- error in output
335
- for error in ["error", "not found", "traceback", "no module"]
336
- ):
337
- return True
335
+ return True
338
336
 
339
337
  # Try pipx run as fallback
340
338
  if shutil.which("pipx"):
@@ -485,16 +483,19 @@ class MCPServiceVerifier:
485
483
  }
486
484
  else:
487
485
  # Direct execution - command should be a valid path
488
- if not Path(command).exists() and command != installed_path:
489
- # Allow for relative paths that might resolve differently
490
- if not shutil.which(command):
491
- return {
492
- "configured": True,
493
- "correct": False,
494
- "command": command,
495
- "args": args,
496
- "issue": f"Command path does not exist: {command}",
497
- }
486
+ if (
487
+ not Path(command).exists()
488
+ and command != installed_path
489
+ and not shutil.which(command)
490
+ ):
491
+ # Command path does not exist and cannot be found
492
+ return {
493
+ "configured": True,
494
+ "correct": False,
495
+ "command": command,
496
+ "args": args,
497
+ "issue": f"Command path does not exist: {command}",
498
+ }
498
499
 
499
500
  # Check required args
500
501
  for req_arg in required_args:
@@ -615,7 +616,7 @@ class MCPServiceVerifier:
615
616
  if diagnostic.fix_command.startswith("chmod "):
616
617
  # Fix permissions
617
618
  path = diagnostic.fix_command.replace("chmod +x ", "")
618
- os.chmod(path, 0o755)
619
+ Path(path).chmod(0o755)
619
620
  return True
620
621
 
621
622
  if "claude-mpm configure" in diagnostic.fix_command:
@@ -22,7 +22,6 @@ documentation verbatim. Creates concise learnings that fit memory constraints
22
22
  while preserving essential information.
23
23
  """
24
24
 
25
- import os
26
25
  import re
27
26
  from datetime import datetime, timezone
28
27
  from pathlib import Path
@@ -118,7 +117,7 @@ class MemoryBuilder(LoggerMixin):
118
117
  self.config = config_loader.load_main_config()
119
118
  self.project_root = get_path_manager().project_root
120
119
  # Use current working directory by default, not project root
121
- self.working_directory = working_directory or Path(os.getcwd())
120
+ self.working_directory = working_directory or Path(Path.cwd())
122
121
  self.memories_dir = self.working_directory / ".claude-mpm" / "memories"
123
122
  self.router = MemoryRouter(config)
124
123
  self.project_analyzer = ProjectAnalyzer(config, self.working_directory)
@@ -573,7 +573,7 @@ class IndexedMemoryService:
573
573
  self.text_index.save(self.data_dir / "text_index.pkl")
574
574
 
575
575
  # Save other indexes
576
- with open(self.data_dir / "indexes.pkl", "wb") as f:
576
+ with Path(self.data_dir / "indexes.pkl").open("wb") as f:
577
577
  pickle.dump(
578
578
  {
579
579
  "memories": self.memories,
@@ -22,7 +22,6 @@ rather than aggressively removing content. Better to keep potentially useful
22
22
  information than lose important insights.
23
23
  """
24
24
 
25
- import os
26
25
  import re
27
26
  from datetime import datetime, timezone
28
27
  from difflib import SequenceMatcher
@@ -79,7 +78,7 @@ class MemoryOptimizer(LoggerMixin):
79
78
  self.config = config or Config()
80
79
  self.project_root = get_path_manager().get_project_root()
81
80
  # Use current working directory by default, not project root
82
- self.working_directory = working_directory or Path(os.getcwd())
81
+ self.working_directory = working_directory or Path(Path.cwd())
83
82
  self.memories_dir = self.working_directory / ".claude-mpm" / "memories"
84
83
 
85
84
  def optimize_agent_memory(self, agent_id: str) -> Dict[str, Any]:
@@ -561,7 +561,7 @@ class DaemonManager:
561
561
  # Open log file for output redirection
562
562
  log_file_handle = None
563
563
  if self.log_file:
564
- log_file_handle = open(self.log_file, "a")
564
+ log_file_handle = Path(self.log_file).open("a")
565
565
  log_file = log_file_handle
566
566
  else:
567
567
  log_file = subprocess.DEVNULL
@@ -858,7 +858,7 @@ class DaemonManager:
858
858
  sys.stderr.flush()
859
859
 
860
860
  # Redirect stdin to /dev/null
861
- with open("/dev/null") as null_in:
861
+ with Path("/dev/null").open() as null_in:
862
862
  os.dup2(null_in.fileno(), sys.stdin.fileno())
863
863
 
864
864
  # Redirect stdout and stderr to log file
@@ -955,7 +955,7 @@ class DaemonManager:
955
955
  except Exception as e:
956
956
  # Try to write error to a debug file since logging might not work
957
957
  try:
958
- with open("/tmp/daemon_debug_error.txt", "a") as debug:
958
+ with Path("/tmp/daemon_debug_error.txt").open("a") as debug:
959
959
  debug.write(f"Error reporting error: {e}\n")
960
960
  debug.write(f"Status file: {self.startup_status_file}\n")
961
961
  except Exception: