claude-mpm 4.3.11__py3-none-any.whl ā 4.3.13__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/PM_INSTRUCTIONS.md +390 -28
- claude_mpm/agents/templates/data_engineer.json +39 -14
- claude_mpm/agents/templates/research.json +20 -8
- claude_mpm/agents/templates/web_qa.json +25 -10
- claude_mpm/cli/__init__.py +1 -0
- claude_mpm/cli/commands/agent_manager.py +3 -3
- claude_mpm/cli/commands/agents.py +2 -2
- claude_mpm/cli/commands/aggregate.py +1 -1
- claude_mpm/cli/commands/config.py +2 -2
- claude_mpm/cli/commands/configure.py +5 -5
- claude_mpm/cli/commands/configure_tui.py +7 -7
- claude_mpm/cli/commands/dashboard.py +1 -1
- claude_mpm/cli/commands/debug.py +5 -5
- claude_mpm/cli/commands/mcp.py +1 -1
- claude_mpm/cli/commands/mcp_command_router.py +12 -1
- claude_mpm/cli/commands/mcp_config.py +154 -0
- claude_mpm/cli/commands/mcp_external_commands.py +249 -0
- claude_mpm/cli/commands/mcp_install_commands.py +93 -24
- claude_mpm/cli/commands/mcp_setup_external.py +870 -0
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init_handler.py +1 -1
- claude_mpm/cli/commands/run.py +114 -0
- claude_mpm/cli/commands/search.py +292 -0
- claude_mpm/cli/interactive/agent_wizard.py +2 -2
- claude_mpm/cli/parsers/base_parser.py +13 -0
- claude_mpm/cli/parsers/mcp_parser.py +15 -0
- claude_mpm/cli/parsers/run_parser.py +5 -0
- claude_mpm/cli/parsers/search_parser.py +245 -0
- claude_mpm/cli/startup_logging.py +3 -5
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/constants.py +1 -0
- claude_mpm/core/agent_registry.py +12 -8
- claude_mpm/core/agent_session_manager.py +8 -8
- claude_mpm/core/api_validator.py +4 -4
- claude_mpm/core/base_service.py +10 -10
- claude_mpm/core/cache.py +5 -5
- claude_mpm/core/config_constants.py +1 -1
- claude_mpm/core/container.py +1 -1
- claude_mpm/core/error_handler.py +2 -2
- claude_mpm/core/file_utils.py +1 -1
- claude_mpm/core/framework_loader.py +3 -3
- claude_mpm/core/hook_manager.py +8 -6
- claude_mpm/core/instruction_reinforcement_hook.py +2 -2
- claude_mpm/core/interactive_session.py +1 -1
- claude_mpm/core/lazy.py +3 -3
- claude_mpm/core/log_manager.py +16 -12
- claude_mpm/core/logger.py +16 -11
- claude_mpm/core/logging_config.py +4 -2
- claude_mpm/core/oneshot_session.py +1 -1
- claude_mpm/core/optimized_agent_loader.py +6 -6
- claude_mpm/core/output_style_manager.py +1 -1
- claude_mpm/core/pm_hook_interceptor.py +3 -3
- claude_mpm/core/service_registry.py +1 -1
- claude_mpm/core/session_manager.py +11 -9
- claude_mpm/core/socketio_pool.py +13 -13
- claude_mpm/core/types.py +2 -2
- claude_mpm/core/unified_agent_registry.py +9 -2
- claude_mpm/core/unified_paths.py +1 -1
- claude_mpm/dashboard/analysis_runner.py +4 -4
- claude_mpm/dashboard/api/simple_directory.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +4 -2
- claude_mpm/hooks/base_hook.py +2 -2
- claude_mpm/hooks/claude_hooks/connection_pool.py +4 -4
- claude_mpm/hooks/claude_hooks/event_handlers.py +12 -12
- claude_mpm/hooks/claude_hooks/hook_handler.py +4 -4
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +3 -3
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +15 -14
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +4 -4
- claude_mpm/hooks/claude_hooks/installer.py +3 -3
- claude_mpm/hooks/claude_hooks/memory_integration.py +3 -3
- claude_mpm/hooks/claude_hooks/response_tracking.py +3 -3
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +5 -5
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +3 -3
- claude_mpm/hooks/claude_hooks/services/state_manager.py +8 -7
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +3 -3
- claude_mpm/hooks/claude_hooks/tool_analysis.py +2 -2
- claude_mpm/hooks/memory_integration_hook.py +1 -1
- claude_mpm/hooks/tool_call_interceptor.py +2 -2
- claude_mpm/models/agent_session.py +5 -5
- claude_mpm/services/__init__.py +1 -1
- claude_mpm/services/agent_capabilities_service.py +1 -1
- claude_mpm/services/agents/agent_builder.py +3 -3
- claude_mpm/services/agents/deployment/agent_deployment.py +29 -13
- claude_mpm/services/agents/deployment/agent_discovery_service.py +22 -6
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +7 -5
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +3 -1
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +1 -1
- claude_mpm/services/agents/deployment/agent_operation_service.py +2 -2
- claude_mpm/services/agents/deployment/agent_state_service.py +2 -2
- claude_mpm/services/agents/deployment/agent_template_builder.py +1 -1
- claude_mpm/services/agents/deployment/agent_versioning.py +1 -1
- claude_mpm/services/agents/deployment/deployment_wrapper.py +2 -3
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +6 -4
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +1 -1
- claude_mpm/services/agents/loading/agent_profile_loader.py +5 -3
- claude_mpm/services/agents/loading/base_agent_manager.py +2 -2
- claude_mpm/services/agents/local_template_manager.py +6 -6
- claude_mpm/services/agents/management/agent_management_service.py +3 -3
- claude_mpm/services/agents/memory/content_manager.py +3 -3
- claude_mpm/services/agents/memory/memory_format_service.py +2 -2
- claude_mpm/services/agents/memory/template_generator.py +3 -3
- claude_mpm/services/agents/registry/__init__.py +1 -1
- claude_mpm/services/agents/registry/modification_tracker.py +2 -2
- claude_mpm/services/async_session_logger.py +3 -3
- claude_mpm/services/claude_session_logger.py +4 -4
- claude_mpm/services/cli/agent_cleanup_service.py +5 -0
- claude_mpm/services/cli/agent_listing_service.py +1 -1
- claude_mpm/services/cli/agent_validation_service.py +1 -0
- claude_mpm/services/cli/memory_crud_service.py +11 -6
- claude_mpm/services/cli/memory_output_formatter.py +1 -1
- claude_mpm/services/cli/session_manager.py +15 -11
- claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
- claude_mpm/services/core/memory_manager.py +81 -23
- claude_mpm/services/core/path_resolver.py +2 -2
- claude_mpm/services/diagnostics/checks/installation_check.py +1 -1
- claude_mpm/services/event_aggregator.py +4 -2
- claude_mpm/services/event_bus/direct_relay.py +5 -3
- claude_mpm/services/event_bus/event_bus.py +3 -3
- claude_mpm/services/event_bus/relay.py +6 -4
- claude_mpm/services/events/consumers/dead_letter.py +5 -3
- claude_mpm/services/events/core.py +3 -3
- claude_mpm/services/events/producers/hook.py +6 -6
- claude_mpm/services/events/producers/system.py +8 -8
- claude_mpm/services/exceptions.py +5 -5
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +2 -2
- claude_mpm/services/hook_installer_service.py +1 -1
- claude_mpm/services/infrastructure/context_preservation.py +6 -4
- claude_mpm/services/infrastructure/daemon_manager.py +2 -2
- claude_mpm/services/infrastructure/logging.py +2 -2
- claude_mpm/services/mcp_config_manager.py +439 -0
- claude_mpm/services/mcp_gateway/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/auto_configure.py +3 -3
- claude_mpm/services/mcp_gateway/config/config_loader.py +1 -1
- claude_mpm/services/mcp_gateway/config/configuration.py +18 -1
- claude_mpm/services/mcp_gateway/core/base.py +2 -2
- claude_mpm/services/mcp_gateway/main.py +52 -0
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +10 -8
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +4 -4
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +1 -1
- claude_mpm/services/mcp_gateway/server/stdio_server.py +4 -3
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +15 -15
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +7 -5
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +443 -0
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +5 -5
- claude_mpm/services/mcp_gateway/tools/hello_world.py +9 -9
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +16 -16
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +17 -17
- claude_mpm/services/memory/builder.py +7 -5
- claude_mpm/services/memory/indexed_memory.py +4 -4
- claude_mpm/services/memory/optimizer.py +6 -6
- claude_mpm/services/memory/router.py +3 -3
- claude_mpm/services/monitor/daemon.py +1 -1
- claude_mpm/services/monitor/daemon_manager.py +6 -6
- claude_mpm/services/monitor/event_emitter.py +2 -2
- claude_mpm/services/monitor/handlers/file.py +1 -1
- claude_mpm/services/monitor/management/lifecycle.py +1 -1
- claude_mpm/services/monitor/server.py +4 -4
- claude_mpm/services/monitor_build_service.py +2 -2
- claude_mpm/services/port_manager.py +2 -2
- claude_mpm/services/response_tracker.py +2 -2
- claude_mpm/services/session_management_service.py +3 -2
- claude_mpm/services/socketio/client_proxy.py +2 -2
- claude_mpm/services/socketio/dashboard_server.py +4 -3
- claude_mpm/services/socketio/event_normalizer.py +12 -8
- claude_mpm/services/socketio/handlers/base.py +2 -2
- claude_mpm/services/socketio/handlers/connection.py +10 -10
- claude_mpm/services/socketio/handlers/connection_handler.py +13 -10
- claude_mpm/services/socketio/handlers/file.py +1 -1
- claude_mpm/services/socketio/handlers/git.py +1 -1
- claude_mpm/services/socketio/handlers/hook.py +16 -15
- claude_mpm/services/socketio/migration_utils.py +1 -1
- claude_mpm/services/socketio/monitor_client.py +5 -5
- claude_mpm/services/socketio/server/broadcaster.py +9 -7
- claude_mpm/services/socketio/server/connection_manager.py +2 -2
- claude_mpm/services/socketio/server/core.py +7 -5
- claude_mpm/services/socketio/server/eventbus_integration.py +18 -11
- claude_mpm/services/socketio/server/main.py +13 -13
- claude_mpm/services/socketio_client_manager.py +4 -4
- claude_mpm/services/system_instructions_service.py +2 -2
- claude_mpm/services/ticket_services/validation_service.py +1 -1
- claude_mpm/services/utility_service.py +5 -2
- claude_mpm/services/version_control/branch_strategy.py +2 -2
- claude_mpm/services/version_control/git_operations.py +22 -20
- claude_mpm/services/version_control/semantic_versioning.py +3 -3
- claude_mpm/services/version_control/version_parser.py +7 -5
- claude_mpm/services/visualization/mermaid_generator.py +1 -1
- claude_mpm/storage/state_storage.py +1 -1
- claude_mpm/tools/code_tree_analyzer.py +19 -18
- claude_mpm/tools/code_tree_builder.py +2 -2
- claude_mpm/tools/code_tree_events.py +10 -8
- claude_mpm/tools/socketio_debug.py +3 -3
- claude_mpm/utils/agent_dependency_loader.py +2 -2
- claude_mpm/utils/dependency_strategies.py +8 -3
- claude_mpm/utils/environment_context.py +2 -2
- claude_mpm/utils/error_handler.py +2 -2
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/imports.py +1 -1
- claude_mpm/utils/log_cleanup.py +21 -7
- claude_mpm/validation/agent_validator.py +2 -2
- {claude_mpm-4.3.11.dist-info ā claude_mpm-4.3.13.dist-info}/METADATA +4 -1
- {claude_mpm-4.3.11.dist-info ā claude_mpm-4.3.13.dist-info}/RECORD +207 -200
- {claude_mpm-4.3.11.dist-info ā claude_mpm-4.3.13.dist-info}/WHEEL +0 -0
- {claude_mpm-4.3.11.dist-info ā claude_mpm-4.3.13.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.3.11.dist-info ā claude_mpm-4.3.13.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.3.11.dist-info ā claude_mpm-4.3.13.dist-info}/top_level.txt +0 -0
|
@@ -37,7 +37,7 @@ class MonitorCommand(BaseCommand):
|
|
|
37
37
|
|
|
38
38
|
return None
|
|
39
39
|
|
|
40
|
-
def run(self, args) -> CommandResult:
|
|
40
|
+
def run(self, args) -> CommandResult: # noqa: PLR0911
|
|
41
41
|
"""Execute the monitor command using unified monitoring daemon."""
|
|
42
42
|
try:
|
|
43
43
|
self.logger.info("Monitor command using unified monitoring daemon")
|
|
@@ -142,7 +142,7 @@ class MonitorCommand(BaseCommand):
|
|
|
142
142
|
return CommandResult.error_result(
|
|
143
143
|
f"Port {port} is already in use. Try 'claude-mpm monitor stop' first or use a different port."
|
|
144
144
|
)
|
|
145
|
-
except:
|
|
145
|
+
except Exception:
|
|
146
146
|
pass
|
|
147
147
|
|
|
148
148
|
return CommandResult.error_result(
|
claude_mpm/cli/commands/run.py
CHANGED
|
@@ -68,6 +68,7 @@ def filter_claude_mpm_args(claude_args):
|
|
|
68
68
|
"--no-native-agents",
|
|
69
69
|
"--launch-method",
|
|
70
70
|
"--mpm-resume",
|
|
71
|
+
"--reload-agents", # New flag to force rebuild system agents
|
|
71
72
|
# Dependency checking flags (MPM-specific)
|
|
72
73
|
"--no-check-dependencies",
|
|
73
74
|
"--force-check-dependencies",
|
|
@@ -568,6 +569,112 @@ class RunCommand(BaseCommand):
|
|
|
568
569
|
return False
|
|
569
570
|
|
|
570
571
|
|
|
572
|
+
def _ensure_mcp_services_configured(logger):
|
|
573
|
+
"""
|
|
574
|
+
Ensure MCP services are configured in .mcp.json on startup.
|
|
575
|
+
|
|
576
|
+
This function automatically configures the core MCP services
|
|
577
|
+
(mcp-vector-search, mcp-browser, mcp-ticketer) if they're not
|
|
578
|
+
already configured in the project's .mcp.json file.
|
|
579
|
+
|
|
580
|
+
Args:
|
|
581
|
+
logger: Logger instance for output
|
|
582
|
+
"""
|
|
583
|
+
try:
|
|
584
|
+
from ...services.mcp_config_manager import MCPConfigManager
|
|
585
|
+
|
|
586
|
+
logger.debug("Checking MCP service configuration...")
|
|
587
|
+
manager = MCPConfigManager()
|
|
588
|
+
|
|
589
|
+
# Check and auto-configure missing MCP services
|
|
590
|
+
success, message = manager.ensure_mcp_services_configured()
|
|
591
|
+
|
|
592
|
+
if success:
|
|
593
|
+
if "already configured" not in message.lower():
|
|
594
|
+
logger.info(message)
|
|
595
|
+
print(f"ā
{message}")
|
|
596
|
+
else:
|
|
597
|
+
logger.debug(message)
|
|
598
|
+
else:
|
|
599
|
+
logger.warning(f"MCP auto-configuration issue: {message}")
|
|
600
|
+
# Don't fail the session, just warn
|
|
601
|
+
|
|
602
|
+
except Exception as e:
|
|
603
|
+
logger.debug(f"MCP auto-configuration skipped: {e}")
|
|
604
|
+
# Don't fail the session if auto-configuration fails
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
def _handle_reload_agents(logger):
|
|
608
|
+
"""
|
|
609
|
+
Handle the --reload-agents flag by deleting all local claude-mpm system agents.
|
|
610
|
+
|
|
611
|
+
This forces a fresh rebuild of system agents on the next deployment,
|
|
612
|
+
while preserving user-created agents.
|
|
613
|
+
|
|
614
|
+
Args:
|
|
615
|
+
logger: Logger instance for output
|
|
616
|
+
"""
|
|
617
|
+
try:
|
|
618
|
+
logger.info("Reloading system agents - cleaning existing deployments...")
|
|
619
|
+
|
|
620
|
+
# Import the cleanup service
|
|
621
|
+
from ...services.agents.deployment.agent_deployment import (
|
|
622
|
+
AgentDeploymentService,
|
|
623
|
+
)
|
|
624
|
+
from ...services.cli.agent_cleanup_service import AgentCleanupService
|
|
625
|
+
|
|
626
|
+
# Create services
|
|
627
|
+
deployment_service = AgentDeploymentService()
|
|
628
|
+
cleanup_service = AgentCleanupService(deployment_service)
|
|
629
|
+
|
|
630
|
+
# Determine the agents directory
|
|
631
|
+
agents_dir = None # Will auto-detect project or user directory
|
|
632
|
+
|
|
633
|
+
# Clean deployed agents (preserves user agents)
|
|
634
|
+
result = cleanup_service.clean_deployed_agents(agents_dir)
|
|
635
|
+
|
|
636
|
+
# Check if cleanup was successful based on the result structure
|
|
637
|
+
# The service returns a dict with 'removed', 'preserved', and possibly 'errors' keys
|
|
638
|
+
# If it has 'success' key, use it; otherwise infer from the result
|
|
639
|
+
success = (
|
|
640
|
+
result.get("success", True)
|
|
641
|
+
if "success" in result
|
|
642
|
+
else not result.get("errors")
|
|
643
|
+
)
|
|
644
|
+
|
|
645
|
+
if success:
|
|
646
|
+
removed_count = result.get("cleaned_count", len(result.get("removed", [])))
|
|
647
|
+
removed_agents = result.get("removed", [])
|
|
648
|
+
preserved_agents = result.get("preserved", [])
|
|
649
|
+
|
|
650
|
+
if removed_count > 0:
|
|
651
|
+
logger.info(f"ā
Successfully removed {removed_count} system agents")
|
|
652
|
+
if removed_agents:
|
|
653
|
+
logger.debug(f"Removed agents: {', '.join(removed_agents)}")
|
|
654
|
+
print(f"š Cleaned {removed_count} claude-mpm system agents")
|
|
655
|
+
else:
|
|
656
|
+
logger.info("No system agents found to clean")
|
|
657
|
+
print("ā¹ļø No system agents found - already clean")
|
|
658
|
+
|
|
659
|
+
if preserved_agents:
|
|
660
|
+
logger.info(f"Preserved {len(preserved_agents)} user-created agents")
|
|
661
|
+
print(f"ā
Preserved {len(preserved_agents)} user-created agents")
|
|
662
|
+
|
|
663
|
+
print("š System agents will be rebuilt on next use")
|
|
664
|
+
else:
|
|
665
|
+
error = result.get("error", "Cleanup failed")
|
|
666
|
+
if result.get("errors"):
|
|
667
|
+
error = f"Cleanup errors: {', '.join(result['errors'])}"
|
|
668
|
+
logger.error(f"Failed to clean system agents: {error}")
|
|
669
|
+
print(f"ā Error cleaning agents: {error}")
|
|
670
|
+
|
|
671
|
+
except Exception as e:
|
|
672
|
+
logger.error(f"Error handling --reload-agents: {e}", exc_info=True)
|
|
673
|
+
print(f"ā Failed to reload agents: {e}")
|
|
674
|
+
# Don't fail the entire session, just log the error
|
|
675
|
+
print("ā ļø Continuing with existing agents...")
|
|
676
|
+
|
|
677
|
+
|
|
571
678
|
def run_session(args):
|
|
572
679
|
"""
|
|
573
680
|
Main entry point for run command.
|
|
@@ -624,6 +731,13 @@ def run_session_legacy(args):
|
|
|
624
731
|
# Check for memory usage issues with .claude.json
|
|
625
732
|
_check_claude_json_memory(args, logger)
|
|
626
733
|
|
|
734
|
+
# Handle --reload-agents flag if specified
|
|
735
|
+
if getattr(args, "reload_agents", False):
|
|
736
|
+
_handle_reload_agents(logger)
|
|
737
|
+
|
|
738
|
+
# Auto-configure MCP services on startup
|
|
739
|
+
_ensure_mcp_services_configured(logger)
|
|
740
|
+
|
|
627
741
|
try:
|
|
628
742
|
from ...core.claude_runner import ClaudeRunner, create_simple_context
|
|
629
743
|
except ImportError:
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Search command module for mcp-vector-search integration.
|
|
3
|
+
|
|
4
|
+
This module provides the /mpm-search command for semantic code search
|
|
5
|
+
using the mcp-vector-search service.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import json
|
|
10
|
+
import sys
|
|
11
|
+
from typing import Any, Dict, Optional
|
|
12
|
+
|
|
13
|
+
import click
|
|
14
|
+
from rich.console import Console
|
|
15
|
+
from rich.panel import Panel
|
|
16
|
+
from rich.syntax import Syntax
|
|
17
|
+
from rich.table import Table
|
|
18
|
+
|
|
19
|
+
from claude_mpm.cli.utils import handle_async_errors
|
|
20
|
+
from claude_mpm.services.service_container import get_service_container
|
|
21
|
+
|
|
22
|
+
console = Console()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class MCPSearchInterface:
|
|
26
|
+
"""Interface for interacting with mcp-vector-search service."""
|
|
27
|
+
|
|
28
|
+
def __init__(self):
|
|
29
|
+
"""Initialize the search interface."""
|
|
30
|
+
self.container = get_service_container()
|
|
31
|
+
self.mcp_gateway = None
|
|
32
|
+
|
|
33
|
+
async def initialize(self):
|
|
34
|
+
"""Initialize the MCP gateway connection."""
|
|
35
|
+
try:
|
|
36
|
+
from claude_mpm.services.mcp_gateway import MCPGatewayService
|
|
37
|
+
|
|
38
|
+
self.mcp_gateway = self.container.resolve(MCPGatewayService)
|
|
39
|
+
if not self.mcp_gateway:
|
|
40
|
+
self.mcp_gateway = MCPGatewayService()
|
|
41
|
+
await self.mcp_gateway.initialize()
|
|
42
|
+
except Exception as e:
|
|
43
|
+
console.print(f"[red]Failed to initialize MCP gateway: {e}[/red]")
|
|
44
|
+
raise
|
|
45
|
+
|
|
46
|
+
async def search_code(
|
|
47
|
+
self,
|
|
48
|
+
query: str,
|
|
49
|
+
limit: int = 10,
|
|
50
|
+
similarity_threshold: float = 0.3,
|
|
51
|
+
file_extensions: Optional[list] = None,
|
|
52
|
+
language: Optional[str] = None,
|
|
53
|
+
) -> Dict[str, Any]:
|
|
54
|
+
"""Search code using semantic similarity."""
|
|
55
|
+
params = {
|
|
56
|
+
"query": query,
|
|
57
|
+
"limit": limit,
|
|
58
|
+
"similarity_threshold": similarity_threshold,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if file_extensions:
|
|
62
|
+
params["file_extensions"] = file_extensions
|
|
63
|
+
if language:
|
|
64
|
+
params["language"] = language
|
|
65
|
+
|
|
66
|
+
return await self._call_mcp_tool("mcp__mcp-vector-search__search_code", params)
|
|
67
|
+
|
|
68
|
+
async def search_similar(
|
|
69
|
+
self,
|
|
70
|
+
file_path: str,
|
|
71
|
+
function_name: Optional[str] = None,
|
|
72
|
+
limit: int = 10,
|
|
73
|
+
similarity_threshold: float = 0.3,
|
|
74
|
+
) -> Dict[str, Any]:
|
|
75
|
+
"""Find code similar to a specific file or function."""
|
|
76
|
+
params = {
|
|
77
|
+
"file_path": file_path,
|
|
78
|
+
"limit": limit,
|
|
79
|
+
"similarity_threshold": similarity_threshold,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if function_name:
|
|
83
|
+
params["function_name"] = function_name
|
|
84
|
+
|
|
85
|
+
return await self._call_mcp_tool(
|
|
86
|
+
"mcp__mcp-vector-search__search_similar", params
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
async def search_context(
|
|
90
|
+
self, description: str, focus_areas: Optional[list] = None, limit: int = 10
|
|
91
|
+
) -> Dict[str, Any]:
|
|
92
|
+
"""Search for code based on contextual description."""
|
|
93
|
+
params = {"description": description, "limit": limit}
|
|
94
|
+
|
|
95
|
+
if focus_areas:
|
|
96
|
+
params["focus_areas"] = focus_areas
|
|
97
|
+
|
|
98
|
+
return await self._call_mcp_tool(
|
|
99
|
+
"mcp__mcp-vector-search__search_context", params
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
async def get_status(self) -> Dict[str, Any]:
|
|
103
|
+
"""Get project indexing status and statistics."""
|
|
104
|
+
return await self._call_mcp_tool(
|
|
105
|
+
"mcp__mcp-vector-search__get_project_status", {}
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
async def index_project(
|
|
109
|
+
self, force: bool = False, file_extensions: Optional[list] = None
|
|
110
|
+
) -> Dict[str, Any]:
|
|
111
|
+
"""Index or reindex the project codebase."""
|
|
112
|
+
params = {"force": force}
|
|
113
|
+
|
|
114
|
+
if file_extensions:
|
|
115
|
+
params["file_extensions"] = file_extensions
|
|
116
|
+
|
|
117
|
+
return await self._call_mcp_tool(
|
|
118
|
+
"mcp__mcp-vector-search__index_project", params
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
async def _call_mcp_tool(
|
|
122
|
+
self, tool_name: str, params: Dict[str, Any]
|
|
123
|
+
) -> Dict[str, Any]:
|
|
124
|
+
"""Call an MCP tool through the gateway."""
|
|
125
|
+
if not self.mcp_gateway:
|
|
126
|
+
await self.initialize()
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
return await self.mcp_gateway.call_tool(tool_name, params)
|
|
130
|
+
except Exception as e:
|
|
131
|
+
return {"error": str(e)}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def display_search_results(results: Dict[str, Any], output_format: str = "rich"):
|
|
135
|
+
"""Display search results in the specified format."""
|
|
136
|
+
if output_format == "json":
|
|
137
|
+
console.print_json(json.dumps(results, indent=2))
|
|
138
|
+
return
|
|
139
|
+
|
|
140
|
+
if "error" in results:
|
|
141
|
+
console.print(f"[red]Error: {results['error']}[/red]")
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
if not results.get("results"):
|
|
145
|
+
console.print("[yellow]No results found.[/yellow]")
|
|
146
|
+
return
|
|
147
|
+
|
|
148
|
+
# Create a table for results
|
|
149
|
+
table = Table(title="Search Results", show_header=True, header_style="bold magenta")
|
|
150
|
+
table.add_column("File", style="cyan", no_wrap=False)
|
|
151
|
+
table.add_column("Score", style="green", width=8)
|
|
152
|
+
table.add_column("Type", style="yellow", width=10)
|
|
153
|
+
table.add_column("Name", style="blue", no_wrap=False)
|
|
154
|
+
|
|
155
|
+
for result in results["results"]:
|
|
156
|
+
file_path = result.get("file_path", "Unknown")
|
|
157
|
+
score = f"{result.get('score', 0):.3f}"
|
|
158
|
+
item_type = result.get("type", "unknown")
|
|
159
|
+
name = result.get("name", result.get("function_name", ""))
|
|
160
|
+
|
|
161
|
+
table.add_row(file_path, score, item_type, name)
|
|
162
|
+
|
|
163
|
+
# Show snippet if available
|
|
164
|
+
if result.get("snippet"):
|
|
165
|
+
snippet_panel = Panel(
|
|
166
|
+
Syntax(
|
|
167
|
+
result["snippet"], result.get("language", "python"), theme="monokai"
|
|
168
|
+
),
|
|
169
|
+
title=f"[cyan]{file_path}[/cyan]",
|
|
170
|
+
border_style="dim",
|
|
171
|
+
)
|
|
172
|
+
console.print(snippet_panel)
|
|
173
|
+
|
|
174
|
+
console.print(table)
|
|
175
|
+
|
|
176
|
+
# Show statistics if available
|
|
177
|
+
if "stats" in results:
|
|
178
|
+
stats = results["stats"]
|
|
179
|
+
console.print("\n[bold]Statistics:[/bold]")
|
|
180
|
+
console.print(f" Total indexed files: {stats.get('total_files', 0)}")
|
|
181
|
+
console.print(f" Total indexed functions: {stats.get('total_functions', 0)}")
|
|
182
|
+
console.print(f" Index last updated: {stats.get('last_updated', 'Unknown')}")
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@click.command()
|
|
186
|
+
@click.argument("query", required=False)
|
|
187
|
+
@click.option("--similar", "-s", help="Find code similar to a specific file")
|
|
188
|
+
@click.option("--context", "-c", help="Search by contextual description")
|
|
189
|
+
@click.option("--index", is_flag=True, help="Index or reindex the project")
|
|
190
|
+
@click.option("--status", is_flag=True, help="Check index status")
|
|
191
|
+
@click.option("--limit", "-l", default=10, help="Maximum number of results")
|
|
192
|
+
@click.option("--threshold", "-t", default=0.3, help="Similarity threshold (0.0-1.0)")
|
|
193
|
+
@click.option("--language", help="Filter by programming language")
|
|
194
|
+
@click.option("--extensions", multiple=True, help="Filter by file extensions")
|
|
195
|
+
@click.option("--function", "-f", help="Function name (with --similar)")
|
|
196
|
+
@click.option("--focus", multiple=True, help="Focus areas (with --context)")
|
|
197
|
+
@click.option("--force", is_flag=True, help="Force reindexing (with --index)")
|
|
198
|
+
@click.option("--json", "output_json", is_flag=True, help="Output results as JSON")
|
|
199
|
+
@handle_async_errors
|
|
200
|
+
async def search_command(
|
|
201
|
+
query: Optional[str],
|
|
202
|
+
similar: Optional[str],
|
|
203
|
+
context: Optional[str],
|
|
204
|
+
index: bool,
|
|
205
|
+
status: bool,
|
|
206
|
+
limit: int,
|
|
207
|
+
threshold: float,
|
|
208
|
+
language: Optional[str],
|
|
209
|
+
extensions: tuple,
|
|
210
|
+
function: Optional[str],
|
|
211
|
+
focus: tuple,
|
|
212
|
+
force: bool,
|
|
213
|
+
output_json: bool,
|
|
214
|
+
):
|
|
215
|
+
"""
|
|
216
|
+
Search the codebase using semantic search powered by mcp-vector-search.
|
|
217
|
+
|
|
218
|
+
Examples:
|
|
219
|
+
/mpm-search "authentication logic"
|
|
220
|
+
/mpm-search --similar src/auth.py
|
|
221
|
+
/mpm-search --context "find all API endpoints"
|
|
222
|
+
/mpm-search --index --force
|
|
223
|
+
/mpm-search --status
|
|
224
|
+
"""
|
|
225
|
+
search = MCPSearchInterface()
|
|
226
|
+
await search.initialize()
|
|
227
|
+
|
|
228
|
+
output_format = "json" if output_json else "rich"
|
|
229
|
+
|
|
230
|
+
try:
|
|
231
|
+
# Handle different operation modes
|
|
232
|
+
if index:
|
|
233
|
+
console.print("[cyan]Indexing project...[/cyan]")
|
|
234
|
+
result = await search.index_project(
|
|
235
|
+
force=force, file_extensions=list(extensions) if extensions else None
|
|
236
|
+
)
|
|
237
|
+
if "error" not in result:
|
|
238
|
+
console.print("[green]ā Project indexed successfully[/green]")
|
|
239
|
+
display_search_results(result, output_format)
|
|
240
|
+
|
|
241
|
+
elif status:
|
|
242
|
+
result = await search.get_status()
|
|
243
|
+
display_search_results(result, output_format)
|
|
244
|
+
|
|
245
|
+
elif similar:
|
|
246
|
+
result = await search.search_similar(
|
|
247
|
+
file_path=similar,
|
|
248
|
+
function_name=function,
|
|
249
|
+
limit=limit,
|
|
250
|
+
similarity_threshold=threshold,
|
|
251
|
+
)
|
|
252
|
+
display_search_results(result, output_format)
|
|
253
|
+
|
|
254
|
+
elif context:
|
|
255
|
+
result = await search.search_context(
|
|
256
|
+
description=context,
|
|
257
|
+
focus_areas=list(focus) if focus else None,
|
|
258
|
+
limit=limit,
|
|
259
|
+
)
|
|
260
|
+
display_search_results(result, output_format)
|
|
261
|
+
|
|
262
|
+
elif query:
|
|
263
|
+
result = await search.search_code(
|
|
264
|
+
query=query,
|
|
265
|
+
limit=limit,
|
|
266
|
+
similarity_threshold=threshold,
|
|
267
|
+
file_extensions=list(extensions) if extensions else None,
|
|
268
|
+
language=language,
|
|
269
|
+
)
|
|
270
|
+
display_search_results(result, output_format)
|
|
271
|
+
|
|
272
|
+
else:
|
|
273
|
+
console.print(
|
|
274
|
+
"[yellow]No search operation specified. Use --help for options.[/yellow]"
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
except Exception as e:
|
|
278
|
+
console.print(f"[red]Search failed: {e}[/red]")
|
|
279
|
+
if not output_json:
|
|
280
|
+
console.print(
|
|
281
|
+
"[dim]Tip: Make sure the project is indexed with --index first[/dim]"
|
|
282
|
+
)
|
|
283
|
+
sys.exit(1)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def main():
|
|
287
|
+
"""Main entry point for the search command."""
|
|
288
|
+
asyncio.run(search_command())
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
if __name__ == "__main__":
|
|
292
|
+
main()
|
|
@@ -600,7 +600,7 @@ class AgentWizard:
|
|
|
600
600
|
tier="project",
|
|
601
601
|
)
|
|
602
602
|
|
|
603
|
-
def _manage_single_agent(self, template: LocalAgentTemplate) -> Tuple[bool, str]:
|
|
603
|
+
def _manage_single_agent(self, template: LocalAgentTemplate) -> Tuple[bool, str]: # noqa: PLR0911
|
|
604
604
|
"""Manage a single agent."""
|
|
605
605
|
print(f"\nš§ Managing Agent: {template.agent_id}")
|
|
606
606
|
print(f" Name: {template.metadata.get('name', template.agent_id)}")
|
|
@@ -815,7 +815,7 @@ class AgentWizard:
|
|
|
815
815
|
return self.manager.project_agents_dir / f"{template.agent_id}.json"
|
|
816
816
|
return self.manager.user_agents_dir / f"{template.agent_id}.json"
|
|
817
817
|
|
|
818
|
-
def _interactive_delete_menu(self, templates: list) -> Tuple[bool, str]:
|
|
818
|
+
def _interactive_delete_menu(self, templates: list) -> Tuple[bool, str]: # noqa: PLR0911
|
|
819
819
|
"""Interactive deletion menu for multiple agents."""
|
|
820
820
|
print("\nšļø Delete Agents")
|
|
821
821
|
print("=" * 50)
|
|
@@ -199,6 +199,11 @@ def add_top_level_run_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
199
199
|
action="store_true",
|
|
200
200
|
help="Force operations even with warnings (e.g., large .claude.json file)",
|
|
201
201
|
)
|
|
202
|
+
run_group.add_argument(
|
|
203
|
+
"--reload-agents",
|
|
204
|
+
action="store_true",
|
|
205
|
+
help="Force rebuild of all system agents by deleting local claude-mpm agents",
|
|
206
|
+
)
|
|
202
207
|
|
|
203
208
|
# Dependency checking options (for backward compatibility at top level)
|
|
204
209
|
dep_group_top = parser.add_argument_group(
|
|
@@ -390,6 +395,14 @@ def create_parser(
|
|
|
390
395
|
except ImportError:
|
|
391
396
|
pass
|
|
392
397
|
|
|
398
|
+
# Add search command parser
|
|
399
|
+
try:
|
|
400
|
+
from .search_parser import add_search_subparser
|
|
401
|
+
|
|
402
|
+
add_search_subparser(subparsers)
|
|
403
|
+
except ImportError:
|
|
404
|
+
pass
|
|
405
|
+
|
|
393
406
|
# Import and add additional command parsers from commands module
|
|
394
407
|
try:
|
|
395
408
|
from ..commands.aggregate import add_aggregate_parser
|
|
@@ -177,4 +177,19 @@ def add_mcp_subparser(subparsers) -> argparse.ArgumentParser:
|
|
|
177
177
|
help="Show setup instructions for Claude Code",
|
|
178
178
|
)
|
|
179
179
|
|
|
180
|
+
# External MCP services management
|
|
181
|
+
external_mcp_parser = mcp_subparsers.add_parser(
|
|
182
|
+
MCPCommands.EXTERNAL.value, help="Manage external MCP services"
|
|
183
|
+
)
|
|
184
|
+
external_mcp_parser.add_argument(
|
|
185
|
+
"external_action",
|
|
186
|
+
nargs="?",
|
|
187
|
+
choices=["setup", "list", "check", "fix-browser", "detect"],
|
|
188
|
+
default="list",
|
|
189
|
+
help="External service action (default: list)",
|
|
190
|
+
)
|
|
191
|
+
external_mcp_parser.add_argument(
|
|
192
|
+
"--force", action="store_true", help="Force overwrite existing configuration"
|
|
193
|
+
)
|
|
194
|
+
|
|
180
195
|
return mcp_parser
|
|
@@ -68,6 +68,11 @@ def add_run_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
68
68
|
action="store_true",
|
|
69
69
|
help="Force operations even with warnings (e.g., large .claude.json file)",
|
|
70
70
|
)
|
|
71
|
+
run_group.add_argument(
|
|
72
|
+
"--reload-agents",
|
|
73
|
+
action="store_true",
|
|
74
|
+
help="Force rebuild of all system agents by deleting local claude-mpm agents",
|
|
75
|
+
)
|
|
71
76
|
run_group.add_argument(
|
|
72
77
|
"--mpm-resume",
|
|
73
78
|
type=str,
|