mcp-proxy-adapter 6.9.24__py3-none-any.whl → 6.9.26__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.
- mcp_proxy_adapter/core/config_validator.py +81 -0
- mcp_proxy_adapter/core/proxy_registration.py +20 -0
- mcp_proxy_adapter/examples/config_builder.py +1 -1
- {mcp_proxy_adapter-6.9.24.dist-info → mcp_proxy_adapter-6.9.26.dist-info}/METADATA +1 -1
- {mcp_proxy_adapter-6.9.24.dist-info → mcp_proxy_adapter-6.9.26.dist-info}/RECORD +8 -8
- {mcp_proxy_adapter-6.9.24.dist-info → mcp_proxy_adapter-6.9.26.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.9.24.dist-info → mcp_proxy_adapter-6.9.26.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.9.24.dist-info → mcp_proxy_adapter-6.9.26.dist-info}/top_level.txt +0 -0
|
@@ -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,24 @@ 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
|
+
# Try to get UUID from proxy_registration section first, then from root config
|
|
98
|
+
self.uuid = self.registration_config.get("uuid") or self.config.get("uuid")
|
|
99
|
+
if not self.uuid:
|
|
100
|
+
raise ValueError(
|
|
101
|
+
"uuid is required in registration configuration. "
|
|
102
|
+
"Please specify a UUID under 'proxy_registration.uuid' or at root level in your configuration."
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Validate UUID4 format
|
|
106
|
+
import re
|
|
107
|
+
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}$'
|
|
108
|
+
if not re.match(uuid4_pattern, self.uuid, re.IGNORECASE):
|
|
109
|
+
error_msg = f"Invalid UUID4 format: '{self.uuid}'. Expected format: xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx"
|
|
110
|
+
get_global_logger().error(f"❌ UUID validation failed: {error_msg}")
|
|
111
|
+
raise ValueError(error_msg)
|
|
112
|
+
|
|
113
|
+
get_global_logger().info(f"✅ UUID validation passed: {self.uuid}")
|
|
96
114
|
self.server_name = self.registration_config.get("server_name")
|
|
97
115
|
if not self.server_name:
|
|
98
116
|
# Try to get from proxy_info.name as fallback
|
|
@@ -113,6 +131,7 @@ class ProxyRegistrationManager:
|
|
|
113
131
|
)
|
|
114
132
|
else:
|
|
115
133
|
self.server_id = None
|
|
134
|
+
self.uuid = None
|
|
116
135
|
self.server_name = None
|
|
117
136
|
self.description = None
|
|
118
137
|
|
|
@@ -419,6 +438,7 @@ class ProxyRegistrationManager:
|
|
|
419
438
|
proxy_info = self.registration_config.get("proxy_info", {})
|
|
420
439
|
registration_data = {
|
|
421
440
|
"server_id": self.server_id,
|
|
441
|
+
"uuid": self.uuid,
|
|
422
442
|
"server_url": self.server_url,
|
|
423
443
|
"server_name": self.server_name,
|
|
424
444
|
"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.
|
|
3
|
+
Version: 6.9.26
|
|
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
|
|
@@ -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=
|
|
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=
|
|
75
|
+
mcp_proxy_adapter/core/proxy_registration.py,sha256=PCBZOrqPtqGWEW_q7u8CiQ3oHheHvKcQw6CTzbyzKTE,42945
|
|
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=
|
|
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.
|
|
146
|
-
mcp_proxy_adapter-6.9.
|
|
147
|
-
mcp_proxy_adapter-6.9.
|
|
148
|
-
mcp_proxy_adapter-6.9.
|
|
149
|
-
mcp_proxy_adapter-6.9.
|
|
145
|
+
mcp_proxy_adapter-6.9.26.dist-info/METADATA,sha256=Gam7jMn2H91U3DtecXjxf9OMTWvwZsEz1ompfXnmNmo,8539
|
|
146
|
+
mcp_proxy_adapter-6.9.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
147
|
+
mcp_proxy_adapter-6.9.26.dist-info/entry_points.txt,sha256=Bf-O5Aq80n22Ayu9fI9BgidzWqwzIVaqextAddTuHZw,563
|
|
148
|
+
mcp_proxy_adapter-6.9.26.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
|
|
149
|
+
mcp_proxy_adapter-6.9.26.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|