mcp-proxy-adapter 6.3.0__py3-none-any.whl → 6.3.2__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.
@@ -10,15 +10,12 @@ email: vasilyvz@gmail.com
10
10
  """
11
11
 
12
12
  import asyncio
13
- import json
14
13
  import time
15
14
  import ssl
16
15
  from typing import Dict, Any, Optional, Tuple
17
16
  from urllib.parse import urljoin
18
17
 
19
18
  import aiohttp
20
- import requests
21
- from requests.exceptions import RequestException
22
19
 
23
20
  from mcp_proxy_adapter.core.logging import logger
24
21
  from mcp_proxy_adapter.core.client_security import create_client_security_manager
@@ -26,88 +23,113 @@ from mcp_proxy_adapter.core.client_security import create_client_security_manage
26
23
 
27
24
  class ProxyRegistrationError(Exception):
28
25
  """Exception raised when proxy registration fails."""
26
+
29
27
  pass
30
28
 
31
29
 
32
30
  class ProxyRegistrationManager:
33
31
  """
34
32
  Manager for proxy registration functionality with security framework integration.
35
-
33
+
36
34
  Handles automatic registration and unregistration of the server
37
35
  with the MCP proxy server using secure authentication methods.
38
36
  """
39
-
37
+
40
38
  def __init__(self, config: Dict[str, Any]):
41
39
  """
42
40
  Initialize the proxy registration manager.
43
-
41
+
44
42
  Args:
45
43
  config: Application configuration
46
44
  """
47
45
  self.config = config
48
46
  # Try both registration and proxy_registration for backward compatibility
49
- self.registration_config = config.get("registration", config.get("proxy_registration", {}))
50
-
47
+ self.registration_config = config.get(
48
+ "registration", config.get("proxy_registration", {})
49
+ )
50
+
51
51
  # Basic registration settings
52
- self.proxy_url = self.registration_config.get("proxy_url", "https://proxy-registry.example.com")
53
- self.server_id = self.registration_config.get("server_id", self.registration_config.get("proxy_info", {}).get("name", "mcp_proxy_adapter"))
54
- self.server_name = self.registration_config.get("server_name", self.registration_config.get("proxy_info", {}).get("name", "MCP Proxy Adapter"))
55
- self.description = self.registration_config.get("description", self.registration_config.get("proxy_info", {}).get("description", "JSON-RPC API for interacting with MCP Proxy"))
56
- self.version = self.registration_config.get("version", self.registration_config.get("proxy_info", {}).get("version", "1.0.0"))
57
-
52
+ self.proxy_url = self.registration_config.get(
53
+ "proxy_url", "https://proxy-registry.example.com"
54
+ )
55
+ self.server_id = self.registration_config.get(
56
+ "server_id",
57
+ self.registration_config.get("proxy_info", {}).get(
58
+ "name", "mcp_proxy_adapter"
59
+ ),
60
+ )
61
+ self.server_name = self.registration_config.get(
62
+ "server_name",
63
+ self.registration_config.get("proxy_info", {}).get(
64
+ "name", "MCP Proxy Adapter"
65
+ ),
66
+ )
67
+ self.description = self.registration_config.get(
68
+ "description",
69
+ self.registration_config.get("proxy_info", {}).get(
70
+ "description", "JSON-RPC API for interacting with MCP Proxy"
71
+ ),
72
+ )
73
+ self.version = self.registration_config.get(
74
+ "version",
75
+ self.registration_config.get("proxy_info", {}).get("version", "1.0.0"),
76
+ )
77
+
58
78
  # Heartbeat settings
59
79
  heartbeat_config = self.registration_config.get("heartbeat", {})
60
80
  self.timeout = heartbeat_config.get("timeout", 30)
61
81
  self.retry_attempts = heartbeat_config.get("retry_attempts", 3)
62
82
  self.retry_delay = heartbeat_config.get("retry_delay", 60)
63
83
  self.heartbeat_interval = heartbeat_config.get("interval", 300)
64
-
84
+
65
85
  # Auto registration settings
66
86
  self.auto_register = self.registration_config.get("enabled", False)
67
87
  self.auto_unregister = True # Always unregister on shutdown
68
-
88
+
69
89
  # Initialize client security manager
70
90
  self.client_security = create_client_security_manager(config)
71
-
91
+
72
92
  # Registration state
73
93
  self.registered = False
74
94
  self.server_key: Optional[str] = None
75
95
  self.server_url: Optional[str] = None
76
96
  self.heartbeat_task: Optional[asyncio.Task] = None
77
-
78
- logger.info("Proxy registration manager initialized with security framework integration")
79
-
97
+
98
+ logger.info(
99
+ "Proxy registration manager initialized with security framework integration"
100
+ )
101
+
80
102
  def is_enabled(self) -> bool:
81
103
  """
