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,502 @@
1
+ """
2
+ Roles Management Command
3
+
4
+ This module provides commands for managing roles in the role-based access control system.
5
+ Includes commands for listing, creating, updating, deleting, and validating roles.
6
+
7
+ Author: MCP Proxy Adapter Team
8
+ Version: 1.0.0
9
+ """
10
+
11
+ import json
12
+ import logging
13
+ from pathlib import Path
14
+
15
+ from .base import Command
16
+ from .result import CommandResult, SuccessResult, ErrorResult
17
+ from ..core.role_utils import RoleUtils
18
+ from ..core.errors import ValidationError, NotFoundError, InternalError
19
+
20
+ from mcp_proxy_adapter.core.logging import get_global_logger
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class RolesListResult(SuccessResult):
25
+ """
26
+ Result for roles list command.
27
+ """
28
+
29
+ def __init__(self, roles: List[Dict[str, Any]], total_count: int):
30
+ """
31
+ Initialize roles list result.
32
+
33
+ Args:
34
+ roles: List of role configurations
35
+ total_count: Total number of roles
36
+ """
37
+ super().__init__()
38
+ self.success = True
39
+ self.roles = roles
40
+ self.total_count = total_count
41
+
42
+
43
+ @classmethod
44
+
45
+
46
+ class RolesCreateResult(SuccessResult):
47
+ """
48
+ Result for roles create command.
49
+ """
50
+
51
+ def __init__(self, role_name: str, role_config: Dict[str, Any]):
52
+ """
53
+ Initialize roles create result.
54
+
55
+ Args:
56
+ role_name: Name of created role
57
+ role_config: Role configuration
58
+ """
59
+ super().__init__()
60
+ self.success = True
61
+ self.role_name = role_name
62
+ self.role_config = role_config
63
+
64
+
65
+ @classmethod
66
+
67
+
68
+ class RolesUpdateResult(SuccessResult):
69
+ """
70
+ Result for roles update command.
71
+ """
72
+
73
+ def __init__(self, role_name: str, role_config: Dict[str, Any]):
74
+ """
75
+ Initialize roles update result.
76
+
77
+ Args:
78
+ role_name: Name of updated role
79
+ role_config: Updated role configuration
80
+ """
81
+ super().__init__()
82
+ self.success = True
83
+ self.role_name = role_name
84
+ self.role_config = role_config
85
+
86
+
87
+ @classmethod
88
+
89
+
90
+ class RolesDeleteResult(SuccessResult):
91
+ """
92
+ Result for roles delete command.
93
+ """
94
+
95
+ def __init__(self, role_name: str):
96
+ """
97
+ Initialize roles delete result.
98
+
99
+ Args:
100
+ role_name: Name of deleted role
101
+ """
102
+ super().__init__()
103
+ self.success = True
104
+ self.role_name = role_name
105
+
106
+
107
+ @classmethod
108
+
109
+
110
+ class RolesValidateResult(SuccessResult):
111
+ """
112
+ Result for roles validate command.
113
+ """
114
+
115
+ def __init__(self, role_name: str, is_valid: bool, validation_errors: List[str]):
116
+ """
117
+ Initialize roles validate result.
118
+
119
+ Args:
120
+ role_name: Name of validated role
121
+ is_valid: Whether role is valid
122
+ validation_errors: List of validation errors
123
+ """
124
+ super().__init__()
125
+ self.success = True
126
+ self.role_name = role_name
127
+ self.is_valid = is_valid
128
+ self.validation_errors = validation_errors
129
+
130
+
131
+ @classmethod
132
+
133
+
134
+ class RolesManagementCommand(Command):
135
+ """
136
+ Command for managing roles in the role-based access control system.
137
+ """
138
+
139
+ name = "roles_management"
140
+ version = "1.0.0"
141
+ descr = "Manage roles in the role-based access control system"
142
+ category = "security"
143
+ author = "MCP Proxy Adapter Team"
144
+ email = "team@mcp-proxy-adapter.com"
145
+ source_url = "https://github.com/mcp-proxy-adapter"
146
+
147
+ def __init__(self, roles_config_path: str = "schemas/roles_schema.json"):
148
+ """
149
+ Initialize roles management command.
150
+
151
+ Args:
152
+ roles_config_path: Path to roles configuration file
153
+ """
154
+ self.roles_config_path = roles_config_path
155
+ self.role_utils = RoleUtils()
156
+ self.roles_config = self._load_roles_config()
157
+
158
+ def _load_roles_config(self) -> Dict[str, Any]:
159
+ """
160
+ Load roles configuration from file.
161
+
162
+ Returns:
163
+ Roles configuration dictionary
164
+ """
165
+ try:
166
+ config_path = Path(self.roles_config_path)
167
+ if not config_path.exists():
168
+ get_global_logger().warning(f"Roles config file not found: {self.roles_config_path}")
169
+ return {"roles": {}, "server_roles": {}, "role_hierarchy": {}}
170
+
171
+ with open(config_path, "r", encoding="utf-8") as f:
172
+ config = json.load(f)
173
+
174
+ return config
175
+
176
+ except Exception as e:
177
+ get_global_logger().error(f"Failed to load roles configuration: {e}")
178
+ return {"roles": {}, "server_roles": {}, "role_hierarchy": {}}
179
+
180
+ def _save_roles_config(self) -> None:
181
+ """
182
+ Save roles configuration to file.
183
+ """
184
+ try:
185
+ config_path = Path(self.roles_config_path)
186
+ config_path.parent.mkdir(parents=True, exist_ok=True)
187
+
188
+ with open(config_path, "w", encoding="utf-8") as f:
189
+ json.dump(self.roles_config, f, indent=2, ensure_ascii=False)
190
+
191
+ get_global_logger().info(f"Roles configuration saved to {self.roles_config_path}")
192
+
193
+ except Exception as e:
194
+ get_global_logger().error(f"Failed to save roles configuration: {e}")
195
+ raise InternalError(f"Failed to save roles configuration: {e}")
196
+
197
+ async def execute(self, **kwargs) -> CommandResult:
198
+ """
199
+ Execute roles management command.
200
+
201
+ Args:
202
+ **kwargs: Command parameters including 'action' and role-specific parameters
203
+
204
+ Returns:
205
+ Command result
206
+ """
207
+ try:
208
+ action = kwargs.get("action")
209
+
210
+ if action == "list":
211
+ return await self.roles_list(**kwargs)
212
+ elif action == "create":
213
+ return await self.roles_create(**kwargs)
214
+ elif action == "update":
215
+ return await self.roles_update(**kwargs)
216
+ elif action == "delete":
217
+ return await self.roles_delete(**kwargs)
218
+ elif action == "validate":
219
+ return await self.roles_validate(**kwargs)
220
+ else:
221
+ raise ValidationError(
222
+ f"Invalid action: {action}. "
223
+ f"Valid actions: list, create, update, delete, validate"
224
+ )
225
+
226
+ except Exception as e:
227
+ get_global_logger().error(f"Roles management command failed: {e}")
228
+ return ErrorResult(str(e))
229
+
230
+ async def roles_list(self, **kwargs) -> RolesListResult:
231
+ """
232
+ List all roles.
233
+
234
+ Args:
235
+ **kwargs: Additional parameters (filter, limit, offset)
236
+
237
+ Returns:
238
+ Roles list result
239
+ """
240
+ roles = self.roles_config.get("roles", {})
241
+
242
+ # Apply filters if specified
243
+ filter_name = kwargs.get("filter")
244
+ if filter_name:
245
+ roles = {
246
+ name: config
247
+ for name, config in roles.items()
248
+ if filter_name.lower() in name.lower()
249
+ }
250
+
251
+ # Convert to list format
252
+ roles_list = []
253
+ for name, config in roles.items():
254
+ role_info = {
255
+ "name": name,
256
+ "description": config.get("description", ""),
257
+ "allowed_servers": config.get("allowed_servers", []),
258
+ "allowed_clients": config.get("allowed_clients", []),
259
+ "permissions": config.get("permissions", []),
260
+ "priority": config.get("priority", 0),
261
+ }
262
+ roles_list.append(role_info)
263
+
264
+ # Apply pagination
265
+ limit = kwargs.get("limit")
266
+ offset = kwargs.get("offset", 0)
267
+
268
+ if limit:
269
+ roles_list = roles_list[offset : offset + limit]
270
+ elif offset:
271
+ roles_list = roles_list[offset:]
272
+
273
+ return RolesListResult(roles_list, len(roles))
274
+
275
+ async def roles_create(self, **kwargs) -> RolesCreateResult:
276
+ """
277
+ Create a new role.
278
+
279
+ Args:
280
+ **kwargs: Role parameters (role_name, description, allowed_servers, etc.)
281
+
282
+ Returns:
283
+ Roles create result
284
+ """
285
+ role_name = kwargs.get("role_name")
286
+ if not role_name:
287
+ raise ValidationError("role_name is required")
288
+
289
+ # Validate role name
290
+ if not self.role_utils.validate_single_role(role_name):
291
+ raise ValidationError(f"Invalid role name: {role_name}")
292
+
293
+ # Check if role already exists
294
+ if role_name in self.roles_config.get("roles", {}):
295
+ raise ValidationError(f"Role {role_name} already exists")
296
+
297
+ # Create role configuration
298
+ role_config = {
299
+ "description": kwargs.get("description", ""),
300
+ "allowed_servers": kwargs.get("allowed_servers", []),
301
+ "allowed_clients": kwargs.get("allowed_clients", []),
302
+ "permissions": kwargs.get("permissions", []),
303
+ "priority": kwargs.get("priority", 0),
304
+ }
305
+
306
+ # Validate role configuration
307
+ validation_errors = self._validate_role_config(role_config)
308
+ if validation_errors:
309
+ raise ValidationError(
310
+ f"Invalid role configuration: {', '.join(validation_errors)}"
311
+ )
312
+
313
+ # Add role to configuration
314
+ if "roles" not in self.roles_config:
315
+ self.roles_config["roles"] = {}
316
+
317
+ self.roles_config["roles"][role_name] = role_config
318
+
319
+ # Save configuration
320
+ self._save_roles_config()
321
+
322
+ get_global_logger().info(f"Role {role_name} created successfully")
323
+ return RolesCreateResult(role_name, role_config)
324
+
325
+ async def roles_update(self, **kwargs) -> RolesUpdateResult:
326
+ """
327
+ Update an existing role.
328
+
329
+ Args:
330
+ **kwargs: Role parameters (role_name, description, allowed_servers, etc.)
331
+
332
+ Returns:
333
+ Roles update result
334
+ """
335
+ role_name = kwargs.get("role_name")
336
+ if not role_name:
337
+ raise ValidationError("role_name is required")
338
+
339
+ # Check if role exists
340
+ if role_name not in self.roles_config.get("roles", {}):
341
+ raise NotFoundError(f"Role {role_name} not found")
342
+
343
+ # Get existing configuration
344
+ existing_config = self.roles_config["roles"][role_name]
345
+
346
+ # Update configuration with new values
347
+ updated_config = existing_config.copy()
348
+ for key in [
349
+ "description",
350
+ "allowed_servers",
351
+ "allowed_clients",
352
+ "permissions",
353
+ "priority",
354
+ ]:
355
+ if key in kwargs:
356
+ updated_config[key] = kwargs[key]
357
+
358
+ # Validate updated configuration
359
+ validation_errors = self._validate_role_config(updated_config)
360
+ if validation_errors:
361
+ raise ValidationError(
362
+ f"Invalid role configuration: {', '.join(validation_errors)}"
363
+ )
364
+
365
+ # Update role configuration
366
+ self.roles_config["roles"][role_name] = updated_config
367
+
368
+ # Save configuration
369
+ self._save_roles_config()
370
+
371
+ get_global_logger().info(f"Role {role_name} updated successfully")
372
+ return RolesUpdateResult(role_name, updated_config)
373
+
374
+ async def roles_delete(self, **kwargs) -> RolesDeleteResult:
375
+ """
376
+ Delete a role.
377
+
378
+ Args:
379
+ **kwargs: Role parameters (role_name)
380
+
381
+ Returns:
382
+ Roles delete result
383
+ """
384
+ role_name = kwargs.get("role_name")
385
+ if not role_name:
386
+ raise ValidationError("role_name is required")
387
+
388
+ # Check if role exists
389
+ if role_name not in self.roles_config.get("roles", {}):
390
+ raise NotFoundError(f"Role {role_name} not found")
391
+
392
+ # Check if role is system role
393
+ if self.role_utils.is_system_role(role_name):
394
+ raise ValidationError(f"Cannot delete system role: {role_name}")
395
+
396
+ # Remove role from configuration
397
+ del self.roles_config["roles"][role_name]
398
+
399
+ # Remove from role hierarchy
400
+ if "role_hierarchy" in self.roles_config:
401
+ if role_name in self.roles_config["role_hierarchy"]:
402
+ del self.roles_config["role_hierarchy"][role_name]
403
+
404
+ # Remove from other roles' hierarchies
405
+ for other_role, hierarchy in self.roles_config["role_hierarchy"].items():
406
+ if role_name in hierarchy:
407
+ hierarchy.remove(role_name)
408
+
409
+ # Save configuration
410
+ self._save_roles_config()
411
+
412
+ get_global_logger().info(f"Role {role_name} deleted successfully")
413
+ return RolesDeleteResult(role_name)
414
+
415
+ async def roles_validate(self, **kwargs) -> RolesValidateResult:
416
+ """
417
+ Validate a role configuration.
418
+
419
+ Args:
420
+ **kwargs: Role parameters (role_name or role_config)
421
+
422
+ Returns:
423
+ Roles validate result
424
+ """
425
+ role_name = kwargs.get("role_name")
426
+ role_config = kwargs.get("role_config")
427
+
428
+ if not role_name and not role_config:
429
+ raise ValidationError("Either role_name or role_config is required")
430
+
431
+ validation_errors = []
432
+
433
+ if role_name:
434
+ # Validate existing role
435
+ if role_name not in self.roles_config.get("roles", {}):
436
+ validation_errors.append(f"Role {role_name} not found")
437
+ else:
438
+ role_config = self.roles_config["roles"][role_name]
439
+
440
+ if role_config:
441
+ # Validate role configuration
442
+ config_errors = self._validate_role_config(role_config)
443
+ validation_errors.extend(config_errors)
444
+
445
+ is_valid = len(validation_errors) == 0
446
+
447
+ return RolesValidateResult(role_name or "unknown", is_valid, validation_errors)
448
+
449
+ def _validate_role_config(self, role_config: Dict[str, Any]) -> List[str]:
450
+ """
451
+ Validate role configuration.
452
+
453
+ Args:
454
+ role_config: Role configuration to validate
455
+
456
+ Returns:
457
+ List of validation errors
458
+ """
459
+ errors = []
460
+
461
+ # Validate description
462
+ description = role_config.get("description", "")
463
+ if not isinstance(description, str):
464
+ errors.append("description must be a string")
465
+
466
+ # Validate allowed_servers
467
+ allowed_servers = role_config.get("allowed_servers", [])
468
+ if not isinstance(allowed_servers, list):
469
+ errors.append("allowed_servers must be a list")
470
+ else:
471
+ for server in allowed_servers:
472
+ if not isinstance(server, str):
473
+ errors.append("allowed_servers must contain only strings")
474
+
475
+ # Validate allowed_clients
476
+ allowed_clients = role_config.get("allowed_clients", [])
477
+ if not isinstance(allowed_clients, list):
478
+ errors.append("allowed_clients must be a list")
479
+ else:
480
+ for client in allowed_clients:
481
+ if not isinstance(client, str):
482
+ errors.append("allowed_clients must contain only strings")
483
+
484
+ # Validate permissions
485
+ permissions = role_config.get("permissions", [])
486
+ if not isinstance(permissions, list):
487
+ errors.append("permissions must be a list")
488
+ else:
489
+ for permission in permissions:
490
+ if not isinstance(permission, str):
491
+ errors.append("permissions must contain only strings")
492
+
493
+ # Validate priority
494
+ priority = role_config.get("priority", 0)
495
+ if not isinstance(priority, int):
496
+ errors.append("priority must be an integer")
497
+ elif priority < 0:
498
+ errors.append("priority must be non-negative")
499
+
500
+ return errors
501
+
502
+ @classmethod