mcp-proxy-adapter 6.9.23__py3-none-any.whl → 6.9.25__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.

@@ -9,6 +9,7 @@ email: vasilyvz@gmail.com
9
9
  import json
10
10
  import os
11
11
  import logging
12
+ import re
12
13
  from pathlib import Path
13
14
  from typing import Dict, List, Any, Optional, Tuple, Set
14
15
  from enum import Enum
@@ -247,6 +248,8 @@ class ConfigValidator:
247
248
  self._validate_ssl_configuration()
248
249
  self._validate_proxy_registration()
249
250
  self._validate_roles_configuration()
251
+ self._validate_uuid_format()
252
+ self._validate_unknown_fields()
250
253
 
251
254
  return self.validation_results
252
255
 
@@ -1195,6 +1198,84 @@ class ConfigValidator:
1195
1198
  key="cert_file"
1196
1199
  ))
1197
1200
 
1201
+ def _validate_uuid_format(self) -> None:
1202
+ """Validate UUID4 format in configuration."""
1203
+
1204
+ # Check root level UUID
1205
+ if "uuid" in self.config_data:
1206
+ uuid_value = self.config_data["uuid"]
1207
+ if not self._is_valid_uuid4(uuid_value):
1208
+ self.validation_results.append(ValidationResult(
1209
+ level="error",
1210
+ message=f"Invalid UUID4 format: '{uuid_value}'. Expected format: xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx",
1211
+ section="uuid",
1212
+ key="uuid"
1213
+ ))
1214
+
1215
+ # Check proxy_registration UUID if it exists
1216
+ if self._has_nested_key("proxy_registration.uuid"):
1217
+ uuid_value = self._get_nested_value("proxy_registration.uuid")
1218
+ if not self._is_valid_uuid4(uuid_value):
1219
+ self.validation_results.append(ValidationResult(
1220
+ level="error",
1221
+ message=f"Invalid UUID4 format in proxy_registration: '{uuid_value}'. Expected format: xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx",
1222
+ section="proxy_registration",
1223
+ key="uuid"
1224
+ ))
1225
+
1226
+ def _is_valid_uuid4(self, uuid_str: str) -> bool:
1227
+ """Check if string is a valid UUID4."""
1228
+ if not isinstance(uuid_str, str):
1229
+ return False
1230
+
1231
+ uuid4_pattern = r'^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
1232
+ return bool(re.match(uuid4_pattern, uuid_str, re.IGNORECASE))
1233
+
1234
+ def _validate_unknown_fields(self) -> None:
1235
+ """Validate that no unknown fields are present in configuration."""
1236
+ # Define all known sections and their allowed fields
1237
+ known_sections = {
1238
+ "server": {"host", "port", "protocol", "debug", "log_level"},
1239
+ "logging": {"level", "file", "log_dir", "log_file", "error_log_file", "access_log_file",
1240
+ "max_file_size", "backup_count", "format", "date_format", "console_output", "file_output"},
1241
+ "commands": {"auto_discovery", "commands_directory", "catalog_directory", "plugin_servers",
1242
+ "auto_install_dependencies", "enabled_commands", "disabled_commands", "custom_commands_path"},
1243
+ "transport": {"type", "port", "verify_client", "chk_hostname", "ssl"},
1244
+ "proxy_registration": {"enabled", "proxy_url", "server_id", "server_name", "description", "version",
1245
+ "registration_timeout", "retry_attempts", "retry_delay", "auto_register_on_startup",
1246
+ "auto_unregister_on_shutdown", "uuid", "heartbeat"},
1247
+ "debug": {"enabled", "level"},
1248
+ "security": {"enabled", "tokens", "roles", "roles_file"},
1249
+ "roles": {"enabled", "config_file", "default_policy", "auto_load", "validation_enabled"},
1250
+ "ssl": {"enabled", "cert_file", "key_file", "ca_cert"},
1251
+ "uuid": set() # Root level UUID
1252
+ }
1253
+
1254
+ # Check for unknown root level fields
1255
+ for field in self.config_data:
1256
+ if field not in known_sections:
1257
+ self.validation_results.append(ValidationResult(
1258
+ level="warning",
1259
+ message=f"Unknown field '{field}' at root level",
1260
+ section=field,
1261
+ suggestion="Check if this field is needed or if it's a typo"
1262
+ ))
1263
+
1264
+ # Check for unknown fields in known sections
1265
+ for section_name, allowed_fields in known_sections.items():
1266
+ if section_name in self.config_data:
1267
+ section_data = self.config_data[section_name]
1268
+ if isinstance(section_data, dict):
1269
+ for field in section_data:
1270
+ if field not in allowed_fields:
1271
+ self.validation_results.append(ValidationResult(
1272
+ level="warning",
1273
+ message=f"Unknown field '{field}' in section '{section_name}'",
1274
+ section=section_name,
1275
+ key=field,
1276
+ suggestion="Check if this field is needed or if it's a typo"
1277
+ ))
1278
+
1198
1279
  def get_validation_summary(self) -> Dict[str, Any]:
1199
1280
  """Get summary of validation results."""
