mcp-proxy-adapter 6.9.28__py3-none-any.whl → 6.9.30__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 (212) hide show
  1. mcp_proxy_adapter/__init__.py +10 -0
  2. mcp_proxy_adapter/__main__.py +8 -21
  3. mcp_proxy_adapter/api/app.py +10 -913
  4. mcp_proxy_adapter/api/core/__init__.py +18 -0
  5. mcp_proxy_adapter/api/core/app_factory.py +243 -0
  6. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  7. mcp_proxy_adapter/api/core/registration_manager.py +166 -0
  8. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  9. mcp_proxy_adapter/api/handlers.py +78 -199
  10. mcp_proxy_adapter/api/middleware/__init__.py +1 -44
  11. mcp_proxy_adapter/api/middleware/base.py +0 -42
  12. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +0 -85
  13. mcp_proxy_adapter/api/middleware/error_handling.py +1 -127
  14. mcp_proxy_adapter/api/middleware/factory.py +0 -94
  15. mcp_proxy_adapter/api/middleware/logging.py +0 -112
  16. mcp_proxy_adapter/api/middleware/performance.py +0 -35
  17. mcp_proxy_adapter/api/middleware/protocol_middleware.py +2 -98
  18. mcp_proxy_adapter/api/middleware/transport_middleware.py +0 -37
  19. mcp_proxy_adapter/api/middleware/unified_security.py +10 -10
  20. mcp_proxy_adapter/api/middleware/user_info_middleware.py +0 -118
  21. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  22. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  23. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  24. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  25. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  26. mcp_proxy_adapter/api/schemas.py +0 -61
  27. mcp_proxy_adapter/api/tool_integration.py +0 -117
  28. mcp_proxy_adapter/api/tools.py +0 -46
  29. mcp_proxy_adapter/cli/__init__.py +12 -0
  30. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  31. mcp_proxy_adapter/cli/commands/client.py +100 -0
  32. mcp_proxy_adapter/cli/commands/config_generate.py +21 -0
  33. mcp_proxy_adapter/cli/commands/config_validate.py +36 -0
  34. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  35. mcp_proxy_adapter/cli/commands/server.py +174 -0
  36. mcp_proxy_adapter/cli/commands/sets.py +128 -0
  37. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  38. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  39. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  40. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  41. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  42. mcp_proxy_adapter/cli/main.py +63 -0
  43. mcp_proxy_adapter/cli/parser.py +324 -0
  44. mcp_proxy_adapter/cli/validators.py +231 -0
  45. mcp_proxy_adapter/client/jsonrpc_client.py +406 -0
  46. mcp_proxy_adapter/client/proxy.py +45 -0
  47. mcp_proxy_adapter/commands/__init__.py +44 -28
  48. mcp_proxy_adapter/commands/auth_validation_command.py +7 -344
  49. mcp_proxy_adapter/commands/base.py +19 -43
  50. mcp_proxy_adapter/commands/builtin_commands.py +0 -75
  51. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  52. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  53. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  54. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  55. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  56. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  57. mcp_proxy_adapter/commands/catalog_manager.py +58 -928
  58. mcp_proxy_adapter/commands/cert_monitor_command.py +0 -88
  59. mcp_proxy_adapter/commands/certificate_management_command.py +0 -45
  60. mcp_proxy_adapter/commands/command_registry.py +172 -904
  61. mcp_proxy_adapter/commands/config_command.py +0 -28
  62. mcp_proxy_adapter/commands/dependency_container.py +1 -70
  63. mcp_proxy_adapter/commands/dependency_manager.py +0 -128
  64. mcp_proxy_adapter/commands/echo_command.py +0 -34
  65. mcp_proxy_adapter/commands/health_command.py +0 -3
  66. mcp_proxy_adapter/commands/help_command.py +0 -159
  67. mcp_proxy_adapter/commands/hooks.py +0 -137
  68. mcp_proxy_adapter/commands/key_management_command.py +0 -25
  69. mcp_proxy_adapter/commands/load_command.py +7 -78
  70. mcp_proxy_adapter/commands/plugins_command.py +0 -16
  71. mcp_proxy_adapter/commands/protocol_management_command.py +0 -28
  72. mcp_proxy_adapter/commands/proxy_registration_command.py +0 -88
  73. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  74. mcp_proxy_adapter/commands/registration_status_command.py +0 -43
  75. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  76. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  77. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  78. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  79. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  80. mcp_proxy_adapter/commands/reload_command.py +0 -80
  81. mcp_proxy_adapter/commands/result.py +25 -77
  82. mcp_proxy_adapter/commands/role_test_command.py +0 -44
  83. mcp_proxy_adapter/commands/roles_management_command.py +0 -199
  84. mcp_proxy_adapter/commands/security_command.py +0 -30
  85. mcp_proxy_adapter/commands/settings_command.py +0 -68
  86. mcp_proxy_adapter/commands/ssl_setup_command.py +0 -42
  87. mcp_proxy_adapter/commands/token_management_command.py +0 -1
  88. mcp_proxy_adapter/commands/transport_management_command.py +0 -20
  89. mcp_proxy_adapter/commands/unload_command.py +0 -71
  90. mcp_proxy_adapter/config.py +15 -626
  91. mcp_proxy_adapter/core/__init__.py +5 -39
  92. mcp_proxy_adapter/core/app_factory.py +14 -36
  93. mcp_proxy_adapter/core/app_runner.py +0 -27
  94. mcp_proxy_adapter/core/auth_validator.py +1 -93
  95. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  96. mcp_proxy_adapter/core/certificate/certificate_creator.py +371 -0
  97. mcp_proxy_adapter/core/certificate/certificate_extractor.py +183 -0
  98. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  99. mcp_proxy_adapter/core/certificate/certificate_validator.py +110 -0
  100. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +70 -0
  101. mcp_proxy_adapter/core/certificate_utils.py +64 -903
  102. mcp_proxy_adapter/core/client.py +10 -9
  103. mcp_proxy_adapter/core/client_manager.py +0 -19
  104. mcp_proxy_adapter/core/client_security.py +0 -2
  105. mcp_proxy_adapter/core/config/__init__.py +18 -0
  106. mcp_proxy_adapter/core/config/config.py +195 -0
  107. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  108. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  109. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  110. mcp_proxy_adapter/core/config/simple_config.py +112 -0
  111. mcp_proxy_adapter/core/config/simple_config_generator.py +50 -0
  112. mcp_proxy_adapter/core/config/simple_config_validator.py +96 -0
  113. mcp_proxy_adapter/core/config_converter.py +0 -186
  114. mcp_proxy_adapter/core/config_validator.py +96 -1238
  115. mcp_proxy_adapter/core/errors.py +7 -42
  116. mcp_proxy_adapter/core/job_manager.py +54 -0
  117. mcp_proxy_adapter/core/logging.py +2 -22
  118. mcp_proxy_adapter/core/mtls_asgi.py +0 -20
  119. mcp_proxy_adapter/core/mtls_asgi_app.py +0 -12
  120. mcp_proxy_adapter/core/mtls_proxy.py +0 -80
  121. mcp_proxy_adapter/core/mtls_server.py +3 -173
  122. mcp_proxy_adapter/core/protocol_manager.py +1 -191
  123. mcp_proxy_adapter/core/proxy/__init__.py +22 -0
  124. mcp_proxy_adapter/core/proxy/auth_manager.py +27 -0
  125. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +137 -0
  126. mcp_proxy_adapter/core/proxy/registration_client.py +60 -0
  127. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  128. mcp_proxy_adapter/core/proxy_client.py +0 -1
  129. mcp_proxy_adapter/core/proxy_registration.py +36 -913
  130. mcp_proxy_adapter/core/role_utils.py +0 -308
  131. mcp_proxy_adapter/core/security_adapter.py +1 -36
  132. mcp_proxy_adapter/core/security_factory.py +1 -150
  133. mcp_proxy_adapter/core/security_integration.py +0 -33
  134. mcp_proxy_adapter/core/server_adapter.py +1 -40
  135. mcp_proxy_adapter/core/server_engine.py +2 -173
  136. mcp_proxy_adapter/core/settings.py +0 -127
  137. mcp_proxy_adapter/core/signal_handler.py +0 -65
  138. mcp_proxy_adapter/core/ssl_utils.py +19 -137
  139. mcp_proxy_adapter/core/transport_manager.py +0 -151
  140. mcp_proxy_adapter/core/unified_config_adapter.py +1 -193
  141. mcp_proxy_adapter/core/utils.py +1 -182
  142. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  143. mcp_proxy_adapter/core/validation/config_validator.py +211 -0
  144. mcp_proxy_adapter/core/validation/file_validator.py +73 -0
  145. mcp_proxy_adapter/core/validation/protocol_validator.py +191 -0
  146. mcp_proxy_adapter/core/validation/security_validator.py +58 -0
  147. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  148. mcp_proxy_adapter/custom_openapi.py +33 -652
  149. mcp_proxy_adapter/examples/bugfix_certificate_config.py +0 -23
  150. mcp_proxy_adapter/examples/check_config.py +0 -2
  151. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  152. mcp_proxy_adapter/examples/config_builder.py +13 -2
  153. mcp_proxy_adapter/examples/config_cli.py +0 -1
  154. mcp_proxy_adapter/examples/create_test_configs.py +0 -46
  155. mcp_proxy_adapter/examples/debug_request_state.py +0 -1
  156. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +0 -47
  157. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +0 -45
  158. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +0 -12
  159. mcp_proxy_adapter/examples/full_application/commands/help_command.py +0 -12
  160. mcp_proxy_adapter/examples/full_application/commands/list_command.py +0 -7
  161. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +0 -2
  162. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +0 -59
  163. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +0 -54
  164. mcp_proxy_adapter/examples/full_application/main.py +186 -150
  165. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +0 -107
  166. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +0 -24
  167. mcp_proxy_adapter/examples/full_application/test_server.py +0 -58
  168. mcp_proxy_adapter/examples/generate_config.py +65 -11
  169. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  170. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  171. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  172. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  173. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  174. mcp_proxy_adapter/examples/required_certificates.py +0 -2
  175. mcp_proxy_adapter/examples/run_full_test_suite.py +0 -29
  176. mcp_proxy_adapter/examples/run_proxy_server.py +31 -71
  177. mcp_proxy_adapter/examples/run_security_tests_fixed.py +0 -27
  178. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  179. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  180. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  181. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  182. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  183. mcp_proxy_adapter/examples/security_test_client.py +24 -1075
  184. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  185. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  186. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  187. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  188. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  189. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  190. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  191. mcp_proxy_adapter/examples/setup_test_environment.py +133 -1425
  192. mcp_proxy_adapter/examples/test_config.py +0 -3
  193. mcp_proxy_adapter/examples/test_config_builder.py +25 -405
  194. mcp_proxy_adapter/examples/test_examples.py +0 -1
  195. mcp_proxy_adapter/examples/test_framework_complete.py +0 -2
  196. mcp_proxy_adapter/examples/test_mcp_server.py +0 -1
  197. mcp_proxy_adapter/examples/test_protocol_examples.py +0 -1
  198. mcp_proxy_adapter/examples/universal_client.py +0 -6
  199. mcp_proxy_adapter/examples/update_config_certificates.py +0 -1
  200. mcp_proxy_adapter/examples/validate_generator_compatibility.py +0 -1
  201. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +0 -187
  202. mcp_proxy_adapter/integrations/__init__.py +25 -0
  203. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  204. mcp_proxy_adapter/main.py +70 -62
  205. mcp_proxy_adapter/openapi.py +0 -22
  206. mcp_proxy_adapter/version.py +1 -1
  207. {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.30.dist-info}/METADATA +2 -1
  208. mcp_proxy_adapter-6.9.30.dist-info/RECORD +235 -0
  209. {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.30.dist-info}/entry_points.txt +1 -1
  210. mcp_proxy_adapter-6.9.28.dist-info/RECORD +0 -149
  211. {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.30.dist-info}/WHEEL +0 -0
  212. {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.30.dist-info}/top_level.txt +0 -0
