mcp-proxy-adapter 2.0.1__py3-none-any.whl → 6.9.50__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.

Potentially problematic release.


This version of mcp-proxy-adapter might be problematic. Click here for more details.

Files changed (269) hide show
  1. mcp_proxy_adapter/__init__.py +47 -0
  2. mcp_proxy_adapter/__main__.py +13 -0
  3. mcp_proxy_adapter/api/__init__.py +0 -0
  4. mcp_proxy_adapter/api/app.py +66 -0
  5. mcp_proxy_adapter/api/core/__init__.py +18 -0
  6. mcp_proxy_adapter/api/core/app_factory.py +400 -0
  7. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  8. mcp_proxy_adapter/api/core/registration_context.py +356 -0
  9. mcp_proxy_adapter/api/core/registration_manager.py +307 -0
  10. mcp_proxy_adapter/api/core/registration_tasks.py +84 -0
  11. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  12. mcp_proxy_adapter/api/handlers.py +181 -0
  13. mcp_proxy_adapter/api/middleware/__init__.py +21 -0
  14. mcp_proxy_adapter/api/middleware/base.py +54 -0
  15. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +73 -0
  16. mcp_proxy_adapter/api/middleware/error_handling.py +76 -0
  17. mcp_proxy_adapter/api/middleware/factory.py +147 -0
  18. mcp_proxy_adapter/api/middleware/logging.py +31 -0
  19. mcp_proxy_adapter/api/middleware/performance.py +51 -0
  20. mcp_proxy_adapter/api/middleware/protocol_middleware.py +140 -0
  21. mcp_proxy_adapter/api/middleware/transport_middleware.py +87 -0
  22. mcp_proxy_adapter/api/middleware/unified_security.py +223 -0
  23. mcp_proxy_adapter/api/middleware/user_info_middleware.py +132 -0
  24. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  25. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  26. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  27. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  28. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  29. mcp_proxy_adapter/api/schemas.py +270 -0
  30. mcp_proxy_adapter/api/tool_integration.py +131 -0
  31. mcp_proxy_adapter/api/tools.py +163 -0
  32. mcp_proxy_adapter/cli/__init__.py +12 -0
  33. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  34. mcp_proxy_adapter/cli/commands/client.py +100 -0
  35. mcp_proxy_adapter/cli/commands/config_generate.py +105 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +94 -0
  37. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  38. mcp_proxy_adapter/cli/commands/server.py +174 -0
  39. mcp_proxy_adapter/cli/commands/sets.py +132 -0
  40. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  41. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  42. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  43. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  44. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  45. mcp_proxy_adapter/cli/main.py +63 -0
  46. mcp_proxy_adapter/cli/parser.py +338 -0
  47. mcp_proxy_adapter/cli/validators.py +231 -0
  48. mcp_proxy_adapter/client/jsonrpc_client/__init__.py +9 -0
  49. mcp_proxy_adapter/client/jsonrpc_client/client.py +42 -0
  50. mcp_proxy_adapter/client/jsonrpc_client/command_api.py +45 -0
  51. mcp_proxy_adapter/client/jsonrpc_client/proxy_api.py +224 -0
  52. mcp_proxy_adapter/client/jsonrpc_client/queue_api.py +60 -0
  53. mcp_proxy_adapter/client/jsonrpc_client/transport.py +108 -0
  54. mcp_proxy_adapter/client/proxy.py +123 -0
  55. mcp_proxy_adapter/commands/__init__.py +66 -0
  56. mcp_proxy_adapter/commands/auth_validation_command.py +69 -0
  57. mcp_proxy_adapter/commands/base.py +389 -0
  58. mcp_proxy_adapter/commands/builtin_commands.py +30 -0
  59. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  60. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  61. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  62. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  63. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  64. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  65. mcp_proxy_adapter/commands/catalog_manager.py +97 -0
  66. mcp_proxy_adapter/commands/cert_monitor_command.py +552 -0
  67. mcp_proxy_adapter/commands/certificate_management_command.py +562 -0
  68. mcp_proxy_adapter/commands/command_registry.py +298 -0
  69. mcp_proxy_adapter/commands/config_command.py +102 -0
  70. mcp_proxy_adapter/commands/dependency_container.py +40 -0
  71. mcp_proxy_adapter/commands/dependency_manager.py +143 -0
  72. mcp_proxy_adapter/commands/echo_command.py +48 -0
  73. mcp_proxy_adapter/commands/health_command.py +142 -0
  74. mcp_proxy_adapter/commands/help_command.py +175 -0
  75. mcp_proxy_adapter/commands/hooks.py +172 -0
  76. mcp_proxy_adapter/commands/key_management_command.py +484 -0
  77. mcp_proxy_adapter/commands/load_command.py +123 -0
  78. mcp_proxy_adapter/commands/plugins_command.py +246 -0
  79. mcp_proxy_adapter/commands/protocol_management_command.py +216 -0
  80. mcp_proxy_adapter/commands/proxy_registration_command.py +319 -0
  81. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  82. mcp_proxy_adapter/commands/registration_status_command.py +76 -0
  83. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  84. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  85. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  86. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  87. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  88. mcp_proxy_adapter/commands/reload_command.py +136 -0
  89. mcp_proxy_adapter/commands/result.py +157 -0
  90. mcp_proxy_adapter/commands/role_test_command.py +99 -0
  91. mcp_proxy_adapter/commands/roles_management_command.py +502 -0
  92. mcp_proxy_adapter/commands/security_command.py +472 -0
  93. mcp_proxy_adapter/commands/settings_command.py +113 -0
  94. mcp_proxy_adapter/commands/ssl_setup_command.py +306 -0
  95. mcp_proxy_adapter/commands/token_management_command.py +500 -0
  96. mcp_proxy_adapter/commands/transport_management_command.py +129 -0
  97. mcp_proxy_adapter/commands/unload_command.py +92 -0
  98. mcp_proxy_adapter/config.py +32 -0
  99. mcp_proxy_adapter/core/__init__.py +8 -0
  100. mcp_proxy_adapter/core/app_factory.py +560 -0
  101. mcp_proxy_adapter/core/app_runner.py +318 -0
  102. mcp_proxy_adapter/core/auth_validator.py +508 -0
  103. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  104. mcp_proxy_adapter/core/certificate/certificate_creator.py +372 -0
  105. mcp_proxy_adapter/core/certificate/certificate_extractor.py +185 -0
  106. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  107. mcp_proxy_adapter/core/certificate/certificate_validator.py +481 -0
  108. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +65 -0
  109. mcp_proxy_adapter/core/certificate_utils.py +249 -0
  110. mcp_proxy_adapter/core/client.py +608 -0
  111. mcp_proxy_adapter/core/client_manager.py +271 -0
  112. mcp_proxy_adapter/core/client_security.py +411 -0
  113. mcp_proxy_adapter/core/config/__init__.py +18 -0
  114. mcp_proxy_adapter/core/config/config.py +237 -0
  115. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  116. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  117. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  118. mcp_proxy_adapter/core/config/simple_config.py +204 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +131 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +476 -0
  121. mcp_proxy_adapter/core/config_converter.py +252 -0
  122. mcp_proxy_adapter/core/config_validator.py +211 -0
  123. mcp_proxy_adapter/core/crl_utils.py +362 -0
  124. mcp_proxy_adapter/core/errors.py +276 -0
  125. mcp_proxy_adapter/core/job_manager.py +54 -0
  126. mcp_proxy_adapter/core/logging.py +250 -0
  127. mcp_proxy_adapter/core/mtls_asgi.py +140 -0
  128. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  129. mcp_proxy_adapter/core/mtls_proxy.py +229 -0
  130. mcp_proxy_adapter/core/mtls_server.py +154 -0
  131. mcp_proxy_adapter/core/protocol_manager.py +232 -0
  132. mcp_proxy_adapter/core/proxy/__init__.py +19 -0
  133. mcp_proxy_adapter/core/proxy/auth_manager.py +26 -0
  134. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +160 -0
  135. mcp_proxy_adapter/core/proxy/registration_client.py +186 -0
  136. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  137. mcp_proxy_adapter/core/proxy_client.py +184 -0
  138. mcp_proxy_adapter/core/proxy_registration.py +80 -0
  139. mcp_proxy_adapter/core/role_utils.py +103 -0
  140. mcp_proxy_adapter/core/security_adapter.py +343 -0
  141. mcp_proxy_adapter/core/security_factory.py +96 -0
  142. mcp_proxy_adapter/core/security_integration.py +342 -0
  143. mcp_proxy_adapter/core/server_adapter.py +251 -0
  144. mcp_proxy_adapter/core/server_engine.py +217 -0
  145. mcp_proxy_adapter/core/settings.py +260 -0
  146. mcp_proxy_adapter/core/signal_handler.py +107 -0
  147. mcp_proxy_adapter/core/ssl_utils.py +161 -0
  148. mcp_proxy_adapter/core/transport_manager.py +153 -0
  149. mcp_proxy_adapter/core/unified_config_adapter.py +471 -0
  150. mcp_proxy_adapter/core/utils.py +101 -0
  151. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  152. mcp_proxy_adapter/core/validation/config_validator.py +219 -0
  153. mcp_proxy_adapter/core/validation/file_validator.py +131 -0
  154. mcp_proxy_adapter/core/validation/protocol_validator.py +205 -0
  155. mcp_proxy_adapter/core/validation/security_validator.py +140 -0
  156. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  157. mcp_proxy_adapter/custom_openapi.py +58 -0
  158. mcp_proxy_adapter/examples/__init__.py +16 -0
  159. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  160. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  161. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  162. mcp_proxy_adapter/examples/basic_framework/main.py +52 -0
  163. mcp_proxy_adapter/examples/bugfix_certificate_config.py +261 -0
  164. mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
  165. mcp_proxy_adapter/examples/check_config.py +413 -0
  166. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  167. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  168. mcp_proxy_adapter/examples/config_builder.py +234 -0
  169. mcp_proxy_adapter/examples/config_cli.py +282 -0
  170. mcp_proxy_adapter/examples/create_test_configs.py +174 -0
  171. mcp_proxy_adapter/examples/debug_request_state.py +130 -0
  172. mcp_proxy_adapter/examples/debug_role_chain.py +191 -0
  173. mcp_proxy_adapter/examples/demo_client.py +287 -0
  174. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  175. mcp_proxy_adapter/examples/full_application/commands/__init__.py +8 -0
  176. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +45 -0
  177. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +52 -0
  178. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +32 -0
  179. mcp_proxy_adapter/examples/full_application/commands/help_command.py +54 -0
  180. mcp_proxy_adapter/examples/full_application/commands/list_command.py +57 -0
  181. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +5 -0
  182. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +29 -0
  183. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +27 -0
  184. mcp_proxy_adapter/examples/full_application/main.py +311 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +161 -0
  186. mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
  187. mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
  188. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +45 -0
  189. mcp_proxy_adapter/examples/full_application/test_server.py +163 -0
  190. mcp_proxy_adapter/examples/full_application/test_simple_server.py +62 -0
  191. mcp_proxy_adapter/examples/generate_config.py +502 -0
  192. mcp_proxy_adapter/examples/proxy_registration_example.py +335 -0
  193. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  194. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  195. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  196. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  197. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  198. mcp_proxy_adapter/examples/required_certificates.py +208 -0
  199. mcp_proxy_adapter/examples/run_example.py +77 -0
  200. mcp_proxy_adapter/examples/run_full_test_suite.py +619 -0
  201. mcp_proxy_adapter/examples/run_proxy_server.py +153 -0
  202. mcp_proxy_adapter/examples/run_security_tests_fixed.py +435 -0
  203. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  204. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  205. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  206. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  207. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  208. mcp_proxy_adapter/examples/security_test_client.py +72 -0
  209. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  210. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  211. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  212. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  213. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  214. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  215. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  216. mcp_proxy_adapter/examples/setup_test_environment.py +235 -0
  217. mcp_proxy_adapter/examples/simple_protocol_test.py +125 -0
  218. mcp_proxy_adapter/examples/test_chk_hostname_automated.py +211 -0
  219. mcp_proxy_adapter/examples/test_config.py +205 -0
  220. mcp_proxy_adapter/examples/test_config_builder.py +110 -0
  221. mcp_proxy_adapter/examples/test_examples.py +308 -0
  222. mcp_proxy_adapter/examples/test_framework_complete.py +267 -0
  223. mcp_proxy_adapter/examples/test_mcp_server.py +187 -0
  224. mcp_proxy_adapter/examples/test_protocol_examples.py +337 -0
  225. mcp_proxy_adapter/examples/universal_client.py +674 -0
  226. mcp_proxy_adapter/examples/update_config_certificates.py +135 -0
  227. mcp_proxy_adapter/examples/validate_generator_compatibility.py +385 -0
  228. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +61 -0
  229. mcp_proxy_adapter/integrations/__init__.py +25 -0
  230. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  231. mcp_proxy_adapter/main.py +311 -0
  232. mcp_proxy_adapter/openapi.py +375 -0
  233. mcp_proxy_adapter/schemas/base_schema.json +114 -0
  234. mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
  235. mcp_proxy_adapter/schemas/roles.json +37 -0
  236. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  237. mcp_proxy_adapter/version.py +5 -0
  238. mcp_proxy_adapter-6.9.50.dist-info/METADATA +1088 -0
  239. mcp_proxy_adapter-6.9.50.dist-info/RECORD +242 -0
  240. {mcp_proxy_adapter-2.0.1.dist-info → mcp_proxy_adapter-6.9.50.dist-info}/WHEEL +1 -1
  241. mcp_proxy_adapter-6.9.50.dist-info/entry_points.txt +14 -0
  242. mcp_proxy_adapter-6.9.50.dist-info/top_level.txt +1 -0
  243. adapters/__init__.py +0 -16
  244. analyzers/__init__.py +0 -14
  245. analyzers/docstring_analyzer.py +0 -199
  246. analyzers/type_analyzer.py +0 -151
  247. cli/__init__.py +0 -12
  248. cli/__main__.py +0 -79
  249. cli/command_runner.py +0 -233
  250. dispatchers/__init__.py +0 -14
  251. dispatchers/base_dispatcher.py +0 -85
  252. dispatchers/json_rpc_dispatcher.py +0 -198
  253. generators/__init__.py +0 -14
  254. generators/endpoint_generator.py +0 -172
  255. generators/openapi_generator.py +0 -254
  256. generators/rest_api_generator.py +0 -207
  257. mcp_proxy_adapter-2.0.1.dist-info/METADATA +0 -272
  258. mcp_proxy_adapter-2.0.1.dist-info/RECORD +0 -28
  259. mcp_proxy_adapter-2.0.1.dist-info/licenses/LICENSE +0 -21
  260. mcp_proxy_adapter-2.0.1.dist-info/top_level.txt +0 -7
  261. openapi_schema/__init__.py +0 -38
  262. openapi_schema/command_registry.py +0 -312
  263. openapi_schema/rest_schema.py +0 -510
  264. openapi_schema/rpc_generator.py +0 -307
  265. openapi_schema/rpc_schema.py +0 -416
  266. validators/__init__.py +0 -14
  267. validators/base_validator.py +0 -23
  268. validators/docstring_validator.py +0 -75
  269. validators/metadata_validator.py +0 -76
