mcp-proxy-adapter 6.9.43__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 (242) 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 +355 -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 +266 -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 +35 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +74 -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 +128 -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 +388 -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 +116 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +100 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +380 -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 +190 -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 +13 -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 +264 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +81 -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 +313 -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.43.dist-info/METADATA +739 -0
  239. mcp_proxy_adapter-6.9.43.dist-info/RECORD +242 -0
  240. mcp_proxy_adapter-6.9.43.dist-info/WHEEL +5 -0
  241. mcp_proxy_adapter-6.9.43.dist-info/entry_points.txt +12 -0
  242. mcp_proxy_adapter-6.9.43.dist-info/top_level.txt +1 -0
@@ -0,0 +1,47 @@
1
+ """MCP Proxy API Service package.
2
+
3
+ This package provides a framework for creating JSON-RPC-enabled microservices.
4
+ """
5
+
6
+ from mcp_proxy_adapter.version import __version__
7
+ from mcp_proxy_adapter.api.app import create_app
8
+ from mcp_proxy_adapter.commands.base import Command
9
+ from mcp_proxy_adapter.commands.result import CommandResult, SuccessResult, ErrorResult
10
+ from mcp_proxy_adapter.commands.command_registry import registry
11
+ from mcp_proxy_adapter.core.errors import (
12
+ MicroserviceError,
13
+ CommandError,
14
+ ValidationError,
15
+ InvalidParamsError,
16
+ NotFoundError,
17
+ TimeoutError,
18
+ InternalError,
19
+ )
20
+
21
+ # CLI module
22
+ # Delayed import of CLI to avoid side effects during server startup
23
+ # CLI can be accessed via entrypoint `mcp-proxy-adapter` or `python -m mcp_proxy_adapter`
24
+ try:
25
+ from mcp_proxy_adapter.cli import main as cli_main
26
+ except Exception:
27
+ # Avoid import errors impacting library/server usage
28
+ cli_main = None
29
+
30
+ # Экспортируем основные классы и функции для удобного использования
31
+ __all__ = [
32
+ "__version__",
33
+ "create_app",
34
+ "Command",
35
+ "CommandResult",
36
+ "SuccessResult",
37
+ "ErrorResult",
38
+ "registry",
39
+ "MicroserviceError",
40
+ "CommandError",
41
+ "ValidationError",
42
+ "InvalidParamsError",
43
+ "NotFoundError",
44
+ "TimeoutError",
45
+ "InternalError",
46
+ "cli_main",
47
+ ]
@@ -0,0 +1,13 @@
1
+ """
2
+ MCP Proxy Adapter CLI Entry Point
3
+
4
+ This module allows running the CLI using: python -m mcp_proxy_adapter
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ from .cli.main import main
11
+
12
+ if __name__ == '__main__':
13
+ main()
File without changes
@@ -0,0 +1,66 @@
1
+ """
2
+ Module for FastAPI application setup.
3
+ """
4
+
5
+ from typing import Any, Dict, Optional
6
+
7
+ from fastapi import FastAPI
8
+
9
+ from .core import AppFactory, SSLContextFactory, RegistrationManager, LifespanManager
10
+
11
+
12
+
13
+
14
+ def create_lifespan(config_path: Optional[str] = None, current_config: Optional[Dict[str, Any]] = None):
15
+ """
16
+ Create lifespan manager for the FastAPI application.
17
+
18
+ Args:
19
+ config_path: Path to configuration file (optional)
20
+ current_config: Current configuration data (optional)
21
+
22
+ Returns:
23
+ Lifespan context manager
24
+ """
25
+ lifespan_manager = LifespanManager()
26
+ return lifespan_manager.create_lifespan(config_path, current_config)
27
+
28
+
29
+ def create_ssl_context(
30
+ app_config: Optional[Dict[str, Any]] = None
31
+ ) -> Optional[Any]:
32
+ """
33
+ Create SSL context based on configuration.
34
+
35
+ Args:
36
+ app_config: Application configuration dictionary (optional)
37
+
38
+ Returns:
39
+ SSL context if SSL is enabled and properly configured, None otherwise
40
+ """
41
+ ssl_factory = SSLContextFactory()
42
+ return ssl_factory.create_ssl_context(app_config)
43
+
44
+
45
+ def create_app(
46
+ title: Optional[str] = None,
47
+ description: Optional[str] = None,
48
+ version: Optional[str] = None,
49
+ app_config: Optional[Dict[str, Any]] = None,
50
+ config_path: Optional[str] = None,
51
+ ) -> FastAPI:
52
+ """
53
+ Creates and configures FastAPI application.
54
+
55
+ Args:
56
+ title: Application title (default: "MCP Proxy Adapter")
57
+ description: Application description (default: "JSON-RPC API for interacting with MCP Proxy")
58
+ version: Application version (default: "1.0.0")
59
+ app_config: Application configuration dictionary (optional)
60
+ config_path: Path to configuration file (optional)
61
+
62
+ Returns:
63
+ Configured FastAPI application.
64
+ """
65
+ app_factory = AppFactory()
66
+ return app_factory.create_app(title, description, version, app_config, config_path)
@@ -0,0 +1,18 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Core API utilities for MCP Proxy Adapter.
6
+ """
7
+
8
+ from .app_factory import AppFactory
9
+ from .ssl_context_factory import SSLContextFactory
10
+ from .registration_manager import RegistrationManager
11
+ from .lifespan_manager import LifespanManager
12
+
13
+ __all__ = [
14
+ "AppFactory",
15
+ "SSLContextFactory",
16
+ "RegistrationManager",
17
+ "LifespanManager",
18
+ ]
@@ -0,0 +1,355 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Application factory for MCP Proxy Adapter API.
6
+ """
7
+
8
+ from typing import Any, Dict, List, Optional, Union
9
+
10
+ from fastapi import FastAPI, Body
11
+ from mcp_proxy_adapter.api.handlers import (
12
+ handle_json_rpc,
13
+ handle_batch_json_rpc,
14
+ get_server_health,
15
+ get_commands_list,
16
+ )
17
+
18
+ # from mcp_proxy_adapter.api.middleware import setup_middleware
19
+ try:
20
+ from mcp_proxy_adapter.api.schemas import (
21
+ JsonRpcRequest,
22
+ JsonRpcSuccessResponse,
23
+ JsonRpcErrorResponse,
24
+ HealthResponse,
25
+ CommandListResponse,
26
+ APIToolDescription,
27
+ )
28
+ except Exception:
29
+ # If schemas are unavailable, define minimal type aliases to satisfy annotations
30
+ JsonRpcRequest = Dict[str, Any] # type: ignore
31
+ JsonRpcSuccessResponse = Dict[str, Any] # type: ignore
32
+ JsonRpcErrorResponse = Dict[str, Any] # type: ignore
33
+ HealthResponse = Dict[str, Any] # type: ignore
34
+ CommandListResponse = Dict[str, Any] # type: ignore
35
+ APIToolDescription = Dict[str, Any] # type: ignore
36
+
37
+ try:
38
+ from mcp_proxy_adapter.api.tools import get_tool_description, execute_tool
39
+ except Exception:
40
+ get_tool_description = None
41
+ execute_tool = None
42
+ from mcp_proxy_adapter.core.logging import get_global_logger
43
+ from mcp_proxy_adapter.custom_openapi import custom_openapi_with_fallback
44
+ from .ssl_context_factory import SSLContextFactory
45
+ from .lifespan_manager import LifespanManager
46
+
47
+
48
+ class AppFactory:
49
+ """Factory for creating FastAPI applications."""
50
+
51
+ def __init__(self):
52
+ """Initialize app factory."""
53
+ self.logger = get_global_logger()
54
+ self.ssl_factory = SSLContextFactory()
55
+ self.lifespan_manager = LifespanManager()
56
+
57
+ def create_app(
58
+ self,
59
+ title: Optional[str] = None,
60
+ description: Optional[str] = None,
61
+ version: Optional[str] = None,
62
+ app_config: Optional[Dict[str, Any]] = None,
63
+ config_path: Optional[str] = None,
64
+ ) -> FastAPI:
65
+ """
66
+ Creates and configures FastAPI application.
67
+
68
+ Args:
69
+ title: Application title (default: "MCP Proxy Adapter")
70
+ description: Application description (default: "JSON-RPC API for interacting with MCP Proxy")
71
+ version: Application version (default: "1.0.0")
72
+ app_config: Application configuration dictionary (optional)
73
+ config_path: Path to configuration file (optional)
74
+
75
+ Returns:
76
+ Configured FastAPI application.
77
+
78
+ Raises:
79
+ SystemExit: If authentication is enabled but required files are missing (security issue)
80
+ """
81
+ # Use provided configuration or fallback to global config
82
+ if app_config is not None:
83
+ if hasattr(app_config, "get_all"):
84
+ current_config = app_config.get_all()
85
+ elif hasattr(app_config, "keys"):
86
+ current_config = app_config
87
+ else:
88
+ # If app_config is not a dict-like object, use it as is
89
+ current_config = app_config
90
+ else:
91
+ # If no app_config provided, try to get global config
92
+ try:
93
+ from mcp_proxy_adapter.config import get_config
94
+
95
+ current_config = get_config().get_all()
96
+ except Exception:
97
+ # If global config is not available, create empty config
98
+ current_config = {}
99
+
100
+ # Debug: Check what config is passed to create_app
101
+ if app_config:
102
+ if hasattr(app_config, "keys"):
103
+ print(
104
+ f"🔍 Debug: create_app received app_config keys: {list(app_config.keys())}"
105
+ )
106
+ # Debug SSL configuration
107
+ protocol = app_config.get("server", {}).get("protocol", "http")
108
+ verify_client = app_config.get("transport", {}).get(
109
+ "verify_client", False
110
+ )
111
+ ssl_enabled = protocol in ["https", "mtls"] or verify_client
112
+ print(f"🔍 Debug: create_app SSL config: enabled={ssl_enabled}")
113
+ print(f"🔍 Debug: create_app protocol: {protocol}")
114
+ print(f"🔍 Debug: create_app verify_client: {verify_client}")
115
+ else:
116
+ print(
117
+ f"🔍 Debug: create_app received app_config type: {type(app_config)}"
118
+ )
119
+ else:
120
+ print("🔍 Debug: create_app received no app_config, using global config")
121
+
122
+ # Security check: Validate configuration strictly at startup (fail-fast)
123
+ self._validate_configuration(current_config)
124
+
125
+ # Security check: Validate all authentication configurations before startup
126
+ self._validate_security_configuration(current_config)
127
+
128
+ # Security check: Validate certificates at startup (fail-fast)
129
+ self._validate_certificates(current_config)
130
+
131
+ # Set default values
132
+ title = title or "MCP Proxy Adapter"
133
+ description = description or "JSON-RPC API for interacting with MCP Proxy"
134
+ version = version or "1.0.0"
135
+
136
+ # Create lifespan manager
137
+ lifespan = self.lifespan_manager.create_lifespan(config_path, current_config)
138
+
139
+ # Create FastAPI application
140
+ app = FastAPI(
141
+ title=title,
142
+ description=description,
143
+ version=version,
144
+ lifespan=lifespan,
145
+ )
146
+
147
+ # Setup middleware - disabled for now
148
+ # setup_middleware(app, current_config)
149
+
150
+ # Setup routes
151
+ self._setup_routes(app)
152
+
153
+ # Setup OpenAPI
154
+ app.openapi = lambda: custom_openapi_with_fallback(app)
155
+
156
+ return app
157
+
158
+ def _validate_configuration(self, current_config: Dict[str, Any]) -> None:
159
+ """Validate configuration at startup."""
160
+ try:
161
+ from mcp_proxy_adapter.core.validation.config_validator import (
162
+ ConfigValidator,
163
+ )
164
+
165
+ validator = ConfigValidator()
166
+ validator.config_data = current_config
167
+ validation_results = validator.validate_config()
168
+ errors = [r for r in validation_results if r.level == "error"]
169
+ warnings = [r for r in validation_results if r.level == "warning"]
170
+
171
+ if errors:
172
+ self.logger.critical(
173
+ "CRITICAL CONFIG ERROR: Invalid configuration at startup:"
174
+ )
175
+ for error in errors:
176
+ self.logger.critical(f" - {error.message}")
177
+ raise SystemExit(1)
178
+ for warning in warnings:
179
+ self.logger.warning(f"Config warning: {warning.message}")
180
+ except Exception as ex:
181
+ self.logger.error(f"Failed to run startup configuration validation: {ex}")
182
+
183
+ def _validate_security_configuration(self, current_config: Dict[str, Any]) -> None:
184
+ """Validate security configuration at startup."""
185
+ security_errors = []
186
+
187
+ print(f"🔍 Debug: current_config keys: {list(current_config.keys())}")
188
+ if "security" in current_config:
189
+ print(f"🔍 Debug: security config: {current_config['security']}")
190
+ if "roles" in current_config:
191
+ print(f"🔍 Debug: roles config: {current_config['roles']}")
192
+
193
+ # Check security framework configuration only if enabled
194
+ security_config = current_config.get("security", {})
195
+ if security_config.get("enabled", False):
196
+ # Validate security framework configuration
197
+ from mcp_proxy_adapter.core.unified_config_adapter import (
198
+ UnifiedConfigAdapter,
199
+ )
200
+
201
+ adapter = UnifiedConfigAdapter()
202
+ validation_result = adapter.validate_configuration(current_config)
203
+
204
+ if not validation_result.is_valid:
205
+ security_errors.extend(validation_result.errors)
206
+
207
+ # Check roles configuration only if enabled
208
+ # Roles validation is handled by UnifiedConfigAdapter in security section validation
209
+ # No need for separate validation here
210
+
211
+ # Fail if there are security errors
212
+ if security_errors:
213
+ self.logger.critical(
214
+ "CRITICAL SECURITY ERROR: Invalid security configuration at startup:"
215
+ )
216
+ for error in security_errors:
217
+ self.logger.critical(f" - {error}")
218
+ raise SystemExit(1)
219
+
220
+ def _validate_certificates(self, current_config: Dict[str, Any]) -> None:
221
+ """
222
+ Validate certificates at startup.
223
+
224
+ Checks:
225
+ - Certificate-key match
226
+ - Certificate expiry
227
+ - Certificate chain (with provided CA or system CA store)
228
+
229
+ Raises SystemExit(1) if validation fails.
230
+ """
231
+ try:
232
+ from mcp_proxy_adapter.core.certificate.certificate_validator import (
233
+ CertificateValidator,
234
+ )
235
+ import os
236
+
237
+ certificate_errors = []
238
+
239
+ # Check if this is SimpleConfig format
240
+ if "server" in current_config and "proxy_client" in current_config:
241
+ # SimpleConfig format
242
+ from mcp_proxy_adapter.core.config.simple_config import (
243
+ SimpleConfigModel,
244
+ ServerConfig,
245
+ ProxyClientConfig,
246
+ AuthConfig,
247
+ )
248
+ from mcp_proxy_adapter.core.config.simple_config_validator import (
249
+ SimpleConfigValidator,
250
+ )
251
+
252
+ try:
253
+ # Try to load as SimpleConfig
254
+ server_config = current_config.get("server", {})
255
+ proxy_client_config = current_config.get("proxy_client", {})
256
+ auth_config = current_config.get("auth", {})
257
+
258
+ server = ServerConfig(**server_config) # type: ignore[arg-type]
259
+ proxy_client = ProxyClientConfig(**proxy_client_config) # type: ignore[arg-type]
260
+ auth = AuthConfig(**auth_config) # type: ignore[arg-type]
261
+
262
+ # Handle nested structures
263
+ if isinstance(proxy_client_config.get("heartbeat"), dict):
264
+ from mcp_proxy_adapter.core.config.simple_config import (
265
+ HeartbeatConfig,
266
+ )
267
+
268
+ proxy_client.heartbeat = HeartbeatConfig(
269
+ **proxy_client_config["heartbeat"]
270
+ ) # type: ignore[arg-type]
271
+ if isinstance(proxy_client_config.get("registration"), dict):
272
+ from mcp_proxy_adapter.core.config.simple_config import (
273
+ RegistrationConfig,
274
+ )
275
+
276
+ proxy_client.registration = RegistrationConfig(
277
+ **proxy_client_config["registration"]
278
+ ) # type: ignore[arg-type]
279
+
280
+ model = SimpleConfigModel(
281
+ server=server, proxy_client=proxy_client, auth=auth
282
+ )
283
+ validator = SimpleConfigValidator()
284
+ validation_errors = validator.validate(model)
285
+
286
+ if validation_errors:
287
+ for error in validation_errors:
288
+ certificate_errors.append(error.message)
289
+
290
+ except Exception as e:
291
+ self.logger.error(
292
+ f"Failed to validate as SimpleConfig format: {e}"
293
+ )
294
+ certificate_errors.append(
295
+ f"Configuration validation failed: {e}. Only SimpleConfig format is supported."
296
+ )
297
+
298
+ # Fail if there are certificate errors
299
+ if certificate_errors:
300
+ self.logger.critical(
301
+ "CRITICAL CERTIFICATE ERROR: Certificate validation failed at startup:"
302
+ )
303
+ for error in certificate_errors:
304
+ self.logger.critical(f" - {error}")
305
+ self.logger.critical(
306
+ "Server startup aborted due to certificate validation errors"
307
+ )
308
+ raise SystemExit(1)
309
+
310
+ except SystemExit:
311
+ raise
312
+ except Exception as ex:
313
+ self.logger.error(f"Failed to run certificate validation: {ex}")
314
+ # Don't fail startup if validation itself fails, but log the error
315
+ self.logger.warning(
316
+ "Certificate validation could not be completed, but server will continue to start"
317
+ )
318
+
319
+ def _setup_routes(self, app: FastAPI) -> None:
320
+ """Setup application routes."""
321
+
322
+ @app.get("/health", response_model=HealthResponse)
323
+ async def health(): # type: ignore
324
+ return await get_server_health() # type: ignore[misc]
325
+
326
+ @app.get("/commands", response_model=CommandListResponse)
327
+ async def commands(): # type: ignore
328
+ return await get_commands_list() # type: ignore[misc]
329
+
330
+ @app.post(
331
+ "/api/jsonrpc",
332
+ response_model=Union[JsonRpcSuccessResponse, JsonRpcErrorResponse],
333
+ )
334
+ async def jsonrpc(request: JsonRpcRequest): # type: ignore
335
+ return await handle_json_rpc(request.dict()) # type: ignore[misc]
336
+
337
+ @app.post(
338
+ "/api/jsonrpc/batch",
339
+ response_model=List[Union[JsonRpcSuccessResponse, JsonRpcErrorResponse]],
340
+ )
341
+ async def jsonrpc_batch(requests: List[JsonRpcRequest]): # type: ignore
342
+ return await handle_batch_json_rpc([req.dict() for req in requests]) # type: ignore[misc]
343
+
344
+ # Optional tool endpoints if tools module is available
345
+ if get_tool_description and execute_tool:
346
+
347
+ @app.get("/api/tools", response_model=List[APIToolDescription])
348
+ async def tools(): # type: ignore
349
+ return await get_tool_description() # type: ignore[misc]
350
+
351
+ @app.post("/api/tools/{tool_name}")
352
+ async def execute_tool_endpoint(
353
+ tool_name: str, params: Dict[str, Any] = Body(...)
354
+ ):
355
+ return await execute_tool(tool_name, params) # type: ignore[misc]
@@ -0,0 +1,55 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Lifespan management utilities for MCP Proxy Adapter API.
6
+ """
7
+
8
+ import asyncio
9
+ from contextlib import asynccontextmanager
10
+ from typing import Any, Dict, Optional
11
+
12
+ from fastapi import FastAPI
13
+
14
+ from mcp_proxy_adapter.core.logging import get_global_logger
15
+ from .registration_manager import RegistrationManager
16
+
17
+
18
+ class LifespanManager:
19
+ """Manager for application lifespan events."""
20
+
21
+ def __init__(self):
22
+ """Initialize lifespan manager."""
23
+ self.logger = get_global_logger()
24
+ self.registration_manager = RegistrationManager()
25
+
26
+ def create_lifespan(self, config_path: Optional[str] = None, current_config: Optional[Dict[str, Any]] = None):
27
+ """
28
+ Create lifespan manager for the FastAPI application.
29
+
30
+ Args:
31
+ config_path: Path to configuration file (optional)
32
+ current_config: Current configuration data (optional)
33
+
34
+ Returns:
35
+ Lifespan context manager
36
+ """
37
+
38
+ @asynccontextmanager
39
+ async def lifespan(app: FastAPI):
40
+ """Lifespan context manager."""
41
+ # Startup
42
+ get_global_logger().info("Starting MCP Proxy Adapter")
43
+
44
+ # Register with proxy if configured
45
+ if current_config:
46
+ await self.registration_manager.register_with_proxy(current_config)
47
+ await self.registration_manager.start_heartbeat(current_config)
48
+
49
+ yield
50
+
51
+ # Shutdown
52
+ get_global_logger().info("Shutting down MCP Proxy Adapter")
53
+ await self.registration_manager.stop()
54
+
55
+ return lifespan