mcp-proxy-adapter 6.9.28__py3-none-any.whl → 6.9.29__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 +0 -6
- 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.29.dist-info}/METADATA +2 -1
- mcp_proxy_adapter-6.9.29.dist-info/RECORD +235 -0
- {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.29.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.29.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.29.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: Vasiliy Zdanovskiy
|
|
3
|
+
email: vasilyvz@gmail.com
|
|
4
|
+
|
|
5
|
+
Main command registry for MCP Proxy Adapter.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
from mcp_proxy_adapter.commands.base import Command
|
|
10
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
11
|
+
from .command_loader import CommandLoader
|
|
12
|
+
from .command_manager import CommandManager
|
|
13
|
+
from .command_info import CommandInfo
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CommandRegistry:
|
|
17
|
+
"""
|
|
18
|
+
Registry for registering and finding commands.
|
|
19
|
+
|
|
20
|
+
Supports three types of commands:
|
|
21
|
+
- Builtin: Core commands that come with the framework
|
|
22
|
+
- Custom: User-defined commands
|
|
23
|
+
- Loaded: Commands loaded from external sources
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self):
|
|
27
|
+
"""Initialize command registry."""
|
|
28
|
+
self.logger = get_global_logger()
|
|
29
|
+
|
|
30
|
+
# Command storage
|
|
31
|
+
self._commands: Dict[str, Type[Command]] = {}
|
|
32
|
+
self._instances: Dict[str, Command] = {}
|
|
33
|
+
self._command_types: Dict[str, str] = {} # "builtin", "custom", "loaded"
|
|
34
|
+
|
|
35
|
+
# Initialize components
|
|
36
|
+
self._loader = CommandLoader()
|
|
37
|
+
self._manager = CommandManager()
|
|
38
|
+
self._info = CommandInfo()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def register_loaded(self, command: Union[Type[Command], Command]) -> None:
|
|
43
|
+
"""
|
|
44
|
+
Register a loaded command.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
command: Command class or instance to register
|
|
48
|
+
"""
|
|
49
|
+
self._register_command(command, "loaded")
|
|
50
|
+
|
|
51
|
+
def _register_command(self, command: Union[Type[Command], Command], cmd_type: str) -> None:
|
|
52
|
+
"""
|
|
53
|
+
Register a command.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
command: Command class or instance to register
|
|
57
|
+
cmd_type: Type of command ("builtin", "custom", "loaded")
|
|
58
|
+
"""
|
|
59
|
+
if isinstance(command, Command):
|
|
60
|
+
# Register instance
|
|
61
|
+
command_name = self._manager._get_command_name(command.__class__)
|
|
62
|
+
self._instances[command_name] = command
|
|
63
|
+
self._commands[command_name] = command.__class__
|
|
64
|
+
else:
|
|
65
|
+
# Register class
|
|
66
|
+
command_name = self._manager._get_command_name(command)
|
|
67
|
+
self._commands[command_name] = command
|
|
68
|
+
|
|
69
|
+
self._command_types[command_name] = cmd_type
|
|
70
|
+
self.logger.info(f"Registered {cmd_type} command: {command_name}")
|
|
71
|
+
|
|
72
|
+
def load_command_from_source(self, source: str) -> Dict[str, Any]:
|
|
73
|
+
"""
|
|
74
|
+
Load command from source.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
source: Source string - local path, URL, or command name from registry
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Dictionary with loading result information
|
|
81
|
+
"""
|
|
82
|
+
result = self._loader.load_command_from_source(source)
|
|
83
|
+
|
|
84
|
+
if result["success"]:
|
|
85
|
+
# Register loaded commands
|
|
86
|
+
for command_class in result["commands"]:
|
|
87
|
+
self.register_loaded(command_class)
|
|
88
|
+
|
|
89
|
+
return result
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def command_exists(self, command_name: str) -> bool:
|
|
93
|
+
"""
|
|
94
|
+
Check if command exists.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
command_name: Name of the command
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
True if command exists, False otherwise
|
|
101
|
+
"""
|
|
102
|
+
return self._manager.command_exists(command_name, self._commands)
|
|
103
|
+
|
|
104
|
+
def get_command(self, command_name: str) -> Type[Command]:
|
|
105
|
+
"""
|
|
106
|
+
Get command class by name.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
command_name: Name of the command
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Command class
|
|
113
|
+
|
|
114
|
+
Raises:
|
|
115
|
+
NotFoundError: If command not found
|
|
116
|
+
"""
|
|
117
|
+
return self._manager.get_command(command_name, self._commands)
|
|
118
|
+
|
|
119
|
+
def get_command_instance(self, command_name: str) -> Command:
|
|
120
|
+
"""
|
|
121
|
+
Get command instance by name.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
command_name: Name of the command
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
Command instance
|
|
128
|
+
|
|
129
|
+
Raises:
|
|
130
|
+
NotFoundError: If command not found
|
|
131
|
+
"""
|
|
132
|
+
return self._manager.get_command_instance(command_name, self._commands, self._instances)
|
|
133
|
+
|
|
134
|
+
def has_instance(self, command_name: str) -> bool:
|
|
135
|
+
"""
|
|
136
|
+
Check if command has instance.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
command_name: Name of the command
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
True if command has instance, False otherwise
|
|
143
|
+
"""
|
|
144
|
+
return self._manager.has_instance(command_name, self._instances)
|
|
145
|
+
|
|
146
|
+
def get_all_commands(self) -> Dict[str, Type[Command]]:
|
|
147
|
+
"""
|
|
148
|
+
Get all registered commands.
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
Dictionary of all commands
|
|
152
|
+
"""
|
|
153
|
+
return self._manager.get_all_commands(self._commands)
|
|
154
|
+
|
|
155
|
+
def get_commands_by_type(self) -> Dict[str, Dict[str, Type[Command]]]:
|
|
156
|
+
"""
|
|
157
|
+
Get commands grouped by type.
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
Dictionary of commands grouped by type
|
|
161
|
+
"""
|
|
162
|
+
return self._manager.get_commands_by_type(self._commands, self._command_types)
|
|
163
|
+
|
|
164
|
+
def get_all_metadata(self) -> Dict[str, Dict[str, Any]]:
|
|
165
|
+
"""
|
|
166
|
+
Get metadata for all commands.
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
Dictionary of command metadata
|
|
170
|
+
"""
|
|
171
|
+
return self._manager.get_all_metadata(self._commands, self._command_types)
|
|
172
|
+
|
|
173
|
+
def clear(self) -> None:
|
|
174
|
+
"""Clear all commands and instances."""
|
|
175
|
+
self._manager.clear(self._commands, self._instances, self._command_types)
|
|
176
|
+
self.logger.info("Cleared all commands")
|
|
177
|
+
|
|
178
|
+
def get_all_commands_info(self) -> Dict[str, Any]:
|
|
179
|
+
"""
|
|
180
|
+
Get comprehensive information about all commands.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Dictionary with command information
|
|
184
|
+
"""
|
|
185
|
+
return self._info.get_all_commands_info(self._commands, self._command_types)
|
|
186
|
+
|
|
187
|
+
def get_command_info(self, command_name: str) -> Optional[Dict[str, Any]]:
|
|
188
|
+
"""
|
|
189
|
+
Get detailed information about a specific command.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
command_name: Name of the command
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
Dictionary with command information or None if not found
|
|
196
|
+
"""
|
|
197
|
+
if command_name not in self._commands:
|
|
198
|
+
return None
|
|
199
|
+
|
|
200
|
+
return self._info.get_command_info(
|
|
201
|
+
command_name,
|
|
202
|
+
self._commands[command_name],
|
|
203
|
+
self._command_types
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
def _load_all_commands(self) -> Dict[str, int]:
|
|
207
|
+
"""
|
|
208
|
+
Load all commands from configured directories.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
Dictionary with loading statistics
|
|
212
|
+
"""
|
|
213
|
+
return self._manager._load_all_commands(self._commands, self._command_types)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
# Global registry instance
|
|
217
|
+
registry = CommandRegistry()
|
|
@@ -73,68 +73,6 @@ class ReloadResult:
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
@classmethod
|
|
76
|
-
def get_schema(cls) -> Dict[str, Any]:
|
|
77
|
-
"""
|
|
78
|
-
Get JSON schema for the result.
|
|
79
|
-
|
|
80
|
-
Returns:
|
|
81
|
-
JSON schema dictionary.
|
|
82
|
-
"""
|
|
83
|
-
return {
|
|
84
|
-
"type": "object",
|
|
85
|
-
"properties": {
|
|
86
|
-
"success": {
|
|
87
|
-
"type": "boolean",
|
|
88
|
-
"description": "Whether reload was successful",
|
|
89
|
-
},
|
|
90
|
-
"config_reloaded": {
|
|
91
|
-
"type": "boolean",
|
|
92
|
-
"description": "Whether configuration was reloaded successfully",
|
|
93
|
-
},
|
|
94
|
-
"builtin_commands": {
|
|
95
|
-
"type": "integer",
|
|
96
|
-
"description": "Number of built-in commands registered",
|
|
97
|
-
},
|
|
98
|
-
"custom_commands": {
|
|
99
|
-
"type": "integer",
|
|
100
|
-
"description": "Number of custom commands registered",
|
|
101
|
-
},
|
|
102
|
-
"loaded_commands": {
|
|
103
|
-
"type": "integer",
|
|
104
|
-
"description": "Number of commands loaded from directory",
|
|
105
|
-
},
|
|
106
|
-
"remote_commands": {
|
|
107
|
-
"type": "integer",
|
|
108
|
-
"description": "Number of commands loaded from remote plugins",
|
|
109
|
-
},
|
|
110
|
-
"total_commands": {
|
|
111
|
-
"type": "integer",
|
|
112
|
-
"description": "Total number of commands after reload",
|
|
113
|
-
},
|
|
114
|
-
"server_restart_required": {
|
|
115
|
-
"type": "boolean",
|
|
116
|
-
"description": "Whether server restart is required to apply changes",
|
|
117
|
-
},
|
|
118
|
-
"message": {
|
|
119
|
-
"type": "string",
|
|
120
|
-
"description": "Information message about the reload operation",
|
|
121
|
-
},
|
|
122
|
-
"error_message": {
|
|
123
|
-
"type": ["string", "null"],
|
|
124
|
-
"description": "Error message if reload failed",
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
"required": [
|
|
128
|
-
"success",
|
|
129
|
-
"config_reloaded",
|
|
130
|
-
"builtin_commands",
|
|
131
|
-
"custom_commands",
|
|
132
|
-
"loaded_commands",
|
|
133
|
-
"remote_commands",
|
|
134
|
-
"total_commands",
|
|
135
|
-
"server_restart_required",
|
|
136
|
-
],
|
|
137
|
-
}
|
|
138
76
|
|
|
139
77
|
|
|
140
78
|
class ReloadCommand(Command):
|
|
@@ -196,21 +134,3 @@ class ReloadCommand(Command):
|
|
|
196
134
|
)
|
|
197
135
|
|
|
198
136
|
@classmethod
|
|
199
|
-
def get_schema(cls) -> Dict[str, Any]:
|
|
200
|
-
"""
|
|
201
|
-
Get JSON schema for command parameters.
|
|
202
|
-
|
|
203
|
-
Returns:
|
|
204
|
-
JSON schema dictionary.
|
|
205
|
-
"""
|
|
206
|
-
return {
|
|
207
|
-
"type": "object",
|
|
208
|
-
"properties": {
|
|
209
|
-
"config_path": {
|
|
210
|
-
"type": "string",
|
|
211
|
-
"description": "Path to configuration file to reload",
|
|
212
|
-
"default": None,
|
|
213
|
-
}
|
|
214
|
-
},
|
|
215
|
-
"additionalProperties": False,
|
|
216
|
-
}
|
|
@@ -4,7 +4,7 @@ Module with base classes for command results.
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
from abc import ABC, abstractmethod
|
|
7
|
-
from typing import
|
|
7
|
+
from typing import TypeVar, Dict, Any, Optional
|
|
8
8
|
|
|
9
9
|
T = TypeVar("T", bound="CommandResult")
|
|
10
10
|
|
|
@@ -27,39 +27,13 @@ class CommandResult(ABC):
|
|
|
27
27
|
@classmethod
|
|
28
28
|
@abstractmethod
|
|
29
29
|
def get_schema(cls) -> Dict[str, Any]:
|
|
30
|
-
"""
|
|
31
|
-
Returns JSON schema for result validation.
|
|
32
|
-
|
|
33
|
-
Returns:
|
|
34
|
-
Dictionary with JSON schema.
|
|
35
|
-
"""
|
|
30
|
+
"""Get JSON schema for the result."""
|
|
36
31
|
pass
|
|
37
32
|
|
|
38
|
-
def to_json(self, indent: Optional[int] = None) -> str:
|
|
39
|
-
"""
|
|
40
|
-
Converts result to JSON string.
|
|
41
|
-
|
|
42
|
-
Args:
|
|
43
|
-
indent: Indentation for JSON formatting.
|
|
44
|
-
|
|
45
|
-
Returns:
|
|
46
|
-
JSON string with result.
|
|
47
|
-
"""
|
|
48
|
-
return json.dumps(self.to_dict(), ensure_ascii=False, indent=indent)
|
|
49
|
-
|
|
50
33
|
@classmethod
|
|
51
|
-
def from_dict(cls
|
|
52
|
-
"""
|
|
53
|
-
|
|
54
|
-
This method must be overridden in subclasses.
|
|
55
|
-
|
|
56
|
-
Args:
|
|
57
|
-
data: Dictionary with result data.
|
|
58
|
-
|
|
59
|
-
Returns:
|
|
60
|
-
Result instance.
|
|
61
|
-
"""
|
|
62
|
-
raise NotImplementedError("Method from_dict must be implemented in subclasses")
|
|
34
|
+
def from_dict(cls, data: Dict[str, Any]) -> "CommandResult":
|
|
35
|
+
"""Create result from dictionary."""
|
|
36
|
+
pass
|
|
63
37
|
|
|
64
38
|
|
|
65
39
|
class SuccessResult(CommandResult):
|
|
@@ -96,34 +70,23 @@ class SuccessResult(CommandResult):
|
|
|
96
70
|
|
|
97
71
|
@classmethod
|
|
98
72
|
def get_schema(cls) -> Dict[str, Any]:
|
|
99
|
-
"""
|
|
100
|
-
Returns JSON schema for result validation.
|
|
101
|
-
|
|
102
|
-
Returns:
|
|
103
|
-
Dictionary with JSON schema.
|
|
104
|
-
"""
|
|
73
|
+
"""Get JSON schema for success result."""
|
|
105
74
|
return {
|
|
106
75
|
"type": "object",
|
|
107
76
|
"properties": {
|
|
108
|
-
"success": {"type": "boolean"},
|
|
77
|
+
"success": {"type": "boolean", "const": True},
|
|
109
78
|
"data": {"type": "object"},
|
|
110
|
-
"message": {"type": "string"}
|
|
111
|
-
}
|
|
112
|
-
"required": ["success"],
|
|
79
|
+
"message": {"type": "string"}
|
|
80
|
+
}
|
|
113
81
|
}
|
|
114
82
|
|
|
115
83
|
@classmethod
|
|
116
84
|
def from_dict(cls, data: Dict[str, Any]) -> "SuccessResult":
|
|
117
|
-
"""
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
Returns:
|
|
124
|
-
Successful result instance.
|
|
125
|
-
"""
|
|
126
|
-
return cls(data=data.get("data"), message=data.get("message"))
|
|
85
|
+
"""Create success result from dictionary."""
|
|
86
|
+
return cls(
|
|
87
|
+
data=data.get("data"),
|
|
88
|
+
message=data.get("message")
|
|
89
|
+
)
|
|
127
90
|
|
|
128
91
|
|
|
129
92
|
class ErrorResult(CommandResult):
|
|
@@ -167,43 +130,28 @@ class ErrorResult(CommandResult):
|
|
|
167
130
|
|
|
168
131
|
@classmethod
|
|
169
132
|
def get_schema(cls) -> Dict[str, Any]:
|
|
170
|
-
"""
|
|
171
|
-
Returns JSON schema for result validation.
|
|
172
|
-
|
|
173
|
-
Returns:
|
|
174
|
-
Dictionary with JSON schema.
|
|
175
|
-
"""
|
|
133
|
+
"""Get JSON schema for error result."""
|
|
176
134
|
return {
|
|
177
135
|
"type": "object",
|
|
178
136
|
"properties": {
|
|
179
|
-
"success": {"type": "boolean"},
|
|
137
|
+
"success": {"type": "boolean", "const": False},
|
|
180
138
|
"error": {
|
|
181
139
|
"type": "object",
|
|
182
140
|
"properties": {
|
|
183
141
|
"code": {"type": "integer"},
|
|
184
142
|
"message": {"type": "string"},
|
|
185
|
-
"data": {"type": "object"}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
},
|
|
190
|
-
"required": ["success", "error"],
|
|
143
|
+
"data": {"type": "object"}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
191
147
|
}
|
|
192
148
|
|
|
193
149
|
@classmethod
|
|
194
150
|
def from_dict(cls, data: Dict[str, Any]) -> "ErrorResult":
|
|
195
|
-
"""
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
Args:
|
|
199
|
-
data: Dictionary with result data.
|
|
200
|
-
|
|
201
|
-
Returns:
|
|
202
|
-
Error result instance.
|
|
203
|
-
"""
|
|
204
|
-
error = data.get("error", {})
|
|
151
|
+
"""Create error result from dictionary."""
|
|
152
|
+
error_data = data.get("error", {})
|
|
205
153
|
return cls(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
details=
|
|
154
|
+
code=error_data.get("code", -32603),
|
|
155
|
+
message=error_data.get("message", "Internal error"),
|
|
156
|
+
details=error_data.get("data")
|
|
209
157
|
)
|
|
@@ -8,7 +8,6 @@ email: vasilyvz@gmail.com
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
import logging
|
|
11
|
-
from typing import Dict, Any, Optional
|
|
12
11
|
from mcp_proxy_adapter.commands.base import Command
|
|
13
12
|
from mcp_proxy_adapter.commands.result import SuccessResult
|
|
14
13
|
|
|
@@ -36,38 +35,8 @@ class RoleTestCommandResult(SuccessResult):
|
|
|
36
35
|
self.action = action
|
|
37
36
|
self.allowed = allowed
|
|
38
37
|
|
|
39
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
40
|
-
"""Convert to dictionary."""
|
|
41
|
-
return {
|
|
42
|
-
"success": True,
|
|
43
|
-
"data": {
|
|
44
|
-
"user_role": self.user_role,
|
|
45
|
-
"permissions": self.permissions,
|
|
46
|
-
"action": self.action,
|
|
47
|
-
"allowed": self.allowed,
|
|
48
|
-
},
|
|
49
|
-
"message": f"Action '{self.action}' {'allowed' if self.allowed else 'denied'} for role '{self.user_role}'",
|
|
50
|
-
}
|
|
51
38
|
|
|
52
39
|
@classmethod
|
|
53
|
-
def get_schema(cls) -> Dict[str, Any]:
|
|
54
|
-
"""Get JSON schema."""
|
|
55
|
-
return {
|
|
56
|
-
"type": "object",
|
|
57
|
-
"properties": {
|
|
58
|
-
"success": {"type": "boolean"},
|
|
59
|
-
"data": {
|
|
60
|
-
"type": "object",
|
|
61
|
-
"properties": {
|
|
62
|
-
"user_role": {"type": "string"},
|
|
63
|
-
"permissions": {"type": "array", "items": {"type": "string"}},
|
|
64
|
-
"action": {"type": "string"},
|
|
65
|
-
"allowed": {"type": "boolean"},
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
"message": {"type": "string"},
|
|
69
|
-
},
|
|
70
|
-
}
|
|
71
40
|
|
|
72
41
|
|
|
73
42
|
class RoleTestCommand(Command):
|
|
@@ -110,19 +79,6 @@ class RoleTestCommand(Command):
|
|
|
110
79
|
return RoleTestCommandResult(user_role, permissions, action, allowed)
|
|
111
80
|
|
|
112
81
|
@classmethod
|
|
113
|
-
def get_schema(cls) -> Dict[str, Any]:
|
|
114
|
-
"""Get JSON schema for command parameters."""
|
|
115
|
-
return {
|
|
116
|
-
"type": "object",
|
|
117
|
-
"properties": {
|
|
118
|
-
"action": {
|
|
119
|
-
"type": "string",
|
|
120
|
-
"description": "Action to test",
|
|
121
|
-
"default": "read",
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
"additionalProperties": False,
|
|
125
|
-
}
|
|
126
82
|
|
|
127
83
|
def _check_permission(self, action: str, permissions: list) -> bool:
|
|
128
84
|
"""
|