mcp-proxy-adapter 6.9.3__py3-none-any.whl → 6.9.5__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.
- mcp_proxy_adapter/core/config_validator.py +26 -19
- mcp_proxy_adapter/core/errors.py +52 -0
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.9.3.dist-info → mcp_proxy_adapter-6.9.5.dist-info}/METADATA +1 -1
- {mcp_proxy_adapter-6.9.3.dist-info → mcp_proxy_adapter-6.9.5.dist-info}/RECORD +8 -8
- {mcp_proxy_adapter-6.9.3.dist-info → mcp_proxy_adapter-6.9.5.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.9.3.dist-info → mcp_proxy_adapter-6.9.5.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.9.3.dist-info → mcp_proxy_adapter-6.9.5.dist-info}/top_level.txt +0 -0
@@ -27,8 +27,8 @@ class ValidationLevel(Enum):
|
|
27
27
|
INFO = "info"
|
28
28
|
|
29
29
|
|
30
|
-
# Import ValidationResult from errors to avoid circular imports
|
31
|
-
from .errors import ValidationResult
|
30
|
+
# Import ValidationResult and exceptions from errors to avoid circular imports
|
31
|
+
from .errors import ValidationResult, MissingConfigKeyError
|
32
32
|
|
33
33
|
|
34
34
|
class ConfigValidator:
|
@@ -314,7 +314,7 @@ class ConfigValidator:
|
|
314
314
|
# Check conditional sections based on feature flags
|
315
315
|
for feature_name, feature_config in self.feature_flags.items():
|
316
316
|
enabled_key = feature_config["enabled_key"]
|
317
|
-
is_enabled = self.
|
317
|
+
is_enabled = self._get_nested_value_safe(enabled_key, False)
|
318
318
|
|
319
319
|
if is_enabled and feature_name in self.required_sections:
|
320
320
|
section_name = feature_name
|
@@ -362,7 +362,7 @@ class ConfigValidator:
|
|
362
362
|
"""Validate feature flags and their dependencies."""
|
363
363
|
for feature_name, feature_config in self.feature_flags.items():
|
364
364
|
enabled_key = feature_config["enabled_key"]
|
365
|
-
is_enabled = self.
|
365
|
+
is_enabled = self._get_nested_value_safe(enabled_key, False)
|
366
366
|
|
367
367
|
if is_enabled:
|
368
368
|
# Check dependencies
|
@@ -400,7 +400,7 @@ class ConfigValidator:
|
|
400
400
|
|
401
401
|
def _validate_protocol_requirements(self) -> None:
|
402
402
|
"""Validate protocol-specific requirements."""
|
403
|
-
protocol = self.
|
403
|
+
protocol = self._get_nested_value_safe("server.protocol", "http")
|
404
404
|
|
405
405
|
if protocol not in self.protocol_requirements:
|
406
406
|
self.validation_results.append(ValidationResult(
|
@@ -415,7 +415,7 @@ class ConfigValidator:
|
|
415
415
|
|
416
416
|
# Check SSL requirements
|
417
417
|
if requirements["ssl_enabled"]:
|
418
|
-
ssl_enabled = self.
|
418
|
+
ssl_enabled = self._get_nested_value_safe("ssl.enabled", False)
|
419
419
|
if not ssl_enabled:
|
420
420
|
self.validation_results.append(ValidationResult(
|
421
421
|
level="error",
|
@@ -444,7 +444,7 @@ class ConfigValidator:
|
|
444
444
|
|
445
445
|
# Check client verification requirements
|
446
446
|
if requirements["client_verification"]:
|
447
|
-
verify_client = self.
|
447
|
+
verify_client = self._get_nested_value_safe("transport.ssl.verify_client", False)
|
448
448
|
if not verify_client:
|
449
449
|
self.validation_results.append(ValidationResult(
|
450
450
|
level="error",
|
@@ -489,13 +489,13 @@ class ConfigValidator:
|
|
489
489
|
|
490
490
|
def _validate_security_consistency(self) -> None:
|
491
491
|
"""Validate security configuration consistency."""
|
492
|
-
security_enabled = self.
|
492
|
+
security_enabled = self._get_nested_value_safe("security.enabled", False)
|
493
493
|
|
494
494
|
if security_enabled:
|
495
495
|
# Check if authentication is properly configured
|
496
|
-
tokens = self.
|
497
|
-
roles = self.
|
498
|
-
roles_file = self.
|
496
|
+
tokens = self._get_nested_value_safe("security.tokens", {})
|
497
|
+
roles = self._get_nested_value_safe("security.roles", {})
|
498
|
+
roles_file = self._get_nested_value_safe("security.roles_file")
|
499
499
|
|
500
500
|
has_tokens = bool(tokens and any(tokens.values()))
|
501
501
|
has_roles = bool(roles and any(roles.values()))
|
@@ -520,7 +520,7 @@ class ConfigValidator:
|
|
520
520
|
|
521
521
|
def _validate_proxy_registration(self) -> None:
|
522
522
|
"""Validate proxy registration configuration."""
|
523
|
-
registration_enabled = self.
|
523
|
+
registration_enabled = self._get_nested_value_safe("proxy_registration.enabled", False)
|
524
524
|
|
525
525
|
if registration_enabled:
|
526
526
|
proxy_url = self._get_nested_value("proxy_registration.proxy_url")
|
@@ -533,7 +533,7 @@ class ConfigValidator:
|
|
533
533
|
))
|
534
534
|
|
535
535
|
# Check authentication method consistency
|
536
|
-
auth_method = self.
|
536
|
+
auth_method = self._get_nested_value_safe("proxy_registration.auth_method", "none")
|
537
537
|
if auth_method != "none":
|
538
538
|
if auth_method == "certificate":
|
539
539
|
cert_file = self._get_nested_value("proxy_registration.certificate.cert_file")
|
@@ -557,7 +557,7 @@ class ConfigValidator:
|
|
557
557
|
|
558
558
|
def _validate_ssl_configuration(self) -> None:
|
559
559
|
"""Validate SSL configuration with detailed certificate validation."""
|
560
|
-
ssl_enabled = self.
|
560
|
+
ssl_enabled = self._get_nested_value_safe("ssl.enabled", False)
|
561
561
|
|
562
562
|
if ssl_enabled:
|
563
563
|
cert_file = self._get_nested_value("ssl.cert_file")
|
@@ -621,7 +621,7 @@ class ConfigValidator:
|
|
621
621
|
|
622
622
|
def _validate_roles_configuration(self) -> None:
|
623
623
|
"""Validate roles configuration."""
|
624
|
-
roles_enabled = self.
|
624
|
+
roles_enabled = self._get_nested_value_safe("roles.enabled", False)
|
625
625
|
|
626
626
|
if roles_enabled:
|
627
627
|
config_file = self._get_nested_value("roles.config_file")
|
@@ -640,8 +640,8 @@ class ConfigValidator:
|
|
640
640
|
key="config_file"
|
641
641
|
))
|
642
642
|
|
643
|
-
def _get_nested_value(self, key: str
|
644
|
-
"""Get value from nested dictionary using dot notation."""
|
643
|
+
def _get_nested_value(self, key: str) -> Any:
|
644
|
+
"""Get value from nested dictionary using dot notation. Raises exception if key not found."""
|
645
645
|
keys = key.split(".")
|
646
646
|
value = self.config_data
|
647
647
|
|
@@ -649,7 +649,7 @@ class ConfigValidator:
|
|
649
649
|
if isinstance(value, dict) and k in value:
|
650
650
|
value = value[k]
|
651
651
|
else:
|
652
|
-
|
652
|
+
raise MissingConfigKeyError(k, ".".join(keys[:keys.index(k)]))
|
653
653
|
|
654
654
|
return value
|
655
655
|
|
@@ -666,11 +666,18 @@ class ConfigValidator:
|
|
666
666
|
|
667
667
|
return True
|
668
668
|
|
669
|
+
def _get_nested_value_safe(self, key: str, default: Any = None) -> Any:
|
670
|
+
"""Get value from nested dictionary using dot notation with fallback."""
|
671
|
+
try:
|
672
|
+
return self._get_nested_value(key)
|
673
|
+
except MissingConfigKeyError:
|
674
|
+
return default
|
675
|
+
|
669
676
|
def _is_file_required_for_enabled_features(self, file_key: str) -> bool:
|
670
677
|
"""Check if file is required based on enabled features."""
|
671
678
|
for feature_name, feature_config in self.feature_flags.items():
|
672
679
|
enabled_key = feature_config["enabled_key"]
|
673
|
-
is_enabled = self.
|
680
|
+
is_enabled = self._get_nested_value_safe(enabled_key, False)
|
674
681
|
|
675
682
|
if is_enabled and file_key in feature_config["required_files"]:
|
676
683
|
return True
|
mcp_proxy_adapter/core/errors.py
CHANGED
@@ -257,3 +257,55 @@ class ConfigError(MicroserviceError):
|
|
257
257
|
error_messages.append(error_msg)
|
258
258
|
|
259
259
|
return "\n".join(error_messages)
|
260
|
+
|
261
|
+
|
262
|
+
class MissingConfigKeyError(ConfigError):
|
263
|
+
"""Missing required configuration key."""
|
264
|
+
|
265
|
+
def __init__(self, key: str, section: str = None):
|
266
|
+
location = f"{section}.{key}" if section else key
|
267
|
+
message = f"Required configuration key '{location}' is missing"
|
268
|
+
super().__init__(message)
|
269
|
+
self.key = key
|
270
|
+
self.section = section
|
271
|
+
|
272
|
+
|
273
|
+
class InvalidConfigValueError(ConfigError):
|
274
|
+
"""Invalid configuration value."""
|
275
|
+
|
276
|
+
def __init__(self, key: str, value: Any, expected_type: str, section: str = None):
|
277
|
+
location = f"{section}.{key}" if section else key
|
278
|
+
message = f"Invalid value for '{location}': got {type(value).__name__}, expected {expected_type}"
|
279
|
+
super().__init__(message)
|
280
|
+
self.key = key
|
281
|
+
self.section = section
|
282
|
+
self.value = value
|
283
|
+
self.expected_type = expected_type
|
284
|
+
|
285
|
+
|
286
|
+
class MissingConfigSectionError(ConfigError):
|
287
|
+
"""Missing required configuration section."""
|
288
|
+
|
289
|
+
def __init__(self, section: str):
|
290
|
+
message = f"Required configuration section '{section}' is missing"
|
291
|
+
super().__init__(message)
|
292
|
+
self.section = section
|
293
|
+
|
294
|
+
|
295
|
+
class MissingConfigFileError(ConfigError):
|
296
|
+
"""Missing configuration file."""
|
297
|
+
|
298
|
+
def __init__(self, file_path: str):
|
299
|
+
message = f"Configuration file '{file_path}' does not exist"
|
300
|
+
super().__init__(message)
|
301
|
+
self.file_path = file_path
|
302
|
+
|
303
|
+
|
304
|
+
class InvalidConfigFileError(ConfigError):
|
305
|
+
"""Invalid configuration file format."""
|
306
|
+
|
307
|
+
def __init__(self, file_path: str, reason: str):
|
308
|
+
message = f"Invalid configuration file '{file_path}': {reason}"
|
309
|
+
super().__init__(message)
|
310
|
+
self.file_path = file_path
|
311
|
+
self.reason = reason
|
mcp_proxy_adapter/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: mcp-proxy-adapter
|
3
|
-
Version: 6.9.
|
3
|
+
Version: 6.9.5
|
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=1Ngxri2IPGoytYdCF5pXzbLUXsWcf6qYENkaDkAppg0,2
|
|
4
4
|
mcp_proxy_adapter/custom_openapi.py,sha256=XRviX-C-ZkSKdBhORhDTdeN_1FWyEfXZADiASft3t9I,28149
|
5
5
|
mcp_proxy_adapter/main.py,sha256=NFcSW7WaEnimRWe5zj28D0CH9otHlRZ92d2Um6XiGjE,10399
|
6
6
|
mcp_proxy_adapter/openapi.py,sha256=2UZOI09ZDRJuBYBjKbMyb2U4uASszoCMD5o_4ktRpvg,13480
|
7
|
-
mcp_proxy_adapter/version.py,sha256=
|
7
|
+
mcp_proxy_adapter/version.py,sha256=H4y12LYc2zqn1jp-HbYjiwhKAaPPybDzCaf9Sl6SshU,74
|
8
8
|
mcp_proxy_adapter/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
9
|
mcp_proxy_adapter/api/app.py,sha256=PQ1Ch5ydJIHp3Z6gcMCzKkTsXPQAuZ9weHtQ-EXnNGY,37134
|
10
10
|
mcp_proxy_adapter/api/handlers.py,sha256=X-hcMNVeTAu4yVkKJEChEsj2bFptUS6sLNN-Wysjkow,10011
|
@@ -62,9 +62,9 @@ mcp_proxy_adapter/core/client.py,sha256=qIbPl8prEwK2U65kl-vGJW2_imo1E4i6HxG_VpPe
|
|
62
62
|
mcp_proxy_adapter/core/client_manager.py,sha256=yD8HZJlOwmDbVU49YfzSbh1XZ-Vib8qfcLVAaH03Jdg,8832
|
63
63
|
mcp_proxy_adapter/core/client_security.py,sha256=siUaYorcDbpZsEIKgLfg-jBKkp7z_Er8wsO63mDD3Is,13127
|
64
64
|
mcp_proxy_adapter/core/config_converter.py,sha256=Wnnsrbw7DxtgDfLG-IyyzK-hkKu0_1yp7-7dW87tu_4,17422
|
65
|
-
mcp_proxy_adapter/core/config_validator.py,sha256=
|
65
|
+
mcp_proxy_adapter/core/config_validator.py,sha256=hEl1w2Ab_GZeGWNdGOVjzFVFgbzDhz3EvAsrENDXwd4,48370
|
66
66
|
mcp_proxy_adapter/core/crl_utils.py,sha256=Jnwq2UN52IoCDZCwByRP3XNMOJexftb-mVaH6zes6Fc,11706
|
67
|
-
mcp_proxy_adapter/core/errors.py,sha256=
|
67
|
+
mcp_proxy_adapter/core/errors.py,sha256=CyhQgvMt0ooQjONa65XRBJ44y-l-E5_ES4KOuRvIpBk,8557
|
68
68
|
mcp_proxy_adapter/core/logging.py,sha256=VIpiC6QTGLukRjiJoVpq3VEoLKhUeLNl8IdfljpW6ZU,9654
|
69
69
|
mcp_proxy_adapter/core/mtls_asgi.py,sha256=tvk0P9024s18dcCHY9AaQIecT4ojOTv21EuQWXwooU0,5200
|
70
70
|
mcp_proxy_adapter/core/mtls_asgi_app.py,sha256=DT_fTUH1RkvBa3ThbyCyNb-XUHyCb4DqaKA1gcZC6z4,6538
|
@@ -135,8 +135,8 @@ mcp_proxy_adapter/schemas/base_schema.json,sha256=v9G9cGMd4dRhCZsOQ_FMqOi5VFyVbI
|
|
135
135
|
mcp_proxy_adapter/schemas/openapi_schema.json,sha256=C3yLkwmDsvnLW9B5gnKKdBGl4zxkeU-rEmjTrNVsQU0,8405
|
136
136
|
mcp_proxy_adapter/schemas/roles.json,sha256=pgf_ZyqKyXbfGUxvobpiLiSJz9zzxrMuoVWEkEpz3N8,764
|
137
137
|
mcp_proxy_adapter/schemas/roles_schema.json,sha256=deHgI7L6GwfBXacOlNtDgDJelDThppClC3Ti4Eh8rJY,5659
|
138
|
-
mcp_proxy_adapter-6.9.
|
139
|
-
mcp_proxy_adapter-6.9.
|
140
|
-
mcp_proxy_adapter-6.9.
|
141
|
-
mcp_proxy_adapter-6.9.
|
142
|
-
mcp_proxy_adapter-6.9.
|
138
|
+
mcp_proxy_adapter-6.9.5.dist-info/METADATA,sha256=z40vgZzi2X2_tKG77uK2up95EKM9hKFfnDp9eT8vMAM,8510
|
139
|
+
mcp_proxy_adapter-6.9.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
140
|
+
mcp_proxy_adapter-6.9.5.dist-info/entry_points.txt,sha256=Bf-O5Aq80n22Ayu9fI9BgidzWqwzIVaqextAddTuHZw,563
|
141
|
+
mcp_proxy_adapter-6.9.5.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
|
142
|
+
mcp_proxy_adapter-6.9.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|