claude-mpm 4.3.12__py3-none-any.whl ā 4.3.14__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 +414 -28
- claude_mpm/agents/templates/data_engineer.json +39 -14
- claude_mpm/agents/templates/engineer.json +11 -3
- 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 +1 -1
- claude_mpm/cli/commands/mcp_config.py +7 -10
- claude_mpm/cli/commands/mcp_external_commands.py +40 -32
- claude_mpm/cli/commands/mcp_install_commands.py +38 -10
- claude_mpm/cli/commands/mcp_setup_external.py +143 -102
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init_handler.py +1 -1
- claude_mpm/cli/commands/run.py +54 -2
- claude_mpm/cli/commands/search.py +41 -34
- claude_mpm/cli/interactive/agent_wizard.py +6 -2
- claude_mpm/cli/parsers/mcp_parser.py +1 -3
- claude_mpm/cli/parsers/search_parser.py +10 -4
- claude_mpm/cli/startup_logging.py +158 -5
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/core/agent_registry.py +2 -2
- claude_mpm/core/agent_session_manager.py +8 -8
- claude_mpm/core/api_validator.py +6 -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 +3 -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/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 +2 -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/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
- 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/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +8 -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 +7 -5
- claude_mpm/scripts/mcp_server.py +0 -0
- claude_mpm/scripts/start_activity_logging.py +0 -0
- 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 +2 -1
- claude_mpm/services/agents/deployment/agent_discovery_service.py +9 -3
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +5 -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/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/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_listing_service.py +3 -1
- claude_mpm/services/cli/agent_validation_service.py +2 -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/core/memory_manager.py +81 -23
- claude_mpm/services/core/path_resolver.py +1 -1
- 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 +175 -30
- 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 +1 -1
- claude_mpm/services/mcp_gateway/core/base.py +2 -2
- claude_mpm/services/mcp_gateway/main.py +21 -7
- 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 +5 -2
- 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 +190 -137
- 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 +16 -16
- 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/management/lifecycle.py +3 -1
- claude_mpm/services/monitor/server.py +4 -4
- claude_mpm/services/monitor_build_service.py +2 -2
- claude_mpm/services/port_manager.py +3 -1
- 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 +11 -7
- 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/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 -12
- 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/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 +3 -1
- claude_mpm/storage/state_storage.py +1 -1
- claude_mpm/tools/code_tree_analyzer.py +23 -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 +6 -2
- claude_mpm/utils/dependency_strategies.py +8 -3
- claude_mpm/utils/environment_context.py +1 -1
- claude_mpm/utils/error_handler.py +2 -2
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/log_cleanup.py +21 -7
- claude_mpm/validation/agent_validator.py +2 -2
- {claude_mpm-4.3.12.dist-info ā claude_mpm-4.3.14.dist-info}/METADATA +1 -1
- {claude_mpm-4.3.12.dist-info ā claude_mpm-4.3.14.dist-info}/RECORD +204 -191
- {claude_mpm-4.3.12.dist-info ā claude_mpm-4.3.14.dist-info}/WHEEL +0 -0
- {claude_mpm-4.3.12.dist-info ā claude_mpm-4.3.14.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.3.12.dist-info ā claude_mpm-4.3.14.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.3.12.dist-info ā claude_mpm-4.3.14.dist-info}/top_level.txt +0 -0
|
@@ -5,11 +5,11 @@ This module handles the registration of external MCP services
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import json
|
|
8
|
-
import os
|
|
9
8
|
import subprocess
|
|
10
9
|
import sys
|
|
10
|
+
from datetime import timezone
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Dict, Optional,
|
|
12
|
+
from typing import Dict, Optional, Tuple
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class MCPExternalServicesSetup:
|
|
@@ -26,21 +26,23 @@ class MCPExternalServicesSetup:
|
|
|
26
26
|
"""
|
|
27
27
|
# Detect best command paths for services
|
|
28
28
|
mcp_browser_config = self._get_best_service_config("mcp-browser", project_path)
|
|
29
|
-
mcp_vector_search_config = self._get_best_service_config(
|
|
29
|
+
mcp_vector_search_config = self._get_best_service_config(
|
|
30
|
+
"mcp-vector-search", project_path
|
|
31
|
+
)
|
|
30
32
|
|
|
31
33
|
return {
|
|
32
34
|
"mcp-vector-search": {
|
|
33
35
|
"package_name": "mcp-vector-search",
|
|
34
36
|
"module_name": "mcp_vector_search",
|
|
35
37
|
"description": "Semantic code search with vector embeddings",
|
|
36
|
-
"config": mcp_vector_search_config
|
|
38
|
+
"config": mcp_vector_search_config,
|
|
37
39
|
},
|
|
38
40
|
"mcp-browser": {
|
|
39
41
|
"package_name": "mcp-browser",
|
|
40
42
|
"module_name": "mcp_browser",
|
|
41
43
|
"description": "Web browsing and content extraction",
|
|
42
|
-
"config": mcp_browser_config
|
|
43
|
-
}
|
|
44
|
+
"config": mcp_browser_config,
|
|
45
|
+
},
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
def _get_best_service_config(self, service_name: str, project_path: Path) -> Dict:
|
|
@@ -85,7 +87,9 @@ class MCPExternalServicesSetup:
|
|
|
85
87
|
# Fall back to system Python
|
|
86
88
|
return self._get_system_config(service_name, project_path)
|
|
87
89
|
|
|
88
|
-
def _get_local_dev_config(
|
|
90
|
+
def _get_local_dev_config(
|
|
91
|
+
self, service_name: str, project_path: Path
|
|
92
|
+
) -> Optional[Dict]:
|
|
89
93
|
"""Get configuration for a locally developed service.
|
|
90
94
|
|
|
91
95
|
Checks common development locations like ~/Projects/managed/
|
|
@@ -128,8 +132,10 @@ class MCPExternalServicesSetup:
|
|
|
128
132
|
"command": str(mcp_browser_binary),
|
|
129
133
|
"args": ["mcp"],
|
|
130
134
|
"env": {
|
|
131
|
-
"MCP_BROWSER_HOME": str(
|
|
132
|
-
|
|
135
|
+
"MCP_BROWSER_HOME": str(
|
|
136
|
+
Path.home() / ".mcp-browser"
|
|
137
|
+
)
|
|
138
|
+
},
|
|
133
139
|
}
|
|
134
140
|
|
|
135
141
|
# Then check for mcp-server.py
|
|
@@ -140,9 +146,11 @@ class MCPExternalServicesSetup:
|
|
|
140
146
|
"command": str(venv_python),
|
|
141
147
|
"args": [str(mcp_server)],
|
|
142
148
|
"env": {
|
|
143
|
-
"MCP_BROWSER_HOME": str(
|
|
144
|
-
|
|
145
|
-
|
|
149
|
+
"MCP_BROWSER_HOME": str(
|
|
150
|
+
Path.home() / ".mcp-browser"
|
|
151
|
+
),
|
|
152
|
+
"PYTHONPATH": str(dev_path),
|
|
153
|
+
},
|
|
146
154
|
}
|
|
147
155
|
|
|
148
156
|
# Check if the package is installed in this venv
|
|
@@ -151,7 +159,8 @@ class MCPExternalServicesSetup:
|
|
|
151
159
|
result = subprocess.run(
|
|
152
160
|
[str(venv_python), "-c", f"import {module_name}"],
|
|
153
161
|
capture_output=True,
|
|
154
|
-
timeout=5
|
|
162
|
+
timeout=5,
|
|
163
|
+
check=False,
|
|
155
164
|
)
|
|
156
165
|
if result.returncode == 0:
|
|
157
166
|
# Use special configuration for local dev
|
|
@@ -159,21 +168,27 @@ class MCPExternalServicesSetup:
|
|
|
159
168
|
return {
|
|
160
169
|
"type": "stdio",
|
|
161
170
|
"command": str(venv_python),
|
|
162
|
-
"args": [
|
|
163
|
-
|
|
171
|
+
"args": [
|
|
172
|
+
"-m",
|
|
173
|
+
"mcp_vector_search.mcp.server",
|
|
174
|
+
str(project_path),
|
|
175
|
+
],
|
|
176
|
+
"env": {},
|
|
164
177
|
}
|
|
165
|
-
|
|
178
|
+
if service_name == "mcp-browser":
|
|
166
179
|
# Fallback for mcp-browser without mcp-server.py
|
|
167
180
|
return {
|
|
168
181
|
"type": "stdio",
|
|
169
182
|
"command": str(venv_python),
|
|
170
183
|
"args": ["-m", "mcp_browser", "mcp"],
|
|
171
184
|
"env": {
|
|
172
|
-
"MCP_BROWSER_HOME": str(
|
|
173
|
-
|
|
174
|
-
|
|
185
|
+
"MCP_BROWSER_HOME": str(
|
|
186
|
+
Path.home() / ".mcp-browser"
|
|
187
|
+
),
|
|
188
|
+
"PYTHONPATH": str(dev_path),
|
|
189
|
+
},
|
|
175
190
|
}
|
|
176
|
-
except:
|
|
191
|
+
except Exception:
|
|
177
192
|
continue
|
|
178
193
|
|
|
179
194
|
return None
|
|
@@ -203,11 +218,14 @@ class MCPExternalServicesSetup:
|
|
|
203
218
|
result = subprocess.run(
|
|
204
219
|
[str(venv_python), "-c", f"import {module_name}"],
|
|
205
220
|
capture_output=True,
|
|
206
|
-
timeout=5
|
|
221
|
+
timeout=5,
|
|
222
|
+
check=False,
|
|
207
223
|
)
|
|
208
224
|
if result.returncode == 0:
|
|
209
|
-
return self._create_service_config(
|
|
210
|
-
|
|
225
|
+
return self._create_service_config(
|
|
226
|
+
service_name, str(venv_python), project_path
|
|
227
|
+
)
|
|
228
|
+
except Exception:
|
|
211
229
|
continue
|
|
212
230
|
|
|
213
231
|
return None
|
|
@@ -224,7 +242,9 @@ class MCPExternalServicesSetup:
|
|
|
224
242
|
"""
|
|
225
243
|
return self._create_service_config(service_name, sys.executable, project_path)
|
|
226
244
|
|
|
227
|
-
def _create_service_config(
|
|
245
|
+
def _create_service_config(
|
|
246
|
+
self, service_name: str, python_path: str, project_path: Path
|
|
247
|
+
) -> Dict:
|
|
228
248
|
"""Create service configuration for the given Python executable.
|
|
229
249
|
|
|
230
250
|
Args:
|
|
@@ -243,32 +263,30 @@ class MCPExternalServicesSetup:
|
|
|
243
263
|
"type": "stdio",
|
|
244
264
|
"command": str(binary_path),
|
|
245
265
|
"args": ["mcp"],
|
|
246
|
-
"env": {"MCP_BROWSER_HOME": str(Path.home() / ".mcp-browser")}
|
|
247
|
-
}
|
|
248
|
-
else:
|
|
249
|
-
# Use Python module invocation
|
|
250
|
-
return {
|
|
251
|
-
"type": "stdio",
|
|
252
|
-
"command": python_path,
|
|
253
|
-
"args": ["-m", "mcp_browser", "mcp"],
|
|
254
|
-
"env": {"MCP_BROWSER_HOME": str(Path.home() / ".mcp-browser")}
|
|
266
|
+
"env": {"MCP_BROWSER_HOME": str(Path.home() / ".mcp-browser")},
|
|
255
267
|
}
|
|
256
|
-
|
|
268
|
+
# Use Python module invocation
|
|
257
269
|
return {
|
|
258
270
|
"type": "stdio",
|
|
259
271
|
"command": python_path,
|
|
260
|
-
"args": ["-m", "
|
|
261
|
-
"env": {}
|
|
272
|
+
"args": ["-m", "mcp_browser", "mcp"],
|
|
273
|
+
"env": {"MCP_BROWSER_HOME": str(Path.home() / ".mcp-browser")},
|
|
262
274
|
}
|
|
263
|
-
|
|
264
|
-
# Generic configuration for other services
|
|
265
|
-
module_name = service_name.replace("-", "_")
|
|
275
|
+
if service_name == "mcp-vector-search":
|
|
266
276
|
return {
|
|
267
277
|
"type": "stdio",
|
|
268
278
|
"command": python_path,
|
|
269
|
-
"args": ["-m",
|
|
270
|
-
"env": {}
|
|
279
|
+
"args": ["-m", "mcp_vector_search.mcp.server", str(project_path)],
|
|
280
|
+
"env": {},
|
|
271
281
|
}
|
|
282
|
+
# Generic configuration for other services
|
|
283
|
+
module_name = service_name.replace("-", "_")
|
|
284
|
+
return {
|
|
285
|
+
"type": "stdio",
|
|
286
|
+
"command": python_path,
|
|
287
|
+
"args": ["-m", module_name],
|
|
288
|
+
"env": {},
|
|
289
|
+
}
|
|
272
290
|
|
|
273
291
|
def detect_mcp_installations(self) -> Dict[str, Dict]:
|
|
274
292
|
"""Detect all MCP service installations and their locations.
|
|
@@ -293,7 +311,7 @@ class MCPExternalServicesSetup:
|
|
|
293
311
|
installations[service_name] = {
|
|
294
312
|
"type": "local_dev",
|
|
295
313
|
"path": local_dev_config["command"],
|
|
296
|
-
"config": local_dev_config
|
|
314
|
+
"config": local_dev_config,
|
|
297
315
|
}
|
|
298
316
|
continue
|
|
299
317
|
|
|
@@ -305,7 +323,7 @@ class MCPExternalServicesSetup:
|
|
|
305
323
|
installations[service_name] = {
|
|
306
324
|
"type": "pipx",
|
|
307
325
|
"path": pipx_config["command"],
|
|
308
|
-
"config": pipx_config
|
|
326
|
+
"config": pipx_config,
|
|
309
327
|
}
|
|
310
328
|
continue
|
|
311
329
|
|
|
@@ -314,7 +332,7 @@ class MCPExternalServicesSetup:
|
|
|
314
332
|
installations[service_name] = {
|
|
315
333
|
"type": "venv",
|
|
316
334
|
"path": venv_config["command"],
|
|
317
|
-
"config": venv_config
|
|
335
|
+
"config": venv_config,
|
|
318
336
|
}
|
|
319
337
|
continue
|
|
320
338
|
|
|
@@ -325,13 +343,13 @@ class MCPExternalServicesSetup:
|
|
|
325
343
|
installations[service_name] = {
|
|
326
344
|
"type": "system",
|
|
327
345
|
"path": system_config["command"],
|
|
328
|
-
"config": system_config
|
|
346
|
+
"config": system_config,
|
|
329
347
|
}
|
|
330
348
|
else:
|
|
331
349
|
installations[service_name] = {
|
|
332
350
|
"type": "not_installed",
|
|
333
351
|
"path": None,
|
|
334
|
-
"config": None
|
|
352
|
+
"config": None,
|
|
335
353
|
}
|
|
336
354
|
|
|
337
355
|
return installations
|
|
@@ -354,13 +372,13 @@ class MCPExternalServicesSetup:
|
|
|
354
372
|
for service_name, info in installations.items():
|
|
355
373
|
print(f"\n{service_name}:")
|
|
356
374
|
if info["type"] == "not_installed":
|
|
357
|
-
print(
|
|
375
|
+
print(" ā Not installed")
|
|
358
376
|
else:
|
|
359
377
|
type_emoji = {
|
|
360
378
|
"local_dev": "š§",
|
|
361
379
|
"pipx": "š¦",
|
|
362
380
|
"venv": "š",
|
|
363
|
-
"system": "š»"
|
|
381
|
+
"system": "š»",
|
|
364
382
|
}.get(info["type"], "ā")
|
|
365
383
|
print(f" {type_emoji} Type: {info['type']}")
|
|
366
384
|
print(f" š Path: {info['path']}")
|
|
@@ -380,7 +398,9 @@ class MCPExternalServicesSetup:
|
|
|
380
398
|
|
|
381
399
|
# Check if already configured
|
|
382
400
|
if service_name in config.get("mcpServers", {}) and not force:
|
|
383
|
-
print(
|
|
401
|
+
print(
|
|
402
|
+
f"\nā ļø {service_name} already configured, skipping (use --force to override)"
|
|
403
|
+
)
|
|
384
404
|
continue
|
|
385
405
|
|
|
386
406
|
# Update configuration
|
|
@@ -394,14 +414,14 @@ class MCPExternalServicesSetup:
|
|
|
394
414
|
# Save configuration if updated
|
|
395
415
|
if updated:
|
|
396
416
|
if self._save_config(config, config_path):
|
|
397
|
-
print(
|
|
417
|
+
print(
|
|
418
|
+
"\nā
Successfully updated .mcp.json with detected configurations"
|
|
419
|
+
)
|
|
398
420
|
return True
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
print("\nš No updates needed")
|
|
404
|
-
return True
|
|
421
|
+
print("\nā Failed to save configuration")
|
|
422
|
+
return False
|
|
423
|
+
print("\nš No updates needed")
|
|
424
|
+
return True
|
|
405
425
|
|
|
406
426
|
def __init__(self, logger):
|
|
407
427
|
"""Initialize the external services setup handler."""
|
|
@@ -439,30 +459,30 @@ class MCPExternalServicesSetup:
|
|
|
439
459
|
|
|
440
460
|
# Setup each external service
|
|
441
461
|
success_count = 0
|
|
442
|
-
for service_name, service_info in self.get_project_services(
|
|
462
|
+
for service_name, service_info in self.get_project_services(
|
|
463
|
+
project_path
|
|
464
|
+
).items():
|
|
443
465
|
if self._setup_service(config, service_name, service_info, force):
|
|
444
466
|
success_count += 1
|
|
445
467
|
|
|
446
468
|
# Save the updated configuration
|
|
447
469
|
if success_count > 0:
|
|
448
470
|
if self._save_config(config, config_path):
|
|
449
|
-
print(
|
|
450
|
-
|
|
451
|
-
|
|
471
|
+
print(
|
|
472
|
+
f"\nā
Successfully configured {success_count} external services in .mcp.json"
|
|
473
|
+
)
|
|
474
|
+
print(
|
|
475
|
+
"\nš Note: Claude Desktop will automatically load these services"
|
|
476
|
+
)
|
|
477
|
+
print(" when you open this project directory in Claude Desktop.")
|
|
452
478
|
return True
|
|
453
|
-
|
|
454
|
-
print("ā Failed to save configuration")
|
|
455
|
-
return False
|
|
456
|
-
else:
|
|
457
|
-
print("\nā ļø No external services were configured")
|
|
479
|
+
print("ā Failed to save configuration")
|
|
458
480
|
return False
|
|
481
|
+
print("\nā ļø No external services were configured")
|
|
482
|
+
return False
|
|
459
483
|
|
|
460
484
|
def _setup_service(
|
|
461
|
-
self,
|
|
462
|
-
config: Dict,
|
|
463
|
-
service_name: str,
|
|
464
|
-
service_info: Dict,
|
|
465
|
-
force: bool
|
|
485
|
+
self, config: Dict, service_name: str, service_info: Dict, force: bool
|
|
466
486
|
) -> bool:
|
|
467
487
|
"""Setup a single external MCP service.
|
|
468
488
|
|
|
@@ -485,12 +505,19 @@ class MCPExternalServicesSetup:
|
|
|
485
505
|
print(f" Current args: {existing_config.get('args')}")
|
|
486
506
|
|
|
487
507
|
# Check if it's using a local development path
|
|
488
|
-
command = str(existing_config.get(
|
|
489
|
-
if any(
|
|
508
|
+
command = str(existing_config.get("command", ""))
|
|
509
|
+
if any(
|
|
510
|
+
path in command
|
|
511
|
+
for path in ["/Projects/managed/", "/Projects/", "/Development/"]
|
|
512
|
+
):
|
|
490
513
|
print(" š Using local development version")
|
|
491
|
-
response =
|
|
514
|
+
response = (
|
|
515
|
+
input(" Keep local development version? (Y/n): ").strip().lower()
|
|
516
|
+
)
|
|
492
517
|
if response not in ["n", "no"]:
|
|
493
|
-
print(
|
|
518
|
+
print(
|
|
519
|
+
f" ā
Keeping existing local configuration for {service_name}"
|
|
520
|
+
)
|
|
494
521
|
return True # Consider it successfully configured
|
|
495
522
|
else:
|
|
496
523
|
response = input(" Overwrite? (y/N): ").strip().lower()
|
|
@@ -503,9 +530,11 @@ class MCPExternalServicesSetup:
|
|
|
503
530
|
if not self._check_python_package(module_name):
|
|
504
531
|
print(f" ā ļø Python package {service_info['package_name']} not installed")
|
|
505
532
|
print(f" ā¹ļø Installing {service_info['package_name']}...")
|
|
506
|
-
if not self._install_python_package(service_info[
|
|
533
|
+
if not self._install_python_package(service_info["package_name"]):
|
|
507
534
|
print(f" ā Failed to install {service_info['package_name']}")
|
|
508
|
-
print(
|
|
535
|
+
print(
|
|
536
|
+
f" ā¹ļø Install manually with: pip install {service_info['package_name']}"
|
|
537
|
+
)
|
|
509
538
|
return False
|
|
510
539
|
|
|
511
540
|
# Add service configuration
|
|
@@ -518,7 +547,6 @@ class MCPExternalServicesSetup:
|
|
|
518
547
|
|
|
519
548
|
return True
|
|
520
549
|
|
|
521
|
-
|
|
522
550
|
def check_and_install_pip_packages(self) -> bool:
|
|
523
551
|
"""Check and install Python packages for external services.
|
|
524
552
|
|
|
@@ -529,7 +557,7 @@ class MCPExternalServicesSetup:
|
|
|
529
557
|
|
|
530
558
|
packages_to_check = [
|
|
531
559
|
("mcp-vector-search", "mcp_vector_search"),
|
|
532
|
-
("mcp-browser", "mcp_browser")
|
|
560
|
+
("mcp-browser", "mcp_browser"),
|
|
533
561
|
]
|
|
534
562
|
|
|
535
563
|
all_installed = True
|
|
@@ -557,6 +585,7 @@ class MCPExternalServicesSetup:
|
|
|
557
585
|
"""
|
|
558
586
|
try:
|
|
559
587
|
import importlib.util
|
|
588
|
+
|
|
560
589
|
spec = importlib.util.find_spec(module_name)
|
|
561
590
|
return spec is not None
|
|
562
591
|
except (ImportError, ModuleNotFoundError):
|
|
@@ -576,7 +605,8 @@ class MCPExternalServicesSetup:
|
|
|
576
605
|
[sys.executable, "-m", "pip", "install", package_name],
|
|
577
606
|
capture_output=True,
|
|
578
607
|
text=True,
|
|
579
|
-
timeout=60
|
|
608
|
+
timeout=60,
|
|
609
|
+
check=False,
|
|
580
610
|
)
|
|
581
611
|
return result.returncode == 0
|
|
582
612
|
except (subprocess.TimeoutExpired, subprocess.CalledProcessError):
|
|
@@ -601,7 +631,7 @@ class MCPExternalServicesSetup:
|
|
|
601
631
|
return config
|
|
602
632
|
else:
|
|
603
633
|
# Create new configuration
|
|
604
|
-
print(
|
|
634
|
+
print(" š Creating new .mcp.json file")
|
|
605
635
|
return {"mcpServers": {}}
|
|
606
636
|
except (OSError, json.JSONDecodeError) as e:
|
|
607
637
|
print(f"ā Error loading config: {e}")
|
|
@@ -625,8 +655,13 @@ class MCPExternalServicesSetup:
|
|
|
625
655
|
# Create backup if file exists
|
|
626
656
|
if config_path.exists():
|
|
627
657
|
from datetime import datetime
|
|
628
|
-
|
|
658
|
+
|
|
659
|
+
backup_path = (
|
|
660
|
+
config_path.parent
|
|
661
|
+
/ f".mcp.backup.{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}.json"
|
|
662
|
+
)
|
|
629
663
|
import shutil
|
|
664
|
+
|
|
630
665
|
shutil.copy2(config_path, backup_path)
|
|
631
666
|
print(f" š Created backup: {backup_path}")
|
|
632
667
|
|
|
@@ -665,16 +700,19 @@ class MCPExternalServicesSetup:
|
|
|
665
700
|
result = subprocess.run(
|
|
666
701
|
[str(python_path), "-c", "import mcp_browser.cli.main"],
|
|
667
702
|
capture_output=True,
|
|
668
|
-
timeout=5
|
|
703
|
+
timeout=5,
|
|
704
|
+
check=False,
|
|
669
705
|
)
|
|
670
706
|
if result.returncode == 0:
|
|
671
707
|
return {
|
|
672
708
|
"type": "stdio",
|
|
673
709
|
"command": str(python_path),
|
|
674
710
|
"args": ["-m", "mcp_browser.cli.main", "mcp"],
|
|
675
|
-
"env": {
|
|
711
|
+
"env": {
|
|
712
|
+
"MCP_BROWSER_HOME": str(Path.home() / ".mcp-browser")
|
|
713
|
+
},
|
|
676
714
|
}
|
|
677
|
-
except:
|
|
715
|
+
except Exception:
|
|
678
716
|
pass
|
|
679
717
|
elif package_name == "mcp-vector-search":
|
|
680
718
|
# mcp-vector-search uses Python module invocation
|
|
@@ -685,16 +723,21 @@ class MCPExternalServicesSetup:
|
|
|
685
723
|
result = subprocess.run(
|
|
686
724
|
[str(python_path), "-c", "import mcp_vector_search"],
|
|
687
725
|
capture_output=True,
|
|
688
|
-
timeout=5
|
|
726
|
+
timeout=5,
|
|
727
|
+
check=False,
|
|
689
728
|
)
|
|
690
729
|
if result.returncode == 0:
|
|
691
730
|
return {
|
|
692
731
|
"type": "stdio",
|
|
693
732
|
"command": str(python_path),
|
|
694
|
-
"args": [
|
|
695
|
-
|
|
733
|
+
"args": [
|
|
734
|
+
"-m",
|
|
735
|
+
"mcp_vector_search.mcp.server",
|
|
736
|
+
str(project_path),
|
|
737
|
+
],
|
|
738
|
+
"env": {},
|
|
696
739
|
}
|
|
697
|
-
except:
|
|
740
|
+
except Exception:
|
|
698
741
|
pass
|
|
699
742
|
|
|
700
743
|
return None
|
|
@@ -774,10 +817,8 @@ class MCPExternalServicesSetup:
|
|
|
774
817
|
print("\nš Note: Claude Desktop will automatically use this configuration")
|
|
775
818
|
print(" when you open this project directory.")
|
|
776
819
|
return True
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
return False
|
|
780
|
-
|
|
820
|
+
print("ā Failed to save configuration")
|
|
821
|
+
return False
|
|
781
822
|
|
|
782
823
|
def list_external_services(self) -> None:
|
|
783
824
|
"""List all available external MCP services and their status."""
|
|
@@ -794,10 +835,10 @@ class MCPExternalServicesSetup:
|
|
|
794
835
|
with open(mcp_config_path) as f:
|
|
795
836
|
mcp_config = json.load(f)
|
|
796
837
|
print(f"\nš Project MCP config: {mcp_config_path}")
|
|
797
|
-
except:
|
|
798
|
-
print(
|
|
838
|
+
except Exception:
|
|
839
|
+
print("\nā ļø Could not read project .mcp.json")
|
|
799
840
|
else:
|
|
800
|
-
print(
|
|
841
|
+
print("\nš No .mcp.json found in project directory")
|
|
801
842
|
|
|
802
843
|
# Get service configurations for this project
|
|
803
844
|
services = self.get_project_services(project_path)
|
|
@@ -809,21 +850,21 @@ class MCPExternalServicesSetup:
|
|
|
809
850
|
|
|
810
851
|
# Check if configured in .mcp.json
|
|
811
852
|
if mcp_config.get("mcpServers", {}).get(service_name):
|
|
812
|
-
print(
|
|
853
|
+
print(" Project Status: ā
Configured in .mcp.json")
|
|
813
854
|
service_config = mcp_config["mcpServers"][service_name]
|
|
814
855
|
print(f" Command: {service_config.get('command')}")
|
|
815
|
-
if service_config.get(
|
|
856
|
+
if service_config.get("args"):
|
|
816
857
|
print(f" Args: {service_config.get('args')}")
|
|
817
858
|
else:
|
|
818
|
-
print(
|
|
859
|
+
print(" Project Status: ā Not configured in .mcp.json")
|
|
819
860
|
|
|
820
861
|
# Check installation type
|
|
821
862
|
is_installed, install_type = self._check_pipx_installation(service_name)
|
|
822
863
|
if is_installed:
|
|
823
864
|
if install_type == "pipx":
|
|
824
|
-
print(
|
|
865
|
+
print(" Installation: ā
Installed via pipx (recommended)")
|
|
825
866
|
else:
|
|
826
|
-
print(
|
|
867
|
+
print(" Installation: ā
Installed via pip")
|
|
827
868
|
else:
|
|
828
|
-
print(
|
|
829
|
-
print(f" Install with: pipx install {service_info['package_name']}")
|
|
869
|
+
print(" Installation: ā Not installed")
|
|
870
|
+
print(f" Install with: pipx install {service_info['package_name']}")
|
|
@@ -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
|
@@ -569,6 +569,41 @@ class RunCommand(BaseCommand):
|
|
|
569
569
|
return False
|
|
570
570
|
|
|
571
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
|
+
|
|
572
607
|
def _handle_reload_agents(logger):
|
|
573
608
|
"""
|
|
574
609
|
Handle the --reload-agents flag by deleting all local claude-mpm system agents.
|
|
@@ -583,8 +618,10 @@ def _handle_reload_agents(logger):
|
|
|
583
618
|
logger.info("Reloading system agents - cleaning existing deployments...")
|
|
584
619
|
|
|
585
620
|
# Import the cleanup service
|
|
621
|
+
from ...services.agents.deployment.agent_deployment import (
|
|
622
|
+
AgentDeploymentService,
|
|
623
|
+
)
|
|
586
624
|
from ...services.cli.agent_cleanup_service import AgentCleanupService
|
|
587
|
-
from ...services.agents.deployment.agent_deployment import AgentDeploymentService
|
|
588
625
|
|
|
589
626
|
# Create services
|
|
590
627
|
deployment_service = AgentDeploymentService()
|
|
@@ -599,7 +636,11 @@ def _handle_reload_agents(logger):
|
|
|
599
636
|
# Check if cleanup was successful based on the result structure
|
|
600
637
|
# The service returns a dict with 'removed', 'preserved', and possibly 'errors' keys
|
|
601
638
|
# If it has 'success' key, use it; otherwise infer from the result
|
|
602
|
-
success =
|
|
639
|
+
success = (
|
|
640
|
+
result.get("success", True)
|
|
641
|
+
if "success" in result
|
|
642
|
+
else not result.get("errors")
|
|
643
|
+
)
|
|
603
644
|
|
|
604
645
|
if success:
|
|
605
646
|
removed_count = result.get("cleaned_count", len(result.get("removed", [])))
|
|
@@ -694,6 +735,17 @@ def run_session_legacy(args):
|
|
|
694
735
|
if getattr(args, "reload_agents", False):
|
|
695
736
|
_handle_reload_agents(logger)
|
|
696
737
|
|
|
738
|
+
# Auto-configure MCP services on startup
|
|
739
|
+
_ensure_mcp_services_configured(logger)
|
|
740
|
+
|
|
741
|
+
# Trigger vector search indexing after MCP is configured
|
|
742
|
+
try:
|
|
743
|
+
from ...cli.startup_logging import start_vector_search_indexing
|
|
744
|
+
|
|
745
|
+
start_vector_search_indexing()
|
|
746
|
+
except Exception as e:
|
|
747
|
+
logger.debug(f"Failed to start vector search indexing: {e}")
|
|
748
|
+
|
|
697
749
|
try:
|
|
698
750
|
from ...core.claude_runner import ClaudeRunner, create_simple_context
|
|
699
751
|
except ImportError:
|