mcp-proxy-adapter 4.1.1__py3-none-any.whl โ†’ 6.1.0__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 (253) hide show
  1. mcp_proxy_adapter/__main__.py +12 -0
  2. mcp_proxy_adapter/api/app.py +254 -33
  3. mcp_proxy_adapter/api/handlers.py +32 -6
  4. mcp_proxy_adapter/api/middleware/__init__.py +36 -30
  5. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
  6. mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
  7. mcp_proxy_adapter/api/middleware/factory.py +243 -0
  8. mcp_proxy_adapter/api/middleware/logging.py +32 -6
  9. mcp_proxy_adapter/api/middleware/protocol_middleware.py +135 -0
  10. mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
  11. mcp_proxy_adapter/api/middleware/unified_security.py +152 -0
  12. mcp_proxy_adapter/api/middleware/user_info_middleware.py +83 -0
  13. mcp_proxy_adapter/commands/__init__.py +19 -4
  14. mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
  15. mcp_proxy_adapter/commands/base.py +66 -32
  16. mcp_proxy_adapter/commands/builtin_commands.py +95 -0
  17. mcp_proxy_adapter/commands/catalog_manager.py +838 -0
  18. mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
  19. mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
  20. mcp_proxy_adapter/commands/command_registry.py +711 -354
  21. mcp_proxy_adapter/commands/dependency_manager.py +245 -0
  22. mcp_proxy_adapter/commands/echo_command.py +81 -0
  23. mcp_proxy_adapter/commands/health_command.py +7 -0
  24. mcp_proxy_adapter/commands/help_command.py +21 -14
  25. mcp_proxy_adapter/commands/hooks.py +200 -167
  26. mcp_proxy_adapter/commands/key_management_command.py +506 -0
  27. mcp_proxy_adapter/commands/load_command.py +176 -0
  28. mcp_proxy_adapter/commands/plugins_command.py +235 -0
  29. mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
  30. mcp_proxy_adapter/commands/proxy_registration_command.py +409 -0
  31. mcp_proxy_adapter/commands/reload_command.py +48 -50
  32. mcp_proxy_adapter/commands/result.py +1 -0
  33. mcp_proxy_adapter/commands/role_test_command.py +141 -0
  34. mcp_proxy_adapter/commands/roles_management_command.py +697 -0
  35. mcp_proxy_adapter/commands/security_command.py +488 -0
  36. mcp_proxy_adapter/commands/ssl_setup_command.py +483 -0
  37. mcp_proxy_adapter/commands/token_management_command.py +529 -0
  38. mcp_proxy_adapter/commands/transport_management_command.py +144 -0
  39. mcp_proxy_adapter/commands/unload_command.py +158 -0
  40. mcp_proxy_adapter/config.py +159 -2
  41. mcp_proxy_adapter/core/app_factory.py +326 -0
  42. mcp_proxy_adapter/core/auth_validator.py +606 -0
  43. mcp_proxy_adapter/core/certificate_utils.py +827 -0
  44. mcp_proxy_adapter/core/client_security.py +384 -0
  45. mcp_proxy_adapter/core/config_converter.py +405 -0
  46. mcp_proxy_adapter/core/config_validator.py +218 -0
  47. mcp_proxy_adapter/core/logging.py +19 -3
  48. mcp_proxy_adapter/core/mtls_asgi.py +156 -0
  49. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  50. mcp_proxy_adapter/core/protocol_manager.py +235 -0
  51. mcp_proxy_adapter/core/proxy_client.py +602 -0
  52. mcp_proxy_adapter/core/proxy_registration.py +522 -0
  53. mcp_proxy_adapter/core/role_utils.py +426 -0
  54. mcp_proxy_adapter/core/security_adapter.py +370 -0
  55. mcp_proxy_adapter/core/security_factory.py +239 -0
  56. mcp_proxy_adapter/core/security_integration.py +277 -0
  57. mcp_proxy_adapter/core/server_adapter.py +345 -0
  58. mcp_proxy_adapter/core/server_engine.py +364 -0
  59. mcp_proxy_adapter/core/settings.py +1 -0
  60. mcp_proxy_adapter/core/ssl_utils.py +233 -0
  61. mcp_proxy_adapter/core/transport_manager.py +292 -0
  62. mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
  63. mcp_proxy_adapter/custom_openapi.py +22 -11
  64. mcp_proxy_adapter/examples/README.md +230 -97
  65. mcp_proxy_adapter/examples/README_EN.md +258 -0
  66. mcp_proxy_adapter/examples/SECURITY_TESTING.md +455 -0
  67. mcp_proxy_adapter/examples/__pycache__/security_configurations.cpython-312.pyc +0 -0
  68. mcp_proxy_adapter/examples/__pycache__/security_test_client.cpython-312.pyc +0 -0
  69. mcp_proxy_adapter/examples/basic_framework/configs/http_auth.json +37 -0
  70. mcp_proxy_adapter/examples/basic_framework/configs/http_simple.json +23 -0
  71. mcp_proxy_adapter/examples/basic_framework/configs/https_auth.json +39 -0
  72. mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +25 -0
  73. mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +39 -0
  74. mcp_proxy_adapter/examples/basic_framework/configs/mtls_with_roles.json +45 -0
  75. mcp_proxy_adapter/examples/basic_framework/main.py +63 -0
  76. mcp_proxy_adapter/examples/basic_framework/roles.json +21 -0
  77. mcp_proxy_adapter/examples/cert_config.json +9 -0
  78. mcp_proxy_adapter/examples/certs/admin.crt +32 -0
  79. mcp_proxy_adapter/examples/certs/admin.key +52 -0
  80. mcp_proxy_adapter/examples/certs/admin_cert.pem +21 -0
  81. mcp_proxy_adapter/examples/certs/admin_key.pem +28 -0
  82. mcp_proxy_adapter/examples/certs/ca_cert.pem +23 -0
  83. mcp_proxy_adapter/examples/certs/ca_cert.srl +1 -0
  84. mcp_proxy_adapter/examples/certs/ca_key.pem +28 -0
  85. mcp_proxy_adapter/examples/certs/cert_config.json +9 -0
  86. mcp_proxy_adapter/examples/certs/client.crt +32 -0
  87. mcp_proxy_adapter/examples/certs/client.key +52 -0
  88. mcp_proxy_adapter/examples/certs/client_admin.crt +32 -0
  89. mcp_proxy_adapter/examples/certs/client_admin.key +52 -0
  90. mcp_proxy_adapter/examples/certs/client_user.crt +32 -0
  91. mcp_proxy_adapter/examples/certs/client_user.key +52 -0
  92. mcp_proxy_adapter/examples/certs/guest_cert.pem +21 -0
  93. mcp_proxy_adapter/examples/certs/guest_key.pem +28 -0
  94. mcp_proxy_adapter/examples/certs/mcp_proxy_adapter_ca_ca.crt +23 -0
  95. mcp_proxy_adapter/examples/certs/proxy_cert.pem +21 -0
  96. mcp_proxy_adapter/examples/certs/proxy_key.pem +28 -0
  97. mcp_proxy_adapter/examples/certs/readonly.crt +32 -0
  98. mcp_proxy_adapter/examples/certs/readonly.key +52 -0
  99. mcp_proxy_adapter/examples/certs/readonly_cert.pem +21 -0
  100. mcp_proxy_adapter/examples/certs/readonly_key.pem +28 -0
  101. mcp_proxy_adapter/examples/certs/server.crt +32 -0
  102. mcp_proxy_adapter/examples/certs/server.key +52 -0
  103. mcp_proxy_adapter/examples/certs/server_cert.pem +32 -0
  104. mcp_proxy_adapter/examples/certs/server_key.pem +52 -0
  105. mcp_proxy_adapter/examples/certs/test_ca_ca.crt +20 -0
  106. mcp_proxy_adapter/examples/certs/user.crt +32 -0
  107. mcp_proxy_adapter/examples/certs/user.key +52 -0
  108. mcp_proxy_adapter/examples/certs/user_cert.pem +21 -0
  109. mcp_proxy_adapter/examples/certs/user_key.pem +28 -0
  110. mcp_proxy_adapter/examples/client_configs/api_key_client.json +13 -0
  111. mcp_proxy_adapter/examples/client_configs/basic_auth_client.json +13 -0
  112. mcp_proxy_adapter/examples/client_configs/certificate_client.json +22 -0
  113. mcp_proxy_adapter/examples/client_configs/jwt_client.json +15 -0
  114. mcp_proxy_adapter/examples/client_configs/no_auth_client.json +9 -0
  115. mcp_proxy_adapter/examples/commands/__init__.py +1 -0
  116. mcp_proxy_adapter/examples/create_certificates_simple.py +307 -0
  117. mcp_proxy_adapter/examples/debug_request_state.py +144 -0
  118. mcp_proxy_adapter/examples/debug_role_chain.py +205 -0
  119. mcp_proxy_adapter/examples/demo_client.py +341 -0
  120. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +99 -0
  121. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +106 -0
  122. mcp_proxy_adapter/examples/full_application/configs/http_auth.json +37 -0
  123. mcp_proxy_adapter/examples/full_application/configs/http_simple.json +23 -0
  124. mcp_proxy_adapter/examples/full_application/configs/https_auth.json +39 -0
  125. mcp_proxy_adapter/examples/full_application/configs/https_simple.json +25 -0
  126. mcp_proxy_adapter/examples/full_application/configs/mtls_no_roles.json +39 -0
  127. mcp_proxy_adapter/examples/full_application/configs/mtls_with_roles.json +45 -0
  128. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +97 -0
  129. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +95 -0
  130. mcp_proxy_adapter/examples/full_application/main.py +138 -0
  131. mcp_proxy_adapter/examples/full_application/roles.json +21 -0
  132. mcp_proxy_adapter/examples/generate_all_certificates.py +429 -0
  133. mcp_proxy_adapter/examples/generate_certificates.py +121 -0
  134. mcp_proxy_adapter/examples/keys/ca_key.pem +28 -0
  135. mcp_proxy_adapter/examples/keys/mcp_proxy_adapter_ca_ca.key +28 -0
  136. mcp_proxy_adapter/examples/keys/test_ca_ca.key +28 -0
  137. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log +220 -0
  138. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.1 +1 -0
  139. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.2 +1 -0
  140. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.3 +1 -0
  141. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.4 +1 -0
  142. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.5 +1 -0
  143. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log +220 -0
  144. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.1 +1 -0
  145. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.2 +1 -0
  146. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.3 +1 -0
  147. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.4 +1 -0
  148. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.5 +1 -0
  149. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log +2 -0
  150. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.1 +1 -0
  151. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.2 +1 -0
  152. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.3 +1 -0
  153. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.4 +1 -0
  154. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.5 +1 -0
  155. mcp_proxy_adapter/examples/proxy_registration_example.py +401 -0
  156. mcp_proxy_adapter/examples/roles.json +38 -0
  157. mcp_proxy_adapter/examples/run_example.py +81 -0
  158. mcp_proxy_adapter/examples/run_security_tests.py +326 -0
  159. mcp_proxy_adapter/examples/run_security_tests_fixed.py +300 -0
  160. mcp_proxy_adapter/examples/security_test_client.py +743 -0
  161. mcp_proxy_adapter/examples/server_configs/config_basic_http.json +204 -0
  162. mcp_proxy_adapter/examples/server_configs/config_http_token.json +238 -0
  163. mcp_proxy_adapter/examples/server_configs/config_https.json +215 -0
  164. mcp_proxy_adapter/examples/server_configs/config_https_token.json +231 -0
  165. mcp_proxy_adapter/examples/server_configs/config_mtls.json +215 -0
  166. mcp_proxy_adapter/examples/server_configs/config_proxy_registration.json +250 -0
  167. mcp_proxy_adapter/examples/server_configs/config_simple.json +46 -0
  168. mcp_proxy_adapter/examples/server_configs/roles.json +38 -0
  169. mcp_proxy_adapter/examples/test_examples.py +344 -0
  170. mcp_proxy_adapter/examples/universal_client.py +628 -0
  171. mcp_proxy_adapter/main.py +186 -0
  172. mcp_proxy_adapter/utils/config_generator.py +639 -0
  173. mcp_proxy_adapter/version.py +2 -1
  174. mcp_proxy_adapter-6.1.0.dist-info/METADATA +205 -0
  175. mcp_proxy_adapter-6.1.0.dist-info/RECORD +193 -0
  176. mcp_proxy_adapter-6.1.0.dist-info/entry_points.txt +2 -0
  177. {mcp_proxy_adapter-4.1.1.dist-info โ†’ mcp_proxy_adapter-6.1.0.dist-info}/licenses/LICENSE +2 -2
  178. mcp_proxy_adapter/api/middleware/auth.py +0 -146
  179. mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
  180. mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
  181. mcp_proxy_adapter/examples/__init__.py +0 -7
  182. mcp_proxy_adapter/examples/basic_server/README.md +0 -60
  183. mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
  184. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
  185. mcp_proxy_adapter/examples/basic_server/config.json +0 -35
  186. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
  187. mcp_proxy_adapter/examples/basic_server/server.py +0 -103
  188. mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
  189. mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
  190. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -250
  191. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
  192. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
  193. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
  194. mcp_proxy_adapter/examples/custom_commands/config.json +0 -35
  195. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
  196. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
  197. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
  198. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
  199. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
  200. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
  201. mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
  202. mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
  203. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
  204. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
  205. mcp_proxy_adapter/examples/custom_commands/server.py +0 -228
  206. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
  207. mcp_proxy_adapter/examples/deployment/README.md +0 -49
  208. mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
  209. mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
  210. mcp_proxy_adapter/examples/deployment/config.json +0 -29
  211. mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
  212. mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
  213. mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
  214. mcp_proxy_adapter/examples/deployment/run.sh +0 -43
  215. mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
  216. mcp_proxy_adapter/schemas/base_schema.json +0 -114
  217. mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
  218. mcp_proxy_adapter/tests/__init__.py +0 -0
  219. mcp_proxy_adapter/tests/api/__init__.py +0 -3
  220. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
  221. mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
  222. mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
  223. mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
  224. mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
  225. mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
  226. mcp_proxy_adapter/tests/commands/__init__.py +0 -3
  227. mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
  228. mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
  229. mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
  230. mcp_proxy_adapter/tests/conftest.py +0 -131
  231. mcp_proxy_adapter/tests/functional/__init__.py +0 -3
  232. mcp_proxy_adapter/tests/functional/test_api.py +0 -253
  233. mcp_proxy_adapter/tests/integration/__init__.py +0 -3
  234. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
  235. mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
  236. mcp_proxy_adapter/tests/performance/__init__.py +0 -3
  237. mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
  238. mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
  239. mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
  240. mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
  241. mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
  242. mcp_proxy_adapter/tests/test_base_command.py +0 -123
  243. mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
  244. mcp_proxy_adapter/tests/test_command_registry.py +0 -281
  245. mcp_proxy_adapter/tests/test_config.py +0 -127
  246. mcp_proxy_adapter/tests/test_utils.py +0 -65
  247. mcp_proxy_adapter/tests/unit/__init__.py +0 -3
  248. mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
  249. mcp_proxy_adapter/tests/unit/test_config.py +0 -217
  250. mcp_proxy_adapter-4.1.1.dist-info/METADATA +0 -200
  251. mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
  252. {mcp_proxy_adapter-4.1.1.dist-info โ†’ mcp_proxy_adapter-6.1.0.dist-info}/WHEEL +0 -0
  253. {mcp_proxy_adapter-4.1.1.dist-info โ†’ mcp_proxy_adapter-6.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,46 @@
1
+ {
2
+ "server": {
3
+ "host": "0.0.0.0",
4
+ "port": 8002,
5
+ "debug": false,
6
+ "workers": 1
7
+ },
8
+
9
+ "security": {
10
+ "framework": "none",
11
+ "enabled": false,
12
+ "debug": false,
13
+ "environment": "dev",
14
+ "version": "1.0.0"
15
+ },
16
+
17
+ "logging": {
18
+ "level": "INFO",
19
+ "console_output": true,
20
+ "file_output": false,
21
+ "file_path": "./logs/server.log",
22
+ "max_file_size": 10,
23
+ "backup_count": 5,
24
+ "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
25
+ },
26
+
27
+ "commands": {
28
+ "auto_discovery": true,
29
+ "commands_directory": "./commands",
30
+ "builtin_commands": ["echo", "health", "config", "roletest", "proxy_registration"],
31
+ "custom_commands": [],
32
+ "command_timeout": 30
33
+ },
34
+
35
+ "protocol": {
36
+ "jsonrpc": {
37
+ "enabled": true,
38
+ "version": "2.0",
39
+ "endpoint": "/api/jsonrpc"
40
+ },
41
+ "rest": {
42
+ "enabled": true,
43
+ "endpoint": "/cmd"
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "roles": {
3
+ "admin": {
4
+ "description": "Administrator with full access",
5
+ "permissions": ["*"],
6
+ "inherits": []
7
+ },
8
+ "user": {
9
+ "description": "Standard user with read/write access",
10
+ "permissions": ["read", "write"],
11
+ "inherits": ["readonly"]
12
+ },
13
+ "readonly": {
14
+ "description": "Read-only user",
15
+ "permissions": ["read"],
16
+ "inherits": []
17
+ },
18
+ "guest": {
19
+ "description": "Guest user with minimal access",
20
+ "permissions": ["read"],
21
+ "inherits": []
22
+ },
23
+ "proxy": {
24
+ "description": "Proxy registration and discovery",
25
+ "permissions": ["register", "heartbeat", "discover"],
26
+ "inherits": []
27
+ }
28
+ },
29
+ "permissions": {
30
+ "read": "Read access to resources",
31
+ "write": "Write access to resources",
32
+ "delete": "Delete access to resources",
33
+ "manage": "Manage system settings",
34
+ "register": "Register proxy with registry",
35
+ "heartbeat": "Send heartbeat to registry",
36
+ "discover": "Discover other proxies"
37
+ }
38
+ }
@@ -0,0 +1,344 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test Examples Script
4
+
5
+ This script tests all examples with different configurations.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ import json
12
+ import os
13
+ import subprocess
14
+ import time
15
+ import requests
16
+ from pathlib import Path
17
+ from typing import Dict, Any, List
18
+
19
+ # Configuration for testing
20
+ CONFIGS = {
21
+ "basic_framework": {
22
+ "http_simple": {"port": 8000, "ssl": False, "auth": False},
23
+ "https_simple": {"port": 8443, "ssl": True, "auth": False},
24
+ "http_auth": {"port": 8001, "ssl": False, "auth": True},
25
+ "https_auth": {"port": 8444, "ssl": True, "auth": True},
26
+ "mtls_no_roles": {"port": 9443, "ssl": True, "auth": True, "mtls": True},
27
+ "mtls_with_roles": {"port": 9444, "ssl": True, "auth": True, "mtls": True}
28
+ },
29
+ "full_application": {
30
+ "http_simple": {"port": 9000, "ssl": False, "auth": False},
31
+ "https_simple": {"port": 9445, "ssl": True, "auth": False},
32
+ "http_auth": {"port": 9001, "ssl": False, "auth": True},
33
+ "https_auth": {"port": 9446, "ssl": True, "auth": True},
34
+ "mtls_no_roles": {"port": 9447, "ssl": True, "auth": True, "mtls": True},
35
+ "mtls_with_roles": {"port": 9448, "ssl": True, "auth": True, "mtls": True}
36
+ }
37
+ }
38
+
39
+ API_KEYS = {
40
+ "admin": "admin-secret-key-123",
41
+ "user": "user-secret-key-456"
42
+ }
43
+
44
+
45
+ class ExampleTester:
46
+ """Test examples with different configurations."""
47
+
48
+ def __init__(self):
49
+ self.examples_dir = Path(__file__).parent
50
+ self.results = {}
51
+ self.processes = []
52
+
53
+ def generate_certificates(self):
54
+ """Generate certificates for testing."""
55
+ print("๐Ÿ” Generating certificates...")
56
+
57
+ cert_script = self.examples_dir.parent / "generate_certificates.py"
58
+ if cert_script.exists():
59
+ result = subprocess.run([sys.executable, str(cert_script)],
60
+ capture_output=True, text=True)
61
+ if result.returncode == 0:
62
+ print("โœ… Certificates generated successfully")
63
+ return True
64
+ else:
65
+ print(f"โŒ Certificate generation failed: {result.stderr}")
66
+ return False
67
+ else:
68
+ print("โš ๏ธ Certificate generation script not found, using existing certificates")
69
+ return True
70
+
71
+ def start_server(self, example_type: str, config_name: str) -> subprocess.Popen:
72
+ """Start a server with specific configuration."""
73
+ config_path = self.examples_dir / example_type / "configs" / f"{config_name}.json"
74
+ main_script = self.examples_dir / example_type / "main.py"
75
+
76
+ if not config_path.exists():
77
+ raise FileNotFoundError(f"Configuration file not found: {config_path}")
78
+
79
+ if not main_script.exists():
80
+ raise FileNotFoundError(f"Main script not found: {main_script}")
81
+
82
+ cmd = [
83
+ sys.executable, str(main_script),
84
+ "--config", str(config_path)
85
+ ]
86
+
87
+ print(f"๐Ÿš€ Starting {example_type} server with {config_name} config...")
88
+ process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
89
+
90
+ # Wait for server to start
91
+ time.sleep(5)
92
+
93
+ return process
94
+
95
+ def test_health_endpoint(self, port: int, ssl: bool = False, auth: bool = False,
96
+ api_key: str = None) -> Dict[str, Any]:
97
+ """Test health endpoint."""
98
+ protocol = "https" if ssl else "http"
99
+ url = f"{protocol}://localhost:{port}/health"
100
+
101
+ headers = {}
102
+ if auth and api_key:
103
+ headers["X-API-Key"] = api_key
104
+
105
+ try:
106
+ response = requests.get(url, headers=headers, verify=False, timeout=10)
107
+ return {
108
+ "success": True,
109
+ "status_code": response.status_code,
110
+ "response": response.json() if response.headers.get('content-type', '').startswith('application/json') else response.text
111
+ }
112
+ except Exception as e:
113
+ return {
114
+ "success": False,
115
+ "error": str(e)
116
+ }
117
+
118
+ def test_echo_command(self, port: int, ssl: bool = False, auth: bool = False,
119
+ api_key: str = None) -> Dict[str, Any]:
120
+ """Test echo command."""
121
+ protocol = "https" if ssl else "http"
122
+ url = f"{protocol}://localhost:{port}/cmd"
123
+
124
+ headers = {"Content-Type": "application/json"}
125
+ if auth and api_key:
126
+ headers["X-API-Key"] = api_key
127
+
128
+ data = {
129
+ "jsonrpc": "2.0",
130
+ "method": "echo",
131
+ "params": {"message": "Hello from test!"},
132
+ "id": 1
133
+ }
134
+
135
+ try:
136
+ response = requests.post(url, json=data, headers=headers, verify=False, timeout=10)
137
+ return {
138
+ "success": True,
139
+ "status_code": response.status_code,
140
+ "response": response.json()
141
+ }
142
+ except Exception as e:
143
+ return {
144
+ "success": False,
145
+ "error": str(e)
146
+ }
147
+
148
+ def test_full_application_commands(self, port: int, ssl: bool = False, auth: bool = False,
149
+ api_key: str = None) -> Dict[str, Any]:
150
+ """Test full application specific commands."""
151
+ protocol = "https" if ssl else "http"
152
+ url = f"{protocol}://localhost:{port}/cmd"
153
+
154
+ headers = {"Content-Type": "application/json"}
155
+ if auth and api_key:
156
+ headers["X-API-Key"] = api_key
157
+
158
+ results = {}
159
+
160
+ # Test custom echo command
161
+ data = {
162
+ "jsonrpc": "2.0",
163
+ "method": "custom_echo",
164
+ "params": {"message": "Custom echo test", "repeat": 3},
165
+ "id": 1
166
+ }
167
+
168
+ try:
169
+ response = requests.post(url, json=data, headers=headers, verify=False, timeout=10)
170
+ results["custom_echo"] = {
171
+ "success": True,
172
+ "status_code": response.status_code,
173
+ "response": response.json()
174
+ }
175
+ except Exception as e:
176
+ results["custom_echo"] = {
177
+ "success": False,
178
+ "error": str(e)
179
+ }
180
+
181
+ # Test dynamic calculator command
182
+ data = {
183
+ "jsonrpc": "2.0",
184
+ "method": "dynamic_calculator",
185
+ "params": {"operation": "add", "a": 10, "b": 5},
186
+ "id": 2
187
+ }
188
+
189
+ try:
190
+ response = requests.post(url, json=data, headers=headers, verify=False, timeout=10)
191
+ results["dynamic_calculator"] = {
192
+ "success": True,
193
+ "status_code": response.status_code,
194
+ "response": response.json()
195
+ }
196
+ except Exception as e:
197
+ results["dynamic_calculator"] = {
198
+ "success": False,
199
+ "error": str(e)
200
+ }
201
+
202
+ return results
203
+
204
+ def run_tests(self):
205
+ """Run all tests."""
206
+ print("๐Ÿงช Starting Example Tests")
207
+ print("=" * 60)
208
+
209
+ # Generate certificates first
210
+ if not self.generate_certificates():
211
+ print("โŒ Certificate generation failed, skipping tests")
212
+ return
213
+
214
+ for example_type, configs in CONFIGS.items():
215
+ print(f"\n๐Ÿ“ Testing {example_type.upper()}")
216
+ print("-" * 40)
217
+
218
+ for config_name, config_info in configs.items():
219
+ print(f"\n๐Ÿ”ง Testing {config_name} configuration...")
220
+
221
+ try:
222
+ # Start server
223
+ process = self.start_server(example_type, config_name)
224
+ self.processes.append(process)
225
+
226
+ port = config_info["port"]
227
+ ssl = config_info.get("ssl", False)
228
+ auth = config_info.get("auth", False)
229
+
230
+ # Test health endpoint
231
+ print(f" ๐Ÿ“Š Testing health endpoint...")
232
+ health_result = self.test_health_endpoint(port, ssl, auth)
233
+ print(f" Health: {'โœ…' if health_result['success'] else 'โŒ'}")
234
+
235
+ # Test echo command
236
+ print(f" ๐Ÿ“ Testing echo command...")
237
+ if auth:
238
+ # Test with admin key
239
+ echo_result = self.test_echo_command(port, ssl, auth, API_KEYS["admin"])
240
+ else:
241
+ echo_result = self.test_echo_command(port, ssl, auth)
242
+ print(f" Echo: {'โœ…' if echo_result['success'] else 'โŒ'}")
243
+
244
+ # Test full application specific commands
245
+ if example_type == "full_application":
246
+ print(f" ๐Ÿ”ง Testing full application commands...")
247
+ app_results = self.test_full_application_commands(port, ssl, auth,
248
+ API_KEYS["admin"] if auth else None)
249
+ for cmd_name, result in app_results.items():
250
+ print(f" {cmd_name}: {'โœ…' if result['success'] else 'โŒ'}")
251
+
252
+ # Store results
253
+ self.results[f"{example_type}_{config_name}"] = {
254
+ "health": health_result,
255
+ "echo": echo_result,
256
+ "config_info": config_info
257
+ }
258
+
259
+ if example_type == "full_application":
260
+ self.results[f"{example_type}_{config_name}"]["app_commands"] = app_results
261
+
262
+ except Exception as e:
263
+ print(f" โŒ Error testing {config_name}: {e}")
264
+ self.results[f"{example_type}_{config_name}"] = {
265
+ "error": str(e),
266
+ "config_info": config_info
267
+ }
268
+
269
+ finally:
270
+ # Stop server
271
+ if process:
272
+ process.terminate()
273
+ process.wait()
274
+ time.sleep(2)
275
+
276
+ self.print_results()
277
+
278
+ def print_results(self):
279
+ """Print test results."""
280
+ print("\n๐Ÿ“Š Test Results Summary")
281
+ print("=" * 60)
282
+
283
+ total_tests = len(self.results)
284
+ successful_tests = 0
285
+
286
+ for test_name, result in self.results.items():
287
+ print(f"\n๐Ÿ” {test_name}")
288
+
289
+ if "error" in result:
290
+ print(f" โŒ Error: {result['error']}")
291
+ continue
292
+
293
+ # Check health test
294
+ health_success = result.get("health", {}).get("success", False)
295
+ print(f" Health: {'โœ…' if health_success else 'โŒ'}")
296
+
297
+ # Check echo test
298
+ echo_success = result.get("echo", {}).get("success", False)
299
+ print(f" Echo: {'โœ…' if echo_success else 'โŒ'}")
300
+
301
+ # Check app commands for full application
302
+ if "app_commands" in result:
303
+ app_success = all(cmd_result.get("success", False)
304
+ for cmd_result in result["app_commands"].values())
305
+ print(f" App Commands: {'โœ…' if app_success else 'โŒ'}")
306
+
307
+ # Overall test success
308
+ test_success = health_success and echo_success
309
+ if test_success:
310
+ successful_tests += 1
311
+
312
+ print(f"\n๐ŸŽฏ Overall Results: {successful_tests}/{total_tests} tests passed")
313
+
314
+ if successful_tests == total_tests:
315
+ print("๐ŸŽ‰ All tests passed!")
316
+ else:
317
+ print("โš ๏ธ Some tests failed. Check the details above.")
318
+
319
+ def cleanup(self):
320
+ """Cleanup processes."""
321
+ for process in self.processes:
322
+ if process.poll() is None:
323
+ process.terminate()
324
+ process.wait()
325
+
326
+
327
+ def main():
328
+ """Main function."""
329
+ import sys
330
+
331
+ tester = ExampleTester()
332
+
333
+ try:
334
+ tester.run_tests()
335
+ except KeyboardInterrupt:
336
+ print("\n๐Ÿ›‘ Tests interrupted by user")
337
+ except Exception as e:
338
+ print(f"\nโŒ Test execution failed: {e}")
339
+ finally:
340
+ tester.cleanup()
341
+
342
+
343
+ if __name__ == "__main__":
344
+ main()