82
104
  Check if proxy registration is enabled.
83
-
105
+
84
106
  Returns:
85
107
  True if registration is enabled, False otherwise.
86
108
  """
87
109
  return self.registration_config.get("enabled", False)
88
-
110
+
89
111
  def set_server_url(self, server_url: str) -> None:
90
112
  """
91
113
  Set the server URL for registration.
92
-
114
+
93
115
  Args:
94
116
  server_url: The URL where this server is accessible.
95
117
  """
96
118
  self.server_url = server_url
97
119
  logger.info(f"Proxy registration server URL set to: {server_url}")
98
-
120
+
99
121
  def _get_auth_headers(self) -> Dict[str, str]:
100
122
  """
101
123
  Get authentication headers for registration requests.
102
-
124
+
103
125
  Returns:
104
126
  Dictionary of authentication headers
105
127
  """
106
128
  if not self.client_security:
107
129
  return {"Content-Type": "application/json"}
108
-
130
+
109
131
  auth_method = self.registration_config.get("auth_method", "certificate")
110
-
132
+
111
133
  if auth_method == "certificate":
112
134
  return self.client_security.get_client_auth_headers("certificate")
113
135
  elif auth_method == "token":
@@ -117,46 +139,48 @@ class ProxyRegistrationManager:
117
139
  elif auth_method == "api_key":
118
140
  api_key_config = self.registration_config.get("api_key", {})
119
141
  api_key = api_key_config.get("key")
120
- return self.client_security.get_client_auth_headers("api_key", api_key=api_key)
142
+ return self.client_security.get_client_auth_headers(
143
+ "api_key", api_key=api_key
144
+ )
121
145
  else:
122
146
  return {"Content-Type": "application/json"}
123
-
147
+
124
148
  def _create_ssl_context(self) -> Optional[ssl.SSLContext]:
125
149
  """
126
150
  Create SSL context for secure connections.
127
-
151
+
128
152
  Returns:
129
153
  SSL context or None if SSL not needed
130
154
  """
131
155
  if not self.client_security:
132
156
  return None
133
-
157
+
134
158
  try:
135
159
  # Check if SSL is enabled for registration
136
160
  cert_config = self.registration_config.get("certificate", {})
137
161
  if cert_config.get("enabled", False):
138
162
  return self.client_security.create_client_ssl_context()
139
-
163
+
140
164
  return None
141
165
  except Exception as e:
142
166
  logger.error(f"Failed to create SSL context: {e}")
143
167
  return None
144
-
168
+
145
169
  async def register_server(self) -> bool:
146
170
  """
147
171
  Register the server with the proxy using secure authentication.
148
-
172
+
149
173
  Returns:
150
174
  True if registration was successful, False otherwise.
