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.
Files changed (207) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/PM_INSTRUCTIONS.md +390 -28
  3. claude_mpm/agents/templates/data_engineer.json +39 -14
  4. claude_mpm/agents/templates/research.json +20 -8
  5. claude_mpm/agents/templates/web_qa.json +25 -10
  6. claude_mpm/cli/__init__.py +1 -0
  7. claude_mpm/cli/commands/agent_manager.py +3 -3
  8. claude_mpm/cli/commands/agents.py +2 -2
  9. claude_mpm/cli/commands/aggregate.py +1 -1
  10. claude_mpm/cli/commands/config.py +2 -2
  11. claude_mpm/cli/commands/configure.py +5 -5
  12. claude_mpm/cli/commands/configure_tui.py +7 -7
  13. claude_mpm/cli/commands/dashboard.py +1 -1
  14. claude_mpm/cli/commands/debug.py +5 -5
  15. claude_mpm/cli/commands/mcp.py +1 -1
  16. claude_mpm/cli/commands/mcp_command_router.py +12 -1
  17. claude_mpm/cli/commands/mcp_config.py +154 -0
  18. claude_mpm/cli/commands/mcp_external_commands.py +249 -0
  19. claude_mpm/cli/commands/mcp_install_commands.py +93 -24
  20. claude_mpm/cli/commands/mcp_setup_external.py +870 -0
  21. claude_mpm/cli/commands/monitor.py +2 -2
  22. claude_mpm/cli/commands/mpm_init_handler.py +1 -1
  23. claude_mpm/cli/commands/run.py +114 -0
  24. claude_mpm/cli/commands/search.py +292 -0
  25. claude_mpm/cli/interactive/agent_wizard.py +2 -2
  26. claude_mpm/cli/parsers/base_parser.py +13 -0
  27. claude_mpm/cli/parsers/mcp_parser.py +15 -0
  28. claude_mpm/cli/parsers/run_parser.py +5 -0
  29. claude_mpm/cli/parsers/search_parser.py +245 -0
  30. claude_mpm/cli/startup_logging.py +3 -5
  31. claude_mpm/cli/utils.py +1 -1
  32. claude_mpm/constants.py +1 -0
  33. claude_mpm/core/agent_registry.py +12 -8
  34. claude_mpm/core/agent_session_manager.py +8 -8
  35. claude_mpm/core/api_validator.py +4 -4
  36. claude_mpm/core/base_service.py +10 -10
  37. claude_mpm/core/cache.py +5 -5
  38. claude_mpm/core/config_constants.py +1 -1
  39. claude_mpm/core/container.py +1 -1
  40. claude_mpm/core/error_handler.py +2 -2
  41. claude_mpm/core/file_utils.py +1 -1
  42. claude_mpm/core/framework_loader.py +3 -3
  43. claude_mpm/core/hook_manager.py +8 -6
  44. claude_mpm/core/instruction_reinforcement_hook.py +2 -2
  45. claude_mpm/core/interactive_session.py +1 -1
  46. claude_mpm/core/lazy.py +3 -3
  47. claude_mpm/core/log_manager.py +16 -12
  48. claude_mpm/core/logger.py +16 -11
  49. claude_mpm/core/logging_config.py +4 -2
  50. claude_mpm/core/oneshot_session.py +1 -1
  51. claude_mpm/core/optimized_agent_loader.py +6 -6
  52. claude_mpm/core/output_style_manager.py +1 -1
  53. claude_mpm/core/pm_hook_interceptor.py +3 -3
  54. claude_mpm/core/service_registry.py +1 -1
  55. claude_mpm/core/session_manager.py +11 -9
  56. claude_mpm/core/socketio_pool.py +13 -13
  57. claude_mpm/core/types.py +2 -2
  58. claude_mpm/core/unified_agent_registry.py +9 -2
  59. claude_mpm/core/unified_paths.py +1 -1
  60. claude_mpm/dashboard/analysis_runner.py +4 -4
  61. claude_mpm/dashboard/api/simple_directory.py +1 -1
  62. claude_mpm/generators/agent_profile_generator.py +4 -2
  63. claude_mpm/hooks/base_hook.py +2 -2
  64. claude_mpm/hooks/claude_hooks/connection_pool.py +4 -4
  65. claude_mpm/hooks/claude_hooks/event_handlers.py +12 -12
  66. claude_mpm/hooks/claude_hooks/hook_handler.py +4 -4
  67. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +3 -3
  68. claude_mpm/hooks/claude_hooks/hook_handler_original.py +15 -14
  69. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +4 -4
  70. claude_mpm/hooks/claude_hooks/installer.py +3 -3
  71. claude_mpm/hooks/claude_hooks/memory_integration.py +3 -3
  72. claude_mpm/hooks/claude_hooks/response_tracking.py +3 -3
  73. claude_mpm/hooks/claude_hooks/services/connection_manager.py +5 -5
  74. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +3 -3
  75. claude_mpm/hooks/claude_hooks/services/state_manager.py +8 -7
  76. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +3 -3
  77. claude_mpm/hooks/claude_hooks/tool_analysis.py +2 -2
  78. claude_mpm/hooks/memory_integration_hook.py +1 -1
  79. claude_mpm/hooks/tool_call_interceptor.py +2 -2
  80. claude_mpm/models/agent_session.py +5 -5
  81. claude_mpm/services/__init__.py +1 -1
  82. claude_mpm/services/agent_capabilities_service.py +1 -1
  83. claude_mpm/services/agents/agent_builder.py +3 -3
  84. claude_mpm/services/agents/deployment/agent_deployment.py +29 -13
  85. claude_mpm/services/agents/deployment/agent_discovery_service.py +22 -6
  86. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +7 -5
  87. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +3 -1
  88. claude_mpm/services/agents/deployment/agent_metrics_collector.py +1 -1
  89. claude_mpm/services/agents/deployment/agent_operation_service.py +2 -2
  90. claude_mpm/services/agents/deployment/agent_state_service.py +2 -2
  91. claude_mpm/services/agents/deployment/agent_template_builder.py +1 -1
  92. claude_mpm/services/agents/deployment/agent_versioning.py +1 -1
  93. claude_mpm/services/agents/deployment/deployment_wrapper.py +2 -3
  94. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +6 -4
  95. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +1 -1
  96. claude_mpm/services/agents/loading/agent_profile_loader.py +5 -3
  97. claude_mpm/services/agents/loading/base_agent_manager.py +2 -2
  98. claude_mpm/services/agents/local_template_manager.py +6 -6
  99. claude_mpm/services/agents/management/agent_management_service.py +3 -3
  100. claude_mpm/services/agents/memory/content_manager.py +3 -3
  101. claude_mpm/services/agents/memory/memory_format_service.py +2 -2
  102. claude_mpm/services/agents/memory/template_generator.py +3 -3
  103. claude_mpm/services/agents/registry/__init__.py +1 -1
  104. claude_mpm/services/agents/registry/modification_tracker.py +2 -2
  105. claude_mpm/services/async_session_logger.py +3 -3
  106. claude_mpm/services/claude_session_logger.py +4 -4
  107. claude_mpm/services/cli/agent_cleanup_service.py +5 -0
  108. claude_mpm/services/cli/agent_listing_service.py +1 -1
  109. claude_mpm/services/cli/agent_validation_service.py +1 -0
  110. claude_mpm/services/cli/memory_crud_service.py +11 -6
  111. claude_mpm/services/cli/memory_output_formatter.py +1 -1
  112. claude_mpm/services/cli/session_manager.py +15 -11
  113. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  114. claude_mpm/services/core/memory_manager.py +81 -23
  115. claude_mpm/services/core/path_resolver.py +2 -2
  116. claude_mpm/services/diagnostics/checks/installation_check.py +1 -1
  117. claude_mpm/services/event_aggregator.py +4 -2
  118. claude_mpm/services/event_bus/direct_relay.py +5 -3
  119. claude_mpm/services/event_bus/event_bus.py +3 -3
  120. claude_mpm/services/event_bus/relay.py +6 -4
  121. claude_mpm/services/events/consumers/dead_letter.py +5 -3
  122. claude_mpm/services/events/core.py +3 -3
  123. claude_mpm/services/events/producers/hook.py +6 -6
  124. claude_mpm/services/events/producers/system.py +8 -8
  125. claude_mpm/services/exceptions.py +5 -5
  126. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -3
  127. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +2 -2
  128. claude_mpm/services/hook_installer_service.py +1 -1
  129. claude_mpm/services/infrastructure/context_preservation.py +6 -4
  130. claude_mpm/services/infrastructure/daemon_manager.py +2 -2
  131. claude_mpm/services/infrastructure/logging.py +2 -2
  132. claude_mpm/services/mcp_config_manager.py +439 -0
  133. claude_mpm/services/mcp_gateway/__init__.py +1 -1
  134. claude_mpm/services/mcp_gateway/auto_configure.py +3 -3
  135. claude_mpm/services/mcp_gateway/config/config_loader.py +1 -1
  136. claude_mpm/services/mcp_gateway/config/configuration.py +18 -1
  137. claude_mpm/services/mcp_gateway/core/base.py +2 -2
  138. claude_mpm/services/mcp_gateway/main.py +52 -0
  139. claude_mpm/services/mcp_gateway/registry/tool_registry.py +10 -8
  140. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +4 -4
  141. claude_mpm/services/mcp_gateway/server/stdio_handler.py +1 -1
  142. claude_mpm/services/mcp_gateway/server/stdio_server.py +4 -3
  143. claude_mpm/services/mcp_gateway/tools/base_adapter.py +15 -15
  144. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +7 -5
  145. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +443 -0
  146. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +5 -5
  147. claude_mpm/services/mcp_gateway/tools/hello_world.py +9 -9
  148. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +16 -16
  149. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +17 -17
  150. claude_mpm/services/memory/builder.py +7 -5
  151. claude_mpm/services/memory/indexed_memory.py +4 -4
  152. claude_mpm/services/memory/optimizer.py +6 -6
  153. claude_mpm/services/memory/router.py +3 -3
  154. claude_mpm/services/monitor/daemon.py +1 -1
  155. claude_mpm/services/monitor/daemon_manager.py +6 -6
  156. claude_mpm/services/monitor/event_emitter.py +2 -2
  157. claude_mpm/services/monitor/handlers/file.py +1 -1
  158. claude_mpm/services/monitor/management/lifecycle.py +1 -1
  159. claude_mpm/services/monitor/server.py +4 -4
  160. claude_mpm/services/monitor_build_service.py +2 -2
  161. claude_mpm/services/port_manager.py +2 -2
  162. claude_mpm/services/response_tracker.py +2 -2
  163. claude_mpm/services/session_management_service.py +3 -2
  164. claude_mpm/services/socketio/client_proxy.py +2 -2
  165. claude_mpm/services/socketio/dashboard_server.py +4 -3
  166. claude_mpm/services/socketio/event_normalizer.py +12 -8
  167. claude_mpm/services/socketio/handlers/base.py +2 -2
  168. claude_mpm/services/socketio/handlers/connection.py +10 -10
  169. claude_mpm/services/socketio/handlers/connection_handler.py +13 -10
  170. claude_mpm/services/socketio/handlers/file.py +1 -1
  171. claude_mpm/services/socketio/handlers/git.py +1 -1
  172. claude_mpm/services/socketio/handlers/hook.py +16 -15
  173. claude_mpm/services/socketio/migration_utils.py +1 -1
  174. claude_mpm/services/socketio/monitor_client.py +5 -5
  175. claude_mpm/services/socketio/server/broadcaster.py +9 -7
  176. claude_mpm/services/socketio/server/connection_manager.py +2 -2
  177. claude_mpm/services/socketio/server/core.py +7 -5
  178. claude_mpm/services/socketio/server/eventbus_integration.py +18 -11
  179. claude_mpm/services/socketio/server/main.py +13 -13
  180. claude_mpm/services/socketio_client_manager.py +4 -4
  181. claude_mpm/services/system_instructions_service.py +2 -2
  182. claude_mpm/services/ticket_services/validation_service.py +1 -1
  183. claude_mpm/services/utility_service.py +5 -2
  184. claude_mpm/services/version_control/branch_strategy.py +2 -2
  185. claude_mpm/services/version_control/git_operations.py +22 -20
  186. claude_mpm/services/version_control/semantic_versioning.py +3 -3
  187. claude_mpm/services/version_control/version_parser.py +7 -5
  188. claude_mpm/services/visualization/mermaid_generator.py +1 -1
  189. claude_mpm/storage/state_storage.py +1 -1
  190. claude_mpm/tools/code_tree_analyzer.py +19 -18
  191. claude_mpm/tools/code_tree_builder.py +2 -2
  192. claude_mpm/tools/code_tree_events.py +10 -8
  193. claude_mpm/tools/socketio_debug.py +3 -3
  194. claude_mpm/utils/agent_dependency_loader.py +2 -2
  195. claude_mpm/utils/dependency_strategies.py +8 -3
  196. claude_mpm/utils/environment_context.py +2 -2
  197. claude_mpm/utils/error_handler.py +2 -2
  198. claude_mpm/utils/file_utils.py +1 -1
  199. claude_mpm/utils/imports.py +1 -1
  200. claude_mpm/utils/log_cleanup.py +21 -7
  201. claude_mpm/validation/agent_validator.py +2 -2
  202. {claude_mpm-4.3.11.dist-info → claude_mpm-4.3.13.dist-info}/METADATA +4 -1
  203. {claude_mpm-4.3.11.dist-info → claude_mpm-4.3.13.dist-info}/RECORD +207 -200
  204. {claude_mpm-4.3.11.dist-info → claude_mpm-4.3.13.dist-info}/WHEEL +0 -0
  205. {claude_mpm-4.3.11.dist-info → claude_mpm-4.3.13.dist-info}/entry_points.txt +0 -0
  206. {claude_mpm-4.3.11.dist-info → claude_mpm-4.3.13.dist-info}/licenses/LICENSE +0 -0
  207. {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(
@@ -11,7 +11,7 @@ from rich.console import Console
11
11
  console = Console()
12
12
 
13
13
 
14
- def manage_mpm_init(args):
14
+ def manage_mpm_init(args): # noqa: PLR0911
15
15
  """
16
16
  Handle mpm-init command execution.
17
17
 
@@ -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,