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

Files changed (269) hide show
  1. mcp_proxy_adapter/__init__.py +47 -0
  2. mcp_proxy_adapter/__main__.py +13 -0
  3. mcp_proxy_adapter/api/__init__.py +0 -0
  4. mcp_proxy_adapter/api/app.py +66 -0
  5. mcp_proxy_adapter/api/core/__init__.py +18 -0
  6. mcp_proxy_adapter/api/core/app_factory.py +400 -0
  7. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  8. mcp_proxy_adapter/api/core/registration_context.py +356 -0
  9. mcp_proxy_adapter/api/core/registration_manager.py +307 -0
  10. mcp_proxy_adapter/api/core/registration_tasks.py +84 -0
  11. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  12. mcp_proxy_adapter/api/handlers.py +181 -0
  13. mcp_proxy_adapter/api/middleware/__init__.py +21 -0
  14. mcp_proxy_adapter/api/middleware/base.py +54 -0
  15. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +73 -0
  16. mcp_proxy_adapter/api/middleware/error_handling.py +76 -0
  17. mcp_proxy_adapter/api/middleware/factory.py +147 -0
  18. mcp_proxy_adapter/api/middleware/logging.py +31 -0
  19. mcp_proxy_adapter/api/middleware/performance.py +51 -0
  20. mcp_proxy_adapter/api/middleware/protocol_middleware.py +140 -0
  21. mcp_proxy_adapter/api/middleware/transport_middleware.py +87 -0
  22. mcp_proxy_adapter/api/middleware/unified_security.py +223 -0
  23. mcp_proxy_adapter/api/middleware/user_info_middleware.py +132 -0
  24. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  25. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  26. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  27. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  28. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  29. mcp_proxy_adapter/api/schemas.py +270 -0
  30. mcp_proxy_adapter/api/tool_integration.py +131 -0
  31. mcp_proxy_adapter/api/tools.py +163 -0
  32. mcp_proxy_adapter/cli/__init__.py +12 -0
  33. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  34. mcp_proxy_adapter/cli/commands/client.py +100 -0
  35. mcp_proxy_adapter/cli/commands/config_generate.py +105 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +94 -0
  37. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  38. mcp_proxy_adapter/cli/commands/server.py +174 -0
  39. mcp_proxy_adapter/cli/commands/sets.py +132 -0
  40. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  41. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  42. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  43. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  44. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  45. mcp_proxy_adapter/cli/main.py +63 -0
  46. mcp_proxy_adapter/cli/parser.py +338 -0
  47. mcp_proxy_adapter/cli/validators.py +231 -0
  48. mcp_proxy_adapter/client/jsonrpc_client/__init__.py +9 -0
  49. mcp_proxy_adapter/client/jsonrpc_client/client.py +42 -0
  50. mcp_proxy_adapter/client/jsonrpc_client/command_api.py +45 -0
  51. mcp_proxy_adapter/client/jsonrpc_client/proxy_api.py +224 -0
  52. mcp_proxy_adapter/client/jsonrpc_client/queue_api.py +60 -0
  53. mcp_proxy_adapter/client/jsonrpc_client/transport.py +108 -0
  54. mcp_proxy_adapter/client/proxy.py +123 -0
  55. mcp_proxy_adapter/commands/__init__.py +66 -0
  56. mcp_proxy_adapter/commands/auth_validation_command.py +69 -0
  57. mcp_proxy_adapter/commands/base.py +389 -0
  58. mcp_proxy_adapter/commands/builtin_commands.py +30 -0
  59. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  60. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  61. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  62. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  63. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  64. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  65. mcp_proxy_adapter/commands/catalog_manager.py +97 -0
  66. mcp_proxy_adapter/commands/cert_monitor_command.py +552 -0
  67. mcp_proxy_adapter/commands/certificate_management_command.py +562 -0
  68. mcp_proxy_adapter/commands/command_registry.py +298 -0
  69. mcp_proxy_adapter/commands/config_command.py +102 -0
  70. mcp_proxy_adapter/commands/dependency_container.py +40 -0
  71. mcp_proxy_adapter/commands/dependency_manager.py +143 -0
  72. mcp_proxy_adapter/commands/echo_command.py +48 -0
  73. mcp_proxy_adapter/commands/health_command.py +142 -0
  74. mcp_proxy_adapter/commands/help_command.py +175 -0
  75. mcp_proxy_adapter/commands/hooks.py +172 -0
  76. mcp_proxy_adapter/commands/key_management_command.py +484 -0
  77. mcp_proxy_adapter/commands/load_command.py +123 -0
  78. mcp_proxy_adapter/commands/plugins_command.py +246 -0
  79. mcp_proxy_adapter/commands/protocol_management_command.py +216 -0
  80. mcp_proxy_adapter/commands/proxy_registration_command.py +319 -0
  81. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  82. mcp_proxy_adapter/commands/registration_status_command.py +76 -0
  83. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  84. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  85. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  86. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  87. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  88. mcp_proxy_adapter/commands/reload_command.py +136 -0
  89. mcp_proxy_adapter/commands/result.py +157 -0
  90. mcp_proxy_adapter/commands/role_test_command.py +99 -0
  91. mcp_proxy_adapter/commands/roles_management_command.py +502 -0
  92. mcp_proxy_adapter/commands/security_command.py +472 -0
  93. mcp_proxy_adapter/commands/settings_command.py +113 -0
  94. mcp_proxy_adapter/commands/ssl_setup_command.py +306 -0
  95. mcp_proxy_adapter/commands/token_management_command.py +500 -0
  96. mcp_proxy_adapter/commands/transport_management_command.py +129 -0
  97. mcp_proxy_adapter/commands/unload_command.py +92 -0
  98. mcp_proxy_adapter/config.py +32 -0
  99. mcp_proxy_adapter/core/__init__.py +8 -0
  100. mcp_proxy_adapter/core/app_factory.py +560 -0
  101. mcp_proxy_adapter/core/app_runner.py +318 -0
  102. mcp_proxy_adapter/core/auth_validator.py +508 -0
  103. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  104. mcp_proxy_adapter/core/certificate/certificate_creator.py +372 -0
  105. mcp_proxy_adapter/core/certificate/certificate_extractor.py +185 -0
  106. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  107. mcp_proxy_adapter/core/certificate/certificate_validator.py +481 -0
  108. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +65 -0
  109. mcp_proxy_adapter/core/certificate_utils.py +249 -0
  110. mcp_proxy_adapter/core/client.py +608 -0
  111. mcp_proxy_adapter/core/client_manager.py +271 -0
  112. mcp_proxy_adapter/core/client_security.py +411 -0
  113. mcp_proxy_adapter/core/config/__init__.py +18 -0
  114. mcp_proxy_adapter/core/config/config.py +237 -0
  115. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  116. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  117. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  118. mcp_proxy_adapter/core/config/simple_config.py +204 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +131 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +476 -0
  121. mcp_proxy_adapter/core/config_converter.py +252 -0
  122. mcp_proxy_adapter/core/config_validator.py +211 -0
  123. mcp_proxy_adapter/core/crl_utils.py +362 -0
  124. mcp_proxy_adapter/core/errors.py +276 -0
  125. mcp_proxy_adapter/core/job_manager.py +54 -0
  126. mcp_proxy_adapter/core/logging.py +250 -0
  127. mcp_proxy_adapter/core/mtls_asgi.py +140 -0
  128. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  129. mcp_proxy_adapter/core/mtls_proxy.py +229 -0
  130. mcp_proxy_adapter/core/mtls_server.py +154 -0
  131. mcp_proxy_adapter/core/protocol_manager.py +232 -0
  132. mcp_proxy_adapter/core/proxy/__init__.py +19 -0
  133. mcp_proxy_adapter/core/proxy/auth_manager.py +26 -0
  134. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +160 -0
  135. mcp_proxy_adapter/core/proxy/registration_client.py +186 -0
  136. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  137. mcp_proxy_adapter/core/proxy_client.py +184 -0
  138. mcp_proxy_adapter/core/proxy_registration.py +80 -0
  139. mcp_proxy_adapter/core/role_utils.py +103 -0
  140. mcp_proxy_adapter/core/security_adapter.py +343 -0
  141. mcp_proxy_adapter/core/security_factory.py +96 -0
  142. mcp_proxy_adapter/core/security_integration.py +342 -0
  143. mcp_proxy_adapter/core/server_adapter.py +251 -0
  144. mcp_proxy_adapter/core/server_engine.py +217 -0
  145. mcp_proxy_adapter/core/settings.py +260 -0
  146. mcp_proxy_adapter/core/signal_handler.py +107 -0
  147. mcp_proxy_adapter/core/ssl_utils.py +161 -0
  148. mcp_proxy_adapter/core/transport_manager.py +153 -0
  149. mcp_proxy_adapter/core/unified_config_adapter.py +471 -0
  150. mcp_proxy_adapter/core/utils.py +101 -0
  151. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  152. mcp_proxy_adapter/core/validation/config_validator.py +219 -0
  153. mcp_proxy_adapter/core/validation/file_validator.py +131 -0
  154. mcp_proxy_adapter/core/validation/protocol_validator.py +205 -0
  155. mcp_proxy_adapter/core/validation/security_validator.py +140 -0
  156. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  157. mcp_proxy_adapter/custom_openapi.py +58 -0
  158. mcp_proxy_adapter/examples/__init__.py +16 -0
  159. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  160. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  161. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  162. mcp_proxy_adapter/examples/basic_framework/main.py +52 -0
  163. mcp_proxy_adapter/examples/bugfix_certificate_config.py +261 -0
  164. mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
  165. mcp_proxy_adapter/examples/check_config.py +413 -0
  166. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  167. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  168. mcp_proxy_adapter/examples/config_builder.py +234 -0
  169. mcp_proxy_adapter/examples/config_cli.py +282 -0
  170. mcp_proxy_adapter/examples/create_test_configs.py +174 -0
  171. mcp_proxy_adapter/examples/debug_request_state.py +130 -0
  172. mcp_proxy_adapter/examples/debug_role_chain.py +191 -0
  173. mcp_proxy_adapter/examples/demo_client.py +287 -0
  174. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  175. mcp_proxy_adapter/examples/full_application/commands/__init__.py +8 -0
  176. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +45 -0
  177. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +52 -0
  178. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +32 -0
  179. mcp_proxy_adapter/examples/full_application/commands/help_command.py +54 -0
  180. mcp_proxy_adapter/examples/full_application/commands/list_command.py +57 -0
  181. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +5 -0
  182. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +29 -0
  183. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +27 -0
  184. mcp_proxy_adapter/examples/full_application/main.py +311 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +161 -0
  186. mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
  187. mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
  188. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +45 -0
  189. mcp_proxy_adapter/examples/full_application/test_server.py +163 -0
  190. mcp_proxy_adapter/examples/full_application/test_simple_server.py +62 -0
  191. mcp_proxy_adapter/examples/generate_config.py +502 -0
  192. mcp_proxy_adapter/examples/proxy_registration_example.py +335 -0
  193. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  194. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  195. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  196. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  197. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  198. mcp_proxy_adapter/examples/required_certificates.py +208 -0
  199. mcp_proxy_adapter/examples/run_example.py +77 -0
  200. mcp_proxy_adapter/examples/run_full_test_suite.py +619 -0
  201. mcp_proxy_adapter/examples/run_proxy_server.py +153 -0
  202. mcp_proxy_adapter/examples/run_security_tests_fixed.py +435 -0
  203. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  204. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  205. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  206. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  207. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  208. mcp_proxy_adapter/examples/security_test_client.py +72 -0
  209. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  210. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  211. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  212. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  213. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  214. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  215. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  216. mcp_proxy_adapter/examples/setup_test_environment.py +235 -0
  217. mcp_proxy_adapter/examples/simple_protocol_test.py +125 -0
  218. mcp_proxy_adapter/examples/test_chk_hostname_automated.py +211 -0
  219. mcp_proxy_adapter/examples/test_config.py +205 -0
  220. mcp_proxy_adapter/examples/test_config_builder.py +110 -0
  221. mcp_proxy_adapter/examples/test_examples.py +308 -0
  222. mcp_proxy_adapter/examples/test_framework_complete.py +267 -0
  223. mcp_proxy_adapter/examples/test_mcp_server.py +187 -0
  224. mcp_proxy_adapter/examples/test_protocol_examples.py +337 -0
  225. mcp_proxy_adapter/examples/universal_client.py +674 -0
  226. mcp_proxy_adapter/examples/update_config_certificates.py +135 -0
  227. mcp_proxy_adapter/examples/validate_generator_compatibility.py +385 -0
  228. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +61 -0
  229. mcp_proxy_adapter/integrations/__init__.py +25 -0
  230. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  231. mcp_proxy_adapter/main.py +311 -0
  232. mcp_proxy_adapter/openapi.py +375 -0
  233. mcp_proxy_adapter/schemas/base_schema.json +114 -0
  234. mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
  235. mcp_proxy_adapter/schemas/roles.json +37 -0
  236. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  237. mcp_proxy_adapter/version.py +5 -0
  238. mcp_proxy_adapter-6.9.50.dist-info/METADATA +1088 -0
  239. mcp_proxy_adapter-6.9.50.dist-info/RECORD +242 -0
  240. {mcp_proxy_adapter-2.0.1.dist-info → mcp_proxy_adapter-6.9.50.dist-info}/WHEEL +1 -1
  241. mcp_proxy_adapter-6.9.50.dist-info/entry_points.txt +14 -0
  242. mcp_proxy_adapter-6.9.50.dist-info/top_level.txt +1 -0
  243. adapters/__init__.py +0 -16
  244. analyzers/__init__.py +0 -14
  245. analyzers/docstring_analyzer.py +0 -199
  246. analyzers/type_analyzer.py +0 -151
  247. cli/__init__.py +0 -12
  248. cli/__main__.py +0 -79
  249. cli/command_runner.py +0 -233
  250. dispatchers/__init__.py +0 -14
  251. dispatchers/base_dispatcher.py +0 -85
  252. dispatchers/json_rpc_dispatcher.py +0 -198
  253. generators/__init__.py +0 -14
  254. generators/endpoint_generator.py +0 -172
  255. generators/openapi_generator.py +0 -254
  256. generators/rest_api_generator.py +0 -207
  257. mcp_proxy_adapter-2.0.1.dist-info/METADATA +0 -272
  258. mcp_proxy_adapter-2.0.1.dist-info/RECORD +0 -28
  259. mcp_proxy_adapter-2.0.1.dist-info/licenses/LICENSE +0 -21
  260. mcp_proxy_adapter-2.0.1.dist-info/top_level.txt +0 -7
  261. openapi_schema/__init__.py +0 -38
  262. openapi_schema/command_registry.py +0 -312
  263. openapi_schema/rest_schema.py +0 -510
  264. openapi_schema/rpc_generator.py +0 -307
  265. openapi_schema/rpc_schema.py +0 -416
  266. validators/__init__.py +0 -14
  267. validators/base_validator.py +0 -23
  268. validators/docstring_validator.py +0 -75
  269. validators/metadata_validator.py +0 -76
