mcp-proxy-adapter 2.0.1__py3-none-any.whl → 6.9.50__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mcp-proxy-adapter might be problematic. Click here for more details.

Files changed (269) hide show
  1. mcp_proxy_adapter/__init__.py +47 -0
  2. mcp_proxy_adapter/__main__.py +13 -0
  3. mcp_proxy_adapter/api/__init__.py +0 -0
  4. mcp_proxy_adapter/api/app.py +66 -0
  5. mcp_proxy_adapter/api/core/__init__.py +18 -0
  6. mcp_proxy_adapter/api/core/app_factory.py +400 -0
  7. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  8. mcp_proxy_adapter/api/core/registration_context.py +356 -0
  9. mcp_proxy_adapter/api/core/registration_manager.py +307 -0
  10. mcp_proxy_adapter/api/core/registration_tasks.py +84 -0
  11. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  12. mcp_proxy_adapter/api/handlers.py +181 -0
  13. mcp_proxy_adapter/api/middleware/__init__.py +21 -0
  14. mcp_proxy_adapter/api/middleware/base.py +54 -0
  15. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +73 -0
  16. mcp_proxy_adapter/api/middleware/error_handling.py +76 -0
  17. mcp_proxy_adapter/api/middleware/factory.py +147 -0
  18. mcp_proxy_adapter/api/middleware/logging.py +31 -0
  19. mcp_proxy_adapter/api/middleware/performance.py +51 -0
  20. mcp_proxy_adapter/api/middleware/protocol_middleware.py +140 -0
  21. mcp_proxy_adapter/api/middleware/transport_middleware.py +87 -0
  22. mcp_proxy_adapter/api/middleware/unified_security.py +223 -0
  23. mcp_proxy_adapter/api/middleware/user_info_middleware.py +132 -0
  24. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  25. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  26. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  27. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  28. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  29. mcp_proxy_adapter/api/schemas.py +270 -0
  30. mcp_proxy_adapter/api/tool_integration.py +131 -0
  31. mcp_proxy_adapter/api/tools.py +163 -0
  32. mcp_proxy_adapter/cli/__init__.py +12 -0
  33. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  34. mcp_proxy_adapter/cli/commands/client.py +100 -0
  35. mcp_proxy_adapter/cli/commands/config_generate.py +105 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +94 -0
  37. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  38. mcp_proxy_adapter/cli/commands/server.py +174 -0
  39. mcp_proxy_adapter/cli/commands/sets.py +132 -0
  40. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  41. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  42. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  43. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  44. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  45. mcp_proxy_adapter/cli/main.py +63 -0
  46. mcp_proxy_adapter/cli/parser.py +338 -0
  47. mcp_proxy_adapter/cli/validators.py +231 -0
  48. mcp_proxy_adapter/client/jsonrpc_client/__init__.py +9 -0
  49. mcp_proxy_adapter/client/jsonrpc_client/client.py +42 -0
  50. mcp_proxy_adapter/client/jsonrpc_client/command_api.py +45 -0
  51. mcp_proxy_adapter/client/jsonrpc_client/proxy_api.py +224 -0
  52. mcp_proxy_adapter/client/jsonrpc_client/queue_api.py +60 -0
  53. mcp_proxy_adapter/client/jsonrpc_client/transport.py +108 -0
  54. mcp_proxy_adapter/client/proxy.py +123 -0
  55. mcp_proxy_adapter/commands/__init__.py +66 -0
  56. mcp_proxy_adapter/commands/auth_validation_command.py +69 -0
  57. mcp_proxy_adapter/commands/base.py +389 -0
  58. mcp_proxy_adapter/commands/builtin_commands.py +30 -0
  59. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  60. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  61. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  62. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  63. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  64. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  65. mcp_proxy_adapter/commands/catalog_manager.py +97 -0
  66. mcp_proxy_adapter/commands/cert_monitor_command.py +552 -0
  67. mcp_proxy_adapter/commands/certificate_management_command.py +562 -0
  68. mcp_proxy_adapter/commands/command_registry.py +298 -0
  69. mcp_proxy_adapter/commands/config_command.py +102 -0
  70. mcp_proxy_adapter/commands/dependency_container.py +40 -0
  71. mcp_proxy_adapter/commands/dependency_manager.py +143 -0
  72. mcp_proxy_adapter/commands/echo_command.py +48 -0
  73. mcp_proxy_adapter/commands/health_command.py +142 -0
  74. mcp_proxy_adapter/commands/help_command.py +175 -0
  75. mcp_proxy_adapter/commands/hooks.py +172 -0
  76. mcp_proxy_adapter/commands/key_management_command.py +484 -0
  77. mcp_proxy_adapter/commands/load_command.py +123 -0
  78. mcp_proxy_adapter/commands/plugins_command.py +246 -0
  79. mcp_proxy_adapter/commands/protocol_management_command.py +216 -0
  80. mcp_proxy_adapter/commands/proxy_registration_command.py +319 -0
  81. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  82. mcp_proxy_adapter/commands/registration_status_command.py +76 -0
  83. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  84. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  85. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  86. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  87. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  88. mcp_proxy_adapter/commands/reload_command.py +136 -0
  89. mcp_proxy_adapter/commands/result.py +157 -0
  90. mcp_proxy_adapter/commands/role_test_command.py +99 -0
  91. mcp_proxy_adapter/commands/roles_management_command.py +502 -0
  92. mcp_proxy_adapter/commands/security_command.py +472 -0
  93. mcp_proxy_adapter/commands/settings_command.py +113 -0
  94. mcp_proxy_adapter/commands/ssl_setup_command.py +306 -0
  95. mcp_proxy_adapter/commands/token_management_command.py +500 -0
  96. mcp_proxy_adapter/commands/transport_management_command.py +129 -0
  97. mcp_proxy_adapter/commands/unload_command.py +92 -0
  98. mcp_proxy_adapter/config.py +32 -0
  99. mcp_proxy_adapter/core/__init__.py +8 -0
  100. mcp_proxy_adapter/core/app_factory.py +560 -0
  101. mcp_proxy_adapter/core/app_runner.py +318 -0
  102. mcp_proxy_adapter/core/auth_validator.py +508 -0
  103. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  104. mcp_proxy_adapter/core/certificate/certificate_creator.py +372 -0
  105. mcp_proxy_adapter/core/certificate/certificate_extractor.py +185 -0
  106. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  107. mcp_proxy_adapter/core/certificate/certificate_validator.py +481 -0
  108. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +65 -0
  109. mcp_proxy_adapter/core/certificate_utils.py +249 -0
  110. mcp_proxy_adapter/core/client.py +608 -0
  111. mcp_proxy_adapter/core/client_manager.py +271 -0
  112. mcp_proxy_adapter/core/client_security.py +411 -0
  113. mcp_proxy_adapter/core/config/__init__.py +18 -0
  114. mcp_proxy_adapter/core/config/config.py +237 -0
  115. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  116. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  117. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  118. mcp_proxy_adapter/core/config/simple_config.py +204 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +131 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +476 -0
  121. mcp_proxy_adapter/core/config_converter.py +252 -0
  122. mcp_proxy_adapter/core/config_validator.py +211 -0
  123. mcp_proxy_adapter/core/crl_utils.py +362 -0
  124. mcp_proxy_adapter/core/errors.py +276 -0
  125. mcp_proxy_adapter/core/job_manager.py +54 -0
  126. mcp_proxy_adapter/core/logging.py +250 -0
  127. mcp_proxy_adapter/core/mtls_asgi.py +140 -0
  128. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  129. mcp_proxy_adapter/core/mtls_proxy.py +229 -0
  130. mcp_proxy_adapter/core/mtls_server.py +154 -0
  131. mcp_proxy_adapter/core/protocol_manager.py +232 -0
  132. mcp_proxy_adapter/core/proxy/__init__.py +19 -0
  133. mcp_proxy_adapter/core/proxy/auth_manager.py +26 -0
  134. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +160 -0
  135. mcp_proxy_adapter/core/proxy/registration_client.py +186 -0
  136. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  137. mcp_proxy_adapter/core/proxy_client.py +184 -0
  138. mcp_proxy_adapter/core/proxy_registration.py +80 -0
  139. mcp_proxy_adapter/core/role_utils.py +103 -0
  140. mcp_proxy_adapter/core/security_adapter.py +343 -0
  141. mcp_proxy_adapter/core/security_factory.py +96 -0
  142. mcp_proxy_adapter/core/security_integration.py +342 -0
  143. mcp_proxy_adapter/core/server_adapter.py +251 -0
  144. mcp_proxy_adapter/core/server_engine.py +217 -0
  145. mcp_proxy_adapter/core/settings.py +260 -0
  146. mcp_proxy_adapter/core/signal_handler.py +107 -0
  147. mcp_proxy_adapter/core/ssl_utils.py +161 -0
  148. mcp_proxy_adapter/core/transport_manager.py +153 -0
  149. mcp_proxy_adapter/core/unified_config_adapter.py +471 -0
  150. mcp_proxy_adapter/core/utils.py +101 -0
  151. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  152. mcp_proxy_adapter/core/validation/config_validator.py +219 -0
  153. mcp_proxy_adapter/core/validation/file_validator.py +131 -0
  154. mcp_proxy_adapter/core/validation/protocol_validator.py +205 -0
  155. mcp_proxy_adapter/core/validation/security_validator.py +140 -0
  156. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  157. mcp_proxy_adapter/custom_openapi.py +58 -0
  158. mcp_proxy_adapter/examples/__init__.py +16 -0
  159. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  160. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  161. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  162. mcp_proxy_adapter/examples/basic_framework/main.py +52 -0
  163. mcp_proxy_adapter/examples/bugfix_certificate_config.py +261 -0
  164. mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
  165. mcp_proxy_adapter/examples/check_config.py +413 -0
  166. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  167. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  168. mcp_proxy_adapter/examples/config_builder.py +234 -0
  169. mcp_proxy_adapter/examples/config_cli.py +282 -0
  170. mcp_proxy_adapter/examples/create_test_configs.py +174 -0
  171. mcp_proxy_adapter/examples/debug_request_state.py +130 -0
  172. mcp_proxy_adapter/examples/debug_role_chain.py +191 -0
  173. mcp_proxy_adapter/examples/demo_client.py +287 -0
  174. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  175. mcp_proxy_adapter/examples/full_application/commands/__init__.py +8 -0
  176. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +45 -0
  177. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +52 -0
  178. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +32 -0
  179. mcp_proxy_adapter/examples/full_application/commands/help_command.py +54 -0
  180. mcp_proxy_adapter/examples/full_application/commands/list_command.py +57 -0
  181. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +5 -0
  182. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +29 -0
  183. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +27 -0
  184. mcp_proxy_adapter/examples/full_application/main.py +311 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +161 -0
  186. mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
  187. mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
  188. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +45 -0
  189. mcp_proxy_adapter/examples/full_application/test_server.py +163 -0
  190. mcp_proxy_adapter/examples/full_application/test_simple_server.py +62 -0
  191. mcp_proxy_adapter/examples/generate_config.py +502 -0
  192. mcp_proxy_adapter/examples/proxy_registration_example.py +335 -0
  193. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  194. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  195. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  196. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  197. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  198. mcp_proxy_adapter/examples/required_certificates.py +208 -0
  199. mcp_proxy_adapter/examples/run_example.py +77 -0
  200. mcp_proxy_adapter/examples/run_full_test_suite.py +619 -0
  201. mcp_proxy_adapter/examples/run_proxy_server.py +153 -0
  202. mcp_proxy_adapter/examples/run_security_tests_fixed.py +435 -0
  203. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  204. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  205. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  206. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  207. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  208. mcp_proxy_adapter/examples/security_test_client.py +72 -0
  209. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  210. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  211. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  212. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  213. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  214. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  215. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  216. mcp_proxy_adapter/examples/setup_test_environment.py +235 -0
  217. mcp_proxy_adapter/examples/simple_protocol_test.py +125 -0
  218. mcp_proxy_adapter/examples/test_chk_hostname_automated.py +211 -0
  219. mcp_proxy_adapter/examples/test_config.py +205 -0
  220. mcp_proxy_adapter/examples/test_config_builder.py +110 -0
  221. mcp_proxy_adapter/examples/test_examples.py +308 -0
  222. mcp_proxy_adapter/examples/test_framework_complete.py +267 -0
  223. mcp_proxy_adapter/examples/test_mcp_server.py +187 -0
  224. mcp_proxy_adapter/examples/test_protocol_examples.py +337 -0
  225. mcp_proxy_adapter/examples/universal_client.py +674 -0
  226. mcp_proxy_adapter/examples/update_config_certificates.py +135 -0
  227. mcp_proxy_adapter/examples/validate_generator_compatibility.py +385 -0
  228. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +61 -0
  229. mcp_proxy_adapter/integrations/__init__.py +25 -0
  230. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  231. mcp_proxy_adapter/main.py +311 -0
  232. mcp_proxy_adapter/openapi.py +375 -0
  233. mcp_proxy_adapter/schemas/base_schema.json +114 -0
  234. mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
  235. mcp_proxy_adapter/schemas/roles.json +37 -0
  236. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  237. mcp_proxy_adapter/version.py +5 -0
  238. mcp_proxy_adapter-6.9.50.dist-info/METADATA +1088 -0
  239. mcp_proxy_adapter-6.9.50.dist-info/RECORD +242 -0
  240. {mcp_proxy_adapter-2.0.1.dist-info → mcp_proxy_adapter-6.9.50.dist-info}/WHEEL +1 -1
  241. mcp_proxy_adapter-6.9.50.dist-info/entry_points.txt +14 -0
  242. mcp_proxy_adapter-6.9.50.dist-info/top_level.txt +1 -0
  243. adapters/__init__.py +0 -16
  244. analyzers/__init__.py +0 -14
  245. analyzers/docstring_analyzer.py +0 -199
  246. analyzers/type_analyzer.py +0 -151
  247. cli/__init__.py +0 -12
  248. cli/__main__.py +0 -79
  249. cli/command_runner.py +0 -233
  250. dispatchers/__init__.py +0 -14
  251. dispatchers/base_dispatcher.py +0 -85
  252. dispatchers/json_rpc_dispatcher.py +0 -198
  253. generators/__init__.py +0 -14
  254. generators/endpoint_generator.py +0 -172
  255. generators/openapi_generator.py +0 -254
  256. generators/rest_api_generator.py +0 -207
  257. mcp_proxy_adapter-2.0.1.dist-info/METADATA +0 -272
  258. mcp_proxy_adapter-2.0.1.dist-info/RECORD +0 -28
  259. mcp_proxy_adapter-2.0.1.dist-info/licenses/LICENSE +0 -21
  260. mcp_proxy_adapter-2.0.1.dist-info/top_level.txt +0 -7
  261. openapi_schema/__init__.py +0 -38
  262. openapi_schema/command_registry.py +0 -312
  263. openapi_schema/rest_schema.py +0 -510
  264. openapi_schema/rpc_generator.py +0 -307
  265. openapi_schema/rpc_schema.py +0 -416
  266. validators/__init__.py +0 -14
  267. validators/base_validator.py +0 -23
  268. validators/docstring_validator.py +0 -75
  269. validators/metadata_validator.py +0 -76
