mcp-proxy-adapter 6.9.43__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.
Files changed (242) 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 +355 -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 +266 -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 +35 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +74 -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 +128 -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 +388 -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 +116 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +100 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +380 -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 +190 -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 +13 -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 +264 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +81 -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 +313 -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.43.dist-info/METADATA +739 -0
  239. mcp_proxy_adapter-6.9.43.dist-info/RECORD +242 -0
  240. mcp_proxy_adapter-6.9.43.dist-info/WHEEL +5 -0
  241. mcp_proxy_adapter-6.9.43.dist-info/entry_points.txt +12 -0
  242. mcp_proxy_adapter-6.9.43.dist-info/top_level.txt +1 -0
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ mTLS Server implementation using built-in http.server.
4
+
5
+ Author: Vasiliy Zdanovskiy
6
+ email: vasilyvz@gmail.com
7
+ """
8
+
9
+ import threading
10
+ import ssl
11
+ import json
12
+ import logging
13
+ from http.server import HTTPServer, BaseHTTPRequestHandler
14
+ from typing import Optional, Dict, Any
15
+ import os
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class mTLSHandler(BaseHTTPRequestHandler):
21
+ """Handler for mTLS connections."""
22
+
23
+ def __init__(self, *args, main_app=None, **kwargs):
24
+ self.main_app = main_app
25
+ super().__init__(*args, **kwargs)
26
+
27
+
28
+
29
+
30
+ def _forward_to_main_app(
31
+ self,
32
+ method: str,
33
+ path: str,
34
+ client_cert: Optional[Dict],
35
+ post_data: Optional[bytes] = None,
36
+ ) -> Dict[str, Any]:
37
+ """Forward request to main FastAPI application."""
38
+ try:
39
+ # This is a simplified forwarding - in real implementation
40
+ # you would use httpx or similar to make internal HTTP calls
41
+ # to the main FastAPI app running on different port
42
+
43
+ return {
44
+ "status": "ok",
45
+ "message": f"mTLS {method} forwarded to main app",
46
+ "client_cert": client_cert,
47
+ "path": path,
48
+ "forwarded": True,
49
+ }
50
+ except Exception as e:
51
+ get_global_logger().error(f"Error forwarding to main app: {e}")
52
+ return {
53
+ "status": "error",
54
+ "message": f"Forwarding failed: {e}",
55
+ "client_cert": client_cert,
56
+ "path": path,
57
+ }
58
+
59
+
60
+ class mTLSServer:
61
+ """mTLS Server using built-in http.server."""
62
+
63
+ def __init__(
64
+ self,
65
+ host: str = "127.0.0.1",
66
+ port: int = 8443,
67
+ cert_file: str = None,
68
+ key_file: str = None,
69
+ ca_cert_file: str = None,
70
+ main_app=None,
71
+ ):
72
+ """
73
+ Initialize mTLS server.
74
+
75
+ Args:
76
+ host: Server host
77
+ port: Server port
78
+ cert_file: Server certificate file
79
+ key_file: Server private key file
80
+ ca_cert_file: CA certificate file for client verification
81
+ main_app: Main FastAPI application for forwarding requests
82
+ """
83
+ self.host = host
84
+ self.port = port
85
+ self.cert_file = cert_file
86
+ self.key_file = key_file
87
+ self.ca_cert_file = ca_cert_file
88
+ self.main_app = main_app
89
+
90
+ self.server: Optional[HTTPServer] = None
91
+ self.server_thread: Optional[threading.Thread] = None
92
+ self.running = False
93
+
94
+ get_global_logger().info(f"mTLS Server initialized: {host}:{port}")
95
+
96
+ def _create_handler(self):
97
+ """Create handler with main app reference."""
98
+
99
+
100
+ return handler
101
+
102
+ def start(self) -> bool:
103
+ """Start mTLS server in separate thread."""
104
+ try:
105
+ # Check if certificate files exist
106
+ if not os.path.exists(self.cert_file):
107
+ get_global_logger().error(f"Certificate file not found: {self.cert_file}")
108
+ return False
109
+
110
+ if not os.path.exists(self.key_file):
111
+ get_global_logger().error(f"Key file not found: {self.key_file}")
112
+ return False
113
+
114
+ if not os.path.exists(self.ca_cert_file):
115
+ get_global_logger().error(
116
+ f"CA certificate file not found: {self.ca_cert_file}"
117
+ )
118
+ return False
119
+
120
+ # Create server
121
+ handler_class = self._create_handler()
122
+ self.server = HTTPServer((self.host, self.port), handler_class)
123
+
124
+ # Configure SSL context
125
+ context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
126
+ context.load_cert_chain(self.cert_file, self.key_file)
127
+ context.load_verify_locations(self.ca_cert_file)
128
+ context.verify_mode = ssl.CERT_REQUIRED
129
+
130
+ # Wrap socket with SSL
131
+ self.server.socket = context.wrap_socket(
132
+ self.server.socket, server_side=True
133
+ )
134
+
135
+ # Start server in separate thread
136
+ self.server_thread = threading.Thread(
137
+ target=self._run_server, daemon=True
138
+ )
139
+ self.server_thread.start()
140
+
141
+ self.running = True
142
+ get_global_logger().info(
143
+ f"✅ mTLS Server started on https://{self.host}:{self.port}"
144
+ )
145
+ return True
146
+
147
+ except Exception as e:
148
+ get_global_logger().error(f"Failed to start mTLS server: {e}")
149
+ return False
150
+
151
+
152
+
153
+
154
+
@@ -0,0 +1,232 @@
1
+ """
2
+ Protocol management module for MCP Proxy Adapter.
3
+
4
+ This module provides functionality for managing and validating protocol configurations,
5
+ including HTTP, HTTPS, and MTLS protocols with their respective ports.
6
+ """
7
+
8
+ import ssl
9
+ from urllib.parse import urlparse
10
+ from typing import Dict, List, Any, Optional
11
+
12
+ from mcp_proxy_adapter.config import config
13
+ from mcp_proxy_adapter.core.logging import get_global_logger
14
+
15
+
16
+ class ProtocolManager:
17
+ """
18
+ Manages protocol configurations and validates protocol access.
19
+
20
+ This class handles the validation of allowed protocols and their associated ports,
21
+ ensuring that only configured protocols are accessible.
22
+ """
23
+
24
+ def __init__(self, app_config: Optional[Dict] = None):
25
+ """
26
+ Initialize the protocol manager.
27
+
28
+ Args:
29
+ app_config: Application configuration dictionary (optional)
30
+ """
31
+ self.app_config = app_config
32
+ self._load_config()
33
+
34
+ def _load_config(self):
35
+ """Load protocol configuration from config."""
36
+ # Use provided config or fallback to global config; normalize types
37
+ current_config = (
38
+ self.app_config if self.app_config is not None else config.get_all()
39
+ )
40
+ get_global_logger().debug(
41
+ f"ProtocolManager._load_config - current_config type: {type(current_config)}"
42
+ )
43
+
44
+ if not hasattr(current_config, "get"):
45
+ # Not a dict-like config, fallback to global
46
+ get_global_logger().debug(
47
+ f"ProtocolManager._load_config - current_config is not dict-like, falling back to global config"
48
+ )
49
+ current_config = config.get_all()
50
+
51
+ get_global_logger().debug(
52
+ f"ProtocolManager._load_config - final current_config type: {type(current_config)}"
53
+ )
54
+ if hasattr(current_config, "get"):
55
+ get_global_logger().debug(
56
+ f"ProtocolManager._load_config - current_config keys: {list(current_config.keys()) if hasattr(current_config, 'keys') else 'no keys'}"
57
+ )
58
+
59
+ # Get server protocol configuration (new simplified structure)
60
+ get_global_logger().debug(f"ProtocolManager._load_config - before getting server protocol")
61
+ try:
62
+ server_config = current_config.get("server", {})
63
+ server_protocol = server_config.get("protocol", "http")
64
+ get_global_logger().debug(f"ProtocolManager._load_config - server protocol: {server_protocol}")
65
+
66
+ # Set allowed protocols based on server protocol
67
+ if server_protocol == "http":
68
+ self.allowed_protocols = ["http"]
69
+ elif server_protocol == "https":
70
+ self.allowed_protocols = ["https"]
71
+ elif server_protocol == "mtls":
72
+ self.allowed_protocols = ["mtls", "https"] # mTLS also supports HTTPS
73
+ else:
74
+ # Fallback to HTTP
75
+ self.allowed_protocols = ["http"]
76
+ get_global_logger().warning(f"Unknown server protocol '{server_protocol}', defaulting to HTTP")
77
+
78
+ get_global_logger().debug(f"ProtocolManager._load_config - allowed protocols: {self.allowed_protocols}")
79
+
80
+ except Exception as e:
81
+ get_global_logger().debug(f"ProtocolManager._load_config - ERROR getting server protocol: {e}")
82
+ # Fallback to HTTP
83
+ self.allowed_protocols = ["http"]
84
+
85
+ # Protocol management is always enabled in new structure
86
+ self.enabled = True
87
+
88
+ get_global_logger().debug(
89
+ f"Protocol manager loaded config: enabled={self.enabled}, allowed_protocols={self.allowed_protocols}"
90
+ )
91
+
92
+
93
+
94
+
95
+ def is_protocol_allowed(self, protocol: str) -> bool:
96
+ """
97
+ Check if a protocol is allowed based on configuration.
98
+
99
+ Args:
100
+ protocol: Protocol name (http, https, mtls)
101
+
102
+ Returns:
103
+ True if protocol is allowed, False otherwise
104
+ """
105
+ get_global_logger().debug(f"🔍 ProtocolManager.is_protocol_allowed - protocol: {protocol}")
106
+ get_global_logger().debug(f"🔍 ProtocolManager.is_protocol_allowed - enabled: {self.enabled}")
107
+ get_global_logger().debug(f"🔍 ProtocolManager.is_protocol_allowed - allowed_protocols: {self.allowed_protocols}")
108
+
109
+ if not self.enabled:
110
+ get_global_logger().debug("✅ ProtocolManager.is_protocol_allowed - Protocol management is disabled, allowing all protocols")
111
+ return True
112
+
113
+ protocol_lower = protocol.lower()
114
+ is_allowed = protocol_lower in self.allowed_protocols
115
+
116
+ get_global_logger().debug(f"🔍 ProtocolManager.is_protocol_allowed - Protocol '{protocol}' allowed: {is_allowed}")
117
+ return is_allowed
118
+
119
+
120
+
121
+ def get_protocol_config(self, protocol: str) -> Dict:
122
+ """
123
+ Get full configuration for a specific protocol.
124
+
125
+ Args:
126
+ protocol: Protocol name (http, https, mtls)
127
+
128
+ Returns:
129
+ Protocol configuration dictionary
130
+ """
131
+ protocol_lower = protocol.lower()
132
+ cfg = self.protocols_config.get(protocol_lower, {})
133
+ # Ensure dict type
134
+ if isinstance(cfg, dict):
135
+ try:
136
+ return cfg.copy()
137
+ except Exception:
138
+ return {}
139
+ return {}
140
+
141
+
142
+ def get_ssl_context_for_protocol(self, protocol: str) -> Optional[ssl.SSLContext]:
143
+ """
144
+ Get SSL context for HTTPS or MTLS protocol.
145
+
146
+ Args:
147
+ protocol: Protocol name (https, mtls)
148
+
149
+ Returns:
150
+ SSL context if protocol requires SSL, None otherwise
151
+ """
152
+ if protocol.lower() not in ["https", "mtls"]:
153
+ return None
154
+
155
+ # Use provided config or fallback to global config
156
+ current_config = (
157
+ self.app_config if self.app_config is not None else config.get_all()
158
+ )
159
+
160
+ # Get SSL configuration
161
+ ssl_config = self._get_ssl_config(current_config)
162
+
163
+ if not ssl_config.get("enabled", False):
164
+ get_global_logger().warning(
165
+ f"SSL required for protocol '{protocol}' but SSL is disabled"
166
+ )
167
+ return None
168
+
169
+ cert_file = ssl_config.get("cert_file")
170
+ key_file = ssl_config.get("key_file")
171
+
172
+ if not cert_file or not key_file:
173
+ get_global_logger().warning(
174
+ f"SSL required for protocol '{protocol}' but certificate files not configured"
175
+ )
176
+ return None
177
+
178
+ try:
179
+ from mcp_proxy_adapter.core.ssl_utils import SSLUtils
180
+
181
+ ssl_context = SSLUtils.create_ssl_context(
182
+ cert_file=cert_file,
183
+ key_file=key_file,
184
+ ca_cert=ssl_config.get("ca_cert"),
185
+ verify_client=protocol.lower() == "mtls"
186
+ or ssl_config.get("verify_client", False),
187
+ cipher_suites=ssl_config.get("cipher_suites", []),
188
+ min_tls_version=ssl_config.get("min_tls_version", "1.2"),
189
+ max_tls_version=ssl_config.get("max_tls_version", "1.3"),
190
+ )
191
+
192
+ get_global_logger().info(f"SSL context created for protocol '{protocol}'")
193
+ return ssl_context
194
+
195
+ except Exception as e:
196
+ get_global_logger().error(f"Failed to create SSL context for protocol '{protocol}': {e}")
197
+ return None
198
+
199
+ def _get_ssl_config(self, current_config: Dict) -> Dict:
200
+ """
201
+ Get SSL configuration from config.
202
+
203
+ Args:
204
+ current_config: Current configuration dictionary
205
+
206
+ Returns:
207
+ SSL configuration dictionary
208
+ """
209
+ # Try security framework SSL config first
210
+ security_config = current_config.get("security", {})
211
+ ssl_config = security_config.get("ssl", {})
212
+
213
+ if ssl_config.get("enabled", False):
214
+ get_global_logger().debug("Using security.ssl configuration")
215
+ return ssl_config
216
+
217
+ # Fallback to legacy SSL config
218
+ legacy_ssl_config = current_config.get("ssl", {})
219
+ if legacy_ssl_config.get("enabled", False):
220
+ get_global_logger().debug("Using legacy ssl configuration")
221
+ return legacy_ssl_config
222
+
223
+ # Return empty config if SSL is disabled
224
+ return {"enabled": False}
225
+
226
+
227
+
228
+
229
+ # Global protocol manager instance - will be updated with config when needed
230
+ protocol_manager = None
231
+
232
+
@@ -0,0 +1,19 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Proxy registration package for MCP Proxy Adapter.
6
+ """
7
+
8
+ from .proxy_registration_manager import ProxyRegistrationManager, ProxyRegistrationError
9
+ from .auth_manager import AuthManager
10
+ from .ssl_manager import SSLManager
11
+ from .registration_client import RegistrationClient
12
+
13
+ __all__ = [
14
+ "ProxyRegistrationManager",
15
+ "ProxyRegistrationError",
16
+ "AuthManager",
17
+ "SSLManager",
18
+ "RegistrationClient",
19
+ ]
@@ -0,0 +1,26 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Authentication management for proxy registration.
6
+ """
7
+
8
+ from typing import Dict, Any
9
+
10
+ from mcp_proxy_adapter.core.logging import get_global_logger
11
+
12
+
13
+ class AuthManager:
14
+ """Manager for authentication in proxy registration."""
15
+
16
+ def __init__(self, client_security, registration_config: Dict[str, Any]):
17
+ """
18
+ Initialize authentication manager.
19
+
20
+ Args:
21
+ client_security: Client security manager instance
22
+ registration_config: Registration configuration
23
+ """
24
+ self.client_security = client_security
25
+ self.registration_config = registration_config
26
+ self.logger = get_global_logger()
@@ -0,0 +1,160 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Main proxy registration manager for MCP Proxy Adapter.
6
+ """
7
+
8
+ import time
9
+ from typing import Dict, Any
10
+
11
+ from mcp_proxy_adapter.core.logging import get_global_logger
12
+ from mcp_proxy_adapter.core.client_security import create_client_security_manager
13
+ from .registration_client import RegistrationClient
14
+
15
+
16
+ class ProxyRegistrationError(Exception):
17
+ """Exception raised when proxy registration fails."""
18
+
19
+ pass
20
+
21
+
22
+ class ProxyRegistrationManager:
23
+ """
24
+ Manager for proxy registration functionality with security framework integration.
25
+
26
+ Handles automatic registration and unregistration of the server
27
+ with the MCP proxy server using secure authentication methods.
28
+ """
29
+
30
+ def __init__(self, config: Dict[str, Any]):
31
+ """
32
+ Initialize the proxy registration manager.
33
+
34
+ Args:
35
+ config: Application configuration
36
+ """
37
+ self.config = config
38
+ self.logger = get_global_logger()
39
+
40
+ # Get registration configuration
41
+ self.registration_config = config.get("proxy_registration", {})
42
+
43
+ # Initialize client security
44
+ self.client_security = create_client_security_manager(config)
45
+
46
+ # Registration state
47
+ self.proxy_url = self.registration_config.get("proxy_url")
48
+ self.server_url = None
49
+ self.registered = False
50
+ self.registration_time = None
51
+
52
+ # Initialize registration client
53
+ self.registration_client = RegistrationClient(
54
+ self.client_security, self.registration_config, config, self.proxy_url
55
+ )
56
+
57
+ def is_enabled(self) -> bool:
58
+ """
59
+ Check if proxy registration is enabled.
60
+
61
+ Returns:
62
+ True if enabled, False otherwise
63
+ """
64
+ return self.registration_config.get("enabled", False)
65
+
66
+ async def register(self) -> bool:
67
+ """
68
+ Register server with proxy.
69
+
70
+ Returns:
71
+ True if registration successful, False otherwise
72
+ """
73
+ if not self.is_enabled():
74
+ self.logger.info("Proxy registration is disabled")
75
+ return True
76
+
77
+ if not self.server_url:
78
+ self.logger.error("Server URL not set for registration")
79
+ return False
80
+
81
+ if not self.proxy_url:
82
+ self.logger.error("Proxy URL not configured")
83
+ return False
84
+
85
+ try:
86
+ self.logger.info(f"Registering with proxy: {self.proxy_url}")
87
+
88
+ success = await self.registration_client.register(self.server_url)
89
+
90
+ if success:
91
+ self.registered = True
92
+ self.registration_time = time.time()
93
+ self.logger.info("✅ Proxy registration completed successfully")
94
+ else:
95
+ self.logger.error("❌ Proxy registration failed")
96
+
97
+ return success
98
+
99
+ except Exception as e:
100
+ self.logger.error(f"Registration error: {e}")
101
+ return False
102
+
103
+ async def unregister(self) -> bool:
104
+ """
105
+ Unregister server from proxy.
106
+
107
+ Returns:
108
+ True if unregistration successful, False otherwise
109
+ """
110
+ if not self.is_enabled():
111
+ self.logger.info("Proxy registration is disabled")
112
+ return True
113
+
114
+ if not self.registered:
115
+ self.logger.info("Server not registered, skipping unregistration")
116
+ return True
117
+
118
+ try:
119
+ self.logger.info("Unregistering from proxy")
120
+
121
+ success = await self.registration_client.unregister()
122
+
123
+ if success:
124
+ self.registered = False
125
+ self.registration_time = None
126
+ self.logger.info("✅ Proxy unregistration completed successfully")
127
+ else:
128
+ self.logger.warning("⚠️ Proxy unregistration failed")
129
+
130
+ return success
131
+
132
+ except Exception as e:
133
+ self.logger.error(f"Unregistration error: {e}")
134
+ return False
135
+
136
+ def set_server_url(self, server_url: str) -> None:
137
+ """
138
+ Set server URL for registration.
139
+
140
+ Args:
141
+ server_url: Server URL to register
142
+ """
143
+ self.server_url = server_url
144
+ self.logger.info(f"Server URL set: {server_url}")
145
+
146
+ def get_registration_status(self) -> Dict[str, Any]:
147
+ """
148
+ Get current registration status.
149
+
150
+ Returns:
151
+ Dictionary with registration status information
152
+ """
153
+ return {
154
+ "enabled": self.is_enabled(),
155
+ "registered": self.registered,
156
+ "proxy_url": self.proxy_url,
157
+ "server_url": self.server_url,
158
+ "registration_time": self.registration_time,
159
+ "client_security_available": self.client_security is not None,
160
+ }