@@ -6,8 +6,8 @@ including HTTP, HTTPS, and MTLS protocols with their respective ports.
6
6
  """
7
7
 
8
8
  import ssl
9
- from typing import Dict, List, Optional, Tuple, Union
10
9
  from urllib.parse import urlparse
10
+ from typing import Dict, List, Any, Optional
11
11
 
12
12
  from mcp_proxy_adapter.config import config
13
13
  from mcp_proxy_adapter.core.logging import get_global_logger
@@ -89,49 +89,8 @@ class ProtocolManager:
89
89
  f"Protocol manager loaded config: enabled={self.enabled}, allowed_protocols={self.allowed_protocols}"
90
90
  )
91
91
 
92
- def _is_ssl_enabled(self, current_config: Dict) -> bool:
93
- """
94
- Check if SSL is enabled in configuration.
95
-
96
- Args:
97
- current_config: Current configuration dictionary
98
-
99
- Returns:
100
- True if SSL is enabled, False otherwise
101
- """
102
- # Try security framework SSL config first
103
- security_config = current_config.get("security", {})
104
- ssl_config = security_config.get("ssl", {})
105
92
 
106
- if ssl_config.get("enabled", False):
107
- get_global_logger().debug("SSL enabled via security.ssl configuration")
108
- return True
109
93
 
110
- # Fallback to legacy SSL config
111
- legacy_ssl_config = current_config.get("ssl", {})
112
- if legacy_ssl_config.get("enabled", False):
113
- get_global_logger().debug("SSL enabled via legacy ssl configuration")
114
- return True
115
-
116
- get_global_logger().debug("SSL is disabled in configuration")
117
- return False
118
-
119
- def update_config(self, new_config: Dict):
120
- """
121
- Update configuration and reload protocol settings.
122
-
123
- Args:
124
- new_config: New configuration dictionary
125
- """
126
- self.app_config = new_config
127
- self._load_config()
128
- get_global_logger().info(
129
- f"Protocol manager configuration updated: allowed_protocols={self.allowed_protocols}"
130
- )
131
-
132
- def reload_config(self):
133
- """Reload protocol configuration from global config."""
134
- self._load_config()
135
94
 
136
95
  def is_protocol_allowed(self, protocol: str) -> bool:
137
96
  """