151
175
  """
152
176
  if not self.is_enabled():
153
177
  logger.info("Proxy registration is disabled in configuration")
154
178
  return False
155
-
179
+
156
180
  if not self.server_url:
157
181
  logger.error("Server URL not set, cannot register with proxy")
158
182
  return False
159
-
183
+
160
184
  # Prepare registration data with proxy info
161
185
  proxy_info = self.registration_config.get("proxy_info", {})
162
186
  registration_data = {
@@ -166,90 +190,100 @@ class ProxyRegistrationManager:
166
190
  "description": self.description,
167
191
  "version": self.version,
168
192
  "capabilities": proxy_info.get("capabilities", ["jsonrpc", "rest"]),
169
- "endpoints": proxy_info.get("endpoints", {
170
- "jsonrpc": "/api/jsonrpc",
171
- "rest": "/cmd",
172
- "health": "/health"
173
- })
193
+ "endpoints": proxy_info.get(
194
+ "endpoints",
195
+ {"jsonrpc": "/api/jsonrpc", "rest": "/cmd", "health": "/health"},
196
+ ),
174
197
  }
175
-
198
+
176
199
  logger.info(f"Attempting to register server with proxy at {self.proxy_url}")
177
200
  logger.debug(f"Registration data: {registration_data}")
178
-
201
+
179
202
  for attempt in range(self.retry_attempts):
180
203
  try:
181
- success, result = await self._make_secure_registration_request(registration_data)
182
-
204
+ success, result = await self._make_secure_registration_request(
205
+ registration_data
206
+ )
207
+
183
208
  if success:
184
209
  self.registered = True
185
210
  self.server_key = result.get("server_key")
186
- logger.info(f"✅ Successfully registered with proxy. Server key: {self.server_key}")
187
-
211
+ logger.info(
212
+ f"✅ Successfully registered with proxy. Server key: {self.server_key}"
213
+ )
214
+
188
215
  # Start heartbeat if enabled
189
- if self.registration_config.get("heartbeat", {}).get("enabled", True):
216
+ if self.registration_config.get("heartbeat", {}).get(
217
+ "enabled", True
218
+ ):
190
219
  await self._start_heartbeat()
191
-
220
+
192
221
  return True
193
222
  else:
194
223
  error_msg = result.get("error", {}).get("message", "Unknown error")
195
- logger.warning(f"❌ Registration attempt {attempt + 1} failed: {error_msg}")
196
-
224
+ logger.warning(
225
+ f"❌ Registration attempt {attempt + 1} failed: {error_msg}"
226
+ )
227
+
197
228
  if attempt < self.retry_attempts - 1:
198
229
  logger.info(f"Retrying in {self.retry_delay} seconds...")
199
230
  await asyncio.sleep(self.retry_delay)
200
-
231
+
201
232
  except Exception as e:
202
- logger.error(f"❌ Registration attempt {attempt + 1} failed with exception: {e}")
203
-
233
+ logger.error(
234
+ f"❌ Registration attempt {attempt + 1} failed with exception: {e}"
235
+ )
236
+
204
237
  if attempt < self.retry_attempts - 1:
205
238
  logger.info(f"Retrying in {self.retry_delay} seconds...")
206
239
  await asyncio.sleep(self.retry_delay)
207
-
208
- logger.error(f"❌ Failed to register with proxy after {self.retry_attempts} attempts")
240
+
241
+ logger.error(
242
+ f"❌ Failed to register with proxy after {self.retry_attempts} attempts"
243
+ )
209
244
  return False
210
-
245
+
211
246
  async def unregister_server(self) -> bool:
212
247
  """
213
248
  Unregister the server from the proxy.
214
-
249
+
215
250
  Returns:
216
251
  True if unregistration was successful, False otherwise.