@@ -0,0 +1,161 @@
1
+ """
2
+ Proxy Registration Endpoints
3
+ This module provides proxy registration endpoints for testing.
4
+ Author: Vasiliy Zdanovskiy
5
+ email: vasilyvz@gmail.com
6
+ """
7
+
8
+ from fastapi import APIRouter, HTTPException
9
+ from pydantic import BaseModel
10
+ from typing import Dict, List, Optional, Any
11
+ import time
12
+ import uuid
13
+
14
+ # In-memory registry for testing
15
+ _registry: Dict[str, Dict] = {}
16
+ router = APIRouter(prefix="/proxy", tags=["proxy"])
17
+
18
+
19
+ class ServerRegistration(BaseModel):
20
+ """Server registration request model."""
21
+
22
+ server_id: str
23
+ server_url: str
24
+ server_name: str
25
+ description: Optional[str] = None
26
+ version: Optional[str] = "1.0.0"
27
+ capabilities: Optional[List[str]] = None
28
+ endpoints: Optional[Dict[str, str]] = None
29
+ auth_method: Optional[str] = "none"
30
+ security_enabled: Optional[bool] = False
31
+
32
+
33
+ class ServerUnregistration(BaseModel):
34
+ """Server unregistration request model."""
35
+
36
+ server_key: str # Use server_key directly
37
+
38
+
39
+ class HeartbeatData(BaseModel):
40
+ """Heartbeat data model."""
41
+
42
+ server_id: str
43
+ server_key: str
44
+ timestamp: Optional[int] = None
45
+ status: Optional[str] = "healthy"
46
+
47
+
48
+ class RegistrationResponse(BaseModel):
49
+ """Registration response model."""
50
+
51
+ success: bool
52
+ server_key: str
53
+ message: str
54
+ copy_number: int
55
+
56
+
57
+ class DiscoveryResponse(BaseModel):
58
+ """Discovery response model."""
59
+
60
+ success: bool
61
+ servers: List[Dict]
62
+ total: int
63
+ active: int
64
+
65
+
66
+ @router.post("/register", response_model=RegistrationResponse)
67
+ async def register_server(data: ServerRegistration) -> RegistrationResponse:
68
+ """Register a server with the proxy."""
69
+ server_key = str(uuid.uuid4())
70
+ copy_number = 1
71
+ if data.server_id in _registry:
72
+ copy_number = len(_registry[data.server_id]) + 1
73
+
74
+ if data.server_id not in _registry:
75
+ _registry[data.server_id] = {}
76
+
77
+ _registry[data.server_id][server_key] = {
78
+ "server_id": data.server_id,
79
+ "server_url": data.server_url,
80
+ "server_name": data.server_name,
81
+ "description": data.description,
82
+ "version": data.version,
83
+ "capabilities": data.capabilities or [],
84
+ "endpoints": data.endpoints or {},
85
+ "auth_method": data.auth_method,
86
+ "security_enabled": data.security_enabled,
87
+ "registered_at": time.time(),
88
+ "last_heartbeat": time.time(),
89
+ }
90
+
91
+ return RegistrationResponse(
92
+ success=True,
93
+ server_key=server_key,
94
+ message=f"Server {data.server_name} registered successfully",
95
+ copy_number=copy_number,
96
+ )
97
+
98
+
99
+ @router.post("/unregister")
100
+ async def unregister_server(data: ServerUnregistration) -> Dict[str, Any]:
101
+ """Unregister a server from the proxy."""
102
+ for server_id, instances in _registry.items():
103
+ if data.server_key in instances:
104
+ del instances[data.server_key]
105
+ if not instances:
106
+ del _registry[server_id]
107
+ return {"success": True, "message": "Server unregistered"}
108
+ raise HTTPException(status_code=404, detail="Server not found")
109
+
110
+
111
+ @router.post("/heartbeat")
112
+ async def heartbeat(data: HeartbeatData) -> Dict[str, Any]:
113
+ """Update server heartbeat."""
114
+ for server_id, instances in _registry.items():
115
+ if data.server_key in instances:
116
+ instances[data.server_key]["last_heartbeat"] = data.timestamp or time.time()
117
+ instances[data.server_key]["status"] = data.status
118
+ return {"success": True, "message": "Heartbeat updated"}
119
+ raise HTTPException(status_code=404, detail="Server not found")
120
+
121
+
122
+ @router.get("/discover", response_model=DiscoveryResponse)
123
+ async def discover_servers() -> DiscoveryResponse:
124
+ """Discover all registered servers."""
125
+ servers = []
126
+ for server_id, instances in _registry.items():
127
+ for server_key, server_data in instances.items():
128
+ servers.append({**server_data, "server_key": server_key})
129
+
130
+ active = sum(1 for s in servers if time.time() - s.get("last_heartbeat", 0) < 60)
131
+ return DiscoveryResponse(
132
+ success=True,
133
+ servers=servers,
134
+ total=len(servers),
135
+ active=active,
136
+ )
137
+
138
+
139
+ @router.get("/status")
140
+ async def get_status() -> Dict[str, Any]:
141
+ """Get proxy status."""
142
+ total_servers = sum(len(instances) for instances in _registry.values())
143
+ active_servers = sum(
144
+ 1
145
+ for instances in _registry.values()
146
+ for server_data in instances.values()
147
+ if time.time() - server_data.get("last_heartbeat", 0) < 60
148
+ )
149
+ return {
150
+ "status": "running",
151
+ "total_servers": total_servers,
152
+ "active_servers": active_servers,
153
+ "registered_ids": list(_registry.keys()),
154
+ }
155
+
156
+
157
+ @router.delete("/clear")
158
+ async def clear_registry() -> Dict[str, Any]:
159
+ """Clear all registrations (for testing)."""
160
+ _registry.clear()
161
+ return {"success": True, "message": "Registry cleared"}
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ mTLS Full Application Runner
4
+ Runs the full application example with mTLS configuration.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ import sys
11
+ import argparse
12
+ import logging
13
+ import json
14
+ import ssl
15
+ import socket
16
+ from pathlib import Path
17
+
18
+ # Add the framework to the path
19
+ sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
20
+
21
+ def validate_mtls_config(config_path: str) -> bool:
22
+ """Validate mTLS configuration file."""
23
+ try:
24
+ with open(config_path, 'r') as f:
25
+ config = json.load(f)
26
+
27
+ # Check required sections
28
+ required_sections = [
29
+ 'uuid', 'server', 'logging', 'commands', 'transport',
30
+ 'proxy_registration', 'debug', 'security', 'roles', 'ssl'
31
+ ]
32
+
33
+ missing_sections = []
34
+ for section in required_sections:
35
+ if section not in config:
36
+ missing_sections.append(section)
37
+
38
+ if missing_sections:
39
+ print(f"❌ Missing required sections: {missing_sections}")
40
+ return False
41
+
42
+ # Check SSL configuration
43
+ ssl_config = config.get('ssl', {})
44
+ if not ssl_config.get('enabled', False):
45
+ print("❌ SSL must be enabled for mTLS")
46
+ return False
47
+
48
+ # Check certificate files
49
+ cert_file = ssl_config.get('cert_file')
50
+ key_file = ssl_config.get('key_file')
51
+ ca_cert_file = ssl_config.get('ca_cert_file')
52
+
53
+ if not cert_file or not key_file or not ca_cert_file:
54
+ print("❌ SSL configuration missing certificate files")
55
+ return False
56
+
57
+ # Check if certificate files exist
58
+ cert_path = Path(cert_file)
59
+ key_path = Path(key_file)
60
+ ca_path = Path(ca_cert_file)
61
+
62
+ if not cert_path.exists():
63
+ print(f"❌ Certificate file not found: {cert_file}")
64
+ return False
65
+
66
+ if not key_path.exists():
67
+ print(f"❌ Key file not found: {key_file}")
68
+ return False
69
+
70
+ if not ca_path.exists():
71
+ print(f"❌ CA certificate file not found: {ca_cert_file}")
72
+ return False
73
+
74
+ print("✅ mTLS Configuration validation passed")
75
+ return True
76
+
77
+ except FileNotFoundError:
78
+ print(f"❌ Configuration file not found: {config_path}")
79
+ return False
80
+ except json.JSONDecodeError as e:
81
+ print(f"❌ Invalid JSON in configuration: {e}")
82
+ return False
83
+ except Exception as e:
84
+ print(f"❌ Configuration validation error: {e}")
85
+ return False
86
+
87
+ def test_mtls_connection(config_path: str):
88
+ """Test mTLS connection to the server."""
89
+ try:
90
+ with open(config_path, 'r') as f:
91
+ config = json.load(f)
92
+
93
+ server_config = config.get('server', {})
94
+ host = server_config.get('host', '0.0.0.0')
95
+ port = server_config.get('port', 8443)
96
+
97
+ ssl_config = config.get('ssl', {})
98
+ cert_file = ssl_config.get('cert_file')
99
+ key_file = ssl_config.get('key_file')
100
+ ca_cert_file = ssl_config.get('ca_cert_file')
101
+
102
+ print(f"🔐 Testing mTLS connection to {host}:{port}")
103
+
104
+ # Create SSL context
105
+ context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
106
+ context.load_cert_chain(cert_file, key_file)
107
+ context.load_verify_locations(ca_cert_file)
108
+ context.verify_mode = ssl.CERT_REQUIRED
109
+
110
+ # Test connection
111
+ with socket.create_connection((host, port), timeout=5) as sock:
112
+ with context.wrap_socket(sock, server_hostname=host) as ssock:
113
+ print(f"✅ mTLS connection successful")
114
+ print(f"🔒 Cipher: {ssock.cipher()}")
115
+ print(f"📜 Protocol: {ssock.version()}")
116
+ return True
117
+
118
+ except Exception as e:
119
+ print(f"❌ mTLS connection failed: {e}")
120
+ return False
121
+
122
+ def run_mtls_application(config_path: str):
123
+ """Run the mTLS application example."""
124
+ print("🚀 Starting mTLS Full Application Example")
125
+ print(f"📁 Configuration: {config_path}")
126
+
127
+ # Validate configuration
128
+ if not validate_mtls_config(config_path):
129
+ print("❌ mTLS Configuration validation failed")
130
+ return False
131
+
132
+ # Load configuration
133
+ try:
134
+ with open(config_path, 'r') as f:
135
+ config = json.load(f)
136
+
137
+ server_config = config.get('server', {})
138
+ host = server_config.get('host', '0.0.0.0')
139
+ port = server_config.get('port', 8443)
140
+ protocol = server_config.get('protocol', 'https')
141
+
142
+ ssl_config = config.get('ssl', {})
143
+ proxy_config = config.get('proxy_registration', {})
144
+
145
+ print(f"🌐 Server: {host}:{port}")
146
+ print(f"🔗 Protocol: {protocol}")
147
+ print(f"🔒 SSL: {'Enabled' if ssl_config.get('enabled', False) else 'Disabled'}")
148
+ print(f"🔐 mTLS: {'Enabled' if ssl_config.get('verify_client', False) else 'Disabled'}")
149
+ print(f"🔒 Security: {'Enabled' if config.get('security', {}).get('enabled', False) else 'Disabled'}")
150
+ print(f"👥 Roles: {'Enabled' if config.get('roles', {}).get('enabled', False) else 'Disabled'}")
151
+ print(f"🌐 Proxy Registration: {'Enabled' if proxy_config.get('enabled', False) else 'Disabled'}")
152
+
153
+ if proxy_config.get('enabled', False):
154
+ proxy_url = proxy_config.get('proxy_url', 'https://localhost:3004')
155
+ server_id = proxy_config.get('server_id', 'unknown')
156
+ print(f"📡 Proxy URL: {proxy_url}")
157
+ print(f"🆔 Server ID: {server_id}")
158
+
159
+ # Simulate application startup
160
+ print("\n🔧 Setting up mTLS application components...")
161
+ print("✅ Configuration loaded and validated")
162
+ print("✅ SSL/TLS certificates loaded")
163
+ print("✅ mTLS context created")
164
+ print("✅ Logging configured")
165
+ print("✅ Command registry initialized")
166
+ print("✅ Transport layer configured with mTLS")
167
+ print("✅ Security layer configured")
168
+ print("✅ Proxy registration configured")
169
+
170
+ if proxy_config.get('enabled', False):
171
+ print("✅ Proxy registration enabled")
172
+ print(f"📡 Will register with proxy at: {proxy_config.get('proxy_url')}")
173
+ print(f"🆔 Server ID: {proxy_config.get('server_id')}")
174
+
175
+ print(f"\n🎉 mTLS Full Application Example started successfully!")
176
+ print(f"📡 Server listening on {host}:{port}")
177
+ print(f"🌐 Access via: {protocol}://{host}:{port}")
178
+ print("\n📋 Available features:")
179
+ print(" - Built-in commands (health, echo, list, help)")
180
+ print(" - Custom commands (custom_echo, dynamic_calculator)")
181
+ print(" - Application hooks")
182
+ print(" - Command hooks")
183
+ print(" - Proxy endpoints")
184
+ print(" - mTLS authentication")
185
+ print(" - Security (if enabled)")
186
+ print(" - Role management (if enabled)")
187
+
188
+ print("\n🔐 mTLS Configuration:")
189
+ print(f" - Certificate: {ssl_config.get('cert_file')}")
190
+ print(f" - Private Key: {ssl_config.get('key_file')}")
191
+ print(f" - CA Certificate: {ssl_config.get('ca_cert_file')}")
192
+ print(f" - Client Verification: {'Required' if ssl_config.get('verify_client', False) else 'Optional'}")
193
+ print(f" - Ciphers: {ssl_config.get('ciphers', 'Default')}")
194
+ print(f" - Protocols: {ssl_config.get('protocols', 'Default')}")
195
+
196
+ print("\n✅ mTLS Application simulation completed successfully")
197
+ print("💡 In a real application, the mTLS server would be running here")
198
+ return True
199
+
200
+ except Exception as e:
201
+ print(f"❌ Application startup error: {e}")
202
+ return False
203
+
204
+ def main():
205
+ """Main function."""
206
+ parser = argparse.ArgumentParser(
207
+ description="Run mTLS Full Application Example",
208
+ formatter_class=argparse.RawDescriptionHelpFormatter,
209
+ epilog="""
210
+ Examples:
211
+ python run_mtls.py --config configs/mtls_no_roles_correct.json
212
+ python run_mtls.py --config configs/mtls_with_roles_correct.json
213
+ python run_mtls.py --config configs/mtls_no_roles_correct.json --test-connection
214
+ """
215
+ )
216
+
217
+ parser.add_argument(
218
+ "--config",
219
+ default="configs/mtls_no_roles_correct.json",
220
+ help="Configuration file path"
221
+ )
222
+
223
+ parser.add_argument(
224
+ "--test-connection",
225
+ action="store_true",
226
+ help="Test mTLS connection"
227
+ )
228
+
229
+ args = parser.parse_args()
230
+
231
+ # Check if config file exists
232
+ config_path = Path(args.config)
233
+ if not config_path.exists():
234
+ print(f"❌ Configuration file not found: {config_path}")
235
+ print("💡 Available mTLS configurations:")
236
+ configs_dir = Path("configs")
237
+ if configs_dir.exists():
238
+ for config_file in configs_dir.glob("*mtls*.json"):
239
+ print(f" - {config_file}")
240
+ return 1
241
+
242
+ # Test connection if requested
243
+ if args.test_connection:
244
+ success = test_mtls_connection(str(config_path))
245
+ return 0 if success else 1
246
+
247
+ # Run application
248
+ success = run_mtls_application(str(config_path))
249
+ return 0 if success else 1
250
+
251
+ if __name__ == "__main__":
252
+ sys.exit(main())
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simple Full Application Runner
4
+ Runs the full application example without complex imports.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ import sys
11
+ import argparse
12
+ import logging
13
+ import json
14
+ from pathlib import Path
15
+
16
+ # Add the framework to the path
17
+ sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
18
+
19
+ def validate_config(config_path: str) -> bool:
20
+ """Validate configuration file."""
21
+ try:
22
+ with open(config_path, 'r') as f:
23
+ config = json.load(f)
24
+
25
+ # Check required sections
26
+ required_sections = [
27
+ 'uuid', 'server', 'logging', 'commands', 'transport',
28
+ 'proxy_registration', 'debug', 'security', 'roles'
29
+ ]
30
+
31
+ missing_sections = []
32
+ for section in required_sections:
33
+ if section not in config:
34
+ missing_sections.append(section)
35
+
36
+ if missing_sections:
37
+ print(f"❌ Missing required sections: {missing_sections}")
38
+ return False
39
+
40
+ # Check server section
41
+ server = config.get('server', {})
42
+ if 'host' not in server or 'port' not in server:
43
+ print("❌ Server section missing host or port")
44
+ return False
45
+
46
+ print("✅ Configuration validation passed")
47
+ return True
48
+
49
+ except FileNotFoundError:
50
+ print(f"❌ Configuration file not found: {config_path}")
51
+ return False
52
+ except json.JSONDecodeError as e:
53
+ print(f"❌ Invalid JSON in configuration: {e}")
54
+ return False
55
+ except Exception as e:
56
+ print(f"❌ Configuration validation error: {e}")
57
+ return False
58
+
59
+ def run_application(config_path: str):
60
+ """Run the full application example."""
61
+ print("🚀 Starting Full Application Example")
62
+ print(f"📁 Configuration: {config_path}")
63
+
64
+ # Validate configuration
65
+ if not validate_config(config_path):
66
+ print("❌ Configuration validation failed")
67
+ return False
68
+
69
+ # Load configuration
70
+ try:
71
+ with open(config_path, 'r') as f:
72
+ config = json.load(f)
73
+
74
+ server_config = config.get('server', {})
75
+ host = server_config.get('host', '0.0.0.0')
76
+ port = server_config.get('port', 8000)
77
+ protocol = server_config.get('protocol', 'http')
78
+
79
+ print(f"🌐 Server: {host}:{port}")
80
+ print(f"🔗 Protocol: {protocol}")
81
+ print(f"🔒 Security: {'Enabled' if config.get('security', {}).get('enabled', False) else 'Disabled'}")
82
+ print(f"👥 Roles: {'Enabled' if config.get('roles', {}).get('enabled', False) else 'Disabled'}")
83
+
84
+ # Simulate application startup
85
+ print("\n🔧 Setting up application components...")
86
+ print("✅ Configuration loaded")
87
+ print("✅ Logging configured")
88
+ print("✅ Command registry initialized")
89
+ print("✅ Transport layer configured")
90
+ print("✅ Security layer configured")
91
+ print("✅ Proxy registration configured")
92
+
93
+ print(f"\n🎉 Full Application Example started successfully!")
94
+ print(f"📡 Server listening on {host}:{port}")
95
+ print(f"🌐 Access via: {protocol}://{host}:{port}")
96
+ print("\n📋 Available features:")
97
+ print(" - Built-in commands (health, echo, list, help)")
98
+ print(" - Custom commands (custom_echo, dynamic_calculator)")
99
+ print(" - Application hooks")
100
+ print(" - Command hooks")
101
+ print(" - Proxy endpoints")
102
+ print(" - Security (if enabled)")
103
+ print(" - Role management (if enabled)")
104
+
105
+ print("\n🛑 Press Ctrl+C to stop the server")
106
+
107
+ # Simulate running server (non-blocking)
108
+ print("✅ Server simulation completed successfully")
109
+ print("💡 In a real application, the server would be running here")
110
+ return True
111
+
112
+ except Exception as e:
113
+ print(f"❌ Application startup error: {e}")
114
+ return False
115
+
116
+ def main():
117
+ """Main function."""
118
+ parser = argparse.ArgumentParser(
119
+ description="Run Full Application Example",
120
+ formatter_class=argparse.RawDescriptionHelpFormatter,
121
+ epilog="""
122
+ Examples:
123
+ python run_simple.py --config configs/http_simple_correct.json
124
+ python run_simple.py --config configs/http_auth_correct.json
125
+ """
126
+ )
127
+
128
+ parser.add_argument(
129
+ "--config",
130
+ default="configs/http_simple_correct.json",
131
+ help="Configuration file path"
132
+ )
133
+
134
+ args = parser.parse_args()
135
+
136
+ # Check if config file exists
137
+ config_path = Path(args.config)
138
+ if not config_path.exists():
139
+ print(f"❌ Configuration file not found: {config_path}")
140
+ print("💡 Available configurations:")
141
+ configs_dir = Path("configs")
142
+ if configs_dir.exists():
143
+ for config_file in configs_dir.glob("*.json"):
144
+ print(f" - {config_file}")
145
+ return 1
146
+
147
+ # Run application
148
+ success = run_application(str(config_path))
149
+ return 0 if success else 1
150
+
151
+ if __name__ == "__main__":
152
+ sys.exit(main())
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Minimal server test without lifespan issues.
4
+ """
5
+
6
+ import sys
7
+ import os
8
+ from pathlib import Path
9
+
10
+ # Add the project root to the path
11
+ project_root = Path(__file__).parent.parent.parent.parent
12
+ sys.path.insert(0, str(project_root))
13
+
14
+ from fastapi import FastAPI
15
+ import uvicorn
16
+
17
+ def main():
18
+ """Test minimal server startup."""
19
+ print("🚀 Testing Minimal Server Startup")
20
+ print("=" * 50)
21
+
22
+ # Create minimal FastAPI app
23
+ app = FastAPI(
24
+ title="Test Server",
25
+ description="Minimal test server",
26
+ version="1.0.0"
27
+ )
28
+
29
+ # Add health endpoint
30
+ @app.get("/health")
31
+
32
+ # Add JSON-RPC endpoint
33
+ @app.post("/api/jsonrpc")
34
+
35
+ print("✅ FastAPI app created successfully")
36
+
37
+ # Start server
38
+ print("🚀 Starting server on http://0.0.0.0:8000")
39
+ print("📡 Test with: curl -X POST http://localhost:8000/api/jsonrpc -H 'Content-Type: application/json' -d '{\"jsonrpc\": \"2.0\", \"method\": \"health\", \"id\": 1}'")
40
+ print("🛑 Press Ctrl+C to stop")
41
+
42
+ uvicorn.run(app, host="0.0.0.0", port=8000)
43
+
44
+ if __name__ == "__main__":
45
+ main()