claude-mpm 4.3.22__py3-none-any.whl → 4.4.3__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/agents/WORKFLOW.md +2 -14
- claude_mpm/cli/commands/configure.py +2 -29
- claude_mpm/cli/commands/doctor.py +2 -2
- claude_mpm/cli/commands/mpm_init.py +3 -3
- claude_mpm/cli/parsers/configure_parser.py +4 -15
- claude_mpm/core/framework/__init__.py +38 -0
- claude_mpm/core/framework/formatters/__init__.py +11 -0
- claude_mpm/core/framework/formatters/capability_generator.py +356 -0
- claude_mpm/core/framework/formatters/content_formatter.py +283 -0
- claude_mpm/core/framework/formatters/context_generator.py +180 -0
- claude_mpm/core/framework/loaders/__init__.py +13 -0
- claude_mpm/core/framework/loaders/agent_loader.py +202 -0
- claude_mpm/core/framework/loaders/file_loader.py +213 -0
- claude_mpm/core/framework/loaders/instruction_loader.py +151 -0
- claude_mpm/core/framework/loaders/packaged_loader.py +208 -0
- claude_mpm/core/framework/processors/__init__.py +11 -0
- claude_mpm/core/framework/processors/memory_processor.py +222 -0
- claude_mpm/core/framework/processors/metadata_processor.py +146 -0
- claude_mpm/core/framework/processors/template_processor.py +238 -0
- claude_mpm/core/framework_loader.py +277 -1798
- claude_mpm/hooks/__init__.py +9 -1
- claude_mpm/hooks/kuzu_memory_hook.py +352 -0
- claude_mpm/hooks/memory_integration_hook.py +1 -1
- claude_mpm/services/agents/memory/content_manager.py +5 -2
- claude_mpm/services/agents/memory/memory_file_service.py +1 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +1 -0
- claude_mpm/services/core/path_resolver.py +1 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +1 -0
- claude_mpm/services/mcp_config_manager.py +67 -4
- claude_mpm/services/mcp_gateway/core/process_pool.py +281 -0
- claude_mpm/services/mcp_gateway/core/startup_verification.py +2 -2
- claude_mpm/services/mcp_gateway/main.py +3 -13
- claude_mpm/services/mcp_gateway/server/stdio_server.py +4 -10
- claude_mpm/services/mcp_gateway/tools/__init__.py +13 -2
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +36 -6
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +542 -0
- claude_mpm/services/shared/__init__.py +2 -1
- claude_mpm/services/shared/service_factory.py +8 -5
- claude_mpm/services/unified/__init__.py +65 -0
- claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +473 -0
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +643 -0
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +804 -0
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +661 -0
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +696 -0
- claude_mpm/services/unified/config_strategies/__init__.py +190 -0
- claude_mpm/services/unified/config_strategies/config_schema.py +689 -0
- claude_mpm/services/unified/config_strategies/context_strategy.py +748 -0
- claude_mpm/services/unified/config_strategies/error_handling_strategy.py +999 -0
- claude_mpm/services/unified/config_strategies/file_loader_strategy.py +871 -0
- claude_mpm/services/unified/config_strategies/unified_config_service.py +802 -0
- claude_mpm/services/unified/config_strategies/validation_strategy.py +1105 -0
- claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
- claude_mpm/services/unified/deployment_strategies/base.py +557 -0
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +486 -0
- claude_mpm/services/unified/deployment_strategies/local.py +594 -0
- claude_mpm/services/unified/deployment_strategies/utils.py +672 -0
- claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
- claude_mpm/services/unified/interfaces.py +499 -0
- claude_mpm/services/unified/migration.py +532 -0
- claude_mpm/services/unified/strategies.py +551 -0
- claude_mpm/services/unified/unified_analyzer.py +534 -0
- claude_mpm/services/unified/unified_config.py +688 -0
- claude_mpm/services/unified/unified_deployment.py +470 -0
- {claude_mpm-4.3.22.dist-info → claude_mpm-4.4.3.dist-info}/METADATA +15 -15
- {claude_mpm-4.3.22.dist-info → claude_mpm-4.4.3.dist-info}/RECORD +71 -32
- claude_mpm/cli/commands/configure_tui.py +0 -1927
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +0 -645
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +0 -602
- {claude_mpm-4.3.22.dist-info → claude_mpm-4.4.3.dist-info}/WHEEL +0 -0
- {claude_mpm-4.3.22.dist-info → claude_mpm-4.4.3.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.3.22.dist-info → claude_mpm-4.4.3.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.3.22.dist-info → claude_mpm-4.4.3.dist-info}/top_level.txt +0 -0
@@ -377,8 +377,289 @@ 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
|
+
config_manager = MCPConfigManager()
|
399
|
+
|
400
|
+
# Check if mcp-vector-search is already installed
|
401
|
+
vector_search_path = config_manager.detect_service_path("mcp-vector-search")
|
402
|
+
|
403
|
+
if vector_search_path:
|
404
|
+
logger.debug(f"mcp-vector-search found at: {vector_search_path}")
|
405
|
+
else:
|
406
|
+
# Not installed - attempt installation
|
407
|
+
logger.info("🔍 mcp-vector-search not found. Installing via pipx...")
|
408
|
+
|
409
|
+
# First check if pipx is available
|
410
|
+
import shutil
|
411
|
+
import subprocess
|
412
|
+
|
413
|
+
if not shutil.which("pipx"):
|
414
|
+
logger.warning("⚠️ pipx not found. Please install pipx to enable automatic mcp-vector-search installation")
|
415
|
+
logger.info(" Install pipx with: python -m pip install --user pipx")
|
416
|
+
return
|
417
|
+
|
418
|
+
try:
|
419
|
+
result = subprocess.run(
|
420
|
+
["pipx", "install", "mcp-vector-search"],
|
421
|
+
capture_output=True,
|
422
|
+
text=True,
|
423
|
+
timeout=60 # 1 minute timeout for installation
|
424
|
+
)
|
425
|
+
|
426
|
+
if result.returncode == 0:
|
427
|
+
logger.info("✅ mcp-vector-search installed successfully")
|
428
|
+
# Detect the newly installed path
|
429
|
+
vector_search_path = config_manager.detect_service_path("mcp-vector-search")
|
430
|
+
if not vector_search_path:
|
431
|
+
logger.warning("mcp-vector-search installed but command not found in PATH")
|
432
|
+
return
|
433
|
+
|
434
|
+
# Update the Claude configuration to include the newly installed service
|
435
|
+
logger.info("📝 Updating Claude configuration...")
|
436
|
+
config_success, config_msg = config_manager.ensure_mcp_services_configured()
|
437
|
+
if config_success:
|
438
|
+
logger.info(f"✅ {config_msg}")
|
439
|
+
else:
|
440
|
+
logger.warning(f"⚠️ Configuration update issue: {config_msg}")
|
441
|
+
else:
|
442
|
+
logger.warning(f"Failed to install mcp-vector-search: {result.stderr}")
|
443
|
+
return
|
444
|
+
|
445
|
+
except subprocess.TimeoutExpired:
|
446
|
+
logger.warning("Installation of mcp-vector-search timed out")
|
447
|
+
return
|
448
|
+
except Exception as e:
|
449
|
+
logger.warning(f"Error installing mcp-vector-search: {e}")
|
450
|
+
return
|
451
|
+
|
452
|
+
# At this point, mcp-vector-search should be available
|
453
|
+
# Get the actual command to use
|
454
|
+
import shutil
|
455
|
+
vector_search_cmd = shutil.which("mcp-vector-search")
|
456
|
+
if not vector_search_cmd:
|
457
|
+
# Try pipx installation path as fallback
|
458
|
+
pipx_path = Path.home() / ".local/pipx/venvs/mcp-vector-search/bin/mcp-vector-search"
|
459
|
+
if pipx_path.exists():
|
460
|
+
vector_search_cmd = str(pipx_path)
|
461
|
+
else:
|
462
|
+
logger.debug("mcp-vector-search command not found after installation")
|
463
|
+
return
|
464
|
+
|
465
|
+
# Check if current project is already initialized
|
466
|
+
current_dir = Path.cwd()
|
467
|
+
vector_config = current_dir / ".mcp-vector-search/config.json"
|
468
|
+
|
469
|
+
if vector_config.exists():
|
470
|
+
logger.debug(f"Vector search already initialized for {current_dir}")
|
471
|
+
# Check if index needs rebuilding (corrupted database)
|
472
|
+
chroma_db = current_dir / ".mcp-vector-search/chroma.sqlite3"
|
473
|
+
if chroma_db.exists():
|
474
|
+
# Quick health check - verify database file exists and is accessible
|
475
|
+
try:
|
476
|
+
# Check if database file exists and has reasonable size
|
477
|
+
if chroma_db.exists() and chroma_db.stat().st_size > 0:
|
478
|
+
logger.info("✓ Vector search index is healthy and ready")
|
479
|
+
return
|
480
|
+
else:
|
481
|
+
logger.info("⚠️ Vector search index may be corrupted, rebuilding...")
|
482
|
+
except Exception as e:
|
483
|
+
logger.debug(f"Vector search health check failed: {e}, will attempt to rebuild")
|
484
|
+
|
485
|
+
# Initialize or reinitialize the project
|
486
|
+
logger.info(f"🎯 Initializing vector search for project: {current_dir}")
|
487
|
+
|
488
|
+
# Initialize the project (this creates the config)
|
489
|
+
# Note: mcp-vector-search operates on the current directory
|
490
|
+
import subprocess
|
491
|
+
proc = subprocess.run(
|
492
|
+
[vector_search_cmd, "init"],
|
493
|
+
capture_output=True,
|
494
|
+
text=True,
|
495
|
+
timeout=30,
|
496
|
+
cwd=str(current_dir) # Run in the project directory
|
497
|
+
)
|
498
|
+
|
499
|
+
if proc.returncode == 0:
|
500
|
+
logger.info("✅ Vector search initialization completed")
|
501
|
+
|
502
|
+
# Start background indexing (non-blocking)
|
503
|
+
def background_index():
|
504
|
+
try:
|
505
|
+
logger.info("🔄 Starting project indexing in background...")
|
506
|
+
index_proc = subprocess.run(
|
507
|
+
[vector_search_cmd, "index", "main"],
|
508
|
+
capture_output=True,
|
509
|
+
text=True,
|
510
|
+
timeout=300, # 5 minute timeout for indexing
|
511
|
+
cwd=str(current_dir) # Run in the project directory
|
512
|
+
)
|
513
|
+
if index_proc.returncode == 0:
|
514
|
+
logger.info("✅ Project indexing completed successfully")
|
515
|
+
# Parse output to show statistics if available
|
516
|
+
if "indexed" in index_proc.stdout.lower():
|
517
|
+
# Extract and log indexing statistics
|
518
|
+
lines = index_proc.stdout.strip().split('\n')
|
519
|
+
for line in lines:
|
520
|
+
if "indexed" in line.lower() or "files" in line.lower():
|
521
|
+
logger.info(f" {line.strip()}")
|
522
|
+
else:
|
523
|
+
logger.warning(f"⚠️ Project indexing failed: {index_proc.stderr}")
|
524
|
+
except subprocess.TimeoutExpired:
|
525
|
+
logger.warning("⚠️ Project indexing timed out (will continue in background)")
|
526
|
+
except Exception as e:
|
527
|
+
logger.debug(f"Background indexing error (non-critical): {e}")
|
528
|
+
|
529
|
+
# Run indexing in background thread
|
530
|
+
import threading
|
531
|
+
index_thread = threading.Thread(target=background_index, daemon=True)
|
532
|
+
index_thread.start()
|
533
|
+
logger.info("📚 Background indexing started - vector search will be available shortly")
|
534
|
+
|
535
|
+
else:
|
536
|
+
logger.warning(f"⚠️ Vector search initialization failed: {proc.stderr}")
|
537
|
+
|
538
|
+
except Exception as e:
|
539
|
+
logger.debug(f"Vector search auto-initialization error (non-critical): {e}")
|
540
|
+
|
541
|
+
|
542
|
+
async def auto_initialize_kuzu_memory():
|
543
|
+
"""
|
544
|
+
Auto-initialize kuzu-memory for persistent knowledge storage.
|
545
|
+
|
546
|
+
WHY: Kuzu-memory provides a graph database for structured memory storage
|
547
|
+
with semantic search capabilities, enabling persistent context across sessions.
|
548
|
+
|
549
|
+
DESIGN DECISION:
|
550
|
+
- Automatically install kuzu-memory if not present via pipx
|
551
|
+
- Initialize database in background to avoid blocking startup
|
552
|
+
- Failures are logged but don't prevent the system from starting
|
553
|
+
"""
|
554
|
+
logger = get_logger("kuzu_memory_init")
|
555
|
+
|
556
|
+
try:
|
557
|
+
# Import MCPConfigManager to handle installation
|
558
|
+
from claude_mpm.services.mcp_config_manager import MCPConfigManager
|
559
|
+
config_manager = MCPConfigManager()
|
560
|
+
|
561
|
+
# Check if kuzu-memory is already installed
|
562
|
+
kuzu_memory_path = config_manager.detect_service_path("kuzu-memory")
|
563
|
+
|
564
|
+
if kuzu_memory_path:
|
565
|
+
logger.debug(f"kuzu-memory found at: {kuzu_memory_path}")
|
566
|
+
else:
|
567
|
+
# Not installed - attempt installation
|
568
|
+
logger.info("🧠 kuzu-memory not found. Installing via pipx...")
|
569
|
+
|
570
|
+
# First check if pipx is available
|
571
|
+
import shutil
|
572
|
+
import subprocess
|
573
|
+
|
574
|
+
if not shutil.which("pipx"):
|
575
|
+
logger.warning("⚠️ pipx not found. Please install pipx to enable automatic kuzu-memory installation")
|
576
|
+
logger.info(" Install pipx with: python -m pip install --user pipx")
|
577
|
+
return
|
578
|
+
|
579
|
+
try:
|
580
|
+
result = subprocess.run(
|
581
|
+
["pipx", "install", "kuzu-memory"],
|
582
|
+
capture_output=True,
|
583
|
+
text=True,
|
584
|
+
timeout=60 # 1 minute timeout for installation
|
585
|
+
)
|
586
|
+
|
587
|
+
if result.returncode == 0:
|
588
|
+
logger.info("✅ kuzu-memory installed successfully")
|
589
|
+
# Detect the newly installed path
|
590
|
+
kuzu_memory_path = config_manager.detect_service_path("kuzu-memory")
|
591
|
+
if not kuzu_memory_path:
|
592
|
+
logger.warning("kuzu-memory installed but command not found in PATH")
|
593
|
+
return
|
594
|
+
|
595
|
+
# Update the Claude configuration to include the newly installed service
|
596
|
+
logger.info("📝 Updating Claude configuration...")
|
597
|
+
config_success, config_msg = config_manager.ensure_mcp_services_configured()
|
598
|
+
if config_success:
|
599
|
+
logger.info(f"✅ {config_msg}")
|
600
|
+
else:
|
601
|
+
logger.warning(f"⚠️ Configuration update issue: {config_msg}")
|
602
|
+
else:
|
603
|
+
logger.warning(f"Failed to install kuzu-memory: {result.stderr}")
|
604
|
+
return
|
605
|
+
|
606
|
+
except subprocess.TimeoutExpired:
|
607
|
+
logger.warning("Installation of kuzu-memory timed out")
|
608
|
+
return
|
609
|
+
except Exception as e:
|
610
|
+
logger.warning(f"Error installing kuzu-memory: {e}")
|
611
|
+
return
|
612
|
+
|
613
|
+
# At this point, kuzu-memory should be available
|
614
|
+
# Get the actual command to use
|
615
|
+
import shutil
|
616
|
+
kuzu_memory_cmd = shutil.which("kuzu-memory")
|
617
|
+
if not kuzu_memory_cmd:
|
618
|
+
# Try pipx installation path as fallback
|
619
|
+
pipx_path = Path.home() / ".local/pipx/venvs/kuzu-memory/bin/kuzu-memory"
|
620
|
+
if pipx_path.exists():
|
621
|
+
kuzu_memory_cmd = str(pipx_path)
|
622
|
+
else:
|
623
|
+
logger.debug("kuzu-memory command not found after installation")
|
624
|
+
return
|
625
|
+
|
626
|
+
# Initialize kuzu-memory database in current project
|
627
|
+
current_dir = Path.cwd()
|
628
|
+
kuzu_memories_dir = current_dir / "kuzu-memories"
|
629
|
+
|
630
|
+
# Check if database is already initialized
|
631
|
+
if kuzu_memories_dir.exists():
|
632
|
+
logger.debug(f"Kuzu-memory database already initialized at {kuzu_memories_dir}")
|
633
|
+
else:
|
634
|
+
logger.info(f"🎯 Initializing kuzu-memory database for project: {current_dir}")
|
635
|
+
|
636
|
+
# Initialize the database in current project directory
|
637
|
+
import subprocess
|
638
|
+
proc = subprocess.run(
|
639
|
+
[kuzu_memory_cmd, "init"],
|
640
|
+
capture_output=True,
|
641
|
+
text=True,
|
642
|
+
timeout=30,
|
643
|
+
cwd=str(current_dir),
|
644
|
+
)
|
645
|
+
|
646
|
+
if proc.returncode == 0:
|
647
|
+
logger.info("✅ Kuzu-memory database initialized successfully")
|
648
|
+
else:
|
649
|
+
logger.warning(f"⚠️ Kuzu-memory initialization failed: {proc.stderr}")
|
650
|
+
|
651
|
+
except Exception as e:
|
652
|
+
logger.debug(f"Kuzu-memory auto-initialization error (non-critical): {e}")
|
653
|
+
|
654
|
+
|
380
655
|
async def pre_warm_mcp_servers():
|
381
656
|
"""Pre-warm MCP servers from configuration."""
|
657
|
+
# Auto-initialize vector search for current project
|
658
|
+
await auto_initialize_vector_search()
|
659
|
+
|
660
|
+
# Auto-initialize kuzu-memory for persistent knowledge
|
661
|
+
await auto_initialize_kuzu_memory()
|
662
|
+
|
382
663
|
pool = get_process_pool()
|
383
664
|
|
384
665
|
# 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
|
-
|
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
|
-
|
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
|
-
|
111
|
-
|
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
|
-
#
|
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
|
-
#
|
33
|
-
|
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
|
-
|
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,7 +12,14 @@ from .base_adapter import (
|
|
12
12
|
SystemInfoToolAdapter,
|
13
13
|
)
|
14
14
|
from .document_summarizer import DocumentSummarizerTool
|
15
|
-
from .
|
15
|
+
from .kuzu_memory_service import (
|
16
|
+
KuzuMemoryService,
|
17
|
+
store_memory,
|
18
|
+
recall_memories,
|
19
|
+
search_memories,
|
20
|
+
get_context,
|
21
|
+
)
|
22
|
+
# Ticket tools removed - using mcp-ticketer instead
|
16
23
|
|
17
24
|
__all__ = [
|
18
25
|
"BaseToolAdapter",
|
@@ -20,5 +27,9 @@ __all__ = [
|
|
20
27
|
"DocumentSummarizerTool",
|
21
28
|
"EchoToolAdapter",
|
22
29
|
"SystemInfoToolAdapter",
|
23
|
-
"
|
30
|
+
"KuzuMemoryService",
|
31
|
+
"store_memory",
|
32
|
+
"recall_memories",
|
33
|
+
"search_memories",
|
34
|
+
"get_context",
|
24
35
|
]
|
@@ -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
|
19
|
+
from claude_mpm.services.mcp_gateway.tools.base_adapter import BaseToolAdapter
|
20
20
|
|
21
21
|
|
22
|
-
class ExternalMCPService(
|
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
|
-
|
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.
|
47
|
-
f"{self.package_name} not installed
|
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,7 @@ class ExternalMCPServiceManager:
|
|
402
432
|
f"Initialized external service: {service.service_name}"
|
403
433
|
)
|
404
434
|
elif self.logger:
|
405
|
-
self.logger.
|
435
|
+
self.logger.debug(f"Service not available (optional): {service.service_name}")
|
406
436
|
except Exception as e:
|
407
437
|
if self.logger:
|
408
438
|
self.logger.error(f"Error initializing {service.service_name}: {e}")
|