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,341 @@
1
+ """
2
+ Demo Client Script
3
+
4
+ This script demonstrates how to use the UniversalClient with different
5
+ authentication methods and connection types.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ import asyncio
12
+ import json
13
+ import sys
14
+ from pathlib import Path
15
+
16
+ # Add project root to path
17
+ sys.path.insert(0, str(Path(__file__).parent.parent))
18
+
19
+ from examples.universal_client import UniversalClient, create_client_config
20
+
21
+
22
+ async def demo_from_config_file(config_file: str):
23
+ """
24
+ Demo client using configuration from file.
25
+
26
+ Args:
27
+ config_file: Path to configuration file
28
+ """
29
+ print(f"🚀 Demo from config file: {config_file}")
30
+ print("=" * 50)
31
+
32
+ try:
33
+ # Load configuration
34
+ with open(config_file, 'r') as f:
35
+ config = json.load(f)
36
+
37
+ print(f"Configuration loaded: {config.get('security', {}).get('auth_method', 'none')} auth")
38
+
39
+ # Create and use client
40
+ async with UniversalClient(config) as client:
41
+ # Test connection
42
+ success = await client.test_connection()
43
+
44
+ if success:
45
+ print("✅ Connection successful!")
46
+
47
+ # Test security features
48
+ security_results = await client.test_security_features()
49
+ print("\nSecurity Features:")
50
+ for feature, status in security_results.items():
51
+ status_icon = "✅" if status else "❌"
52
+ print(f" {status_icon} {feature}: {status}")
53
+
54
+ # Make API calls
55
+ await demo_api_calls(client)
56
+ else:
57
+ print("❌ Connection failed")
58
+
59
+ except FileNotFoundError:
60
+ print(f"❌ Configuration file not found: {config_file}")
61
+ except json.JSONDecodeError:
62
+ print(f"❌ Invalid JSON in configuration file: {config_file}")
63
+ except Exception as e:
64
+ print(f"❌ Demo failed: {e}")
65
+
66
+
67
+ async def demo_api_calls(client: UniversalClient):
68
+ """Demonstrate various API calls."""
69
+ print("\n📡 API Calls Demo:")
70
+ print("-" * 30)
71
+
72
+ # Test health endpoint
73
+ try:
74
+ health = await client.get("/health")
75
+ print(f"Health: {health}")
76
+ except Exception as e:
77
+ print(f"Health check failed: {e}")
78
+
79
+ # Test status endpoint
80
+ try:
81
+ status = await client.get("/api/status")
82
+ print(f"Status: {status}")
83
+ except Exception as e:
84
+ print(f"Status check failed: {e}")
85
+
86
+ # Test JSON-RPC command
87
+ try:
88
+ command_data = {
89
+ "jsonrpc": "2.0",
90
+ "method": "test_command",
91
+ "params": {
92
+ "message": "Hello from universal client!",
93
+ "timestamp": "2024-01-01T00:00:00Z"
94
+ },
95
+ "id": 1
96
+ }
97
+
98
+ result = await client.post("/api/jsonrpc", command_data)
99
+ print(f"Command Result: {result}")
100
+ except Exception as e:
101
+ print(f"Command execution failed: {e}")
102
+
103
+ # Test security command if available
104
+ try:
105
+ security_data = {
106
+ "jsonrpc": "2.0",
107
+ "method": "security_command",
108
+ "params": {
109
+ "action": "get_status",
110
+ "include_certificates": True
111
+ },
112
+ "id": 2
113
+ }
114
+
115
+ result = await client.post("/api/jsonrpc", security_data)
116
+ print(f"Security Status: {result}")
117
+ except Exception as e:
118
+ print(f"Security command failed: {e}")
119
+
120
+
121
+ async def demo_all_configs():
122
+ """Demo all available client configurations."""
123
+ print("🚀 Demo All Client Configurations")
124
+ print("=" * 50)
125
+
126
+ config_dir = Path(__file__).parent / "client_configs"
127
+
128
+ if not config_dir.exists():
129
+ print(f"❌ Config directory not found: {config_dir}")
130
+ return
131
+
132
+ config_files = list(config_dir.glob("*.json"))
133
+
134
+ if not config_files:
135
+ print(f"❌ No configuration files found in {config_dir}")
136
+ return
137
+
138
+ print(f"Found {len(config_files)} configuration files:")
139
+ for config_file in config_files:
140
+ print(f" - {config_file.name}")
141
+
142
+ print("\n" + "=" * 50)
143
+
144
+ for config_file in config_files:
145
+ await demo_from_config_file(str(config_file))
146
+ print("\n" + "-" * 50)
147
+
148
+
149
+ async def demo_programmatic_config():
150
+ """Demo client with programmatically created configuration."""
151
+ print("🚀 Demo Programmatic Configuration")
152
+ print("=" * 50)
153
+
154
+ # Create different configurations programmatically
155
+ configs = [
156
+ {
157
+ "name": "API Key Client",
158
+ "config": create_client_config(
159
+ "http://localhost:8000",
160
+ "api_key",
161
+ api_key="demo_api_key_123"
162
+ )
163
+ },
164
+ {
165
+ "name": "JWT Client",
166
+ "config": create_client_config(
167
+ "http://localhost:8000",
168
+ "jwt",
169
+ username="demo_user",
170
+ password="demo_password",
171
+ secret="demo_jwt_secret"
172
+ )
173
+ },
174
+ {
175
+ "name": "Certificate Client",
176
+ "config": create_client_config(
177
+ "https://localhost:8443",
178
+ "certificate",
179
+ cert_file="./certs/client.crt",
180
+ key_file="./keys/client.key",
181
+ ca_cert_file="./certs/ca.crt"
182
+ )
183
+ },
184
+ {
185
+ "name": "Basic Auth Client",
186
+ "config": create_client_config(
187
+ "http://localhost:8000",
188
+ "basic",
189
+ username="demo_user",
190
+ password="demo_password"
191
+ )
192
+ }
193
+ ]
194
+
195
+ for config_info in configs:
196
+ print(f"\n📋 Testing: {config_info['name']}")
197
+ print("-" * 30)
198
+
199
+ try:
200
+ async with UniversalClient(config_info["config"]) as client:
201
+ success = await client.test_connection()
202
+
203
+ if success:
204
+ print("✅ Connection successful!")
205
+ await demo_api_calls(client)
206
+ else:
207
+ print("❌ Connection failed")
208
+
209
+ except Exception as e:
210
+ print(f"❌ Test failed: {e}")
211
+
212
+
213
+ async def interactive_demo():
214
+ """Interactive demo with user input."""
215
+ print("🚀 Interactive Client Demo")
216
+ print("=" * 50)
217
+
218
+ print("Available authentication methods:")
219
+ print("1. No authentication")
220
+ print("2. API Key")
221
+ print("3. JWT Token")
222
+ print("4. Certificate")
223
+ print("5. Basic Authentication")
224
+
225
+ try:
226
+ choice = input("\nSelect authentication method (1-5): ").strip()
227
+
228
+ auth_methods = {
229
+ "1": "none",
230
+ "2": "api_key",
231
+ "3": "jwt",
232
+ "4": "certificate",
233
+ "5": "basic"
234
+ }
235
+
236
+ if choice not in auth_methods:
237
+ print("❌ Invalid choice")
238
+ return
239
+
240
+ auth_method = auth_methods[choice]
241
+
242
+ # Get server URL
243
+ server_url = input("Enter server URL (default: http://localhost:8000): ").strip()
244
+ if not server_url:
245
+ server_url = "http://localhost:8000"
246
+
247
+ # Create configuration based on choice
248
+ config_kwargs = {}
249
+
250
+ if auth_method == "api_key":
251
+ api_key = input("Enter API key: ").strip()
252
+ if api_key:
253
+ config_kwargs["api_key"] = api_key
254
+
255
+ elif auth_method == "jwt":
256
+ username = input("Enter username: ").strip()
257
+ password = input("Enter password: ").strip()
258
+ secret = input("Enter JWT secret: ").strip()
259
+ if username and password and secret:
260
+ config_kwargs.update({
261
+ "username": username,
262
+ "password": password,
263
+ "secret": secret
264
+ })
265
+
266
+ elif auth_method == "certificate":
267
+ cert_file = input("Enter certificate file path: ").strip()
268
+ key_file = input("Enter key file path: ").strip()
269
+ ca_cert_file = input("Enter CA certificate file path: ").strip()
270
+ if cert_file and key_file:
271
+ config_kwargs.update({
272
+ "cert_file": cert_file,
273
+ "key_file": key_file,
274
+ "ca_cert_file": ca_cert_file
275
+ })
276
+
277
+ elif auth_method == "basic":
278
+ username = input("Enter username: ").strip()
279
+ password = input("Enter password: ").strip()
280
+ if username and password:
281
+ config_kwargs.update({
282
+ "username": username,
283
+ "password": password
284
+ })
285
+
286
+ # Create configuration
287
+ config = create_client_config(server_url, auth_method, **config_kwargs)
288
+
289
+ print(f"\nConfiguration created for {auth_method} authentication")
290
+ print(f"Server URL: {server_url}")
291
+
292
+ # Test connection
293
+ async with UniversalClient(config) as client:
294
+ success = await client.test_connection()
295
+
296
+ if success:
297
+ print("✅ Connection successful!")
298
+ await demo_api_calls(client)
299
+ else:
300
+ print("❌ Connection failed")
301
+
302
+ except KeyboardInterrupt:
303
+ print("\n\nDemo interrupted by user")
304
+ except Exception as e:
305
+ print(f"❌ Interactive demo failed: {e}")
306
+
307
+
308
+ def main():
309
+ """Main demo function."""
310
+ if len(sys.argv) > 1:
311
+ command = sys.argv[1]
312
+
313
+ if command == "config":
314
+ if len(sys.argv) > 2:
315
+ config_file = sys.argv[2]
316
+ asyncio.run(demo_from_config_file(config_file))
317
+ else:
318
+ print("Usage: python demo_client.py config <config_file>")
319
+
320
+ elif command == "all":
321
+ asyncio.run(demo_all_configs())
322
+
323
+ elif command == "programmatic":
324
+ asyncio.run(demo_programmatic_config())
325
+
326
+ elif command == "interactive":
327
+ asyncio.run(interactive_demo())
328
+
329
+ else:
330
+ print("Unknown command. Available commands:")
331
+ print(" config <file> - Demo with config file")
332
+ print(" all - Demo all config files")
333
+ print(" programmatic - Demo programmatic configs")
334
+ print(" interactive - Interactive demo")
335
+ else:
336
+ # Default: demo all configs
337
+ asyncio.run(demo_all_configs())
338
+
339
+
340
+ if __name__ == "__main__":
341
+ main()
@@ -0,0 +1,99 @@
1
+ """
2
+ Custom Echo Command
3
+
4
+ This module demonstrates a custom command implementation for the full application example.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ from typing import Dict, Any, Optional
11
+ from mcp_proxy_adapter.commands.base import BaseCommand
12
+ from mcp_proxy_adapter.commands.result import CommandResult
13
+
14
+
15
+ class CustomEchoResult(CommandResult):
16
+ """Result class for custom echo command."""
17
+
18
+ def __init__(self, message: str, timestamp: str, echo_count: int):
19
+ self.message = message
20
+ self.timestamp = timestamp
21
+ self.echo_count = echo_count
22
+
23
+ def to_dict(self) -> Dict[str, Any]:
24
+ """Convert result to dictionary."""
25
+ return {
26
+ "message": self.message,
27
+ "timestamp": self.timestamp,
28
+ "echo_count": self.echo_count,
29
+ "command_type": "custom_echo"
30
+ }
31
+
32
+ def get_schema(self) -> Dict[str, Any]:
33
+ """Get result schema."""
34
+ return {
35
+ "type": "object",
36
+ "properties": {
37
+ "message": {"type": "string", "description": "Echoed message"},
38
+ "timestamp": {"type": "string", "description": "Timestamp of echo"},
39
+ "echo_count": {"type": "integer", "description": "Number of echoes"},
40
+ "command_type": {"type": "string", "description": "Command type"}
41
+ },
42
+ "required": ["message", "timestamp", "echo_count", "command_type"]
43
+ }
44
+
45
+
46
+ class CustomEchoCommand(BaseCommand):
47
+ """Custom echo command implementation."""
48
+
49
+ def __init__(self):
50
+ super().__init__()
51
+ self.echo_count = 0
52
+
53
+ def get_name(self) -> str:
54
+ """Get command name."""
55
+ return "custom_echo"
56
+
57
+ def get_description(self) -> str:
58
+ """Get command description."""
59
+ return "Custom echo command with enhanced features"
60
+
61
+ def get_schema(self) -> Dict[str, Any]:
62
+ """Get command schema."""
63
+ return {
64
+ "type": "object",
65
+ "properties": {
66
+ "message": {
67
+ "type": "string",
68
+ "description": "Message to echo",
69
+ "default": "Hello from custom echo!"
70
+ },
71
+ "repeat": {
72
+ "type": "integer",
73
+ "description": "Number of times to repeat",
74
+ "default": 1,
75
+ "minimum": 1,
76
+ "maximum": 10
77
+ }
78
+ },
79
+ "required": ["message"]
80
+ }
81
+
82
+ async def execute(self, params: Dict[str, Any]) -> CustomEchoResult:
83
+ """Execute the custom echo command."""
84
+ message = params.get("message", "Hello from custom echo!")
85
+ repeat = min(max(params.get("repeat", 1), 1), 10)
86
+
87
+ self.echo_count += 1
88
+
89
+ from datetime import datetime
90
+ timestamp = datetime.now().isoformat()
91
+
92
+ # Repeat the message
93
+ echoed_message = " ".join([message] * repeat)
94
+
95
+ return CustomEchoResult(
96
+ message=echoed_message,
97
+ timestamp=timestamp,
98
+ echo_count=self.echo_count
99
+ )
@@ -0,0 +1,106 @@
1
+ """
2
+ Dynamic Calculator Command
3
+
4
+ This module demonstrates a dynamically loaded command implementation for the full application example.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ from typing import Dict, Any, Optional
11
+ from mcp_proxy_adapter.commands.base import BaseCommand
12
+ from mcp_proxy_adapter.commands.result import CommandResult
13
+
14
+
15
+ class CalculatorResult(CommandResult):
16
+ """Result class for calculator command."""
17
+
18
+ def __init__(self, operation: str, result: float, expression: str):
19
+ self.operation = operation
20
+ self.result = result
21
+ self.expression = expression
22
+
23
+ def to_dict(self) -> Dict[str, Any]:
24
+ """Convert result to dictionary."""
25
+ return {
26
+ "operation": self.operation,
27
+ "result": self.result,
28
+ "expression": self.expression,
29
+ "command_type": "dynamic_calculator"
30
+ }
31
+
32
+ def get_schema(self) -> Dict[str, Any]:
33
+ """Get result schema."""
34
+ return {
35
+ "type": "object",
36
+ "properties": {
37
+ "operation": {"type": "string", "description": "Mathematical operation"},
38
+ "result": {"type": "number", "description": "Calculation result"},
39
+ "expression": {"type": "string", "description": "Full expression"},
40
+ "command_type": {"type": "string", "description": "Command type"}
41
+ },
42
+ "required": ["operation", "result", "expression", "command_type"]
43
+ }
44
+
45
+
46
+ class DynamicCalculatorCommand(BaseCommand):
47
+ """Dynamic calculator command implementation."""
48
+
49
+ def get_name(self) -> str:
50
+ """Get command name."""
51
+ return "dynamic_calculator"
52
+
53
+ def get_description(self) -> str:
54
+ """Get command description."""
55
+ return "Dynamic calculator with basic mathematical operations"
56
+
57
+ def get_schema(self) -> Dict[str, Any]:
58
+ """Get command schema."""
59
+ return {
60
+ "type": "object",
61
+ "properties": {
62
+ "operation": {
63
+ "type": "string",
64
+ "description": "Mathematical operation (add, subtract, multiply, divide)",
65
+ "enum": ["add", "subtract", "multiply", "divide"]
66
+ },
67
+ "a": {
68
+ "type": "number",
69
+ "description": "First number"
70
+ },
71
+ "b": {
72
+ "type": "number",
73
+ "description": "Second number"
74
+ }
75
+ },
76
+ "required": ["operation", "a", "b"]
77
+ }
78
+
79
+ async def execute(self, params: Dict[str, Any]) -> CalculatorResult:
80
+ """Execute the calculator command."""
81
+ operation = params.get("operation")
82
+ a = params.get("a")
83
+ b = params.get("b")
84
+
85
+ if operation == "add":
86
+ result = a + b
87
+ expression = f"{a} + {b}"
88
+ elif operation == "subtract":
89
+ result = a - b
90
+ expression = f"{a} - {b}"
91
+ elif operation == "multiply":
92
+ result = a * b
93
+ expression = f"{a} * {b}"
94
+ elif operation == "divide":
95
+ if b == 0:
96
+ raise ValueError("Division by zero is not allowed")
97
+ result = a / b
98
+ expression = f"{a} / {b}"
99
+ else:
100
+ raise ValueError(f"Unknown operation: {operation}")
101
+
102
+ return CalculatorResult(
103
+ operation=operation,
104
+ result=result,
105
+ expression=expression
106
+ )
@@ -0,0 +1,37 @@
1
+ {
2
+ "server": {
3
+ "host": "0.0.0.0",
4
+ "port": 8001,
5
+ "debug": false,
6
+ "log_level": "INFO"
7
+ },
8
+ "ssl": {
9
+ "enabled": false
10
+ },
11
+ "security": {
12
+ "enabled": true,
13
+ "auth": {
14
+ "enabled": true,
15
+ "methods": ["api_key"],
16
+ "api_keys": {
17
+ "admin": "admin-secret-key-123",
18
+ "user": "user-secret-key-456"
19
+ }
20
+ },
21
+ "rate_limit": {
22
+ "enabled": true,
23
+ "requests_per_minute": 60,
24
+ "requests_per_hour": 1000,
25
+ "burst_limit": 10
26
+ }
27
+ },
28
+ "logging": {
29
+ "level": "INFO",
30
+ "console_output": true,
31
+ "file_output": false
32
+ },
33
+ "commands": {
34
+ "auto_discovery": true,
35
+ "commands_directory": "./commands"
36
+ }
37
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "server": {
3
+ "host": "0.0.0.0",
4
+ "port": 8000,
5
+ "debug": false,
6
+ "log_level": "INFO"
7
+ },
8
+ "ssl": {
9
+ "enabled": false
10
+ },
11
+ "security": {
12
+ "enabled": false
13
+ },
14
+ "logging": {
15
+ "level": "INFO",
16
+ "console_output": true,
17
+ "file_output": false
18
+ },
19
+ "commands": {
20
+ "auto_discovery": true,
21
+ "commands_directory": "./commands"
22
+ }
23
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "server": {
3
+ "host": "0.0.0.0",
4
+ "port": 8444,
5
+ "debug": false,
6
+ "log_level": "INFO"
7
+ },
8
+ "ssl": {
9
+ "enabled": true,
10
+ "cert_file": "./certs/server.crt",
11
+ "key_file": "./certs/server.key"
12
+ },
13
+ "security": {
14
+ "enabled": true,
15
+ "auth": {
16
+ "enabled": true,
17
+ "methods": ["api_key"],
18
+ "api_keys": {
19
+ "admin": "admin-secret-key-123",
20
+ "user": "user-secret-key-456"
21
+ }
22
+ },
23
+ "rate_limit": {
24
+ "enabled": true,
25
+ "requests_per_minute": 60,
26
+ "requests_per_hour": 1000,
27
+ "burst_limit": 10
28
+ }
29
+ },
30
+ "logging": {
31
+ "level": "INFO",
32
+ "console_output": true,
33
+ "file_output": false
34
+ },
35
+ "commands": {
36
+ "auto_discovery": true,
37
+ "commands_directory": "./commands"
38
+ }
39
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "server": {
3
+ "host": "0.0.0.0",
4
+ "port": 8443,
5
+ "debug": false,
6
+ "log_level": "INFO"
7
+ },
8
+ "ssl": {
9
+ "enabled": true,
10
+ "cert_file": "./certs/server.crt",
11
+ "key_file": "./certs/server.key"
12
+ },
13
+ "security": {
14
+ "enabled": false
15
+ },
16
+ "logging": {
17
+ "level": "INFO",
18
+ "console_output": true,
19
+ "file_output": false
20
+ },
21
+ "commands": {
22
+ "auto_discovery": true,
23
+ "commands_directory": "./commands"
24
+ }
25
+ }