claude-mpm 4.4.0__py3-none-any.whl → 4.4.4__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 (129) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/WORKFLOW.md +2 -14
  3. claude_mpm/agents/agent_loader.py +3 -2
  4. claude_mpm/agents/agent_loader_integration.py +2 -1
  5. claude_mpm/agents/async_agent_loader.py +2 -2
  6. claude_mpm/agents/base_agent_loader.py +2 -2
  7. claude_mpm/agents/frontmatter_validator.py +1 -0
  8. claude_mpm/agents/system_agent_config.py +2 -1
  9. claude_mpm/cli/commands/configure.py +2 -29
  10. claude_mpm/cli/commands/doctor.py +44 -5
  11. claude_mpm/cli/commands/mpm_init.py +117 -63
  12. claude_mpm/cli/parsers/configure_parser.py +6 -15
  13. claude_mpm/cli/startup_logging.py +1 -3
  14. claude_mpm/config/agent_config.py +1 -1
  15. claude_mpm/config/paths.py +2 -1
  16. claude_mpm/core/agent_name_normalizer.py +1 -0
  17. claude_mpm/core/config.py +2 -1
  18. claude_mpm/core/config_aliases.py +2 -1
  19. claude_mpm/core/file_utils.py +0 -1
  20. claude_mpm/core/framework/__init__.py +38 -0
  21. claude_mpm/core/framework/formatters/__init__.py +11 -0
  22. claude_mpm/core/framework/formatters/capability_generator.py +367 -0
  23. claude_mpm/core/framework/formatters/content_formatter.py +288 -0
  24. claude_mpm/core/framework/formatters/context_generator.py +184 -0
  25. claude_mpm/core/framework/loaders/__init__.py +13 -0
  26. claude_mpm/core/framework/loaders/agent_loader.py +206 -0
  27. claude_mpm/core/framework/loaders/file_loader.py +223 -0
  28. claude_mpm/core/framework/loaders/instruction_loader.py +161 -0
  29. claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
  30. claude_mpm/core/framework/processors/__init__.py +11 -0
  31. claude_mpm/core/framework/processors/memory_processor.py +230 -0
  32. claude_mpm/core/framework/processors/metadata_processor.py +146 -0
  33. claude_mpm/core/framework/processors/template_processor.py +244 -0
  34. claude_mpm/core/framework_loader.py +298 -1795
  35. claude_mpm/core/log_manager.py +2 -1
  36. claude_mpm/core/tool_access_control.py +1 -0
  37. claude_mpm/core/unified_agent_registry.py +2 -1
  38. claude_mpm/core/unified_paths.py +1 -0
  39. claude_mpm/experimental/cli_enhancements.py +1 -0
  40. claude_mpm/hooks/__init__.py +9 -1
  41. claude_mpm/hooks/base_hook.py +1 -0
  42. claude_mpm/hooks/instruction_reinforcement.py +1 -0
  43. claude_mpm/hooks/kuzu_memory_hook.py +359 -0
  44. claude_mpm/hooks/validation_hooks.py +1 -1
  45. claude_mpm/scripts/mpm_doctor.py +1 -0
  46. claude_mpm/services/agents/loading/agent_profile_loader.py +1 -1
  47. claude_mpm/services/agents/loading/base_agent_manager.py +1 -1
  48. claude_mpm/services/agents/loading/framework_agent_loader.py +1 -1
  49. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -0
  50. claude_mpm/services/agents/management/agent_management_service.py +1 -1
  51. claude_mpm/services/agents/memory/memory_categorization_service.py +0 -1
  52. claude_mpm/services/agents/memory/memory_file_service.py +6 -2
  53. claude_mpm/services/agents/memory/memory_format_service.py +0 -1
  54. claude_mpm/services/agents/registry/deployed_agent_discovery.py +1 -1
  55. claude_mpm/services/async_session_logger.py +1 -1
  56. claude_mpm/services/claude_session_logger.py +1 -0
  57. claude_mpm/services/core/path_resolver.py +2 -0
  58. claude_mpm/services/diagnostics/checks/__init__.py +2 -0
  59. claude_mpm/services/diagnostics/checks/installation_check.py +126 -25
  60. claude_mpm/services/diagnostics/checks/mcp_services_check.py +399 -0
  61. claude_mpm/services/diagnostics/diagnostic_runner.py +4 -0
  62. claude_mpm/services/diagnostics/doctor_reporter.py +259 -32
  63. claude_mpm/services/event_bus/direct_relay.py +2 -1
  64. claude_mpm/services/event_bus/event_bus.py +1 -0
  65. claude_mpm/services/event_bus/relay.py +3 -2
  66. claude_mpm/services/framework_claude_md_generator/content_assembler.py +1 -1
  67. claude_mpm/services/infrastructure/daemon_manager.py +1 -1
  68. claude_mpm/services/mcp_config_manager.py +67 -4
  69. claude_mpm/services/mcp_gateway/core/process_pool.py +320 -0
  70. claude_mpm/services/mcp_gateway/core/startup_verification.py +2 -2
  71. claude_mpm/services/mcp_gateway/main.py +3 -13
  72. claude_mpm/services/mcp_gateway/server/stdio_server.py +4 -10
  73. claude_mpm/services/mcp_gateway/tools/__init__.py +14 -2
  74. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +38 -6
  75. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +527 -0
  76. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  77. claude_mpm/services/project/archive_manager.py +159 -96
  78. claude_mpm/services/project/documentation_manager.py +64 -45
  79. claude_mpm/services/project/enhanced_analyzer.py +132 -89
  80. claude_mpm/services/project/project_organizer.py +225 -131
  81. claude_mpm/services/response_tracker.py +1 -1
  82. claude_mpm/services/shared/__init__.py +2 -1
  83. claude_mpm/services/shared/service_factory.py +8 -5
  84. claude_mpm/services/socketio/server/eventbus_integration.py +1 -1
  85. claude_mpm/services/unified/__init__.py +1 -1
  86. claude_mpm/services/unified/analyzer_strategies/__init__.py +3 -3
  87. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +97 -53
  88. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +81 -40
  89. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +277 -178
  90. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +196 -112
  91. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +83 -49
  92. claude_mpm/services/unified/config_strategies/__init__.py +175 -0
  93. claude_mpm/services/unified/config_strategies/config_schema.py +735 -0
  94. claude_mpm/services/unified/config_strategies/context_strategy.py +750 -0
  95. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1009 -0
  96. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +879 -0
  97. claude_mpm/services/unified/config_strategies/unified_config_service.py +814 -0
  98. claude_mpm/services/unified/config_strategies/validation_strategy.py +1144 -0
  99. claude_mpm/services/unified/deployment_strategies/__init__.py +7 -7
  100. claude_mpm/services/unified/deployment_strategies/base.py +24 -28
  101. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +168 -88
  102. claude_mpm/services/unified/deployment_strategies/local.py +49 -34
  103. claude_mpm/services/unified/deployment_strategies/utils.py +39 -43
  104. claude_mpm/services/unified/deployment_strategies/vercel.py +30 -24
  105. claude_mpm/services/unified/interfaces.py +0 -26
  106. claude_mpm/services/unified/migration.py +17 -40
  107. claude_mpm/services/unified/strategies.py +9 -26
  108. claude_mpm/services/unified/unified_analyzer.py +48 -44
  109. claude_mpm/services/unified/unified_config.py +21 -19
  110. claude_mpm/services/unified/unified_deployment.py +21 -26
  111. claude_mpm/storage/state_storage.py +1 -0
  112. claude_mpm/utils/agent_dependency_loader.py +18 -6
  113. claude_mpm/utils/common.py +14 -12
  114. claude_mpm/utils/database_connector.py +15 -12
  115. claude_mpm/utils/error_handler.py +1 -0
  116. claude_mpm/utils/log_cleanup.py +1 -0
  117. claude_mpm/utils/path_operations.py +1 -0
  118. claude_mpm/utils/session_logging.py +1 -1
  119. claude_mpm/utils/subprocess_utils.py +1 -0
  120. claude_mpm/validation/agent_validator.py +1 -1
  121. {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/METADATA +23 -17
  122. {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/RECORD +126 -105
  123. claude_mpm/cli/commands/configure_tui.py +0 -1927
  124. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +0 -645
  125. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +0 -602
  126. {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/WHEEL +0 -0
  127. {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/entry_points.txt +0 -0
  128. {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/licenses/LICENSE +0 -0
  129. {claude_mpm-4.4.0.dist-info → claude_mpm-4.4.4.dist-info}/top_level.txt +0 -0
@@ -377,8 +377,328 @@ def get_process_pool() -> MCPProcessPool:
377
377
  return _pool
378
378
 
379
379
 
380
+ async def auto_initialize_vector_search():
381
+ """
382
+ Auto-initialize mcp-vector-search for the current project.
383
+
384
+ WHY: Vector search requires project initialization before it can be used.
385
+ This function ensures the current project is automatically initialized
386
+ for vector search when the system starts up.
387
+
388
+ DESIGN DECISION:
389
+ - Automatically install mcp-vector-search if not present
390
+ - Run in background with timeout to avoid blocking startup
391
+ - Failures are logged but don't prevent the system from starting
392
+ """
393
+ logger = get_logger("vector_search_init")
394
+
395
+ try:
396
+ # Import MCPConfigManager to handle installation
397
+ from claude_mpm.services.mcp_config_manager import MCPConfigManager
398
+
399
+ config_manager = MCPConfigManager()
400
+
401
+ # Check if mcp-vector-search is already installed
402
+ vector_search_path = config_manager.detect_service_path("mcp-vector-search")
403
+
404
+ if vector_search_path:
405
+ logger.debug(f"mcp-vector-search found at: {vector_search_path}")
406
+ else:
407
+ # Not installed - attempt installation
408
+ logger.info("🔍 mcp-vector-search not found. Installing via pipx...")
409
+
410
+ # First check if pipx is available
411
+ import shutil
412
+ import subprocess
413
+
414
+ if not shutil.which("pipx"):
415
+ logger.warning(
416
+ "⚠️ pipx not found. Please install pipx to enable automatic mcp-vector-search installation"
417
+ )
418
+ logger.info(" Install pipx with: python -m pip install --user pipx")
419
+ return
420
+
421
+ try:
422
+ result = subprocess.run(
423
+ ["pipx", "install", "mcp-vector-search"],
424
+ capture_output=True,
425
+ text=True,
426
+ timeout=60, check=False, # 1 minute timeout for installation
427
+ )
428
+
429
+ if result.returncode == 0:
430
+ logger.info("✅ mcp-vector-search installed successfully")
431
+ # Detect the newly installed path
432
+ vector_search_path = config_manager.detect_service_path(
433
+ "mcp-vector-search"
434
+ )
435
+ if not vector_search_path:
436
+ logger.warning(
437
+ "mcp-vector-search installed but command not found in PATH"
438
+ )
439
+ return
440
+
441
+ # Update the Claude configuration to include the newly installed service
442
+ logger.info("📝 Updating Claude configuration...")
443
+ config_success, config_msg = (
444
+ config_manager.ensure_mcp_services_configured()
445
+ )
446
+ if config_success:
447
+ logger.info(f"✅ {config_msg}")
448
+ else:
449
+ logger.warning(f"⚠️ Configuration update issue: {config_msg}")
450
+ else:
451
+ logger.warning(
452
+ f"Failed to install mcp-vector-search: {result.stderr}"
453
+ )
454
+ return
455
+
456
+ except subprocess.TimeoutExpired:
457
+ logger.warning("Installation of mcp-vector-search timed out")
458
+ return
459
+ except Exception as e:
460
+ logger.warning(f"Error installing mcp-vector-search: {e}")
461
+ return
462
+
463
+ # At this point, mcp-vector-search should be available
464
+ # Get the actual command to use
465
+ import shutil
466
+
467
+ vector_search_cmd = shutil.which("mcp-vector-search")
468
+ if not vector_search_cmd:
469
+ # Try pipx installation path as fallback
470
+ pipx_path = (
471
+ Path.home()
472
+ / ".local/pipx/venvs/mcp-vector-search/bin/mcp-vector-search"
473
+ )
474
+ if pipx_path.exists():
475
+ vector_search_cmd = str(pipx_path)
476
+ else:
477
+ logger.debug("mcp-vector-search command not found after installation")
478
+ return
479
+
480
+ # Check if current project is already initialized
481
+ current_dir = Path.cwd()
482
+ vector_config = current_dir / ".mcp-vector-search/config.json"
483
+
484
+ if vector_config.exists():
485
+ logger.debug(f"Vector search already initialized for {current_dir}")
486
+ # Check if index needs rebuilding (corrupted database)
487
+ chroma_db = current_dir / ".mcp-vector-search/chroma.sqlite3"
488
+ if chroma_db.exists():
489
+ # Quick health check - verify database file exists and is accessible
490
+ try:
491
+ # Check if database file exists and has reasonable size
492
+ if chroma_db.exists() and chroma_db.stat().st_size > 0:
493
+ logger.info("✓ Vector search index is healthy and ready")
494
+ return
495
+ logger.info(
496
+ "⚠️ Vector search index may be corrupted, rebuilding..."
497
+ )
498
+ except Exception as e:
499
+ logger.debug(
500
+ f"Vector search health check failed: {e}, will attempt to rebuild"
501
+ )
502
+
503
+ # Initialize or reinitialize the project
504
+ logger.info(f"🎯 Initializing vector search for project: {current_dir}")
505
+
506
+ # Initialize the project (this creates the config)
507
+ # Note: mcp-vector-search operates on the current directory
508
+ import subprocess
509
+
510
+ proc = subprocess.run(
511
+ [vector_search_cmd, "init"],
512
+ capture_output=True,
513
+ text=True,
514
+ timeout=30,
515
+ cwd=str(current_dir), check=False, # Run in the project directory
516
+ )
517
+
518
+ if proc.returncode == 0:
519
+ logger.info("✅ Vector search initialization completed")
520
+
521
+ # Start background indexing (non-blocking)
522
+ def background_index():
523
+ try:
524
+ logger.info("🔄 Starting project indexing in background...")
525
+ index_proc = subprocess.run(
526
+ [vector_search_cmd, "index", "main"],
527
+ capture_output=True,
528
+ text=True,
529
+ timeout=300, # 5 minute timeout for indexing
530
+ cwd=str(current_dir), check=False, # Run in the project directory
531
+ )
532
+ if index_proc.returncode == 0:
533
+ logger.info("✅ Project indexing completed successfully")
534
+ # Parse output to show statistics if available
535
+ if "indexed" in index_proc.stdout.lower():
536
+ # Extract and log indexing statistics
537
+ lines = index_proc.stdout.strip().split("\n")
538
+ for line in lines:
539
+ if "indexed" in line.lower() or "files" in line.lower():
540
+ logger.info(f" {line.strip()}")
541
+ else:
542
+ logger.warning(
543
+ f"⚠️ Project indexing failed: {index_proc.stderr}"
544
+ )
545
+ except subprocess.TimeoutExpired:
546
+ logger.warning(
547
+ "⚠️ Project indexing timed out (will continue in background)"
548
+ )
549
+ except Exception as e:
550
+ logger.debug(f"Background indexing error (non-critical): {e}")
551
+
552
+ # Run indexing in background thread
553
+ import threading
554
+
555
+ index_thread = threading.Thread(target=background_index, daemon=True)
556
+ index_thread.start()
557
+ logger.info(
558
+ "📚 Background indexing started - vector search will be available shortly"
559
+ )
560
+
561
+ else:
562
+ logger.warning(f"⚠️ Vector search initialization failed: {proc.stderr}")
563
+
564
+ except Exception as e:
565
+ logger.debug(f"Vector search auto-initialization error (non-critical): {e}")
566
+
567
+
568
+ async def auto_initialize_kuzu_memory():
569
+ """
570
+ Auto-initialize kuzu-memory for persistent knowledge storage.
571
+
572
+ WHY: Kuzu-memory provides a graph database for structured memory storage
573
+ with semantic search capabilities, enabling persistent context across sessions.
574
+
575
+ DESIGN DECISION:
576
+ - Automatically install kuzu-memory if not present via pipx
577
+ - Initialize database in background to avoid blocking startup
578
+ - Failures are logged but don't prevent the system from starting
579
+ """
580
+ logger = get_logger("kuzu_memory_init")
581
+
582
+ try:
583
+ # Import MCPConfigManager to handle installation
584
+ from claude_mpm.services.mcp_config_manager import MCPConfigManager
585
+
586
+ config_manager = MCPConfigManager()
587
+
588
+ # Check if kuzu-memory is already installed
589
+ kuzu_memory_path = config_manager.detect_service_path("kuzu-memory")
590
+
591
+ if kuzu_memory_path:
592
+ logger.debug(f"kuzu-memory found at: {kuzu_memory_path}")
593
+ else:
594
+ # Not installed - attempt installation
595
+ logger.info("🧠 kuzu-memory not found. Installing via pipx...")
596
+
597
+ # First check if pipx is available
598
+ import shutil
599
+ import subprocess
600
+
601
+ if not shutil.which("pipx"):
602
+ logger.warning(
603
+ "⚠️ pipx not found. Please install pipx to enable automatic kuzu-memory installation"
604
+ )
605
+ logger.info(" Install pipx with: python -m pip install --user pipx")
606
+ return
607
+
608
+ try:
609
+ result = subprocess.run(
610
+ ["pipx", "install", "kuzu-memory"],
611
+ capture_output=True,
612
+ text=True,
613
+ timeout=60, check=False, # 1 minute timeout for installation
614
+ )
615
+
616
+ if result.returncode == 0:
617
+ logger.info("✅ kuzu-memory installed successfully")
618
+ # Detect the newly installed path
619
+ kuzu_memory_path = config_manager.detect_service_path("kuzu-memory")
620
+ if not kuzu_memory_path:
621
+ logger.warning(
622
+ "kuzu-memory installed but command not found in PATH"
623
+ )
624
+ return
625
+
626
+ # Update the Claude configuration to include the newly installed service
627
+ logger.info("📝 Updating Claude configuration...")
628
+ config_success, config_msg = (
629
+ config_manager.ensure_mcp_services_configured()
630
+ )
631
+ if config_success:
632
+ logger.info(f"✅ {config_msg}")
633
+ else:
634
+ logger.warning(f"⚠️ Configuration update issue: {config_msg}")
635
+ else:
636
+ logger.warning(f"Failed to install kuzu-memory: {result.stderr}")
637
+ return
638
+
639
+ except subprocess.TimeoutExpired:
640
+ logger.warning("Installation of kuzu-memory timed out")
641
+ return
642
+ except Exception as e:
643
+ logger.warning(f"Error installing kuzu-memory: {e}")
644
+ return
645
+
646
+ # At this point, kuzu-memory should be available
647
+ # Get the actual command to use
648
+ import shutil
649
+
650
+ kuzu_memory_cmd = shutil.which("kuzu-memory")
651
+ if not kuzu_memory_cmd:
652
+ # Try pipx installation path as fallback
653
+ pipx_path = Path.home() / ".local/pipx/venvs/kuzu-memory/bin/kuzu-memory"
654
+ if pipx_path.exists():
655
+ kuzu_memory_cmd = str(pipx_path)
656
+ else:
657
+ logger.debug("kuzu-memory command not found after installation")
658
+ return
659
+
660
+ # Initialize kuzu-memory database in current project
661
+ current_dir = Path.cwd()
662
+ kuzu_memories_dir = current_dir / "kuzu-memories"
663
+
664
+ # Check if database is already initialized
665
+ if kuzu_memories_dir.exists():
666
+ logger.debug(
667
+ f"Kuzu-memory database already initialized at {kuzu_memories_dir}"
668
+ )
669
+ else:
670
+ logger.info(
671
+ f"🎯 Initializing kuzu-memory database for project: {current_dir}"
672
+ )
673
+
674
+ # Initialize the database in current project directory
675
+ import subprocess
676
+
677
+ proc = subprocess.run(
678
+ [kuzu_memory_cmd, "init"],
679
+ capture_output=True,
680
+ text=True,
681
+ timeout=30,
682
+ cwd=str(current_dir), check=False,
683
+ )
684
+
685
+ if proc.returncode == 0:
686
+ logger.info("✅ Kuzu-memory database initialized successfully")
687
+ else:
688
+ logger.warning(f"⚠️ Kuzu-memory initialization failed: {proc.stderr}")
689
+
690
+ except Exception as e:
691
+ logger.debug(f"Kuzu-memory auto-initialization error (non-critical): {e}")
692
+
693
+
380
694
  async def pre_warm_mcp_servers():
381
695
  """Pre-warm MCP servers from configuration."""
696
+ # Auto-initialize vector search for current project
697
+ await auto_initialize_vector_search()
698
+
699
+ # Auto-initialize kuzu-memory for persistent knowledge
700
+ await auto_initialize_kuzu_memory()
701
+
382
702
  pool = get_process_pool()
383
703
 
384
704
  # Load MCP configurations
@@ -45,7 +45,7 @@ class MCPGatewayStartupVerifier:
45
45
  "system_info", # System diagnostics
46
46
  "health_check", # Health diagnostics
47
47
  "document_summarizer", # File summarizer
48
- "ticket", # Ticket service (unified)
48
+ # Ticket functionality now provided by mcp-ticketer
49
49
  ]
50
50
 
51
51
  async def verify_and_configure(self) -> Dict[str, Any]:
@@ -210,7 +210,7 @@ class MCPGatewayStartupVerifier:
210
210
  "..tools.document_summarizer",
211
211
  "DocumentSummarizerTool",
212
212
  ),
213
- "ticket": ("..tools.unified_ticket_tool", "UnifiedTicketTool"),
213
+ # Ticket functionality now provided by mcp-ticketer
214
214
  }
215
215
 
216
216
  if tool_name not in tool_map:
@@ -107,13 +107,8 @@ try:
107
107
  except ImportError:
108
108
  DocumentSummarizerTool = None
109
109
 
110
- try:
111
- from claude_mpm.services.mcp_gateway.tools.unified_ticket_tool import (
112
- UnifiedTicketTool,
113
- )
114
- except ImportError:
115
- # Unified ticket tool is optional
116
- UnifiedTicketTool = None
110
+ # Ticket tools removed - using mcp-ticketer instead
111
+ UnifiedTicketTool = None
117
112
 
118
113
  try:
119
114
  from claude_mpm.services.mcp_gateway.tools.external_mcp_services import (
@@ -316,12 +311,7 @@ class MCPGatewayOrchestrator:
316
311
  except Exception as e:
317
312
  self.logger.warning(f"Could not load document summarizer: {e}")
318
313
 
319
- # Optional: Unified ticket management tool
320
- if UnifiedTicketTool is not None:
321
- try:
322
- tools.append(UnifiedTicketTool())
323
- except Exception as e:
324
- self.logger.warning(f"Could not load unified ticket tool: {e}")
314
+ # Ticket tools removed - mcp-ticketer provides ticket functionality
325
315
 
326
316
  if not tools:
327
317
  self.logger.warning("No tools available to register")
@@ -29,15 +29,8 @@ from mcp.types import TextContent, Tool
29
29
  # Import pydantic for model patching
30
30
  from claude_mpm.core.logger import get_logger
31
31
 
32
- # Import unified ticket tool if available
33
- try:
34
- from claude_mpm.services.mcp_gateway.tools.unified_ticket_tool import (
35
- UnifiedTicketTool,
36
- )
37
-
38
- TICKET_TOOLS_AVAILABLE = True
39
- except ImportError:
40
- TICKET_TOOLS_AVAILABLE = False
32
+ # Ticket tools removed - using mcp-ticketer instead
33
+ TICKET_TOOLS_AVAILABLE = False
41
34
 
42
35
 
43
36
  def apply_backward_compatibility_patches():
@@ -629,7 +622,8 @@ class SimpleMCPServer:
629
622
 
630
623
  try:
631
624
  self.logger.info("Initializing unified ticket tool...")
632
- self.unified_ticket_tool = UnifiedTicketTool()
625
+ # Ticket tools removed - using mcp-ticketer instead
626
+ self.unified_ticket_tool = None
633
627
  # If the tool has an async init method, call it
634
628
  if hasattr(self.unified_ticket_tool, "initialize"):
635
629
  await self.unified_ticket_tool.initialize()
@@ -12,13 +12,25 @@ from .base_adapter import (
12
12
  SystemInfoToolAdapter,
13
13
  )
14
14
  from .document_summarizer import DocumentSummarizerTool
15
- from .unified_ticket_tool import UnifiedTicketTool
15
+ from .kuzu_memory_service import (
16
+ KuzuMemoryService,
17
+ get_context,
18
+ recall_memories,
19
+ search_memories,
20
+ store_memory,
21
+ )
22
+
23
+ # Ticket tools removed - using mcp-ticketer instead
16
24
 
17
25
  __all__ = [
18
26
  "BaseToolAdapter",
19
27
  "CalculatorToolAdapter",
20
28
  "DocumentSummarizerTool",
21
29
  "EchoToolAdapter",
30
+ "KuzuMemoryService",
22
31
  "SystemInfoToolAdapter",
23
- "UnifiedTicketTool",
32
+ "get_context",
33
+ "recall_memories",
34
+ "search_memories",
35
+ "store_memory",
24
36
  ]
@@ -16,10 +16,10 @@ import sys
16
16
  from pathlib import Path
17
17
  from typing import Any, Dict, List
18
18
 
19
- from claude_mpm.services.mcp_gateway.tools.base_adapter import BaseMCPToolAdapter
19
+ from claude_mpm.services.mcp_gateway.tools.base_adapter import BaseToolAdapter
20
20
 
21
21
 
22
- class ExternalMCPService(BaseMCPToolAdapter):
22
+ class ExternalMCPService(BaseToolAdapter):
23
23
  """Base class for external MCP service integration."""
24
24
 
25
25
  def __init__(self, service_name: str, package_name: str):
@@ -30,12 +30,40 @@ class ExternalMCPService(BaseMCPToolAdapter):
30
30
  service_name: Name of the service for MCP
31
31
  package_name: Python package name to install/run
32
32
  """
33
- super().__init__()
33
+ # Import here to avoid circular imports
34
+ from claude_mpm.services.mcp_gateway.core.interfaces import MCPToolDefinition
35
+
36
+ # Create a basic tool definition for the service
37
+ tool_def = MCPToolDefinition(
38
+ name=service_name,
39
+ description=f"External MCP service: {package_name}",
40
+ input_schema={
41
+ "type": "object",
42
+ "properties": {},
43
+ "required": [],
44
+ },
45
+ )
46
+ super().__init__(tool_def)
34
47
  self.service_name = service_name
35
48
  self.package_name = package_name
36
49
  self.process = None
37
50
  self._is_installed = False
38
51
 
52
+ async def invoke(self, invocation):
53
+ """
54
+ Invoke method required by BaseToolAdapter interface.
55
+
56
+ This base implementation should be overridden by subclasses.
57
+ """
58
+ # Import here to avoid circular imports
59
+ from claude_mpm.services.mcp_gateway.core.interfaces import MCPToolResult
60
+
61
+ return MCPToolResult(
62
+ success=False,
63
+ error="invoke method not implemented in base ExternalMCPService",
64
+ execution_time=0.0,
65
+ )
66
+
39
67
  async def initialize(self) -> bool:
40
68
  """Initialize the external service."""
41
69
  try:
@@ -43,8 +71,8 @@ class ExternalMCPService(BaseMCPToolAdapter):
43
71
  self._is_installed = await self._check_installation()
44
72
 
45
73
  if not self._is_installed:
46
- self.logger.warning(
47
- f"{self.package_name} not installed, attempting installation..."
74
+ self.logger.debug(
75
+ f"{self.package_name} not installed - will attempt automatic installation if needed"
48
76
  )
49
77
  await self._install_package()
50
78
  self._is_installed = await self._check_installation()
@@ -389,6 +417,8 @@ class ExternalMCPServiceManager:
389
417
  them as tools in the gateway - they run as separate MCP servers.
390
418
  """
391
419
  # Create service instances
420
+ # Note: kuzu-memory is configured via MCPConfigManager and runs as a separate MCP server
421
+ # It doesn't need to be included here since it's already set up through the MCP config
392
422
  services = [MCPVectorSearchService(), MCPBrowserService()]
393
423
 
394
424
  # Initialize each service
@@ -402,7 +432,9 @@ class ExternalMCPServiceManager:
402
432
  f"Initialized external service: {service.service_name}"
403
433
  )
404
434
  elif self.logger:
405
- self.logger.warning(f"Failed to initialize: {service.service_name}")
435
+ self.logger.debug(
436
+ f"Service not available (optional): {service.service_name}"
437
+ )
406
438
  except Exception as e:
407
439
  if self.logger:
408
440
  self.logger.error(f"Error initializing {service.service_name}: {e}")