mcp-proxy-adapter 6.9.43__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.
Files changed (242) 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 +355 -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 +266 -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 +35 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +74 -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 +128 -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 +388 -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 +116 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +100 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +380 -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 +190 -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 +13 -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 +264 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +81 -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 +313 -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.43.dist-info/METADATA +739 -0
  239. mcp_proxy_adapter-6.9.43.dist-info/RECORD +242 -0
  240. mcp_proxy_adapter-6.9.43.dist-info/WHEEL +5 -0
  241. mcp_proxy_adapter-6.9.43.dist-info/entry_points.txt +12 -0
  242. mcp_proxy_adapter-6.9.43.dist-info/top_level.txt +1 -0
@@ -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,116 @@
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, proxy_client and auth.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import json
14
+ from dataclasses import dataclass, field
15
+ from pathlib import Path
16
+ from typing import Any, Dict, List, Optional
17
+
18
+
19
+ @dataclass
20
+ class ServerConfig:
21
+ host: str
22
+ port: int
23
+ protocol: str # http | https | mtls
24
+ cert_file: Optional[str] = None
25
+ key_file: Optional[str] = None
26
+ ca_cert_file: Optional[str] = None
27
+ crl_file: Optional[str] = None
28
+ use_system_ca: bool = False # If True, allow system CA store when ca_cert_file is not provided
29
+ log_dir: str = "./logs"
30
+
31
+
32
+ @dataclass
33
+ class HeartbeatConfig:
34
+ endpoint: str = "/heartbeat"
35
+ interval: int = 30
36
+
37
+
38
+ @dataclass
39
+ class RegistrationConfig:
40
+ register_endpoint: str = "/register"
41
+ unregister_endpoint: str = "/unregister"
42
+ auto_on_startup: bool = True
43
+ auto_on_shutdown: bool = True
44
+
45
+
46
+ @dataclass
47
+ class ProxyClientConfig:
48
+ enabled: bool = False
49
+ host: str = "localhost"
50
+ port: int = 3005
51
+ protocol: str = "http"
52
+ server_id: Optional[str] = None # Server identifier for registration (preferred)
53
+ server_name: Optional[str] = None # Legacy field, use server_id instead
54
+ cert_file: Optional[str] = None
55
+ key_file: Optional[str] = None
56
+ ca_cert_file: Optional[str] = None
57
+ crl_file: Optional[str] = None
58
+ use_system_ca: bool = False # If True, allow system CA store when ca_cert_file is not provided
59
+ heartbeat: HeartbeatConfig = field(default_factory=HeartbeatConfig)
60
+ registration: RegistrationConfig = field(default_factory=RegistrationConfig)
61
+
62
+
63
+ @dataclass
64
+ class AuthConfig:
65
+ use_token: bool = False
66
+ use_roles: bool = False
67
+ tokens: Dict[str, List[str]] = field(default_factory=dict)
68
+ roles: Dict[str, List[str]] = field(default_factory=dict)
69
+
70
+
71
+ @dataclass
72
+ class SimpleConfigModel:
73
+ server: ServerConfig
74
+ proxy_client: ProxyClientConfig = field(default_factory=ProxyClientConfig)
75
+ auth: AuthConfig = field(default_factory=AuthConfig)
76
+
77
+
78
+ class SimpleConfig:
79
+ """High-level loader/saver for SimpleConfigModel."""
80
+
81
+ def __init__(self, config_path: str = "config.json") -> None:
82
+ self.config_path: Path = Path(config_path)
83
+ self.model: Optional[SimpleConfigModel] = None
84
+
85
+ def load(self) -> SimpleConfigModel:
86
+ content = json.loads(self.config_path.read_text(encoding="utf-8"))
87
+ server = ServerConfig(**content["server"]) # type: ignore[arg-type]
88
+ proxy_client = ProxyClientConfig(**content.get("proxy_client", {})) # type: ignore[arg-type]
89
+ # Nested structures for proxy client (heartbeat/registration)
90
+ if isinstance(content.get("proxy_client"), dict):
91
+ pc = content["proxy_client"]
92
+ if isinstance(pc.get("heartbeat"), dict):
93
+ proxy_client.heartbeat = HeartbeatConfig(**pc["heartbeat"]) # type: ignore[arg-type]
94
+ if isinstance(pc.get("registration"), dict):
95
+ proxy_client.registration = RegistrationConfig(**pc["registration"]) # type: ignore[arg-type]
96
+ auth = AuthConfig(**content.get("auth", {})) # type: ignore[arg-type]
97
+ self.model = SimpleConfigModel(server=server, proxy_client=proxy_client, auth=auth)
98
+ return self.model
99
+
100
+ def save(self, out_path: Optional[str] = None) -> None:
101
+ if self.model is None:
102
+ raise ValueError("Configuration model is not loaded")
103
+ path = Path(out_path) if out_path else self.config_path
104
+ data: Dict[str, Any] = {
105
+ "server": vars(self.model.server),
106
+ "proxy_client": {
107
+ **{k: v for k, v in vars(self.model.proxy_client).items() if k not in {"heartbeat", "registration"}},
108
+ "heartbeat": vars(self.model.proxy_client.heartbeat),
109
+ "registration": vars(self.model.proxy_client.registration),
110
+ },
111
+ "auth": vars(self.model.auth),
112
+ }
113
+ path.parent.mkdir(parents=True, exist_ok=True)
114
+ path.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")
115
+
116
+
@@ -0,0 +1,100 @@
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
+ ProxyClientConfig,
17
+ AuthConfig,
18
+ )
19
+
20
+
21
+ class SimpleConfigGenerator:
22
+ """Generate minimal configuration according to the plan."""
23
+
24
+ def generate(
25
+ self,
26
+ protocol: str,
27
+ with_proxy: bool = False,
28
+ out_path: str = "config.json",
29
+ server_host: Optional[str] = None,
30
+ server_port: Optional[int] = None,
31
+ server_cert_file: Optional[str] = None,
32
+ server_key_file: Optional[str] = None,
33
+ server_ca_cert_file: Optional[str] = None,
34
+ proxy_host: Optional[str] = None,
35
+ proxy_port: Optional[int] = None,
36
+ proxy_cert_file: Optional[str] = None,
37
+ proxy_key_file: Optional[str] = None,
38
+ proxy_ca_cert_file: Optional[str] = None,
39
+ ) -> str:
40
+ """
41
+ Generate configuration with optional custom parameters.
42
+
43
+ Args:
44
+ protocol: Server protocol (http, https, mtls)
45
+ with_proxy: Enable proxy registration
46
+ out_path: Output file path
47
+ server_host: Server host (default: 0.0.0.0)
48
+ server_port: Server port (default: 8080)
49
+ server_cert_file: Server certificate file path
50
+ server_key_file: Server key file path
51
+ server_ca_cert_file: Server CA certificate file path
52
+ proxy_host: Proxy host (default: localhost)
53
+ proxy_port: Proxy port (default: 3005)
54
+ proxy_cert_file: Proxy client certificate file path
55
+ proxy_key_file: Proxy client key file path
56
+ proxy_ca_cert_file: Proxy CA certificate file path
57
+ """
58
+ # Server configuration
59
+ server = ServerConfig(
60
+ host=server_host or "0.0.0.0", port=server_port or 8080, protocol=protocol
61
+ )
62
+ if protocol in ("https", "mtls"):
63
+ server.cert_file = server_cert_file or "./certs/server.crt"
64
+ server.key_file = server_key_file or "./certs/server.key"
65
+ # For mtls: CA is required if use_system_ca=False (default), optional if use_system_ca=True
66
+ # Only set if explicitly provided
67
+ if protocol == "mtls" and server_ca_cert_file:
68
+ server.ca_cert_file = server_ca_cert_file
69
+ # use_system_ca defaults to False (only CA from config is used by default)
70
+
71
+ # Proxy configuration
72
+ proxy = ProxyClientConfig(enabled=with_proxy)
73
+ if with_proxy:
74
+ # NOTE: proxy.protocol indicates the SERVER's protocol, not the proxy's protocol
75
+ # The proxy itself typically runs on HTTP (for test proxy) or may have its own protocol
76
+ # This field is used to determine if client certificates are needed for proxy connection
77
+ # (if proxy itself uses HTTPS/mTLS, which is not the case for test proxy)
78
+ proxy.protocol = protocol
79
+ proxy.host = proxy_host or "localhost"
80
+ proxy.port = proxy_port or 3005
81
+ # Client certificates for proxy connection (only if proxy itself uses HTTPS/mTLS)
82
+ # For test proxy (HTTP), these are not used but may be set for consistency
83
+ if protocol in ("https", "mtls"):
84
+ proxy.cert_file = proxy_cert_file or "./certs/client.crt"
85
+ proxy.key_file = proxy_key_file or "./certs/client.key"
86
+ # For mtls: CA is required if use_system_ca=False (default), optional if use_system_ca=True
87
+ # Only set if explicitly provided
88
+ if protocol == "mtls" and proxy_ca_cert_file:
89
+ proxy.ca_cert_file = proxy_ca_cert_file
90
+ # use_system_ca defaults to False (only CA from config is used by default)
91
+ # Explicitly set registration.auto_on_startup when proxy is enabled
92
+ # Note: enabled controls client availability, registration.auto_on_startup controls auto-registration
93
+ proxy.registration.auto_on_startup = True
94
+
95
+ auth = AuthConfig(use_token=False, use_roles=False, tokens={}, roles={})
96
+
97
+ cfg = SimpleConfig()
98
+ cfg.model = SimpleConfigModel(server=server, proxy_client=proxy, auth=auth)
99
+ cfg.save(out_path)
100
+ return out_path