mcp-proxy-adapter 2.0.1__py3-none-any.whl → 6.9.50__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.

Files changed (269) hide show
  1. mcp_proxy_adapter/__init__.py +47 -0
  2. mcp_proxy_adapter/__main__.py +13 -0
  3. mcp_proxy_adapter/api/__init__.py +0 -0
  4. mcp_proxy_adapter/api/app.py +66 -0
  5. mcp_proxy_adapter/api/core/__init__.py +18 -0
  6. mcp_proxy_adapter/api/core/app_factory.py +400 -0
  7. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  8. mcp_proxy_adapter/api/core/registration_context.py +356 -0
  9. mcp_proxy_adapter/api/core/registration_manager.py +307 -0
  10. mcp_proxy_adapter/api/core/registration_tasks.py +84 -0
  11. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  12. mcp_proxy_adapter/api/handlers.py +181 -0
  13. mcp_proxy_adapter/api/middleware/__init__.py +21 -0
  14. mcp_proxy_adapter/api/middleware/base.py +54 -0
  15. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +73 -0
  16. mcp_proxy_adapter/api/middleware/error_handling.py +76 -0
  17. mcp_proxy_adapter/api/middleware/factory.py +147 -0
  18. mcp_proxy_adapter/api/middleware/logging.py +31 -0
  19. mcp_proxy_adapter/api/middleware/performance.py +51 -0
  20. mcp_proxy_adapter/api/middleware/protocol_middleware.py +140 -0
  21. mcp_proxy_adapter/api/middleware/transport_middleware.py +87 -0
  22. mcp_proxy_adapter/api/middleware/unified_security.py +223 -0
  23. mcp_proxy_adapter/api/middleware/user_info_middleware.py +132 -0
  24. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  25. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  26. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  27. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  28. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  29. mcp_proxy_adapter/api/schemas.py +270 -0
  30. mcp_proxy_adapter/api/tool_integration.py +131 -0
  31. mcp_proxy_adapter/api/tools.py +163 -0
  32. mcp_proxy_adapter/cli/__init__.py +12 -0
  33. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  34. mcp_proxy_adapter/cli/commands/client.py +100 -0
  35. mcp_proxy_adapter/cli/commands/config_generate.py +105 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +94 -0
  37. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  38. mcp_proxy_adapter/cli/commands/server.py +174 -0
  39. mcp_proxy_adapter/cli/commands/sets.py +132 -0
  40. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  41. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  42. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  43. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  44. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  45. mcp_proxy_adapter/cli/main.py +63 -0
  46. mcp_proxy_adapter/cli/parser.py +338 -0
  47. mcp_proxy_adapter/cli/validators.py +231 -0
  48. mcp_proxy_adapter/client/jsonrpc_client/__init__.py +9 -0
  49. mcp_proxy_adapter/client/jsonrpc_client/client.py +42 -0
  50. mcp_proxy_adapter/client/jsonrpc_client/command_api.py +45 -0
  51. mcp_proxy_adapter/client/jsonrpc_client/proxy_api.py +224 -0
  52. mcp_proxy_adapter/client/jsonrpc_client/queue_api.py +60 -0
  53. mcp_proxy_adapter/client/jsonrpc_client/transport.py +108 -0
  54. mcp_proxy_adapter/client/proxy.py +123 -0
  55. mcp_proxy_adapter/commands/__init__.py +66 -0
  56. mcp_proxy_adapter/commands/auth_validation_command.py +69 -0
  57. mcp_proxy_adapter/commands/base.py +389 -0
  58. mcp_proxy_adapter/commands/builtin_commands.py +30 -0
  59. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  60. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  61. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  62. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  63. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  64. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  65. mcp_proxy_adapter/commands/catalog_manager.py +97 -0
  66. mcp_proxy_adapter/commands/cert_monitor_command.py +552 -0
  67. mcp_proxy_adapter/commands/certificate_management_command.py +562 -0
  68. mcp_proxy_adapter/commands/command_registry.py +298 -0
  69. mcp_proxy_adapter/commands/config_command.py +102 -0
  70. mcp_proxy_adapter/commands/dependency_container.py +40 -0
  71. mcp_proxy_adapter/commands/dependency_manager.py +143 -0
  72. mcp_proxy_adapter/commands/echo_command.py +48 -0
  73. mcp_proxy_adapter/commands/health_command.py +142 -0
  74. mcp_proxy_adapter/commands/help_command.py +175 -0
  75. mcp_proxy_adapter/commands/hooks.py +172 -0
  76. mcp_proxy_adapter/commands/key_management_command.py +484 -0
  77. mcp_proxy_adapter/commands/load_command.py +123 -0
  78. mcp_proxy_adapter/commands/plugins_command.py +246 -0
  79. mcp_proxy_adapter/commands/protocol_management_command.py +216 -0
  80. mcp_proxy_adapter/commands/proxy_registration_command.py +319 -0
  81. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  82. mcp_proxy_adapter/commands/registration_status_command.py +76 -0
  83. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  84. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  85. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  86. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  87. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  88. mcp_proxy_adapter/commands/reload_command.py +136 -0
  89. mcp_proxy_adapter/commands/result.py +157 -0
  90. mcp_proxy_adapter/commands/role_test_command.py +99 -0
  91. mcp_proxy_adapter/commands/roles_management_command.py +502 -0
  92. mcp_proxy_adapter/commands/security_command.py +472 -0
  93. mcp_proxy_adapter/commands/settings_command.py +113 -0
  94. mcp_proxy_adapter/commands/ssl_setup_command.py +306 -0
  95. mcp_proxy_adapter/commands/token_management_command.py +500 -0
  96. mcp_proxy_adapter/commands/transport_management_command.py +129 -0
  97. mcp_proxy_adapter/commands/unload_command.py +92 -0
  98. mcp_proxy_adapter/config.py +32 -0
  99. mcp_proxy_adapter/core/__init__.py +8 -0
  100. mcp_proxy_adapter/core/app_factory.py +560 -0
  101. mcp_proxy_adapter/core/app_runner.py +318 -0
  102. mcp_proxy_adapter/core/auth_validator.py +508 -0
  103. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  104. mcp_proxy_adapter/core/certificate/certificate_creator.py +372 -0
  105. mcp_proxy_adapter/core/certificate/certificate_extractor.py +185 -0
  106. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  107. mcp_proxy_adapter/core/certificate/certificate_validator.py +481 -0
  108. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +65 -0
  109. mcp_proxy_adapter/core/certificate_utils.py +249 -0
  110. mcp_proxy_adapter/core/client.py +608 -0
  111. mcp_proxy_adapter/core/client_manager.py +271 -0
  112. mcp_proxy_adapter/core/client_security.py +411 -0
  113. mcp_proxy_adapter/core/config/__init__.py +18 -0
  114. mcp_proxy_adapter/core/config/config.py +237 -0
  115. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  116. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  117. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  118. mcp_proxy_adapter/core/config/simple_config.py +204 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +131 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +476 -0
  121. mcp_proxy_adapter/core/config_converter.py +252 -0
  122. mcp_proxy_adapter/core/config_validator.py +211 -0
  123. mcp_proxy_adapter/core/crl_utils.py +362 -0
  124. mcp_proxy_adapter/core/errors.py +276 -0
  125. mcp_proxy_adapter/core/job_manager.py +54 -0
  126. mcp_proxy_adapter/core/logging.py +250 -0
  127. mcp_proxy_adapter/core/mtls_asgi.py +140 -0
  128. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  129. mcp_proxy_adapter/core/mtls_proxy.py +229 -0
  130. mcp_proxy_adapter/core/mtls_server.py +154 -0
  131. mcp_proxy_adapter/core/protocol_manager.py +232 -0
  132. mcp_proxy_adapter/core/proxy/__init__.py +19 -0
  133. mcp_proxy_adapter/core/proxy/auth_manager.py +26 -0
  134. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +160 -0
  135. mcp_proxy_adapter/core/proxy/registration_client.py +186 -0
  136. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  137. mcp_proxy_adapter/core/proxy_client.py +184 -0
  138. mcp_proxy_adapter/core/proxy_registration.py +80 -0
  139. mcp_proxy_adapter/core/role_utils.py +103 -0
  140. mcp_proxy_adapter/core/security_adapter.py +343 -0
  141. mcp_proxy_adapter/core/security_factory.py +96 -0
  142. mcp_proxy_adapter/core/security_integration.py +342 -0
  143. mcp_proxy_adapter/core/server_adapter.py +251 -0
  144. mcp_proxy_adapter/core/server_engine.py +217 -0
  145. mcp_proxy_adapter/core/settings.py +260 -0
  146. mcp_proxy_adapter/core/signal_handler.py +107 -0
  147. mcp_proxy_adapter/core/ssl_utils.py +161 -0
  148. mcp_proxy_adapter/core/transport_manager.py +153 -0
  149. mcp_proxy_adapter/core/unified_config_adapter.py +471 -0
  150. mcp_proxy_adapter/core/utils.py +101 -0
  151. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  152. mcp_proxy_adapter/core/validation/config_validator.py +219 -0
  153. mcp_proxy_adapter/core/validation/file_validator.py +131 -0
  154. mcp_proxy_adapter/core/validation/protocol_validator.py +205 -0
  155. mcp_proxy_adapter/core/validation/security_validator.py +140 -0
  156. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  157. mcp_proxy_adapter/custom_openapi.py +58 -0
  158. mcp_proxy_adapter/examples/__init__.py +16 -0
  159. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  160. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  161. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  162. mcp_proxy_adapter/examples/basic_framework/main.py +52 -0
  163. mcp_proxy_adapter/examples/bugfix_certificate_config.py +261 -0
  164. mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
  165. mcp_proxy_adapter/examples/check_config.py +413 -0
  166. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  167. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  168. mcp_proxy_adapter/examples/config_builder.py +234 -0
  169. mcp_proxy_adapter/examples/config_cli.py +282 -0
  170. mcp_proxy_adapter/examples/create_test_configs.py +174 -0
  171. mcp_proxy_adapter/examples/debug_request_state.py +130 -0
  172. mcp_proxy_adapter/examples/debug_role_chain.py +191 -0
  173. mcp_proxy_adapter/examples/demo_client.py +287 -0
  174. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  175. mcp_proxy_adapter/examples/full_application/commands/__init__.py +8 -0
  176. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +45 -0
  177. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +52 -0
  178. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +32 -0
  179. mcp_proxy_adapter/examples/full_application/commands/help_command.py +54 -0
  180. mcp_proxy_adapter/examples/full_application/commands/list_command.py +57 -0
  181. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +5 -0
  182. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +29 -0
  183. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +27 -0
  184. mcp_proxy_adapter/examples/full_application/main.py +311 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +161 -0
  186. mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
  187. mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
  188. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +45 -0
  189. mcp_proxy_adapter/examples/full_application/test_server.py +163 -0
  190. mcp_proxy_adapter/examples/full_application/test_simple_server.py +62 -0
  191. mcp_proxy_adapter/examples/generate_config.py +502 -0
  192. mcp_proxy_adapter/examples/proxy_registration_example.py +335 -0
  193. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  194. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  195. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  196. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  197. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  198. mcp_proxy_adapter/examples/required_certificates.py +208 -0
  199. mcp_proxy_adapter/examples/run_example.py +77 -0
  200. mcp_proxy_adapter/examples/run_full_test_suite.py +619 -0
  201. mcp_proxy_adapter/examples/run_proxy_server.py +153 -0
  202. mcp_proxy_adapter/examples/run_security_tests_fixed.py +435 -0
  203. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  204. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  205. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  206. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  207. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  208. mcp_proxy_adapter/examples/security_test_client.py +72 -0
  209. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  210. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  211. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  212. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  213. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  214. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  215. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  216. mcp_proxy_adapter/examples/setup_test_environment.py +235 -0
  217. mcp_proxy_adapter/examples/simple_protocol_test.py +125 -0
  218. mcp_proxy_adapter/examples/test_chk_hostname_automated.py +211 -0
  219. mcp_proxy_adapter/examples/test_config.py +205 -0
  220. mcp_proxy_adapter/examples/test_config_builder.py +110 -0
  221. mcp_proxy_adapter/examples/test_examples.py +308 -0
  222. mcp_proxy_adapter/examples/test_framework_complete.py +267 -0
  223. mcp_proxy_adapter/examples/test_mcp_server.py +187 -0
  224. mcp_proxy_adapter/examples/test_protocol_examples.py +337 -0
  225. mcp_proxy_adapter/examples/universal_client.py +674 -0
  226. mcp_proxy_adapter/examples/update_config_certificates.py +135 -0
  227. mcp_proxy_adapter/examples/validate_generator_compatibility.py +385 -0
  228. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +61 -0
  229. mcp_proxy_adapter/integrations/__init__.py +25 -0
  230. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  231. mcp_proxy_adapter/main.py +311 -0
  232. mcp_proxy_adapter/openapi.py +375 -0
  233. mcp_proxy_adapter/schemas/base_schema.json +114 -0
  234. mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
  235. mcp_proxy_adapter/schemas/roles.json +37 -0
  236. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  237. mcp_proxy_adapter/version.py +5 -0
  238. mcp_proxy_adapter-6.9.50.dist-info/METADATA +1088 -0
  239. mcp_proxy_adapter-6.9.50.dist-info/RECORD +242 -0
  240. {mcp_proxy_adapter-2.0.1.dist-info → mcp_proxy_adapter-6.9.50.dist-info}/WHEEL +1 -1
  241. mcp_proxy_adapter-6.9.50.dist-info/entry_points.txt +14 -0
  242. mcp_proxy_adapter-6.9.50.dist-info/top_level.txt +1 -0
  243. adapters/__init__.py +0 -16
  244. analyzers/__init__.py +0 -14
  245. analyzers/docstring_analyzer.py +0 -199
  246. analyzers/type_analyzer.py +0 -151
  247. cli/__init__.py +0 -12
  248. cli/__main__.py +0 -79
  249. cli/command_runner.py +0 -233
  250. dispatchers/__init__.py +0 -14
  251. dispatchers/base_dispatcher.py +0 -85
  252. dispatchers/json_rpc_dispatcher.py +0 -198
  253. generators/__init__.py +0 -14
  254. generators/endpoint_generator.py +0 -172
  255. generators/openapi_generator.py +0 -254
  256. generators/rest_api_generator.py +0 -207
  257. mcp_proxy_adapter-2.0.1.dist-info/METADATA +0 -272
  258. mcp_proxy_adapter-2.0.1.dist-info/RECORD +0 -28
  259. mcp_proxy_adapter-2.0.1.dist-info/licenses/LICENSE +0 -21
  260. mcp_proxy_adapter-2.0.1.dist-info/top_level.txt +0 -7
  261. openapi_schema/__init__.py +0 -38
  262. openapi_schema/command_registry.py +0 -312
  263. openapi_schema/rest_schema.py +0 -510
  264. openapi_schema/rpc_generator.py +0 -307
  265. openapi_schema/rpc_schema.py +0 -416
  266. validators/__init__.py +0 -14
  267. validators/base_validator.py +0 -23
  268. validators/docstring_validator.py +0 -75
  269. validators/metadata_validator.py +0 -76
