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,298 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Main command registry for MCP Proxy Adapter.
6
+ """
7
+
8
+
9
+ from typing import Dict, List, Type, Union, Any, Optional
10
+
11
+ from mcp_proxy_adapter.commands.base import Command
12
+ from mcp_proxy_adapter.core.logging import get_global_logger
13
+ # from .command_loader import CommandLoader
14
+ # from .command_manager import CommandManager
15
+ # from .command_info import CommandInfo
16
+
17
+
18
+ class CommandRegistry:
19
+ """
20
+ Registry for registering and finding commands.
21
+
22
+ Supports three types of commands:
23
+ - Builtin: Core commands that come with the framework
24
+ - Custom: User-defined commands
25
+ - Loaded: Commands loaded from external sources
26
+ """
27
+
28
+ def __init__(self):
29
+ """Initialize command registry."""
30
+ self.logger = get_global_logger()
31
+
32
+ # Command storage
33
+ self._commands: Dict[str, Type[Command]] = {}
34
+ self._instances: Dict[str, Command] = {}
35
+ self._command_types: Dict[str, str] = {} # "builtin", "custom", "loaded"
36
+
37
+ # Initialize components
38
+ # self._loader = CommandLoader()
39
+ self._loader = None
40
+ # self._manager = CommandManager()
41
+ # self._info = CommandInfo()
42
+ self._manager = None
43
+ self._info = None
44
+
45
+ # Register built-in echo command
46
+ self._register_echo_command()
47
+ self._register_long_task_commands()
48
+
49
+ def _register_echo_command(self) -> None:
50
+ """Register built-in echo command."""
51
+ from mcp_proxy_adapter.commands.base import Command, CommandResult
52
+
53
+ class EchoCommand(Command):
54
+ name = "echo"
55
+ descr = "Echo command for testing"
56
+
57
+ async def execute(self, message: str = "Hello", **kwargs) -> CommandResult:
58
+ return CommandResult(success=True, data={"message": message})
59
+
60
+ @classmethod
61
+ def get_schema(cls) -> Dict[str, Any]:
62
+ return {
63
+ "type": "object",
64
+ "properties": {
65
+ "message": {"type": "string", "default": "Hello"}
66
+ }
67
+ }
68
+
69
+ self._commands["echo"] = EchoCommand
70
+ self._command_types["echo"] = "builtin"
71
+
72
+ def _register_long_task_commands(self) -> None:
73
+ """Register demo long-running task commands (enqueue/status)."""
74
+ from mcp_proxy_adapter.commands.base import Command, CommandResult
75
+ from mcp_proxy_adapter.core.job_manager import enqueue_coroutine, get_job_status
76
+ import asyncio
77
+
78
+ class LongTaskCommand(Command):
79
+ name = "long_task"
80
+ descr = "Enqueue a long-running task that sleeps for given seconds"
81
+
82
+ async def execute(self, seconds: float = 5.0, **kwargs) -> CommandResult:
83
+ async def _work():
84
+ await asyncio.sleep(max(0.0, float(seconds)))
85
+ return {"slept": float(seconds)}
86
+
87
+ job_id = enqueue_coroutine(_work())
88
+ return CommandResult(success=True, data={"job_id": job_id, "status": "queued"})
89
+
90
+ @classmethod
91
+ def get_schema(cls) -> Dict[str, Any]:
92
+ return {
93
+ "type": "object",
94
+ "properties": {"seconds": {"type": "number", "default": 5.0}},
95
+ "description": "Start a demo long-running job"
96
+ }
97
+
98
+ class JobStatusCommand(Command):
99
+ name = "job_status"
100
+ descr = "Get status of a previously enqueued job"
101
+
102
+ async def execute(self, job_id: str, **kwargs) -> CommandResult:
103
+ status = get_job_status(job_id)
104
+ return CommandResult(success=True, data=status)
105
+
106
+ @classmethod
107
+ def get_schema(cls) -> Dict[str, Any]:
108
+ return {
109
+ "type": "object",
110
+ "properties": {"job_id": {"type": "string"}},
111
+ "required": ["job_id"],
112
+ "description": "Check job status"
113
+ }
114
+
115
+ self._commands["long_task"] = LongTaskCommand
116
+ self._command_types["long_task"] = "builtin"
117
+ self._commands["job_status"] = JobStatusCommand
118
+ self._command_types["job_status"] = "builtin"
119
+
120
+
121
+ def register_loaded(self, command: Union[Type[Command], Command]) -> None:
122
+ """
123
+ Register a loaded command.
124
+
125
+ Args:
126
+ command: Command class or instance to register
127
+ """
128
+ self._register_command(command, "loaded")
129
+
130
+ def _register_command(self, command: Union[Type[Command], Command], cmd_type: str) -> None:
131
+ """
132
+ Register a command.
133
+
134
+ Args:
135
+ command: Command class or instance to register
136
+ cmd_type: Type of command ("builtin", "custom", "loaded")
137
+ """
138
+ if isinstance(command, Command):
139
+ # Register instance
140
+ command_name = self._manager._get_command_name(command.__class__)
141
+ self._instances[command_name] = command
142
+ self._commands[command_name] = command.__class__
143
+ else:
144
+ # Register class
145
+ command_name = self._manager._get_command_name(command)
146
+ self._commands[command_name] = command
147
+
148
+ self._command_types[command_name] = cmd_type
149
+ self.logger.info(f"Registered {cmd_type} command: {command_name}")
150
+
151
+ def load_command_from_source(self, source: str) -> Dict[str, Any]:
152
+ """
153
+ Load command from source.
154
+
155
+ Args:
156
+ source: Source string - local path, URL, or command name from registry
157
+
158
+ Returns:
159
+ Dictionary with loading result information
160
+ """
161
+ result = self._loader.load_command_from_source(source)
162
+
163
+ if result["success"]:
164
+ # Register loaded commands
165
+ for command_class in result["commands"]:
166
+ self.register_loaded(command_class)
167
+
168
+ return result
169
+
170
+
171
+ def command_exists(self, command_name: str) -> bool:
172
+ """
173
+ Check if command exists.
174
+
175
+ Args:
176
+ command_name: Name of the command
177
+
178
+ Returns:
179
+ True if command exists, False otherwise
180
+ """
181
+ return self._manager.command_exists(command_name, self._commands)
182
+
183
+ def get_command(self, command_name: str) -> Type[Command]:
184
+ """
185
+ Get command class by name.
186
+
187
+ Args:
188
+ command_name: Name of the command
189
+
190
+ Returns:
191
+ Command class
192
+
193
+ Raises:
194
+ NotFoundError: If command not found
195
+ """
196
+ if command_name not in self._commands:
197
+ raise KeyError(f"Command '{command_name}' not found")
198
+ return self._commands[command_name]
199
+
200
+ def get_command_instance(self, command_name: str) -> Command:
201
+ """
202
+ Get command instance by name.
203
+
204
+ Args:
205
+ command_name: Name of the command
206
+
207
+ Returns:
208
+ Command instance
209
+
210
+ Raises:
211
+ NotFoundError: If command not found
212
+ """
213
+ return self._manager.get_command_instance(command_name, self._commands, self._instances)
214
+
215
+ def has_instance(self, command_name: str) -> bool:
216
+ """
217
+ Check if command has instance.
218
+
219
+ Args:
220
+ command_name: Name of the command
221
+
222
+ Returns:
223
+ True if command has instance, False otherwise
224
+ """
225
+ return self._manager.has_instance(command_name, self._instances)
226
+
227
+ def get_all_commands(self) -> Dict[str, Type[Command]]:
228
+ """
229
+ Get all registered commands.
230
+
231
+ Returns:
232
+ Dictionary of all commands
233
+ """
234
+ return self._commands
235
+
236
+ def get_commands_by_type(self) -> Dict[str, Dict[str, Type[Command]]]:
237
+ """
238
+ Get commands grouped by type.
239
+
240
+ Returns:
241
+ Dictionary of commands grouped by type
242
+ """
243
+ return self._manager.get_commands_by_type(self._commands, self._command_types)
244
+
245
+ def get_all_metadata(self) -> Dict[str, Dict[str, Any]]:
246
+ """
247
+ Get metadata for all commands.
248
+
249
+ Returns:
250
+ Dictionary of command metadata
251
+ """
252
+ return self._manager.get_all_metadata(self._commands, self._command_types)
253
+
254
+ def clear(self) -> None:
255
+ """Clear all commands and instances."""
256
+ self._manager.clear(self._commands, self._instances, self._command_types)
257
+ self.logger.info("Cleared all commands")
258
+
259
+ def get_all_commands_info(self) -> Dict[str, Any]:
260
+ """
261
+ Get comprehensive information about all commands.
262
+
263
+ Returns:
264
+ Dictionary with command information
265
+ """
266
+ return self._info.get_all_commands_info(self._commands, self._command_types)
267
+
268
+ def get_command_info(self, command_name: str) -> Optional[Dict[str, Any]]:
269
+ """
270
+ Get detailed information about a specific command.
271
+
272
+ Args:
273
+ command_name: Name of the command
274
+
275
+ Returns:
276
+ Dictionary with command information or None if not found
277
+ """
278
+ if command_name not in self._commands:
279
+ return None
280
+
281
+ return self._info.get_command_info(
282
+ command_name,
283
+ self._commands[command_name],
284
+ self._command_types
285
+ )
286
+
287
+ def _load_all_commands(self) -> Dict[str, int]:
288
+ """
289
+ Load all commands from configured directories.
290
+
291
+ Returns:
292
+ Dictionary with loading statistics
293
+ """
294
+ return self._manager._load_all_commands(self._commands, self._command_types)
295
+
296
+
297
+ # Global registry instance
298
+ registry = CommandRegistry()
@@ -0,0 +1,102 @@
1
+ """
2
+ Config command implementation for managing service configuration.
3
+ """
4
+
5
+ from typing import Dict, Any, Optional
6
+
7
+ from mcp_proxy_adapter.commands.base import Command
8
+ from mcp_proxy_adapter.commands.result import SuccessResult
9
+ from mcp_proxy_adapter.config import get_config
10
+
11
+
12
+ class ConfigResult(SuccessResult):
13
+ """
14
+ Config operation result.
15
+ """
16
+
17
+ def __init__(
18
+ self,
19
+ config: Dict[str, Any],
20
+ operation: str,
21
+ message: Optional[str] = None,
22
+ ):
23
+ """
24
+ Initialize config result.
25
+
26
+ Args:
27
+ config: Configuration values
28
+ operation: Operation performed
29
+ message: Optional message
30
+ """
31
+ super().__init__(
32
+ data={"config": config, "operation": operation}, message=message
33
+ )
34
+
35
+
36
+ class ConfigCommand(Command):
37
+ """
38
+ Command for managing service configuration.
39
+ """
40
+
41
+ name = "config"
42
+ description = "Get or set configuration values"
43
+ result_class = ConfigResult
44
+
45
+ async def execute(
46
+ self,
47
+ operation: str = "get",
48
+ path: Optional[str] = None,
49
+ value: Any = None,
50
+ context: Optional[Dict] = None,
51
+ **kwargs,
52
+ ) -> ConfigResult:
53
+ """
54
+ Execute the command.
55
+
56
+ Args:
57
+ operation: Operation to perform (get, set)
58
+ path: Configuration path (dot notation)
59
+ value: Value to set (for set operation)
60
+ context: Optional context parameter passed by framework
61
+ **kwargs: Additional parameters
62
+
63
+ Returns:
64
+ Config operation result
65
+ """
66
+ message = None
67
+ result_config = {}
68
+
69
+ if operation == "get":
70
+ config_instance = get_config()
71
+ if path:
72
+ # Get specific config value
73
+ result_config = {path: config_instance.get(path)}
74
+ else:
75
+ # Get all config
76
+ result_config = config_instance.get_all()
77
+ message = "Configuration retrieved successfully"
78
+
79
+ elif operation == "set":
80
+ if path and value is not None:
81
+ # Set config value
82
+ config_instance = get_config()
83
+ config_instance.set(path, value)
84
+ # Save config
85
+ config_instance.save()
86
+ result_config = {path: value}
87
+ message = "Configuration updated successfully"
88
+ else:
89
+ # Error - missing required parameters
90
+ raise ValueError(
91
+ "Both 'path' and 'value' are required for 'set' operation"
92
+ )
93
+
94
+ else:
95
+ # Invalid operation
96
+ raise ValueError(
97
+ f"Invalid operation: {operation}. Valid operations: get, set"
98
+ )
99
+
100
+ return ConfigResult(config=result_config, operation=operation, message=message)
101
+
102
+ @classmethod
@@ -0,0 +1,40 @@
1
+ """
2
+ Module for dependency injection container implementation.
3
+
4
+ This module provides a container for registering and resolving dependencies
5
+ for command instances in the microservice.
6
+ """
7
+
8
+ from typing import TypeVar, Dict, Any, Callable, Optional
9
+
10
+ T = TypeVar("T")
11
+
12
+
13
+ class DependencyContainer:
14
+ """
15
+ Container for managing dependencies.
16
+
17
+ This class provides functionality to register, resolve, and manage
18
+ dependencies that can be injected into command instances.
19
+ """
20
+
21
+ def __init__(self):
22
+ """Initialize dependency container."""
23
+ self._dependencies: Dict[str, Any] = {}
24
+ self._factories: Dict[str, callable] = {}
25
+ self._singletons: Dict[str, Any] = {}
26
+
27
+
28
+
29
+
30
+
31
+ def clear(self) -> None:
32
+ """Clear all registered dependencies."""
33
+ self._dependencies.clear()
34
+ self._factories.clear()
35
+ self._singletons.clear()
36
+
37
+
38
+
39
+ # Global dependency container instance
40
+ container = DependencyContainer()
@@ -0,0 +1,143 @@
1
+ """
2
+ Dependency management system for remote plugins.
3
+
4
+ This module handles automatic installation and verification of plugin dependencies
5
+ using pip and other package management tools.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ import subprocess
12
+ import sys
13
+ import importlib
14
+ from typing import List, Dict, Any, Tuple
15
+
16
+ try: # Python 3.8+
17
+ from importlib import metadata as importlib_metadata # type: ignore
18
+ except Exception: # pragma: no cover - very old Python fallback
19
+ import importlib_metadata # type: ignore
20
+
21
+ from packaging.requirements import Requirement
22
+ from packaging.version import Version, InvalidVersion
23
+
24
+ from mcp_proxy_adapter.core.logging import get_global_logger
25
+
26
+
27
+ class DependencyManager:
28
+ """
29
+ Manages plugin dependencies installation and verification.
30
+ """
31
+
32
+ def __init__(self):
33
+ """Initialize dependency manager."""
34
+ self._installed_packages: Dict[str, str] = {}
35
+ self._load_installed_packages()
36
+
37
+ def _load_installed_packages(self) -> None:
38
+ """Load list of currently installed packages."""
39
+ try:
40
+ self._installed_packages.clear()
41
+ for dist in importlib_metadata.distributions():
42
+ try:
43
+ name = dist.metadata.get("Name") or dist.metadata.get("name")
44
+ version = dist.version
45
+ if name and version:
46
+ self._installed_packages[name.lower()] = version
47
+ except Exception:
48
+ continue
49
+ except Exception as e:
50
+ get_global_logger().warning(f"Failed to load installed packages: {e}")
51
+
52
+
53
+ def _is_dependency_satisfied(self, dependency: str) -> bool:
54
+ """
55
+ Check if a single dependency is satisfied.
56
+
57
+ Args:
58
+ dependency: Dependency name or spec
59
+
60
+ Returns:
61
+ True if dependency is satisfied, False otherwise
62
+ """
63
+ # Parse requirement (handles version specifiers)
64
+ try:
65
+ req = Requirement(dependency)
66
+ except Exception:
67
+ # Fallback: treat as importable module name
68
+ try:
69
+ importlib.import_module(dependency)
70
+ return True
71
+ except ImportError:
72
+ return False
73
+
74
+ # Check installation by distribution name
75
+ try:
76
+ installed_version = importlib_metadata.version(req.name)
77
+ except importlib_metadata.PackageNotFoundError:
78
+ return False
79
+
80
+ # If no specifier, any installed version satisfies
81
+ if not req.specifier:
82
+ return True
83
+
84
+ try:
85
+ return Version(installed_version) in req.specifier
86
+ except InvalidVersion:
87
+ # If version parsing fails, fallback to string comparison via specifier
88
+ return req.specifier.contains(installed_version, prereleases=True)
89
+
90
+
91
+ def _install_single_dependency(
92
+ self, dependency: str, user_install: bool = False
93
+ ) -> bool:
94
+ """
95
+ Install a single dependency using pip.
96
+
97
+ Args:
98
+ dependency: Dependency name or spec
99
+ user_install: Whether to install for current user only
100
+
101
+ Returns:
102
+ True if installation successful, False otherwise
103
+ """
104
+ try:
105
+ # Build pip command
106
+ cmd = [sys.executable, "-m", "pip", "install"]
107
+
108
+ if user_install:
109
+ cmd.append("--user")
110
+
111
+ # Add quiet flag to reduce output
112
+ cmd.append("--quiet")
113
+
114
+ # Add dependency
115
+ cmd.append(dependency)
116
+
117
+ get_global_logger().debug(f"Installing dependency: {' '.join(cmd)}")
118
+
119
+ # Run pip install
120
+ result = subprocess.run(
121
+ cmd, capture_output=True, text=True, timeout=300 # 5 minutes timeout
122
+ )
123
+
124
+ if result.returncode == 0:
125
+ get_global_logger().debug(f"Successfully installed {dependency}")
126
+ return True
127
+ else:
128
+ get_global_logger().error(f"Failed to install {dependency}: {result.stderr}")
129
+ return False
130
+
131
+ except subprocess.TimeoutExpired:
132
+ get_global_logger().error(f"Timeout while installing {dependency}")
133
+ return False
134
+ except Exception as e:
135
+ get_global_logger().error(f"Error installing {dependency}: {e}")
136
+ return False
137
+
138
+
139
+
140
+
141
+
142
+ # Global instance
143
+ dependency_manager = DependencyManager()
@@ -0,0 +1,48 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Echo command for testing purposes.
6
+ """
7
+
8
+ import asyncio
9
+ from typing import Any, Dict, Optional
10
+
11
+ from mcp_proxy_adapter.commands.base import Command
12
+ from mcp_proxy_adapter.commands.result import SuccessResult
13
+
14
+
15
+ class EchoCommandResult(SuccessResult):
16
+ """Result for echo command."""
17
+
18
+ def __init__(self, message: str, timestamp: Optional[str] = None):
19
+ data = {"message": message}
20
+ if timestamp:
21
+ data["timestamp"] = timestamp
22
+ super().__init__(data=data, message=message)
23
+
24
+ @classmethod
25
+
26
+
27
+ class EchoCommand(Command):
28
+ """Echo command for testing purposes."""
29
+
30
+ name = "echo"
31
+ version = "1.0.0"
32
+ descr = "Echo command for testing"
33
+ category = "testing"
34
+ author = "Vasiliy Zdanovskiy"
35
+ email = "vasilyvz@gmail.com"
36
+ result_class = EchoCommandResult
37
+
38
+ async def execute(self, **kwargs) -> EchoCommandResult:
39
+ """Execute echo command."""
40
+ message = kwargs.get("message", "Hello, World!")
41
+ timestamp = kwargs.get("timestamp")
42
+
43
+ # Simulate some processing time
44
+ await asyncio.sleep(0.001)
45
+
46
+ return EchoCommandResult(message=message, timestamp=timestamp)
47
+
48
+ @classmethod