217
252
  """
218
253
  if not self.is_enabled():
219
254
  logger.info("Proxy registration is disabled, skipping unregistration")
220
255
  return True
221
-
256
+
222
257
  if not self.registered or not self.server_key:
223
258
  logger.info("Server not registered with proxy, skipping unregistration")
224
259
  return True
225
-
260
+
226
261
  # Stop heartbeat
227
262
  await self._stop_heartbeat()
228
-
263
+
229
264
  # Extract copy_number from server_key (format: server_id_copy_number)
230
265
  try:
231
266
  copy_number = int(self.server_key.split("_")[-1])
232
267
  except (ValueError, IndexError):
233
268
  copy_number = 1
234
-
235
- unregistration_data = {
236
- "server_id": self.server_id,
237
- "copy_number": copy_number
238
- }
239
-
269
+
270
+ unregistration_data = {"server_id": self.server_id, "copy_number": copy_number}
271
+
240
272
  logger.info(f"Attempting to unregister server from proxy at {self.proxy_url}")
241
273
  logger.debug(f"Unregistration data: {unregistration_data}")
242
-
274
+
243
275
  try:
244
- success, result = await self._make_secure_unregistration_request(unregistration_data)
245
-
276
+ success, result = await self._make_secure_unregistration_request(
277
+ unregistration_data
278
+ )
279
+
246
280
  if success:
247
281
  unregistered = result.get("unregistered", False)
248
282
  if unregistered:
249
283
  logger.info("✅ Successfully unregistered from proxy")
250
284
  else:
251
285
  logger.warning("⚠️ Server was not found in proxy registry")
252
-
286
+
253
287
  self.registered = False
254
288
  self.server_key = None
255
289
  return True
@@ -257,105 +291,143 @@ class ProxyRegistrationManager:
257
291
  error_msg = result.get("error", {}).get("message", "Unknown error")
258
292
  logger.error(f"❌ Failed to unregister from proxy: {error_msg}")
259
293
  return False
260
-
294
+
261
295
  except Exception as e:
262
296
  logger.error(f"❌ Unregistration failed with exception: {e}")
263
297
  return False
264
-
265
- async def _make_secure_registration_request(self, data: Dict[str, Any]) -> Tuple[bool, Dict[str, Any]]:
298
+
299
+ async def _make_secure_registration_request(
300
+ self, data: Dict[str, Any]
301
+ ) -> Tuple[bool, Dict[str, Any]]:
266
302
  """
267
303
  Make secure registration request to proxy using security framework.
268
-
304
+
269
305
  Args:
270
306
  data: Registration data.
271
-
307
+
272
308
  Returns:
273
309
  Tuple of (success, result).
274
310
  """
275
311
  url = urljoin(self.proxy_url, "/register")
276
-
312
+
277
313
  # Get authentication headers
278
314
  headers = self._get_auth_headers()
279
315
  headers["Content-Type"] = "application/json"
280
-
316
+
281
317
  # Create SSL context if needed
282
318
  ssl_context = self._create_ssl_context()
283
-
319
+
284
320
  # Create connector with SSL context
285
321
  connector = None
286
322
  if ssl_context:
287
323
  connector = aiohttp.TCPConnector(ssl=ssl_context)
288
-
324
+
289
325
  try:
290
326
  async with aiohttp.ClientSession(connector=connector) as session:
291
327
  async with session.post(
292
328
  url,
293
329
  json=data,
294
330
  headers=headers,
295
- timeout=aiohttp.ClientTimeout(total=self.timeout)
331
+ timeout=aiohttp.ClientTimeout(total=self.timeout),
296
332
  ) as response:
297
333
  result = await response.json()
298
-
334
+
299
335
  # Validate response headers if security framework available
300
336
  if self.client_security:
301
- self.client_security.validate_server_response(dict(response.headers))
302
-
303
- return response.status == 200, result
337
+ self.client_security.validate_server_response(
338
+ dict(response.headers)
339
+ )
340
+
341
+ # Check both HTTP status and JSON success field
342
+ if response.status == 200:
343
+ success = result.get("success", False)
344
+ if not success:
345
+ error_info = result.get("error", {})
346
+ error_msg = error_info.get("message", "Unknown error")
347
+ error_code = error_info.get("code", "UNKNOWN_ERROR")
348
+ logger.warning(
349
+ f"Registration failed: {error_code} - {error_msg}"
350
+ )
351
+ return success, result
352
+ else:
353
+ logger.warning(
354
+ f"Registration failed with HTTP status: {response.status}"
355
+ )
356
+ return False, result
304
357
  finally:
305
358
  if connector:
306
359
  await connector.close()
307
-
308
- async def _make_secure_unregistration_request(self, data: Dict[str, Any]) -> Tuple[bool, Dict[str, Any]]:
360
+
361
+ async def _make_secure_unregistration_request(
362
+ self, data: Dict[str, Any]
363
+ ) -> Tuple[bool, Dict[str, Any]]:
309
364
  """
310
365
  Make secure unregistration request to proxy using security framework.
311
-
366
+
312
367
  Args:
313
368
  data: Unregistration data.
314
-
369
+
315
370
  Returns:
316
371
  Tuple of (success, result).
