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,342 @@
1
+ """
2
+ Direct Security Framework Integration
3
+
4
+ This module provides direct integration with mcp_security_framework,
5
+ replacing all project security methods with framework calls.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ from typing import Dict, Any, List
12
+
13
+ # Direct imports from framework
14
+ try:
15
+ from mcp_security_framework import (
16
+ SecurityManager,
17
+ AuthManager,
18
+ CertificateManager,
19
+ PermissionManager,
20
+ RateLimiter,
21
+ )
22
+ from mcp_security_framework.schemas.config import (
23
+ SecurityConfig,
24
+ AuthConfig,
25
+ SSLConfig,
26
+ PermissionConfig,
27
+ RateLimitConfig,
28
+ CertificateConfig,
29
+ LoggingConfig,
30
+ )
31
+ from mcp_security_framework.schemas.models import (
32
+ AuthResult,
33
+ ValidationResult,
34
+ CertificatePair,
35
+ )
36
+ from mcp_security_framework.middleware.fastapi_middleware import (
37
+ FastAPISecurityMiddleware,
38
+ )
39
+
40
+ SECURITY_FRAMEWORK_AVAILABLE = True
41
+ except ImportError as e:
42
+ # NO FALLBACK! mcp_security_framework is REQUIRED
43
+ raise RuntimeError(
44
+ f"CRITICAL: mcp_security_framework is required but not available: {e}. "
45
+ "Install it with: pip install mcp_security_framework>=1.2.8"
46
+ ) from e
47
+
48
+ from mcp_proxy_adapter.core.logging import get_global_logger
49
+
50
+
51
+ class SecurityIntegration:
52
+ """
53
+ Direct integration with mcp_security_framework.
54
+
55
+ This class replaces all project security methods with direct calls
56
+ to the security framework components.
57
+ """
58
+
59
+ def __init__(self, config: Dict[str, Any]):
60
+ """
61
+ Initialize security integration.
62
+
63
+ Args:
64
+ config: Configuration dictionary
65
+ """
66
+ if not SECURITY_FRAMEWORK_AVAILABLE:
67
+ raise ImportError("mcp_security_framework is not available")
68
+
69
+ self.config = config
70
+ self.security_config = self._create_security_config()
71
+
72
+ # Initialize framework components
73
+ self.security_manager = SecurityManager(self.security_config)
74
+ self.permission_manager = PermissionManager(self.security_config.permissions)
75
+ self.auth_manager = AuthManager(
76
+ self.security_config.auth, self.permission_manager
77
+ )
78
+ self.certificate_manager = CertificateManager(self.security_config.certificates)
79
+ self.rate_limiter = RateLimiter(self.security_config.rate_limit)
80
+
81
+ get_global_logger().info("Security integration initialized with mcp_security_framework")
82
+
83
+ def _create_security_config(self) -> SecurityConfig:
84
+ """Create SecurityConfig from project configuration."""
85
+ # self.config is already the security section passed from unified_security.py
86
+ security_section = self.config
87
+
88
+ # Create SSL config - SSL is handled by server protocol, not security config
89
+ ssl_config = SSLConfig(
90
+ enabled=False, # SSL is handled by server protocol
91
+ cert_file=None,
92
+ key_file=None,
93
+ ca_cert_file=None,
94
+ client_cert_file=None,
95
+ client_key_file=None,
96
+ verify_mode="CERT_REQUIRED",
97
+ min_tls_version="TLSv1.2",
98
+ check_hostname=True,
99
+ check_expiry=True,
100
+ expiry_warning_days=30,
101
+ )
102
+
103
+ # Create auth config - use new simplified structure
104
+ auth_config = AuthConfig(
105
+ enabled=security_section.get("enabled", True),
106
+ methods=["api_key"], # Use token-based authentication
107
+ api_keys=security_section.get("tokens", {}),
108
+ user_roles={}, # Will be handled by permissions
109
+ jwt_secret=None,
110
+ jwt_algorithm="HS256",
111
+ jwt_expiry_hours=24,
112
+ certificate_auth=False,
113
+ public_paths=[],
114
+ )
115
+
116
+ # Create permission config - use new simplified structure
117
+ roles = security_section.get("roles", {})
118
+ roles_file = security_section.get("roles_file")
119
+
120
+ # Enable permissions if we have roles or roles_file
121
+ permissions_enabled = bool(roles or roles_file)
122
+
123
+ if permissions_enabled:
124
+ # If roles_file is None or empty string, don't pass it to avoid framework errors
125
+ if roles_file is None or roles_file == "":
126
+ get_global_logger().warning(
127
+ "roles_file is None or empty, permissions will use default configuration"
128
+ )
129
+ roles_file = None
130
+
131
+ permission_config = PermissionConfig(
132
+ enabled=True,
133
+ roles_file=roles_file,
134
+ default_role="guest",
135
+ admin_role="admin",
136
+ role_hierarchy={},
137
+ permission_cache_enabled=True,
138
+ permission_cache_ttl=300,
139
+ wildcard_permissions=False,
140
+ strict_mode=True,
141
+ roles=roles,
142
+ )
143
+ else:
144
+ # Create minimal permission config when permissions are disabled
145
+ permission_config = PermissionConfig(
146
+ enabled=False,
147
+ roles_file=None,
148
+ default_role="guest",
149
+ admin_role="admin",
150
+ role_hierarchy={},
151
+ permission_cache_enabled=False,
152
+ permission_cache_ttl=300,
153
+ wildcard_permissions=False,
154
+ strict_mode=False,
155
+ roles={},
156
+ )
157
+
158
+ # Create rate limit config - use defaults since rate_limit section doesn't exist in new structure
159
+ rate_limit_config = RateLimitConfig(
160
+ enabled=True,
161
+ default_requests_per_minute=60,
162
+ default_requests_per_hour=1000,
163
+ burst_limit=2,
164
+ window_size_seconds=60,
165
+ storage_backend="memory",
166
+ exempt_paths=[],
167
+ exempt_roles=[],
168
+ )
169
+
170
+ # Create certificate config - certificates are handled by server protocol
171
+ certificate_config = CertificateConfig(
172
+ enabled=False, # Certificates are handled by server protocol
173
+ ca_cert_path=None,
174
+ ca_key_path=None,
175
+ cert_storage_path="./certs",
176
+ key_storage_path="./keys",
177
+ default_validity_days=365,
178
+ key_size=2048,
179
+ hash_algorithm="sha256",
180
+ )
181
+
182
+ # Create logging config - use defaults since logging section doesn't exist in new structure
183
+ logging_config = LoggingConfig(
184
+ enabled=True,
185
+ level="INFO",
186
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
187
+ console_output=True,
188
+ file_path=None,
189
+ )
190
+
191
+ # Create main security config
192
+ return SecurityConfig(
193
+ ssl=ssl_config,
194
+ auth=auth_config,
195
+ permissions=permission_config,
196
+ rate_limit=rate_limit_config,
197
+ certificates=certificate_config,
198
+ logging=logging_config,
199
+ debug=security_section.get("debug", False),
200
+ environment=security_section.get("environment", "dev"),
201
+ version=security_section.get("version", "1.0.0"),
202
+ )
203
+
204
+ # Authentication methods - direct calls to AuthManager
205
+ async def authenticate_api_key(self, api_key: str) -> AuthResult:
206
+ """Authenticate using API key."""
207
+ return await self.auth_manager.authenticate_api_key(api_key)
208
+
209
+ async def authenticate_jwt(self, token: str) -> AuthResult:
210
+ """Authenticate using JWT token."""
211
+ return await self.auth_manager.authenticate_jwt(token)
212
+
213
+ async def authenticate_certificate(self, cert_data: bytes) -> AuthResult:
214
+ """Authenticate using certificate."""
215
+ return await self.auth_manager.authenticate_certificate(cert_data)
216
+
217
+ async def validate_request(self, request_data: Dict[str, Any]) -> ValidationResult:
218
+ """Validate request using security manager."""
219
+ return await self.security_manager.validate_request(request_data)
220
+
221
+ # Certificate methods - direct calls to CertificateManager
222
+ async def create_ca_certificate(
223
+ self, common_name: str, **kwargs
224
+ ) -> CertificatePair:
225
+ """Create CA certificate."""
226
+ return await self.certificate_manager.create_ca_certificate(
227
+ common_name, **kwargs
228
+ )
229
+
230
+ async def create_client_certificate(
231
+ self, common_name: str, **kwargs
232
+ ) -> CertificatePair:
233
+ """Create client certificate."""
234
+ return await self.certificate_manager.create_client_certificate(
235
+ common_name, **kwargs
236
+ )
237
+
238
+ async def create_server_certificate(
239
+ self, common_name: str, **kwargs
240
+ ) -> CertificatePair:
241
+ """Create server certificate."""
242
+ return await self.certificate_manager.create_server_certificate(
243
+ common_name, **kwargs
244
+ )
245
+
246
+ async def validate_certificate(self, cert_path: str) -> bool:
247
+ """Validate certificate with CRL check if enabled."""
248
+ try:
249
+ # Get CRL configuration from security config
250
+ crl_config = None
251
+ if hasattr(self.security_config, "certificates"):
252
+ cert_config = self.security_config.certificates
253
+ # Only analyze CRL paths if certificates are enabled
254
+ if (
255
+ hasattr(cert_config, "enabled")
256
+ and cert_config.enabled
257
+ and hasattr(cert_config, "crl_enabled")
258
+ and cert_config.crl_enabled
259
+ ):
260
+ crl_config = {
261
+ "crl_enabled": cert_config.crl_enabled,
262
+ "crl_path": getattr(cert_config, "crl_path", None),
263
+ "crl_url": getattr(cert_config, "crl_url", None),
264
+ "crl_validity_days": getattr(
265
+ cert_config, "crl_validity_days", 30
266
+ ),
267
+ }
268
+
269
+ # Use mcp_security_framework's validate_certificate_chain with CRL
270
+ if crl_config and crl_config.get("crl_enabled"):
271
+ from mcp_security_framework.utils.cert_utils import (
272
+ validate_certificate_chain,
273
+ )
274
+ from .crl_utils import CRLManager
275
+
276
+ # Get CRL data
277
+ crl_manager = CRLManager(crl_config)
278
+ crl_data = crl_manager.get_crl_data()
279
+
280
+ # Validate with CRL
281
+ if crl_data:
282
+ return validate_certificate_chain(
283
+ cert_path,
284
+ self.security_config.certificates.ca_cert_path,
285
+ crl_data,
286
+ )
287
+
288
+ # Fallback to standard validation
289
+ return await self.certificate_manager.validate_certificate(cert_path)
290
+
291
+ except Exception as e:
292
+ get_global_logger().error(f"Certificate validation failed: {e}")
293
+ return False
294
+
295
+ async def extract_roles_from_certificate(self, cert_path: str) -> List[str]:
296
+ """Extract roles from certificate."""
297
+ return await self.certificate_manager.extract_roles_from_certificate(cert_path)
298
+
299
+ async def revoke_certificate(self, cert_path: str) -> bool:
300
+ """Revoke certificate."""
301
+ return await self.certificate_manager.revoke_certificate(cert_path)
302
+
303
+ # Permission methods - direct calls to PermissionManager
304
+ async def check_permission(self, user_id: str, permission: str) -> bool:
305
+ """Check user permission."""
306
+ return await self.permission_manager.check_permission(user_id, permission)
307
+
308
+ async def get_user_roles(self, user_id: str) -> List[str]:
309
+ """Get user roles."""
310
+ return await self.permission_manager.get_user_roles(user_id)
311
+
312
+ async def add_user_role(self, user_id: str, role: str) -> bool:
313
+ """Add role to user."""
314
+ return await self.permission_manager.add_user_role(user_id, role)
315
+
316
+ async def remove_user_role(self, user_id: str, role: str) -> bool:
317
+ """Remove role from user."""
318
+ return await self.permission_manager.remove_user_role(user_id, role)
319
+
320
+ # Rate limiting methods - direct calls to RateLimiter
321
+ async def check_rate_limit(
322
+ self, identifier: str, limit_type: str = "per_minute"
323
+ ) -> bool:
324
+ """Check rate limit."""
325
+ return await self.rate_limiter.check_rate_limit(identifier, limit_type)
326
+
327
+ async def increment_rate_limit(self, identifier: str) -> None:
328
+ """Increment rate limit counter."""
329
+ await self.rate_limiter.increment_rate_limit(identifier)
330
+
331
+ async def get_rate_limit_info(self, identifier: str) -> Dict[str, Any]:
332
+ """Get rate limit information."""
333
+ return await self.rate_limiter.get_rate_limit_info(identifier)
334
+
335
+ # Middleware creation - direct use of framework middleware
336
+
337
+ # Utility methods
338
+
339
+
340
+
341
+
342
+ # Factory function for easy integration
@@ -0,0 +1,251 @@
1
+ """
2
+ Server Configuration Adapter
3
+
4
+ This module provides adapters for converting configuration between different
5
+ server engines and handling SSL configuration mapping.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ import logging
12
+ from typing import Dict, Any, Optional
13
+
14
+ from .server_engine import ServerEngineFactory, ServerEngine
15
+ from .logging import get_global_logger
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class ServerConfigAdapter:
21
+ """
22
+ Adapter for converting server configurations between different engines.
23
+
24
+ This class handles the mapping of configuration parameters between
25
+ different server engines and provides unified configuration management.
26
+ """
27
+
28
+ @staticmethod
29
+ def convert_ssl_config_for_engine(
30
+ ssl_config: Dict[str, Any], target_engine: str
31
+ ) -> Dict[str, Any]:
32
+ """
33
+ Convert SSL configuration for a specific server engine.
34
+
35
+ Args:
36
+ ssl_config: Source SSL configuration
37
+ target_engine: Target engine name (hypercorn)
38
+
39
+ Returns:
40
+ Converted SSL configuration for the target engine
41
+ """
42
+ engine = ServerEngineFactory.get_engine(target_engine)
43
+ if not engine:
44
+ get_global_logger().error(f"Unknown server engine: {target_engine}")
45
+ return {}
46
+
47
+ if target_engine == "hypercorn":
48
+ return ServerConfigAdapter._convert_to_hypercorn_ssl(ssl_config)
49
+ else:
50
+ get_global_logger().warning(f"No SSL conversion available for engine: {target_engine}")
51
+ return {}
52
+
53
+ @staticmethod
54
+ def _convert_to_hypercorn_ssl(ssl_config: Dict[str, Any]) -> Dict[str, Any]:
55
+ """Convert SSL configuration to hypercorn format."""
56
+ hypercorn_ssl = {}
57
+
58
+ # Map SSL parameters
59
+ if ssl_config.get("cert_file"):
60
+ hypercorn_ssl["certfile"] = ssl_config["cert_file"]
61
+ if ssl_config.get("key_file"):
62
+ hypercorn_ssl["keyfile"] = ssl_config["key_file"]
63
+ if ssl_config.get("ca_cert"):
64
+ hypercorn_ssl["ca_certs"] = ssl_config["ca_cert"]
65
+
66
+ # Map verification mode
67
+ if ssl_config.get("verify_client", False):
68
+ hypercorn_ssl["verify_mode"] = 2 # ssl.CERT_REQUIRED
69
+
70
+ # Map hostname checking
71
+ if "chk_hostname" in ssl_config:
72
+ hypercorn_ssl["check_hostname"] = ssl_config["chk_hostname"]
73
+
74
+ get_global_logger().debug(f"Converted SSL config to hypercorn: {hypercorn_ssl}")
75
+ return hypercorn_ssl
76
+
77
+ @staticmethod
78
+
79
+ @staticmethod
80
+ def validate_engine_compatibility(config: Dict[str, Any], engine_name: str) -> bool:
81
+ """
82
+ Validate if a configuration is compatible with a specific engine.
83
+
84
+ Args:
85
+ config: Server configuration
86
+ engine_name: Name of the server engine
87
+
88
+ Returns:
89
+ True if compatible, False otherwise
90
+ """
91
+ engine = ServerEngineFactory.get_engine(engine_name)
92
+ if not engine:
93
+ get_global_logger().error(f"Unknown engine: {engine_name}")
94
+ return False
95
+
96
+ # Check SSL requirements
97
+ ssl_config = config.get("ssl", {})
98
+ if not ssl_config:
99
+ # Try to get SSL config from security section
100
+ ssl_config = config.get("security", {}).get("ssl", {})
101
+
102
+ if ssl_config.get("verify_client", False):
103
+ if not engine.get_supported_features().get("mtls_client_certs", False):
104
+ get_global_logger().error(
105
+ f"Engine {engine_name} doesn't support mTLS client certificates"
106
+ )
107
+ return False
108
+
109
+ # Validate engine-specific configuration
110
+ return engine.validate_config(config)
111
+
112
+ @staticmethod
113
+ def get_engine_capabilities(engine_name: str) -> Dict[str, Any]:
114
+ """
115
+ Get capabilities of a specific server engine.
116
+
117
+ Args:
118
+ engine_name: Name of the server engine
119
+
120
+ Returns:
121
+ Dictionary of engine capabilities
122
+ """
123
+ engine = ServerEngineFactory.get_engine(engine_name)
124
+ if not engine:
125
+ return {}
126
+
127
+ return {
128
+ "name": engine.get_name(),
129
+ "features": engine.get_supported_features(),
130
+ "config_schema": engine.get_config_schema(),
131
+ }
132
+
133
+
134
+ class UnifiedServerRunner:
135
+ """
136
+ Unified server runner that uses hypercorn as the default engine.
137
+
138
+ This class provides a unified interface for running servers using hypercorn
139
+ as the underlying engine.
140
+ """
141
+
142
+ def __init__(self, default_engine: str = "hypercorn"):
143
+ """
144
+ Initialize the unified server runner.
145
+
146
+ Args:
147
+ default_engine: Default engine to use (currently only hypercorn is supported)
148
+ """
149
+ self.default_engine = default_engine
150
+ self.available_engines = ServerEngineFactory.get_available_engines()
151
+
152
+ get_global_logger().info(f"Available engines: {list(self.available_engines.keys())}")
153
+ get_global_logger().info(f"Default engine: {default_engine}")
154
+
155
+ def run_server(
156
+ self, app: Any, config: Dict[str, Any], engine_name: Optional[str] = None
157
+ ) -> None:
158
+ """
159
+ Run server with hypercorn engine.
160
+
161
+ Args:
162
+ app: ASGI application
163
+ config: Server configuration
164
+ engine_name: Engine to use (currently only hypercorn is supported)
165
+ """
166
+ # Use hypercorn as the only supported engine
167
+ selected_engine = "hypercorn"
168
+ get_global_logger().info(f"Using hypercorn engine")
169
+
170
+ # Validate compatibility
171
+ if not ServerConfigAdapter.validate_engine_compatibility(
172
+ config, selected_engine
173
+ ):
174
+ raise ValueError(
175
+ f"Configuration not compatible with engine: {selected_engine}"
176
+ )
177
+
178
+ # Get engine instance
179
+ engine = ServerEngineFactory.get_engine(selected_engine)
180
+ if not engine:
181
+ raise ValueError(f"Engine not available: {selected_engine}")
182
+
183
+ # Convert configuration if needed
184
+ converted_config = self._prepare_config_for_engine(config, selected_engine)
185
+
186
+ # Run server
187
+ get_global_logger().info(f"Starting server with {selected_engine} engine")
188
+ engine.run_server(app, converted_config)
189
+
190
+ def _prepare_config_for_engine(
191
+ self, config: Dict[str, Any], engine_name: str
192
+ ) -> Dict[str, Any]:
193
+ get_global_logger().info(
194
+ f"🔍 Debug: _prepare_config_for_engine called with config keys: {list(config.keys())}"
195
+ )
196
+ get_global_logger().info(f"🔍 Debug: SSL config in input: {config.get('ssl', 'NOT_FOUND')}")
197
+ """
198
+ Prepare configuration for a specific engine.
199
+
200
+ Args:
201
+ config: Original configuration
202
+ engine_name: Target engine name
203
+
204
+ Returns:
205
+ Engine-specific configuration
206
+ """
207
+ # Start with basic config
208
+ engine_config = {
209
+ "host": config.get("host", "127.0.0.1"),
210
+ "port": config.get("port", 8000),
211
+ "log_level": config.get("log_level", "info"),
212
+ "reload": config.get("reload", False),
213
+ }
214
+
215
+ # Add SSL configuration if present
216
+ # First check for direct SSL parameters (from app_factory.py)
217
+ if (
218
+ "certfile" in config
219
+ or "keyfile" in config
220
+ or "ca_certs" in config
221
+ or "verify_mode" in config
222
+ ):
223
+ get_global_logger().info(f"🔍 DEBUG: Direct SSL parameters found in config")
224
+ if "certfile" in config:
225
+ engine_config["certfile"] = config["certfile"]
226
+ if "keyfile" in config:
227
+ engine_config["keyfile"] = config["keyfile"]
228
+ if "ca_certs" in config:
229
+ engine_config["ca_certs"] = config["ca_certs"]
230
+ if "verify_mode" in config:
231
+ engine_config["verify_mode"] = config["verify_mode"]
232
+ else:
233
+ # Try to get SSL config from ssl section
234
+ ssl_config = config.get("ssl", {})
235
+ if not ssl_config:
236
+ # Try to get SSL config from security section
237
+ ssl_config = config.get("security", {}).get("ssl", {})
238
+
239
+ if ssl_config:
240
+ converted_ssl = ServerConfigAdapter.convert_ssl_config_for_engine(
241
+ ssl_config, engine_name
242
+ )
243
+ engine_config.update(converted_ssl)
244
+
245
+ # Add engine-specific configuration
246
+ if "workers" in config:
247
+ engine_config["workers"] = config["workers"]
248
+
249
+ return engine_config
250
+
251
+