mcp-proxy-adapter 6.8.2__tar.gz → 6.9.1__tar.gz

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 (159) hide show
  1. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/PKG-INFO +1 -1
  2. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/config.py +208 -110
  3. mcp_proxy_adapter-6.9.1/mcp_proxy_adapter/core/config_validator.py +1106 -0
  4. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/errors.py +42 -0
  5. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/logging.py +16 -16
  6. mcp_proxy_adapter-6.9.1/mcp_proxy_adapter/examples/config_builder.py +217 -0
  7. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/full_application/main.py +10 -2
  8. mcp_proxy_adapter-6.9.1/mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
  9. mcp_proxy_adapter-6.9.1/mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
  10. mcp_proxy_adapter-6.9.1/mcp_proxy_adapter/examples/full_application/test_server.py +221 -0
  11. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/generate_config.py +61 -8
  12. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/test_config.py +47 -2
  13. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/version.py +1 -1
  14. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter.egg-info/PKG-INFO +1 -1
  15. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter.egg-info/SOURCES.txt +15 -1
  16. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/pyproject.toml +1 -1
  17. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/setup.py +13 -3
  18. mcp_proxy_adapter-6.9.1/tests/test_certificate_validation.py +345 -0
  19. mcp_proxy_adapter-6.9.1/tests/test_config_integration.py +287 -0
  20. mcp_proxy_adapter-6.9.1/tests/test_config_validation.py +491 -0
  21. mcp_proxy_adapter-6.9.1/tests/test_config_validation_isolated.py +458 -0
  22. mcp_proxy_adapter-6.9.1/tests/test_direct_import.py +87 -0
  23. mcp_proxy_adapter-6.9.1/tests/test_isolated_validation.py +281 -0
  24. mcp_proxy_adapter-6.9.1/tests/test_no_defaults.py +313 -0
  25. mcp_proxy_adapter-6.9.1/tests/test_simple_validation.py +197 -0
  26. mcp_proxy_adapter-6.8.2/mcp_proxy_adapter/core/config_validator.py +0 -218
  27. mcp_proxy_adapter-6.8.2/mcp_proxy_adapter/examples/config_builder.py +0 -766
  28. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/README.md +0 -0
  29. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/__init__.py +0 -0
  30. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/__main__.py +0 -0
  31. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/__init__.py +0 -0
  32. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/app.py +0 -0
  33. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/handlers.py +0 -0
  34. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/middleware/__init__.py +0 -0
  35. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/middleware/base.py +0 -0
  36. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/middleware/command_permission_middleware.py +0 -0
  37. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/middleware/error_handling.py +0 -0
  38. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/middleware/factory.py +0 -0
  39. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/middleware/logging.py +0 -0
  40. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/middleware/performance.py +0 -0
  41. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/middleware/protocol_middleware.py +0 -0
  42. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/middleware/transport_middleware.py +0 -0
  43. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/middleware/unified_security.py +0 -0
  44. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/middleware/user_info_middleware.py +0 -0
  45. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/schemas.py +0 -0
  46. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/tool_integration.py +0 -0
  47. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/api/tools.py +0 -0
  48. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/__init__.py +0 -0
  49. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/auth_validation_command.py +0 -0
  50. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/base.py +0 -0
  51. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/builtin_commands.py +0 -0
  52. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/catalog_manager.py +0 -0
  53. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/cert_monitor_command.py +0 -0
  54. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/certificate_management_command.py +0 -0
  55. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/command_registry.py +0 -0
  56. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/config_command.py +0 -0
  57. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/dependency_container.py +0 -0
  58. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/dependency_manager.py +0 -0
  59. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/echo_command.py +0 -0
  60. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/health_command.py +0 -0
  61. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/help_command.py +0 -0
  62. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/hooks.py +0 -0
  63. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/key_management_command.py +0 -0
  64. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/load_command.py +0 -0
  65. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/plugins_command.py +0 -0
  66. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/protocol_management_command.py +0 -0
  67. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/proxy_registration_command.py +0 -0
  68. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/registration_status_command.py +0 -0
  69. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/reload_command.py +0 -0
  70. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/result.py +0 -0
  71. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/role_test_command.py +0 -0
  72. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/roles_management_command.py +0 -0
  73. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/security_command.py +0 -0
  74. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/settings_command.py +0 -0
  75. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/ssl_setup_command.py +0 -0
  76. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/token_management_command.py +0 -0
  77. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/transport_management_command.py +0 -0
  78. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/commands/unload_command.py +0 -0
  79. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/__init__.py +0 -0
  80. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/app_factory.py +0 -0
  81. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/app_runner.py +0 -0
  82. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/auth_validator.py +0 -0
  83. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/certificate_utils.py +0 -0
  84. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/client.py +0 -0
  85. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/client_manager.py +0 -0
  86. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/client_security.py +0 -0
  87. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/config_converter.py +0 -0
  88. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/crl_utils.py +0 -0
  89. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/mtls_asgi.py +0 -0
  90. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/mtls_asgi_app.py +0 -0
  91. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/mtls_proxy.py +0 -0
  92. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/mtls_server.py +0 -0
  93. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/protocol_manager.py +0 -0
  94. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/proxy_client.py +0 -0
  95. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/proxy_registration.py +0 -0
  96. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/role_utils.py +0 -0
  97. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/security_adapter.py +0 -0
  98. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/security_factory.py +0 -0
  99. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/security_integration.py +0 -0
  100. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/server_adapter.py +0 -0
  101. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/server_engine.py +0 -0
  102. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/settings.py +0 -0
  103. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/signal_handler.py +0 -0
  104. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/ssl_utils.py +0 -0
  105. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/transport_manager.py +0 -0
  106. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/unified_config_adapter.py +0 -0
  107. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/core/utils.py +0 -0
  108. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/custom_openapi.py +0 -0
  109. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/__init__.py +0 -0
  110. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/basic_framework/__init__.py +0 -0
  111. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +0 -0
  112. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +0 -0
  113. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/basic_framework/main.py +0 -0
  114. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/bugfix_certificate_config.py +0 -0
  115. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/cert_manager_bugfix.py +0 -0
  116. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/check_config.py +0 -0
  117. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/commands/__init__.py +0 -0
  118. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/config_cli.py +0 -0
  119. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/create_test_configs.py +0 -0
  120. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/debug_request_state.py +0 -0
  121. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/debug_role_chain.py +0 -0
  122. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/demo_client.py +0 -0
  123. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/full_application/__init__.py +0 -0
  124. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/full_application/commands/__init__.py +0 -0
  125. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +0 -0
  126. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +0 -0
  127. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/full_application/hooks/__init__.py +0 -0
  128. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +0 -0
  129. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +0 -0
  130. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +0 -0
  131. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/proxy_registration_example.py +0 -0
  132. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/required_certificates.py +0 -0
  133. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/run_example.py +0 -0
  134. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/run_full_test_suite.py +0 -0
  135. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/run_proxy_server.py +0 -0
  136. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/run_security_tests_fixed.py +0 -0
  137. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/security_test_client.py +0 -0
  138. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/setup_test_environment.py +0 -0
  139. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/simple_protocol_test.py +0 -0
  140. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/test_chk_hostname_automated.py +0 -0
  141. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/test_config_builder.py +0 -0
  142. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/test_examples.py +0 -0
  143. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/test_framework_complete.py +0 -0
  144. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/test_mcp_server.py +0 -0
  145. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/test_protocol_examples.py +0 -0
  146. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/universal_client.py +0 -0
  147. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/examples/update_config_certificates.py +0 -0
  148. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/main.py +0 -0
  149. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/openapi.py +0 -0
  150. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/schemas/base_schema.json +0 -0
  151. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/schemas/openapi_schema.json +0 -0
  152. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/schemas/roles.json +0 -0
  153. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter/schemas/roles_schema.json +0 -0
  154. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter.egg-info/dependency_links.txt +0 -0
  155. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter.egg-info/entry_points.txt +0 -0
  156. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter.egg-info/not-zip-safe +0 -0
  157. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter.egg-info/requires.txt +0 -0
  158. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/mcp_proxy_adapter.egg-info/top_level.txt +0 -0
  159. {mcp_proxy_adapter-6.8.2 → mcp_proxy_adapter-6.9.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-proxy-adapter
3
- Version: 6.8.2
3
+ Version: 6.9.1
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
@@ -12,6 +12,17 @@ from typing import Any, Dict, Optional, List
12
12
 
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
+ # Import validation if available
16
+ try:
17
+ from .core.config_validator import ConfigValidator, ValidationResult, ValidationLevel
18
+ VALIDATION_AVAILABLE = True
19
+ except ImportError:
20
+ VALIDATION_AVAILABLE = False
21
+ logger.warning("Configuration validation not available. Install the package to enable validation.")
22
+
23
+ # Import configuration errors
24
+ from .core.errors import ConfigError, ValidationResult
25
+
15
26
 
16
27
  class Config:
17
28
  """
@@ -20,113 +31,64 @@ class Config:
20
31
  Supports optional features that can be enabled/disabled.
21
32
  """
22
33
 
23
- def __init__(self, config_path: Optional[str] = None):
34
+ def __init__(self, config_path: Optional[str] = None, validate_on_load: bool = True):
24
35
  """
25
36
  Initialize configuration.
26
37
 
27
38
  Args:
28
39
  config_path: Path to configuration file. If not specified,
29
40
  "./config.json" is used.
41
+ validate_on_load: Whether to validate configuration on load (default: True)
42
+
43
+ Raises:
44
+ ConfigError: If configuration validation fails
30
45
  """
31
46
  self.config_path = config_path or "./config.json"
32
47
  self.config_data: Dict[str, Any] = {}
48
+ self.validate_on_load = validate_on_load
49
+ self.validation_results: List[ValidationResult] = []
50
+ self.validator = None
51
+
52
+ if VALIDATION_AVAILABLE:
53
+ self.validator = ConfigValidator()
54
+
33
55
  self.load_config()
34
56
 
35
57
  def load_config(self) -> None:
36
58
  """
37
59
  Load configuration from file and environment variables.
60
+ NO DEFAULT VALUES - configuration must be complete and valid.
38
61
  """
39
- # Set default config values
40
- self.config_data = {
41
- "server": {
42
- "host": "0.0.0.0",
43
- "port": 8000,
44
- "protocol": "http",
45
- "debug": False,
46
- "log_level": "INFO",
47
- },
48
- "logging": {
49
- "level": "INFO",
50
- "file": None,
51
- "log_dir": "./logs",
52
- "log_file": "mcp_proxy_adapter.log",
53
- "error_log_file": "mcp_proxy_adapter_error.log",
54
- "access_log_file": "mcp_proxy_adapter_access.log",
55
- "max_file_size": "10MB",
56
- "backup_count": 5,
57
- "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
58
- "date_format": "%Y-%m-%d %H:%M:%S",
59
- "console_output": True,
60
- "file_output": True,
61
- },
62
- "commands": {
63
- "auto_discovery": True,
64
- "commands_directory": "./commands",
65
- "catalog_directory": "./catalog",
66
- "plugin_servers": [],
67
- "auto_install_dependencies": True,
68
- "enabled_commands": ["health", "echo", "list", "help"],
69
- "disabled_commands": [],
70
- "custom_commands_path": "./commands",
71
- },
72
- "roles": {
73
- "enabled": False,
74
- "config_file": None,
75
- "default_policy": {
76
- "deny_by_default": False,
77
- "require_role_match": False,
78
- "case_sensitive": False,
79
- "allow_wildcard": False,
80
- },
81
- "auto_load": False,
82
- "validation_enabled": False,
83
- },
84
- "transport": {
85
- "type": "http",
86
- "port": None,
87
- "verify_client": False,
88
- "chk_hostname": False, # Default to False for HTTP
89
- },
90
- "proxy_registration": {
91
- "enabled": False,
92
- "proxy_url": "http://localhost:3004",
93
- "server_id": "mcp_proxy_adapter",
94
- "server_name": "MCP Proxy Adapter",
95
- "description": "JSON-RPC API for interacting with MCP Proxy",
96
- "version": "6.2.33",
97
- "registration_timeout": 30,
98
- "retry_attempts": 3,
99
- "retry_delay": 5,
100
- "auto_register_on_startup": True,
101
- "auto_unregister_on_shutdown": True,
102
- },
103
- "debug": {"enabled": False, "level": "WARNING"},
104
- "security": {
105
- "enabled": False,
106
- "tokens": {
107
- "admin": "admin-secret-key",
108
- "user": "user-secret-key",
109
- "readonly": "readonly-secret-key"
110
- },
111
- "roles": {
112
- "admin": ["read", "write", "delete", "admin"],
113
- "user": ["read", "write"],
114
- "readonly": ["read"]
115
- },
116
- "roles_file": None
117
- },
118
- }
119
-
120
- # Try to load configuration from file
121
- if os.path.exists(self.config_path):
122
- try:
62
+ # Load configuration from file - NO DEFAULTS
63
+ if not os.path.exists(self.config_path):
64
+ raise ConfigError(f"Configuration file '{self.config_path}' does not exist. Use the configuration generator to create a valid configuration.")
65
+
66
+ try:
123
67
  with open(self.config_path, "r", encoding="utf-8") as f:
124
- file_config = json.load(f)
125
- self._update_nested_dict(self.config_data, file_config)
126
- except Exception as e:
127
- print(f"Error loading config from {self.config_path}: {e}")
128
-
129
- # Load configuration from environment variables
68
+ self.config_data = json.load(f)
69
+ except json.JSONDecodeError as e:
70
+ raise ConfigError(f"Configuration file '{self.config_path}' contains invalid JSON: {e}")
71
+ except Exception as e:
72
+ raise ConfigError(f"Error loading configuration from '{self.config_path}': {e}")
73
+
74
+ # Validate configuration BEFORE applying any logic
75
+ if self.validate_on_load:
76
+ if VALIDATION_AVAILABLE and self.validator:
77
+ self.validator.config_data = self.config_data
78
+ validation_results = self.validator.validate_config()
79
+
80
+ # Check for critical errors
81
+ errors = [r for r in validation_results if r.level == "error"]
82
+ if errors:
83
+ error_summary = "\n".join([f"[{r.section}.{r.key if r.key else 'root'}] {r.message}" for r in errors])
84
+ raise ConfigError(f"Configuration validation failed with {len(errors)} error(s):\n{error_summary}", errors)
85
+
86
+ # Store validation results for later access
87
+ self.validation_results = validation_results
88
+ else:
89
+ raise ConfigError("Configuration validation is not available. Install required dependencies.")
90
+
91
+ # Load configuration from environment variables (overrides file values)
130
92
  self._load_env_variables()
131
93
 
132
94
  # Apply hostname check logic based on SSL configuration
@@ -257,23 +219,6 @@ class Config:
257
219
  with open(save_path, "w", encoding="utf-8") as f:
258
220
  json.dump(self.config_data, f, indent=2)
259
221
 
260
- def _update_nested_dict(self, d: Dict, u: Dict) -> Dict:
261
- """
262
- Update nested dictionary recursively.
263
-
264
- Args:
265
- d: Dictionary to update
266
- u: Dictionary with new values
267
-
268
- Returns:
269
- Updated dictionary
270
- """
271
- for k, v in u.items():
272
- if isinstance(v, dict) and k in d and isinstance(d[k], dict):
273
- self._update_nested_dict(d[k], v)
274
- else:
275
- d[k] = v
276
- return d
277
222
 
278
223
  def enable_feature(self, feature: str) -> None:
279
224
  """
@@ -540,6 +485,159 @@ class Config:
540
485
  chk_hostname_value = self.get("transport.ssl.chk_hostname")
541
486
  logger.debug(f"Using explicitly set chk_hostname={chk_hostname_value} for protocol {protocol}")
542
487
 
488
+ def validate(self) -> List[ValidationResult]:
489
+ """
490
+ Validate current configuration.
491
+
492
+ Returns:
493
+ List of validation results
494
+
495
+ Raises:
496
+ ConfigError: If validation is not available or critical errors are found
497
+ """
498
+ if not VALIDATION_AVAILABLE:
499
+ raise ConfigError("Configuration validation is not available. Please install the package properly.")
500
+
501
+ if not self.validator:
502
+ self.validator = ConfigValidator()
503
+
504
+ self.validator.config_data = self.config_data
505
+ self.validation_results = self.validator.validate_config()
506
+
507
+ # Log validation results
508
+ for result in self.validation_results:
509
+ if result.level == ValidationLevel.ERROR:
510
+ logger.error(f"Configuration error: {result.message}")
511
+ elif result.level == ValidationLevel.WARNING:
512
+ logger.warning(f"Configuration warning: {result.message}")
513
+ else:
514
+ logger.info(f"Configuration info: {result.message}")
515
+
516
+ # Raise ConfigError if there are critical errors
517
+ errors = [r for r in self.validation_results if r.level == ValidationLevel.ERROR]
518
+ if errors:
519
+ error_summary = "\n".join([f"[{r.section}.{r.key if r.key else 'root'}] {r.message}" for r in errors])
520
+ raise ConfigError(f"Configuration validation failed with {len(errors)} error(s):\n{error_summary}", errors)
521
+
522
+ return self.validation_results
523
+
524
+ def is_valid(self) -> bool:
525
+ """Check if configuration is valid."""
526
+ if not VALIDATION_AVAILABLE:
527
+ return True
528
+
529
+ return all(result.level != ValidationLevel.ERROR for result in self.validation_results)
530
+
531
+ def get_validation_errors(self) -> List[ValidationResult]:
532
+ """Get all validation errors."""
533
+ return [r for r in self.validation_results if r.level == ValidationLevel.ERROR]
534
+
535
+ def get_validation_warnings(self) -> List[ValidationResult]:
536
+ """Get all validation warnings."""
537
+ return [r for r in self.validation_results if r.level == ValidationLevel.WARNING]
538
+
539
+ def get_validation_summary(self) -> Dict[str, Any]:
540
+ """Get validation summary."""
541
+ if not VALIDATION_AVAILABLE or not self.validator:
542
+ return {"total_issues": 0, "errors": 0, "warnings": 0, "info": 0, "is_valid": True}
543
+
544
+ return self.validator.get_validation_summary()
545
+
546
+ def print_validation_report(self) -> None:
547
+ """Print detailed validation report."""
548
+ if not VALIDATION_AVAILABLE or not self.validator:
549
+ print("Configuration validation not available")
550
+ return
551
+
552
+ self.validator.print_validation_report()
553
+
554
+ def check_feature_requirements(self, feature: str) -> List[ValidationResult]:
555
+ """Check if all requirements for a feature are met."""
556
+ if not VALIDATION_AVAILABLE:
557
+ return []
558
+
559
+ results = []
560
+
561
+ if feature == "security":
562
+ if self.get("security.enabled", False):
563
+ tokens = self.get("security.tokens", {})
564
+ roles = self.get("security.roles", {})
565
+ roles_file = self.get("security.roles_file")
566
+
567
+ has_tokens = bool(tokens and any(tokens.values()))
568
+ has_roles = bool(roles and any(roles.values()))
569
+ has_roles_file = bool(roles_file and os.path.exists(roles_file))
570
+
571
+ if not (has_tokens or has_roles or has_roles_file):
572
+ results.append(ValidationResult(
573
+ level=ValidationLevel.WARNING,
574
+ message="Security is enabled but no authentication methods are configured",
575
+ section="security",
576
+ suggestion="Configure tokens, roles, or roles_file"
577
+ ))
578
+
579
+ elif feature == "roles":
580
+ if self.get("roles.enabled", False):
581
+ config_file = self.get("roles.config_file")
582
+ if not config_file:
583
+ results.append(ValidationResult(
584
+ level=ValidationLevel.ERROR,
585
+ message="Roles are enabled but config_file is not specified",
586
+ section="roles",
587
+ key="config_file"
588
+ ))
589
+ elif not os.path.exists(config_file):
590
+ results.append(ValidationResult(
591
+ level=ValidationLevel.ERROR,
592
+ message=f"Roles config file '{config_file}' does not exist",
593
+ section="roles",
594
+ key="config_file"
595
+ ))
596
+
597
+ elif feature == "ssl":
598
+ if self.get("ssl.enabled", False):
599
+ cert_file = self.get("ssl.cert_file")
600
+ key_file = self.get("ssl.key_file")
601
+
602
+ if not cert_file:
603
+ results.append(ValidationResult(
604
+ level=ValidationLevel.ERROR,
605
+ message="SSL is enabled but cert_file is not specified",
606
+ section="ssl",
607
+ key="cert_file"
608
+ ))
609
+ elif not os.path.exists(cert_file):
610
+ results.append(ValidationResult(
611
+ level=ValidationLevel.ERROR,
612
+ message=f"SSL certificate file '{cert_file}' does not exist",
613
+ section="ssl",
614
+ key="cert_file"
615
+ ))
616
+
617
+ if not key_file:
618
+ results.append(ValidationResult(
619
+ level=ValidationLevel.ERROR,
620
+ message="SSL is enabled but key_file is not specified",
621
+ section="ssl",
622
+ key="key_file"
623
+ ))
624
+ elif not os.path.exists(key_file):
625
+ results.append(ValidationResult(
626
+ level=ValidationLevel.ERROR,
627
+ message=f"SSL key file '{key_file}' does not exist",
628
+ section="ssl",
629
+ key="key_file"
630
+ ))
631
+
632
+ return results
633
+
634
+
635
+ # Singleton instance - will be created when needed
636
+ config = None
543
637
 
544
- # Singleton instance
545
- config = Config()
638
+ def get_config() -> Config:
639
+ """Get the global configuration instance."""
640
+ global config
641
+ if config is None:
642
+ config = Config()
643
+ return config