317
372
  """
318
373
  url = urljoin(self.proxy_url, "/unregister")
319
-
374
+
320
375
  # Get authentication headers
321
376
  headers = self._get_auth_headers()
322
377
  headers["Content-Type"] = "application/json"
323
-
378
+
324
379
  # Create SSL context if needed
325
380
  ssl_context = self._create_ssl_context()
326
-
381
+
327
382
  # Create connector with SSL context
328
383
  connector = None
329
384
  if ssl_context:
330
385
  connector = aiohttp.TCPConnector(ssl=ssl_context)
331
-
386
+
332
387
  try:
333
388
  async with aiohttp.ClientSession(connector=connector) as session:
334
389
  async with session.post(
335
390
  url,
336
391
  json=data,
337
392
  headers=headers,
338
- timeout=aiohttp.ClientTimeout(total=self.timeout)
393
+ timeout=aiohttp.ClientTimeout(total=self.timeout),
339
394
  ) as response:
340
395
  result = await response.json()
341
-
396
+
342
397
  # Validate response headers if security framework available
343
398
  if self.client_security:
344
- self.client_security.validate_server_response(dict(response.headers))
345
-
346
- return response.status == 200, result
399
+ self.client_security.validate_server_response(
400
+ dict(response.headers)
401
+ )
402
+
403
+ # Check both HTTP status and JSON success field
404
+ if response.status == 200:
405
+ success = result.get("success", False)
406
+ if not success:
407
+ error_info = result.get("error", {})
408
+ error_msg = error_info.get("message", "Unknown error")
409
+ error_code = error_info.get("code", "UNKNOWN_ERROR")
410
+ logger.warning(
411
+ f"Unregistration failed: {error_code} - {error_msg}"
412
+ )
413
+ return success, result
414
+ else:
415
+ logger.warning(
416
+ f"Unregistration failed with HTTP status: {response.status}"
417
+ )
418
+ return False, result
347
419
  finally:
348
420
  if connector:
349
421
  await connector.close()
350
-
422
+
351
423
  async def _start_heartbeat(self) -> None:
352
424
  """Start heartbeat task for keeping registration alive."""
353
425
  if self.heartbeat_task and not self.heartbeat_task.done():
354
426
  return
355
-
427
+
356
428
  self.heartbeat_task = asyncio.create_task(self._heartbeat_loop())
357
429
  logger.info("Heartbeat task started")
358
-
430
+
359
431
  async def _stop_heartbeat(self) -> None:
360
432
  """Stop heartbeat task."""
361
433
  if self.heartbeat_task and not self.heartbeat_task.done():
@@ -365,65 +437,67 @@ class ProxyRegistrationManager:
365
437
  except asyncio.CancelledError:
366
438
  pass
367
439
  logger.info("Heartbeat task stopped")
368
-
440
+
369
441
  async def _heartbeat_loop(self) -> None:
370
442
  """Heartbeat loop to keep registration alive."""
371
443
  while self.registered:
372
444
  try:
373
445
  await asyncio.sleep(self.heartbeat_interval)
374
-
446
+
375
447
  if not self.registered:
376
448
  break
377
-
449
+
378
450
  # Send heartbeat
379
451
  success = await self._send_heartbeat()
380
452
  if not success:
381
453
  logger.warning("Heartbeat failed, attempting to re-register")
382
454
  await self.register_server()
383
-
455
+
384
456
  except asyncio.CancelledError:
385
457
  break
386
458
  except Exception as e:
387
459
  logger.error(f"Heartbeat error: {e}")
388
-
460
+
389
461
  async def _send_heartbeat(self) -> bool:
390
462
  """Send heartbeat to proxy server."""
391
463
  if not self.server_key:
392
464
  return False
393
-
465
+
394
466
  heartbeat_data = {
395
467
  "server_id": self.server_id,
396
468
  "server_key": self.server_key,
397
- "timestamp": int(time.time())
469
+ "timestamp": int(time.time()),
398
470
  }
399
-
471
+
400
472
  url = urljoin(self.proxy_url, "/heartbeat")
401
-
473
+
402
474
  # Get authentication headers
403
475
  headers = self._get_auth_headers()
404
476
  headers["Content-Type"] = "application/json"
405
-
477
+
406
478
  # Create SSL context if needed
407
479
  ssl_context = self._create_ssl_context()
408
-
480
+
409
481
  # Create connector with SSL context
410
482
  connector = None
411
483
  if ssl_context:
412
484
  connector = aiohttp.TCPConnector(ssl=ssl_context)
413
-
485
+
414
486
  try:
415
487
  async with aiohttp.ClientSession(connector=connector) as session:
416
488
  async with session.post(
417
489
  url,
418
490
  json=heartbeat_data,
419
491
  headers=headers,
420
- timeout=aiohttp.ClientTimeout(total=self.timeout)
492
+ timeout=aiohttp.ClientTimeout(total=self.timeout),
421
493
  ) as response:
422
494
  if response.status == 200:
423
495
  logger.debug("Heartbeat sent successfully")
424
496
  return True
425
497
  else:
426
- logger.warning(f"Heartbeat failed with status: {response.status}")
498
+ logger.warning(
499
+ f"Heartbeat failed with status: {response.status}"
500
+ )
427
501
  return False
428
502
  except Exception as e:
429
503
  logger.error(f"Heartbeat error: {e}")
@@ -431,11 +505,11 @@ class ProxyRegistrationManager:
431
505
  finally:
432
506
  if connector:
433
507
  await connector.close()
434
-
508
+
435
509
  def get_registration_status(self) -> Dict[str, Any]:
436
510
  """
