mcp-proxy-adapter 6.9.28__py3-none-any.whl → 6.9.30__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 mcp-proxy-adapter might be problematic. Click here for more details.
- mcp_proxy_adapter/__init__.py +10 -0
- mcp_proxy_adapter/__main__.py +8 -21
- mcp_proxy_adapter/api/app.py +10 -913
- mcp_proxy_adapter/api/core/__init__.py +18 -0
- mcp_proxy_adapter/api/core/app_factory.py +243 -0
- mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
- mcp_proxy_adapter/api/core/registration_manager.py +166 -0
- mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
- mcp_proxy_adapter/api/handlers.py +78 -199
- mcp_proxy_adapter/api/middleware/__init__.py +1 -44
- mcp_proxy_adapter/api/middleware/base.py +0 -42
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +0 -85
- mcp_proxy_adapter/api/middleware/error_handling.py +1 -127
- mcp_proxy_adapter/api/middleware/factory.py +0 -94
- mcp_proxy_adapter/api/middleware/logging.py +0 -112
- mcp_proxy_adapter/api/middleware/performance.py +0 -35
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +2 -98
- mcp_proxy_adapter/api/middleware/transport_middleware.py +0 -37
- mcp_proxy_adapter/api/middleware/unified_security.py +10 -10
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +0 -118
- mcp_proxy_adapter/api/openapi/__init__.py +21 -0
- mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
- mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
- mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
- mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
- mcp_proxy_adapter/api/schemas.py +0 -61
- mcp_proxy_adapter/api/tool_integration.py +0 -117
- mcp_proxy_adapter/api/tools.py +0 -46
- mcp_proxy_adapter/cli/__init__.py +12 -0
- mcp_proxy_adapter/cli/commands/__init__.py +15 -0
- mcp_proxy_adapter/cli/commands/client.py +100 -0
- mcp_proxy_adapter/cli/commands/config_generate.py +21 -0
- mcp_proxy_adapter/cli/commands/config_validate.py +36 -0
- mcp_proxy_adapter/cli/commands/generate.py +259 -0
- mcp_proxy_adapter/cli/commands/server.py +174 -0
- mcp_proxy_adapter/cli/commands/sets.py +128 -0
- mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
- mcp_proxy_adapter/cli/examples/__init__.py +8 -0
- mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
- mcp_proxy_adapter/cli/examples/https_token.py +96 -0
- mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
- mcp_proxy_adapter/cli/main.py +63 -0
- mcp_proxy_adapter/cli/parser.py +324 -0
- mcp_proxy_adapter/cli/validators.py +231 -0
- mcp_proxy_adapter/client/jsonrpc_client.py +406 -0
- mcp_proxy_adapter/client/proxy.py +45 -0
- mcp_proxy_adapter/commands/__init__.py +44 -28
- mcp_proxy_adapter/commands/auth_validation_command.py +7 -344
- mcp_proxy_adapter/commands/base.py +19 -43
- mcp_proxy_adapter/commands/builtin_commands.py +0 -75
- mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
- mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
- mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
- mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
- mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
- mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
- mcp_proxy_adapter/commands/catalog_manager.py +58 -928
- mcp_proxy_adapter/commands/cert_monitor_command.py +0 -88
- mcp_proxy_adapter/commands/certificate_management_command.py +0 -45
- mcp_proxy_adapter/commands/command_registry.py +172 -904
- mcp_proxy_adapter/commands/config_command.py +0 -28
- mcp_proxy_adapter/commands/dependency_container.py +1 -70
- mcp_proxy_adapter/commands/dependency_manager.py +0 -128
- mcp_proxy_adapter/commands/echo_command.py +0 -34
- mcp_proxy_adapter/commands/health_command.py +0 -3
- mcp_proxy_adapter/commands/help_command.py +0 -159
- mcp_proxy_adapter/commands/hooks.py +0 -137
- mcp_proxy_adapter/commands/key_management_command.py +0 -25
- mcp_proxy_adapter/commands/load_command.py +7 -78
- mcp_proxy_adapter/commands/plugins_command.py +0 -16
- mcp_proxy_adapter/commands/protocol_management_command.py +0 -28
- mcp_proxy_adapter/commands/proxy_registration_command.py +0 -88
- mcp_proxy_adapter/commands/queue_commands.py +750 -0
- mcp_proxy_adapter/commands/registration_status_command.py +0 -43
- mcp_proxy_adapter/commands/registry/__init__.py +18 -0
- mcp_proxy_adapter/commands/registry/command_info.py +103 -0
- mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
- mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
- mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
- mcp_proxy_adapter/commands/reload_command.py +0 -80
- mcp_proxy_adapter/commands/result.py +25 -77
- mcp_proxy_adapter/commands/role_test_command.py +0 -44
- mcp_proxy_adapter/commands/roles_management_command.py +0 -199
- mcp_proxy_adapter/commands/security_command.py +0 -30
- mcp_proxy_adapter/commands/settings_command.py +0 -68
- mcp_proxy_adapter/commands/ssl_setup_command.py +0 -42
- mcp_proxy_adapter/commands/token_management_command.py +0 -1
- mcp_proxy_adapter/commands/transport_management_command.py +0 -20
- mcp_proxy_adapter/commands/unload_command.py +0 -71
- mcp_proxy_adapter/config.py +15 -626
- mcp_proxy_adapter/core/__init__.py +5 -39
- mcp_proxy_adapter/core/app_factory.py +14 -36
- mcp_proxy_adapter/core/app_runner.py +0 -27
- mcp_proxy_adapter/core/auth_validator.py +1 -93
- mcp_proxy_adapter/core/certificate/__init__.py +20 -0
- mcp_proxy_adapter/core/certificate/certificate_creator.py +371 -0
- mcp_proxy_adapter/core/certificate/certificate_extractor.py +183 -0
- mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
- mcp_proxy_adapter/core/certificate/certificate_validator.py +110 -0
- mcp_proxy_adapter/core/certificate/ssl_context_manager.py +70 -0
- mcp_proxy_adapter/core/certificate_utils.py +64 -903
- mcp_proxy_adapter/core/client.py +10 -9
- mcp_proxy_adapter/core/client_manager.py +0 -19
- mcp_proxy_adapter/core/client_security.py +0 -2
- mcp_proxy_adapter/core/config/__init__.py +18 -0
- mcp_proxy_adapter/core/config/config.py +195 -0
- mcp_proxy_adapter/core/config/config_factory.py +22 -0
- mcp_proxy_adapter/core/config/config_loader.py +66 -0
- mcp_proxy_adapter/core/config/feature_manager.py +31 -0
- mcp_proxy_adapter/core/config/simple_config.py +112 -0
- mcp_proxy_adapter/core/config/simple_config_generator.py +50 -0
- mcp_proxy_adapter/core/config/simple_config_validator.py +96 -0
- mcp_proxy_adapter/core/config_converter.py +0 -186
- mcp_proxy_adapter/core/config_validator.py +96 -1238
- mcp_proxy_adapter/core/errors.py +7 -42
- mcp_proxy_adapter/core/job_manager.py +54 -0
- mcp_proxy_adapter/core/logging.py +2 -22
- mcp_proxy_adapter/core/mtls_asgi.py +0 -20
- mcp_proxy_adapter/core/mtls_asgi_app.py +0 -12
- mcp_proxy_adapter/core/mtls_proxy.py +0 -80
- mcp_proxy_adapter/core/mtls_server.py +3 -173
- mcp_proxy_adapter/core/protocol_manager.py +1 -191
- mcp_proxy_adapter/core/proxy/__init__.py +22 -0
- mcp_proxy_adapter/core/proxy/auth_manager.py +27 -0
- mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +137 -0
- mcp_proxy_adapter/core/proxy/registration_client.py +60 -0
- mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
- mcp_proxy_adapter/core/proxy_client.py +0 -1
- mcp_proxy_adapter/core/proxy_registration.py +36 -913
- mcp_proxy_adapter/core/role_utils.py +0 -308
- mcp_proxy_adapter/core/security_adapter.py +1 -36
- mcp_proxy_adapter/core/security_factory.py +1 -150
- mcp_proxy_adapter/core/security_integration.py +0 -33
- mcp_proxy_adapter/core/server_adapter.py +1 -40
- mcp_proxy_adapter/core/server_engine.py +2 -173
- mcp_proxy_adapter/core/settings.py +0 -127
- mcp_proxy_adapter/core/signal_handler.py +0 -65
- mcp_proxy_adapter/core/ssl_utils.py +19 -137
- mcp_proxy_adapter/core/transport_manager.py +0 -151
- mcp_proxy_adapter/core/unified_config_adapter.py +1 -193
- mcp_proxy_adapter/core/utils.py +1 -182
- mcp_proxy_adapter/core/validation/__init__.py +21 -0
- mcp_proxy_adapter/core/validation/config_validator.py +211 -0
- mcp_proxy_adapter/core/validation/file_validator.py +73 -0
- mcp_proxy_adapter/core/validation/protocol_validator.py +191 -0
- mcp_proxy_adapter/core/validation/security_validator.py +58 -0
- mcp_proxy_adapter/core/validation/validation_result.py +27 -0
- mcp_proxy_adapter/custom_openapi.py +33 -652
- mcp_proxy_adapter/examples/bugfix_certificate_config.py +0 -23
- mcp_proxy_adapter/examples/check_config.py +0 -2
- mcp_proxy_adapter/examples/client_usage_example.py +164 -0
- mcp_proxy_adapter/examples/config_builder.py +13 -2
- mcp_proxy_adapter/examples/config_cli.py +0 -1
- mcp_proxy_adapter/examples/create_test_configs.py +0 -46
- mcp_proxy_adapter/examples/debug_request_state.py +0 -1
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +0 -47
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +0 -45
- mcp_proxy_adapter/examples/full_application/commands/echo_command.py +0 -12
- mcp_proxy_adapter/examples/full_application/commands/help_command.py +0 -12
- mcp_proxy_adapter/examples/full_application/commands/list_command.py +0 -7
- mcp_proxy_adapter/examples/full_application/hooks/__init__.py +0 -2
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +0 -59
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +0 -54
- mcp_proxy_adapter/examples/full_application/main.py +186 -150
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +0 -107
- mcp_proxy_adapter/examples/full_application/test_minimal_server.py +0 -24
- mcp_proxy_adapter/examples/full_application/test_server.py +0 -58
- mcp_proxy_adapter/examples/generate_config.py +65 -11
- mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
- mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
- mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
- mcp_proxy_adapter/examples/queue_server_example.py +85 -0
- mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
- mcp_proxy_adapter/examples/required_certificates.py +0 -2
- mcp_proxy_adapter/examples/run_full_test_suite.py +0 -29
- mcp_proxy_adapter/examples/run_proxy_server.py +31 -71
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +0 -27
- mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
- mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
- mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
- mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
- mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
- mcp_proxy_adapter/examples/security_test_client.py +24 -1075
- mcp_proxy_adapter/examples/setup/__init__.py +24 -0
- mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
- mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
- mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
- mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
- mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
- mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
- mcp_proxy_adapter/examples/setup_test_environment.py +133 -1425
- mcp_proxy_adapter/examples/test_config.py +0 -3
- mcp_proxy_adapter/examples/test_config_builder.py +25 -405
- mcp_proxy_adapter/examples/test_examples.py +0 -1
- mcp_proxy_adapter/examples/test_framework_complete.py +0 -2
- mcp_proxy_adapter/examples/test_mcp_server.py +0 -1
- mcp_proxy_adapter/examples/test_protocol_examples.py +0 -1
- mcp_proxy_adapter/examples/universal_client.py +0 -6
- mcp_proxy_adapter/examples/update_config_certificates.py +0 -1
- mcp_proxy_adapter/examples/validate_generator_compatibility.py +0 -1
- mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +0 -187
- mcp_proxy_adapter/integrations/__init__.py +25 -0
- mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
- mcp_proxy_adapter/main.py +70 -62
- mcp_proxy_adapter/openapi.py +0 -22
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.30.dist-info}/METADATA +2 -1
- mcp_proxy_adapter-6.9.30.dist-info/RECORD +235 -0
- {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.30.dist-info}/entry_points.txt +1 -1
- mcp_proxy_adapter-6.9.28.dist-info/RECORD +0 -149
- {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.30.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.30.dist-info}/top_level.txt +0 -0
|
@@ -100,31 +100,3 @@ class ConfigCommand(Command):
|
|
|
100
100
|
return ConfigResult(config=result_config, operation=operation, message=message)
|
|
101
101
|
|
|
102
102
|
@classmethod
|
|
103
|
-
def get_schema(cls) -> Dict[str, Any]:
|
|
104
|
-
"""
|
|
105
|
-
Returns JSON schema for command parameters validation.
|
|
106
|
-
|
|
107
|
-
Returns:
|
|
108
|
-
Dictionary with JSON schema.
|
|
109
|
-
"""
|
|
110
|
-
return {
|
|
111
|
-
"type": "object",
|
|
112
|
-
"properties": {
|
|
113
|
-
"operation": {
|
|
114
|
-
"type": "string",
|
|
115
|
-
"enum": ["get", "set"],
|
|
116
|
-
"default": "get",
|
|
117
|
-
"description": "Operation to perform (get or set)",
|
|
118
|
-
},
|
|
119
|
-
"path": {
|
|
120
|
-
"type": "string",
|
|
121
|
-
"description": "Configuration path in dot notation "
|
|
122
|
-
"(e.g. 'server.host')",
|
|
123
|
-
},
|
|
124
|
-
"value": {
|
|
125
|
-
"description": "Value to set (required for " "'set' operation)"
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
"required": ["operation"],
|
|
129
|
-
"additionalProperties": False,
|
|
130
|
-
}
|
|
@@ -5,7 +5,7 @@ This module provides a container for registering and resolving dependencies
|
|
|
5
5
|
for command instances in the microservice.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import TypeVar, Dict, Any, Callable, Optional
|
|
9
9
|
|
|
10
10
|
T = TypeVar("T")
|
|
11
11
|
|
|
@@ -24,67 +24,9 @@ class DependencyContainer:
|
|
|
24
24
|
self._factories: Dict[str, callable] = {}
|
|
25
25
|
self._singletons: Dict[str, Any] = {}
|
|
26
26
|
|
|
27
|
-
def register(self, name: str, instance: Any) -> None:
|
|
28
|
-
"""
|
|
29
|
-
Register a dependency instance with a given name.
|
|
30
27
|
|
|
31
|
-
Args:
|
|
32
|
-
name: The name to register the dependency under
|
|
33
|
-
instance: The dependency instance
|
|
34
|
-
"""
|
|
35
|
-
self._dependencies[name] = instance
|
|
36
28
|
|
|
37
|
-
def register_factory(self, name: str, factory: callable) -> None:
|
|
38
|
-
"""
|
|
39
|
-
Register a factory function that will be called to create the dependency.
|
|
40
29
|
|
|
41
|
-
Args:
|
|
42
|
-
name: The name to register the factory under
|
|
43
|
-
factory: A callable that creates the dependency
|
|
44
|
-
"""
|
|
45
|
-
self._factories[name] = factory
|
|
46
|
-
|
|
47
|
-
def register_singleton(self, name: str, factory: callable) -> None:
|
|
48
|
-
"""
|
|
49
|
-
Register a singleton factory that will create the instance only once.
|
|
50
|
-
|
|
51
|
-
Args:
|
|
52
|
-
name: The name to register the singleton under
|
|
53
|
-
factory: A callable that creates the singleton instance
|
|
54
|
-
"""
|
|
55
|
-
self._factories[name] = factory
|
|
56
|
-
# Mark as singleton but don't create until requested
|
|
57
|
-
self._singletons[name] = None
|
|
58
|
-
|
|
59
|
-
def get(self, name: str) -> Any:
|
|
60
|
-
"""
|
|
61
|
-
Get a dependency by name.
|
|
62
|
-
|
|
63
|
-
Args:
|
|
64
|
-
name: The name of the dependency to get
|
|
65
|
-
|
|
66
|
-
Returns:
|
|
67
|
-
The dependency instance
|
|
68
|
-
|
|
69
|
-
Raises:
|
|
70
|
-
KeyError: If the dependency is not registered
|
|
71
|
-
"""
|
|
72
|
-
# Check for direct instance
|
|
73
|
-
if name in self._dependencies:
|
|
74
|
-
return self._dependencies[name]
|
|
75
|
-
|
|
76
|
-
# Check for singleton
|
|
77
|
-
if name in self._singletons:
|
|
78
|
-
# Create singleton if doesn't exist
|
|
79
|
-
if self._singletons[name] is None:
|
|
80
|
-
self._singletons[name] = self._factories[name]()
|
|
81
|
-
return self._singletons[name]
|
|
82
|
-
|
|
83
|
-
# Check for factory
|
|
84
|
-
if name in self._factories:
|
|
85
|
-
return self._factories[name]()
|
|
86
|
-
|
|
87
|
-
raise KeyError(f"Dependency '{name}' not registered")
|
|
88
30
|
|
|
89
31
|
def clear(self) -> None:
|
|
90
32
|
"""Clear all registered dependencies."""
|
|
@@ -92,17 +34,6 @@ class DependencyContainer:
|
|
|
92
34
|
self._factories.clear()
|
|
93
35
|
self._singletons.clear()
|
|
94
36
|
|
|
95
|
-
def has(self, name: str) -> bool:
|
|
96
|
-
"""
|
|
97
|
-
Check if a dependency is registered.
|
|
98
|
-
|
|
99
|
-
Args:
|
|
100
|
-
name: The name of the dependency
|
|
101
|
-
|
|
102
|
-
Returns:
|
|
103
|
-
True if the dependency is registered, False otherwise
|
|
104
|
-
"""
|
|
105
|
-
return name in self._dependencies or name in self._factories
|
|
106
37
|
|
|
107
38
|
|
|
108
39
|
# Global dependency container instance
|
|
@@ -12,7 +12,6 @@ import subprocess
|
|
|
12
12
|
import sys
|
|
13
13
|
import importlib
|
|
14
14
|
from typing import List, Dict, Any, Tuple
|
|
15
|
-
from pathlib import Path
|
|
16
15
|
|
|
17
16
|
try: # Python 3.8+
|
|
18
17
|
from importlib import metadata as importlib_metadata # type: ignore
|
|
@@ -20,7 +19,6 @@ except Exception: # pragma: no cover - very old Python fallback
|
|
|
20
19
|
import importlib_metadata # type: ignore
|
|
21
20
|
|
|
22
21
|
from packaging.requirements import Requirement
|
|
23
|
-
from packaging.specifiers import SpecifierSet
|
|
24
22
|
from packaging.version import Version, InvalidVersion
|
|
25
23
|
|
|
26
24
|
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
@@ -51,32 +49,6 @@ class DependencyManager:
|
|
|
51
49
|
except Exception as e:
|
|
52
50
|
get_global_logger().warning(f"Failed to load installed packages: {e}")
|
|
53
51
|
|
|
54
|
-
def check_dependencies(
|
|
55
|
-
self, dependencies: List[str]
|
|
56
|
-
) -> Tuple[bool, List[str], List[str]]:
|
|
57
|
-
"""
|
|
58
|
-
Check if dependencies are satisfied.
|
|
59
|
-
|
|
60
|
-
Args:
|
|
61
|
-
dependencies: List of dependency names
|
|
62
|
-
|
|
63
|
-
Returns:
|
|
64
|
-
Tuple of (all_satisfied, missing_deps, installed_deps)
|
|
65
|
-
"""
|
|
66
|
-
if not dependencies:
|
|
67
|
-
return True, [], []
|
|
68
|
-
|
|
69
|
-
missing_deps = []
|
|
70
|
-
installed_deps = []
|
|
71
|
-
|
|
72
|
-
for dep in dependencies:
|
|
73
|
-
if self._is_dependency_satisfied(dep):
|
|
74
|
-
installed_deps.append(dep)
|
|
75
|
-
else:
|
|
76
|
-
missing_deps.append(dep)
|
|
77
|
-
|
|
78
|
-
all_satisfied = len(missing_deps) == 0
|
|
79
|
-
return all_satisfied, missing_deps, installed_deps
|
|
80
52
|
|
|
81
53
|
def _is_dependency_satisfied(self, dependency: str) -> bool:
|
|
82
54
|
"""
|
|
@@ -115,44 +87,6 @@ class DependencyManager:
|
|
|
115
87
|
# If version parsing fails, fallback to string comparison via specifier
|
|
116
88
|
return req.specifier.contains(installed_version, prereleases=True)
|
|
117
89
|
|
|
118
|
-
def install_dependencies(
|
|
119
|
-
self, dependencies: List[str], user_install: bool = False
|
|
120
|
-
) -> Tuple[bool, List[str], List[str]]:
|
|
121
|
-
"""
|
|
122
|
-
Install dependencies using pip.
|
|
123
|
-
|
|
124
|
-
Args:
|
|
125
|
-
dependencies: List of dependency names to install
|
|
126
|
-
user_install: Whether to install for current user only
|
|
127
|
-
|
|
128
|
-
Returns:
|
|
129
|
-
Tuple of (success, installed_deps, failed_deps)
|
|
130
|
-
"""
|
|
131
|
-
if not dependencies:
|
|
132
|
-
return True, [], []
|
|
133
|
-
|
|
134
|
-
installed_deps = []
|
|
135
|
-
failed_deps = []
|
|
136
|
-
|
|
137
|
-
for dep in dependencies:
|
|
138
|
-
try:
|
|
139
|
-
if self._install_single_dependency(dep, user_install):
|
|
140
|
-
installed_deps.append(dep)
|
|
141
|
-
get_global_logger().info(f"Successfully installed dependency: {dep}")
|
|
142
|
-
else:
|
|
143
|
-
failed_deps.append(dep)
|
|
144
|
-
get_global_logger().error(f"Failed to install dependency: {dep}")
|
|
145
|
-
except Exception as e:
|
|
146
|
-
failed_deps.append(dep)
|
|
147
|
-
get_global_logger().error(f"Error installing dependency {dep}: {e}")
|
|
148
|
-
|
|
149
|
-
success = len(failed_deps) == 0
|
|
150
|
-
|
|
151
|
-
# Reload installed packages cache
|
|
152
|
-
if success:
|
|
153
|
-
self._load_installed_packages()
|
|
154
|
-
|
|
155
|
-
return success, installed_deps, failed_deps
|
|
156
90
|
|
|
157
91
|
def _install_single_dependency(
|
|
158
92
|
self, dependency: str, user_install: bool = False
|
|
@@ -201,70 +135,8 @@ class DependencyManager:
|
|
|
201
135
|
get_global_logger().error(f"Error installing {dependency}: {e}")
|
|
202
136
|
return False
|
|
203
137
|
|
|
204
|
-
def verify_installation(self, dependencies: List[str]) -> Tuple[bool, List[str]]:
|
|
205
|
-
"""
|
|
206
|
-
Verify that dependencies are properly installed.
|
|
207
138
|
|
|
208
|
-
Args:
|
|
209
|
-
dependencies: List of dependencies to verify
|
|
210
|
-
|
|
211
|
-
Returns:
|
|
212
|
-
Tuple of (all_verified, failed_verifications)
|
|
213
|
-
"""
|
|
214
|
-
if not dependencies:
|
|
215
|
-
return True, []
|
|
216
|
-
|
|
217
|
-
failed_verifications = []
|
|
218
|
-
|
|
219
|
-
for dep in dependencies:
|
|
220
|
-
if not self._is_dependency_satisfied(dep):
|
|
221
|
-
failed_verifications.append(dep)
|
|
222
139
|
|
|
223
|
-
all_verified = len(failed_verifications) == 0
|
|
224
|
-
return all_verified, failed_verifications
|
|
225
|
-
|
|
226
|
-
def get_dependency_info(self, dependency: str) -> Dict[str, Any]:
|
|
227
|
-
"""
|
|
228
|
-
Get information about a dependency.
|
|
229
|
-
|
|
230
|
-
Args:
|
|
231
|
-
dependency: Dependency name
|
|
232
|
-
|
|
233
|
-
Returns:
|
|
234
|
-
Dictionary with dependency information
|
|
235
|
-
"""
|
|
236
|
-
info: Dict[str, Any] = {
|
|
237
|
-
"name": dependency,
|
|
238
|
-
"installed": False,
|
|
239
|
-
"version": None,
|
|
240
|
-
"importable": False,
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
# Check if it's installed
|
|
244
|
-
try:
|
|
245
|
-
version = importlib_metadata.version(dependency)
|
|
246
|
-
info["installed"] = True
|
|
247
|
-
info["version"] = version
|
|
248
|
-
except importlib_metadata.PackageNotFoundError:
|
|
249
|
-
pass
|
|
250
|
-
|
|
251
|
-
# Check if it's importable
|
|
252
|
-
try:
|
|
253
|
-
importlib.import_module(dependency)
|
|
254
|
-
info["importable"] = True
|
|
255
|
-
except ImportError:
|
|
256
|
-
pass
|
|
257
|
-
|
|
258
|
-
return info
|
|
259
|
-
|
|
260
|
-
def list_installed_dependencies(self) -> Dict[str, str]:
|
|
261
|
-
"""
|
|
262
|
-
Get list of all installed packages.
|
|
263
|
-
|
|
264
|
-
Returns:
|
|
265
|
-
Dictionary mapping package names to versions
|
|
266
|
-
"""
|
|
267
|
-
return self._installed_packages.copy()
|
|
268
140
|
|
|
269
141
|
|
|
270
142
|
# Global instance
|
|
@@ -22,23 +22,6 @@ class EchoCommandResult(SuccessResult):
|
|
|
22
22
|
super().__init__(data=data, message=message)
|
|
23
23
|
|
|
24
24
|
@classmethod
|
|
25
|
-
def get_schema(cls) -> Dict[str, Any]:
|
|
26
|
-
"""Get JSON schema for result."""
|
|
27
|
-
return {
|
|
28
|
-
"type": "object",
|
|
29
|
-
"properties": {
|
|
30
|
-
"success": {"type": "boolean"},
|
|
31
|
-
"data": {
|
|
32
|
-
"type": "object",
|
|
33
|
-
"properties": {
|
|
34
|
-
"message": {"type": "string"},
|
|
35
|
-
"timestamp": {"type": "string", "nullable": True},
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
"message": {"type": "string"},
|
|
39
|
-
},
|
|
40
|
-
"required": ["success", "data"],
|
|
41
|
-
}
|
|
42
25
|
|
|
43
26
|
|
|
44
27
|
class EchoCommand(Command):
|
|
@@ -63,20 +46,3 @@ class EchoCommand(Command):
|
|
|
63
46
|
return EchoCommandResult(message=message, timestamp=timestamp)
|
|
64
47
|
|
|
65
48
|
@classmethod
|
|
66
|
-
def get_schema(cls) -> Dict[str, Any]:
|
|
67
|
-
"""Get command schema."""
|
|
68
|
-
return {
|
|
69
|
-
"type": "object",
|
|
70
|
-
"properties": {
|
|
71
|
-
"message": {
|
|
72
|
-
"type": "string",
|
|
73
|
-
"description": "Message to echo",
|
|
74
|
-
"default": "Hello, World!",
|
|
75
|
-
},
|
|
76
|
-
"timestamp": {
|
|
77
|
-
"type": "string",
|
|
78
|
-
"description": "Optional timestamp",
|
|
79
|
-
"nullable": True,
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
}
|
|
@@ -7,10 +7,8 @@ import platform
|
|
|
7
7
|
import sys
|
|
8
8
|
import psutil
|
|
9
9
|
from datetime import datetime
|
|
10
|
-
from typing import Dict, Any, Optional
|
|
11
10
|
|
|
12
11
|
from mcp_proxy_adapter.commands.base import Command
|
|
13
|
-
from mcp_proxy_adapter.commands.result import CommandResult, SuccessResult
|
|
14
12
|
from mcp_proxy_adapter.commands.command_registry import registry
|
|
15
13
|
from mcp_proxy_adapter.core.proxy_registration import get_proxy_registration_status
|
|
16
14
|
|
|
@@ -91,7 +89,6 @@ class HealthCommand(Command):
|
|
|
91
89
|
"""
|
|
92
90
|
# Get version from package
|
|
93
91
|
try:
|
|
94
|
-
from mcp_proxy_adapter.version import __version__ as version
|
|
95
92
|
except ImportError:
|
|
96
93
|
version = "unknown"
|
|
97
94
|
|
|
@@ -39,150 +39,8 @@ class HelpResult(CommandResult):
|
|
|
39
39
|
self.commands_info = commands_info
|
|
40
40
|
self.command_info = command_info
|
|
41
41
|
|
|
42
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
43
|
-
"""
|
|
44
|
-
Convert result to dictionary.
|
|
45
|
-
|
|
46
|
-
Returns:
|
|
47
|
-
Dict[str, Any]: Result as dictionary
|
|
48
|
-
"""
|
|
49
|
-
try:
|
|
50
|
-
get_global_logger().debug(
|
|
51
|
-
f"HelpResult.to_dict: command_info={self.command_info is not None}, commands_info={self.commands_info is not None}"
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
# Защита от None для self.command_info
|
|
55
|
-
if self.command_info is not None:
|
|
56
|
-
get_global_logger().debug(
|
|
57
|
-
f"HelpResult.to_dict: returning command_info for {self.command_info.get('name', 'unknown')}"
|
|
58
|
-
)
|
|
59
|
-
# Делаем безопасное получение всех полей с дефолтными значениями
|
|
60
|
-
metadata = self.command_info.get("metadata", {})
|
|
61
|
-
schema = self.command_info.get("schema", {})
|
|
62
|
-
return {
|
|
63
|
-
"cmdname": self.command_info.get("name", "unknown"),
|
|
64
|
-
"info": {
|
|
65
|
-
"description": metadata.get("description", ""),
|
|
66
|
-
"summary": metadata.get("summary", ""),
|
|
67
|
-
"params": schema.get("properties", {}),
|
|
68
|
-
"examples": metadata.get("examples", []),
|
|
69
|
-
},
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
# Защита от None для self.commands_info
|
|
73
|
-
if self.commands_info is None:
|
|
74
|
-
get_global_logger().warning(
|
|
75
|
-
"HelpResult.to_dict: commands_info is None, создаем пустой результат"
|
|
76
|
-
)
|
|
77
|
-
# Возвращаем пустой список команд вместо ошибки
|
|
78
|
-
return {
|
|
79
|
-
"tool_info": {
|
|
80
|
-
"name": "MCP-Proxy API Service",
|
|
81
|
-
"description": "JSON-RPC API for microservice command execution",
|
|
82
|
-
"version": "1.0.0",
|
|
83
|
-
},
|
|
84
|
-
"help_usage": {
|
|
85
|
-
"description": "Get information about commands",
|
|
86
|
-
"examples": [
|
|
87
|
-
{
|
|
88
|
-
"command": "help",
|
|
89
|
-
"description": "List of all available commands",
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
"command": "help",
|
|
93
|
-
"params": {"cmdname": "command_name"},
|
|
94
|
-
"description": "Get detailed information about a specific command",
|
|
95
|
-
},
|
|
96
|
-
],
|
|
97
|
-
},
|
|
98
|
-
"commands": {},
|
|
99
|
-
"total": 0,
|
|
100
|
-
"note": 'To get detailed information about a specific command, call help with parameter: POST /cmd {"command": "help", "params": {"cmdname": "<command_name>"}}',
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
# For list of all commands, return as is (already formatted)
|
|
104
|
-
get_global_logger().debug(
|
|
105
|
-
f"HelpResult.to_dict: processing commands_info with {len(self.commands_info.get('commands', {}))} commands"
|
|
106
|
-
)
|
|
107
|
-
result = self.commands_info.copy()
|
|
108
|
-
|
|
109
|
-
# Add total count and note about usage
|
|
110
|
-
commands = result.get("commands", {})
|
|
111
|
-
result["total"] = len(commands)
|
|
112
|
-
result["note"] = (
|
|
113
|
-
'To get detailed information about a specific command, call help with parameter: POST /cmd {"command": "help", "params": {"cmdname": "<command_name>"}}'
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
get_global_logger().debug(
|
|
117
|
-
f"HelpResult.to_dict: returning result with {result['total']} commands"
|
|
118
|
-
)
|
|
119
|
-
return result
|
|
120
|
-
except Exception as e:
|
|
121
|
-
get_global_logger().error(f"Ошибка в HelpResult.to_dict: {e}")
|
|
122
|
-
get_global_logger().debug(f"Трассировка: {traceback.format_exc()}")
|
|
123
|
-
# В случае неожиданной ошибки возвращаем базовый ответ вместо ошибки
|
|
124
|
-
return {
|
|
125
|
-
"tool_info": {
|
|
126
|
-
"name": "MCP-Proxy API Service",
|
|
127
|
-
"description": "JSON-RPC API for microservice command execution",
|
|
128
|
-
"version": "1.0.0",
|
|
129
|
-
},
|
|
130
|
-
"commands": {},
|
|
131
|
-
"total": 0,
|
|
132
|
-
"error": str(e),
|
|
133
|
-
}
|
|
134
42
|
|
|
135
43
|
@classmethod
|
|
136
|
-
def get_schema(cls) -> Dict[str, Any]:
|
|
137
|
-
"""
|
|
138
|
-
Get JSON schema for result validation.
|
|
139
|
-
|
|
140
|
-
Returns:
|
|
141
|
-
Dict[str, Any]: JSON schema
|
|
142
|
-
"""
|
|
143
|
-
return {
|
|
144
|
-
"type": "object",
|
|
145
|
-
"oneOf": [
|
|
146
|
-
{
|
|
147
|
-
"properties": {
|
|
148
|
-
"commands": {
|
|
149
|
-
"type": "object",
|
|
150
|
-
"additionalProperties": {
|
|
151
|
-
"type": "object",
|
|
152
|
-
"properties": {"description": {"type": "string"}},
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
"tool_info": {
|
|
156
|
-
"type": "object",
|
|
157
|
-
"properties": {
|
|
158
|
-
"name": {"type": "string"},
|
|
159
|
-
"description": {"type": "string"},
|
|
160
|
-
"version": {"type": "string"},
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
"help_usage": {"type": "object"},
|
|
164
|
-
"total": {"type": "integer"},
|
|
165
|
-
"note": {"type": "string"},
|
|
166
|
-
},
|
|
167
|
-
"required": ["commands"],
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
"properties": {
|
|
171
|
-
"cmdname": {"type": "string"},
|
|
172
|
-
"info": {
|
|
173
|
-
"type": "object",
|
|
174
|
-
"properties": {
|
|
175
|
-
"description": {"type": "string"},
|
|
176
|
-
"summary": {"type": "string"},
|
|
177
|
-
"params": {"type": "object"},
|
|
178
|
-
"examples": {"type": "array"},
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
},
|
|
182
|
-
"required": ["cmdname", "info"],
|
|
183
|
-
},
|
|
184
|
-
],
|
|
185
|
-
}
|
|
186
44
|
|
|
187
45
|
|
|
188
46
|
class HelpCommand(Command):
|
|
@@ -315,20 +173,3 @@ class HelpCommand(Command):
|
|
|
315
173
|
)
|
|
316
174
|
|
|
317
175
|
@classmethod
|
|
318
|
-
def get_schema(cls) -> Dict[str, Any]:
|
|
319
|
-
"""
|
|
320
|
-
Get JSON schema for command parameters validation.
|
|
321
|
-
|
|
322
|
-
Returns:
|
|
323
|
-
Dict[str, Any]: JSON schema
|
|
324
|
-
"""
|
|
325
|
-
return {
|
|
326
|
-
"type": "object",
|
|
327
|
-
"properties": {
|
|
328
|
-
"cmdname": {
|
|
329
|
-
"type": "string",
|
|
330
|
-
"description": "Name of command to get information about",
|
|
331
|
-
}
|
|
332
|
-
},
|
|
333
|
-
"additionalProperties": False,
|
|
334
|
-
}
|
|
@@ -5,7 +5,6 @@ This module provides a hook system for registering custom commands
|
|
|
5
5
|
that will be called during system initialization.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from typing import Callable, List, Optional, Dict, Any, Union
|
|
9
8
|
from enum import Enum
|
|
10
9
|
from dataclasses import dataclass
|
|
11
10
|
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
@@ -109,147 +108,11 @@ class CommandHooks:
|
|
|
109
108
|
self._after_command_hooks.append(hook_func)
|
|
110
109
|
get_global_logger().debug(f"Registered after command hook: {hook_func.__name__}")
|
|
111
110
|
|
|
112
|
-
def execute_custom_commands_hooks(self, registry) -> int:
|
|
113
|
-
"""
|
|
114
|
-
Execute all registered custom commands hooks.
|
|
115
|
-
|
|
116
|
-
Args:
|
|
117
|
-
registry: Command registry instance.
|
|
118
|
-
|
|
119
|
-
Returns:
|
|
120
|
-
Number of hooks executed.
|
|
121
|
-
"""
|
|
122
|
-
get_global_logger().debug("Executing custom commands hooks...")
|
|
123
|
-
hooks_executed = 0
|
|
124
|
-
|
|
125
|
-
for hook_func in self._custom_commands_hooks:
|
|
126
|
-
try:
|
|
127
|
-
hook_func(registry)
|
|
128
|
-
hooks_executed += 1
|
|
129
|
-
get_global_logger().debug(f"Executed custom commands hook: {hook_func.__name__}")
|
|
130
|
-
except Exception as e:
|
|
131
|
-
get_global_logger().error(
|
|
132
|
-
f"Failed to execute custom commands hook {hook_func.__name__}: {e}"
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
get_global_logger().info(f"Executed {hooks_executed} custom commands hooks")
|
|
136
|
-
return hooks_executed
|
|
137
|
-
|
|
138
|
-
def execute_before_init_hooks(self) -> int:
|
|
139
|
-
"""
|
|
140
|
-
Execute all registered before initialization hooks.
|
|
141
|
-
|
|
142
|
-
Returns:
|
|
143
|
-
Number of hooks executed.
|
|
144
|
-
"""
|
|
145
|
-
get_global_logger().debug("Executing before init hooks...")
|
|
146
|
-
hooks_executed = 0
|
|
147
|
-
|
|
148
|
-
for hook_func in self._before_init_hooks:
|
|
149
|
-
try:
|
|
150
|
-
hook_func()
|
|
151
|
-
hooks_executed += 1
|
|
152
|
-
get_global_logger().debug(f"Executed before init hook: {hook_func.__name__}")
|
|
153
|
-
except Exception as e:
|
|
154
|
-
get_global_logger().error(
|
|
155
|
-
f"Failed to execute before init hook {hook_func.__name__}: {e}"
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
get_global_logger().debug(f"Executed {hooks_executed} before init hooks")
|
|
159
|
-
return hooks_executed
|
|
160
|
-
|
|
161
|
-
def execute_after_init_hooks(self) -> int:
|
|
162
|
-
"""
|
|
163
|
-
Execute all registered after initialization hooks.
|
|
164
111
|
|
|
165
|
-
Returns:
|
|
166
|
-
Number of hooks executed.
|
|
167
|
-
"""
|
|
168
|
-
get_global_logger().debug("Executing after init hooks...")
|
|
169
|
-
hooks_executed = 0
|
|
170
|
-
|
|
171
|
-
for hook_func in self._after_init_hooks:
|
|
172
|
-
try:
|
|
173
|
-
hook_func()
|
|
174
|
-
hooks_executed += 1
|
|
175
|
-
get_global_logger().debug(f"Executed after init hook: {hook_func.__name__}")
|
|
176
|
-
except Exception as e:
|
|
177
|
-
get_global_logger().error(
|
|
178
|
-
f"Failed to execute after init hook {hook_func.__name__}: {e}"
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
get_global_logger().debug(f"Executed {hooks_executed} after init hooks")
|
|
182
|
-
return hooks_executed
|
|
183
|
-
|
|
184
|
-
def execute_before_command_hooks(
|
|
185
|
-
self, command_name: str, params: Dict[str, Any]
|
|
186
|
-
) -> int:
|
|
187
|
-
"""
|
|
188
|
-
Execute all registered before command execution hooks.
|
|
189
112
|
|
|
190
|
-
Args:
|
|
191
|
-
command_name: Name of the command being executed
|
|
192
|
-
params: Command parameters
|
|
193
113
|
|
|
194
|
-
Returns:
|
|
195
|
-
Number of hooks executed.
|
|
196
|
-
"""
|
|
197
|
-
get_global_logger().debug(f"Executing before command hooks for: {command_name}")
|
|
198
|
-
hooks_executed = 0
|
|
199
|
-
|
|
200
|
-
for hook_func in self._before_command_hooks:
|
|
201
|
-
try:
|
|
202
|
-
hook_func(command_name, params)
|
|
203
|
-
hooks_executed += 1
|
|
204
|
-
get_global_logger().debug(f"Executed before command hook: {hook_func.__name__}")
|
|
205
|
-
except Exception as e:
|
|
206
|
-
get_global_logger().error(
|
|
207
|
-
f"Failed to execute before command hook {hook_func.__name__}: {e}"
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
get_global_logger().debug(f"Executed {hooks_executed} before command hooks")
|
|
211
|
-
return hooks_executed
|
|
212
|
-
|
|
213
|
-
def execute_after_command_hooks(
|
|
214
|
-
self, command_name: str, params: Dict[str, Any], result: Any
|
|
215
|
-
) -> int:
|
|
216
|
-
"""
|
|
217
|
-
Execute all registered after command execution hooks.
|
|
218
114
|
|
|
219
|
-
Args:
|
|
220
|
-
command_name: Name of the command that was executed
|
|
221
|
-
params: Command parameters that were used
|
|
222
|
-
result: Command execution result
|
|
223
115
|
|
|
224
|
-
Returns:
|
|
225
|
-
Number of hooks executed.
|
|
226
|
-
"""
|
|
227
|
-
get_global_logger().debug(f"Executing after command hooks for: {command_name}")
|
|
228
|
-
hooks_executed = 0
|
|
229
|
-
|
|
230
|
-
for hook_func in self._after_command_hooks:
|
|
231
|
-
try:
|
|
232
|
-
hook_func(command_name, params, result)
|
|
233
|
-
hooks_executed += 1
|
|
234
|
-
get_global_logger().debug(f"Executed after command hook: {hook_func.__name__}")
|
|
235
|
-
except Exception as e:
|
|
236
|
-
get_global_logger().error(
|
|
237
|
-
f"Failed to execute after command hook {hook_func.__name__}: {e}"
|
|
238
|
-
)
|
|
239
|
-
|
|
240
|
-
get_global_logger().debug(f"Executed {hooks_executed} after command hooks")
|
|
241
|
-
return hooks_executed
|
|
242
|
-
|
|
243
|
-
def clear_hooks(self) -> None:
|
|
244
|
-
"""
|
|
245
|
-
Clear all registered hooks.
|
|
246
|
-
"""
|
|
247
|
-
self._custom_commands_hooks.clear()
|
|
248
|
-
self._before_init_hooks.clear()
|
|
249
|
-
self._after_init_hooks.clear()
|
|
250
|
-
self._before_command_hooks.clear()
|
|
251
|
-
self._after_command_hooks.clear()
|
|
252
|
-
get_global_logger().debug("Cleared all hooks")
|
|
253
116
|
|
|
254
117
|
|
|
255
118
|
# Global hooks instance
|