@@ -157,35 +116,7 @@ class ProtocolManager:
157
116
  get_global_logger().debug(f"🔍 ProtocolManager.is_protocol_allowed - Protocol '{protocol}' allowed: {is_allowed}")
158
117
  return is_allowed
159
118
 
160
- def get_protocol_port(self, protocol: str) -> Optional[int]:
161
- """
162
- Get the configured port for a specific protocol.
163
119
 
164
- Args:
165
- protocol: Protocol name (http, https, mtls)
166
-
167
- Returns:
168
- Port number if configured, None otherwise
169
- """
170
- protocol_lower = protocol.lower()
171
- protocol_config = self.protocols_config.get(protocol_lower, {})
172
-
173
- if not protocol_config.get("enabled", False):
174
- get_global_logger().debug(f"Protocol '{protocol}' is not enabled")
175
- return None
176
-
177
- port = protocol_config.get("port")
178
- get_global_logger().debug(f"Protocol '{protocol}' port: {port}")
179
- return port
180
-
181
- def get_allowed_protocols(self) -> List[str]:
182
- """
183
- Get list of all allowed protocols.
184
-
185
- Returns:
186
- List of allowed protocol names
187
- """
188
- return self.allowed_protocols.copy()
189
120
 
190
121
  def get_protocol_config(self, protocol: str) -> Dict:
191
122
  """
@@ -207,33 +138,6 @@ class ProtocolManager:
207
138
  return {}
208
139
  return {}
209
140
 
210
- def validate_url_protocol(self, url: str) -> Tuple[bool, Optional[str]]:
211
- """
212
- Validate if the URL protocol is allowed.
213
-
214
- Args:
215
- url: URL to validate
216
-
217
- Returns:
218
- Tuple of (is_allowed, error_message)
219
- """
220
- try:
221
- parsed = urlparse(url)
222
- protocol = parsed.scheme.lower()
223
-
224
- if not protocol:
225
- return False, "No protocol specified in URL"
226
-
227
- if not self.is_protocol_allowed(protocol):
228
- return (
229
- False,
230
- f"Protocol '{protocol}' is not allowed. Allowed protocols: {self.allowed_protocols}",
231
- )
232
-
233
- return True, None
234
-
235
- except Exception as e:
236
- return False, f"Invalid URL format: {str(e)}"
237
141
 
238
142
  def get_ssl_context_for_protocol(self, protocol: str) -> Optional[ssl.SSLContext]:
239
143
  """
@@ -319,104 +223,10 @@ class ProtocolManager:
319
223
  # Return empty config if SSL is disabled
320
224
  return {"enabled": False}
321
225
 