437
511
  Get current registration status.
438
-
512
+
439
513
  Returns:
440
514
  Dictionary with registration status information.
441
515
  """
@@ -446,21 +520,22 @@ class ProxyRegistrationManager:
446
520
  "server_url": self.server_url,
447
521
  "proxy_url": self.proxy_url,
448
522
  "server_id": self.server_id,
449
- "heartbeat_active": self.heartbeat_task is not None and not self.heartbeat_task.done()
523
+ "heartbeat_active": self.heartbeat_task is not None
524
+ and not self.heartbeat_task.done(),
450
525
  }
451
-
526
+
452
527
  # Add security information if available
453
528
  if self.client_security:
454
529
  status["security_enabled"] = True
455
530
  status["ssl_enabled"] = self.client_security.is_ssl_enabled()
456
531
  status["auth_methods"] = self.client_security.get_supported_auth_methods()
457
-
532
+
458
533
  cert_info = self.client_security.get_client_certificate_info()
459
534
  if cert_info:
460
535
  status["client_certificate"] = cert_info
461
536
  else:
462
537
  status["security_enabled"] = False
463
-
538
+
464
539
  return status
465
540
 
466
541
 
@@ -471,7 +546,7 @@ proxy_registration_manager: Optional[ProxyRegistrationManager] = None
471
546
  def initialize_proxy_registration(config: Dict[str, Any]) -> None:
472
547
  """
473
548
  Initialize global proxy registration manager.
474
-
549
+
475
550
  Args:
476
551
  config: Application configuration
477
552
  """
@@ -482,17 +557,17 @@ def initialize_proxy_registration(config: Dict[str, Any]) -> None:
482
557
  async def register_with_proxy(server_url: str) -> bool:
483
558
  """
484
559
  Register the server with the proxy.
485
-
560
+
486
561
  Args:
487
562
  server_url: The URL where this server is accessible.
488
-
563
+
489
564
  Returns:
490
565
  True if registration was successful, False otherwise.
491
566
  """
492
567
  if not proxy_registration_manager:
493
568
  logger.error("Proxy registration manager not initialized")
494
569
  return False
495
-
570
+
496
571
  proxy_registration_manager.set_server_url(server_url)
497
572
  return await proxy_registration_manager.register_server()
498
573
 
@@ -500,25 +575,25 @@ async def register_with_proxy(server_url: str) -> bool:
500
575
  async def unregister_from_proxy() -> bool:
501
576
  """
502
577
  Unregister the server from the proxy.
503
-
578
+
504
579
  Returns:
505
580
  True if unregistration was successful, False otherwise.