1200
1281
  error_count = sum(1 for r in self.validation_results if r.level == "error")
@@ -93,6 +93,23 @@ class ProxyRegistrationManager:
93
93
  "server_id is required in registration configuration. "
94
94
  "Please specify a server_id or proxy_info.name in your configuration."
95
95
  )
96
+ # UUID is mandatory for registration payload
97
+ self.uuid = self.registration_config.get("uuid")
98
+ if not self.uuid:
99
+ raise ValueError(
100
+ "uuid is required in registration configuration. "
101
+ "Please specify a UUID under 'proxy_registration.uuid' in your configuration."
102
+ )
103
+
104
+ # Validate UUID4 format
105
+ import re
106
+ uuid4_pattern = r'^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
107
+ if not re.match(uuid4_pattern, self.uuid, re.IGNORECASE):
108
+ error_msg = f"Invalid UUID4 format: '{self.uuid}'. Expected format: xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx"
109
+ get_global_logger().error(f"❌ UUID validation failed: {error_msg}")
110
+ raise ValueError(error_msg)
111
+
112
+ get_global_logger().info(f"✅ UUID validation passed: {self.uuid}")
96
113
  self.server_name = self.registration_config.get("server_name")
97
114
  if not self.server_name:
98
115
  # Try to get from proxy_info.name as fallback
@@ -113,6 +130,7 @@ class ProxyRegistrationManager:
113
130
  )
114
131
  else:
115
132
  self.server_id = None
133
+ self.uuid = None
116
134
  self.server_name = None
117
135
  self.description = None
118
136
 
@@ -419,6 +437,7 @@ class ProxyRegistrationManager:
419
437
  proxy_info = self.registration_config.get("proxy_info", {})
