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,401 @@
1
+ """
2
+ Proxy Registration Example
3
+
4
+ This example demonstrates how to use the MCP Proxy Adapter framework
5
+ for proxy registration with different authentication methods.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ import asyncio
12
+ import json
13
+ import sys
14
+ import os
15
+ from pathlib import Path
16
+ from typing import Dict, Any, Optional
17
+
18
+ # Add project root to path
19
+ project_root = Path(__file__).parent.parent.parent
20
+ sys.path.insert(0, str(project_root))
21
+
22
+ import aiohttp
23
+ from aiohttp import ClientTimeout, TCPConnector
24
+ import ssl
25
+
26
+ from mcp_proxy_adapter.core.logging import logger
27
+
28
+
29
+ class ProxyRegistrationExample:
30
+ """Example client for testing proxy registration functionality."""
31
+
32
+ def __init__(self, server_url: str, auth_token: Optional[str] = None):
33
+ """
34
+ Initialize example client.
35
+
36
+ Args:
37
+ server_url: Server URL
38
+ auth_token: Authentication token
39
+ """
40
+ self.server_url = server_url
41
+ self.auth_token = auth_token
42
+ self.session: Optional[aiohttp.ClientSession] = None
43
+
44
+ # Test data
45
+ self.test_servers = [
46
+ {
47
+ "server_id": "example-server-1",
48
+ "server_url": "http://localhost:8001",
49
+ "server_name": "Example Server 1",
50
+ "description": "Example server for registration testing",
51
+ "version": "1.0.0",
52
+ "capabilities": ["jsonrpc", "rest"],
53
+ "endpoints": {
54
+ "jsonrpc": "/api/jsonrpc",
55
+ "rest": "/cmd",
56
+ "health": "/health"
57
+ },
58
+ "auth_method": "api_key",
59
+ "security_enabled": True
60
+ },
61
+ {
62
+ "server_id": "example-server-2",
63
+ "server_url": "http://localhost:8002",
64
+ "server_name": "Example Server 2",
65
+ "description": "Another example server",
66
+ "version": "1.0.0",
67
+ "capabilities": ["jsonrpc", "rest", "security"],
68
+ "endpoints": {
69
+ "jsonrpc": "/api/jsonrpc",
70
+ "rest": "/cmd",
71
+ "health": "/health"
72
+ },
73
+ "auth_method": "certificate",
74
+ "security_enabled": True
75
+ }
76
+ ]
77
+
78
+ async def __aenter__(self):
79
+ """Async context manager entry."""
80
+ # Create SSL context for HTTPS
81
+ ssl_context = None
82
+ if self.server_url.startswith("https"):
83
+ ssl_context = ssl.create_default_context()
84
+ ssl_context.check_hostname = False
85
+ ssl_context.verify_mode = ssl.CERT_NONE
86
+
87
+ # Create connector
88
+ connector = TCPConnector(ssl=ssl_context) if ssl_context else None
89
+
90
+ # Create session
91
+ timeout = ClientTimeout(total=30)
92
+ self.session = aiohttp.ClientSession(
93
+ connector=connector,
94
+ timeout=timeout
95
+ )
96
+
97
+ return self
98
+
99
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
100
+ """Async context manager exit."""
101
+ if self.session:
102
+ await self.session.close()
103
+
104
+ def _get_headers(self) -> Dict[str, str]:
105
+ """Get request headers with authentication."""
106
+ headers = {
107
+ "Content-Type": "application/json"
108
+ }
109
+
110
+ if self.auth_token:
111
+ headers["X-API-Key"] = self.auth_token
112
+
113
+ return headers
114
+
115
+ async def test_registration(self, server_data: Dict[str, Any]) -> Dict[str, Any]:
116
+ """
117
+ Test registration with authentication.
118
+
119
+ Args:
120
+ server_data: Server registration data
121
+
122
+ Returns:
123
+ Test result
124
+ """
125
+ try:
126
+ # Prepare JSON-RPC request
127
+ request_data = {
128
+ "jsonrpc": "2.0",
129
+ "id": 1,
130
+ "method": "proxy_registration",
131
+ "params": {
132
+ "operation": "register",
133
+ **server_data
134
+ }
135
+ }
136
+
137
+ logger.info(f"Testing registration for server: {server_data['server_id']}")
138
+ logger.debug(f"Request data: {json.dumps(request_data, indent=2)}")
139
+
140
+ # Make request
141
+ async with self.session.post(
142
+ f"{self.server_url}/cmd",
143
+ json=request_data,
144
+ headers=self._get_headers()
145
+ ) as response:
146
+ result = await response.json()
147
+
148
+ logger.info(f"Response status: {response.status}")
149
+ logger.debug(f"Response: {json.dumps(result, indent=2)}")
150
+
151
+ return {
152
+ "success": response.status == 200,
153
+ "status_code": response.status,
154
+ "result": result,
155
+ "server_id": server_data["server_id"]
156
+ }
157
+
158
+ except Exception as e:
159
+ logger.error(f"Registration test failed: {e}")
160
+ return {
161
+ "success": False,
162
+ "error": str(e),
163
+ "server_id": server_data["server_id"]
164
+ }
165
+
166
+ async def test_discovery(self) -> Dict[str, Any]:
167
+ """
168
+ Test discovery operation.
169
+
170
+ Returns:
171
+ Test result
172
+ """
173
+ try:
174
+ # Prepare JSON-RPC request
175
+ request_data = {
176
+ "jsonrpc": "2.0",
177
+ "id": 1,
178
+ "method": "proxy_registration",
179
+ "params": {
180
+ "operation": "discover"
181
+ }
182
+ }
183
+
184
+ logger.info("Testing discovery operation")
185
+
186
+ # Make request
187
+ async with self.session.post(
188
+ f"{self.server_url}/cmd",
189
+ json=request_data,
190
+ headers=self._get_headers()
191
+ ) as response:
192
+ result = await response.json()
193
+
194
+ logger.info(f"Response status: {response.status}")
195
+ logger.debug(f"Response: {json.dumps(result, indent=2)}")
196
+
197
+ return {
198
+ "success": response.status == 200,
199
+ "status_code": response.status,
200
+ "result": result
201
+ }
202
+
203
+ except Exception as e:
204
+ logger.error(f"Discovery test failed: {e}")
205
+ return {
206
+ "success": False,
207
+ "error": str(e)
208
+ }
209
+
210
+ async def test_heartbeat(self, server_key: str) -> Dict[str, Any]:
211
+ """
212
+ Test heartbeat operation.
213
+
214
+ Args:
215
+ server_key: Server key for heartbeat
216
+
217
+ Returns:
218
+ Test result
219
+ """
220
+ try:
221
+ # Prepare JSON-RPC request
222
+ request_data = {
223
+ "jsonrpc": "2.0",
224
+ "id": 1,
225
+ "method": "proxy_registration",
226
+ "params": {
227
+ "operation": "heartbeat",
228
+ "server_key": server_key,
229
+ "timestamp": 1234567890,
230
+ "status": "healthy"
231
+ }
232
+ }
233
+
234
+ logger.info(f"Testing heartbeat for server: {server_key}")
235
+
236
+ # Make request
237
+ async with self.session.post(
238
+ f"{self.server_url}/cmd",
239
+ json=request_data,
240
+ headers=self._get_headers()
241
+ ) as response:
242
+ result = await response.json()
243
+
244
+ logger.info(f"Response status: {response.status}")
245
+ logger.debug(f"Response: {json.dumps(result, indent=2)}")
246
+
247
+ return {
248
+ "success": response.status == 200,
249
+ "status_code": response.status,
250
+ "result": result,
251
+ "server_key": server_key
252
+ }
253
+
254
+ except Exception as e:
255
+ logger.error(f"Heartbeat test failed: {e}")
256
+ return {
257
+ "success": False,
258
+ "error": str(e),
259
+ "server_key": server_key
260
+ }
261
+
262
+
263
+ async def run_proxy_registration_example():
264
+ """Run proxy registration example."""
265
+ logger.info("🚀 Starting proxy registration example")
266
+
267
+ # Test configurations
268
+ test_configs = [
269
+ {
270
+ "name": "Admin Token",
271
+ "server_url": "http://localhost:8002",
272
+ "auth_token": "test-token-123"
273
+ },
274
+ {
275
+ "name": "User Token",
276
+ "server_url": "http://localhost:8002",
277
+ "auth_token": "user-token-456"
278
+ },
279
+ {
280
+ "name": "Readonly Token",
281
+ "server_url": "http://localhost:8002",
282
+ "auth_token": "readonly-token-123"
283
+ }
284
+ ]
285
+
286
+ results = []
287
+
288
+ for config in test_configs:
289
+ logger.info(f"\n📋 Testing: {config['name']}")
290
+ logger.info(f"Server URL: {config['server_url']}")
291
+ logger.info(f"Auth Token: {config['auth_token']}")
292
+
293
+ async with ProxyRegistrationExample(
294
+ config['server_url'],
295
+ config['auth_token']
296
+ ) as client:
297
+ # Test registration
298
+ for server_data in client.test_servers:
299
+ result = await client.test_registration(server_data)
300
+ results.append({
301
+ "test": f"{config['name']} - Registration",
302
+ "server_id": server_data["server_id"],
303
+ **result
304
+ })
305
+
306
+ # If registration successful, test heartbeat
307
+ if result["success"] and "result" in result:
308
+ server_key = result["result"].get("result", {}).get("server_key")
309
+ if server_key:
310
+ heartbeat_result = await client.test_heartbeat(server_key)
311
+ results.append({
312
+ "test": f"{config['name']} - Heartbeat",
313
+ "server_key": server_key,
314
+ **heartbeat_result
315
+ })
316
+
317
+ # Test discovery
318
+ discovery_result = await client.test_discovery()
319
+ results.append({
320
+ "test": f"{config['name']} - Discovery",
321
+ **discovery_result
322
+ })
323
+
324
+ # Test without authentication
325
+ logger.info(f"\n📋 Testing: No Authentication")
326
+ async with ProxyRegistrationExample("http://localhost:8002") as client:
327
+ for server_data in client.test_servers:
328
+ result = await client.test_registration(server_data)
329
+ results.append({
330
+ "test": "No Auth - Registration",
331
+ "server_id": server_data["server_id"],
332
+ **result
333
+ })
334
+
335
+ # Print results
336
+ logger.info("\n" + "="*80)
337
+ logger.info("📊 EXAMPLE RESULTS")
338
+ logger.info("="*80)
339
+
340
+ passed = 0
341
+ failed = 0
342
+
343
+ for result in results:
344
+ status = "✅ PASS" if result["success"] else "❌ FAIL"
345
+ logger.info(f"{status} {result['test']}")
346
+
347
+ if result["success"]:
348
+ passed += 1
349
+ else:
350
+ failed += 1
351
+
352
+ if "error" in result:
353
+ logger.error(f" Error: {result['error']}")
354
+ elif "result" in result:
355
+ result_data = result["result"]
356
+ if "error" in result_data:
357
+ logger.error(f" API Error: {result_data['error']}")
358
+ elif "result" in result_data:
359
+ api_result = result_data["result"]
360
+ if "server_key" in api_result:
361
+ logger.info(f" Server Key: {api_result['server_key']}")
362
+ if "message" in api_result:
363
+ logger.info(f" Message: {api_result['message']}")
364
+
365
+ logger.info("\n" + "="*80)
366
+ logger.info(f"📈 SUMMARY: {passed} passed, {failed} failed")
367
+ logger.info("="*80)
368
+
369
+ return passed, failed
370
+
371
+
372
+ def main():
373
+ """Main function for the example."""
374
+ logger.info("🔧 MCP Proxy Adapter - Proxy Registration Example")
375
+ logger.info("="*60)
376
+
377
+ # Check if server is running
378
+ import socket
379
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
380
+ result = sock.connect_ex(('localhost', 8002))
381
+ sock.close()
382
+
383
+ if result != 0:
384
+ logger.error("❌ Server is not running on localhost:8002")
385
+ logger.info("💡 Please start the server first:")
386
+ logger.info(" cd mcp_proxy_adapter/examples")
387
+ logger.info(" python -m mcp_proxy_adapter.main --config server_configs/config_proxy_registration.json")
388
+ sys.exit(1)
389
+
390
+ logger.info("✅ Server is running on localhost:8002")
391
+ logger.info("🚀 Starting proxy registration example...")
392
+
393
+ # Run example
394
+ passed, failed = asyncio.run(run_proxy_registration_example())
395
+
396
+ # Exit with appropriate code
397
+ sys.exit(0 if failed == 0 else 1)
398
+
399
+
400
+ if __name__ == "__main__":
401
+ main()
@@ -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,81 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Example Runner Script
4
+
5
+ This script provides a simple way to run the examples.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ import sys
12
+ import subprocess
13
+ import argparse
14
+ from pathlib import Path
15
+
16
+
17
+ def run_basic_example(config_name: str, port: int = None):
18
+ """Run basic framework example."""
19
+ config_path = Path(__file__).parent / "basic_framework" / "configs" / f"{config_name}.json"
20
+ main_script = Path(__file__).parent / "basic_framework" / "main.py"
21
+
22
+ if not config_path.exists():
23
+ print(f"❌ Configuration file not found: {config_path}")
24
+ return False
25
+
26
+ cmd = [sys.executable, str(main_script), "--config", str(config_path)]
27
+ if port:
28
+ cmd.extend(["--port", str(port)])
29
+
30
+ print(f"🚀 Running basic framework example with {config_name} configuration...")
31
+ return subprocess.run(cmd).returncode == 0
32
+
33
+
34
+ def run_full_example(config_name: str, port: int = None):
35
+ """Run full application example."""
36
+ config_path = Path(__file__).parent / "full_application" / "configs" / f"{config_name}.json"
37
+ main_script = Path(__file__).parent / "full_application" / "main.py"
38
+
39
+ if not config_path.exists():
40
+ print(f"❌ Configuration file not found: {config_path}")
41
+ return False
42
+
43
+ cmd = [sys.executable, str(main_script), "--config", str(config_path)]
44
+ if port:
45
+ cmd.extend(["--port", str(port)])
46
+
47
+ print(f"🚀 Running full application example with {config_name} configuration...")
48
+ return subprocess.run(cmd).returncode == 0
49
+
50
+
51
+ def main():
52
+ """Main function."""
53
+ parser = argparse.ArgumentParser(description="Run MCP Proxy Adapter Examples")
54
+ parser.add_argument("example", choices=["basic", "full"], help="Example type")
55
+ parser.add_argument("config", help="Configuration name (e.g., http_simple, https_auth)")
56
+ parser.add_argument("--port", type=int, help="Override port")
57
+
58
+ args = parser.parse_args()
59
+
60
+ # Available configurations
61
+ configs = [
62
+ "http_simple", "https_simple", "http_auth",
63
+ "https_auth", "mtls_no_roles", "mtls_with_roles"
64
+ ]
65
+
66
+ if args.config not in configs:
67
+ print(f"❌ Unknown configuration: {args.config}")
68
+ print(f"Available configurations: {', '.join(configs)}")
69
+ return 1
70
+
71
+ # Run the appropriate example
72
+ if args.example == "basic":
73
+ success = run_basic_example(args.config, args.port)
74
+ else:
75
+ success = run_full_example(args.config, args.port)
76
+
77
+ return 0 if success else 1
78
+
79
+
80
+ if __name__ == "__main__":
81
+ sys.exit(main())