322
- def get_protocol_info(self) -> Dict[str, Dict]:
323
- """
324
- Get information about all configured protocols.
325
226
 
326
- Returns:
327
- Dictionary with protocol information
328
- """
329
- info = {}
330
-
331
- for protocol in ["http", "https", "mtls"]:
332
- protocol_config = self.get_protocol_config(protocol)
333
- info[protocol] = {
334
- "enabled": protocol_config.get("enabled", False),
335
- "allowed": self.is_protocol_allowed(protocol),
336
- "port": protocol_config.get("port"),
337
- "requires_ssl": protocol in ["https", "mtls"],
338
- "ssl_context_available": self.get_ssl_context_for_protocol(protocol)
339
- is not None,
340
- }
341
-
342
- return info
343
-
344
- def validate_protocol_configuration(self) -> List[str]:
345
- """
346
- Validate the current protocol configuration.
347
-
348
- Returns:
349
- List of validation errors (empty if configuration is valid)
350
- """
351
- errors = []
352
-
353
- if not self.enabled:
354
- return errors
355
-
356
- # Check if allowed protocols are configured
357
- for protocol in self.allowed_protocols:
358
- if protocol not in ["http", "https", "mtls"]:
359
- errors.append(f"Unknown protocol '{protocol}' in allowed_protocols")
360
- continue
361
-
362
- protocol_config = self.get_protocol_config(protocol)
363
-
364
- if not protocol_config.get("enabled", False):
365
- errors.append(
366
- f"Protocol '{protocol}' is in allowed_protocols but not enabled"
367
- )
368
- continue
369
-
370
- port = protocol_config.get("port")
371
- if not port:
372
- errors.append(
373
- f"Protocol '{protocol}' is enabled but no port configured"
374
- )
375
- continue
376
-
377
- # Check SSL requirements
378
- if protocol in ["https", "mtls"]:
379
- # Use provided config or fallback to global config
380
- current_config = (
381
- self.app_config if self.app_config is not None else config.get_all()
382
- )
383
- ssl_config = self._get_ssl_config(current_config)
384
-
385
- if not ssl_config.get("enabled", False):
386
- errors.append(
387
- f"Protocol '{protocol}' requires SSL but SSL is disabled"
388
- )
389
- elif not ssl_config.get("cert_file") or not ssl_config.get("key_file"):
390
- errors.append(
391
- f"Protocol '{protocol}' requires SSL but certificate files not configured"
392
- )
393
-
394
- return errors
395
227
 
396
228
 
397
229
  # Global protocol manager instance - will be updated with config when needed
398
230
  protocol_manager = None
399
231
 
400
232
 
