mcp-proxy-adapter 6.3.4__py3-none-any.whl โ 6.3.5__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.
- mcp_proxy_adapter/__init__.py +9 -5
- mcp_proxy_adapter/__main__.py +1 -1
- mcp_proxy_adapter/api/app.py +227 -176
- mcp_proxy_adapter/api/handlers.py +68 -60
- mcp_proxy_adapter/api/middleware/__init__.py +7 -5
- mcp_proxy_adapter/api/middleware/base.py +19 -16
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
- mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
- mcp_proxy_adapter/api/middleware/factory.py +50 -52
- mcp_proxy_adapter/api/middleware/logging.py +46 -30
- mcp_proxy_adapter/api/middleware/performance.py +19 -16
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
- mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
- mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
- mcp_proxy_adapter/api/schemas.py +69 -43
- mcp_proxy_adapter/api/tool_integration.py +83 -63
- mcp_proxy_adapter/api/tools.py +60 -50
- mcp_proxy_adapter/commands/__init__.py +15 -6
- mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
- mcp_proxy_adapter/commands/base.py +108 -112
- mcp_proxy_adapter/commands/builtin_commands.py +28 -18
- mcp_proxy_adapter/commands/catalog_manager.py +394 -265
- mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
- mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
- mcp_proxy_adapter/commands/command_registry.py +275 -226
- mcp_proxy_adapter/commands/config_command.py +48 -33
- mcp_proxy_adapter/commands/dependency_container.py +22 -23
- mcp_proxy_adapter/commands/dependency_manager.py +65 -56
- mcp_proxy_adapter/commands/echo_command.py +15 -15
- mcp_proxy_adapter/commands/health_command.py +31 -29
- mcp_proxy_adapter/commands/help_command.py +97 -61
- mcp_proxy_adapter/commands/hooks.py +65 -49
- mcp_proxy_adapter/commands/key_management_command.py +148 -147
- mcp_proxy_adapter/commands/load_command.py +58 -40
- mcp_proxy_adapter/commands/plugins_command.py +80 -54
- mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
- mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
- mcp_proxy_adapter/commands/reload_command.py +43 -37
- mcp_proxy_adapter/commands/result.py +26 -33
- mcp_proxy_adapter/commands/role_test_command.py +26 -26
- mcp_proxy_adapter/commands/roles_management_command.py +176 -173
- mcp_proxy_adapter/commands/security_command.py +134 -122
- mcp_proxy_adapter/commands/settings_command.py +47 -56
- mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
- mcp_proxy_adapter/commands/token_management_command.py +129 -158
- mcp_proxy_adapter/commands/transport_management_command.py +41 -36
- mcp_proxy_adapter/commands/unload_command.py +42 -37
- mcp_proxy_adapter/config.py +36 -35
- mcp_proxy_adapter/core/__init__.py +19 -21
- mcp_proxy_adapter/core/app_factory.py +30 -9
- mcp_proxy_adapter/core/app_runner.py +81 -64
- mcp_proxy_adapter/core/auth_validator.py +176 -182
- mcp_proxy_adapter/core/certificate_utils.py +469 -426
- mcp_proxy_adapter/core/client.py +155 -126
- mcp_proxy_adapter/core/client_manager.py +60 -54
- mcp_proxy_adapter/core/client_security.py +108 -88
- mcp_proxy_adapter/core/config_converter.py +176 -143
- mcp_proxy_adapter/core/config_validator.py +12 -4
- mcp_proxy_adapter/core/crl_utils.py +21 -7
- mcp_proxy_adapter/core/errors.py +64 -20
- mcp_proxy_adapter/core/logging.py +34 -29
- mcp_proxy_adapter/core/mtls_asgi.py +29 -25
- mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
- mcp_proxy_adapter/core/protocol_manager.py +154 -104
- mcp_proxy_adapter/core/proxy_client.py +202 -144
- mcp_proxy_adapter/core/proxy_registration.py +7 -3
- mcp_proxy_adapter/core/role_utils.py +139 -125
- mcp_proxy_adapter/core/security_adapter.py +88 -77
- mcp_proxy_adapter/core/security_factory.py +50 -44
- mcp_proxy_adapter/core/security_integration.py +72 -24
- mcp_proxy_adapter/core/server_adapter.py +68 -64
- mcp_proxy_adapter/core/server_engine.py +71 -53
- mcp_proxy_adapter/core/settings.py +68 -58
- mcp_proxy_adapter/core/ssl_utils.py +69 -56
- mcp_proxy_adapter/core/transport_manager.py +72 -60
- mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
- mcp_proxy_adapter/core/utils.py +4 -2
- mcp_proxy_adapter/custom_openapi.py +107 -99
- mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/commands/__init__.py +1 -1
- mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
- mcp_proxy_adapter/examples/debug_request_state.py +38 -19
- mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
- mcp_proxy_adapter/examples/demo_client.py +48 -36
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
- mcp_proxy_adapter/examples/generate_certificates.py +31 -16
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
- mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
- mcp_proxy_adapter/examples/run_example.py +23 -5
- mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
- mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
- mcp_proxy_adapter/examples/run_security_tests.py +103 -41
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
- mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/security_test_client.py +196 -127
- mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
- mcp_proxy_adapter/examples/test_config.py +19 -4
- mcp_proxy_adapter/examples/test_config_generator.py +23 -7
- mcp_proxy_adapter/examples/test_examples.py +84 -56
- mcp_proxy_adapter/examples/universal_client.py +119 -62
- mcp_proxy_adapter/openapi.py +108 -115
- mcp_proxy_adapter/utils/config_generator.py +429 -274
- mcp_proxy_adapter/version.py +1 -2
- {mcp_proxy_adapter-6.3.4.dist-info โ mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
- mcp_proxy_adapter-6.3.4.dist-info/RECORD +0 -143
- {mcp_proxy_adapter-6.3.4.dist-info โ mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info โ mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info โ mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info โ mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -16,6 +16,7 @@ import shutil
|
|
16
16
|
import sys
|
17
17
|
import argparse
|
18
18
|
from pathlib import Path
|
19
|
+
|
19
20
|
# Import mcp_security_framework
|
20
21
|
try:
|
21
22
|
from mcp_security_framework.core.cert_manager import CertificateManager
|
@@ -25,6 +26,7 @@ try:
|
|
25
26
|
ServerCertConfig,
|
26
27
|
ClientCertConfig,
|
27
28
|
)
|
29
|
+
|
28
30
|
SECURITY_FRAMEWORK_AVAILABLE = True
|
29
31
|
except ImportError:
|
30
32
|
SECURITY_FRAMEWORK_AVAILABLE = False
|
@@ -60,7 +62,7 @@ def setup_test_environment(output_dir: Path) -> None:
|
|
60
62
|
"certs",
|
61
63
|
"keys",
|
62
64
|
"tokens",
|
63
|
-
"logs"
|
65
|
+
"logs",
|
64
66
|
]
|
65
67
|
for directory in directories:
|
66
68
|
target_dir = output_dir / directory
|
@@ -111,11 +113,7 @@ def setup_test_environment(output_dir: Path) -> None:
|
|
111
113
|
if roles_configs_src.exists():
|
112
114
|
shutil.copy2(roles_configs_src, output_dir / "roles.json")
|
113
115
|
print("โ
Updated roles.json from configs directory")
|
114
|
-
print(
|
115
|
-
"๐ Test environment setup completed successfully at: {}".format(
|
116
|
-
output_dir
|
117
|
-
)
|
118
|
-
)
|
116
|
+
print("๐ Test environment setup completed successfully at: {}".format(output_dir))
|
119
117
|
|
120
118
|
|
121
119
|
def generate_certificates_with_framework(output_dir: Path) -> bool:
|
@@ -123,15 +121,10 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
|
|
123
121
|
Generate certificates using mcp_security_framework.
|
124
122
|
"""
|
125
123
|
if not SECURITY_FRAMEWORK_AVAILABLE:
|
126
|
-
print(
|
127
|
-
"โ mcp_security_framework not available for certificate "
|
128
|
-
"generation"
|
129
|
-
)
|
124
|
+
print("โ mcp_security_framework not available for certificate " "generation")
|
130
125
|
return False
|
131
126
|
try:
|
132
|
-
print(
|
133
|
-
"๐ Generating certificates using mcp_security_framework..."
|
134
|
-
)
|
127
|
+
print("๐ Generating certificates using mcp_security_framework...")
|
135
128
|
# Configure certificate manager
|
136
129
|
cert_config = CertificateConfig(
|
137
130
|
cert_storage_path=str((output_dir / "certs").resolve()),
|
@@ -155,9 +148,7 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
|
|
155
148
|
)
|
156
149
|
cert_pair = cert_manager.create_root_ca(ca_config)
|
157
150
|
if not cert_pair or not cert_pair.certificate_path:
|
158
|
-
print(
|
159
|
-
"โ Failed to create CA certificate: Invalid certificate pair"
|
160
|
-
)
|
151
|
+
print("โ Failed to create CA certificate: Invalid certificate pair")
|
161
152
|
return False
|
162
153
|
print("โ
CA certificate created successfully")
|
163
154
|
# Find CA key file
|
@@ -182,10 +173,7 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
|
|
182
173
|
)
|
183
174
|
cert_pair = cert_manager.create_server_certificate(server_config)
|
184
175
|
if not cert_pair or not cert_pair.certificate_path:
|
185
|
-
print(
|
186
|
-
"โ Failed to create server certificate: Invalid certificate "
|
187
|
-
"pair"
|
188
|
-
)
|
176
|
+
print("โ Failed to create server certificate: Invalid certificate " "pair")
|
189
177
|
return False
|
190
178
|
print("โ
Server certificate created successfully")
|
191
179
|
# Generate client certificates
|
@@ -239,7 +227,7 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
|
|
239
227
|
roles=roles,
|
240
228
|
permissions=permissions,
|
241
229
|
ca_cert_path=cert_pair.certificate_path,
|
242
|
-
ca_key_path=ca_key_path
|
230
|
+
ca_key_path=ca_key_path,
|
243
231
|
)
|
244
232
|
cert_pair = cert_manager.create_client_certificate(client_config)
|
245
233
|
if not cert_pair or not cert_pair.certificate_path:
|
@@ -250,11 +238,7 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
|
|
250
238
|
).format(client_name)
|
251
239
|
)
|
252
240
|
return False
|
253
|
-
print(
|
254
|
-
"โ
Client certificate {} created successfully".format(
|
255
|
-
client_name
|
256
|
-
)
|
257
|
-
)
|
241
|
+
print("โ
Client certificate {} created successfully".format(client_name))
|
258
242
|
print(
|
259
243
|
"๐ All certificates generated successfully using "
|
260
244
|
"mcp_security_framework!"
|
@@ -307,19 +291,23 @@ def main() -> int:
|
|
307
291
|
print("2. Verify mcp_security_framework installation")
|
308
292
|
print("3. Check available disk space")
|
309
293
|
return 1
|
310
|
-
|
294
|
+
|
311
295
|
print("\n" + "=" * 60)
|
312
296
|
print("โ
TEST ENVIRONMENT SETUP COMPLETED SUCCESSFULLY")
|
313
297
|
print("=" * 60)
|
314
298
|
print("\n๐ NEXT STEPS:")
|
315
299
|
print("1. Generate test configurations:")
|
316
|
-
print(
|
300
|
+
print(
|
301
|
+
" python -m mcp_proxy_adapter.examples.generate_test_configs --output-dir configs"
|
302
|
+
)
|
317
303
|
print("\n2. Generate additional certificates (if needed):")
|
318
304
|
print(" python -m mcp_proxy_adapter.examples.generate_certificates")
|
319
305
|
print("\n3. Run security tests:")
|
320
306
|
print(" python -m mcp_proxy_adapter.examples.run_security_tests")
|
321
307
|
print("\n4. Start basic framework example:")
|
322
|
-
print(
|
308
|
+
print(
|
309
|
+
" python -m mcp_proxy_adapter.examples.basic_framework.main --config configs/https_simple.json"
|
310
|
+
)
|
323
311
|
print("=" * 60)
|
324
312
|
return 0
|
325
313
|
|
@@ -14,16 +14,20 @@ import time
|
|
14
14
|
import subprocess
|
15
15
|
from pathlib import Path
|
16
16
|
from typing import Dict, Any, Optional
|
17
|
+
|
17
18
|
# Import mcp_security_framework
|
18
19
|
try:
|
19
20
|
from mcp_security_framework import SecurityManager
|
20
21
|
from mcp_security_framework.schemas.config import SecurityConfig
|
22
|
+
|
21
23
|
SECURITY_FRAMEWORK_AVAILABLE = True
|
22
24
|
except ImportError:
|
23
25
|
SECURITY_FRAMEWORK_AVAILABLE = False
|
24
26
|
print("Warning: mcp_security_framework not available")
|
25
27
|
# Add parent directory to path to import mcp_proxy_adapter
|
26
28
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../.."))
|
29
|
+
|
30
|
+
|
27
31
|
def validate_security_config(config: Dict[str, Any]) -> bool:
|
28
32
|
"""
|
29
33
|
Validate security configuration using mcp_security_framework.
|
@@ -46,7 +50,7 @@ def validate_security_config(config: Dict[str, Any]) -> bool:
|
|
46
50
|
auth=security_section.get("auth", {}),
|
47
51
|
ssl=security_section.get("ssl", {}),
|
48
52
|
permissions=security_section.get("permissions", {}),
|
49
|
-
rate_limit=security_section.get("rate_limit", {})
|
53
|
+
rate_limit=security_section.get("rate_limit", {}),
|
50
54
|
)
|
51
55
|
# Create SecurityManager for validation
|
52
56
|
security_manager = SecurityManager(security_config)
|
@@ -63,6 +67,8 @@ def validate_security_config(config: Dict[str, Any]) -> bool:
|
|
63
67
|
except Exception as e:
|
64
68
|
print(f"โ Error validating security configuration: {e}")
|
65
69
|
return False
|
70
|
+
|
71
|
+
|
66
72
|
def test_configuration(config_path: str, timeout: int = 30) -> bool:
|
67
73
|
"""
|
68
74
|
Test a configuration by creating an application and validating it.
|
@@ -76,11 +82,12 @@ def test_configuration(config_path: str, timeout: int = 30) -> bool:
|
|
76
82
|
print("=" * 60)
|
77
83
|
try:
|
78
84
|
# Load configuration
|
79
|
-
with open(config_path,
|
85
|
+
with open(config_path, "r") as f:
|
80
86
|
config = json.load(f)
|
81
87
|
# Import required modules
|
82
88
|
from mcp_proxy_adapter.core.app_factory import create_application
|
83
89
|
from mcp_proxy_adapter.core.app_runner import ApplicationRunner
|
90
|
+
|
84
91
|
# Create application
|
85
92
|
print("๐ง Creating application...")
|
86
93
|
app = create_application(config)
|
@@ -133,16 +140,24 @@ def test_configuration(config_path: str, timeout: int = 30) -> bool:
|
|
133
140
|
except Exception as e:
|
134
141
|
print(f"โ Configuration test failed: {e}")
|
135
142
|
return False
|
143
|
+
|
144
|
+
|
136
145
|
def main():
|
137
146
|
"""Main function for command line execution."""
|
138
147
|
parser = argparse.ArgumentParser(description="Test MCP Proxy Adapter configuration")
|
139
|
-
parser.add_argument(
|
140
|
-
|
148
|
+
parser.add_argument(
|
149
|
+
"--config", "-c", required=True, help="Path to configuration file"
|
150
|
+
)
|
151
|
+
parser.add_argument(
|
152
|
+
"--timeout", "-t", type=int, default=30, help="Timeout in seconds"
|
153
|
+
)
|
141
154
|
args = parser.parse_args()
|
142
155
|
if not os.path.exists(args.config):
|
143
156
|
print(f"โ Configuration file not found: {args.config}")
|
144
157
|
return 1
|
145
158
|
success = test_configuration(args.config, args.timeout)
|
146
159
|
return 0 if success else 1
|
160
|
+
|
161
|
+
|
147
162
|
if __name__ == "__main__":
|
148
163
|
exit(main())
|
@@ -7,10 +7,13 @@ configurations with the new protocols section and fixes for ProtocolMiddleware i
|
|
7
7
|
import sys
|
8
8
|
import json
|
9
9
|
from pathlib import Path
|
10
|
+
|
10
11
|
# Add the project root to the path
|
11
12
|
project_root = Path(__file__).parent.parent.parent
|
12
13
|
sys.path.insert(0, str(project_root))
|
13
14
|
from mcp_proxy_adapter.utils.config_generator import ConfigGenerator
|
15
|
+
|
16
|
+
|
14
17
|
def test_config_generator():
|
15
18
|
"""Test the configuration generator with different types."""
|
16
19
|
generator = ConfigGenerator()
|
@@ -22,7 +25,7 @@ def test_config_generator():
|
|
22
25
|
"https_token",
|
23
26
|
"https_no_protocol_middleware",
|
24
27
|
"mtls",
|
25
|
-
"mtls_no_protocol_middleware"
|
28
|
+
"mtls_no_protocol_middleware",
|
26
29
|
]
|
27
30
|
print("Testing Configuration Generator")
|
28
31
|
print("=" * 50)
|
@@ -37,17 +40,26 @@ def test_config_generator():
|
|
37
40
|
protocols = config["protocols"]
|
38
41
|
print(f"โ
Protocols section found:")
|
39
42
|
print(f" - enabled: {protocols.get('enabled', 'NOT SET')}")
|
40
|
-
print(
|
41
|
-
|
43
|
+
print(
|
44
|
+
f" - allowed_protocols: {protocols.get('allowed_protocols', 'NOT SET')}"
|
45
|
+
)
|
46
|
+
print(
|
47
|
+
f" - default_protocol: {protocols.get('default_protocol', 'NOT SET')}"
|
48
|
+
)
|
42
49
|
else:
|
43
50
|
print("โ Protocols section missing!")
|
44
51
|
# Check SSL configuration
|
45
52
|
ssl_enabled = config.get("ssl", {}).get("enabled", False)
|
46
|
-
security_ssl_enabled =
|
53
|
+
security_ssl_enabled = (
|
54
|
+
config.get("security", {}).get("ssl", {}).get("enabled", False)
|
55
|
+
)
|
47
56
|
print(f" - legacy ssl.enabled: {ssl_enabled}")
|
48
57
|
print(f" - security.ssl.enabled: {security_ssl_enabled}")
|
49
58
|
# Check if configuration is valid for its type
|
50
|
-
if
|
59
|
+
if (
|
60
|
+
config_type == "https_no_protocol_middleware"
|
61
|
+
or config_type == "mtls_no_protocol_middleware"
|
62
|
+
):
|
51
63
|
if protocols.get("enabled") == False:
|
52
64
|
print("โ
ProtocolMiddleware correctly disabled")
|
53
65
|
else:
|
@@ -59,13 +71,15 @@ def test_config_generator():
|
|
59
71
|
print("โ ProtocolMiddleware should be enabled but is disabled")
|
60
72
|
# Save configuration to file for inspection
|
61
73
|
output_file = f"test_config_{config_type}.json"
|
62
|
-
with open(output_file,
|
74
|
+
with open(output_file, "w") as f:
|
63
75
|
json.dump(config, f, indent=2)
|
64
76
|
print(f" - Configuration saved to {output_file}")
|
65
77
|
except Exception as e:
|
66
78
|
print(f"โ Error generating {config_type} configuration: {e}")
|
67
79
|
print("\n" + "=" * 50)
|
68
80
|
print("Configuration generator test completed!")
|
81
|
+
|
82
|
+
|
69
83
|
def test_config_with_comments():
|
70
84
|
"""Test configuration generation with comments."""
|
71
85
|
generator = ConfigGenerator()
|
@@ -76,11 +90,13 @@ def test_config_with_comments():
|
|
76
90
|
commented_config = generator.generate_config_with_comments("https")
|
77
91
|
print("โ
HTTPS configuration with comments generated successfully")
|
78
92
|
# Save to file
|
79
|
-
with open("test_https_with_comments.json",
|
93
|
+
with open("test_https_with_comments.json", "w") as f:
|
80
94
|
f.write(commented_config)
|
81
95
|
print(" - Configuration saved to test_https_with_comments.json")
|
82
96
|
except Exception as e:
|
83
97
|
print(f"โ Error generating configuration with comments: {e}")
|
98
|
+
|
99
|
+
|
84
100
|
if __name__ == "__main__":
|
85
101
|
test_config_generator()
|
86
102
|
test_config_with_comments()
|
@@ -12,6 +12,7 @@ import time
|
|
12
12
|
import requests
|
13
13
|
from pathlib import Path
|
14
14
|
from typing import Dict, Any, List
|
15
|
+
|
15
16
|
# Configuration for testing
|
16
17
|
CONFIGS = {
|
17
18
|
"basic_framework": {
|
@@ -20,7 +21,7 @@ CONFIGS = {
|
|
20
21
|
"http_auth": {"port": 8001, "ssl": False, "auth": True},
|
21
22
|
"https_auth": {"port": 8444, "ssl": True, "auth": True},
|
22
23
|
"mtls_no_roles": {"port": 9443, "ssl": True, "auth": True, "mtls": True},
|
23
|
-
"mtls_with_roles": {"port": 9444, "ssl": True, "auth": True, "mtls": True}
|
24
|
+
"mtls_with_roles": {"port": 9444, "ssl": True, "auth": True, "mtls": True},
|
24
25
|
},
|
25
26
|
"full_application": {
|
26
27
|
"http_simple": {"port": 9000, "ssl": False, "auth": False},
|
@@ -28,26 +29,28 @@ CONFIGS = {
|
|
28
29
|
"http_auth": {"port": 9001, "ssl": False, "auth": True},
|
29
30
|
"https_auth": {"port": 9446, "ssl": True, "auth": True},
|
30
31
|
"mtls_no_roles": {"port": 9447, "ssl": True, "auth": True, "mtls": True},
|
31
|
-
"mtls_with_roles": {"port": 9448, "ssl": True, "auth": True, "mtls": True}
|
32
|
-
}
|
33
|
-
}
|
34
|
-
API_KEYS = {
|
35
|
-
"admin": "admin-secret-key-123",
|
36
|
-
"user": "user-secret-key-456"
|
32
|
+
"mtls_with_roles": {"port": 9448, "ssl": True, "auth": True, "mtls": True},
|
33
|
+
},
|
37
34
|
}
|
35
|
+
API_KEYS = {"admin": "admin-secret-key-123", "user": "user-secret-key-456"}
|
36
|
+
|
37
|
+
|
38
38
|
class ExampleTester:
|
39
39
|
"""Test examples with different configurations."""
|
40
|
+
|
40
41
|
def __init__(self):
|
41
42
|
self.examples_dir = Path(__file__).parent
|
42
43
|
self.results = {}
|
43
44
|
self.processes = []
|
45
|
+
|
44
46
|
def generate_certificates(self):
|
45
47
|
"""Generate certificates for testing."""
|
46
48
|
print("๐ Generating certificates...")
|
47
49
|
cert_script = self.examples_dir.parent / "generate_certificates.py"
|
48
50
|
if cert_script.exists():
|
49
|
-
result = subprocess.run(
|
50
|
-
|
51
|
+
result = subprocess.run(
|
52
|
+
[sys.executable, str(cert_script)], capture_output=True, text=True
|
53
|
+
)
|
51
54
|
if result.returncode == 0:
|
52
55
|
print("โ
Certificates generated successfully")
|
53
56
|
return True
|
@@ -55,27 +58,31 @@ class ExampleTester:
|
|
55
58
|
print(f"โ Certificate generation failed: {result.stderr}")
|
56
59
|
return False
|
57
60
|
else:
|
58
|
-
print(
|
61
|
+
print(
|
62
|
+
"โ ๏ธ Certificate generation script not found, using existing certificates"
|
63
|
+
)
|
59
64
|
return True
|
65
|
+
|
60
66
|
def start_server(self, example_type: str, config_name: str) -> subprocess.Popen:
|
61
67
|
"""Start a server with specific configuration."""
|
62
|
-
config_path =
|
68
|
+
config_path = (
|
69
|
+
self.examples_dir / example_type / "configs" / f"{config_name}.json"
|
70
|
+
)
|
63
71
|
main_script = self.examples_dir / example_type / "main.py"
|
64
72
|
if not config_path.exists():
|
65
73
|
raise FileNotFoundError(f"Configuration file not found: {config_path}")
|
66
74
|
if not main_script.exists():
|
67
75
|
raise FileNotFoundError(f"Main script not found: {main_script}")
|
68
|
-
cmd = [
|
69
|
-
sys.executable, str(main_script),
|
70
|
-
"--config", str(config_path)
|
71
|
-
]
|
76
|
+
cmd = [sys.executable, str(main_script), "--config", str(config_path)]
|
72
77
|
print(f"๐ Starting {example_type} server with {config_name} config...")
|
73
78
|
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
74
79
|
# Wait for server to start
|
75
80
|
time.sleep(5)
|
76
81
|
return process
|
77
|
-
|
78
|
-
|
82
|
+
|
83
|
+
def test_health_endpoint(
|
84
|
+
self, port: int, ssl: bool = False, auth: bool = False, api_key: str = None
|
85
|
+
) -> Dict[str, Any]:
|
79
86
|
"""Test health endpoint."""
|
80
87
|
protocol = "https" if ssl else "http"
|
81
88
|
url = f"{protocol}://localhost:{port}/health"
|
@@ -87,15 +94,20 @@ class ExampleTester:
|
|
87
94
|
return {
|
88
95
|
"success": True,
|
89
96
|
"status_code": response.status_code,
|
90
|
-
"response":
|
97
|
+
"response": (
|
98
|
+
response.json()
|
99
|
+
if response.headers.get("content-type", "").startswith(
|
100
|
+
"application/json"
|
101
|
+
)
|
102
|
+
else response.text
|
103
|
+
),
|
91
104
|
}
|
92
105
|
except Exception as e:
|
93
|
-
return {
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
api_key: str = None) -> Dict[str, Any]:
|
106
|
+
return {"success": False, "error": str(e)}
|
107
|
+
|
108
|
+
def test_echo_command(
|
109
|
+
self, port: int, ssl: bool = False, auth: bool = False, api_key: str = None
|
110
|
+
) -> Dict[str, Any]:
|
99
111
|
"""Test echo command."""
|
100
112
|
protocol = "https" if ssl else "http"
|
101
113
|
url = f"{protocol}://localhost:{port}/cmd"
|
@@ -106,22 +118,23 @@ class ExampleTester:
|
|
106
118
|
"jsonrpc": "2.0",
|
107
119
|
"method": "echo",
|
108
120
|
"params": {"message": "Hello from test!"},
|
109
|
-
"id": 1
|
121
|
+
"id": 1,
|
110
122
|
}
|
111
123
|
try:
|
112
|
-
response = requests.post(
|
124
|
+
response = requests.post(
|
125
|
+
url, json=data, headers=headers, verify=False, timeout=10
|
126
|
+
)
|
113
127
|
return {
|
114
128
|
"success": True,
|
115
129
|
"status_code": response.status_code,
|
116
|
-
"response": response.json()
|
130
|
+
"response": response.json(),
|
117
131
|
}
|
118
132
|
except Exception as e:
|
119
|
-
return {
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
api_key: str = None) -> Dict[str, Any]:
|
133
|
+
return {"success": False, "error": str(e)}
|
134
|
+
|
135
|
+
def test_full_application_commands(
|
136
|
+
self, port: int, ssl: bool = False, auth: bool = False, api_key: str = None
|
137
|
+
) -> Dict[str, Any]:
|
125
138
|
"""Test full application specific commands."""
|
126
139
|
protocol = "https" if ssl else "http"
|
127
140
|
url = f"{protocol}://localhost:{port}/cmd"
|
@@ -134,40 +147,39 @@ class ExampleTester:
|
|
134
147
|
"jsonrpc": "2.0",
|
135
148
|
"method": "custom_echo",
|
136
149
|
"params": {"message": "Custom echo test", "repeat": 3},
|
137
|
-
"id": 1
|
150
|
+
"id": 1,
|
138
151
|
}
|
139
152
|
try:
|
140
|
-
response = requests.post(
|
153
|
+
response = requests.post(
|
154
|
+
url, json=data, headers=headers, verify=False, timeout=10
|
155
|
+
)
|
141
156
|
results["custom_echo"] = {
|
142
157
|
"success": True,
|
143
158
|
"status_code": response.status_code,
|
144
|
-
"response": response.json()
|
159
|
+
"response": response.json(),
|
145
160
|
}
|
146
161
|
except Exception as e:
|
147
|
-
results["custom_echo"] = {
|
148
|
-
"success": False,
|
149
|
-
"error": str(e)
|
150
|
-
}
|
162
|
+
results["custom_echo"] = {"success": False, "error": str(e)}
|
151
163
|
# Test dynamic calculator command
|
152
164
|
data = {
|
153
165
|
"jsonrpc": "2.0",
|
154
166
|
"method": "dynamic_calculator",
|
155
167
|
"params": {"operation": "add", "a": 10, "b": 5},
|
156
|
-
"id": 2
|
168
|
+
"id": 2,
|
157
169
|
}
|
158
170
|
try:
|
159
|
-
response = requests.post(
|
171
|
+
response = requests.post(
|
172
|
+
url, json=data, headers=headers, verify=False, timeout=10
|
173
|
+
)
|
160
174
|
results["dynamic_calculator"] = {
|
161
175
|
"success": True,
|
162
176
|
"status_code": response.status_code,
|
163
|
-
"response": response.json()
|
177
|
+
"response": response.json(),
|
164
178
|
}
|
165
179
|
except Exception as e:
|
166
|
-
results["dynamic_calculator"] = {
|
167
|
-
"success": False,
|
168
|
-
"error": str(e)
|
169
|
-
}
|
180
|
+
results["dynamic_calculator"] = {"success": False, "error": str(e)}
|
170
181
|
return results
|
182
|
+
|
171
183
|
def run_tests(self):
|
172
184
|
"""Run all tests."""
|
173
185
|
print("๐งช Starting Example Tests")
|
@@ -196,30 +208,37 @@ class ExampleTester:
|
|
196
208
|
print(f" ๐ Testing echo command...")
|
197
209
|
if auth:
|
198
210
|
# Test with admin key
|
199
|
-
echo_result = self.test_echo_command(
|
211
|
+
echo_result = self.test_echo_command(
|
212
|
+
port, ssl, auth, API_KEYS["admin"]
|
213
|
+
)
|
200
214
|
else:
|
201
215
|
echo_result = self.test_echo_command(port, ssl, auth)
|
202
216
|
print(f" Echo: {'โ
' if echo_result['success'] else 'โ'}")
|
203
217
|
# Test full application specific commands
|
204
218
|
if example_type == "full_application":
|
205
219
|
print(f" ๐ง Testing full application commands...")
|
206
|
-
app_results = self.test_full_application_commands(
|
207
|
-
|
220
|
+
app_results = self.test_full_application_commands(
|
221
|
+
port, ssl, auth, API_KEYS["admin"] if auth else None
|
222
|
+
)
|
208
223
|
for cmd_name, result in app_results.items():
|
209
|
-
print(
|
224
|
+
print(
|
225
|
+
f" {cmd_name}: {'โ
' if result['success'] else 'โ'}"
|
226
|
+
)
|
210
227
|
# Store results
|
211
228
|
self.results[f"{example_type}_{config_name}"] = {
|
212
229
|
"health": health_result,
|
213
230
|
"echo": echo_result,
|
214
|
-
"config_info": config_info
|
231
|
+
"config_info": config_info,
|
215
232
|
}
|
216
233
|
if example_type == "full_application":
|
217
|
-
self.results[f"{example_type}_{config_name}"][
|
234
|
+
self.results[f"{example_type}_{config_name}"][
|
235
|
+
"app_commands"
|
236
|
+
] = app_results
|
218
237
|
except Exception as e:
|
219
238
|
print(f" โ Error testing {config_name}: {e}")
|
220
239
|
self.results[f"{example_type}_{config_name}"] = {
|
221
240
|
"error": str(e),
|
222
|
-
"config_info": config_info
|
241
|
+
"config_info": config_info,
|
223
242
|
}
|
224
243
|
finally:
|
225
244
|
# Stop server
|
@@ -228,6 +247,7 @@ class ExampleTester:
|
|
228
247
|
process.wait()
|
229
248
|
time.sleep(2)
|
230
249
|
self.print_results()
|
250
|
+
|
231
251
|
def print_results(self):
|
232
252
|
"""Print test results."""
|
233
253
|
print("\n๐ Test Results Summary")
|
@@ -247,8 +267,10 @@ class ExampleTester:
|
|
247
267
|
print(f" Echo: {'โ
' if echo_success else 'โ'}")
|
248
268
|
# Check app commands for full application
|
249
269
|
if "app_commands" in result:
|
250
|
-
app_success = all(
|
251
|
-
|
270
|
+
app_success = all(
|
271
|
+
cmd_result.get("success", False)
|
272
|
+
for cmd_result in result["app_commands"].values()
|
273
|
+
)
|
252
274
|
print(f" App Commands: {'โ
' if app_success else 'โ'}")
|
253
275
|
# Overall test success
|
254
276
|
test_success = health_success and echo_success
|
@@ -259,15 +281,19 @@ class ExampleTester:
|
|
259
281
|
print("๐ All tests passed!")
|
260
282
|
else:
|
261
283
|
print("โ ๏ธ Some tests failed. Check the details above.")
|
284
|
+
|
262
285
|
def cleanup(self):
|
263
286
|
"""Cleanup processes."""
|
264
287
|
for process in self.processes:
|
265
288
|
if process.poll() is None:
|
266
289
|
process.terminate()
|
267
290
|
process.wait()
|
291
|
+
|
292
|
+
|
268
293
|
def main():
|
269
294
|
"""Main function."""
|
270
295
|
import sys
|
296
|
+
|
271
297
|
tester = ExampleTester()
|
272
298
|
try:
|
273
299
|
tester.run_tests()
|
@@ -277,5 +303,7 @@ def main():
|
|
277
303
|
print(f"\nโ Test execution failed: {e}")
|
278
304
|
finally:
|
279
305
|
tester.cleanup()
|
306
|
+
|
307
|
+
|
280
308
|
if __name__ == "__main__":
|
281
309
|
main()
|