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,252 @@
1
+ """
2
+ Configuration Converter for security framework integration.
3
+
4
+ This module provides utilities to convert between mcp_proxy_adapter configuration
5
+ format and mcp_security_framework configuration format, ensuring backward compatibility.
6
+ """
7
+
8
+ import json
9
+ import logging
10
+ from typing import Dict, Any, Optional
11
+ from pathlib import Path
12
+
13
+ from mcp_proxy_adapter.core.logging import get_global_logger
14
+
15
+
16
+ class ConfigConverter:
17
+ """
18
+ Converter for configuration formats.
19
+
20
+ Provides methods to convert between mcp_proxy_adapter configuration
21
+ and mcp_security_framework configuration formats.
22
+ """
23
+
24
+ @staticmethod
25
+ def to_security_framework_config(mcp_config: Dict[str, Any]) -> Dict[str, Any]:
26
+ """
27
+ Convert mcp_proxy_adapter configuration to SecurityConfig format.
28
+
29
+ Args:
30
+ mcp_config: mcp_proxy_adapter configuration dictionary
31
+
32
+ Returns:
33
+ SecurityConfig compatible dictionary
34
+ """
35
+ try:
36
+ # Start with default security framework config
37
+ security_config = {
38
+ "auth": {
39
+ "enabled": True,
40
+ "methods": ["api_key"],
41
+ "api_keys": {},
42
+ "jwt_secret": "",
43
+ "jwt_algorithm": "HS256",
44
+ },
45
+ "ssl": {
46
+ "enabled": False,
47
+ "cert_file": None,
48
+ "key_file": None,
49
+ "ca_cert": None,
50
+ "min_tls_version": "TLSv1.2",
51
+ "verify_client": False,
52
+ "client_cert_required": False,
53
+ },
54
+ "permissions": {
55
+ "enabled": True,
56
+ "roles_file": "roles.json",
57
+ "default_role": "user",
58
+ "deny_by_default": True,
59
+ },
60
+ "rate_limit": {
61
+ "enabled": True,
62
+ "requests_per_minute": 60,
63
+ "requests_per_hour": 1000,
64
+ "burst_limit": 10,
65
+ "by_ip": True,
66
+ "by_user": True,
67
+ },
68
+ }
69
+
70
+ # Convert from security section if exists
71
+ if "security" in mcp_config:
72
+ security_section = mcp_config["security"]
73
+
74
+ # Convert auth config
75
+ if "auth" in security_section:
76
+ auth_config = security_section["auth"]
77
+ security_config["auth"].update(
78
+ {
79
+ "enabled": auth_config.get("enabled", True),
80
+ "methods": auth_config.get("methods", ["api_key"]),
81
+ "api_keys": auth_config.get("api_keys", {}),
82
+ "jwt_secret": auth_config.get("jwt_secret", ""),
83
+ "jwt_algorithm": auth_config.get("jwt_algorithm", "HS256"),
84
+ }
85
+ )
86
+
87
+ # Convert SSL config
88
+ if "ssl" in security_section:
89
+ ssl_config = security_section["ssl"]
90
+ security_config["ssl"].update(
91
+ {
92
+ "enabled": ssl_config.get("enabled", False),
93
+ "cert_file": ssl_config.get("cert_file"),
94
+ "key_file": ssl_config.get("key_file"),
95
+ "ca_cert": ssl_config.get("ca_cert"),
96
+ "min_tls_version": ssl_config.get(
97
+ "min_tls_version", "TLSv1.2"
98
+ ),
99
+ "verify_client": ssl_config.get("verify_client", False),
100
+ "client_cert_required": ssl_config.get(
101
+ "client_cert_required", False
102
+ ),
103
+ }
104
+ )
105
+
106
+ # Convert permissions config
107
+ if "permissions" in security_section:
108
+ permissions_config = security_section["permissions"]
109
+ security_config["permissions"].update(
110
+ {
111
+ "enabled": permissions_config.get("enabled", True),
112
+ "roles_file": permissions_config.get(
113
+ "roles_file", "roles.json"
114
+ ),
115
+ "default_role": permissions_config.get(
116
+ "default_role", "user"
117
+ ),
118
+ "deny_by_default": permissions_config.get(
119
+ "deny_by_default", True
120
+ ),
121
+ }
122
+ )
123
+
124
+ # Convert rate limit config
125
+ if "rate_limit" in security_section:
126
+ rate_limit_config = security_section["rate_limit"]
127
+ security_config["rate_limit"].update(
128
+ {
129
+ "enabled": rate_limit_config.get("enabled", True),
130
+ "requests_per_minute": rate_limit_config.get(
131
+ "requests_per_minute", 60
132
+ ),
133
+ "requests_per_hour": rate_limit_config.get(
134
+ "requests_per_hour", 1000
135
+ ),
136
+ "burst_limit": rate_limit_config.get("burst_limit", 10),
137
+ "by_ip": rate_limit_config.get("by_ip", True),
138
+ "by_user": rate_limit_config.get("by_user", True),
139
+ }
140
+ )
141
+
142
+ # Convert from legacy SSL config if security section doesn't exist
143
+ elif "ssl" in mcp_config:
144
+ ssl_config = mcp_config["ssl"]
145
+ security_config["ssl"].update(
146
+ {
147
+ "enabled": ssl_config.get("enabled", False),
148
+ "cert_file": ssl_config.get("cert_file"),
149
+ "key_file": ssl_config.get("key_file"),
150
+ "ca_cert": ssl_config.get("ca_cert"),
151
+ "min_tls_version": ssl_config.get("min_tls_version", "TLSv1.2"),
152
+ "verify_client": ssl_config.get("verify_client", False),
153
+ "client_cert_required": ssl_config.get(
154
+ "client_cert_required", False
155
+ ),
156
+ }
157
+ )
158
+
159
+ # Extract API keys from legacy SSL config
160
+ if "api_keys" in ssl_config:
161
+ security_config["auth"]["api_keys"] = ssl_config["api_keys"]
162
+
163
+ # Convert from legacy roles config
164
+ if "roles" in mcp_config:
165
+ roles_config = mcp_config["roles"]
166
+ security_config["permissions"].update(
167
+ {
168
+ "enabled": roles_config.get("enabled", True),
169
+ "roles_file": roles_config.get("config_file", "roles.json"),
170
+ "default_role": "user",
171
+ "deny_by_default": roles_config.get("default_policy", {}).get(
172
+ "deny_by_default", True
173
+ ),
174
+ }
175
+ )
176
+
177
+ get_global_logger().info(
178
+ "Configuration converted to security framework format successfully"
179
+ )
180
+ return security_config
181
+
182
+ except Exception as e:
183
+ get_global_logger().error(
184
+ f"Failed to convert configuration to security framework format: {e}"
185
+ )
186
+ return ConfigConverter._get_default_security_config()
187
+
188
+ @staticmethod
189
+
190
+ @staticmethod
191
+
192
+ @staticmethod
193
+
194
+ @staticmethod
195
+ def _get_default_security_config() -> Dict[str, Any]:
196
+ """
197
+ Get default security framework configuration.
198
+
199
+ Returns:
200
+ Default security framework configuration
201
+ """
202
+ return {
203
+ "auth": {
204
+ "enabled": True,
205
+ "methods": ["api_key"],
206
+ "api_keys": {},
207
+ "jwt_secret": "",
208
+ "jwt_algorithm": "HS256",
209
+ },
210
+ "ssl": {
211
+ "enabled": False,
212
+ "cert_file": None,
213
+ "key_file": None,
214
+ "ca_cert": None,
215
+ "min_tls_version": "TLSv1.2",
216
+ "verify_client": False,
217
+ "client_cert_required": False,
218
+ },
219
+ "permissions": {
220
+ "enabled": True,
221
+ "roles_file": "roles.json",
222
+ "default_role": "user",
223
+ "deny_by_default": True,
224
+ },
225
+ "rate_limit": {
226
+ "enabled": True,
227
+ "requests_per_minute": 60,
228
+ "requests_per_hour": 1000,
229
+ "burst_limit": 10,
230
+ "by_ip": True,
231
+ "by_user": True,
232
+ },
233
+ }
234
+
235
+ @staticmethod
236
+ def _get_default_mcp_config() -> Dict[str, Any]:
237
+ """
238
+ Get default mcp_proxy_adapter configuration.
239
+
240
+ Returns:
241
+ Default mcp_proxy_adapter configuration
242
+ """
243
+ return {
244
+ "security": {
245
+ "framework": "mcp_security_framework",
246
+ "enabled": True,
247
+ "auth": {"enabled": True, "methods": ["api_key"], "api_keys": {}},
248
+ "ssl": {"enabled": False, "cert_file": None, "key_file": None},
249
+ "permissions": {"enabled": True, "roles_file": "roles.json"},
250
+ "rate_limit": {"enabled": True, "requests_per_minute": 60},
251
+ }
252
+ }
@@ -0,0 +1,211 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Main configuration validator for MCP Proxy Adapter.
6
+ """
7
+
8
+ import json
9
+ import logging
10
+ from pathlib import Path
11
+ from typing import Dict, List, Any, Optional
12
+
13
+ from .file_validator import FileValidator
14
+ from .security_validator import SecurityValidator
15
+ from .protocol_validator import ProtocolValidator
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class ConfigValidator:
21
+ """
22
+ Comprehensive configuration validator for MCP Proxy Adapter.
23
+
24
+ Validates:
25
+ - Required sections and keys
26
+ - File existence for referenced files
27
+ - Feature flag dependencies
28
+ - Protocol-specific requirements
29
+ - Security configuration consistency
30
+ """
31
+
32
+ def __init__(self, config_path: Optional[str] = None):
33
+ """
34
+ Initialize configuration validator.
35
+
36
+ Args:
37
+ config_path: Path to configuration file (optional)
38
+ """
39
+ self.config_path = config_path
40
+ self.config_data: Dict[str, Any] = {}
41
+ self.validation_results: List[ValidationResult] = []
42
+
43
+ def load_config(self, config_path: Optional[str] = None) -> None:
44
+ """
45
+ Load configuration from file.
46
+
47
+ Args:
48
+ config_path: Path to configuration file
49
+ """
50
+ if config_path:
51
+ self.config_path = config_path
52
+
53
+ if not self.config_path:
54
+ raise ValueError("No configuration path provided")
55
+
56
+ try:
57
+ with open(self.config_path, 'r', encoding='utf-8') as f:
58
+ self.config_data = json.load(f)
59
+ logger.info(f"Configuration loaded from {self.config_path}")
60
+ except FileNotFoundError:
61
+ raise FileNotFoundError(f"Configuration file not found: {self.config_path}")
62
+ except json.JSONDecodeError as e:
63
+ raise ValueError(f"Invalid JSON in configuration file: {e}")
64
+ except Exception as e:
65
+ raise RuntimeError(f"Error loading configuration: {e}")
66
+
67
+ def validate_config(self, config_data: Optional[Dict[str, Any]] = None) -> List[ValidationResult]:
68
+ """
69
+ Validate configuration data.
70
+
71
+ Args:
72
+ config_data: Configuration data to validate (optional)
73
+
74
+ Returns:
75
+ List of validation results
76
+ """
77
+ if config_data is not None:
78
+ self.config_data = config_data
79
+
80
+ if not self.config_data:
81
+ raise ValueError("No configuration data to validate")
82
+
83
+ self.validation_results = []
84
+
85
+ # Initialize validators
86
+ file_validator = FileValidator(self.config_data)
87
+ security_validator = SecurityValidator(self.config_data)
88
+ protocol_validator = ProtocolValidator(self.config_data)
89
+
90
+ # Run all validations
91
+ self.validation_results.extend(protocol_validator.validate_required_sections())
92
+ self.validation_results.extend(protocol_validator.validate_protocol_requirements())
93
+ self.validation_results.extend(file_validator.validate_file_existence())
94
+ self.validation_results.extend(security_validator.validate_security_consistency())
95
+ self.validation_results.extend(security_validator.validate_ssl_configuration())
96
+ self.validation_results.extend(security_validator.validate_roles_configuration())
97
+ self.validation_results.extend(security_validator.validate_proxy_registration())
98
+
99
+ # Additional validations
100
+ self._validate_unknown_fields()
101
+ self._validate_uuid_format()
102
+
103
+ return self.validation_results
104
+
105
+ def validate_all(self, config_data: Optional[Dict[str, Any]] = None) -> List[ValidationResult]:
106
+ """
107
+ Validate all aspects of the configuration.
108
+
109
+ Args:
110
+ config_data: Configuration data to validate (optional)
111
+
112
+ Returns:
113
+ List of validation results
114
+ """
115
+ return self.validate_config(config_data)
116
+
117
+ def _validate_unknown_fields(self) -> None:
118
+ """Validate for unknown configuration fields."""
119
+ known_sections = {
120
+ "server", "protocols", "security", "ssl", "auth", "roles",
121
+ "logging", "commands", "proxy_registration", "transport"
122
+ }
123
+
124
+ for section in self.config_data.keys():
125
+ if section not in known_sections:
126
+ self.validation_results.append(ValidationResult(
127
+ level="warning",
128
+ message=f"Unknown configuration section: {section}",
129
+ section=section,
130
+ suggestion="Check if this section is needed or if it's a typo"
131
+ ))
132
+
133
+ def _validate_uuid_format(self) -> None:
134
+ """Validate UUID format in configuration."""
135
+ uuid_fields = ["server.server_id", "proxy_registration.server_id"]
136
+
137
+ for field in uuid_fields:
138
+ value = self._get_nested_value_safe(field)
139
+ if value and not self._is_valid_uuid4(str(value)):
140
+ self.validation_results.append(ValidationResult(
141
+ level="warning",
142
+ message=f"Invalid UUID format in {field}: {value}",
143
+ section=field.split(".")[0],
144
+ key=field.split(".")[1],
145
+ suggestion="Use a valid UUID4 format"
146
+ ))
147
+
148
+ def _is_valid_uuid4(self, uuid_str: str) -> bool:
149
+ """Check if string is a valid UUID4."""
150
+ import re
151
+ uuid_pattern = r'^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
152
+ return bool(re.match(uuid_pattern, uuid_str, re.IGNORECASE))
153
+
154
+ def _get_nested_value_safe(self, key: str, default: Any = None) -> Any:
155
+ """Safely get a nested value from configuration."""
156
+ keys = key.split('.')
157
+ value = self.config_data
158
+
159
+ for k in keys:
160
+ if isinstance(value, dict) and k in value:
161
+ value = value[k]
162
+ else:
163
+ return default
164
+
165
+ return value
166
+
167
+ def get_validation_summary(self) -> Dict[str, Any]:
168
+ """
169
+ Get a summary of validation results.
170
+
171
+ Returns:
172
+ Dictionary with validation summary
173
+ """
174
+ error_count = sum(1 for r in self.validation_results if r.level == "error")
175
+ warning_count = sum(1 for r in self.validation_results if r.level == "warning")
176
+ info_count = sum(1 for r in self.validation_results if r.level == "info")
177
+
178
+ return {
179
+ "total_issues": len(self.validation_results),
180
+ "errors": error_count,
181
+ "warnings": warning_count,
182
+ "info": info_count,
183
+ "is_valid": error_count == 0
184
+ }
185
+
186
+ def print_validation_report(self) -> None:
187
+ """Print a formatted validation report."""
188
+ summary = self.get_validation_summary()
189
+
190
+ print(f"\\nšŸ“‹ Configuration Validation Report")
191
+ print(f"{'=' * 40}")
192
+ print(f"Total issues: {summary['total_issues']}")
193
+ print(f"Errors: {summary['errors']}")
194
+ print(f"Warnings: {summary['warnings']}")
195
+ print(f"Info: {summary['info']}")
196
+ print(f"Valid: {'āœ… Yes' if summary['is_valid'] else 'āŒ No'}")
197
+
198
+ if self.validation_results:
199
+ print(f"\\nšŸ“ Issues:")
200
+ for i, result in enumerate(self.validation_results, 1):
201
+ level_icon = {"error": "āŒ", "warning": "āš ļø", "info": "ā„¹ļø"}[result.level]
202
+ print(f"{i:2d}. {level_icon} {result.message}")
203
+ if result.section:
204
+ print(f" Section: {result.section}")
205
+ if result.key:
206
+ print(f" Key: {result.key}")
207
+ if result.suggestion:
208
+ print(f" Suggestion: {result.suggestion}")
209
+ print()
210
+
211
+