mcp-proxy-adapter 6.9.17__py3-none-any.whl → 6.9.19__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 (87) hide show
  1. mcp_proxy_adapter/api/app.py +52 -52
  2. mcp_proxy_adapter/api/handlers.py +5 -5
  3. mcp_proxy_adapter/api/middleware/__init__.py +8 -8
  4. mcp_proxy_adapter/api/middleware/base.py +14 -14
  5. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +7 -7
  6. mcp_proxy_adapter/api/middleware/error_handling.py +9 -9
  7. mcp_proxy_adapter/api/middleware/factory.py +17 -17
  8. mcp_proxy_adapter/api/middleware/logging.py +6 -6
  9. mcp_proxy_adapter/api/middleware/performance.py +3 -3
  10. mcp_proxy_adapter/api/middleware/protocol_middleware.py +19 -19
  11. mcp_proxy_adapter/api/middleware/transport_middleware.py +3 -3
  12. mcp_proxy_adapter/api/middleware/unified_security.py +11 -11
  13. mcp_proxy_adapter/api/middleware/user_info_middleware.py +21 -21
  14. mcp_proxy_adapter/api/tool_integration.py +3 -2
  15. mcp_proxy_adapter/api/tools.py +4 -3
  16. mcp_proxy_adapter/commands/auth_validation_command.py +6 -5
  17. mcp_proxy_adapter/commands/base.py +10 -10
  18. mcp_proxy_adapter/commands/builtin_commands.py +6 -6
  19. mcp_proxy_adapter/commands/catalog_manager.py +74 -74
  20. mcp_proxy_adapter/commands/cert_monitor_command.py +13 -12
  21. mcp_proxy_adapter/commands/certificate_management_command.py +20 -19
  22. mcp_proxy_adapter/commands/command_registry.py +68 -67
  23. mcp_proxy_adapter/commands/config_command.py +3 -1
  24. mcp_proxy_adapter/commands/dependency_manager.py +10 -10
  25. mcp_proxy_adapter/commands/help_command.py +21 -20
  26. mcp_proxy_adapter/commands/hooks.py +27 -27
  27. mcp_proxy_adapter/commands/key_management_command.py +19 -18
  28. mcp_proxy_adapter/commands/plugins_command.py +2 -1
  29. mcp_proxy_adapter/commands/protocol_management_command.py +6 -6
  30. mcp_proxy_adapter/commands/proxy_registration_command.py +9 -9
  31. mcp_proxy_adapter/commands/registration_status_command.py +4 -4
  32. mcp_proxy_adapter/commands/reload_command.py +5 -5
  33. mcp_proxy_adapter/commands/role_test_command.py +2 -1
  34. mcp_proxy_adapter/commands/roles_management_command.py +9 -8
  35. mcp_proxy_adapter/commands/security_command.py +3 -2
  36. mcp_proxy_adapter/commands/ssl_setup_command.py +7 -6
  37. mcp_proxy_adapter/commands/token_management_command.py +12 -11
  38. mcp_proxy_adapter/commands/transport_management_command.py +2 -2
  39. mcp_proxy_adapter/config.py +3 -3
  40. mcp_proxy_adapter/core/__init__.py +1 -1
  41. mcp_proxy_adapter/core/app_runner.py +3 -3
  42. mcp_proxy_adapter/core/auth_validator.py +9 -9
  43. mcp_proxy_adapter/core/certificate_utils.py +27 -27
  44. mcp_proxy_adapter/core/client_manager.py +13 -13
  45. mcp_proxy_adapter/core/client_security.py +26 -26
  46. mcp_proxy_adapter/core/config_converter.py +18 -18
  47. mcp_proxy_adapter/core/config_validator.py +5 -1
  48. mcp_proxy_adapter/core/crl_utils.py +22 -22
  49. mcp_proxy_adapter/core/logging.py +21 -13
  50. mcp_proxy_adapter/core/mtls_asgi.py +7 -7
  51. mcp_proxy_adapter/core/mtls_asgi_app.py +9 -9
  52. mcp_proxy_adapter/core/mtls_proxy.py +9 -9
  53. mcp_proxy_adapter/core/mtls_server.py +18 -18
  54. mcp_proxy_adapter/core/protocol_manager.py +29 -29
  55. mcp_proxy_adapter/core/proxy_registration.py +67 -67
  56. mcp_proxy_adapter/core/security_adapter.py +18 -18
  57. mcp_proxy_adapter/core/security_factory.py +16 -16
  58. mcp_proxy_adapter/core/security_integration.py +6 -6
  59. mcp_proxy_adapter/core/server_adapter.py +12 -12
  60. mcp_proxy_adapter/core/server_engine.py +17 -17
  61. mcp_proxy_adapter/core/signal_handler.py +12 -12
  62. mcp_proxy_adapter/core/ssl_utils.py +12 -12
  63. mcp_proxy_adapter/core/transport_manager.py +14 -14
  64. mcp_proxy_adapter/core/unified_config_adapter.py +6 -6
  65. mcp_proxy_adapter/core/utils.py +5 -5
  66. mcp_proxy_adapter/custom_openapi.py +7 -7
  67. mcp_proxy_adapter/examples/cert_manager_bugfix.py +2 -2
  68. mcp_proxy_adapter/examples/full_application/commands/__init__.py +6 -5
  69. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +44 -0
  70. mcp_proxy_adapter/examples/full_application/commands/help_command.py +66 -0
  71. mcp_proxy_adapter/examples/full_application/commands/list_command.py +64 -0
  72. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +21 -21
  73. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +6 -6
  74. mcp_proxy_adapter/examples/full_application/main.py +28 -0
  75. mcp_proxy_adapter/examples/proxy_registration_example.py +38 -38
  76. mcp_proxy_adapter/examples/test_framework_complete.py +35 -35
  77. mcp_proxy_adapter/examples/test_mcp_server.py +2 -2
  78. mcp_proxy_adapter/examples/validate_generator_compatibility.py +386 -0
  79. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +248 -0
  80. mcp_proxy_adapter/main.py +3 -0
  81. mcp_proxy_adapter/version.py +1 -1
  82. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/METADATA +1 -1
  83. mcp_proxy_adapter-6.9.19.dist-info/RECORD +149 -0
  84. mcp_proxy_adapter-6.9.17.dist-info/RECORD +0 -144
  85. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/WHEEL +0 -0
  86. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/entry_points.txt +0 -0
  87. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,386 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script to validate compatibility between config generator and validator.