@@ -0,0 +1,217 @@
1
+ """
2
+ Server Engine Abstraction
3
+
4
+ This module provides an abstraction layer for the hypercorn ASGI server engine,
5
+ providing full mTLS support and SSL capabilities.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ import logging
12
+ from abc import ABC, abstractmethod
13
+ from typing import Dict, Optional, Any
14
+
15
+ from .logging import get_global_logger
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class ServerEngine(ABC):
21
+ """
22
+ Abstract base class for server engines.
23
+
24
+ This class defines the interface that all server engines must implement,
25
+ allowing the framework to work with different ASGI servers transparently.
26
+ """
27
+
28
+ @abstractmethod
29
+ def get_name(self) -> str:
30
+ """Get the name of the server engine."""
31
+ pass
32
+
33
+ @abstractmethod
34
+ def get_supported_features(self) -> Dict[str, bool]:
35
+ """
36
+ Get supported features of this server engine.
37
+
38
+ Returns:
39
+ Dictionary mapping feature names to boolean support status
40
+ """
41
+ pass
42
+
43
+ def validate_config(self, config: Dict[str, Any]) -> bool:
44
+ """
45
+ Validate configuration for this engine.
46
+
47
+ Args:
48
+ config: Configuration dictionary to validate
49
+
50
+ Returns:
51
+ True if configuration is valid, False otherwise
52
+ """
53
+ # Default implementation: always valid
54
+ return True
55
+
56
+ def get_config_schema(self) -> Dict[str, Any]:
57
+ """
58
+ Get configuration schema for this engine.
59
+
60
+ Returns:
61
+ Dictionary describing the configuration schema
62
+ """
63
+ # Default implementation: empty schema
64
+ return {}
65
+
66
+ def run_server(self, app: Any, config: Dict[str, Any]) -> None:
67
+ """
68
+ Run the server with the given application and configuration.
69
+
70
+ Args:
71
+ app: ASGI application
72
+ config: Server configuration
73
+
74
+ Raises:
75
+ NotImplementedError: This method must be implemented by subclasses
76
+ """
77
+ raise NotImplementedError("run_server must be implemented by subclasses")
78
+
79
+
80
+ class HypercornEngine(ServerEngine):
81
+ """
82
+ Hypercorn server engine implementation.
83
+
84
+ Provides full mTLS support and better SSL capabilities.
85
+ """
86
+
87
+ def get_name(self) -> str:
88
+ return "hypercorn"
89
+
90
+ def get_supported_features(self) -> Dict[str, bool]:
91
+ return {
92
+ "ssl_tls": True,
93
+ "mtls_client_certs": True, # Full support
94
+ "ssl_scope_info": True, # SSL info in request scope
95
+ "client_cert_verification": True,
96
+ "websockets": True,
97
+ "http2": True,
98
+ "reload": True,
99
+ }
100
+
101
+ def run_server(self, app: Any, config: Dict[str, Any]) -> None:
102
+ """
103
+ Run the server with the given application and configuration.
104
+
105
+ Args:
106
+ app: ASGI application
107
+ config: Server configuration dictionary containing:
108
+ - host: Server host (default: "127.0.0.1")
109
+ - port: Server port (default: 8000)
110
+ - certfile: SSL certificate file (optional)
111
+ - keyfile: SSL key file (optional)
112
+ - ca_certs: CA certificate file (optional)
113
+ - verify_mode: SSL verification mode (optional)
114
+ - check_hostname: Enable hostname checking (optional)
115
+ - log_level: Logging level (optional)
116
+ - reload: Enable auto-reload (optional)
117
+ """
118
+ import asyncio
119
+ import hypercorn.asyncio
120
+ from hypercorn.config import Config as HypercornConfig
121
+
122
+ # Create hypercorn configuration
123
+ hypercorn_config = HypercornConfig()
124
+ hypercorn_config.bind = [f"{config.get('host', '127.0.0.1')}:{config.get('port', 8000)}"]
125
+
126
+ # Apply SSL configuration if present
127
+ if "certfile" in config:
128
+ hypercorn_config.certfile = config["certfile"]
129
+ if "keyfile" in config:
130
+ hypercorn_config.keyfile = config["keyfile"]
131
+ if "ca_certs" in config:
132
+ hypercorn_config.ca_certs = config["ca_certs"]
133
+ if "verify_mode" in config:
134
+ hypercorn_config.verify_mode = config["verify_mode"]
135
+ if "check_hostname" in config:
136
+ hypercorn_config.check_hostname = config["check_hostname"]
137
+
138
+ # Apply other settings
139
+ if "log_level" in config:
140
+ hypercorn_config.loglevel = config["log_level"].upper()
141
+ if "reload" in config:
142
+ hypercorn_config.reload = config["reload"]
143
+
144
+ # Try to set ALPN protocols for HTTP/2 support
145
+ try:
146
+ hypercorn_config.alpn_protocols = ["h2", "http/1.1"]
147
+ except Exception:
148
+ pass
149
+
150
+ # Run the server (blocking call)
151
+ # Note: This uses asyncio.run internally, so it will block until server stops
152
+ asyncio.run(hypercorn.asyncio.serve(app, hypercorn_config))
153
+
154
+
155
+ class ServerEngineFactory:
156
+ """
157
+ Factory for creating server engines.
158
+
159
+ This class manages the creation and configuration of different server engines.
160
+ """
161
+
162
+ _engines: Dict[str, ServerEngine] = {}
163
+
164
+ @classmethod
165
+ def register_engine(cls, engine: ServerEngine) -> None:
166
+ """
167
+ Register a server engine.
168
+
169
+ Args:
170
+ engine: Server engine instance to register
171
+ """
172
+ cls._engines[engine.get_name()] = engine
173
+ get_global_logger().info(f"Registered server engine: {engine.get_name()}")
174
+
175
+ @classmethod
176
+ def get_engine(cls, engine_name: str) -> Optional[ServerEngine]:
177
+ """
178
+ Get a registered server engine by name.
179
+
180
+ Args:
181
+ engine_name: Name of the engine to retrieve
182
+
183
+ Returns:
184
+ ServerEngine instance if found, None otherwise
185
+ """
186
+ return cls._engines.get(engine_name)
187
+
188
+ @classmethod
189
+ def get_available_engines(cls) -> Dict[str, ServerEngine]:
190
+ """
191
+ Get all registered server engines.
192
+
193
+ Returns:
194
+ Dictionary mapping engine names to ServerEngine instances
195
+ """
196
+ return cls._engines.copy()
197
+
198
+ @classmethod
199
+ def initialize_default_engines(cls) -> None:
200
+ """Initialize default server engines."""
201
+ # Register hypercorn engine (only supported engine)
202
+ try:
203
+ import hypercorn # noqa: F401
204
+
205
+ cls.register_engine(HypercornEngine())
206
+ get_global_logger().info(
207
+ "Hypercorn engine registered (full mTLS support available)"
208
+ )
209
+ except ImportError:
210
+ get_global_logger().error(
211
+ "Hypercorn not available - this is required for the framework"
212
+ )
213
+ raise
214
+
215
+
216
+ # Initialize default engines
217
+ ServerEngineFactory.initialize_default_engines()
@@ -0,0 +1,260 @@
1
+ """
2
+ Settings management for the MCP Proxy Adapter framework.
3
+ Provides utilities for reading and managing framework settings from configuration.
4
+ """
5
+
6
+ from mcp_proxy_adapter.config import config
7
+
8
+
9
+ class Settings:
10
+ """
11
+ Settings management class for the framework.
12
+ Provides easy access to configuration values with type conversion and validation.
13
+ """
14
+
15
+ # Store custom settings as a class variable
16
+ _custom_settings: Dict[str, Any] = {}
17
+
18
+ @classmethod
19
+ def add_custom_settings(cls, settings: Dict[str, Any]) -> None:
20
+ """
21
+ Add custom settings to the settings manager.
22
+
23
+ Args:
24
+ settings: Dictionary with custom settings
25
+ """
26
+ cls._custom_settings.update(settings)
27
+
28
+ @classmethod
29
+ def get_custom_settings(cls) -> Dict[str, Any]:
30
+ """
31
+ Get all custom settings.
32
+
33
+ Returns:
34
+ Dictionary with all custom settings
35
+ """
36
+ return cls._custom_settings.copy()
37
+
38
+ @classmethod
39
+ def get_custom_setting_value(cls, key: str, default: Any = None) -> Any:
40
+ """
41
+ Get custom setting value.
42
+
43
+ Args:
44
+ key: Setting key
45
+ default: Default value if key not found
46
+
47
+ Returns:
48
+ Setting value
49
+ """
50
+ return cls._custom_settings.get(key, default)
51
+
52
+ @classmethod
53
+ def set_custom_setting_value(cls, key: str, value: Any) -> None:
54
+ """
55
+ Set custom setting value.
56
+
57
+ Args:
58
+ key: Setting key
59
+ value: Value to set
60
+ """
61
+ cls._custom_settings[key] = value
62
+
63
+ @classmethod
64
+ def clear_custom_settings(cls) -> None:
65
+ """
66
+ Clear all custom settings.
67
+ """
68
+ cls._custom_settings.clear()
69
+
70
+ @staticmethod
71
+
72
+ @staticmethod
73
+
74
+ @staticmethod
75
+
76
+ @staticmethod
77
+ def get_custom_setting(key: str, default: Any = None) -> Any:
78
+ """
79
+ Get custom setting from configuration.
80
+
81
+ Args:
82
+ key: Configuration key in dot notation (e.g., "custom.feature_enabled")
83
+ default: Default value if key not found
84
+
85
+ Returns:
86
+ Configuration value
87
+ """
88
+ return config.get(key, default)
89
+
90
+ @staticmethod
91
+
92
+ @staticmethod
93
+ def set_custom_setting(key: str, value: Any) -> None:
94
+ """
95
+ Set custom setting in configuration.
96
+
97
+ Args:
98
+ key: Configuration key in dot notation
99
+ value: Value to set
100
+ """
101
+ config.set(key, value)
102
+
103
+ @staticmethod
104
+ def reload_config() -> None:
105
+ """
106
+ Reload configuration from file and environment variables.
107
+ """
108
+ config.load_config()
109
+
110
+
111
+ class ServerSettings:
112
+ """
113
+ Server-specific settings helper.
114
+ """
115
+
116
+ @staticmethod
117
+ def get_host() -> str:
118
+ """Get server host."""
119
+ return config.get("server.host", "0.0.0.0")
120
+
121
+ @staticmethod
122
+ def get_port() -> int:
123
+ """Get server port."""
124
+ return config.get("server.port", 8000)
125
+
126
+ @staticmethod
127
+ def get_debug() -> bool:
128
+ """Get debug mode."""
129
+ return config.get("server.debug", False)
130
+
131
+
132
+ class LoggingSettings:
133
+ """
134
+ Logging-specific settings helper.
135
+ """
136
+
137
+ @staticmethod
138
+ def get_level() -> str:
139
+ """Get logging level."""
140
+ return config.get("logging.level", "INFO")
141
+
142
+ @staticmethod
143
+ def get_log_dir() -> str:
144
+ """Get log directory."""
145
+ return config.get("logging.log_dir", "./logs")
146
+
147
+ @staticmethod
148
+
149
+ @staticmethod
150
+
151
+ @staticmethod
152
+
153
+ @staticmethod
154
+
155
+ @staticmethod
156
+
157
+ @staticmethod
158
+
159
+ @staticmethod
160
+
161
+ @staticmethod
162
+
163
+ @staticmethod
164
+
165
+
166
+ class CommandsSettings:
167
+ """
168
+ Commands-specific settings helper.
169
+ """
170
+
171
+ @staticmethod
172
+ def get_auto_discovery() -> bool:
173
+ """Get auto discovery setting."""
174
+ return config.get("commands.auto_discovery", True)
175
+
176
+ @staticmethod
177
+ def get_discovery_path() -> str:
178
+ """Get discovery path."""
179
+ return config.get("commands.discovery_path", "mcp_proxy_adapter.commands")
180
+
181
+ @staticmethod
182
+
183
+
184
+ # Convenience functions for easy access
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+ def get_auto_discovery() -> bool:
196
+ """Get auto discovery setting."""
197
+ return CommandsSettings.get_auto_discovery()
198
+
199
+
200
+ def get_discovery_path() -> str:
201
+ """Get discovery path."""
202
+ return CommandsSettings.get_discovery_path()
203
+
204
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+ def add_custom_settings(settings: Dict[str, Any]) -> None:
212
+ """
213
+ Add custom settings to the settings manager.
214
+
215
+ Args:
216
+ settings: Dictionary with custom settings
217
+ """
218
+ Settings.add_custom_settings(settings)
219
+
220
+
221
+ def get_custom_settings() -> Dict[str, Any]:
222
+ """
223
+ Get all custom settings.
224
+
225
+ Returns:
226
+ Dictionary with all custom settings
227
+ """
228
+ return Settings.get_custom_settings()
229
+
230
+
231
+ def get_custom_setting_value(key: str, default: Any = None) -> Any:
232
+ """
233
+ Get custom setting value.
234
+
235
+ Args:
236
+ key: Setting key
237
+ default: Default value if key not found
238
+
239
+ Returns:
240
+ Setting value
241
+ """
242
+ return Settings.get_custom_setting_value(key, default)
243
+
244
+
245
+ def set_custom_setting_value(key: str, value: Any) -> None:
246
+ """
247
+ Set custom setting value.
248
+
249
+ Args:
250
+ key: Setting key
251
+ value: Value to set
252
+ """
253
+ Settings.set_custom_setting_value(key, value)
254
+
255
+
256
+ def clear_custom_settings() -> None:
257
+ """
258
+ Clear all custom settings.
259
+ """
260
+ Settings.clear_custom_settings()
@@ -0,0 +1,107 @@
1
+ """
2
+ Signal handler for graceful shutdown with proxy unregistration.
3
+
4
+ This module provides signal handling for SIGTERM, SIGINT, and SIGHUP
5
+ to ensure proper proxy unregistration before server shutdown.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ import signal
12
+ import threading
13
+ from typing import Optional, Callable, Any
14
+ from mcp_proxy_adapter.core.logging import get_global_logger
15
+
16
+
17
+ class SignalHandler:
18
+ """
19
+ Signal handler for graceful shutdown with proxy unregistration.
20
+ """
21
+
22
+ def __init__(self):
23
+ """Initialize signal handler."""
24
+ self._shutdown_callback: Optional[Callable] = None
25
+ self._shutdown_event = threading.Event()
26
+ self._original_handlers = {}
27
+ self._setup_signal_handlers()
28
+
29
+ def set_shutdown_callback(self, callback: Callable):
30
+ """
31
+ Set callback function to be called during shutdown.
32
+
33
+ Args:
34
+ callback: Function to call during shutdown
35
+ """
36
+ self._shutdown_callback = callback
37
+ get_global_logger().info("Shutdown callback set for signal handler")
38
+
39
+ def _setup_signal_handlers(self):
40
+ """Setup signal handlers for graceful shutdown."""
41
+ # Handle SIGTERM (termination signal)
42
+ self._original_handlers[signal.SIGTERM] = signal.signal(
43
+ signal.SIGTERM, self._handle_shutdown_signal
44
+ )
45
+
46
+ # Handle SIGINT (Ctrl+C)
47
+ self._original_handlers[signal.SIGINT] = signal.signal(
48
+ signal.SIGINT, self._handle_shutdown_signal
49
+ )
50
+
51
+ # Handle SIGHUP (hangup signal)
52
+ self._original_handlers[signal.SIGHUP] = signal.signal(
53
+ signal.SIGHUP, self._handle_shutdown_signal
54
+ )
55
+
56
+ get_global_logger().info("Signal handlers installed for SIGTERM, SIGINT, SIGHUP")
57
+
58
+
59
+
60
+ def wait_for_shutdown(self, timeout: Optional[float] = None) -> bool:
61
+ """
62
+ Wait for shutdown signal.
63
+
64
+ Args:
65
+ timeout: Maximum time to wait in seconds
66
+
67
+ Returns:
68
+ True if shutdown signal received, False if timeout
69
+ """
70
+ return self._shutdown_event.wait(timeout)
71
+
72
+ def is_shutdown_requested(self) -> bool:
73
+ """
74
+ Check if shutdown has been requested.
75
+
76
+ Returns:
77
+ True if shutdown signal received
78
+ """
79
+ return self._shutdown_event.is_set()
80
+
81
+
82
+
83
+ # Global signal handler instance
84
+ _signal_handler: Optional[SignalHandler] = None
85
+
86
+
87
+ def get_signal_handler() -> SignalHandler:
88
+ """Get the global signal handler instance."""
89
+ global _signal_handler
90
+ if _signal_handler is None:
91
+ _signal_handler = SignalHandler()
92
+ return _signal_handler
93
+
94
+
95
+
96
+
97
+
98
+
99
+ def is_shutdown_requested() -> bool:
100
+ """
101
+ Check if shutdown has been requested.
102
+
103
+ Returns:
104
+ True if shutdown signal received
105
+ """
106
+ handler = get_signal_handler()
107
+ return handler.is_shutdown_requested()