506
581
  """
507
582
  if not proxy_registration_manager:
508
583
  logger.error("Proxy registration manager not initialized")
509
584
  return False
510
-
585
+
511
586
  return await proxy_registration_manager.unregister_server()
512
587
 
513
588
 
514
589
  def get_proxy_registration_status() -> Dict[str, Any]:
515
590
  """
516
591
  Get current proxy registration status.
517
-
592
+
518
593
  Returns:
519
594
  Dictionary with registration status information.
520
595
  """
521
596
  if not proxy_registration_manager:
522
597
  return {"error": "Proxy registration manager not initialized"}
523
-
524
- return proxy_registration_manager.get_registration_status()
598
+
599
+ return proxy_registration_manager.get_registration_status()
@@ -10,6 +10,7 @@ email: vasilyvz@gmail.com
10
10
 
11
11
  import json
12
12
  import logging
13
+ import uuid
13
14
  from pathlib import Path
14
15
  from typing import Dict, Any, Optional
15
16
 
@@ -32,6 +33,7 @@ class ConfigGenerator:
32
33
  def _get_template_config(self) -> Dict[str, Any]:
33
34
  """Get template configuration with all available options."""
34
35
  return {
36
+ "uuid": str(uuid.uuid4()),
35
37
  "server": {
36
38
  "host": "0.0.0.0",
37
39
  "port": 8000,
@@ -878,6 +880,7 @@ class ConfigGenerator:
878
880
  def _get_comments_for_type(self, config_type: str) -> Dict[str, str]:
879
881
  """Get comments for configuration sections."""
880
882
  base_comments = {
883
+ "uuid": "Unique service identifier (UUID4) - REQUIRED for service identification",
881
884
  "server": "Server configuration for FastAPI application",
882
885
  "ssl": "SSL/TLS configuration for secure connections",
883
886
  "security": "Security framework configuration (mcp_security_framework)",
@@ -2,5 +2,5 @@
2
2
  Version information for MCP Proxy Adapter.
3
3
  """
4
4
 
5
- __version__ = "6.3.0"
5
+ __version__ = "6.3.2"
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-proxy-adapter
3
- Version: 6.3.0
3
+ Version: 6.3.2
4
4
  Summary: Powerful JSON-RPC microservices framework with built-in security, authentication, and proxy registration
5
5
  Home-page: https://github.com/maverikod/mcp-proxy-adapter
6
6
  Author: Vasiliy Zdanovskiy
@@ -4,7 +4,7 @@ mcp_proxy_adapter/config.py,sha256=_VpJrmdK6NS27ABgoEABvMcgUHxCjd1D1H-HUzx3-hY,2
4
4
  mcp_proxy_adapter/custom_openapi.py,sha256=jYUrCy8C1mShh3sjKj-JkzSMLAvxDLTvtzSJFj5HUNg,15023
5
5
  mcp_proxy_adapter/main.py,sha256=Q5WxLVbQ5y9cdpcriFvIuILaxFyPyyxyxQ4OeU3xaYY,3193
6
6
  mcp_proxy_adapter/openapi.py,sha256=36vOEbJjGnVZR6hUhl6mHCD29HYOEFKo2bL0JdGSm-4,13952
7
- mcp_proxy_adapter/version.py,sha256=cLE5eMWL3J6hNIyPXsLiTIJi4BsSVpfAngjwGMVZ1mQ,75
7
+ mcp_proxy_adapter/version.py,sha256=A0-RO2zxRJWT7MAmVnv81okgNGwsizc4BPyzwLzaT-w,75
8
8
  mcp_proxy_adapter/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  mcp_proxy_adapter/api/app.py,sha256=khl4kaI4mJ6dNbfAK7hR97Ek-eWC9NBeuXHr6GVbLoU,28911
10
10
  mcp_proxy_adapter/api/handlers.py,sha256=DcZT7MVBV33q-0EJ0iFqxE0VgBkFt6d_SqoRkntwyvc,8477
@@ -69,7 +69,7 @@ mcp_proxy_adapter/core/mtls_asgi.py,sha256=X2lAj3wk3L85amRCp_-10sqvZa5wJf_diXhwr
69
69
  mcp_proxy_adapter/core/mtls_asgi_app.py,sha256=VeolP08TTaqYU5fGeaZexj6EBWBDugoVrEGXzJW4PuM,6406