401
- def get_protocol_manager(app_config: Optional[Dict] = None) -> ProtocolManager:
402
- """
403
- Get protocol manager instance with current configuration.
404
-
405
- Args:
406
- app_config: Application configuration dictionary (optional)
407
-
408
- Returns:
409
- ProtocolManager instance
410
- """
411
- global protocol_manager
412
-
413
- # If no app_config provided, use global config
414
- if app_config is None:
415
- app_config = config.get_all()
416
-
417
- # Create new instance if none exists or config changed
418
- if protocol_manager is None or protocol_manager.app_config != app_config:
419
- protocol_manager = ProtocolManager(app_config)
420
- get_global_logger().info("Protocol manager created with new configuration")
421
-
422
- return protocol_manager
@@ -0,0 +1,22 @@
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
+ from .proxy_registration import initialize_proxy_registration, get_proxy_registration_status
13
+
14
+ __all__ = [
15
+ "ProxyRegistrationManager",
16
+ "ProxyRegistrationError",
17
+ "AuthManager",
18
+ "SSLManager",
19
+ "RegistrationClient",
20
+ "initialize_proxy_registration",
21
+ "get_proxy_registration_status",
22
+ ]
@@ -0,0 +1,27 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Authentication management for proxy registration.
6
+ """
7
+
8
+
9
+ from mcp_proxy_adapter.core.logging import get_global_logger
10
+
11
+
12
+ class AuthManager:
13
+ """Manager for authentication in proxy registration."""
14
+
15
+ def __init__(self, client_security, registration_config: Dict[str, Any]):
16
+ """
17
+ Initialize authentication manager.
18
+
19
+ Args:
20
+ client_security: Client security manager instance
21
+ registration_config: Registration configuration
22
+ """
23
+ self.client_security = client_security
24
+ self.registration_config = registration_config
25
+ self.logger = get_global_logger()
26
+
27
+
@@ -0,0 +1,137 @@
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
+
10
+ from mcp_proxy_adapter.core.logging import get_global_logger
11
+ from mcp_proxy_adapter.core.client_security import create_client_security_manager
12
+ from .registration_client import RegistrationClient
13
+
14
+
15
+ class ProxyRegistrationError(Exception):
16
+ """Exception raised when proxy registration fails."""
17
+ pass
18
+
19
+
20
+ class ProxyRegistrationManager:
21
+ """
22
+ Manager for proxy registration functionality with security framework integration.
23
+
24
+ Handles automatic registration and unregistration of the server
25
+ with the MCP proxy server using secure authentication methods.
26
+ """
27
+
28
+ def __init__(self, config: Dict[str, Any]):
29
+ """
30
+ Initialize the proxy registration manager.
31
+
32
+ Args:
33
+ config: Application configuration
34
+ """
35
+ self.config = config
36
+ self.logger = get_global_logger()
37
+
38
+ # Get registration configuration
39
+ self.registration_config = config.get("proxy_registration", {})
40
+
41
+ # Initialize client security
42
+ self.client_security = create_client_security_manager(config)
43
+
44
+ # Registration state
45
+ self.proxy_url = self.registration_config.get("proxy_url")
46
+ self.server_url = None
47
+ self.registered = False
48
+ self.registration_time = None
49
+
50
+ # Initialize registration client
51
+ self.registration_client = RegistrationClient(
52
+ self.client_security,
53
+ self.registration_config,
54
+ config,
55
+ self.proxy_url
56
+ )
57
+
58
+ def is_enabled(self) -> bool:
59
+ """
60
+ Check if proxy registration is enabled.
61
+
62
+ Returns:
63
+ True if enabled, False otherwise
64
+ """
65
+ return self.registration_config.get("enabled", False)
66
+
67
+
68
+ async def register(self) -> bool:
69
+ """
70
+ Register server with proxy.
71
+
72
+ Returns:
73
+ True if registration successful, False otherwise
74
+ """
75
+ if not self.is_enabled():
76
+ self.logger.info("Proxy registration is disabled")
77
+ return True
78
+
79
+ if not self.server_url:
80
+ self.logger.error("Server URL not set for registration")
81
+ return False
82
+
83
+ if not self.proxy_url:
84
+ self.logger.error("Proxy URL not configured")
85
+ return False
86
+
87
+ try:
88
+ self.logger.info(f"Registering with proxy: {self.proxy_url}")
89
+
90
+ success = await self.registration_client.register(self.server_url)
91
+
92
+ if success:
93
+ self.registered = True
94
+ self.registration_time = time.time()
95
+ self.logger.info("✅ Proxy registration completed successfully")
96
+ else:
97
+ self.logger.error("❌ Proxy registration failed")
98
+
99
+ return success
100
+
101
+ except Exception as e:
102
+ self.logger.error(f"Registration error: {e}")
103
+ return False
104
+
105
+ async def unregister(self) -> bool:
106
+ """
107
+ Unregister server from proxy.
108
+
109
+ Returns:
110
+ True if unregistration successful, False otherwise
111
+ """
112
+ if not self.is_enabled():
113
+ self.logger.info("Proxy registration is disabled")
114
+ return True
115
+
116
+ if not self.registered:
117
+ self.logger.info("Server not registered, skipping unregistration")
118
+ return True
119
+
120
+ try:
121
+ self.logger.info("Unregistering from proxy")
122
+
123
+ success = await self.registration_client.unregister()
124
+
125
+ if success:
126
+ self.registered = False
127
+ self.registration_time = None
128
+ self.logger.info("✅ Proxy unregistration completed successfully")
129
+ else:
130
+ self.logger.warning("⚠️ Proxy unregistration failed")
131
+
132
+ return success
133
+
134
+ except Exception as e:
135
+ self.logger.error(f"Unregistration error: {e}")
136
+ return False
137
+
@@ -0,0 +1,60 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Registration client for proxy registration.
6
+ """
7
+
8
+ import time
9
+ import traceback
10
+
11
+ import aiohttp
12
+
13
+ from mcp_proxy_adapter.core.logging import get_global_logger
14
+ from .auth_manager import AuthManager
15
+ from .ssl_manager import SSLManager
16
+
17
+
18
+ class RegistrationClient:
19
+ """Client for proxy registration operations."""
20
+
21
+ def __init__(self, client_security, registration_config: Dict[str, Any], config: Dict[str, Any], proxy_url: str):
22
+ """
23
+ Initialize registration client.
24
+
25
+ Args:
26
+ client_security: Client security manager instance
27
+ registration_config: Registration configuration
28
+ config: Application configuration
29
+ proxy_url: Proxy server URL
30
+ """
31
+ self.client_security = client_security
32
+ self.registration_config = registration_config
33
+ self.config = config
34
+ self.proxy_url = proxy_url
35
+ self.logger = get_global_logger()
36
+
37
+ # Initialize managers
38
+ self.auth_manager = AuthManager(client_security, registration_config)
39
+ self.ssl_manager = SSLManager(client_security, registration_config, config, proxy_url)
40
+
41
+
42
+
43
+ def _prepare_registration_data(self, server_url: str) -> Dict[str, Any]:
44
+ """
45
+ Prepare registration data.
46
+
47
+ Args:
48
+ server_url: Server URL to register
49
+
50
+ Returns:
51
+ Registration data dictionary
52
+ """
53
+ return {
54
+ "server_id": self.registration_config.get("server_id"),
55
+ "server_name": self.registration_config.get("server_name"),
56
+ "server_url": server_url,
57
+ "description": self.registration_config.get("description", ""),
58
+ "version": self.registration_config.get("version", "1.0.0"),
59
+ "capabilities": self.registration_config.get("capabilities", []),
60
+ }
@@ -0,0 +1,101 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ SSL management for proxy registration.
6
+ """
7
+
8
+ import ssl
9
+ from typing import Dict, Any, Optional
10
+ from urllib.parse import urlparse
11
+
12
+ from mcp_proxy_adapter.core.logging import get_global_logger
13
+
14
+
15
+ class SSLManager:
16
+ """Manager for SSL connections in proxy registration."""
17
+
18
+ def __init__(self, client_security, registration_config: Dict[str, Any], config: Dict[str, Any], proxy_url: str):
19
+ """
20
+ Initialize SSL manager.
21
+
22
+ Args:
23
+ client_security: Client security manager instance
24
+ registration_config: Registration configuration
25
+ config: Application configuration
26
+ proxy_url: Proxy server URL
27
+ """
28
+ self.client_security = client_security
29
+ self.registration_config = registration_config
30
+ self.config = config
31
+ self.proxy_url = proxy_url
32
+ self.logger = get_global_logger()
33
+
34
+ def create_ssl_context(self) -> Optional[ssl.SSLContext]:
35
+ """
36
+ Create SSL context for secure connections using registration SSL configuration.
37
+
38
+ Returns:
39
+ SSL context or None if SSL not needed
40
+ """
41
+ self.logger.debug("_create_ssl_context called")
42
+
43
+ # Decide SSL strictly by proxy URL scheme: use SSL only for https proxy URLs
44
+ try:
45
+ scheme = urlparse(self.proxy_url).scheme if self.proxy_url else "http"
46
+ if scheme.lower() != "https":
47
+ self.logger.debug("Proxy URL is HTTP, skipping SSL context creation for registration")
48
+ return None
49
+ except Exception:
50
+ self.logger.debug("Failed to parse proxy_url, assuming HTTP and skipping SSL context")
51
+ return None
52
+
53
+ if not self.client_security:
54
+ self.logger.debug("SSL context creation failed: client_security is None")
55
+ return None
56
+
57
+ try:
58
+ # Check if SSL is enabled for registration
59
+ cert_config = self.registration_config.get("certificate", {})
60
+ ssl_config = self.registration_config.get("ssl", {})
61
+
62
+ # FALLBACK: if no explicit registration SSL/certs provided, reuse global SSL config
63
+ if not cert_config and not ssl_config:
64
+ global_ssl = self.config.get("security", {}).get("ssl", {}) or self.config.get("ssl", {})
65
+ if global_ssl:
66
+ # Map global ssl to registration-style configs
67
+ mapped_cert = {}
68
+ if global_ssl.get("cert_file") and global_ssl.get("key_file"):
69
+ mapped_cert = {
70
+ "cert_file": global_ssl.get("cert_file"),
71
+ "key_file": global_ssl.get("key_file"),
72
+ }
73
+ mapped_ssl = {}
74
+ if global_ssl.get("ca_cert"):
75
+ mapped_ssl["ca_cert"] = global_ssl.get("ca_cert")
76
+ if global_ssl.get("verify_client") is not None:
77
+ mapped_ssl["verify_mode"] = (
78
+ "CERT_REQUIRED" if global_ssl.get("verify_client") else "CERT_NONE"
79
+ )
80
+ cert_config = mapped_cert
81
+ ssl_config = mapped_ssl
82
+
83
+ # Use client security manager to create SSL context
84
+ if cert_config or ssl_config:
85
+ ssl_context = self.client_security.create_ssl_context(
86
+ cert_config=cert_config,
87
+ ssl_config=ssl_config
88
+ )
89
+ if ssl_context:
90
+ self.logger.debug("SSL context created successfully for registration")
91
+ return ssl_context
92
+ else:
93
+ self.logger.warning("Failed to create SSL context for registration")
94
+ return None
95
+ else:
96
+ self.logger.debug("No SSL configuration found for registration")
97
+ return None
98
+
99
+ except Exception as e:
100
+ self.logger.error(f"Error creating SSL context for registration: {e}")
101
+ return None
@@ -12,7 +12,6 @@ mutual TLS. Designed to be used by services built on this framework to:
12
12
  This client intentionally avoids framework-specific configuration objects and
13
13
  accepts explicit parameters for clarity and portability.
14
14
  """
15
- from __future__ import annotations
16
15
 
17
16
  import json
18
17
  import ssl