claude-mpm 5.1.9__py3-none-any.whl → 5.4.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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +4 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +85 -0
- claude_mpm/agents/agent_loader.py +13 -44
- claude_mpm/agents/templates/circuit-breakers.md +138 -1
- claude_mpm/cli/__main__.py +4 -0
- claude_mpm/cli/commands/agent_state_manager.py +8 -17
- claude_mpm/cli/commands/auto_configure.py +210 -25
- claude_mpm/cli/commands/config.py +88 -2
- claude_mpm/cli/commands/configure.py +1097 -158
- claude_mpm/cli/commands/configure_agent_display.py +15 -6
- claude_mpm/cli/commands/mpm_init/core.py +160 -46
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
- claude_mpm/cli/commands/skills.py +21 -2
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/executor.py +11 -3
- claude_mpm/cli/parsers/base_parser.py +5 -0
- claude_mpm/cli/parsers/config_parser.py +153 -83
- claude_mpm/cli/parsers/skills_parser.py +3 -2
- claude_mpm/cli/startup.py +333 -89
- claude_mpm/commands/mpm-config.md +266 -0
- claude_mpm/commands/{mpm-ticket-organize.md → mpm-organize.md} +4 -5
- claude_mpm/config/agent_sources.py +27 -0
- claude_mpm/core/framework/formatters/content_formatter.py +3 -13
- claude_mpm/core/framework/loaders/agent_loader.py +8 -5
- claude_mpm/core/framework_loader.py +4 -2
- claude_mpm/core/logger.py +13 -0
- claude_mpm/core/socketio_pool.py +3 -3
- claude_mpm/core/unified_agent_registry.py +5 -15
- claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +206 -78
- claude_mpm/hooks/claude_hooks/hook_handler.py +6 -0
- claude_mpm/hooks/claude_hooks/installer.py +33 -10
- claude_mpm/hooks/claude_hooks/memory_integration.py +26 -9
- claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +4 -0
- claude_mpm/hooks/memory_integration_hook.py +46 -1
- claude_mpm/init.py +0 -19
- claude_mpm/scripts/claude-hook-handler.sh +58 -18
- claude_mpm/scripts/launch_monitor.py +93 -13
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/deployment/agent_discovery_service.py +2 -3
- claude_mpm/services/agents/deployment/agent_template_builder.py +4 -2
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +78 -9
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +335 -53
- claude_mpm/services/agents/git_source_manager.py +34 -0
- claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
- claude_mpm/services/agents/sources/git_source_sync_service.py +8 -1
- claude_mpm/services/agents/toolchain_detector.py +10 -6
- claude_mpm/services/analysis/__init__.py +11 -1
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/command_deployment_service.py +71 -10
- claude_mpm/services/event_bus/config.py +3 -1
- claude_mpm/services/git/git_operations_service.py +93 -8
- claude_mpm/services/monitor/daemon.py +9 -2
- claude_mpm/services/monitor/daemon_manager.py +39 -3
- claude_mpm/services/monitor/server.py +225 -19
- claude_mpm/services/self_upgrade_service.py +120 -12
- claude_mpm/services/skills/__init__.py +3 -0
- claude_mpm/services/skills/git_skill_source_manager.py +32 -2
- claude_mpm/services/skills/selective_skill_deployer.py +230 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_deployer.py +64 -3
- claude_mpm/services/socketio/event_normalizer.py +15 -1
- claude_mpm/services/socketio/server/core.py +160 -21
- claude_mpm/services/version_control/git_operations.py +103 -0
- claude_mpm/utils/agent_filters.py +17 -44
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/METADATA +47 -84
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/RECORD +76 -150
- claude_mpm-5.4.14.dist-info/entry_points.txt +5 -0
- claude_mpm-5.4.14.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.14.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
- claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
- claude_mpm/agents/BASE_ENGINEER.md +0 -658
- claude_mpm/agents/BASE_OPS.md +0 -219
- claude_mpm/agents/BASE_PM.md +0 -480
- claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
- claude_mpm/agents/BASE_QA.md +0 -167
- claude_mpm/agents/BASE_RESEARCH.md +0 -53
- claude_mpm/agents/base_agent.json +0 -31
- claude_mpm/agents/base_agent_loader.py +0 -601
- claude_mpm/cli/ticket_cli.py +0 -35
- claude_mpm/commands/mpm-config-view.md +0 -150
- claude_mpm/dashboard/analysis_runner.py +0 -455
- claude_mpm/dashboard/index.html +0 -13
- claude_mpm/dashboard/open_dashboard.py +0 -66
- claude_mpm/dashboard/static/css/activity.css +0 -1958
- claude_mpm/dashboard/static/css/connection-status.css +0 -370
- claude_mpm/dashboard/static/css/dashboard.css +0 -4701
- claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
- claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
- claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
- claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
- claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
- claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
- claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
- claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
- claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
- claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
- claude_mpm/dashboard/static/js/connection-manager.js +0 -536
- claude_mpm/dashboard/static/js/dashboard.js +0 -1914
- claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/js/socket-client.js +0 -1474
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/socket.io.min.js +0 -7
- claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
- claude_mpm/dashboard/templates/code_simple.html +0 -153
- claude_mpm/dashboard/templates/index.html +0 -606
- claude_mpm/dashboard/test_dashboard.html +0 -372
- claude_mpm/scripts/mcp_server.py +0 -75
- claude_mpm/scripts/mcp_wrapper.py +0 -39
- claude_mpm/services/mcp_gateway/__init__.py +0 -159
- claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
- claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
- claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
- claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
- claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
- claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
- claude_mpm/services/mcp_gateway/core/base.py +0 -312
- claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
- claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
- claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
- claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
- claude_mpm/services/mcp_gateway/main.py +0 -589
- claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
- claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
- claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
- claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
- claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
- claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
- claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
- claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
- claude_mpm-5.1.9.dist-info/entry_points.txt +0 -10
- claude_mpm-5.1.9.dist-info/licenses/LICENSE +0 -21
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/WHEEL +0 -0
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/top_level.txt +0 -0
|
@@ -1,589 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
|
|
3
|
-
"""
|
|
4
|
-
MCP Gateway Main Entry Point
|
|
5
|
-
=============================
|
|
6
|
-
|
|
7
|
-
Main entry point for running the MCP Gateway server.
|
|
8
|
-
Orchestrates server initialization, tool registration, and lifecycle management.
|
|
9
|
-
|
|
10
|
-
Part of ISS-0035: MCP Server Implementation - Core Server and Tool Registry
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
import argparse
|
|
14
|
-
import asyncio
|
|
15
|
-
import logging
|
|
16
|
-
import signal
|
|
17
|
-
import sys
|
|
18
|
-
from typing import Optional
|
|
19
|
-
|
|
20
|
-
# Import with fallback handling for missing dependencies
|
|
21
|
-
try:
|
|
22
|
-
from claude_mpm.core.logger import get_logger
|
|
23
|
-
except ImportError:
|
|
24
|
-
import logging
|
|
25
|
-
|
|
26
|
-
def get_logger(name):
|
|
27
|
-
return logging.getLogger(name)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
try:
|
|
31
|
-
from claude_mpm.services.mcp_gateway.config.configuration import MCPConfiguration
|
|
32
|
-
except ImportError:
|
|
33
|
-
# Fallback configuration class
|
|
34
|
-
class MCPConfiguration:
|
|
35
|
-
def __init__(self):
|
|
36
|
-
self.config = {}
|
|
37
|
-
|
|
38
|
-
def load_config(self, path):
|
|
39
|
-
return True
|
|
40
|
-
|
|
41
|
-
def get(self, key, default=None):
|
|
42
|
-
return default
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
try:
|
|
46
|
-
from claude_mpm.services.mcp_gateway.registry.tool_registry import ToolRegistry
|
|
47
|
-
except ImportError:
|
|
48
|
-
# Minimal fallback registry
|
|
49
|
-
class ToolRegistry:
|
|
50
|
-
def __init__(self):
|
|
51
|
-
self.tools = []
|
|
52
|
-
|
|
53
|
-
async def initialize(self):
|
|
54
|
-
return True
|
|
55
|
-
|
|
56
|
-
def register_tool(self, tool, category="builtin"):
|
|
57
|
-
return True
|
|
58
|
-
|
|
59
|
-
async def shutdown(self):
|
|
60
|
-
pass
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
try:
|
|
64
|
-
from claude_mpm.services.mcp_gateway.server.mcp_gateway import MCPGateway
|
|
65
|
-
except ImportError as e:
|
|
66
|
-
raise ImportError(f"Critical: Cannot import MCPGateway server: {e}") from e
|
|
67
|
-
|
|
68
|
-
try:
|
|
69
|
-
from claude_mpm.services.mcp_gateway.server.stdio_handler import StdioHandler
|
|
70
|
-
except ImportError:
|
|
71
|
-
# Fallback stdio handler
|
|
72
|
-
class StdioHandler:
|
|
73
|
-
async def initialize(self):
|
|
74
|
-
return True
|
|
75
|
-
|
|
76
|
-
async def shutdown(self):
|
|
77
|
-
pass
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
# Import tools with individual fallbacks
|
|
81
|
-
try:
|
|
82
|
-
from claude_mpm.services.mcp_gateway.tools.base_adapter import (
|
|
83
|
-
CalculatorToolAdapter,
|
|
84
|
-
EchoToolAdapter,
|
|
85
|
-
SystemInfoToolAdapter,
|
|
86
|
-
)
|
|
87
|
-
except ImportError:
|
|
88
|
-
# Create dummy tool adapters
|
|
89
|
-
class BaseToolAdapter:
|
|
90
|
-
def __init__(self):
|
|
91
|
-
pass
|
|
92
|
-
|
|
93
|
-
async def initialize(self):
|
|
94
|
-
return True
|
|
95
|
-
|
|
96
|
-
def get_definition(self):
|
|
97
|
-
return type("ToolDef", (), {"name": "unknown"})
|
|
98
|
-
|
|
99
|
-
CalculatorToolAdapter = BaseToolAdapter
|
|
100
|
-
EchoToolAdapter = BaseToolAdapter
|
|
101
|
-
SystemInfoToolAdapter = BaseToolAdapter
|
|
102
|
-
|
|
103
|
-
try:
|
|
104
|
-
from claude_mpm.services.mcp_gateway.tools.document_summarizer import (
|
|
105
|
-
DocumentSummarizerTool,
|
|
106
|
-
)
|
|
107
|
-
except ImportError:
|
|
108
|
-
DocumentSummarizerTool = None
|
|
109
|
-
|
|
110
|
-
# Ticket tools removed - using mcp-ticketer instead
|
|
111
|
-
UnifiedTicketTool = None
|
|
112
|
-
|
|
113
|
-
try:
|
|
114
|
-
from claude_mpm.services.mcp_gateway.tools.external_mcp_services import (
|
|
115
|
-
ExternalMCPServiceManager,
|
|
116
|
-
)
|
|
117
|
-
except ImportError:
|
|
118
|
-
# External MCP services are optional
|
|
119
|
-
ExternalMCPServiceManager = None
|
|
120
|
-
|
|
121
|
-
# Manager module removed - using simplified architecture
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
class MCPGatewayOrchestrator:
|
|
125
|
-
"""
|
|
126
|
-
Main MCP Gateway orchestrator.
|
|
127
|
-
|
|
128
|
-
WHY: This class coordinates all MCP components, managing their lifecycle
|
|
129
|
-
and ensuring proper initialization, startup, and shutdown sequences.
|
|
130
|
-
|
|
131
|
-
DESIGN DECISIONS:
|
|
132
|
-
- Use dependency injection to wire components together
|
|
133
|
-
- Implement graceful shutdown on SIGINT/SIGTERM
|
|
134
|
-
- Support both configuration file and CLI arguments
|
|
135
|
-
- Provide comprehensive logging for debugging
|
|
136
|
-
- Renamed from MCPGateway to avoid naming conflict with server class
|
|
137
|
-
"""
|
|
138
|
-
|
|
139
|
-
def __init__(self, config_path: Optional[Path] = None):
|
|
140
|
-
"""
|
|
141
|
-
Initialize the MCP Gateway.
|
|
142
|
-
|
|
143
|
-
Args:
|
|
144
|
-
config_path: Optional path to configuration file
|
|
145
|
-
"""
|
|
146
|
-
self.logger = get_logger(self.__class__.__name__)
|
|
147
|
-
self.config_path = config_path
|
|
148
|
-
|
|
149
|
-
# Core components
|
|
150
|
-
self.server: Optional[MCPGateway] = None
|
|
151
|
-
self.registry: Optional[ToolRegistry] = None
|
|
152
|
-
self.communication: Optional[StdioHandler] = None
|
|
153
|
-
self.configuration: Optional[MCPConfiguration] = None
|
|
154
|
-
self.external_services: Optional[ExternalMCPServiceManager] = None
|
|
155
|
-
|
|
156
|
-
# Shutdown handling
|
|
157
|
-
self._shutdown_event = asyncio.Event()
|
|
158
|
-
self._setup_signal_handlers()
|
|
159
|
-
|
|
160
|
-
def _setup_signal_handlers(self) -> None:
|
|
161
|
-
"""Setup signal handlers for graceful shutdown."""
|
|
162
|
-
|
|
163
|
-
def signal_handler(sig, frame):
|
|
164
|
-
self.logger.info(f"Received signal {sig}, initiating shutdown...")
|
|
165
|
-
self._shutdown_event.set()
|
|
166
|
-
|
|
167
|
-
signal.signal(signal.SIGINT, signal_handler)
|
|
168
|
-
signal.signal(signal.SIGTERM, signal_handler)
|
|
169
|
-
|
|
170
|
-
async def initialize(self) -> bool:
|
|
171
|
-
"""
|
|
172
|
-
Initialize all MCP Gateway components.
|
|
173
|
-
|
|
174
|
-
Returns:
|
|
175
|
-
True if initialization successful
|
|
176
|
-
"""
|
|
177
|
-
try:
|
|
178
|
-
self.logger.info("Initializing MCP Gateway")
|
|
179
|
-
|
|
180
|
-
# Load configuration
|
|
181
|
-
self.configuration = MCPConfiguration()
|
|
182
|
-
if (
|
|
183
|
-
self.config_path
|
|
184
|
-
and self.config_path.exists()
|
|
185
|
-
and not self.configuration.load_config(self.config_path)
|
|
186
|
-
):
|
|
187
|
-
self.logger.error("Failed to load configuration")
|
|
188
|
-
return False
|
|
189
|
-
|
|
190
|
-
# Initialize tool registry with error handling
|
|
191
|
-
try:
|
|
192
|
-
self.registry = ToolRegistry()
|
|
193
|
-
if not await self.registry.initialize():
|
|
194
|
-
self.logger.error("Failed to initialize tool registry")
|
|
195
|
-
# Continue anyway - server can run without tools
|
|
196
|
-
self.registry = None
|
|
197
|
-
except Exception as e:
|
|
198
|
-
self.logger.warning(f"Tool registry initialization failed: {e}")
|
|
199
|
-
self.registry = None
|
|
200
|
-
|
|
201
|
-
# Register built-in tools if registry is available
|
|
202
|
-
if self.registry:
|
|
203
|
-
try:
|
|
204
|
-
await self._register_builtin_tools()
|
|
205
|
-
except Exception as e:
|
|
206
|
-
self.logger.warning(f"Failed to register some tools: {e}")
|
|
207
|
-
# Continue - server can run with partial tools
|
|
208
|
-
|
|
209
|
-
# Initialize external MCP services if available
|
|
210
|
-
if ExternalMCPServiceManager is not None:
|
|
211
|
-
try:
|
|
212
|
-
self.logger.info("Initializing external MCP services...")
|
|
213
|
-
self.external_services = ExternalMCPServiceManager()
|
|
214
|
-
external_services = (
|
|
215
|
-
await self.external_services.initialize_services()
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
if external_services and self.registry:
|
|
219
|
-
for service in external_services:
|
|
220
|
-
try:
|
|
221
|
-
if self.registry.register_tool(
|
|
222
|
-
service, category="external"
|
|
223
|
-
):
|
|
224
|
-
self.logger.info(
|
|
225
|
-
f"Registered external service: {service.service_name}"
|
|
226
|
-
)
|
|
227
|
-
else:
|
|
228
|
-
self.logger.warning(
|
|
229
|
-
f"Failed to register external service: {service.service_name}"
|
|
230
|
-
)
|
|
231
|
-
except Exception as e:
|
|
232
|
-
self.logger.warning(
|
|
233
|
-
f"Error registering {service.service_name}: {e}"
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
self.logger.info(
|
|
237
|
-
f"Initialized {len(external_services)} external MCP services"
|
|
238
|
-
)
|
|
239
|
-
except Exception as e:
|
|
240
|
-
self.logger.warning(
|
|
241
|
-
f"Failed to initialize external MCP services: {e}"
|
|
242
|
-
)
|
|
243
|
-
self.external_services = None
|
|
244
|
-
|
|
245
|
-
# Initialize communication handler with fallback
|
|
246
|
-
try:
|
|
247
|
-
self.communication = StdioHandler()
|
|
248
|
-
if not await self.communication.initialize():
|
|
249
|
-
self.logger.warning("Failed to initialize communication handler")
|
|
250
|
-
# Communication is optional for the server
|
|
251
|
-
self.communication = None
|
|
252
|
-
except Exception as e:
|
|
253
|
-
self.logger.warning(f"Communication handler initialization failed: {e}")
|
|
254
|
-
self.communication = None
|
|
255
|
-
|
|
256
|
-
# Initialize MCP gateway server
|
|
257
|
-
gateway_name = self.configuration.get("server.name", "claude-mpm-mcp")
|
|
258
|
-
version = self.configuration.get("server.version", "1.0.0")
|
|
259
|
-
self.server = MCPGateway(gateway_name=gateway_name, version=version)
|
|
260
|
-
|
|
261
|
-
# Wire dependencies (only if available)
|
|
262
|
-
if self.registry:
|
|
263
|
-
self.server.set_tool_registry(self.registry)
|
|
264
|
-
else:
|
|
265
|
-
self.logger.warning("Running without tool registry")
|
|
266
|
-
|
|
267
|
-
if self.communication:
|
|
268
|
-
self.server.set_communication(self.communication)
|
|
269
|
-
else:
|
|
270
|
-
self.logger.info("Running without custom communication handler")
|
|
271
|
-
|
|
272
|
-
if not await self.server.initialize():
|
|
273
|
-
self.logger.error("Failed to initialize MCP server")
|
|
274
|
-
return False
|
|
275
|
-
|
|
276
|
-
self.logger.info("MCP Gateway initialized successfully")
|
|
277
|
-
return True
|
|
278
|
-
|
|
279
|
-
except Exception as e:
|
|
280
|
-
self.logger.error(f"Failed to initialize MCP Gateway: {e}")
|
|
281
|
-
return False
|
|
282
|
-
|
|
283
|
-
async def _register_builtin_tools(self) -> None:
|
|
284
|
-
"""Register built-in tools with the registry."""
|
|
285
|
-
self.logger.info("Registering built-in tools")
|
|
286
|
-
|
|
287
|
-
# Create tool adapters (only include available tools)
|
|
288
|
-
tools = []
|
|
289
|
-
|
|
290
|
-
# Always include basic tools
|
|
291
|
-
try:
|
|
292
|
-
tools.extend(
|
|
293
|
-
[
|
|
294
|
-
EchoToolAdapter(),
|
|
295
|
-
CalculatorToolAdapter(),
|
|
296
|
-
SystemInfoToolAdapter(),
|
|
297
|
-
]
|
|
298
|
-
)
|
|
299
|
-
except Exception as e:
|
|
300
|
-
self.logger.warning(f"Could not load basic tools: {e}")
|
|
301
|
-
|
|
302
|
-
# Optional: Health check tool
|
|
303
|
-
try:
|
|
304
|
-
from .tools.health_check_tool import HealthCheckTool
|
|
305
|
-
|
|
306
|
-
tools.append(HealthCheckTool())
|
|
307
|
-
except Exception as e:
|
|
308
|
-
self.logger.warning(f"Could not load health check tool: {e}")
|
|
309
|
-
|
|
310
|
-
# Optional: Document summarizer
|
|
311
|
-
if DocumentSummarizerTool is not None:
|
|
312
|
-
try:
|
|
313
|
-
tools.append(DocumentSummarizerTool())
|
|
314
|
-
except Exception as e:
|
|
315
|
-
self.logger.warning(f"Could not load document summarizer: {e}")
|
|
316
|
-
|
|
317
|
-
# Kuzu-Memory Service (now a required dependency)
|
|
318
|
-
try:
|
|
319
|
-
from .tools.kuzu_memory_service import KuzuMemoryService
|
|
320
|
-
|
|
321
|
-
tools.append(KuzuMemoryService())
|
|
322
|
-
self.logger.info("KuzuMemoryService added to built-in tools")
|
|
323
|
-
except Exception as e:
|
|
324
|
-
self.logger.warning(f"Could not load KuzuMemoryService: {e}")
|
|
325
|
-
|
|
326
|
-
# MCP Vector Search Service (optional - will auto-install on first use)
|
|
327
|
-
try:
|
|
328
|
-
from .tools.external_mcp_services import MCPVectorSearchService
|
|
329
|
-
|
|
330
|
-
vector_search = MCPVectorSearchService()
|
|
331
|
-
# Try to initialize without interactive prompts during gateway startup
|
|
332
|
-
# This will only succeed if already installed
|
|
333
|
-
init_success = await vector_search.initialize(
|
|
334
|
-
auto_install=False, interactive=False
|
|
335
|
-
)
|
|
336
|
-
|
|
337
|
-
if init_success:
|
|
338
|
-
tools.append(vector_search)
|
|
339
|
-
self.logger.info("MCPVectorSearchService added to built-in tools")
|
|
340
|
-
else:
|
|
341
|
-
self.logger.debug(
|
|
342
|
-
"mcp-vector-search not installed - will be available via auto-install on first use"
|
|
343
|
-
)
|
|
344
|
-
except Exception as e:
|
|
345
|
-
self.logger.debug(f"Could not load MCPVectorSearchService: {e}")
|
|
346
|
-
|
|
347
|
-
# Ticket tools removed - mcp-ticketer provides ticket functionality
|
|
348
|
-
|
|
349
|
-
if not tools:
|
|
350
|
-
self.logger.warning("No tools available to register")
|
|
351
|
-
return
|
|
352
|
-
|
|
353
|
-
# Register each tool
|
|
354
|
-
for tool in tools:
|
|
355
|
-
try:
|
|
356
|
-
# Initialize the tool
|
|
357
|
-
if await tool.initialize():
|
|
358
|
-
# Register with the registry
|
|
359
|
-
if self.registry.register_tool(tool, category="builtin"):
|
|
360
|
-
self.logger.info(
|
|
361
|
-
f"Registered tool: {tool.get_definition().name}"
|
|
362
|
-
)
|
|
363
|
-
else:
|
|
364
|
-
self.logger.warning(
|
|
365
|
-
f"Failed to register tool: {tool.get_definition().name}"
|
|
366
|
-
)
|
|
367
|
-
else:
|
|
368
|
-
self.logger.warning(
|
|
369
|
-
f"Failed to initialize tool: {tool.get_definition().name}"
|
|
370
|
-
)
|
|
371
|
-
except Exception as e:
|
|
372
|
-
self.logger.error(
|
|
373
|
-
f"Error registering tool {tool.get_definition().name}: {e}"
|
|
374
|
-
)
|
|
375
|
-
|
|
376
|
-
async def start(self) -> bool:
|
|
377
|
-
"""
|
|
378
|
-
Start the MCP Gateway server.
|
|
379
|
-
|
|
380
|
-
Returns:
|
|
381
|
-
True if startup successful
|
|
382
|
-
"""
|
|
383
|
-
try:
|
|
384
|
-
self.logger.info("Starting MCP Gateway")
|
|
385
|
-
|
|
386
|
-
if not self.server:
|
|
387
|
-
self.logger.error("Server not initialized")
|
|
388
|
-
return False
|
|
389
|
-
|
|
390
|
-
if not await self.server.start():
|
|
391
|
-
self.logger.error("Failed to start MCP server")
|
|
392
|
-
return False
|
|
393
|
-
|
|
394
|
-
self.logger.info("MCP Gateway started successfully")
|
|
395
|
-
return True
|
|
396
|
-
|
|
397
|
-
except Exception as e:
|
|
398
|
-
self.logger.error(f"Failed to start MCP Gateway: {e}")
|
|
399
|
-
return False
|
|
400
|
-
|
|
401
|
-
async def run(self) -> None:
|
|
402
|
-
"""
|
|
403
|
-
Run the MCP Gateway main loop.
|
|
404
|
-
|
|
405
|
-
This method blocks until shutdown is requested.
|
|
406
|
-
"""
|
|
407
|
-
try:
|
|
408
|
-
self.logger.info("MCP Gateway running")
|
|
409
|
-
|
|
410
|
-
# Wait for shutdown signal
|
|
411
|
-
await self._shutdown_event.wait()
|
|
412
|
-
|
|
413
|
-
self.logger.info("Shutdown signal received")
|
|
414
|
-
|
|
415
|
-
except Exception as e:
|
|
416
|
-
self.logger.error(f"Error in MCP Gateway main loop: {e}")
|
|
417
|
-
raise
|
|
418
|
-
|
|
419
|
-
async def shutdown(self) -> None:
|
|
420
|
-
"""Shutdown the MCP Gateway gracefully."""
|
|
421
|
-
try:
|
|
422
|
-
self.logger.info("Shutting down MCP Gateway")
|
|
423
|
-
|
|
424
|
-
# Shutdown server
|
|
425
|
-
if self.server:
|
|
426
|
-
await self.server.shutdown()
|
|
427
|
-
|
|
428
|
-
# Shutdown registry (which will shutdown all tools)
|
|
429
|
-
if self.registry:
|
|
430
|
-
try:
|
|
431
|
-
await self.registry.shutdown()
|
|
432
|
-
except Exception as e:
|
|
433
|
-
self.logger.warning(f"Error during registry shutdown: {e}")
|
|
434
|
-
|
|
435
|
-
# Shutdown communication handler
|
|
436
|
-
if self.communication:
|
|
437
|
-
try:
|
|
438
|
-
await self.communication.shutdown()
|
|
439
|
-
except Exception as e:
|
|
440
|
-
self.logger.warning(f"Error during communication shutdown: {e}")
|
|
441
|
-
|
|
442
|
-
# Shutdown external services
|
|
443
|
-
if self.external_services:
|
|
444
|
-
try:
|
|
445
|
-
await self.external_services.shutdown()
|
|
446
|
-
except Exception as e:
|
|
447
|
-
self.logger.warning(f"Error during external services shutdown: {e}")
|
|
448
|
-
|
|
449
|
-
self.logger.info("MCP Gateway shutdown complete")
|
|
450
|
-
|
|
451
|
-
except Exception as e:
|
|
452
|
-
self.logger.error(f"Error during shutdown: {e}")
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
async def main(args: argparse.Namespace) -> int:
|
|
456
|
-
"""
|
|
457
|
-
Main entry point for the MCP Gateway.
|
|
458
|
-
|
|
459
|
-
Args:
|
|
460
|
-
args: Command line arguments
|
|
461
|
-
|
|
462
|
-
Returns:
|
|
463
|
-
Exit code (0 for success, 1 for failure)
|
|
464
|
-
"""
|
|
465
|
-
# Setup logging
|
|
466
|
-
log_level = logging.DEBUG if args.debug else logging.INFO
|
|
467
|
-
logging.basicConfig(
|
|
468
|
-
level=log_level, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
469
|
-
)
|
|
470
|
-
|
|
471
|
-
# Create gateway orchestrator instance
|
|
472
|
-
config_path = Path(args.config) if args.config else None
|
|
473
|
-
gateway = MCPGatewayOrchestrator(config_path=config_path)
|
|
474
|
-
|
|
475
|
-
try:
|
|
476
|
-
# Initialize
|
|
477
|
-
if not await gateway.initialize():
|
|
478
|
-
logging.error("Failed to initialize MCP Gateway")
|
|
479
|
-
return 1
|
|
480
|
-
|
|
481
|
-
# Start
|
|
482
|
-
if not await gateway.start():
|
|
483
|
-
logging.error("Failed to start MCP Gateway")
|
|
484
|
-
return 1
|
|
485
|
-
|
|
486
|
-
# Run until shutdown
|
|
487
|
-
await gateway.run()
|
|
488
|
-
|
|
489
|
-
# Graceful shutdown
|
|
490
|
-
await gateway.shutdown()
|
|
491
|
-
|
|
492
|
-
return 0
|
|
493
|
-
|
|
494
|
-
except Exception as e:
|
|
495
|
-
logging.error(f"Unhandled exception: {e}")
|
|
496
|
-
await gateway.shutdown()
|
|
497
|
-
return 1
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
def parse_arguments() -> argparse.Namespace:
|
|
501
|
-
"""
|
|
502
|
-
Parse command line arguments.
|
|
503
|
-
|
|
504
|
-
Returns:
|
|
505
|
-
Parsed arguments
|
|
506
|
-
"""
|
|
507
|
-
parser = argparse.ArgumentParser(
|
|
508
|
-
description="Claude MPM MCP Gateway Server",
|
|
509
|
-
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
510
|
-
epilog="""
|
|
511
|
-
Examples:
|
|
512
|
-
# Run with default configuration
|
|
513
|
-
python -m claude_mpm.services.mcp_gateway.main
|
|
514
|
-
|
|
515
|
-
# Run with custom configuration file
|
|
516
|
-
python -m claude_mpm.services.mcp_gateway.main --config /path/to/config.yaml
|
|
517
|
-
|
|
518
|
-
# Run with debug logging
|
|
519
|
-
python -m claude_mpm.services.mcp_gateway.main --debug
|
|
520
|
-
|
|
521
|
-
# Run as MCP server for Claude Code
|
|
522
|
-
python -m claude_mpm.services.mcp_gateway.main --stdio
|
|
523
|
-
""",
|
|
524
|
-
)
|
|
525
|
-
|
|
526
|
-
parser.add_argument("--config", type=str, help="Path to configuration file")
|
|
527
|
-
|
|
528
|
-
parser.add_argument("--debug", action="store_true", help="Enable debug logging")
|
|
529
|
-
|
|
530
|
-
parser.add_argument(
|
|
531
|
-
"--stdio",
|
|
532
|
-
action="store_true",
|
|
533
|
-
default=True,
|
|
534
|
-
help="Use stdio for communication (default)",
|
|
535
|
-
)
|
|
536
|
-
|
|
537
|
-
parser.add_argument(
|
|
538
|
-
"--version", action="version", version="Claude MPM MCP Gateway 1.0.0"
|
|
539
|
-
)
|
|
540
|
-
|
|
541
|
-
return parser.parse_args()
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
async def run_standalone_gateway(
|
|
545
|
-
gateway_name: str = "claude-mpm-mcp", version: str = "1.0.0"
|
|
546
|
-
):
|
|
547
|
-
"""
|
|
548
|
-
Run the MCP Gateway as a standalone server.
|
|
549
|
-
|
|
550
|
-
This creates a simple instance without complex management.
|
|
551
|
-
|
|
552
|
-
Args:
|
|
553
|
-
gateway_name: Name for the gateway
|
|
554
|
-
version: Gateway version
|
|
555
|
-
"""
|
|
556
|
-
logger = get_logger("MCPGatewayMain")
|
|
557
|
-
|
|
558
|
-
try:
|
|
559
|
-
logger.info(f"Starting standalone MCP gateway: {gateway_name}")
|
|
560
|
-
|
|
561
|
-
# Create and run a simple orchestrator
|
|
562
|
-
orchestrator = MCPGatewayOrchestrator()
|
|
563
|
-
|
|
564
|
-
if not await orchestrator.initialize():
|
|
565
|
-
logger.error("Failed to initialize gateway")
|
|
566
|
-
return False
|
|
567
|
-
|
|
568
|
-
if not await orchestrator.start():
|
|
569
|
-
logger.error("Failed to start gateway")
|
|
570
|
-
return False
|
|
571
|
-
|
|
572
|
-
# Run until shutdown
|
|
573
|
-
await orchestrator.run()
|
|
574
|
-
await orchestrator.shutdown()
|
|
575
|
-
|
|
576
|
-
return True
|
|
577
|
-
|
|
578
|
-
except Exception as e:
|
|
579
|
-
logger.error(f"Error running standalone gateway: {e}")
|
|
580
|
-
return False
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
if __name__ == "__main__":
|
|
584
|
-
# Parse arguments
|
|
585
|
-
args = parse_arguments()
|
|
586
|
-
|
|
587
|
-
# Run the gateway
|
|
588
|
-
exit_code = asyncio.run(main(args))
|
|
589
|
-
sys.exit(exit_code)
|