70
70
  mcp_proxy_adapter/core/protocol_manager.py,sha256=ISFRXjUuK4Q3uMbVB8-O_ozQSsDEH0PQA_HAKGeUrrw,14763
71
71
  mcp_proxy_adapter/core/proxy_client.py,sha256=n44T5iBS29y6E2lQLGKpOQxPYVrxIl98OAs6mMuhEsM,22916
72
- mcp_proxy_adapter/core/proxy_registration.py,sha256=Mmh-hWVJKkADLP8361Nx_SGFp9JRwtWnQtjuOhGx5Ss,19785
72
+ mcp_proxy_adapter/core/proxy_registration.py,sha256=CCxzKwkGMLjooX6aTdeBCvad4T29nnhGBQ90FcG38f0,21278
73
73
  mcp_proxy_adapter/core/role_utils.py,sha256=wMoTVz3gF5fM7jozNMwsEwPkp1tui26M-t_KH1Oz8gs,12880
74
74
  mcp_proxy_adapter/core/security_adapter.py,sha256=wZ3OH1WzhUdpN8N8CrGJSFFVNi474DqdazIqQ1T8PN4,13343
75
75
  mcp_proxy_adapter/core/security_factory.py,sha256=4r7qvBq30XfosGD_b1ZHyNVLN8rOQ3NAKuaCOCEK8jA,8262
@@ -134,10 +134,10 @@ mcp_proxy_adapter/examples/scripts/create_certificates_simple.py,sha256=xkIvUYl6
134
134
  mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py,sha256=J0qHm_BMY8RYqfuwf7V7xKsHcsRJx8E7x-8JxmW5sPw,15988
135
135
  mcp_proxy_adapter/schemas/base_schema.json,sha256=v9G9cGMd4dRhCZsOQ_FMqOi5VFyVbI6Cf3fyIvOT9dc,2881
136
136
  mcp_proxy_adapter/schemas/openapi_schema.json,sha256=C3yLkwmDsvnLW9B5gnKKdBGl4zxkeU-rEmjTrNVsQU0,8405
137
- mcp_proxy_adapter/utils/config_generator.py,sha256=0CnUuz4WMBtHY-FNB7MNS1eV6lsu_S_lpMmhefNvlEw,46502
138
- mcp_proxy_adapter-6.3.0.dist-info/licenses/LICENSE,sha256=6KdtUcTwmTRbJrAmYjVn7e6S-V42ubeDJ-AiVEzZ510,1075
139
- mcp_proxy_adapter-6.3.0.dist-info/METADATA,sha256=JgFm83RdMmT727lE7gpIwsvdQhL6xdK9EW0M5vBVFmU,22347
140
- mcp_proxy_adapter-6.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
141
- mcp_proxy_adapter-6.3.0.dist-info/entry_points.txt,sha256=J3eV6ID0lt_VSp4lIdIgBFTqLCThgObNNxRCbyfiMHw,70
142
- mcp_proxy_adapter-6.3.0.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
143
- mcp_proxy_adapter-6.3.0.dist-info/RECORD,,
137
+ mcp_proxy_adapter/utils/config_generator.py,sha256=HuNqUgV-aoJ6A1LfX_EGJAVsj-tbaOcV2H6jw6TjfmY,46648
138
+ mcp_proxy_adapter-6.3.2.dist-info/licenses/LICENSE,sha256=6KdtUcTwmTRbJrAmYjVn7e6S-V42ubeDJ-AiVEzZ510,1075
139
+ mcp_proxy_adapter-6.3.2.dist-info/METADATA,sha256=x487vHH_rG-nAcWPh8pfh6ZHteSfTpF_gu3H3BZMRxk,22347
140
+ mcp_proxy_adapter-6.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
141
+ mcp_proxy_adapter-6.3.2.dist-info/entry_points.txt,sha256=J3eV6ID0lt_VSp4lIdIgBFTqLCThgObNNxRCbyfiMHw,70
142
+ mcp_proxy_adapter-6.3.2.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
143
+ mcp_proxy_adapter-6.3.2.dist-info/RECORD,,