@@ -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()
@@ -0,0 +1,136 @@
1
+ """
2
+ Reload command for configuration and command discovery.
3
+
4
+ This command allows reloading configuration and rediscovering commands
5
+ without restarting the server.
6
+ """
7
+
8
+ from typing import Any, Dict, Optional
9
+
10
+ from mcp_proxy_adapter.commands.base import Command
11
+ from mcp_proxy_adapter.commands.command_registry import registry
12
+ from mcp_proxy_adapter.core.logging import get_global_logger
13
+
14
+
15
+ class ReloadResult:
16
+ """
17
+ Result of reload operation.
18
+ """
19
+
20
+ def __init__(
21
+ self,
22
+ config_reloaded: bool,
23
+ builtin_commands: int,
24
+ custom_commands: int,
25
+ loaded_commands: int,
26
+ remote_commands: int = 0,
27
+ total_commands: int = 0,
28
+ server_restart_required: bool = True,
29
+ success: bool = True,
30
+ error_message: Optional[str] = None,
31
+ ):
32
+ """
33
+ Initialize reload result.
34
+
35
+ Args:
36
+ config_reloaded: Whether configuration was reloaded successfully
37
+ builtin_commands: Number of built-in commands registered
38
+ custom_commands: Number of custom commands registered
39
+ loaded_commands: Number of commands loaded from directory
40
+ total_commands: Total number of commands after reload
41
+ server_restart_required: Whether server restart is required
42
+ success: Whether reload was successful
43
+ error_message: Error message if reload failed
44
+ """
45
+ self.config_reloaded = config_reloaded
46
+ self.builtin_commands = builtin_commands
47
+ self.custom_commands = custom_commands
48
+ self.loaded_commands = loaded_commands
49
+ self.remote_commands = remote_commands
50
+ self.total_commands = total_commands
51
+ self.server_restart_required = server_restart_required
52
+ self.success = success
53
+ self.error_message = error_message
54
+
55
+ def to_dict(self) -> Dict[str, Any]:
56
+ """
57
+ Convert result to dictionary.
58
+
59
+ Returns:
60
+ Dictionary representation of the result.
61
+ """
62
+ return {
63
+ "success": self.success,
64
+ "config_reloaded": self.config_reloaded,
65
+ "builtin_commands": self.builtin_commands,
66
+ "custom_commands": self.custom_commands,
67
+ "loaded_commands": self.loaded_commands,
68
+ "remote_commands": self.remote_commands,
69
+ "total_commands": self.total_commands,
70
+ "server_restart_required": self.server_restart_required,
71
+ "message": "Server restart required to apply configuration changes",
72
+ "error_message": self.error_message,
73
+ }
74
+
75
+ @classmethod
76
+
77
+
78
+ class ReloadCommand(Command):
79
+ """
80
+ Command for reloading configuration and rediscovering commands.
81
+ Uses the unified initialization logic.
82
+ """
83
+
84
+ name = "reload"
85
+
86
+ async def execute(self, **params) -> ReloadResult:
87
+ """
88
+ Execute reload command.
89
+
90
+ Args:
91
+ **params: Command parameters (config_path)
92
+
93
+ Returns:
94
+ ReloadResult with reload information
95
+ """
96
+ try:
97
+ get_global_logger().info("🔄 Starting configuration and commands reload...")
98
+
99
+ # Get config path from parameters
100
+ config_path = params.get("config_path")
101
+ if not config_path:
102
+ get_global_logger().warning("No config_path provided, using default configuration")
103
+
104
+ # Perform reload using unified initialization
105
+ reload_info = await registry.reload_system(config_path=config_path)
106
+
107
+ # Create result
108
+ result = ReloadResult(
109
+ config_reloaded=reload_info.get("config_reloaded", False),
110
+ builtin_commands=reload_info.get("builtin_commands", 0),
111
+ custom_commands=reload_info.get("custom_commands", 0),
112
+ loaded_commands=reload_info.get("loaded_commands", 0),
113
+ remote_commands=reload_info.get("remote_commands", 0),
114
+ total_commands=reload_info.get("total_commands", 0),
115
+ server_restart_required=True, # Default to True as per tests
116
+ success=True,
117
+ )
118
+
119
+ get_global_logger().info(f"✅ Reload completed successfully: {result.to_dict()}")
120
+ return result
121
+
122
+ except Exception as e:
123
+ get_global_logger().error(f"❌ Reload failed: {str(e)}")
124
+ return ReloadResult(
125
+ config_reloaded=False,
126
+ builtin_commands=0,
127
+ custom_commands=0,
128
+ loaded_commands=0,
129
+ remote_commands=0,
130
+ total_commands=0,
131
+ server_restart_required=False,
132
+ success=False,
133
+ error_message=str(e),
134
+ )
135
+
136
+ @classmethod
@@ -0,0 +1,157 @@
1
+ """
2
+ Module with base classes for command results.
3
+ """
4
+
5
+ import json
6
+ from abc import ABC, abstractmethod
7
+ from typing import TypeVar, Dict, Any, Optional
8
+
9
+ T = TypeVar("T", bound="CommandResult")
10
+
11
+
12
+ class CommandResult(ABC):
13
+ """
14
+ Base abstract class for command execution results.
15
+ """
16
+
17
+ @abstractmethod
18
+ def to_dict(self) -> Dict[str, Any]:
19
+ """
20
+ Converts result to dictionary for serialization.
21
+
22
+ Returns:
23
+ Dictionary with result data.
24
+ """
25
+ pass
26
+
27
+ @classmethod
28
+ @abstractmethod
29
+ def get_schema(cls) -> Dict[str, Any]:
30
+ """Get JSON schema for the result."""
31
+ pass
32
+
33
+ @classmethod
34
+ def from_dict(cls, data: Dict[str, Any]) -> "CommandResult":
35
+ """Create result from dictionary."""
36
+ pass
37
+
38
+
39
+ class SuccessResult(CommandResult):
40
+ """
41
+ Base class for successful command results.
42
+ """
43
+
44
+ def __init__(
45
+ self, data: Optional[Dict[str, Any]] = None, message: Optional[str] = None
46
+ ):
47
+ """
48
+ Initialize successful result.
49
+
50
+ Args:
51
+ data: Result data.
52
+ message: Result message.
53
+ """
54
+ self.data = data or {}
55
+ self.message = message
56
+
57
+ def to_dict(self) -> Dict[str, Any]:
58
+ """
59
+ Converts result to dictionary for serialization.
60
+
61
+ Returns:
62
+ Dictionary with result data.
63
+ """
64
+ result = {"success": True}
65
+ if self.data:
66
+ result["data"] = self.data
67
+ if self.message:
68
+ result["message"] = self.message
69
+ return result
70
+
71
+ @classmethod
72
+ def get_schema(cls) -> Dict[str, Any]:
73
+ """Get JSON schema for success result."""
74
+ return {
75
+ "type": "object",
76
+ "properties": {
77
+ "success": {"type": "boolean", "const": True},
78
+ "data": {"type": "object"},
79
+ "message": {"type": "string"}
80
+ }
81
+ }
82
+
83
+ @classmethod
84
+ def from_dict(cls, data: Dict[str, Any]) -> "SuccessResult":
85
+ """Create success result from dictionary."""
86
+ return cls(
87
+ data=data.get("data"),
88
+ message=data.get("message")
89
+ )
90
+
91
+
92
+ class ErrorResult(CommandResult):
93
+ """
94
+ Base class for command results with error.
95
+
96
+ This class follows the JSON-RPC 2.0 error object format:
97
+ https://www.jsonrpc.org/specification#error_object
98
+ """
99
+
100
+ def __init__(
101
+ self, message: str, code: int = -32000, details: Optional[Dict[str, Any]] = None
102
+ ):
103
+ """
104
+ Initialize error result.
105
+
106
+ Args:
107
+ message: Error message.
108
+ code: Error code (following JSON-RPC 2.0 spec).
109
+ details: Additional error details.
110
+ """
111
+ self.message = message
112
+ self.error = message # For backward compatibility with tests
113
+ self.code = code
114
+ self.details = details or {}
115
+
116
+ def to_dict(self) -> Dict[str, Any]:
117
+ """
118
+ Converts result to dictionary for serialization.
119
+
120
+ Returns:
121
+ Dictionary with result data in JSON-RPC 2.0 error format.
122
+ """
123
+ result = {
124
+ "success": False,
125
+ "error": {"code": self.code, "message": self.message},
126
+ }
127
+ if self.details:
128
+ result["error"]["data"] = self.details
129
+ return result
130
+
131
+ @classmethod
132
+ def get_schema(cls) -> Dict[str, Any]:
133
+ """Get JSON schema for error result."""
134
+ return {
135
+ "type": "object",
136
+ "properties": {
137
+ "success": {"type": "boolean", "const": False},
138
+ "error": {
139
+ "type": "object",
140
+ "properties": {
141
+ "code": {"type": "integer"},
142
+ "message": {"type": "string"},
143
+ "data": {"type": "object"}
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ @classmethod
150
+ def from_dict(cls, data: Dict[str, Any]) -> "ErrorResult":
151
+ """Create error result from dictionary."""
152
+ error_data = data.get("error", {})
153
+ return cls(
154
+ code=error_data.get("code", -32603),
155
+ message=error_data.get("message", "Internal error"),
156
+ details=error_data.get("data")
157
+ )
@@ -0,0 +1,99 @@
1
+ """
2
+ Role Test Command
3
+
4
+ This command tests role-based access control by checking user permissions.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ import logging
11
+ from mcp_proxy_adapter.commands.base import Command
12
+ from mcp_proxy_adapter.commands.result import SuccessResult
13
+
14
+
15
+ from mcp_proxy_adapter.core.logging import get_global_logger
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class RoleTestCommandResult(SuccessResult):
20
+ """Result for role test command."""
21
+
22
+ def __init__(self, user_role: str, permissions: list, action: str, allowed: bool):
23
+ """
24
+ Initialize role test result.
25
+
26
+ Args:
27
+ user_role: User's role
28
+ permissions: User's permissions
29
+ action: Action being tested
30
+ allowed: Whether action is allowed
31
+ """
32
+ super().__init__()
33
+ self.user_role = user_role
34
+ self.permissions = permissions
35
+ self.action = action
36
+ self.allowed = allowed
37
+
38
+
39
+ @classmethod
40
+
41
+
42
+ class RoleTestCommand(Command):
43
+ """Test role-based access control."""
44
+
45
+ name = "roletest"
46
+ descr = "Test role-based access control"
47
+ category = "security"
48
+ author = "Vasiliy Zdanovskiy"
49
+ email = "vasilyvz@gmail.com"
50
+
51
+ async def execute(self, **kwargs) -> RoleTestCommandResult:
52
+ """
53
+ Execute role test command.
54
+
55
+ Args:
56
+ **kwargs: Command parameters including context
57
+
58
+ Returns:
59
+ RoleTestCommandResult
60
+ """
61
+ # Extract parameters
62
+ action = kwargs.get("action", "read")
63
+ context = kwargs.get("context", {})
64
+
65
+ # Get user info from context
66
+ user_role = "guest" # Default
67
+ permissions = ["read"] # Default
68
+
69
+ if context:
70
+ user_info = context.get("user", {})
71
+ user_role = user_info.get("role", "guest")
72
+ permissions = user_info.get("permissions", ["read"])
73
+
74
+ # Check if action is allowed
75
+ allowed = self._check_permission(action, permissions)
76
+
77
+ get_global_logger().info(f"Role test: user={user_role}, action={action}, allowed={allowed}")
78
+
79
+ return RoleTestCommandResult(user_role, permissions, action, allowed)
80
+
81
+ @classmethod
82
+
83
+ def _check_permission(self, action: str, permissions: list) -> bool:
84
+ """
85
+ Check if action is allowed for given permissions.
86
+
87
+ Args:
88
+ action: Action to check
89
+ permissions: User permissions
90
+
91
+ Returns:
92
+ True if allowed, False otherwise
93
+ """
94
+ # Admin has all permissions
95
+ if "*" in permissions:
96
+ return True
97
+
98
+ # Check specific permission
99
+ return action in permissions