@@ -0,0 +1,237 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Main configuration class for MCP Proxy Adapter.
6
+ """
7
+
8
+ from typing import Any, Dict, Optional, List
9
+ from pathlib import Path
10
+
11
+ from mcp_proxy_adapter.core.logging import get_global_logger
12
+ from .config_loader import ConfigLoader
13
+ from .feature_manager import FeatureManager
14
+ from .config_factory import ConfigFactory
15
+
16
+ # Import validation if available
17
+ try:
18
+ VALIDATION_AVAILABLE = True
19
+ except ImportError:
20
+ VALIDATION_AVAILABLE = False
21
+
22
+ # Import configuration errors
23
+ from ..errors import ConfigError, ValidationResult
24
+
25
+
26
+ class Config:
27
+ """
28
+ Configuration management class for the microservice.
29
+ Allows loading settings from configuration file and environment variables.
30
+ Supports optional features that can be enabled/disabled.
31
+ """
32
+
33
+ def __init__(
34
+ self, config_path: Optional[str] = None, validate_on_load: bool = False
35
+ ):
36
+ """
37
+ Initialize configuration.
38
+
39
+ Args:
40
+ config_path: Path to configuration file. If not specified,
41
+ "./config.json" is used.
42
+ validate_on_load: Whether to validate configuration on load (default: False)
43
+
44
+ Raises:
45
+ ConfigError: If configuration validation fails
46
+ """
47
+ self.config_path = config_path or "./config.json"
48
+ self.config_data: Dict[str, Any] = {}
49
+ self.validate_on_load = validate_on_load
50
+ self.validation_results: List[ValidationResult] = []
51
+ self.validator = None
52
+
53
+ # Initialize components
54
+ self.logger = get_global_logger()
55
+ self.loader = ConfigLoader()
56
+ self.feature_manager = FeatureManager(self.config_data)
57
+ self.factory = ConfigFactory()
58
+
59
+ # Load configuration
60
+ self.load_config()
61
+
62
+ def load_config(self) -> None:
63
+ """Load configuration from file and environment variables."""
64
+ try:
65
+ # Load from file if it exists
66
+ if Path(self.config_path).exists():
67
+ file_config = self.loader.load_from_file(self.config_path)
68
+ self.config_data.update(file_config)
69
+
70
+ # Load from environment variables
71
+ try:
72
+ env_config = self.loader.load_from_env()
73
+ self._merge_config(env_config)
74
+ except AttributeError:
75
+ # load_from_env doesn't exist yet, skip
76
+ pass
77
+
78
+ # Validate if required
79
+ if self.validate_on_load and VALIDATION_AVAILABLE:
80
+ self.validate()
81
+
82
+ except Exception as e:
83
+ self.logger.error(f"Failed to load configuration: {e}")
84
+ raise ConfigError(f"Configuration loading failed: {e}")
85
+
86
+ def _merge_config(self, new_config: Dict[str, Any]) -> None:
87
+ """
88
+ Merge new configuration into existing configuration.
89
+
90
+ Args:
91
+ new_config: New configuration to merge
92
+ """
93
+ for section, values in new_config.items():
94
+ if section in self.config_data:
95
+ if isinstance(self.config_data[section], dict) and isinstance(
96
+ values, dict
97
+ ):
98
+ self.config_data[section].update(values)
99
+ else:
100
+ self.config_data[section] = values
101
+ else:
102
+ self.config_data[section] = values
103
+
104
+ def enable_feature(self, feature: str) -> None:
105
+ """
106
+ Enable a feature.
107
+
108
+ Args:
109
+ feature: Feature name
110
+ """
111
+ self.feature_manager.enable_feature(feature)
112
+
113
+ def disable_feature(self, feature: str) -> None:
114
+ """
115
+ Disable a feature.
116
+
117
+ Args:
118
+ feature: Feature name
119
+ """
120
+ self.feature_manager.disable_feature(feature)
121
+
122
+ def is_feature_enabled(self, feature: str) -> bool:
123
+ """
124
+ Check if feature is enabled.
125
+
126
+ Args:
127
+ feature: Feature name
128
+
129
+ Returns:
130
+ True if enabled, False otherwise
131
+ """
132
+ return self.feature_manager.is_feature_enabled(feature)
133
+
134
+ def get_enabled_features(self) -> List[str]:
135
+ """
136
+ Get list of enabled features.
137
+
138
+ Returns:
139
+ List of enabled feature names
140
+ """
141
+ return self.feature_manager.get_enabled_features()
142
+
143
+ def validate(self) -> List[ValidationResult]:
144
+ """
145
+ Validate configuration.
146
+
147
+ Returns:
148
+ List of validation results
149
+ """
150
+ if not VALIDATION_AVAILABLE:
151
+ self.logger.warning("Configuration validation not available")
152
+ return []
153
+
154
+ try:
155
+ from ..config_validator import ConfigValidator
156
+
157
+ self.validator = ConfigValidator()
158
+ self.validator.config_data = self.config_data
159
+ self.validation_results = self.validator.validate_config()
160
+ return self.validation_results
161
+ except Exception as e:
162
+ self.logger.error(f"Configuration validation failed: {e}")
163
+ return []
164
+
165
+ def get_validation_errors(self) -> List[ValidationResult]:
166
+ """Get validation errors."""
167
+ return [result for result in self.validation_results if result.level == "error"]
168
+
169
+ def get_validation_warnings(self) -> List[ValidationResult]:
170
+ """Get validation warnings."""
171
+ return [
172
+ result for result in self.validation_results if result.level == "warning"
173
+ ]
174
+
175
+ def get_validation_summary(self) -> Dict[str, Any]:
176
+ """Get validation summary."""
177
+ errors = self.get_validation_errors()
178
+ warnings = self.get_validation_warnings()
179
+
180
+ return {
181
+ "total": len(self.validation_results),
182
+ "errors": len(errors),
183
+ "warnings": len(warnings),
184
+ "is_valid": len(errors) == 0,
185
+ }
186
+
187
+ def check_feature_requirements(self, feature: str) -> List[ValidationResult]:
188
+ """
189
+ Check feature requirements.
190
+
191
+ Args:
192
+ feature: Feature name
193
+
194
+ Returns:
195
+ List of validation results
196
+ """
197
+ return self.feature_manager.check_feature_requirements(feature)
198
+
199
+ def get(self, key: str, default: Any = None) -> Any:
200
+ """
201
+ Get configuration value using dot notation.
202
+
203
+ Supports nested dictionary access using dot notation.
204
+ For example: "transport.cert_file" will access config_data["transport"]["cert_file"]
205
+
206
+ Args:
207
+ key: Configuration key, can use dot notation (e.g., "transport.cert_file")
208
+ default: Default value if key not found
209
+
210
+ Returns:
211
+ Configuration value or default
212
+
213
+ Examples:
214
+ >>> config.get("server.host", "0.0.0.0")
215
+ >>> config.get("transport.ssl.cert_file")
216
+ """
217
+ keys = key.split(".")
218
+ value = self.config_data
219
+
220
+ for k in keys:
221
+ if isinstance(value, dict):
222
+ value = value.get(k)
223
+ if value is None:
224
+ return default
225
+ else:
226
+ return default
227
+
228
+ return value if value is not None else default
229
+
230
+ def get_all(self) -> Dict[str, Any]:
231
+ """
232
+ Get all configuration data.
233
+
234
+ Returns:
235
+ Complete configuration dictionary
236
+ """
237
+ return self.config_data
@@ -0,0 +1,22 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Configuration factory for creating predefined configurations.
6
+ """
7
+
8
+ from typing import Dict, Any
9
+
10
+ from mcp_proxy_adapter.core.logging import get_global_logger
11
+
12
+
13
+ class ConfigFactory:
14
+ """Factory for creating predefined configurations."""
15
+
16
+ def __init__(self):
17
+ """Initialize config factory."""
18
+ self.logger = get_global_logger()
19
+
20
+
21
+
22
+
@@ -0,0 +1,66 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Configuration loading utilities for MCP Proxy Adapter.
6
+ """
7
+
8
+ import json
9
+ import os
10
+ from pathlib import Path
11
+ from typing import Any
12
+
13
+ from mcp_proxy_adapter.core.logging import get_global_logger
14
+
15
+
16
+ class ConfigLoader:
17
+ """Loader for configuration files and environment variables."""
18
+
19
+ def __init__(self):
20
+ """Initialize config loader."""
21
+ self.logger = get_global_logger()
22
+
23
+ def load_from_file(self, config_path: str | Path) -> dict:
24
+ """
25
+ Load configuration from JSON file.
26
+
27
+ Args:
28
+ config_path: Path to configuration file
29
+
30
+ Returns:
31
+ Configuration dictionary
32
+
33
+ Raises:
34
+ FileNotFoundError: If config file doesn't exist
35
+ json.JSONDecodeError: If config file is invalid JSON
36
+ """
37
+ path = Path(config_path)
38
+ if not path.exists():
39
+ raise FileNotFoundError(f"Configuration file not found: {config_path}")
40
+
41
+ with open(path, 'r', encoding='utf-8') as f:
42
+ return json.load(f)
43
+
44
+ def _convert_env_value(self, value: str) -> Any:
45
+ """
46
+ Convert environment variable value to appropriate type.
47
+
48
+ Args:
49
+ value: Value as string
50
+
51
+ Returns:
52
+ Converted value
53
+ """
54
+ # Try to convert to appropriate type
55
+ if value.lower() == "true":
56
+ return True
57
+ elif value.lower() == "false":
58
+ return False
59
+ elif value.isdigit():
60
+ return int(value)
61
+ else:
62
+ try:
63
+ return float(value)
64
+ except ValueError:
65
+ return value
66
+
@@ -0,0 +1,31 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Feature management utilities for MCP Proxy Adapter configuration.
6
+ """
7
+
8
+ from typing import Any, Dict, List
9
+
10
+ from mcp_proxy_adapter.core.logging import get_global_logger
11
+
12
+
13
+ class FeatureManager:
14
+ """Manager for configuration features."""
15
+
16
+ def __init__(self, config_data: Dict[str, Any]):
17
+ """
18
+ Initialize feature manager.
19
+
20
+ Args:
21
+ config_data: Configuration data dictionary
22
+ """
23
+ self.config_data = config_data
24
+ self.logger = get_global_logger()
25
+
26
+
27
+
28
+
29
+
30
+
31
+
@@ -0,0 +1,204 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Simple configuration data container and IO helpers for MCP Proxy Adapter.
6
+
7
+ This module provides a minimal, explicit configuration model with three
8
+ sections: server, client, registration and auth.
9
+
10
+ - server: Server endpoint configuration (listening for incoming connections)
11
+ - client: Client configuration (for connecting to external servers)
12
+ - registration: Proxy registration configuration (for registering with proxy server)
13
+ - auth: Authentication and authorization configuration
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ from dataclasses import dataclass, field
20
+ from pathlib import Path
21
+ from typing import Any, Dict, List, Optional
22
+
23
+
24
+ @dataclass
25
+ class ServerConfig:
26
+ """Server endpoint configuration (listening for incoming connections)."""
27
+
28
+ host: str
29
+ port: int
30
+ protocol: str # http | https | mtls
31
+ cert_file: Optional[str] = None
32
+ key_file: Optional[str] = None
33
+ ca_cert_file: Optional[str] = None
34
+ crl_file: Optional[str] = None
35
+ use_system_ca: bool = (
36
+ False # If True, allow system CA store when ca_cert_file is not provided
37
+ )
38
+ log_dir: str = "./logs"
39
+
40
+
41
+ @dataclass
42
+ class ClientConfig:
43
+ """Client configuration (for connecting to external servers)."""
44
+
45
+ enabled: bool = False
46
+ protocol: str = "http" # http | https | mtls
47
+ cert_file: Optional[str] = None
48
+ key_file: Optional[str] = None
49
+ ca_cert_file: Optional[str] = None
50
+ crl_file: Optional[str] = None
51
+ use_system_ca: bool = (
52
+ False # If True, allow system CA store when ca_cert_file is not provided
53
+ )
54
+
55
+
56
+ @dataclass
57
+ class HeartbeatConfig:
58
+ endpoint: str = "/heartbeat"
59
+ interval: int = 30
60
+
61
+
62
+ @dataclass
63
+ class RegistrationConfig:
64
+ """Proxy registration configuration (for registering with proxy server)."""
65
+
66
+ enabled: bool = False
67
+ host: str = "localhost"
68
+ port: int = 3005
69
+ protocol: str = "http" # http | https | mtls
70
+ server_id: Optional[str] = None # Server identifier for registration (preferred)
71
+ server_name: Optional[str] = None # Legacy field, use server_id instead
72
+ cert_file: Optional[str] = None
73
+ key_file: Optional[str] = None
74
+ ca_cert_file: Optional[str] = None
75
+ crl_file: Optional[str] = None
76
+ use_system_ca: bool = (
77
+ False # If True, allow system CA store when ca_cert_file is not provided
78
+ )
79
+ register_endpoint: str = "/register"
80
+ unregister_endpoint: str = "/unregister"
81
+ auto_on_startup: bool = True
82
+ auto_on_shutdown: bool = True
83
+ heartbeat: HeartbeatConfig = field(default_factory=HeartbeatConfig)
84
+
85
+
86
+ @dataclass
87
+ class AuthConfig:
88
+ use_token: bool = False
89
+ use_roles: bool = False
90
+ tokens: Dict[str, List[str]] = field(default_factory=dict)
91
+ roles: Dict[str, List[str]] = field(default_factory=dict)
92
+
93
+
94
+ @dataclass
95
+ class SimpleConfigModel:
96
+ server: ServerConfig
97
+ client: ClientConfig = field(default_factory=ClientConfig)
98
+ registration: RegistrationConfig = field(default_factory=RegistrationConfig)
99
+ auth: AuthConfig = field(default_factory=AuthConfig)
100
+
101
+
102
+ class SimpleConfig:
103
+ """High-level loader/saver for SimpleConfigModel."""
104
+
105
+ def __init__(self, config_path: str = "config.json") -> None:
106
+ self.config_path: Path = Path(config_path)
107
+ self.model: Optional[SimpleConfigModel] = None
108
+
109
+ def load(self) -> SimpleConfigModel:
110
+ content = json.loads(self.config_path.read_text(encoding="utf-8"))
111
+ # Filter out unknown fields from server config (like debug, log_level from old format)
112
+ server_data = content["server"].copy()
113
+ # Remove fields that are not in ServerConfig
114
+ known_fields = {
115
+ "host",
116
+ "port",
117
+ "protocol",
118
+ "cert_file",
119
+ "key_file",
120
+ "ca_cert_file",
121
+ "crl_file",
122
+ "use_system_ca",
123
+ "log_dir",
124
+ }
125
+ server_data = {k: v for k, v in server_data.items() if k in known_fields}
126
+
127
+ server = ServerConfig(**server_data) # type: ignore[arg-type]
128
+
129
+ # Load client config (new structure)
130
+ client = ClientConfig(**content.get("client", {})) # type: ignore[arg-type]
131
+
132
+ # Load registration config (new structure)
133
+ # Support backward compatibility: if proxy_client exists, migrate to registration
134
+ registration_data = content.get("registration", {})
135
+ if not registration_data and "proxy_client" in content:
136
+ # Migrate from old proxy_client structure
137
+ pc = content["proxy_client"]
138
+ registration_data = {
139
+ "enabled": pc.get("enabled", False),
140
+ "host": pc.get("host", "localhost"),
141
+ "port": pc.get("port", 3005),
142
+ "protocol": pc.get("protocol", "http"),
143
+ "server_id": pc.get("server_id"),
144
+ "server_name": pc.get("server_name"),
145
+ "cert_file": pc.get("cert_file"),
146
+ "key_file": pc.get("key_file"),
147
+ "ca_cert_file": pc.get("ca_cert_file"),
148
+ "crl_file": pc.get("crl_file"),
149
+ "use_system_ca": pc.get("use_system_ca", False),
150
+ "register_endpoint": (
151
+ pc.get("registration", {}).get("register_endpoint", "/register")
152
+ if isinstance(pc.get("registration"), dict)
153
+ else "/register"
154
+ ),
155
+ "unregister_endpoint": (
156
+ pc.get("registration", {}).get("unregister_endpoint", "/unregister")
157
+ if isinstance(pc.get("registration"), dict)
158
+ else "/unregister"
159
+ ),
160
+ "auto_on_startup": (
161
+ pc.get("registration", {}).get("auto_on_startup", True)
162
+ if isinstance(pc.get("registration"), dict)
163
+ else True
164
+ ),
165
+ "auto_on_shutdown": (
166
+ pc.get("registration", {}).get("auto_on_shutdown", True)
167
+ if isinstance(pc.get("registration"), dict)
168
+ else True
169
+ ),
170
+ "heartbeat": pc.get("heartbeat", {}),
171
+ }
172
+
173
+ registration = RegistrationConfig(**registration_data) # type: ignore[arg-type]
174
+ # Handle nested heartbeat structure
175
+ if isinstance(registration_data.get("heartbeat"), dict):
176
+ registration.heartbeat = HeartbeatConfig(**registration_data["heartbeat"]) # type: ignore[arg-type]
177
+
178
+ auth = AuthConfig(**content.get("auth", {})) # type: ignore[arg-type]
179
+ self.model = SimpleConfigModel(
180
+ server=server, client=client, registration=registration, auth=auth
181
+ )
182
+ return self.model
183
+
184
+ def save(self, out_path: Optional[str] = None) -> None:
185
+ if self.model is None:
186
+ raise ValueError("Configuration model is not loaded")
187
+ path = Path(out_path) if out_path else self.config_path
188
+ data: Dict[str, Any] = {
189
+ "server": vars(self.model.server),
190
+ "client": vars(self.model.client),
191
+ "registration": {
192
+ **{
193
+ k: v
194
+ for k, v in vars(self.model.registration).items()
195
+ if k != "heartbeat"
196
+ },
197
+ "heartbeat": vars(self.model.registration.heartbeat),
198
+ },
199
+ "auth": vars(self.model.auth),
200
+ }
201
+ path.parent.mkdir(parents=True, exist_ok=True)
202
+ path.write_text(
203
+ json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8"
204
+ )
@@ -0,0 +1,131 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Simple configuration generator for MCP Proxy Adapter.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Optional
11
+
12
+ from .simple_config import (
13
+ SimpleConfig,
14
+ SimpleConfigModel,
15
+ ServerConfig,
16
+ ClientConfig,
17
+ RegistrationConfig,
18
+ AuthConfig,
19
+ )
20
+
21
+
22
+ class SimpleConfigGenerator:
23
+ """Generate minimal configuration according to the plan."""
24
+
25
+ def generate(
26
+ self,
27
+ protocol: str,
28
+ with_proxy: bool = False,
29
+ out_path: str = "config.json",
30
+ # Server parameters
31
+ server_host: Optional[str] = None,
32
+ server_port: Optional[int] = None,
33
+ server_cert_file: Optional[str] = None,
34
+ server_key_file: Optional[str] = None,
35
+ server_ca_cert_file: Optional[str] = None,
36
+ server_crl_file: Optional[str] = None,
37
+ # Client parameters
38
+ client_enabled: bool = False,
39
+ client_protocol: Optional[str] = None,
40
+ client_cert_file: Optional[str] = None,
41
+ client_key_file: Optional[str] = None,
42
+ client_ca_cert_file: Optional[str] = None,
43
+ client_crl_file: Optional[str] = None,
44
+ # Registration parameters
45
+ registration_host: Optional[str] = None,
46
+ registration_port: Optional[int] = None,
47
+ registration_protocol: Optional[str] = None,
48
+ registration_cert_file: Optional[str] = None,
49
+ registration_key_file: Optional[str] = None,
50
+ registration_ca_cert_file: Optional[str] = None,
51
+ registration_crl_file: Optional[str] = None,
52
+ ) -> str:
53
+ """
54
+ Generate configuration with optional custom parameters.
55
+
56
+ Args:
57
+ protocol: Server protocol (http, https, mtls)
58
+ with_proxy: Enable proxy registration (deprecated, use registration parameters)
59
+ out_path: Output file path
60
+ # Server parameters
61
+ server_host: Server host (default: 0.0.0.0)
62
+ server_port: Server port (default: 8080)
63
+ server_cert_file: Server certificate file path
64
+ server_key_file: Server key file path
65
+ server_ca_cert_file: Server CA certificate file path
66
+ server_crl_file: Server CRL file path
67
+ # Client parameters
68
+ client_enabled: Enable client configuration
69
+ client_protocol: Client protocol (http, https, mtls)
70
+ client_cert_file: Client certificate file path
71
+ client_key_file: Client key file path
72
+ client_ca_cert_file: Client CA certificate file path
73
+ client_crl_file: Client CRL file path
74
+ # Registration parameters
75
+ registration_host: Registration proxy host (default: localhost)
76
+ registration_port: Registration proxy port (default: 3005)
77
+ registration_protocol: Registration protocol (http, https, mtls)
78
+ registration_cert_file: Registration certificate file path
79
+ registration_key_file: Registration key file path
80
+ registration_ca_cert_file: Registration CA certificate file path
81
+ registration_crl_file: Registration CRL file path
82
+ """
83
+ # Server configuration
84
+ server = ServerConfig(
85
+ host=server_host or "0.0.0.0", port=server_port or 8080, protocol=protocol
86
+ )
87
+ if protocol in ("https", "mtls"):
88
+ server.cert_file = server_cert_file or "./certs/server.crt"
89
+ server.key_file = server_key_file or "./certs/server.key"
90
+ # For mtls: CA is required if use_system_ca=False (default), optional if use_system_ca=True
91
+ # Only set if explicitly provided
92
+ if protocol == "mtls" and server_ca_cert_file:
93
+ server.ca_cert_file = server_ca_cert_file
94
+ if server_crl_file:
95
+ server.crl_file = server_crl_file
96
+ # use_system_ca defaults to False (only CA from config is used by default)
97
+
98
+ # Client configuration
99
+ client = ClientConfig(enabled=client_enabled)
100
+ if client_enabled:
101
+ client.protocol = client_protocol or protocol
102
+ if client.protocol in ("https", "mtls"):
103
+ client.cert_file = client_cert_file or "./certs/client.crt"
104
+ client.key_file = client_key_file or "./certs/client.key"
105
+ if client.protocol == "mtls" and client_ca_cert_file:
106
+ client.ca_cert_file = client_ca_cert_file
107
+ if client_crl_file:
108
+ client.crl_file = client_crl_file
109
+
110
+ # Registration configuration
111
+ registration = RegistrationConfig(enabled=with_proxy)
112
+ if with_proxy:
113
+ registration.host = registration_host or "localhost"
114
+ registration.port = registration_port or 3005
115
+ registration.protocol = registration_protocol or "http"
116
+ # Client certificates for proxy connection (only if proxy itself uses HTTPS/mTLS)
117
+ if registration.protocol in ("https", "mtls"):
118
+ registration.cert_file = registration_cert_file or "./certs/registration.crt"
119
+ registration.key_file = registration_key_file or "./certs/registration.key"
120
+ if registration.protocol == "mtls" and registration_ca_cert_file:
121
+ registration.ca_cert_file = registration_ca_cert_file
122
+ if registration_crl_file:
123
+ registration.crl_file = registration_crl_file
124
+ registration.auto_on_startup = True
125
+
126
+ auth = AuthConfig(use_token=False, use_roles=False, tokens={}, roles={})
127
+
128
+ cfg = SimpleConfig()
129
+ cfg.model = SimpleConfigModel(server=server, client=client, registration=registration, auth=auth)
130
+ cfg.save(out_path)
131
+ return out_path