mcp-proxy-adapter 4.1.1__py3-none-any.whl → 6.0.0__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 (101) hide show
  1. mcp_proxy_adapter/__main__.py +12 -0
  2. mcp_proxy_adapter/api/app.py +138 -11
  3. mcp_proxy_adapter/api/handlers.py +16 -1
  4. mcp_proxy_adapter/api/middleware/__init__.py +30 -29
  5. mcp_proxy_adapter/api/middleware/auth_adapter.py +235 -0
  6. mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
  7. mcp_proxy_adapter/api/middleware/factory.py +219 -0
  8. mcp_proxy_adapter/api/middleware/logging.py +32 -6
  9. mcp_proxy_adapter/api/middleware/mtls_adapter.py +305 -0
  10. mcp_proxy_adapter/api/middleware/mtls_middleware.py +296 -0
  11. mcp_proxy_adapter/api/middleware/protocol_middleware.py +135 -0
  12. mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +241 -0
  13. mcp_proxy_adapter/api/middleware/roles_adapter.py +365 -0
  14. mcp_proxy_adapter/api/middleware/roles_middleware.py +381 -0
  15. mcp_proxy_adapter/api/middleware/security.py +376 -0
  16. mcp_proxy_adapter/api/middleware/token_auth_middleware.py +261 -0
  17. mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
  18. mcp_proxy_adapter/commands/__init__.py +13 -4
  19. mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
  20. mcp_proxy_adapter/commands/base.py +61 -30
  21. mcp_proxy_adapter/commands/builtin_commands.py +89 -0
  22. mcp_proxy_adapter/commands/catalog_manager.py +838 -0
  23. mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
  24. mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
  25. mcp_proxy_adapter/commands/command_registry.py +703 -354
  26. mcp_proxy_adapter/commands/dependency_manager.py +245 -0
  27. mcp_proxy_adapter/commands/health_command.py +7 -0
  28. mcp_proxy_adapter/commands/hooks.py +200 -167
  29. mcp_proxy_adapter/commands/key_management_command.py +506 -0
  30. mcp_proxy_adapter/commands/load_command.py +176 -0
  31. mcp_proxy_adapter/commands/plugins_command.py +235 -0
  32. mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
  33. mcp_proxy_adapter/commands/proxy_registration_command.py +268 -0
  34. mcp_proxy_adapter/commands/reload_command.py +48 -50
  35. mcp_proxy_adapter/commands/result.py +1 -0
  36. mcp_proxy_adapter/commands/roles_management_command.py +697 -0
  37. mcp_proxy_adapter/commands/ssl_setup_command.py +483 -0
  38. mcp_proxy_adapter/commands/token_management_command.py +529 -0
  39. mcp_proxy_adapter/commands/transport_management_command.py +144 -0
  40. mcp_proxy_adapter/commands/unload_command.py +158 -0
  41. mcp_proxy_adapter/config.py +99 -2
  42. mcp_proxy_adapter/core/auth_validator.py +606 -0
  43. mcp_proxy_adapter/core/certificate_utils.py +827 -0
  44. mcp_proxy_adapter/core/config_converter.py +405 -0
  45. mcp_proxy_adapter/core/config_validator.py +218 -0
  46. mcp_proxy_adapter/core/logging.py +11 -0
  47. mcp_proxy_adapter/core/protocol_manager.py +226 -0
  48. mcp_proxy_adapter/core/proxy_registration.py +270 -0
  49. mcp_proxy_adapter/core/role_utils.py +426 -0
  50. mcp_proxy_adapter/core/security_adapter.py +373 -0
  51. mcp_proxy_adapter/core/security_factory.py +239 -0
  52. mcp_proxy_adapter/core/settings.py +1 -0
  53. mcp_proxy_adapter/core/ssl_utils.py +233 -0
  54. mcp_proxy_adapter/core/transport_manager.py +292 -0
  55. mcp_proxy_adapter/custom_openapi.py +22 -11
  56. mcp_proxy_adapter/examples/basic_server/config.json +58 -23
  57. mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +54 -0
  58. mcp_proxy_adapter/examples/basic_server/config_http.json +70 -0
  59. mcp_proxy_adapter/examples/basic_server/config_http_only.json +52 -0
  60. mcp_proxy_adapter/examples/basic_server/config_https.json +58 -0
  61. mcp_proxy_adapter/examples/basic_server/config_mtls.json +58 -0
  62. mcp_proxy_adapter/examples/basic_server/config_ssl.json +46 -0
  63. mcp_proxy_adapter/examples/basic_server/server.py +12 -1
  64. mcp_proxy_adapter/examples/custom_commands/__init__.py +1 -1
  65. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +339 -23
  66. mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +105 -0
  67. mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +129 -0
  68. mcp_proxy_adapter/examples/custom_commands/config.json +101 -18
  69. mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +46 -0
  70. mcp_proxy_adapter/examples/custom_commands/config_https_only.json +46 -0
  71. mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +33 -0
  72. mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +46 -0
  73. mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +33 -0
  74. mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +33 -0
  75. mcp_proxy_adapter/examples/custom_commands/full_help_response.json +1 -0
  76. mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +629 -0
  77. mcp_proxy_adapter/examples/custom_commands/get_openapi.py +103 -0
  78. mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +129 -0
  79. mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +278 -0
  80. mcp_proxy_adapter/examples/custom_commands/server.py +92 -68
  81. mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +75 -0
  82. mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +299 -0
  83. mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +278 -0
  84. mcp_proxy_adapter/examples/custom_commands/test_openapi.py +27 -0
  85. mcp_proxy_adapter/examples/custom_commands/test_registry.py +23 -0
  86. mcp_proxy_adapter/examples/custom_commands/test_simple.py +19 -0
  87. mcp_proxy_adapter/examples/custom_project_example/README.md +103 -0
  88. mcp_proxy_adapter/examples/custom_project_example/README_EN.md +103 -0
  89. mcp_proxy_adapter/examples/simple_custom_commands/README.md +149 -0
  90. mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +149 -0
  91. mcp_proxy_adapter/main.py +175 -0
  92. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  93. mcp_proxy_adapter/tests/unit/test_config.py +53 -0
  94. mcp_proxy_adapter/version.py +1 -1
  95. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/METADATA +2 -1
  96. mcp_proxy_adapter-6.0.0.dist-info/RECORD +179 -0
  97. mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
  98. mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
  99. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/WHEEL +0 -0
  100. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/licenses/LICENSE +0 -0
  101. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,226 @@
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 typing import Dict, List, Optional, Tuple, Union
10
+ from urllib.parse import urlparse
11
+
12
+ from mcp_proxy_adapter.config import config
13
+ from mcp_proxy_adapter.core.logging import 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):
25
+ """Initialize the protocol manager."""
26
+ self.protocols_config = config.get("protocols", {})
27
+ self.enabled = self.protocols_config.get("enabled", True)
28
+ self.allowed_protocols = self.protocols_config.get("allowed_protocols", ["http"])
29
+
30
+ def is_protocol_allowed(self, protocol: str) -> bool:
31
+ """
32
+ Check if a protocol is allowed based on configuration.
33
+
34
+ Args:
35
+ protocol: Protocol name (http, https, mtls)
36
+
37
+ Returns:
38
+ True if protocol is allowed, False otherwise
39
+ """
40
+ if not self.enabled:
41
+ logger.debug("Protocol management is disabled, allowing all protocols")
42
+ return True
43
+
44
+ protocol_lower = protocol.lower()
45
+ is_allowed = protocol_lower in self.allowed_protocols
46
+
47
+ logger.debug(f"Protocol '{protocol}' allowed: {is_allowed}")
48
+ return is_allowed
49
+
50
+ def get_protocol_port(self, protocol: str) -> Optional[int]:
51
+ """
52
+ Get the configured port for a specific protocol.
53
+
54
+ Args:
55
+ protocol: Protocol name (http, https, mtls)
56
+
57
+ Returns:
58
+ Port number if configured, None otherwise
59
+ """
60
+ protocol_lower = protocol.lower()
61
+ protocol_config = self.protocols_config.get(protocol_lower, {})
62
+
63
+ if not protocol_config.get("enabled", False):
64
+ logger.debug(f"Protocol '{protocol}' is not enabled")
65
+ return None
66
+
67
+ port = protocol_config.get("port")
68
+ logger.debug(f"Protocol '{protocol}' port: {port}")
69
+ return port
70
+
71
+ def get_allowed_protocols(self) -> List[str]:
72
+ """
73
+ Get list of all allowed protocols.
74
+
75
+ Returns:
76
+ List of allowed protocol names
77
+ """
78
+ return self.allowed_protocols.copy()
79
+
80
+ def get_protocol_config(self, protocol: str) -> Dict:
81
+ """
82
+ Get full configuration for a specific protocol.
83
+
84
+ Args:
85
+ protocol: Protocol name (http, https, mtls)
86
+
87
+ Returns:
88
+ Protocol configuration dictionary
89
+ """
90
+ protocol_lower = protocol.lower()
91
+ return self.protocols_config.get(protocol_lower, {}).copy()
92
+
93
+ def validate_url_protocol(self, url: str) -> Tuple[bool, Optional[str]]:
94
+ """
95
+ Validate if the URL protocol is allowed.
96
+
97
+ Args:
98
+ url: URL to validate
99
+
100
+ Returns:
101
+ Tuple of (is_allowed, error_message)
102
+ """
103
+ try:
104
+ parsed = urlparse(url)
105
+ protocol = parsed.scheme.lower()
106
+
107
+ if not protocol:
108
+ return False, "No protocol specified in URL"
109
+
110
+ if not self.is_protocol_allowed(protocol):
111
+ return False, f"Protocol '{protocol}' is not allowed. Allowed protocols: {self.allowed_protocols}"
112
+
113
+ return True, None
114
+
115
+ except Exception as e:
116
+ return False, f"Invalid URL format: {str(e)}"
117
+
118
+ def get_ssl_context_for_protocol(self, protocol: str) -> Optional[ssl.SSLContext]:
119
+ """
120
+ Get SSL context for HTTPS or MTLS protocol.
121
+
122
+ Args:
123
+ protocol: Protocol name (https, mtls)
124
+
125
+ Returns:
126
+ SSL context if protocol requires SSL, None otherwise
127
+ """
128
+ if protocol.lower() not in ["https", "mtls"]:
129
+ return None
130
+
131
+ ssl_config = config.get("ssl", {})
132
+
133
+ if not ssl_config.get("enabled", False):
134
+ logger.warning(f"SSL required for protocol '{protocol}' but SSL is disabled")
135
+ return None
136
+
137
+ cert_file = ssl_config.get("cert_file")
138
+ key_file = ssl_config.get("key_file")
139
+
140
+ if not cert_file or not key_file:
141
+ logger.warning(f"SSL required for protocol '{protocol}' but certificate files not configured")
142
+ return None
143
+
144
+ try:
145
+ from mcp_proxy_adapter.core.ssl_utils import SSLUtils
146
+
147
+ ssl_context = SSLUtils.create_ssl_context(
148
+ cert_file=cert_file,
149
+ key_file=key_file,
150
+ ca_cert=ssl_config.get("ca_cert"),
151
+ verify_client=protocol.lower() == "mtls" or ssl_config.get("verify_client", False),
152
+ cipher_suites=ssl_config.get("cipher_suites", []),
153
+ min_tls_version=ssl_config.get("min_tls_version", "1.2"),
154
+ max_tls_version=ssl_config.get("max_tls_version", "1.3")
155
+ )
156
+
157
+ logger.info(f"SSL context created for protocol '{protocol}'")
158
+ return ssl_context
159
+
160
+ except Exception as e:
161
+ logger.error(f"Failed to create SSL context for protocol '{protocol}': {e}")
162
+ return None
163
+
164
+ def get_protocol_info(self) -> Dict[str, Dict]:
165
+ """
166
+ Get information about all configured protocols.
167
+
168
+ Returns:
169
+ Dictionary with protocol information
170
+ """
171
+ info = {}
172
+
173
+ for protocol in ["http", "https", "mtls"]:
174
+ protocol_config = self.get_protocol_config(protocol)
175
+ info[protocol] = {
176
+ "enabled": protocol_config.get("enabled", False),
177
+ "allowed": self.is_protocol_allowed(protocol),
178
+ "port": protocol_config.get("port"),
179
+ "requires_ssl": protocol in ["https", "mtls"],
180
+ "ssl_context_available": self.get_ssl_context_for_protocol(protocol) is not None
181
+ }
182
+
183
+ return info
184
+
185
+ def validate_protocol_configuration(self) -> List[str]:
186
+ """
187
+ Validate the current protocol configuration.
188
+
189
+ Returns:
190
+ List of validation errors (empty if configuration is valid)
191
+ """
192
+ errors = []
193
+
194
+ if not self.enabled:
195
+ return errors
196
+
197
+ # Check if allowed protocols are configured
198
+ for protocol in self.allowed_protocols:
199
+ if protocol not in ["http", "https", "mtls"]:
200
+ errors.append(f"Unknown protocol '{protocol}' in allowed_protocols")
201
+ continue
202
+
203
+ protocol_config = self.get_protocol_config(protocol)
204
+
205
+ if not protocol_config.get("enabled", False):
206
+ errors.append(f"Protocol '{protocol}' is in allowed_protocols but not enabled")
207
+ continue
208
+
209
+ port = protocol_config.get("port")
210
+ if not port:
211
+ errors.append(f"Protocol '{protocol}' is enabled but no port configured")
212
+ continue
213
+
214
+ # Check SSL requirements
215
+ if protocol in ["https", "mtls"]:
216
+ ssl_config = config.get("ssl", {})
217
+ if not ssl_config.get("enabled", False):
218
+ errors.append(f"Protocol '{protocol}' requires SSL but SSL is disabled")
219
+ elif not ssl_config.get("cert_file") or not ssl_config.get("key_file"):
220
+ errors.append(f"Protocol '{protocol}' requires SSL but certificate files not configured")
221
+
222
+ return errors
223
+
224
+
225
+ # Global protocol manager instance
226
+ protocol_manager = ProtocolManager()
@@ -0,0 +1,270 @@
1
+ """
2
+ Module for proxy registration functionality.
3
+
4
+ This module handles automatic registration and unregistration of the server
5
+ with the MCP proxy server during startup and shutdown.
6
+ """
7
+
8
+ import asyncio
9
+ import json
10
+ import time
11
+ from typing import Dict, Any, Optional, Tuple
12
+ from urllib.parse import urljoin
13
+
14
+ import aiohttp
15
+ import requests
16
+ from requests.exceptions import RequestException
17
+
18
+ from mcp_proxy_adapter.config import config
19
+ from mcp_proxy_adapter.core.logging import logger
20
+
21
+
22
+ class ProxyRegistrationError(Exception):
23
+ """Exception raised when proxy registration fails."""
24
+ pass
25
+
26
+
27
+ class ProxyRegistrationManager:
28
+ """
29
+ Manager for proxy registration functionality.
30
+
31
+ Handles automatic registration and unregistration of the server
32
+ with the MCP proxy server.
33
+ """
34
+
35
+ def __init__(self):
36
+ """Initialize the proxy registration manager."""
37
+ self.registration_config = config.get("proxy_registration", {})
38
+ self.proxy_url = self.registration_config.get("proxy_url", "http://localhost:3004")
39
+ self.server_id = self.registration_config.get("server_id", "mcp_proxy_adapter")
40
+ self.server_name = self.registration_config.get("server_name", "MCP Proxy Adapter")
41
+ self.description = self.registration_config.get("description", "JSON-RPC API for interacting with MCP Proxy")
42
+ self.timeout = self.registration_config.get("registration_timeout", 30)
43
+ self.retry_attempts = self.registration_config.get("retry_attempts", 3)
44
+ self.retry_delay = self.registration_config.get("retry_delay", 5)
45
+ self.auto_register = self.registration_config.get("auto_register_on_startup", True)
46
+ self.auto_unregister = self.registration_config.get("auto_unregister_on_shutdown", True)
47
+
48
+ self.registered = False
49
+ self.server_key: Optional[str] = None
50
+ self.server_url: Optional[str] = None
51
+
52
+ def is_enabled(self) -> bool:
53
+ """
54
+ Check if proxy registration is enabled.
55
+
56
+ Returns:
57
+ True if registration is enabled, False otherwise.
58
+ """
59
+ return self.registration_config.get("enabled", False)
60
+
61
+ def set_server_url(self, server_url: str) -> None:
62
+ """
63
+ Set the server URL for registration.
64
+
65
+ Args:
66
+ server_url: The URL where this server is accessible.
67
+ """
68
+ self.server_url = server_url
69
+ logger.info(f"Proxy registration server URL set to: {server_url}")
70
+
71
+ async def register_server(self) -> bool:
72
+ """
73
+ Register the server with the proxy.
74
+
75
+ Returns:
76
+ True if registration was successful, False otherwise.
77
+ """
78
+ if not self.is_enabled():
79
+ logger.info("Proxy registration is disabled in configuration")
80
+ return False
81
+
82
+ if not self.server_url:
83
+ logger.error("Server URL not set, cannot register with proxy")
84
+ return False
85
+
86
+ registration_data = {
87
+ "server_id": self.server_id,
88
+ "server_url": self.server_url,
89
+ "server_name": self.server_name,
90
+ "description": self.description
91
+ }
92
+
93
+ logger.info(f"Attempting to register server with proxy at {self.proxy_url}")
94
+ logger.debug(f"Registration data: {registration_data}")
95
+
96
+ for attempt in range(self.retry_attempts):
97
+ try:
98
+ success, result = await self._make_registration_request(registration_data)
99
+
100
+ if success:
101
+ self.registered = True
102
+ self.server_key = result.get("server_key")
103
+ logger.info(f"✅ Successfully registered with proxy. Server key: {self.server_key}")
104
+ return True
105
+ else:
106
+ error_msg = result.get("error", {}).get("message", "Unknown error")
107
+ logger.warning(f"❌ Registration attempt {attempt + 1} failed: {error_msg}")
108
+
109
+ if attempt < self.retry_attempts - 1:
110
+ logger.info(f"Retrying in {self.retry_delay} seconds...")
111
+ await asyncio.sleep(self.retry_delay)
112
+
113
+ except Exception as e:
114
+ logger.error(f"❌ Registration attempt {attempt + 1} failed with exception: {e}")
115
+
116
+ if attempt < self.retry_attempts - 1:
117
+ logger.info(f"Retrying in {self.retry_delay} seconds...")
118
+ await asyncio.sleep(self.retry_delay)
119
+
120
+ logger.error(f"❌ Failed to register with proxy after {self.retry_attempts} attempts")
121
+ return False
122
+
123
+ async def unregister_server(self) -> bool:
124
+ """
125
+ Unregister the server from the proxy.
126
+
127
+ Returns:
128
+ True if unregistration was successful, False otherwise.
129
+ """
130
+ if not self.is_enabled():
131
+ logger.info("Proxy registration is disabled, skipping unregistration")
132
+ return True
133
+
134
+ if not self.registered or not self.server_key:
135
+ logger.info("Server not registered with proxy, skipping unregistration")
136
+ return True
137
+
138
+ # Extract copy_number from server_key (format: server_id_copy_number)
139
+ try:
140
+ copy_number = int(self.server_key.split("_")[-1])
141
+ except (ValueError, IndexError):
142
+ copy_number = 1
143
+
144
+ unregistration_data = {
145
+ "server_id": self.server_id,
146
+ "copy_number": copy_number
147
+ }
148
+
149
+ logger.info(f"Attempting to unregister server from proxy at {self.proxy_url}")
150
+ logger.debug(f"Unregistration data: {unregistration_data}")
151
+
152
+ try:
153
+ success, result = await self._make_unregistration_request(unregistration_data)
154
+
155
+ if success:
156
+ unregistered = result.get("unregistered", False)
157
+ if unregistered:
158
+ logger.info("✅ Successfully unregistered from proxy")
159
+ else:
160
+ logger.warning("⚠️ Server was not found in proxy registry")
161
+
162
+ self.registered = False
163
+ self.server_key = None
164
+ return True
165
+ else:
166
+ error_msg = result.get("error", {}).get("message", "Unknown error")
167
+ logger.error(f"❌ Failed to unregister from proxy: {error_msg}")
168
+ return False
169
+
170
+ except Exception as e:
171
+ logger.error(f"❌ Unregistration failed with exception: {e}")
172
+ return False
173
+
174
+ async def _make_registration_request(self, data: Dict[str, Any]) -> Tuple[bool, Dict[str, Any]]:
175
+ """
176
+ Make registration request to proxy.
177
+
178
+ Args:
179
+ data: Registration data.
180
+
181
+ Returns:
182
+ Tuple of (success, result).
183
+ """
184
+ url = urljoin(self.proxy_url, "/register")
185
+
186
+ async with aiohttp.ClientSession() as session:
187
+ async with session.post(
188
+ url,
189
+ json=data,
190
+ headers={"Content-Type": "application/json"},
191
+ timeout=aiohttp.ClientTimeout(total=self.timeout)
192
+ ) as response:
193
+ result = await response.json()
194
+ return response.status == 200, result
195
+
196
+ async def _make_unregistration_request(self, data: Dict[str, Any]) -> Tuple[bool, Dict[str, Any]]:
197
+ """
198
+ Make unregistration request to proxy.
199
+
200
+ Args:
201
+ data: Unregistration data.
202
+
203
+ Returns:
204
+ Tuple of (success, result).
205
+ """
206
+ url = urljoin(self.proxy_url, "/unregister")
207
+
208
+ async with aiohttp.ClientSession() as session:
209
+ async with session.post(
210
+ url,
211
+ json=data,
212
+ headers={"Content-Type": "application/json"},
213
+ timeout=aiohttp.ClientTimeout(total=self.timeout)
214
+ ) as response:
215
+ result = await response.json()
216
+ return response.status == 200, result
217
+
218
+ def get_registration_status(self) -> Dict[str, Any]:
219
+ """
220
+ Get current registration status.
221
+
222
+ Returns:
223
+ Dictionary with registration status information.
224
+ """
225
+ return {
226
+ "enabled": self.is_enabled(),
227
+ "registered": self.registered,
228
+ "server_key": self.server_key,
229
+ "server_url": self.server_url,
230
+ "proxy_url": self.proxy_url,
231
+ "server_id": self.server_id
232
+ }
233
+
234
+
235
+ # Global proxy registration manager instance
236
+ proxy_registration_manager = ProxyRegistrationManager()
237
+
238
+
239
+ async def register_with_proxy(server_url: str) -> bool:
240
+ """
241
+ Register the server with the proxy.
242
+
243
+ Args:
244
+ server_url: The URL where this server is accessible.
245
+
246
+ Returns:
247
+ True if registration was successful, False otherwise.
248
+ """
249
+ proxy_registration_manager.set_server_url(server_url)
250
+ return await proxy_registration_manager.register_server()
251
+
252
+
253
+ async def unregister_from_proxy() -> bool:
254
+ """
255
+ Unregister the server from the proxy.
256
+
257
+ Returns:
258
+ True if unregistration was successful, False otherwise.
259
+ """
260
+ return await proxy_registration_manager.unregister_server()
261
+
262
+
263
+ def get_proxy_registration_status() -> Dict[str, Any]:
264
+ """
265
+ Get current proxy registration status.
266
+
267
+ Returns:
268
+ Dictionary with registration status information.
269
+ """
270
+ return proxy_registration_manager.get_registration_status()