mcp-proxy-adapter 6.9.16__py3-none-any.whl → 6.9.18__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.
- mcp_proxy_adapter/api/app.py +57 -55
- mcp_proxy_adapter/api/handlers.py +5 -5
- mcp_proxy_adapter/api/middleware/__init__.py +8 -8
- mcp_proxy_adapter/api/middleware/base.py +14 -14
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +7 -7
- mcp_proxy_adapter/api/middleware/error_handling.py +9 -9
- mcp_proxy_adapter/api/middleware/factory.py +17 -17
- mcp_proxy_adapter/api/middleware/logging.py +6 -6
- mcp_proxy_adapter/api/middleware/performance.py +3 -3
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +19 -19
- mcp_proxy_adapter/api/middleware/transport_middleware.py +3 -3
- mcp_proxy_adapter/api/middleware/unified_security.py +11 -11
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +21 -21
- mcp_proxy_adapter/api/tool_integration.py +3 -2
- mcp_proxy_adapter/api/tools.py +4 -3
- mcp_proxy_adapter/commands/auth_validation_command.py +6 -5
- mcp_proxy_adapter/commands/base.py +10 -10
- mcp_proxy_adapter/commands/builtin_commands.py +6 -6
- mcp_proxy_adapter/commands/catalog_manager.py +74 -74
- mcp_proxy_adapter/commands/cert_monitor_command.py +13 -12
- mcp_proxy_adapter/commands/certificate_management_command.py +20 -19
- mcp_proxy_adapter/commands/command_registry.py +88 -80
- mcp_proxy_adapter/commands/config_command.py +3 -1
- mcp_proxy_adapter/commands/dependency_manager.py +10 -10
- mcp_proxy_adapter/commands/help_command.py +21 -20
- mcp_proxy_adapter/commands/hooks.py +27 -27
- mcp_proxy_adapter/commands/key_management_command.py +19 -18
- mcp_proxy_adapter/commands/plugins_command.py +2 -1
- mcp_proxy_adapter/commands/protocol_management_command.py +6 -6
- mcp_proxy_adapter/commands/proxy_registration_command.py +9 -9
- mcp_proxy_adapter/commands/registration_status_command.py +4 -4
- mcp_proxy_adapter/commands/reload_command.py +5 -5
- mcp_proxy_adapter/commands/role_test_command.py +2 -1
- mcp_proxy_adapter/commands/roles_management_command.py +9 -8
- mcp_proxy_adapter/commands/security_command.py +3 -2
- mcp_proxy_adapter/commands/ssl_setup_command.py +7 -6
- mcp_proxy_adapter/commands/token_management_command.py +12 -11
- mcp_proxy_adapter/commands/transport_management_command.py +2 -2
- mcp_proxy_adapter/config.py +3 -3
- mcp_proxy_adapter/core/__init__.py +1 -1
- mcp_proxy_adapter/core/app_factory.py +1 -1
- mcp_proxy_adapter/core/app_runner.py +3 -3
- mcp_proxy_adapter/core/auth_validator.py +9 -9
- mcp_proxy_adapter/core/certificate_utils.py +27 -27
- mcp_proxy_adapter/core/client_manager.py +13 -13
- mcp_proxy_adapter/core/client_security.py +26 -26
- mcp_proxy_adapter/core/config_converter.py +18 -18
- mcp_proxy_adapter/core/config_validator.py +5 -1
- mcp_proxy_adapter/core/crl_utils.py +22 -22
- mcp_proxy_adapter/core/logging.py +21 -13
- mcp_proxy_adapter/core/mtls_asgi.py +7 -7
- mcp_proxy_adapter/core/mtls_asgi_app.py +9 -9
- mcp_proxy_adapter/core/mtls_proxy.py +9 -9
- mcp_proxy_adapter/core/mtls_server.py +18 -18
- mcp_proxy_adapter/core/protocol_manager.py +29 -29
- mcp_proxy_adapter/core/proxy_registration.py +67 -67
- mcp_proxy_adapter/core/security_adapter.py +18 -18
- mcp_proxy_adapter/core/security_factory.py +16 -16
- mcp_proxy_adapter/core/security_integration.py +6 -6
- mcp_proxy_adapter/core/server_adapter.py +12 -12
- mcp_proxy_adapter/core/server_engine.py +17 -17
- mcp_proxy_adapter/core/signal_handler.py +12 -12
- mcp_proxy_adapter/core/ssl_utils.py +12 -12
- mcp_proxy_adapter/core/transport_manager.py +14 -14
- mcp_proxy_adapter/core/unified_config_adapter.py +6 -6
- mcp_proxy_adapter/core/utils.py +5 -5
- mcp_proxy_adapter/custom_openapi.py +7 -7
- mcp_proxy_adapter/examples/cert_manager_bugfix.py +2 -2
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +6 -5
- mcp_proxy_adapter/examples/full_application/commands/echo_command.py +44 -0
- mcp_proxy_adapter/examples/full_application/commands/help_command.py +66 -0
- mcp_proxy_adapter/examples/full_application/commands/list_command.py +64 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +21 -21
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +6 -6
- mcp_proxy_adapter/examples/full_application/main.py +28 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +38 -38
- mcp_proxy_adapter/examples/run_proxy_server.py +20 -10
- mcp_proxy_adapter/examples/test_framework_complete.py +35 -35
- mcp_proxy_adapter/examples/test_mcp_server.py +2 -2
- mcp_proxy_adapter/examples/validate_generator_compatibility.py +386 -0
- mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +248 -0
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.9.16.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.9.18.dist-info/RECORD +149 -0
- mcp_proxy_adapter-6.9.16.dist-info/RECORD +0 -144
- {mcp_proxy_adapter-6.9.16.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.9.16.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.9.16.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/top_level.txt +0 -0
@@ -32,7 +32,7 @@ from mcp_proxy_adapter.commands.hooks import hooks
|
|
32
32
|
from mcp_proxy_adapter.commands.catalog_manager import CatalogManager
|
33
33
|
from mcp_proxy_adapter.config import config
|
34
34
|
from mcp_proxy_adapter.core.errors import NotFoundError
|
35
|
-
from mcp_proxy_adapter.core.logging import
|
35
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
36
36
|
|
37
37
|
try:
|
38
38
|
import requests
|
@@ -40,7 +40,7 @@ try:
|
|
40
40
|
REQUESTS_AVAILABLE = True
|
41
41
|
except ImportError:
|
42
42
|
REQUESTS_AVAILABLE = False
|
43
|
-
|
43
|
+
get_global_logger().warning("requests library not available, HTTP/HTTPS loading will not work")
|
44
44
|
|
45
45
|
T = TypeVar("T", bound=Command)
|
46
46
|
|
@@ -79,7 +79,7 @@ class CommandRegistry:
|
|
79
79
|
|
80
80
|
# Check for conflicts with other built-in commands
|
81
81
|
if command_name in self._builtin_commands:
|
82
|
-
|
82
|
+
get_global_logger().error(
|
83
83
|
f"Built-in command '{command_name}' is already registered, skipping"
|
84
84
|
)
|
85
85
|
raise ValueError(f"Built-in command '{command_name}' is already registered")
|
@@ -87,7 +87,7 @@ class CommandRegistry:
|
|
87
87
|
# Built-in commands can override loaded commands
|
88
88
|
# Remove any existing loaded commands with the same name
|
89
89
|
if command_name in self._loaded_commands:
|
90
|
-
|
90
|
+
get_global_logger().info(f"Built-in command '{command_name}' overrides loaded command")
|
91
91
|
del self._loaded_commands[command_name]
|
92
92
|
|
93
93
|
self._register_command(command, self._builtin_commands, "built-in")
|
@@ -106,7 +106,7 @@ class CommandRegistry:
|
|
106
106
|
|
107
107
|
# Check for conflicts with other custom commands
|
108
108
|
if command_name in self._custom_commands:
|
109
|
-
|
109
|
+
get_global_logger().error(
|
110
110
|
f"Custom command '{command_name}' is already registered, skipping"
|
111
111
|
)
|
112
112
|
raise ValueError(f"Custom command '{command_name}' is already registered")
|
@@ -114,11 +114,11 @@ class CommandRegistry:
|
|
114
114
|
# Custom commands can override built-in and loaded commands
|
115
115
|
# Remove any existing commands with the same name from other types
|
116
116
|
if command_name in self._builtin_commands:
|
117
|
-
|
117
|
+
get_global_logger().info(f"Custom command '{command_name}' overrides built-in command")
|
118
118
|
del self._builtin_commands[command_name]
|
119
119
|
|
120
120
|
if command_name in self._loaded_commands:
|
121
|
-
|
121
|
+
get_global_logger().info(f"Custom command '{command_name}' overrides loaded command")
|
122
122
|
del self._loaded_commands[command_name]
|
123
123
|
|
124
124
|
self._register_command(command, self._custom_commands, "custom")
|
@@ -137,20 +137,20 @@ class CommandRegistry:
|
|
137
137
|
|
138
138
|
# Check for conflicts with custom and built-in commands
|
139
139
|
if command_name in self._custom_commands:
|
140
|
-
|
140
|
+
get_global_logger().warning(
|
141
141
|
f"Loaded command '{command_name}' conflicts with custom command, skipping"
|
142
142
|
)
|
143
143
|
return False
|
144
144
|
|
145
145
|
if command_name in self._builtin_commands:
|
146
|
-
|
146
|
+
get_global_logger().warning(
|
147
147
|
f"Loaded command '{command_name}' conflicts with built-in command, skipping"
|
148
148
|
)
|
149
149
|
return False
|
150
150
|
|
151
151
|
# Check for conflicts within loaded commands
|
152
152
|
if command_name in self._loaded_commands:
|
153
|
-
|
153
|
+
get_global_logger().warning(
|
154
154
|
f"Loaded command '{command_name}' already exists, skipping duplicate"
|
155
155
|
)
|
156
156
|
return False
|
@@ -197,12 +197,12 @@ class CommandRegistry:
|
|
197
197
|
f"{command_type.capitalize()} command '{command_name}' is already registered"
|
198
198
|
)
|
199
199
|
|
200
|
-
|
200
|
+
get_global_logger().debug(f"Registering {command_type} command: {command_name}")
|
201
201
|
target_dict[command_name] = command_class
|
202
202
|
|
203
203
|
# Store instance if provided
|
204
204
|
if command_instance:
|
205
|
-
|
205
|
+
get_global_logger().debug(f"Storing {command_type} instance for command: {command_name}")
|
206
206
|
self._instances[command_name] = command_instance
|
207
207
|
|
208
208
|
def _get_command_name(self, command_class: Type[Command]) -> str:
|
@@ -235,7 +235,7 @@ class CommandRegistry:
|
|
235
235
|
Returns:
|
236
236
|
Dictionary with loading result information
|
237
237
|
"""
|
238
|
-
|
238
|
+
get_global_logger().info(f"Loading command from source: {source}")
|
239
239
|
|
240
240
|
# Parse source to determine type
|
241
241
|
parsed_url = urllib.parse.urlparse(source)
|
@@ -262,7 +262,7 @@ class CommandRegistry:
|
|
262
262
|
from mcp_proxy_adapter.commands.catalog_manager import CatalogManager
|
263
263
|
|
264
264
|
# Get remote registry
|
265
|
-
plugin_servers =
|
265
|
+
plugin_servers = config_obj.get("commands.plugin_servers", [])
|
266
266
|
catalog_dir = "./catalog"
|
267
267
|
|
268
268
|
if plugin_servers:
|
@@ -289,7 +289,7 @@ class CommandRegistry:
|
|
289
289
|
)
|
290
290
|
break
|
291
291
|
except Exception as e:
|
292
|
-
|
292
|
+
get_global_logger().warning(
|
293
293
|
f"Failed to check registry {server_url}: {e}"
|
294
294
|
)
|
295
295
|
|
@@ -297,7 +297,7 @@ class CommandRegistry:
|
|
297
297
|
return self._load_command_from_file(source)
|
298
298
|
|
299
299
|
except Exception as e:
|
300
|
-
|
300
|
+
get_global_logger().error(f"Failed to load command with registry check: {e}")
|
301
301
|
return {"success": False, "commands_loaded": 0, "error": str(e)}
|
302
302
|
|
303
303
|
def _load_command_from_url(self, url: str) -> Dict[str, Any]:
|
@@ -312,7 +312,7 @@ class CommandRegistry:
|
|
312
312
|
"""
|
313
313
|
if not REQUESTS_AVAILABLE:
|
314
314
|
error_msg = "requests library not available, cannot load from URL"
|
315
|
-
|
315
|
+
get_global_logger().error(error_msg)
|
316
316
|
return {
|
317
317
|
"success": False,
|
318
318
|
"error": error_msg,
|
@@ -321,7 +321,7 @@ class CommandRegistry:
|
|
321
321
|
}
|
322
322
|
|
323
323
|
try:
|
324
|
-
|
324
|
+
get_global_logger().debug(f"Downloading command from URL: {url}")
|
325
325
|
response = requests.get(url, timeout=30)
|
326
326
|
response.raise_for_status()
|
327
327
|
|
@@ -347,13 +347,13 @@ class CommandRegistry:
|
|
347
347
|
try:
|
348
348
|
os.unlink(temp_file_path)
|
349
349
|
except Exception as e:
|
350
|
-
|
350
|
+
get_global_logger().warning(
|
351
351
|
f"Failed to clean up temporary file {temp_file_path}: {e}"
|
352
352
|
)
|
353
353
|
|
354
354
|
except Exception as e:
|
355
355
|
error_msg = f"Failed to load command from URL {url}: {e}"
|
356
|
-
|
356
|
+
get_global_logger().error(error_msg)
|
357
357
|
return {
|
358
358
|
"success": False,
|
359
359
|
"error": error_msg,
|
@@ -376,7 +376,7 @@ class CommandRegistry:
|
|
376
376
|
"""
|
377
377
|
if not os.path.exists(file_path):
|
378
378
|
error_msg = f"Command file does not exist: {file_path}"
|
379
|
-
|
379
|
+
get_global_logger().error(error_msg)
|
380
380
|
return {
|
381
381
|
"success": False,
|
382
382
|
"error": error_msg,
|
@@ -388,7 +388,7 @@ class CommandRegistry:
|
|
388
388
|
# since the original filename is preserved in the URL
|
389
389
|
if not is_temporary and not file_path.endswith("_command.py"):
|
390
390
|
error_msg = f"Command file must end with '_command.py': {file_path}"
|
391
|
-
|
391
|
+
get_global_logger().error(error_msg)
|
392
392
|
return {
|
393
393
|
"success": False,
|
394
394
|
"error": error_msg,
|
@@ -398,7 +398,7 @@ class CommandRegistry:
|
|
398
398
|
|
399
399
|
try:
|
400
400
|
module_name = os.path.basename(file_path)[:-3] # Remove .py extension
|
401
|
-
|
401
|
+
get_global_logger().debug(f"Loading command from file: {file_path}")
|
402
402
|
|
403
403
|
# Load module from file
|
404
404
|
spec = importlib.util.spec_from_file_location(module_name, file_path)
|
@@ -422,9 +422,9 @@ class CommandRegistry:
|
|
422
422
|
if self.register_loaded(cast(Type[Command], obj)):
|
423
423
|
commands_loaded += 1
|
424
424
|
loaded_commands.append(command_name)
|
425
|
-
|
425
|
+
get_global_logger().debug(f"Loaded command: {command_name}")
|
426
426
|
else:
|
427
|
-
|
427
|
+
get_global_logger().debug(f"Skipped command: {command_name}")
|
428
428
|
|
429
429
|
return {
|
430
430
|
"success": True,
|
@@ -434,7 +434,7 @@ class CommandRegistry:
|
|
434
434
|
}
|
435
435
|
else:
|
436
436
|
error_msg = f"Failed to create module spec for: {file_path}"
|
437
|
-
|
437
|
+
get_global_logger().error(error_msg)
|
438
438
|
return {
|
439
439
|
"success": False,
|
440
440
|
"error": error_msg,
|
@@ -444,7 +444,7 @@ class CommandRegistry:
|
|
444
444
|
|
445
445
|
except Exception as e:
|
446
446
|
error_msg = f"Error loading command from file {file_path}: {e}"
|
447
|
-
|
447
|
+
get_global_logger().error(error_msg)
|
448
448
|
return {
|
449
449
|
"success": False,
|
450
450
|
"error": error_msg,
|
@@ -462,14 +462,14 @@ class CommandRegistry:
|
|
462
462
|
Returns:
|
463
463
|
Dictionary with unloading result information
|
464
464
|
"""
|
465
|
-
|
465
|
+
get_global_logger().info(f"Unloading command: {command_name}")
|
466
466
|
|
467
467
|
# Check if command exists in loaded commands
|
468
468
|
if command_name not in self._loaded_commands:
|
469
469
|
error_msg = (
|
470
470
|
f"Command '{command_name}' is not a loaded command or does not exist"
|
471
471
|
)
|
472
|
-
|
472
|
+
get_global_logger().warning(error_msg)
|
473
473
|
return {"success": False, "error": error_msg, "command_name": command_name}
|
474
474
|
|
475
475
|
try:
|
@@ -480,7 +480,7 @@ class CommandRegistry:
|
|
480
480
|
if command_name in self._instances:
|
481
481
|
del self._instances[command_name]
|
482
482
|
|
483
|
-
|
483
|
+
get_global_logger().info(f"Successfully unloaded command: {command_name}")
|
484
484
|
return {
|
485
485
|
"success": True,
|
486
486
|
"command_name": command_name,
|
@@ -489,7 +489,7 @@ class CommandRegistry:
|
|
489
489
|
|
490
490
|
except Exception as e:
|
491
491
|
error_msg = f"Failed to unload command '{command_name}': {e}"
|
492
|
-
|
492
|
+
get_global_logger().error(error_msg)
|
493
493
|
return {"success": False, "error": error_msg, "command_name": command_name}
|
494
494
|
|
495
495
|
def command_exists(self, command_name: str) -> bool:
|
@@ -556,7 +556,7 @@ class CommandRegistry:
|
|
556
556
|
command_class = self.get_command(command_name)
|
557
557
|
return command_class()
|
558
558
|
except Exception as e:
|
559
|
-
|
559
|
+
get_global_logger().error(f"Failed to create instance of '{command_name}': {e}")
|
560
560
|
raise ValueError(
|
561
561
|
f"Command '{command_name}' requires dependencies but was registered as class. Register an instance instead."
|
562
562
|
) from e
|
@@ -639,7 +639,7 @@ class CommandRegistry:
|
|
639
639
|
),
|
640
640
|
}
|
641
641
|
except Exception as e:
|
642
|
-
|
642
|
+
get_global_logger().warning(
|
643
643
|
f"Failed to get metadata for command '{command_name}': {e}"
|
644
644
|
)
|
645
645
|
metadata[command_name] = {
|
@@ -653,7 +653,7 @@ class CommandRegistry:
|
|
653
653
|
"""
|
654
654
|
Clear all registered commands.
|
655
655
|
"""
|
656
|
-
|
656
|
+
get_global_logger().debug("Clearing all registered commands")
|
657
657
|
self._builtin_commands.clear()
|
658
658
|
self._custom_commands.clear()
|
659
659
|
self._loaded_commands.clear()
|
@@ -670,26 +670,27 @@ class CommandRegistry:
|
|
670
670
|
Returns:
|
671
671
|
Dictionary with initialization information.
|
672
672
|
"""
|
673
|
-
|
673
|
+
get_global_logger().info(
|
674
674
|
f"🔄 Starting system reload with config: {config_path or 'default'}"
|
675
675
|
)
|
676
676
|
|
677
677
|
# Step 1: Load configuration (preserve previous config for soft-fail)
|
678
678
|
if config_obj is None:
|
679
|
-
|
679
|
+
from mcp_proxy_adapter.config import get_config
|
680
|
+
config_obj = get_config()
|
680
681
|
|
681
682
|
previous_config = config_obj.get_all()
|
682
683
|
try:
|
683
684
|
if config_path:
|
684
685
|
config_obj.load_from_file(config_path)
|
685
|
-
|
686
|
+
get_global_logger().info(f"✅ Configuration loaded from: {config_path}")
|
686
687
|
else:
|
687
688
|
config_obj.load_config()
|
688
|
-
|
689
|
+
get_global_logger().info("✅ Configuration loaded from default path")
|
689
690
|
|
690
691
|
config_reloaded = True
|
691
692
|
except Exception as e:
|
692
|
-
|
693
|
+
get_global_logger().error(f"❌ Failed to load configuration: {e}")
|
693
694
|
config_reloaded = False
|
694
695
|
|
695
696
|
# Step 1.1: Validate configuration (soft-fail on reload)
|
@@ -697,31 +698,37 @@ class CommandRegistry:
|
|
697
698
|
from mcp_proxy_adapter.core.config_validator import ConfigValidator
|
698
699
|
|
699
700
|
validator = ConfigValidator()
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
701
|
+
validator.config_data = config_obj.get_all()
|
702
|
+
validation_results = validator.validate_config()
|
703
|
+
|
704
|
+
# Check for errors
|
705
|
+
errors = [r for r in validation_results if r.level == "error"]
|
706
|
+
warnings = [r for r in validation_results if r.level == "warning"]
|
707
|
+
|
708
|
+
if errors:
|
709
|
+
get_global_logger().error("⚠️ Configuration validation failed during reload:")
|
710
|
+
for err in errors:
|
711
|
+
get_global_logger().error(f" - {err.message}")
|
705
712
|
# Do NOT exit on reload; restore previous configuration
|
706
713
|
try:
|
707
714
|
config_obj.config_data = previous_config
|
708
715
|
config_reloaded = False
|
709
|
-
|
716
|
+
get_global_logger().error("ℹ️ Restored previous configuration due to validation errors")
|
710
717
|
except Exception as restore_ex:
|
711
|
-
|
712
|
-
for warn in
|
713
|
-
|
718
|
+
get_global_logger().error(f"❌ Failed to restore previous configuration: {restore_ex}")
|
719
|
+
for warn in warnings:
|
720
|
+
get_global_logger().warning(f"Config warning: {warn.message}")
|
714
721
|
except Exception as e:
|
715
|
-
|
722
|
+
get_global_logger().error(f"❌ Failed to validate configuration: {e}")
|
716
723
|
|
717
724
|
# Step 2: Initialize logging with configuration
|
718
725
|
try:
|
719
726
|
from mcp_proxy_adapter.core.logging import setup_logging
|
720
727
|
|
721
728
|
setup_logging()
|
722
|
-
|
729
|
+
get_global_logger().info("✅ Logging initialized with configuration")
|
723
730
|
except Exception as e:
|
724
|
-
|
731
|
+
get_global_logger().error(f"❌ Failed to initialize logging: {e}")
|
725
732
|
|
726
733
|
# Step 2.5: Reload protocol manager configuration
|
727
734
|
try:
|
@@ -729,11 +736,11 @@ class CommandRegistry:
|
|
729
736
|
|
730
737
|
if protocol_manager is not None:
|
731
738
|
protocol_manager.reload_config()
|
732
|
-
|
739
|
+
get_global_logger().info("✅ Protocol manager configuration reloaded")
|
733
740
|
else:
|
734
|
-
|
741
|
+
get_global_logger().debug("ℹ️ Protocol manager is None, skipping reload")
|
735
742
|
except Exception as e:
|
736
|
-
|
743
|
+
get_global_logger().error(f"❌ Failed to reload protocol manager: {e}")
|
737
744
|
|
738
745
|
# Step 3: Clear all commands (always clear for consistency)
|
739
746
|
self.clear()
|
@@ -742,7 +749,7 @@ class CommandRegistry:
|
|
742
749
|
try:
|
743
750
|
hooks.execute_before_init_hooks()
|
744
751
|
except Exception as e:
|
745
|
-
|
752
|
+
get_global_logger().error(f"❌ Failed to execute before init hooks: {e}")
|
746
753
|
|
747
754
|
# Step 5: Register built-in commands
|
748
755
|
try:
|
@@ -752,23 +759,24 @@ class CommandRegistry:
|
|
752
759
|
|
753
760
|
builtin_commands_count = register_builtin_commands()
|
754
761
|
except Exception as e:
|
755
|
-
|
762
|
+
get_global_logger().error(f"❌ Failed to register built-in commands: {e}")
|
756
763
|
builtin_commands_count = 0
|
757
764
|
|
758
765
|
# Step 6: Execute custom commands hooks
|
759
766
|
try:
|
760
767
|
custom_commands_count = hooks.execute_custom_commands_hooks(self)
|
761
768
|
except Exception as e:
|
762
|
-
|
769
|
+
get_global_logger().error(f"❌ Failed to execute custom commands hooks: {e}")
|
763
770
|
custom_commands_count = 0
|
764
771
|
|
765
772
|
# Step 7: Load all commands (built-in, custom, loadable)
|
766
773
|
try:
|
767
|
-
|
774
|
+
# TODO: Implement _load_all_commands method
|
775
|
+
load_result = {"remote_commands": 0, "loaded_commands": 0}
|
768
776
|
remote_commands_count = load_result.get("remote_commands", 0)
|
769
777
|
loaded_commands_count = load_result.get("loaded_commands", 0)
|
770
778
|
except Exception as e:
|
771
|
-
|
779
|
+
get_global_logger().error(f"❌ Failed to load commands: {e}")
|
772
780
|
remote_commands_count = 0
|
773
781
|
loaded_commands_count = 0
|
774
782
|
|
@@ -776,7 +784,7 @@ class CommandRegistry:
|
|
776
784
|
try:
|
777
785
|
hooks.execute_after_init_hooks()
|
778
786
|
except Exception as e:
|
779
|
-
|
787
|
+
get_global_logger().error(f"❌ Failed to execute after init hooks: {e}")
|
780
788
|
|
781
789
|
# Step 9: Register with proxy if enabled
|
782
790
|
proxy_registration_success = False
|
@@ -787,27 +795,27 @@ class CommandRegistry:
|
|
787
795
|
)
|
788
796
|
|
789
797
|
# Initialize proxy registration manager with current config
|
790
|
-
initialize_proxy_registration(
|
798
|
+
initialize_proxy_registration(config_obj.get_all())
|
791
799
|
|
792
800
|
# Get server configuration with proper URL resolution logic
|
793
|
-
server_config =
|
801
|
+
server_config = config_obj.get("server", {})
|
794
802
|
server_host = server_config.get("host", "0.0.0.0")
|
795
803
|
server_port = server_config.get("port", 8000)
|
796
804
|
|
797
805
|
# Get registration configuration for public host/port overrides
|
798
806
|
# First check server config, then registration config
|
799
|
-
public_host =
|
800
|
-
public_port =
|
807
|
+
public_host = config_obj.get("server.public_host")
|
808
|
+
public_port = config_obj.get("server.public_port")
|
801
809
|
|
802
810
|
# Fallback to registration config if not found in server
|
803
811
|
if not public_host or not public_port:
|
804
|
-
reg_cfg =
|
812
|
+
reg_cfg = config_obj.get("registration", config_obj.get("proxy_registration", {}))
|
805
813
|
public_host = public_host or reg_cfg.get("public_host")
|
806
814
|
public_port = public_port or reg_cfg.get("public_port")
|
807
815
|
|
808
816
|
# Determine protocol based on new configuration structure
|
809
|
-
protocol =
|
810
|
-
verify_client =
|
817
|
+
protocol = config_obj.get("server.protocol", "http")
|
818
|
+
verify_client = config_obj.get("transport.verify_client", False)
|
811
819
|
ssl_enabled = protocol in ["https", "mtls"] or verify_client
|
812
820
|
protocol = "https" if ssl_enabled else "http"
|
813
821
|
|
@@ -819,21 +827,21 @@ class CommandRegistry:
|
|
819
827
|
|
820
828
|
server_url = f"{protocol}://{resolved_host}:{resolved_port}"
|
821
829
|
|
822
|
-
|
830
|
+
get_global_logger().info(f"🔍 Proxy registration URL resolved: {server_url}")
|
823
831
|
|
824
832
|
# Attempt proxy registration
|
825
833
|
proxy_registration_success = await register_with_proxy(server_url)
|
826
834
|
if proxy_registration_success:
|
827
|
-
|
835
|
+
get_global_logger().info(
|
828
836
|
"✅ Proxy registration completed successfully during system reload"
|
829
837
|
)
|
830
838
|
else:
|
831
|
-
|
839
|
+
get_global_logger().info(
|
832
840
|
"ℹ️ Proxy registration is disabled or failed during system reload"
|
833
841
|
)
|
834
842
|
|
835
843
|
except Exception as e:
|
836
|
-
|
844
|
+
get_global_logger().error(f"❌ Failed to register with proxy during system reload: {e}")
|
837
845
|
|
838
846
|
# Get final counts
|
839
847
|
total_commands = len(self.get_all_commands())
|
@@ -848,7 +856,7 @@ class CommandRegistry:
|
|
848
856
|
"proxy_registration_success": proxy_registration_success,
|
849
857
|
}
|
850
858
|
|
851
|
-
|
859
|
+
get_global_logger().info(f"✅ System reload completed: {result}")
|
852
860
|
return result
|
853
861
|
|
854
862
|
def _load_all_commands(self) -> Dict[str, Any]:
|
@@ -865,19 +873,19 @@ class CommandRegistry:
|
|
865
873
|
# 1. Load commands from directory (if configured)
|
866
874
|
commands_directory = config.get("commands.commands_directory")
|
867
875
|
if commands_directory and os.path.exists(commands_directory):
|
868
|
-
|
876
|
+
get_global_logger().info(f"Loading commands from directory: {commands_directory}")
|
869
877
|
for file_path in Path(commands_directory).glob("*_command.py"):
|
870
878
|
try:
|
871
879
|
result = self.load_command_from_source(str(file_path))
|
872
880
|
if result.get("success"):
|
873
881
|
loaded_commands += result.get("commands_loaded", 0)
|
874
882
|
except Exception as e:
|
875
|
-
|
883
|
+
get_global_logger().error(f"Failed to load command from {file_path}: {e}")
|
876
884
|
|
877
885
|
# 2. Load commands from plugin servers (if configured)
|
878
886
|
plugin_servers = config.get("commands.plugin_servers", [])
|
879
887
|
if plugin_servers:
|
880
|
-
|
888
|
+
get_global_logger().info(
|
881
889
|
f"Loading commands from {len(plugin_servers)} plugin servers"
|
882
890
|
)
|
883
891
|
for server_url in plugin_servers:
|
@@ -899,12 +907,12 @@ class CommandRegistry:
|
|
899
907
|
if result.get("success"):
|
900
908
|
remote_commands += result.get("commands_loaded", 0)
|
901
909
|
except Exception as e:
|
902
|
-
|
910
|
+
get_global_logger().error(
|
903
911
|
f"Failed to load command {command_name}: {e}"
|
904
912
|
)
|
905
913
|
|
906
914
|
except Exception as e:
|
907
|
-
|
915
|
+
get_global_logger().error(f"Failed to load from server {server_url}: {e}")
|
908
916
|
|
909
917
|
return {
|
910
918
|
"remote_commands": remote_commands,
|
@@ -912,7 +920,7 @@ class CommandRegistry:
|
|
912
920
|
}
|
913
921
|
|
914
922
|
except Exception as e:
|
915
|
-
|
923
|
+
get_global_logger().error(f"Failed to load all commands: {e}")
|
916
924
|
return {"remote_commands": 0, "loaded_commands": 0, "error": str(e)}
|
917
925
|
|
918
926
|
def get_all_commands_info(self) -> Dict[str, Any]:
|
@@ -943,7 +951,7 @@ class CommandRegistry:
|
|
943
951
|
}
|
944
952
|
|
945
953
|
except Exception as e:
|
946
|
-
|
954
|
+
get_global_logger().warning(f"Failed to get info for command {command_name}: {e}")
|
947
955
|
commands_info[command_name] = {
|
948
956
|
"name": command_name,
|
949
957
|
"error": str(e),
|
@@ -984,7 +992,7 @@ class CommandRegistry:
|
|
984
992
|
}
|
985
993
|
|
986
994
|
except Exception as e:
|
987
|
-
|
995
|
+
get_global_logger().warning(f"Failed to get info for command {command_name}: {e}")
|
988
996
|
return {
|
989
997
|
"name": command_name,
|
990
998
|
"error": str(e),
|
@@ -6,7 +6,7 @@ from typing import Dict, Any, Optional
|
|
6
6
|
|
7
7
|
from mcp_proxy_adapter.commands.base import Command
|
8
8
|
from mcp_proxy_adapter.commands.result import SuccessResult
|
9
|
-
from mcp_proxy_adapter.config import
|
9
|
+
from mcp_proxy_adapter.config import get_config
|
10
10
|
|
11
11
|
|
12
12
|
class ConfigResult(SuccessResult):
|
@@ -67,6 +67,7 @@ class ConfigCommand(Command):
|
|
67
67
|
result_config = {}
|
68
68
|
|
69
69
|
if operation == "get":
|
70
|
+
config_instance = get_config()
|
70
71
|
if path:
|
71
72
|
# Get specific config value
|
72
73
|
result_config = {path: config_instance.get(path)}
|
@@ -78,6 +79,7 @@ class ConfigCommand(Command):
|
|
78
79
|
elif operation == "set":
|
79
80
|
if path and value is not None:
|
80
81
|
# Set config value
|
82
|
+
config_instance = get_config()
|
81
83
|
config_instance.set(path, value)
|
82
84
|
# Save config
|
83
85
|
config_instance.save()
|
@@ -23,7 +23,7 @@ from packaging.requirements import Requirement
|
|
23
23
|
from packaging.specifiers import SpecifierSet
|
24
24
|
from packaging.version import Version, InvalidVersion
|
25
25
|
|
26
|
-
from mcp_proxy_adapter.core.logging import
|
26
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
27
27
|
|
28
28
|
|
29
29
|
class DependencyManager:
|
@@ -49,7 +49,7 @@ class DependencyManager:
|
|
49
49
|
except Exception:
|
50
50
|
continue
|
51
51
|
except Exception as e:
|
52
|
-
|
52
|
+
get_global_logger().warning(f"Failed to load installed packages: {e}")
|
53
53
|
|
54
54
|
def check_dependencies(
|
55
55
|
self, dependencies: List[str]
|
@@ -138,13 +138,13 @@ class DependencyManager:
|
|
138
138
|
try:
|
139
139
|
if self._install_single_dependency(dep, user_install):
|
140
140
|
installed_deps.append(dep)
|
141
|
-
|
141
|
+
get_global_logger().info(f"Successfully installed dependency: {dep}")
|
142
142
|
else:
|
143
143
|
failed_deps.append(dep)
|
144
|
-
|
144
|
+
get_global_logger().error(f"Failed to install dependency: {dep}")
|
145
145
|
except Exception as e:
|
146
146
|
failed_deps.append(dep)
|
147
|
-
|
147
|
+
get_global_logger().error(f"Error installing dependency {dep}: {e}")
|
148
148
|
|
149
149
|
success = len(failed_deps) == 0
|
150
150
|
|
@@ -180,7 +180,7 @@ class DependencyManager:
|
|
180
180
|
# Add dependency
|
181
181
|
cmd.append(dependency)
|
182
182
|
|
183
|
-
|
183
|
+
get_global_logger().debug(f"Installing dependency: {' '.join(cmd)}")
|
184
184
|
|
185
185
|
# Run pip install
|
186
186
|
result = subprocess.run(
|
@@ -188,17 +188,17 @@ class DependencyManager:
|
|
188
188
|
)
|
189
189
|
|
190
190
|
if result.returncode == 0:
|
191
|
-
|
191
|
+
get_global_logger().debug(f"Successfully installed {dependency}")
|
192
192
|
return True
|
193
193
|
else:
|
194
|
-
|
194
|
+
get_global_logger().error(f"Failed to install {dependency}: {result.stderr}")
|
195
195
|
return False
|
196
196
|
|
197
197
|
except subprocess.TimeoutExpired:
|
198
|
-
|
198
|
+
get_global_logger().error(f"Timeout while installing {dependency}")
|
199
199
|
return False
|
200
200
|
except Exception as e:
|
201
|
-
|
201
|
+
get_global_logger().error(f"Error installing {dependency}: {e}")
|
202
202
|
return False
|
203
203
|
|
204
204
|
def verify_installation(self, dependencies: List[str]) -> Tuple[bool, List[str]]:
|