420
438
  registration_data = {
421
439
  "server_id": self.server_id,
440
+ "uuid": self.uuid,
422
441
  "server_url": self.server_url,
423
442
  "server_name": self.server_name,
424
443
  "description": self.description,
@@ -27,7 +27,7 @@ def generate_complete_config(host: str = "0.0.0.0", port: int = 8000) -> Dict[st
27
27
  Complete configuration dictionary
28
28
  """
29
29
  return {
30
- "uuid": str(uuid.uuid4()),
30
+ "uuid": str(uuid.uuid4()), # This generates valid UUID4
31
31
  "server": {
32
32
  "host": host,
33
33
  "port": port,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-proxy-adapter
3
- Version: 6.9.23
3
+ Version: 6.9.25
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
@@ -35,7 +35,7 @@ Requires-Dist: docstring-parser<1.0.0,>=0.15
35
35
  Requires-Dist: typing-extensions<5.0.0,>=4.5.0
36
36
  Requires-Dist: jsonrpc>=1.2.0
37
37
  Requires-Dist: psutil>=5.9.0
38
- Requires-Dist: mcp_security_framework>=1.2.6
38
+ Requires-Dist: mcp_security_framework>=1.2.8
39
39
  Requires-Dist: flask>=3.1.0
40
40
  Requires-Dist: packaging>=20.0
41
41
  Requires-Dist: aiohttp<4.0.0,>=3.8.0
@@ -62,7 +62,7 @@ mcp_proxy_adapter/core/client.py,sha256=qIbPl8prEwK2U65kl-vGJW2_imo1E4i6HxG_VpPe
62
62
  mcp_proxy_adapter/core/client_manager.py,sha256=RIOQqvoefxfjZIDLobnsQW2-_d5iA9wx4n145aIX7NI,9001
63
63
  mcp_proxy_adapter/core/client_security.py,sha256=xxws0brmT5dEKyL4vEJQZsL4PH_iXdbzsFJqCsf45Bw,13463
64
64
  mcp_proxy_adapter/core/config_converter.py,sha256=_aMJPFwKIbMlzLgtpEHBbXp_PgScKMGHGvXnq95GzgA,17654
65
- mcp_proxy_adapter/core/config_validator.py,sha256=yzDbBnx12pFKGOXeE_Xayymco8L5MJJosvYBVCJUQ34,55284
65
+ mcp_proxy_adapter/core/config_validator.py,sha256=i0tkmWPPugG5XwQvBGoNuANZwMoHidlFOIhWSezI3QE,59666
66
66
  mcp_proxy_adapter/core/crl_utils.py,sha256=JagcJBkGY-YEmkhRWBDDkfi75wIyBOlf6s7YvXgTiHI,11992
67
67
  mcp_proxy_adapter/core/errors.py,sha256=CyhQgvMt0ooQjONa65XRBJ44y-l-E5_ES4KOuRvIpBk,8557
68
68
  mcp_proxy_adapter/core/logging.py,sha256=g0ZPyDZa8sR_d1OPf-kdEEApUTp1FX_BXajrQdge6IA,8791
@@ -72,7 +72,7 @@ mcp_proxy_adapter/core/mtls_proxy.py,sha256=f_B_cB0REzHiL2WZQPBCwzQnKAzT5s0qsZ8t
72
72
  mcp_proxy_adapter/core/mtls_server.py,sha256=dhx_KXEmq8lMI2F6XEpoNybGnVzXeuVyR2abJ0_VZkE,10740
73
73
  mcp_proxy_adapter/core/protocol_manager.py,sha256=LzQMxnBfF4UKr1ZTgfK5_KDQEKrHhoJgzw1C-YJjtoQ,15055
74
74
  mcp_proxy_adapter/core/proxy_client.py,sha256=T9rqITYNijAw-yE4wvBe7ABN-LhJjkbIEeK6Rv1iUeA,6100
75
- mcp_proxy_adapter/core/proxy_registration.py,sha256=wBiRT9nSn3PpLQos69Umvuo3B5MX3oXwQVBLQ0OaeI4,41792
75
+ mcp_proxy_adapter/core/proxy_registration.py,sha256=bguolcyGaClcEuRkBkl5s8CnHsn5Vy4yrN9k2jrEM2I,42810
76
76
  mcp_proxy_adapter/core/role_utils.py,sha256=YwRenGoXI5YrHVbFjKFAH2DJs2miyqhcr9LWF7mxieg,12284
77
77
  mcp_proxy_adapter/core/security_adapter.py,sha256=ArBYnAKh4HsVAow1Qy17apkgWGn6TSiu4yVfdwXE0lk,13189
78
78
  mcp_proxy_adapter/core/security_factory.py,sha256=u_WUwnNSTsTFwRV-uwyRufbcUSeOrdZATGs4NEmfNA0,8211
@@ -89,7 +89,7 @@ mcp_proxy_adapter/examples/__init__.py,sha256=k1F-EotAFbJ3JvK_rNgiH4bUztmxIWtYn0
89
89
  mcp_proxy_adapter/examples/bugfix_certificate_config.py,sha256=YGBE_SI6wYZUJLWl7-fP1OWXiSH4mHJAZHApgQWvG7s,10529
90
90
  mcp_proxy_adapter/examples/cert_manager_bugfix.py,sha256=pwifGipvxQX2WR0sTYZWs0k8g_C228Kd5KJuR0wYB_s,7285
91
91
  mcp_proxy_adapter/examples/check_config.py,sha256=oDP3cymq76TqEpPztPihH-_sBktiEb2cG0MdVrY1Sj8,14104
92
- mcp_proxy_adapter/examples/config_builder.py,sha256=z0I5d83kdNVaR1ATaeT_P4jmxBiIcovlNu7-9I6zgcQ,6978
92
+ mcp_proxy_adapter/examples/config_builder.py,sha256=w4qXjMGgyoEZbQl1dbur6wiTC3KjaA9p6N3IP_-km5U,7008
93
93
  mcp_proxy_adapter/examples/config_cli.py,sha256=ZhVG6XEpTFe5-MzELByVsUh0AD4bHPBZeoXnGWbqifs,11059
94
94
  mcp_proxy_adapter/examples/create_test_configs.py,sha256=9TrvLa4-bWLPu0SB1JXwWuCsjj-4Vz3yAdowcHtCSSA,8228
95
95
  mcp_proxy_adapter/examples/debug_request_state.py,sha256=Z3Gy2-fWtu7KIV9OkzGDLVz7TpL_h9V_99ica40uQBU,4489
@@ -142,8 +142,8 @@ mcp_proxy_adapter/schemas/base_schema.json,sha256=v9G9cGMd4dRhCZsOQ_FMqOi5VFyVbI
142
142
  mcp_proxy_adapter/schemas/openapi_schema.json,sha256=C3yLkwmDsvnLW9B5gnKKdBGl4zxkeU-rEmjTrNVsQU0,8405
143
143
  mcp_proxy_adapter/schemas/roles.json,sha256=pgf_ZyqKyXbfGUxvobpiLiSJz9zzxrMuoVWEkEpz3N8,764
144
144
  mcp_proxy_adapter/schemas/roles_schema.json,sha256=deHgI7L6GwfBXacOlNtDgDJelDThppClC3Ti4Eh8rJY,5659
145
- mcp_proxy_adapter-6.9.23.dist-info/METADATA,sha256=Wn5Pd1sRjnuXqqSZLz6XdnyYqttAUXRVjApjB_Wg_Aw,8539
146
- mcp_proxy_adapter-6.9.23.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
147
- mcp_proxy_adapter-6.9.23.dist-info/entry_points.txt,sha256=Bf-O5Aq80n22Ayu9fI9BgidzWqwzIVaqextAddTuHZw,563
148
- mcp_proxy_adapter-6.9.23.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
149
- mcp_proxy_adapter-6.9.23.dist-info/RECORD,,
145
+ mcp_proxy_adapter-6.9.25.dist-info/METADATA,sha256=fCo-1vIB1WCjsOzQuB-UnVNnTzcGsyE6revoPZpJNyY,8539
146
+ mcp_proxy_adapter-6.9.25.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
147
+ mcp_proxy_adapter-6.9.25.dist-info/entry_points.txt,sha256=Bf-O5Aq80n22Ayu9fI9BgidzWqwzIVaqextAddTuHZw,563
148
+ mcp_proxy_adapter-6.9.25.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
149
+ mcp_proxy_adapter-6.9.25.dist-info/RECORD,,