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
claude_mpm/cli/commands/mcp.py
CHANGED
|
@@ -186,7 +186,7 @@ def _show_status(
|
|
|
186
186
|
ToolRegistry()
|
|
187
187
|
# Don't initialize fully, just check
|
|
188
188
|
print("\n🔧 Tools: Check with 'claude-mpm mcp tools'")
|
|
189
|
-
except:
|
|
189
|
+
except Exception:
|
|
190
190
|
print("\n🔧 Tools: Registry not available")
|
|
191
191
|
|
|
192
192
|
print("\n💡 Available Commands:")
|
|
@@ -16,7 +16,7 @@ class MCPCommandRouter:
|
|
|
16
16
|
"""Initialize the command router."""
|
|
17
17
|
self.logger = logger
|
|
18
18
|
|
|
19
|
-
def route_command(self, args) -> int:
|
|
19
|
+
def route_command(self, args) -> int: # noqa: PLR0911
|
|
20
20
|
"""Route command to appropriate handler."""
|
|
21
21
|
if args.mcp_command == MCPCommands.START.value:
|
|
22
22
|
return asyncio.run(self._start_server(args))
|
|
@@ -45,6 +45,9 @@ class MCPCommandRouter:
|
|
|
45
45
|
if args.mcp_command == MCPCommands.SERVER.value:
|
|
46
46
|
return self._run_server(args)
|
|
47
47
|
|
|
48
|
+
if args.mcp_command == MCPCommands.EXTERNAL.value:
|
|
49
|
+
return self._manage_external(args)
|
|
50
|
+
|
|
48
51
|
if args.mcp_command == "cleanup":
|
|
49
52
|
return self._cleanup_locks(args)
|
|
50
53
|
|
|
@@ -124,6 +127,13 @@ class MCPCommandRouter:
|
|
|
124
127
|
handler = MCPServerCommands(self.logger)
|
|
125
128
|
return asyncio.run(handler.start_server(args))
|
|
126
129
|
|
|
130
|
+
def _manage_external(self, args) -> int:
|
|
131
|
+
"""Manage external MCP services command handler."""
|
|
132
|
+
from .mcp_external_commands import MCPExternalCommands
|
|
133
|
+
|
|
134
|
+
handler = MCPExternalCommands(self.logger)
|
|
135
|
+
return handler.manage_external(args)
|
|
136
|
+
|
|
127
137
|
def _show_help(self):
|
|
128
138
|
"""Show available MCP commands."""
|
|
129
139
|
print("\nAvailable MCP commands:")
|
|
@@ -136,6 +146,7 @@ class MCPCommandRouter:
|
|
|
136
146
|
print(" register - Register a new tool")
|
|
137
147
|
print(" test - Test tool invocation")
|
|
138
148
|
print(" config - View and manage configuration")
|
|
149
|
+
print(" external - Manage external MCP services")
|
|
139
150
|
print(" cleanup - Clean up legacy files")
|
|
140
151
|
print("\nFor help with a specific command:")
|
|
141
152
|
print(" claude-mpm mcp <command> --help")
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MCP Configuration Command
|
|
3
|
+
=========================
|
|
4
|
+
|
|
5
|
+
Command for managing MCP service configurations with pipx preference.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from ...services.mcp_config_manager import MCPConfigManager
|
|
12
|
+
from ..shared import BaseCommand, CommandResult
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MCPConfigCommand(BaseCommand):
|
|
16
|
+
"""Manage MCP service configurations."""
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
super().__init__("mcp-config")
|
|
20
|
+
|
|
21
|
+
def run(self, args) -> CommandResult:
|
|
22
|
+
"""Execute the MCP configuration command."""
|
|
23
|
+
manager = MCPConfigManager()
|
|
24
|
+
|
|
25
|
+
# Handle different sub-commands
|
|
26
|
+
if hasattr(args, "mcp_config_command"):
|
|
27
|
+
command = args.mcp_config_command
|
|
28
|
+
|
|
29
|
+
if command == "detect":
|
|
30
|
+
return self._detect_services(manager)
|
|
31
|
+
if command == "update":
|
|
32
|
+
return self._update_config(manager, args)
|
|
33
|
+
if command == "validate":
|
|
34
|
+
return self._validate_config(manager)
|
|
35
|
+
if command == "install":
|
|
36
|
+
return self._install_services(manager)
|
|
37
|
+
return self._show_status(manager)
|
|
38
|
+
return self._show_status(manager)
|
|
39
|
+
|
|
40
|
+
def _detect_services(self, manager: MCPConfigManager) -> CommandResult:
|
|
41
|
+
"""Detect available MCP services."""
|
|
42
|
+
results = {}
|
|
43
|
+
for service in manager.PIPX_SERVICES:
|
|
44
|
+
path = manager.detect_service_path(service)
|
|
45
|
+
results[service] = {
|
|
46
|
+
"found": path is not None,
|
|
47
|
+
"path": path or "Not found",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return CommandResult(
|
|
51
|
+
success=True,
|
|
52
|
+
message="MCP service detection complete",
|
|
53
|
+
data=results,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def _update_config(self, manager: MCPConfigManager, args) -> CommandResult:
|
|
57
|
+
"""Update MCP configuration."""
|
|
58
|
+
force_pipx = getattr(args, "force_pipx", True)
|
|
59
|
+
success, message = manager.update_mcp_config(force_pipx=force_pipx)
|
|
60
|
+
|
|
61
|
+
if success:
|
|
62
|
+
# Show the updated configuration
|
|
63
|
+
config_path = Path.cwd() / ".mcp.json"
|
|
64
|
+
if config_path.exists():
|
|
65
|
+
with open(config_path) as f:
|
|
66
|
+
config = json.load(f)
|
|
67
|
+
return CommandResult(
|
|
68
|
+
success=True,
|
|
69
|
+
message=message,
|
|
70
|
+
data=config,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
return CommandResult(
|
|
74
|
+
success=success,
|
|
75
|
+
message=message,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
def _validate_config(self, manager: MCPConfigManager) -> CommandResult:
|
|
79
|
+
"""Validate current MCP configuration."""
|
|
80
|
+
results = manager.validate_configuration()
|
|
81
|
+
|
|
82
|
+
all_valid = all(results.values()) if results else False
|
|
83
|
+
message = (
|
|
84
|
+
"All MCP services are properly configured"
|
|
85
|
+
if all_valid
|
|
86
|
+
else "Some MCP services are not accessible"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
return CommandResult(
|
|
90
|
+
success=all_valid,
|
|
91
|
+
message=message,
|
|
92
|
+
data=results,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
def _install_services(self, manager: MCPConfigManager) -> CommandResult:
|
|
96
|
+
"""Install missing MCP services."""
|
|
97
|
+
success, message = manager.install_missing_services()
|
|
98
|
+
return CommandResult(
|
|
99
|
+
success=success,
|
|
100
|
+
message=message,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
def _show_status(self, manager: MCPConfigManager) -> CommandResult:
|
|
104
|
+
"""Show current MCP configuration status."""
|
|
105
|
+
# Detect services
|
|
106
|
+
detected = {}
|
|
107
|
+
for service in manager.PIPX_SERVICES:
|
|
108
|
+
path = manager.detect_service_path(service)
|
|
109
|
+
detected[service] = {
|
|
110
|
+
"installed": path is not None,
|
|
111
|
+
"path": path or "Not installed",
|
|
112
|
+
"via_pipx": path and "pipx" in path if path else False,
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
# Validate configuration
|
|
116
|
+
config_valid = manager.validate_configuration()
|
|
117
|
+
|
|
118
|
+
# Read current config
|
|
119
|
+
config_path = Path.cwd() / ".mcp.json"
|
|
120
|
+
current_config = {}
|
|
121
|
+
if config_path.exists():
|
|
122
|
+
try:
|
|
123
|
+
with open(config_path) as f:
|
|
124
|
+
current_config = json.load(f)
|
|
125
|
+
except Exception:
|
|
126
|
+
pass
|
|
127
|
+
|
|
128
|
+
status_data = {
|
|
129
|
+
"services": detected,
|
|
130
|
+
"configuration_valid": config_valid,
|
|
131
|
+
"config_file_exists": config_path.exists(),
|
|
132
|
+
"configured_services": list(current_config.get("mcpServers", {}).keys()),
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return CommandResult(
|
|
136
|
+
success=True,
|
|
137
|
+
message="MCP configuration status",
|
|
138
|
+
data=status_data,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def manage_mcp_config(args):
|
|
143
|
+
"""
|
|
144
|
+
Entry point for MCP configuration command.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
args: Parsed command line arguments
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Exit code
|
|
151
|
+
"""
|
|
152
|
+
command = MCPConfigCommand()
|
|
153
|
+
result = command.execute(args)
|
|
154
|
+
return result.exit_code
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"""MCP external services command implementations.
|
|
2
|
+
|
|
3
|
+
This module provides commands for managing external MCP services
|
|
4
|
+
like mcp-vector-search and mcp-browser.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MCPExternalCommands:
|
|
9
|
+
"""Handles MCP external service commands."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, logger):
|
|
12
|
+
"""Initialize the MCP external commands handler."""
|
|
13
|
+
self.logger = logger
|
|
14
|
+
|
|
15
|
+
def manage_external(self, args): # noqa: PLR0911
|
|
16
|
+
"""Manage external MCP services.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
args: Parsed command line arguments
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
int: Exit code (0 for success, non-zero for failure)
|
|
23
|
+
"""
|
|
24
|
+
# Get the external subcommand if it exists
|
|
25
|
+
external_action = getattr(args, "external_action", None)
|
|
26
|
+
|
|
27
|
+
if not external_action:
|
|
28
|
+
# No subcommand provided, show help
|
|
29
|
+
self._show_help()
|
|
30
|
+
return 0
|
|
31
|
+
|
|
32
|
+
# Route to appropriate handler
|
|
33
|
+
if external_action == "setup":
|
|
34
|
+
return self._setup_external(args)
|
|
35
|
+
if external_action == "list":
|
|
36
|
+
return self._list_external(args)
|
|
37
|
+
if external_action == "check":
|
|
38
|
+
return self._check_external(args)
|
|
39
|
+
if external_action == "fix-browser":
|
|
40
|
+
return self._fix_browser(args)
|
|
41
|
+
if external_action == "detect":
|
|
42
|
+
return self._detect_and_update(args)
|
|
43
|
+
print(f"Unknown external subcommand: {external_action}")
|
|
44
|
+
self._show_help()
|
|
45
|
+
return 1
|
|
46
|
+
|
|
47
|
+
def _setup_external(self, args):
|
|
48
|
+
"""Setup external MCP services in Claude Desktop.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
args: Command line arguments
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
int: Exit code
|
|
55
|
+
"""
|
|
56
|
+
print("📦 Setting up External MCP Services")
|
|
57
|
+
print("=" * 50)
|
|
58
|
+
|
|
59
|
+
from .mcp_setup_external import MCPExternalServicesSetup
|
|
60
|
+
|
|
61
|
+
setup = MCPExternalServicesSetup(self.logger)
|
|
62
|
+
|
|
63
|
+
# First install Python packages
|
|
64
|
+
print("\n1️⃣ Installing Python packages...")
|
|
65
|
+
if not setup.check_and_install_pip_packages():
|
|
66
|
+
print("⚠️ Some Python packages could not be installed")
|
|
67
|
+
print(" You may need to install them manually:")
|
|
68
|
+
print(" pip install mcp-vector-search mcp-browser")
|
|
69
|
+
|
|
70
|
+
# Then configure in Claude Desktop
|
|
71
|
+
print("\n2️⃣ Configuring Claude Desktop...")
|
|
72
|
+
force = getattr(args, "force", False)
|
|
73
|
+
if setup.setup_external_services(force=force):
|
|
74
|
+
print("\n✅ External services setup completed successfully!")
|
|
75
|
+
print("\nNext steps:")
|
|
76
|
+
print("1. Restart Claude Desktop to load the new services")
|
|
77
|
+
print("2. Check status with: claude-mpm mcp external list")
|
|
78
|
+
print("3. The services will be available in Claude as separate MCP servers")
|
|
79
|
+
return 0
|
|
80
|
+
print("\n❌ Failed to setup external services")
|
|
81
|
+
print("Please check the error messages above and try again")
|
|
82
|
+
return 1
|
|
83
|
+
|
|
84
|
+
def _list_external(self, args):
|
|
85
|
+
"""List external MCP services and their status.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
args: Command line arguments
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
int: Exit code
|
|
92
|
+
"""
|
|
93
|
+
from .mcp_setup_external import MCPExternalServicesSetup
|
|
94
|
+
|
|
95
|
+
setup = MCPExternalServicesSetup(self.logger)
|
|
96
|
+
setup.list_external_services()
|
|
97
|
+
return 0
|
|
98
|
+
|
|
99
|
+
def _check_external(self, args):
|
|
100
|
+
"""Check if external services are properly configured.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
args: Command line arguments
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
int: Exit code
|
|
107
|
+
"""
|
|
108
|
+
print("🔍 Checking External MCP Services Configuration")
|
|
109
|
+
print("=" * 50)
|
|
110
|
+
|
|
111
|
+
import json
|
|
112
|
+
from pathlib import Path
|
|
113
|
+
|
|
114
|
+
# Check Claude Desktop configuration
|
|
115
|
+
config_paths = [
|
|
116
|
+
Path.home()
|
|
117
|
+
/ "Library"
|
|
118
|
+
/ "Application Support"
|
|
119
|
+
/ "Claude"
|
|
120
|
+
/ "claude_desktop_config.json", # macOS
|
|
121
|
+
Path.home() / ".config" / "Claude" / "claude_desktop_config.json", # Linux
|
|
122
|
+
Path.home()
|
|
123
|
+
/ "AppData"
|
|
124
|
+
/ "Roaming"
|
|
125
|
+
/ "Claude"
|
|
126
|
+
/ "claude_desktop_config.json", # Windows
|
|
127
|
+
Path.home() / ".claude" / "claude_desktop_config.json", # Alternative
|
|
128
|
+
Path.home() / ".claude.json", # Legacy
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
config_found = False
|
|
132
|
+
for config_path in config_paths:
|
|
133
|
+
if config_path.exists():
|
|
134
|
+
config_found = True
|
|
135
|
+
print(f"\n📄 Found config: {config_path}")
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
with open(config_path) as f:
|
|
139
|
+
config = json.load(f)
|
|
140
|
+
|
|
141
|
+
mcp_servers = config.get("mcpServers", {})
|
|
142
|
+
|
|
143
|
+
# Check for external services
|
|
144
|
+
external_services = ["mcp-vector-search", "mcp-browser"]
|
|
145
|
+
for service in external_services:
|
|
146
|
+
if service in mcp_servers:
|
|
147
|
+
print(f" ✅ {service} is configured")
|
|
148
|
+
server_config = mcp_servers[service]
|
|
149
|
+
print(f" Command: {server_config.get('command')}")
|
|
150
|
+
print(f" Args: {server_config.get('args')}")
|
|
151
|
+
else:
|
|
152
|
+
print(f" ❌ {service} is NOT configured")
|
|
153
|
+
|
|
154
|
+
except Exception as e:
|
|
155
|
+
print(f" ❌ Error reading config: {e}")
|
|
156
|
+
|
|
157
|
+
break
|
|
158
|
+
|
|
159
|
+
if not config_found:
|
|
160
|
+
print("❌ No Claude Desktop configuration found")
|
|
161
|
+
print(" Please run: claude-mpm mcp install")
|
|
162
|
+
|
|
163
|
+
# Check Python packages
|
|
164
|
+
print("\n🐍 Python Package Status:")
|
|
165
|
+
from .mcp_setup_external import MCPExternalServicesSetup
|
|
166
|
+
|
|
167
|
+
setup = MCPExternalServicesSetup(self.logger)
|
|
168
|
+
|
|
169
|
+
packages = [
|
|
170
|
+
("mcp-vector-search", "mcp_vector_search"),
|
|
171
|
+
("mcp-browser", "mcp_browser"),
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
for package_name, module_name in packages:
|
|
175
|
+
if setup._check_python_package(module_name):
|
|
176
|
+
print(f" ✅ {package_name} is installed")
|
|
177
|
+
else:
|
|
178
|
+
print(f" ❌ {package_name} is NOT installed")
|
|
179
|
+
|
|
180
|
+
return 0
|
|
181
|
+
|
|
182
|
+
def _fix_browser(self, args):
|
|
183
|
+
"""Fix mcp-browser configuration to use pipx installation.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
args: Command line arguments
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
int: Exit code
|
|
190
|
+
"""
|
|
191
|
+
from .mcp_setup_external import MCPExternalServicesSetup
|
|
192
|
+
|
|
193
|
+
setup = MCPExternalServicesSetup(self.logger)
|
|
194
|
+
if setup.fix_browser_configuration():
|
|
195
|
+
return 0
|
|
196
|
+
return 1
|
|
197
|
+
|
|
198
|
+
def _detect_and_update(self, args):
|
|
199
|
+
"""Auto-detect MCP service installations and update configuration.
|
|
200
|
+
|
|
201
|
+
Prioritizes local development installations over pipx/system.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
args: Command line arguments
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
int: Exit code
|
|
208
|
+
"""
|
|
209
|
+
from .mcp_setup_external import MCPExternalServicesSetup
|
|
210
|
+
|
|
211
|
+
setup = MCPExternalServicesSetup(self.logger)
|
|
212
|
+
force = getattr(args, "force", False)
|
|
213
|
+
|
|
214
|
+
if setup.update_mcp_json_with_detected(force=force):
|
|
215
|
+
print("\n✅ Configuration updated successfully!")
|
|
216
|
+
print("\nNext steps:")
|
|
217
|
+
print("1. Review the .mcp.json file to verify the configuration")
|
|
218
|
+
print("2. Restart Claude Desktop to load the updated services")
|
|
219
|
+
return 0
|
|
220
|
+
print("\n❌ Failed to update configuration")
|
|
221
|
+
return 1
|
|
222
|
+
|
|
223
|
+
def _show_help(self):
|
|
224
|
+
"""Show help for external commands."""
|
|
225
|
+
print("\nMCP External Services Management")
|
|
226
|
+
print("=" * 40)
|
|
227
|
+
print("\nAvailable commands:")
|
|
228
|
+
print(
|
|
229
|
+
" setup - Setup external MCP services (mcp-vector-search, mcp-browser)"
|
|
230
|
+
)
|
|
231
|
+
print(" list - List available external services and their status")
|
|
232
|
+
print(" check - Check configuration and installation status")
|
|
233
|
+
print(
|
|
234
|
+
" detect - Auto-detect installations and update .mcp.json (prioritizes local dev)"
|
|
235
|
+
)
|
|
236
|
+
print(" fix-browser - Fix mcp-browser configuration to use pipx installation")
|
|
237
|
+
print("\nUsage:")
|
|
238
|
+
print(" claude-mpm mcp external setup # Interactive setup")
|
|
239
|
+
print(" claude-mpm mcp external setup --force # Force reconfiguration")
|
|
240
|
+
print(" claude-mpm mcp external detect # Auto-detect and update config")
|
|
241
|
+
print(
|
|
242
|
+
" claude-mpm mcp external detect --force # Force update even if configured"
|
|
243
|
+
)
|
|
244
|
+
print(" claude-mpm mcp external list # Show service status")
|
|
245
|
+
print(" claude-mpm mcp external check # Detailed configuration check")
|
|
246
|
+
print(" claude-mpm mcp external fix-browser # Fix mcp-browser to use pipx")
|
|
247
|
+
print("\nExternal services provide additional capabilities:")
|
|
248
|
+
print(" - mcp-vector-search: Semantic code search with embeddings")
|
|
249
|
+
print(" - mcp-browser: Web browsing and content extraction")
|
|
@@ -46,31 +46,62 @@ class MCPInstallCommands:
|
|
|
46
46
|
print("\nPlease install manually with: pip install mcp")
|
|
47
47
|
return 1
|
|
48
48
|
|
|
49
|
-
# Step 2: Configure Claude
|
|
50
|
-
print("\n2️⃣ Configuring Claude
|
|
49
|
+
# Step 2: Configure Claude Desktop with the new CLI command
|
|
50
|
+
print("\n2️⃣ Configuring Claude Desktop...")
|
|
51
51
|
try:
|
|
52
52
|
success = self._configure_claude_desktop(args.force)
|
|
53
|
-
if success:
|
|
54
|
-
print("
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
if not success:
|
|
54
|
+
print("❌ Main gateway configuration failed")
|
|
55
|
+
return 1
|
|
56
|
+
|
|
57
|
+
# Step 3: Setup external MCP services
|
|
58
|
+
print("\n3️⃣ Setting up External MCP Services...")
|
|
59
|
+
from .mcp_setup_external import MCPExternalServicesSetup
|
|
60
|
+
|
|
61
|
+
external_setup = MCPExternalServicesSetup(self.logger)
|
|
62
|
+
|
|
63
|
+
# Check if user wants to set up external services
|
|
64
|
+
response = (
|
|
65
|
+
input(
|
|
66
|
+
"\nDo you want to set up external MCP services (mcp-vector-search, mcp-browser)? (Y/n): "
|
|
67
|
+
)
|
|
68
|
+
.strip()
|
|
69
|
+
.lower()
|
|
70
|
+
)
|
|
71
|
+
if response in ["", "y", "yes"]:
|
|
72
|
+
# Install Python packages for external services
|
|
73
|
+
external_setup.check_and_install_pip_packages()
|
|
74
|
+
|
|
75
|
+
# Setup external services in Claude Desktop config
|
|
76
|
+
if external_setup.setup_external_services(force=args.force):
|
|
77
|
+
print("✅ External services configured successfully")
|
|
78
|
+
else:
|
|
79
|
+
print("⚠️ Some external services may not have been configured")
|
|
80
|
+
else:
|
|
81
|
+
print("⏭️ Skipping external services setup")
|
|
82
|
+
print(
|
|
83
|
+
" You can set them up later with: claude-mpm mcp external setup"
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
print("\n✅ Configuration completed successfully")
|
|
87
|
+
print("\n🎉 MCP Gateway is ready to use!")
|
|
88
|
+
print("\nNext steps:")
|
|
89
|
+
print("1. Restart Claude Desktop (if running)")
|
|
90
|
+
print("2. Test the server: claude-mpm mcp server --test")
|
|
91
|
+
print("3. Check status: claude-mpm mcp status")
|
|
92
|
+
print("4. List external services: claude-mpm mcp external list")
|
|
93
|
+
return 0
|
|
63
94
|
|
|
64
95
|
except Exception as e:
|
|
65
96
|
print(f"❌ Error during configuration: {e}")
|
|
66
97
|
return 1
|
|
67
98
|
|
|
68
99
|
def _configure_claude_desktop(self, force=False):
|
|
69
|
-
"""Configure Claude
|
|
100
|
+
"""Configure Claude Desktop to use the MCP gateway via CLI command.
|
|
70
101
|
|
|
71
|
-
WHY: Claude
|
|
72
|
-
|
|
73
|
-
|
|
102
|
+
WHY: Claude Desktop reads MCP server configurations from a platform-specific
|
|
103
|
+
configuration file. This method updates that file to include the claude-mpm-gateway
|
|
104
|
+
server configuration.
|
|
74
105
|
|
|
75
106
|
Args:
|
|
76
107
|
force: Whether to overwrite existing configuration
|
|
@@ -135,16 +166,54 @@ class MCPInstallCommands:
|
|
|
135
166
|
return self._save_config(config, config_path)
|
|
136
167
|
|
|
137
168
|
def _get_claude_config_path(self):
|
|
138
|
-
"""Get the Claude
|
|
169
|
+
"""Get the Claude Desktop configuration file path.
|
|
139
170
|
|
|
140
171
|
Returns:
|
|
141
|
-
Path or None: Path to Claude
|
|
172
|
+
Path or None: Path to Claude Desktop config file
|
|
142
173
|
"""
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
#
|
|
146
|
-
|
|
147
|
-
|
|
174
|
+
import platform
|
|
175
|
+
|
|
176
|
+
# Try multiple possible locations for Claude Desktop config
|
|
177
|
+
possible_paths = [
|
|
178
|
+
Path.home()
|
|
179
|
+
/ "Library"
|
|
180
|
+
/ "Application Support"
|
|
181
|
+
/ "Claude"
|
|
182
|
+
/ "claude_desktop_config.json", # macOS
|
|
183
|
+
Path.home() / ".config" / "Claude" / "claude_desktop_config.json", # Linux
|
|
184
|
+
Path.home()
|
|
185
|
+
/ "AppData"
|
|
186
|
+
/ "Roaming"
|
|
187
|
+
/ "Claude"
|
|
188
|
+
/ "claude_desktop_config.json", # Windows
|
|
189
|
+
Path.home() / ".claude" / "claude_desktop_config.json", # Alternative
|
|
190
|
+
Path.home() / ".claude.json", # Legacy
|
|
191
|
+
]
|
|
192
|
+
|
|
193
|
+
for path in possible_paths:
|
|
194
|
+
if path.exists():
|
|
195
|
+
return path
|
|
196
|
+
|
|
197
|
+
# If none exist, return the platform-appropriate default
|
|
198
|
+
system = platform.system()
|
|
199
|
+
if system == "Darwin": # macOS
|
|
200
|
+
return (
|
|
201
|
+
Path.home()
|
|
202
|
+
/ "Library"
|
|
203
|
+
/ "Application Support"
|
|
204
|
+
/ "Claude"
|
|
205
|
+
/ "claude_desktop_config.json"
|
|
206
|
+
)
|
|
207
|
+
if system == "Windows":
|
|
208
|
+
return (
|
|
209
|
+
Path.home()
|
|
210
|
+
/ "AppData"
|
|
211
|
+
/ "Roaming"
|
|
212
|
+
/ "Claude"
|
|
213
|
+
/ "claude_desktop_config.json"
|
|
214
|
+
)
|
|
215
|
+
# Linux and others
|
|
216
|
+
return Path.home() / ".config" / "Claude" / "claude_desktop_config.json"
|
|
148
217
|
|
|
149
218
|
def _find_claude_mpm_executable(self):
|
|
150
219
|
"""Find the claude-mpm executable path.
|
|
@@ -240,7 +309,7 @@ class MCPInstallCommands:
|
|
|
240
309
|
existing_config = json.load(f)
|
|
241
310
|
config = existing_config
|
|
242
311
|
print(" Force mode: Overwriting existing configuration")
|
|
243
|
-
except:
|
|
312
|
+
except Exception:
|
|
244
313
|
pass # File doesn't exist or is invalid, start fresh
|
|
245
314
|
|
|
246
315
|
# Ensure mcpServers section exists
|