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
|
@@ -10,14 +10,12 @@ Note: As of the latest architecture, external services are registered as separat
|
|
|
10
10
|
MCP servers in Claude Desktop configuration, not as tools within the gateway.
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
|
-
import asyncio
|
|
14
13
|
import json
|
|
15
14
|
import subprocess
|
|
16
15
|
import sys
|
|
17
16
|
from pathlib import Path
|
|
18
|
-
from typing import Any, Dict, List
|
|
17
|
+
from typing import Any, Dict, List
|
|
19
18
|
|
|
20
|
-
from claude_mpm.services.mcp_gateway.core.base import BaseMCPService
|
|
21
19
|
from claude_mpm.services.mcp_gateway.tools.base_adapter import BaseMCPToolAdapter
|
|
22
20
|
|
|
23
21
|
|
|
@@ -45,7 +43,9 @@ class ExternalMCPService(BaseMCPToolAdapter):
|
|
|
45
43
|
self._is_installed = await self._check_installation()
|
|
46
44
|
|
|
47
45
|
if not self._is_installed:
|
|
48
|
-
self.logger.warning(
|
|
46
|
+
self.logger.warning(
|
|
47
|
+
f"{self.package_name} not installed, attempting installation..."
|
|
48
|
+
)
|
|
49
49
|
await self._install_package()
|
|
50
50
|
self._is_installed = await self._check_installation()
|
|
51
51
|
|
|
@@ -67,10 +67,15 @@ class ExternalMCPService(BaseMCPToolAdapter):
|
|
|
67
67
|
[sys.executable, "-m", self.package_name.replace("-", "_"), "--help"],
|
|
68
68
|
capture_output=True,
|
|
69
69
|
text=True,
|
|
70
|
-
timeout=5
|
|
70
|
+
timeout=5,
|
|
71
|
+
check=False,
|
|
71
72
|
)
|
|
72
73
|
return result.returncode == 0
|
|
73
|
-
except (
|
|
74
|
+
except (
|
|
75
|
+
subprocess.TimeoutExpired,
|
|
76
|
+
FileNotFoundError,
|
|
77
|
+
subprocess.CalledProcessError,
|
|
78
|
+
):
|
|
74
79
|
return False
|
|
75
80
|
|
|
76
81
|
async def _install_package(self) -> bool:
|
|
@@ -81,15 +86,15 @@ class ExternalMCPService(BaseMCPToolAdapter):
|
|
|
81
86
|
[sys.executable, "-m", "pip", "install", self.package_name],
|
|
82
87
|
capture_output=True,
|
|
83
88
|
text=True,
|
|
84
|
-
timeout=30
|
|
89
|
+
timeout=30,
|
|
90
|
+
check=False,
|
|
85
91
|
)
|
|
86
92
|
|
|
87
93
|
if result.returncode == 0:
|
|
88
94
|
self.logger.info(f"Successfully installed {self.package_name}")
|
|
89
95
|
return True
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return False
|
|
96
|
+
self.logger.error(f"Failed to install {self.package_name}: {result.stderr}")
|
|
97
|
+
return False
|
|
93
98
|
|
|
94
99
|
except Exception as e:
|
|
95
100
|
self.logger.error(f"Error installing {self.package_name}: {e}")
|
|
@@ -102,7 +107,7 @@ class ExternalMCPService(BaseMCPToolAdapter):
|
|
|
102
107
|
"description": f"External MCP service: {self.package_name}",
|
|
103
108
|
"type": "external_service",
|
|
104
109
|
"package": self.package_name,
|
|
105
|
-
"installed": self._is_installed
|
|
110
|
+
"installed": self._is_installed,
|
|
106
111
|
}
|
|
107
112
|
|
|
108
113
|
|
|
@@ -116,77 +121,103 @@ class MCPVectorSearchService(ExternalMCPService):
|
|
|
116
121
|
def get_definition(self) -> Dict[str, Any]:
|
|
117
122
|
"""Get tool definition for MCP registration."""
|
|
118
123
|
base_def = super().get_definition()
|
|
119
|
-
base_def.update(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
"
|
|
127
|
-
|
|
128
|
-
"
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
124
|
+
base_def.update(
|
|
125
|
+
{
|
|
126
|
+
"description": "Semantic code search powered by vector embeddings",
|
|
127
|
+
"tools": [
|
|
128
|
+
{
|
|
129
|
+
"name": "mcp__mcp-vector-search__search_code",
|
|
130
|
+
"description": "Search for code using semantic similarity",
|
|
131
|
+
"inputSchema": {
|
|
132
|
+
"type": "object",
|
|
133
|
+
"properties": {
|
|
134
|
+
"query": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"description": "The search query",
|
|
137
|
+
},
|
|
138
|
+
"limit": {"type": "integer", "default": 10},
|
|
139
|
+
"similarity_threshold": {
|
|
140
|
+
"type": "number",
|
|
141
|
+
"default": 0.3,
|
|
142
|
+
},
|
|
143
|
+
"language": {"type": "string"},
|
|
144
|
+
"file_extensions": {
|
|
145
|
+
"type": "array",
|
|
146
|
+
"items": {"type": "string"},
|
|
147
|
+
},
|
|
148
|
+
"files": {"type": "string"},
|
|
149
|
+
"class_name": {"type": "string"},
|
|
150
|
+
"function_name": {"type": "string"},
|
|
151
|
+
},
|
|
152
|
+
"required": ["query"],
|
|
136
153
|
},
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"name": "mcp__mcp-vector-search__search_similar",
|
|
157
|
+
"description": "Find code similar to a specific file or function",
|
|
158
|
+
"inputSchema": {
|
|
159
|
+
"type": "object",
|
|
160
|
+
"properties": {
|
|
161
|
+
"file_path": {
|
|
162
|
+
"type": "string",
|
|
163
|
+
"description": "Path to the file",
|
|
164
|
+
},
|
|
165
|
+
"function_name": {"type": "string"},
|
|
166
|
+
"limit": {"type": "integer", "default": 10},
|
|
167
|
+
"similarity_threshold": {
|
|
168
|
+
"type": "number",
|
|
169
|
+
"default": 0.3,
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
"required": ["file_path"],
|
|
150
173
|
},
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"name": "mcp__mcp-vector-search__search_context",
|
|
177
|
+
"description": "Search for code based on contextual description",
|
|
178
|
+
"inputSchema": {
|
|
179
|
+
"type": "object",
|
|
180
|
+
"properties": {
|
|
181
|
+
"description": {
|
|
182
|
+
"type": "string",
|
|
183
|
+
"description": "Contextual description",
|
|
184
|
+
},
|
|
185
|
+
"focus_areas": {
|
|
186
|
+
"type": "array",
|
|
187
|
+
"items": {"type": "string"},
|
|
188
|
+
},
|
|
189
|
+
"limit": {"type": "integer", "default": 10},
|
|
190
|
+
},
|
|
191
|
+
"required": ["description"],
|
|
163
192
|
},
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
"properties": {},
|
|
173
|
-
"required": []
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
"name": "mcp__mcp-vector-search__index_project",
|
|
178
|
-
"description": "Index or reindex the project codebase",
|
|
179
|
-
"inputSchema": {
|
|
180
|
-
"type": "object",
|
|
181
|
-
"properties": {
|
|
182
|
-
"force": {"type": "boolean", "default": False},
|
|
183
|
-
"file_extensions": {"type": "array", "items": {"type": "string"}}
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"name": "mcp__mcp-vector-search__get_project_status",
|
|
196
|
+
"description": "Get project indexing status and statistics",
|
|
197
|
+
"inputSchema": {
|
|
198
|
+
"type": "object",
|
|
199
|
+
"properties": {},
|
|
200
|
+
"required": [],
|
|
184
201
|
},
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"name": "mcp__mcp-vector-search__index_project",
|
|
205
|
+
"description": "Index or reindex the project codebase",
|
|
206
|
+
"inputSchema": {
|
|
207
|
+
"type": "object",
|
|
208
|
+
"properties": {
|
|
209
|
+
"force": {"type": "boolean", "default": False},
|
|
210
|
+
"file_extensions": {
|
|
211
|
+
"type": "array",
|
|
212
|
+
"items": {"type": "string"},
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
"required": [],
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
}
|
|
220
|
+
)
|
|
190
221
|
return base_def
|
|
191
222
|
|
|
192
223
|
async def invoke(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -197,9 +228,13 @@ class MCPVectorSearchService(ExternalMCPService):
|
|
|
197
228
|
|
|
198
229
|
# Prepare the command
|
|
199
230
|
cmd = [
|
|
200
|
-
sys.executable,
|
|
201
|
-
"
|
|
202
|
-
"
|
|
231
|
+
sys.executable,
|
|
232
|
+
"-m",
|
|
233
|
+
"mcp_vector_search",
|
|
234
|
+
"--tool",
|
|
235
|
+
actual_tool,
|
|
236
|
+
"--args",
|
|
237
|
+
json.dumps(arguments),
|
|
203
238
|
]
|
|
204
239
|
|
|
205
240
|
# Run the command
|
|
@@ -208,7 +243,8 @@ class MCPVectorSearchService(ExternalMCPService):
|
|
|
208
243
|
capture_output=True,
|
|
209
244
|
text=True,
|
|
210
245
|
timeout=30,
|
|
211
|
-
cwd=Path.cwd()
|
|
246
|
+
cwd=Path.cwd(),
|
|
247
|
+
check=False, # Use current working directory for project context
|
|
212
248
|
)
|
|
213
249
|
|
|
214
250
|
if result.returncode == 0:
|
|
@@ -235,47 +271,61 @@ class MCPBrowserService(ExternalMCPService):
|
|
|
235
271
|
def get_definition(self) -> Dict[str, Any]:
|
|
236
272
|
"""Get tool definition for MCP registration."""
|
|
237
273
|
base_def = super().get_definition()
|
|
238
|
-
base_def.update(
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
"
|
|
246
|
-
|
|
247
|
-
"
|
|
248
|
-
|
|
274
|
+
base_def.update(
|
|
275
|
+
{
|
|
276
|
+
"description": "Web browsing and content extraction capabilities",
|
|
277
|
+
"tools": [
|
|
278
|
+
{
|
|
279
|
+
"name": "mcp__mcp-browser__browse",
|
|
280
|
+
"description": "Browse a webpage and extract content",
|
|
281
|
+
"inputSchema": {
|
|
282
|
+
"type": "object",
|
|
283
|
+
"properties": {
|
|
284
|
+
"url": {
|
|
285
|
+
"type": "string",
|
|
286
|
+
"description": "URL to browse",
|
|
287
|
+
},
|
|
288
|
+
"extract": {
|
|
289
|
+
"type": "string",
|
|
290
|
+
"description": "What to extract",
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
"required": ["url"],
|
|
249
294
|
},
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
"name": "mcp__mcp-browser__search",
|
|
298
|
+
"description": "Search the web",
|
|
299
|
+
"inputSchema": {
|
|
300
|
+
"type": "object",
|
|
301
|
+
"properties": {
|
|
302
|
+
"query": {
|
|
303
|
+
"type": "string",
|
|
304
|
+
"description": "Search query",
|
|
305
|
+
},
|
|
306
|
+
"num_results": {"type": "integer", "default": 10},
|
|
307
|
+
},
|
|
308
|
+
"required": ["query"],
|
|
261
309
|
},
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"name": "mcp__mcp-browser__screenshot",
|
|
313
|
+
"description": "Take a screenshot of a webpage",
|
|
314
|
+
"inputSchema": {
|
|
315
|
+
"type": "object",
|
|
316
|
+
"properties": {
|
|
317
|
+
"url": {
|
|
318
|
+
"type": "string",
|
|
319
|
+
"description": "URL to screenshot",
|
|
320
|
+
},
|
|
321
|
+
"full_page": {"type": "boolean", "default": False},
|
|
322
|
+
},
|
|
323
|
+
"required": ["url"],
|
|
273
324
|
},
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
})
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
}
|
|
328
|
+
)
|
|
279
329
|
return base_def
|
|
280
330
|
|
|
281
331
|
async def invoke(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -286,17 +336,18 @@ class MCPBrowserService(ExternalMCPService):
|
|
|
286
336
|
|
|
287
337
|
# Prepare the command
|
|
288
338
|
cmd = [
|
|
289
|
-
sys.executable,
|
|
290
|
-
"
|
|
291
|
-
"
|
|
339
|
+
sys.executable,
|
|
340
|
+
"-m",
|
|
341
|
+
"mcp_browser",
|
|
342
|
+
"--tool",
|
|
343
|
+
actual_tool,
|
|
344
|
+
"--args",
|
|
345
|
+
json.dumps(arguments),
|
|
292
346
|
]
|
|
293
347
|
|
|
294
348
|
# Run the command
|
|
295
349
|
result = subprocess.run(
|
|
296
|
-
cmd,
|
|
297
|
-
capture_output=True,
|
|
298
|
-
text=True,
|
|
299
|
-
timeout=30
|
|
350
|
+
cmd, capture_output=True, text=True, timeout=30, check=False
|
|
300
351
|
)
|
|
301
352
|
|
|
302
353
|
if result.returncode == 0:
|
|
@@ -338,10 +389,7 @@ class ExternalMCPServiceManager:
|
|
|
338
389
|
them as tools in the gateway - they run as separate MCP servers.
|
|
339
390
|
"""
|
|
340
391
|
# Create service instances
|
|
341
|
-
services = [
|
|
342
|
-
MCPVectorSearchService(),
|
|
343
|
-
MCPBrowserService()
|
|
344
|
-
]
|
|
392
|
+
services = [MCPVectorSearchService(), MCPBrowserService()]
|
|
345
393
|
|
|
346
394
|
# Initialize each service
|
|
347
395
|
initialized_services = []
|
|
@@ -350,10 +398,11 @@ class ExternalMCPServiceManager:
|
|
|
350
398
|
if await service.initialize():
|
|
351
399
|
initialized_services.append(service)
|
|
352
400
|
if self.logger:
|
|
353
|
-
self.logger.info(
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
401
|
+
self.logger.info(
|
|
402
|
+
f"Initialized external service: {service.service_name}"
|
|
403
|
+
)
|
|
404
|
+
elif self.logger:
|
|
405
|
+
self.logger.warning(f"Failed to initialize: {service.service_name}")
|
|
357
406
|
except Exception as e:
|
|
358
407
|
if self.logger:
|
|
359
408
|
self.logger.error(f"Error initializing {service.service_name}: {e}")
|
|
@@ -370,7 +419,9 @@ class ExternalMCPServiceManager:
|
|
|
370
419
|
all_tools.extend(service_def["tools"])
|
|
371
420
|
return all_tools
|
|
372
421
|
|
|
373
|
-
async def invoke_tool(
|
|
422
|
+
async def invoke_tool(
|
|
423
|
+
self, tool_name: str, arguments: Dict[str, Any]
|
|
424
|
+
) -> Dict[str, Any]:
|
|
374
425
|
"""Invoke a tool from any registered external service."""
|
|
375
426
|
# Find the service that handles this tool
|
|
376
427
|
for service in self.services:
|
|
@@ -387,4 +438,6 @@ class ExternalMCPServiceManager:
|
|
|
387
438
|
await service.shutdown()
|
|
388
439
|
except Exception as e:
|
|
389
440
|
if self.logger:
|
|
390
|
-
self.logger.warning(
|
|
441
|
+
self.logger.warning(
|
|
442
|
+
f"Error shutting down {service.service_name}: {e}"
|
|
443
|
+
)
|
|
@@ -20,7 +20,7 @@ import asyncio
|
|
|
20
20
|
import os
|
|
21
21
|
import platform
|
|
22
22
|
import sys
|
|
23
|
-
from datetime import datetime
|
|
23
|
+
from datetime import datetime, timezone
|
|
24
24
|
from typing import Any, Dict
|
|
25
25
|
|
|
26
26
|
import psutil
|
|
@@ -86,7 +86,7 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
86
86
|
Returns:
|
|
87
87
|
Tool execution result with health check results
|
|
88
88
|
"""
|
|
89
|
-
start_time = datetime.now()
|
|
89
|
+
start_time = datetime.now(timezone.utc)
|
|
90
90
|
|
|
91
91
|
try:
|
|
92
92
|
# Get parameters
|
|
@@ -98,7 +98,7 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
98
98
|
results = await self._perform_health_checks(check_type, detailed, timeout)
|
|
99
99
|
|
|
100
100
|
# Calculate execution time
|
|
101
|
-
execution_time = (datetime.now() - start_time).total_seconds()
|
|
101
|
+
execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
|
|
102
102
|
|
|
103
103
|
# Update metrics
|
|
104
104
|
self._update_metrics(True, execution_time)
|
|
@@ -115,7 +115,7 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
115
115
|
)
|
|
116
116
|
|
|
117
117
|
except Exception as e:
|
|
118
|
-
execution_time = (datetime.now() - start_time).total_seconds()
|
|
118
|
+
execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
|
|
119
119
|
self._update_metrics(False, execution_time)
|
|
120
120
|
|
|
121
121
|
return MCPToolResult(
|
|
@@ -130,7 +130,7 @@ class HealthCheckTool(BaseToolAdapter):
|
|
|
130
130
|
) -> Dict[str, Any]:
|
|
131
131
|
"""Perform the requested health checks."""
|
|
132
132
|
results = {
|
|
133
|
-
"timestamp": datetime.now().isoformat(),
|
|
133
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
134
134
|
"check_type": check_type,
|
|
135
135
|
"detailed": detailed,
|
|
136
136
|
"overall_status": "unknown",
|
|
@@ -27,7 +27,7 @@ import json
|
|
|
27
27
|
import platform
|
|
28
28
|
import re
|
|
29
29
|
import sys
|
|
30
|
-
from datetime import datetime
|
|
30
|
+
from datetime import datetime, timezone
|
|
31
31
|
from typing import Any, Dict, List, Optional
|
|
32
32
|
|
|
33
33
|
from claude_mpm.services.mcp_gateway.core.interfaces import (
|
|
@@ -204,7 +204,7 @@ class HelloWorldTool(BaseToolAdapter):
|
|
|
204
204
|
self.greeting_history: List[Dict[str, Any]] = []
|
|
205
205
|
self.max_history_size = 100
|
|
206
206
|
|
|
207
|
-
def validate_parameters(self, parameters: Dict[str, Any]) -> bool:
|
|
207
|
+
def validate_parameters(self, parameters: Dict[str, Any]) -> bool: # noqa: PLR0911
|
|
208
208
|
"""
|
|
209
209
|
Enhanced parameter validation with detailed error messages.
|
|
210
210
|
|
|
@@ -305,7 +305,7 @@ class HelloWorldTool(BaseToolAdapter):
|
|
|
305
305
|
Returns:
|
|
306
306
|
Tool execution result with greeting
|
|
307
307
|
"""
|
|
308
|
-
start_time = datetime.now()
|
|
308
|
+
start_time = datetime.now(timezone.utc)
|
|
309
309
|
|
|
310
310
|
try:
|
|
311
311
|
# Validate parameters
|
|
@@ -353,13 +353,13 @@ class HelloWorldTool(BaseToolAdapter):
|
|
|
353
353
|
greeting = " ".join([greeting] * repeat)
|
|
354
354
|
|
|
355
355
|
# Calculate execution time
|
|
356
|
-
execution_time = (datetime.now() - start_time).total_seconds()
|
|
356
|
+
execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
|
|
357
357
|
|
|
358
358
|
# Build response data
|
|
359
359
|
response_data = {
|
|
360
360
|
"greeting": greeting,
|
|
361
361
|
"mode": mode,
|
|
362
|
-
"timestamp": datetime.now().isoformat(),
|
|
362
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
# Add metadata if requested
|
|
@@ -389,7 +389,7 @@ class HelloWorldTool(BaseToolAdapter):
|
|
|
389
389
|
)
|
|
390
390
|
|
|
391
391
|
except Exception as e:
|
|
392
|
-
execution_time = (datetime.now() - start_time).total_seconds()
|
|
392
|
+
execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
|
|
393
393
|
self._update_metrics(False, execution_time)
|
|
394
394
|
self._metrics["last_error"] = str(e)
|
|
395
395
|
|
|
@@ -409,11 +409,11 @@ class HelloWorldTool(BaseToolAdapter):
|
|
|
409
409
|
|
|
410
410
|
async def _time_based_greeting(self) -> str:
|
|
411
411
|
"""Generate a greeting based on current time."""
|
|
412
|
-
current_hour = datetime.now().hour
|
|
412
|
+
current_hour = datetime.now(timezone.utc).hour
|
|
413
413
|
|
|
414
414
|
for (start, end), greeting in self.TIME_GREETINGS.items():
|
|
415
415
|
if start <= current_hour < end:
|
|
416
|
-
return f"{greeting}! It's {datetime.now().strftime('%I:%M %p')}."
|
|
416
|
+
return f"{greeting}! It's {datetime.now(timezone.utc).strftime('%I:%M %p')}."
|
|
417
417
|
|
|
418
418
|
return "Hello! Time is a curious thing."
|
|
419
419
|
|
|
@@ -482,7 +482,7 @@ class HelloWorldTool(BaseToolAdapter):
|
|
|
482
482
|
execution_time: Time taken to generate greeting
|
|
483
483
|
"""
|
|
484
484
|
entry = {
|
|
485
|
-
"timestamp": datetime.now().isoformat(),
|
|
485
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
486
486
|
"mode": mode,
|
|
487
487
|
"greeting": greeting[:100], # Truncate long greetings
|
|
488
488
|
"execution_time": execution_time,
|