4
+
5
+ Author: Vasiliy Zdanovskiy
6
+ email: vasilyvz@gmail.com
7
+ """
8
+
9
+ import json
10
+ import sys
11
+ import tempfile
12
+ import shutil
13
+ from pathlib import Path
14
+ from typing import Dict, Any, List
15
+
16
+ # Add the project root to the path
17
+ project_root = Path(__file__).parent.parent.parent
18
+ sys.path.insert(0, str(project_root))
19
+
20
+ from mcp_proxy_adapter.core.config_validator import ConfigValidator
21
+ from mcp_proxy_adapter.examples.config_builder import generate_complete_config
22
+
23
+
24
+ def test_generator_validator_compatibility():
25
+ """Test that generated configs pass validation."""
26
+ print("🔍 Testing Generator-Validator Compatibility")
27
+ print("=" * 50)
28
+
29
+ # Test configurations to generate
30
+ test_configs = [
31
+ {
32
+ "name": "HTTP Basic",
33
+ "protocol": "http",
34
+ "ssl_enabled": False,
35
+ "security_enabled": False,
36
+ "roles_enabled": False,
37
+ "proxy_registration_enabled": False
38
+ },
39
+ {
40
+ "name": "HTTP + Token",
41
+ "protocol": "http",
42
+ "ssl_enabled": False,
43
+ "security_enabled": True,
44
+ "roles_enabled": False,
45
+ "proxy_registration_enabled": False
46
+ },
47
+ {
48
+ "name": "HTTP + Token + Roles",
49
+ "protocol": "http",
50
+ "ssl_enabled": False,
51
+ "security_enabled": True,
52
+ "roles_enabled": True,
53
+ "proxy_registration_enabled": False
54
+ },
55
+ {
56
+ "name": "HTTPS Basic",
57
+ "protocol": "https",
58
+ "ssl_enabled": True,
59
+ "security_enabled": False,
60
+ "roles_enabled": False,
61
+ "proxy_registration_enabled": False
62
+ },
63
+ {
64
+ "name": "HTTPS + Token",
65
+ "protocol": "https",
66
+ "ssl_enabled": True,
67
+ "security_enabled": True,
68
+ "roles_enabled": False,
69
+ "proxy_registration_enabled": False
70
+ },
71
+ {
72
+ "name": "HTTPS + Token + Roles",
73
+ "protocol": "https",
74
+ "ssl_enabled": True,
75
+ "security_enabled": True,
76
+ "roles_enabled": True,
77
+ "proxy_registration_enabled": False
78
+ },
79
+ {
80
+ "name": "mTLS + Proxy Registration",
81
+ "protocol": "mtls",
82
+ "ssl_enabled": True,
83
+ "security_enabled": False,
84
+ "roles_enabled": False,
85
+ "proxy_registration_enabled": True
86
+ }
87
+ ]
88
+
89
+ results = []
90
+
91
+ for test_config in test_configs:
92
+ print(f"\n📋 Testing: {test_config['name']}")
93
+ print("-" * 30)
94
+
95
+ try:
96
+ # Generate configuration
97
+ print(" 🔧 Generating configuration...")
98
+ generated_config = generate_complete_config(
99
+ host="localhost",
100
+ port=8080
101
+ )
102
+
103
+ # Create temporary test files
104
+ temp_dir = Path(tempfile.mkdtemp())
105
+ test_files = {}
106
+
107
+ # Modify config based on test parameters
108
+ if test_config["protocol"] != "http":
109
+ generated_config["server"]["protocol"] = test_config["protocol"]
110
+
111
+ if test_config["ssl_enabled"]:
112
+ generated_config["ssl"]["enabled"] = True
113
+ # Create test SSL certificates
114
+ cert_file = temp_dir / "test_cert.crt"
115
+ key_file = temp_dir / "test_key.key"
116
+ ca_cert = temp_dir / "test_ca.crt"
117
+
118
+ # Create dummy certificate files
119
+ cert_file.write_text("-----BEGIN CERTIFICATE-----\nDUMMY CERT\n-----END CERTIFICATE-----")
120
+ key_file.write_text("-----BEGIN PRIVATE KEY-----\nDUMMY KEY\n-----END PRIVATE KEY-----")
121
+ ca_cert.write_text("-----BEGIN CERTIFICATE-----\nDUMMY CA\n-----END CERTIFICATE-----")
122
+
123
+ generated_config["ssl"]["cert_file"] = str(cert_file)
124
+ generated_config["ssl"]["key_file"] = str(key_file)
125
+ generated_config["ssl"]["ca_cert"] = str(ca_cert)
126
+
127
+ test_files["ssl"] = [cert_file, key_file, ca_cert]
128
+
129
+ if test_config["security_enabled"]:
130
+ generated_config["security"]["enabled"] = True
131
+ generated_config["security"]["tokens"] = {
132
+ "test_token": {"permissions": ["*"]}
133
+ }
134
+
135
+ if test_config["roles_enabled"]:
136
+ generated_config["roles"]["enabled"] = True
137
+ roles_file = temp_dir / "test_roles.json"
138
+ roles_file.write_text('{"admin": ["*"], "user": ["read"]}')
139
+ generated_config["roles"]["config_file"] = str(roles_file)
140
+ test_files["roles"] = [roles_file]
141
+
142
+ if test_config["proxy_registration_enabled"]:
143
+ generated_config["proxy_registration"]["enabled"] = True
144
+ generated_config["proxy_registration"]["proxy_url"] = "http://localhost:3005"
145
+
146
+ # Create test client certificates
147
+ client_cert = temp_dir / "test_client.crt"
148
+ client_key = temp_dir / "test_client.key"
149
+ client_cert.write_text("-----BEGIN CERTIFICATE-----\nDUMMY CLIENT CERT\n-----END CERTIFICATE-----")
150
+ client_key.write_text("-----BEGIN PRIVATE KEY-----\nDUMMY CLIENT KEY\n-----END PRIVATE KEY-----")
151
+
152
+ generated_config["proxy_registration"]["certificate"] = {
153
+ "cert_file": str(client_cert),
154
+ "key_file": str(client_key)
155
+ }
156
+ generated_config["proxy_registration"]["ssl"] = {
157
+ "ca_cert": str(ca_cert) if test_config["ssl_enabled"] else str(temp_dir / "test_ca.crt")
158
+ }
159
+
160
+ if "proxy" not in test_files:
161
+ test_files["proxy"] = []
162
+ test_files["proxy"].extend([client_cert, client_key])
163
+
164
+ # Validate configuration
165
+ print(" ✅ Validating configuration...")
166
+ validator = ConfigValidator()
167
+ validator.config_data = generated_config
168
+ validation_results = validator.validate_config()
169
+
170
+ # Analyze results
171
+ errors = [r for r in validation_results if r.level == "error"]
172
+ warnings = [r for r in validation_results if r.level == "warning"]
173
+ info = [r for r in validation_results if r.level == "info"]
174
+
175
+ result = {
176
+ "name": test_config["name"],
177
+ "success": len(errors) == 0,
178
+ "errors": len(errors),
179
+ "warnings": len(warnings),
180
+ "info": len(info),
181
+ "error_details": errors,
182
+ "warning_details": warnings
183
+ }
184
+
185
+ results.append(result)
186
+
187
+ # Clean up temporary files
188
+ try:
189
+ shutil.rmtree(temp_dir)
190
+ except Exception as e:
191
+ print(f" ⚠️ Warning: Could not clean up temp files: {e}")
192
+
193
+ # Print results
194
+ if result["success"]:
195
+ print(f" ✅ PASS - {len(warnings)} warnings, {len(info)} info")
196
+ else:
197
+ print(f" ❌ FAIL - {len(errors)} errors, {len(warnings)} warnings")
198
+ for error in errors[:3]: # Show first 3 errors
199
+ print(f" • {error.message}")
200
+ if len(errors) > 3:
201
+ print(f" ... and {len(errors) - 3} more errors")
202
+
203
+ except Exception as e:
204
+ print(f" 💥 EXCEPTION: {str(e)}")
205
+ results.append({
206
+ "name": test_config["name"],
207
+ "success": False,
208
+ "errors": 1,
209
+ "warnings": 0,
210
+ "info": 0,
211
+ "error_details": [f"Exception: {str(e)}"],
212
+ "warning_details": []
213
+ })
214
+
215
+ # Summary
216
+ print("\n" + "=" * 50)
217
+ print("📊 COMPATIBILITY SUMMARY")
218
+ print("=" * 50)
219
+
220
+ total_tests = len(results)
221
+ passed_tests = sum(1 for r in results if r["success"])
222
+ failed_tests = total_tests - passed_tests
223
+
224
+ print(f"Total tests: {total_tests}")
225
+ print(f"Passed: {passed_tests}")
226
+ print(f"Failed: {failed_tests}")
227
+ print(f"Success rate: {(passed_tests/total_tests)*100:.1f}%")
228
+
229
+ if failed_tests > 0:
230
+ print("\n❌ FAILED TESTS:")
231
+ for result in results:
232
+ if not result["success"]:
233
+ print(f" • {result['name']}: {result['errors']} errors")
234
+ for error in result["error_details"][:2]:
235
+ print(f" - {error}")
236
+
237
+ return results
238
+
239
+
240
+ def test_validation_coverage():
241
+ """Test that validator covers all generator features."""
242
+ print("\n🔍 Testing Validation Coverage")
243
+ print("=" * 50)
244
+
245
+ # Test that validator checks all required sections
246
+ required_sections = [
247
+ "server", "logging", "commands", "debug"
248
+ ]
249
+
250
+ optional_sections = [
251
+ "ssl", "security", "roles", "proxy_registration", "transport"
252
+ ]
253
+
254
+ print("📋 Required sections validation:")
255
+ for section in required_sections:
256
+ print(f" ✅ {section}")
257
+
258
+ print("\n📋 Optional sections validation:")
259
+ for section in optional_sections:
260
+ print(f" ✅ {section}")
261
+
262
+ return True
263
+
264
+
265
+ def test_edge_cases():
266
+ """Test edge cases and error conditions."""
267
+ print("\n🔍 Testing Edge Cases")
268
+ print("=" * 50)
269
+
270
+ edge_cases = [
271
+ {
272
+ "name": "Empty config",
273
+ "config": {},
274
+ "should_fail": True
275
+ },
276
+ {
277
+ "name": "Missing server section",
278
+ "config": {"logging": {"level": "INFO"}},
279
+ "should_fail": True
280
+ },
281
+ {
282
+ "name": "Invalid protocol",
283
+ "config": {
284
+ "server": {"protocol": "invalid", "host": "localhost", "port": 8080},
285
+ "logging": {"level": "INFO"},
286
+ "commands": {"enabled": True},
287
+ "debug": {"enabled": False}
288
+ },
289
+ "should_fail": True
290
+ },
291
+ {
292
+ "name": "SSL enabled without certificates",
293
+ "config": {
294
+ "server": {"protocol": "https", "host": "localhost", "port": 8080},
295
+ "ssl": {"enabled": True},
296
+ "logging": {"level": "INFO"},
297
+ "commands": {"enabled": True},
298
+ "debug": {"enabled": False}
299
+ },
300
+ "should_fail": True
301
+ }
302
+ ]
303
+
304
+ results = []
305
+
306
+ for case in edge_cases:
307
+ print(f"\n🧪 Testing: {case['name']}")
308
+
309
+ try:
310
+ validator = ConfigValidator()
311
+ validator.config_data = case["config"]
312
+ validation_results = validator.validate_config()
313
+
314
+ errors = [r for r in validation_results if r.level == "error"]
315
+ has_errors = len(errors) > 0
316
+
317
+ expected_failure = case["should_fail"]
318
+ test_passed = (has_errors == expected_failure)
319
+
320
+ if test_passed:
321
+ print(f" ✅ PASS - {'Correctly failed' if has_errors else 'Correctly passed'}")
322
+ else:
323
+ print(f" ❌ FAIL - Expected {'failure' if expected_failure else 'success'}, got {'failure' if has_errors else 'success'}")
324
+
325
+ results.append({
326
+ "name": case["name"],
327
+ "passed": test_passed,
328
+ "errors": len(errors)
329
+ })
330
+
331
+ except Exception as e:
332
+ print(f" 💥 EXCEPTION: {str(e)}")
333
+ results.append({
334
+ "name": case["name"],
335
+ "passed": False,
336
+ "errors": 1
337
+ })
338
+
339
+ return results
340
+
341
+
342
+ def main():
343
+ """Main test function."""
344
+ print("🚀 Generator-Validator Compatibility Test")
345
+ print("=" * 60)
346
+
347
+ try:
348
+ # Test 1: Generator-Validator compatibility
349
+ compatibility_results = test_generator_validator_compatibility()
350
+
351
+ # Test 2: Validation coverage
352
+ test_validation_coverage()
353
+
354
+ # Test 3: Edge cases
355
+ edge_case_results = test_edge_cases()
356
+
357
+ # Final summary
358
+ print("\n" + "=" * 60)
359
+ print("🎯 FINAL RESULTS")
360
+ print("=" * 60)
361
+
362
+ compatibility_passed = sum(1 for r in compatibility_results if r["success"])
363
+ edge_cases_passed = sum(1 for r in edge_case_results if r["passed"])
364
+
365
+ print(f"Compatibility tests: {compatibility_passed}/{len(compatibility_results)} passed")
366
+ print(f"Edge case tests: {edge_cases_passed}/{len(edge_case_results)} passed")
367
+
368
+ total_passed = compatibility_passed + edge_cases_passed
369
+ total_tests = len(compatibility_results) + len(edge_case_results)
370
+
371
+ print(f"Overall: {total_passed}/{total_tests} tests passed")
372
+
373
+ if total_passed == total_tests:
374
+ print("🎉 ALL TESTS PASSED! Generator and validator are compatible.")
375
+ return 0
376
+ else:
377
+ print("❌ Some tests failed. Check the output above for details.")
378
+ return 1
379
+
380
+ except Exception as e:
381
+ print(f"💥 Test suite failed with exception: {str(e)}")
382
+ return 1
383
+
384
+
385
+ if __name__ == "__main__":
386
+ sys.exit(main())
@@ -0,0 +1,248 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simple compatibility test between config generator and validator.
4
+ Tests only the structure and required fields, not file existence or certificate validity.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ import json
11
+ import sys
12
+ from pathlib import Path
13
+ from typing import Dict, Any, List
14
+
15
+ # Add the project root to the path
16
+ project_root = Path(__file__).parent.parent.parent
17
+ sys.path.insert(0, str(project_root))
18
+
19
+ from mcp_proxy_adapter.core.config_validator import ConfigValidator
20
+ from mcp_proxy_adapter.examples.config_builder import generate_complete_config
21
+
22
+
23
+ def test_generator_validator_structure():
24
+ """Test that generated configs have the correct structure."""
25
+ print("🔍 Testing Generator-Validator Structure Compatibility")
26
+ print("=" * 60)
27
+
28
+ # Test basic HTTP configuration
29
+ print("\n📋 Testing: HTTP Basic Configuration")
30
+ print("-" * 40)
31
+
32
+ try:
33
+ # Generate configuration
34
+ print(" 🔧 Generating configuration...")
35
+ config = generate_complete_config(host="localhost", port=8080)
36
+
37
+ # Check required sections exist
38
+ required_sections = ["server", "logging", "commands", "debug", "ssl", "security", "roles", "proxy_registration"]
39
+ missing_sections = []
40
+
41
+ for section in required_sections:
42
+ if section not in config:
43
+ missing_sections.append(section)
44
+
45
+ if missing_sections:
46
+ print(f" ❌ FAIL - Missing sections: {missing_sections}")
47
+ return False
48
+
49
+ # Check server section
50
+ server_required = ["host", "port", "protocol", "debug", "log_level"]
51
+ server_missing = [key for key in server_required if key not in config["server"]]
52
+
53
+ if server_missing:
54
+ print(f" ❌ FAIL - Server section missing keys: {server_missing}")
55
+ return False
56
+
57
+ # Check protocol is HTTP
58
+ if config["server"]["protocol"] != "http":
59
+ print(f" ❌ FAIL - Expected protocol 'http', got '{config['server']['protocol']}'")
60
+ return False
61
+
62
+ # Check SSL is disabled
63
+ if config["ssl"]["enabled"] != False:
64
+ print(f" ❌ FAIL - Expected SSL disabled, got {config['ssl']['enabled']}")
65
+ return False
66
+
67
+ # Check security is disabled
68
+ if config["security"]["enabled"] != False:
69
+ print(f" ❌ FAIL - Expected security disabled, got {config['security']['enabled']}")
70
+ return False
71
+
72
+ # Check roles is disabled
73
+ if config["roles"]["enabled"] != False:
74
+ print(f" ❌ FAIL - Expected roles disabled, got {config['roles']['enabled']}")
75
+ return False
76
+
77
+ # Check proxy registration is disabled
78
+ if config["proxy_registration"]["enabled"] != False:
79
+ print(f" ❌ FAIL - Expected proxy registration disabled, got {config['proxy_registration']['enabled']}")
80
+ return False
81
+
82
+ print(" ✅ PASS - All required sections and fields present")
83
+ print(" ✅ PASS - All features correctly disabled")
84
+ print(" ✅ PASS - Protocol correctly set to HTTP")
85
+
86
+ return True
87
+
88
+ except Exception as e:
89
+ print(f" 💥 EXCEPTION: {str(e)}")
90
+ return False
91
+
92
+
93
+ def test_config_modification():
94
+ """Test that we can modify generated configs for different scenarios."""
95
+ print("\n📋 Testing: Configuration Modification")
96
+ print("-" * 40)
97
+
98
+ try:
99
+ # Generate base config
100
+ config = generate_complete_config(host="localhost", port=8080)
101
+
102
+ # Test 1: Enable HTTPS
103
+ print(" 🔧 Testing HTTPS modification...")
104
+ config["server"]["protocol"] = "https"
105
+ config["ssl"]["enabled"] = True
106
+
107
+ if config["server"]["protocol"] != "https":
108
+ print(" ❌ FAIL - Could not change protocol to HTTPS")
109
+ return False
110
+
111
+ if config["ssl"]["enabled"] != True:
112
+ print(" ❌ FAIL - Could not enable SSL")
113
+ return False
114
+
115
+ print(" ✅ PASS - HTTPS modification successful")
116
+
117
+ # Test 2: Enable security
118
+ print(" 🔧 Testing security modification...")
119
+ config["security"]["enabled"] = True
120
+ config["security"]["tokens"] = {"test_token": {"permissions": ["*"]}}
121
+
122
+ if config["security"]["enabled"] != True:
123
+ print(" ❌ FAIL - Could not enable security")
124
+ return False
125
+
126
+ if "tokens" not in config["security"]:
127
+ print(" ❌ FAIL - Could not add tokens")
128
+ return False
129
+
130
+ print(" ✅ PASS - Security modification successful")
131
+
132
+ # Test 3: Enable roles
133
+ print(" 🔧 Testing roles modification...")
134
+ config["roles"]["enabled"] = True
135
+ config["roles"]["config_file"] = "./test_roles.json"
136
+
137
+ if config["roles"]["enabled"] != True:
138
+ print(" ❌ FAIL - Could not enable roles")
139
+ return False
140
+
141
+ if config["roles"]["config_file"] != "./test_roles.json":
142
+ print(" ❌ FAIL - Could not set roles config file")
143
+ return False
144
+
145
+ print(" ✅ PASS - Roles modification successful")
146
+
147
+ return True
148
+
149
+ except Exception as e:
150
+ print(f" 💥 EXCEPTION: {str(e)}")
151
+ return False
152
+
153
+
154
+ def test_validator_accepts_generated_config():
155
+ """Test that validator accepts the basic generated config without file checks."""
156
+ print("\n📋 Testing: Validator Accepts Generated Config")
157
+ print("-" * 40)
158
+
159
+ try:
160
+ # Generate config
161
+ config = generate_complete_config(host="localhost", port=8080)
162
+
163
+ # Create a mock validator that doesn't check files
164
+ class MockValidator(ConfigValidator):
165
+ def _validate_file_existence(self):
166
+ """Skip file existence checks for testing."""
167
+ pass
168
+
169
+ def _validate_certificate_file(self, cert_file, section, key):
170
+ """Skip certificate validation for testing."""
171
+ pass
172
+
173
+ def _validate_key_file(self, key_file, section, key):
174
+ """Skip key validation for testing."""
175
+ pass
176
+
177
+ def _validate_ca_certificate_file(self, ca_cert_file, section, key):
178
+ """Skip CA certificate validation for testing."""
179
+ pass
180
+
181
+ # Validate with mock validator
182
+ validator = MockValidator()
183
+ validator.config_data = config
184
+ results = validator.validate_config()
185
+
186
+ errors = [r for r in results if r.level == "error"]
187
+ warnings = [r for r in results if r.level == "warning"]
188
+
189
+ if len(errors) > 0:
190
+ print(f" ❌ FAIL - {len(errors)} validation errors:")
191
+ for error in errors[:3]:
192
+ print(f" • {error.message}")
193
+ return False
194
+
195
+ print(f" ✅ PASS - No validation errors ({len(warnings)} warnings)")
196
+ return True
197
+
198
+ except Exception as e:
199
+ print(f" 💥 EXCEPTION: {str(e)}")
200
+ return False
201
+
202
+
203
+ def main():
204
+ """Main test function."""
205
+ print("🚀 Generator-Validator Structure Compatibility Test")
206
+ print("=" * 70)
207
+
208
+ tests = [
209
+ ("Structure Test", test_generator_validator_structure),
210
+ ("Modification Test", test_config_modification),
211
+ ("Validator Acceptance Test", test_validator_accepts_generated_config)
212
+ ]
213
+
214
+ results = []
215
+
216
+ for test_name, test_func in tests:
217
+ print(f"\n🧪 Running: {test_name}")
218
+ try:
219
+ result = test_func()
220
+ results.append((test_name, result))
221
+ except Exception as e:
222
+ print(f" 💥 Test failed with exception: {str(e)}")
223
+ results.append((test_name, False))
224
+
225
+ # Summary
226
+ print("\n" + "=" * 70)
227
+ print("🎯 FINAL RESULTS")
228
+ print("=" * 70)
229
+
230
+ passed = sum(1 for _, result in results if result)
231
+ total = len(results)
232
+
233
+ print(f"Tests passed: {passed}/{total}")
234
+
235
+ for test_name, result in results:
236
+ status = "✅ PASS" if result else "❌ FAIL"
237
+ print(f" {status} - {test_name}")
238
+
239
+ if passed == total:
240
+ print("\n🎉 ALL TESTS PASSED! Generator and validator are structurally compatible.")
241
+ return 0
242
+ else:
243
+ print(f"\n❌ {total - passed} tests failed. Check the output above for details.")
244
+ return 1
245
+
246
+
247
+ if __name__ == "__main__":
248
+ sys.exit(main())
mcp_proxy_adapter/main.py CHANGED
@@ -49,6 +49,9 @@ def main():
49
49
  else:
50
50
  config = Config()
51
51
 
52
+ # Load configuration from file
53
+ config.load_config()
54
+
52
55
  # Validate UUID configuration (mandatory)
53
56
  validator = ConfigValidator(config.get_all())
54
57
  if not validator.validate_all():
@@ -2,4 +2,4 @@
2
2
  Version information for MCP Proxy Adapter.
3
3
  """
4
4
 
5
- __version__ = "6.9.17"
5
+ __version__ = "6.9.19"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-proxy-adapter
3
- Version: 6.9.17
3
+ Version: 6.9.19
4
4
  Summary: Powerful JSON-RPC microservices framework with built-in security, authentication, and proxy registration
5
5
  Home-page: https://github.com/maverikod/mcp-proxy-adapter
6
6
  Author: Vasiliy Zdanovskiy