mcp-proxy-adapter 6.0.0__py3-none-any.whl → 6.1.1__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 (264) hide show
  1. mcp_proxy_adapter/api/app.py +174 -80
  2. mcp_proxy_adapter/api/handlers.py +16 -5
  3. mcp_proxy_adapter/api/middleware/__init__.py +9 -4
  4. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
  5. mcp_proxy_adapter/api/middleware/factory.py +36 -12
  6. mcp_proxy_adapter/api/middleware/protocol_middleware.py +32 -13
  7. mcp_proxy_adapter/api/middleware/unified_security.py +160 -0
  8. mcp_proxy_adapter/api/middleware/user_info_middleware.py +83 -0
  9. mcp_proxy_adapter/commands/__init__.py +7 -1
  10. mcp_proxy_adapter/commands/base.py +7 -4
  11. mcp_proxy_adapter/commands/builtin_commands.py +8 -2
  12. mcp_proxy_adapter/commands/command_registry.py +8 -0
  13. mcp_proxy_adapter/commands/echo_command.py +81 -0
  14. mcp_proxy_adapter/commands/help_command.py +21 -14
  15. mcp_proxy_adapter/commands/proxy_registration_command.py +326 -185
  16. mcp_proxy_adapter/commands/role_test_command.py +141 -0
  17. mcp_proxy_adapter/commands/security_command.py +488 -0
  18. mcp_proxy_adapter/commands/ssl_setup_command.py +2 -2
  19. mcp_proxy_adapter/commands/token_management_command.py +1 -1
  20. mcp_proxy_adapter/config.py +81 -21
  21. mcp_proxy_adapter/core/app_factory.py +326 -0
  22. mcp_proxy_adapter/core/client_security.py +384 -0
  23. mcp_proxy_adapter/core/logging.py +8 -3
  24. mcp_proxy_adapter/core/mtls_asgi.py +156 -0
  25. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  26. mcp_proxy_adapter/core/protocol_manager.py +139 -8
  27. mcp_proxy_adapter/core/proxy_client.py +602 -0
  28. mcp_proxy_adapter/core/proxy_registration.py +299 -47
  29. mcp_proxy_adapter/core/security_adapter.py +12 -15
  30. mcp_proxy_adapter/core/security_integration.py +285 -0
  31. mcp_proxy_adapter/core/server_adapter.py +345 -0
  32. mcp_proxy_adapter/core/server_engine.py +364 -0
  33. mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
  34. mcp_proxy_adapter/docs/EN/TROUBLESHOOTING.md +285 -0
  35. mcp_proxy_adapter/docs/RU/TROUBLESHOOTING.md +285 -0
  36. mcp_proxy_adapter/examples/README.md +230 -97
  37. mcp_proxy_adapter/examples/README_EN.md +258 -0
  38. mcp_proxy_adapter/examples/SECURITY_TESTING.md +455 -0
  39. mcp_proxy_adapter/examples/basic_framework/configs/http_auth.json +37 -0
  40. mcp_proxy_adapter/examples/basic_framework/configs/http_simple.json +23 -0
  41. mcp_proxy_adapter/examples/basic_framework/configs/https_auth.json +43 -0
  42. mcp_proxy_adapter/examples/basic_framework/configs/https_no_protocol_middleware.json +36 -0
  43. mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +29 -0
  44. mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_protocol_middleware.json +34 -0
  45. mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +39 -0
  46. mcp_proxy_adapter/examples/basic_framework/configs/mtls_simple.json +35 -0
  47. mcp_proxy_adapter/examples/basic_framework/configs/mtls_with_roles.json +45 -0
  48. mcp_proxy_adapter/examples/basic_framework/main.py +63 -0
  49. mcp_proxy_adapter/examples/basic_framework/roles.json +21 -0
  50. mcp_proxy_adapter/examples/cert_config.json +9 -0
  51. mcp_proxy_adapter/examples/certs/admin.crt +32 -0
  52. mcp_proxy_adapter/examples/certs/admin.key +52 -0
  53. mcp_proxy_adapter/examples/certs/admin_cert.pem +21 -0
  54. mcp_proxy_adapter/examples/certs/admin_key.pem +28 -0
  55. mcp_proxy_adapter/examples/certs/ca_cert.pem +23 -0
  56. mcp_proxy_adapter/examples/certs/ca_cert.srl +1 -0
  57. mcp_proxy_adapter/examples/certs/ca_key.pem +28 -0
  58. mcp_proxy_adapter/examples/certs/cert_config.json +9 -0
  59. mcp_proxy_adapter/examples/certs/client.crt +32 -0
  60. mcp_proxy_adapter/examples/certs/client.key +52 -0
  61. mcp_proxy_adapter/examples/certs/client_admin.crt +32 -0
  62. mcp_proxy_adapter/examples/certs/client_admin.key +52 -0
  63. mcp_proxy_adapter/examples/certs/client_user.crt +32 -0
  64. mcp_proxy_adapter/examples/certs/client_user.key +52 -0
  65. mcp_proxy_adapter/examples/certs/guest_cert.pem +21 -0
  66. mcp_proxy_adapter/examples/certs/guest_key.pem +28 -0
  67. mcp_proxy_adapter/examples/certs/mcp_proxy_adapter_ca_ca.crt +23 -0
  68. mcp_proxy_adapter/examples/certs/proxy_cert.pem +21 -0
  69. mcp_proxy_adapter/examples/certs/proxy_key.pem +28 -0
  70. mcp_proxy_adapter/examples/certs/readonly.crt +32 -0
  71. mcp_proxy_adapter/examples/certs/readonly.key +52 -0
  72. mcp_proxy_adapter/examples/certs/readonly_cert.pem +21 -0
  73. mcp_proxy_adapter/examples/certs/readonly_key.pem +28 -0
  74. mcp_proxy_adapter/examples/certs/server.crt +32 -0
  75. mcp_proxy_adapter/examples/certs/server.key +52 -0
  76. mcp_proxy_adapter/examples/certs/server_cert.pem +32 -0
  77. mcp_proxy_adapter/examples/certs/server_key.pem +52 -0
  78. mcp_proxy_adapter/examples/certs/test_ca_ca.crt +20 -0
  79. mcp_proxy_adapter/examples/certs/user.crt +32 -0
  80. mcp_proxy_adapter/examples/certs/user.key +52 -0
  81. mcp_proxy_adapter/examples/certs/user_cert.pem +21 -0
  82. mcp_proxy_adapter/examples/certs/user_key.pem +28 -0
  83. mcp_proxy_adapter/examples/client_configs/api_key_client.json +13 -0
  84. mcp_proxy_adapter/examples/client_configs/basic_auth_client.json +13 -0
  85. mcp_proxy_adapter/examples/client_configs/certificate_client.json +22 -0
  86. mcp_proxy_adapter/examples/client_configs/jwt_client.json +15 -0
  87. mcp_proxy_adapter/examples/client_configs/no_auth_client.json +9 -0
  88. mcp_proxy_adapter/examples/commands/__init__.py +1 -0
  89. mcp_proxy_adapter/examples/create_certificates_simple.py +307 -0
  90. mcp_proxy_adapter/examples/debug_request_state.py +144 -0
  91. mcp_proxy_adapter/examples/debug_role_chain.py +205 -0
  92. mcp_proxy_adapter/examples/demo_client.py +341 -0
  93. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +99 -0
  94. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +106 -0
  95. mcp_proxy_adapter/examples/full_application/configs/http_auth.json +37 -0
  96. mcp_proxy_adapter/examples/full_application/configs/http_simple.json +23 -0
  97. mcp_proxy_adapter/examples/full_application/configs/https_auth.json +39 -0
  98. mcp_proxy_adapter/examples/full_application/configs/https_simple.json +25 -0
  99. mcp_proxy_adapter/examples/full_application/configs/mtls_no_roles.json +39 -0
  100. mcp_proxy_adapter/examples/full_application/configs/mtls_with_roles.json +45 -0
  101. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +97 -0
  102. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +95 -0
  103. mcp_proxy_adapter/examples/full_application/main.py +138 -0
  104. mcp_proxy_adapter/examples/full_application/roles.json +21 -0
  105. mcp_proxy_adapter/examples/generate_all_certificates.py +429 -0
  106. mcp_proxy_adapter/examples/generate_certificates.py +121 -0
  107. mcp_proxy_adapter/examples/keys/ca_key.pem +28 -0
  108. mcp_proxy_adapter/examples/keys/mcp_proxy_adapter_ca_ca.key +28 -0
  109. mcp_proxy_adapter/examples/keys/test_ca_ca.key +28 -0
  110. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log +220 -0
  111. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.1 +1 -0
  112. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.2 +1 -0
  113. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.3 +1 -0
  114. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.4 +1 -0
  115. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.5 +1 -0
  116. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log +220 -0
  117. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.1 +1 -0
  118. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.2 +1 -0
  119. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.3 +1 -0
  120. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.4 +1 -0
  121. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.5 +1 -0
  122. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log +2 -0
  123. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.1 +1 -0
  124. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.2 +1 -0
  125. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.3 +1 -0
  126. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.4 +1 -0
  127. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.5 +1 -0
  128. mcp_proxy_adapter/examples/proxy_registration_example.py +401 -0
  129. mcp_proxy_adapter/examples/roles.json +38 -0
  130. mcp_proxy_adapter/examples/run_example.py +81 -0
  131. mcp_proxy_adapter/examples/run_security_tests.py +326 -0
  132. mcp_proxy_adapter/examples/run_security_tests_fixed.py +300 -0
  133. mcp_proxy_adapter/examples/security_test_client.py +743 -0
  134. mcp_proxy_adapter/examples/server_configs/config_basic_http.json +204 -0
  135. mcp_proxy_adapter/examples/server_configs/config_http_token.json +238 -0
  136. mcp_proxy_adapter/examples/server_configs/config_https.json +215 -0
  137. mcp_proxy_adapter/examples/server_configs/config_https_token.json +231 -0
  138. mcp_proxy_adapter/examples/server_configs/config_mtls.json +215 -0
  139. mcp_proxy_adapter/examples/server_configs/config_proxy_registration.json +250 -0
  140. mcp_proxy_adapter/examples/server_configs/config_simple.json +46 -0
  141. mcp_proxy_adapter/examples/server_configs/roles.json +38 -0
  142. mcp_proxy_adapter/examples/test_config_generator.py +110 -0
  143. mcp_proxy_adapter/examples/test_examples.py +344 -0
  144. mcp_proxy_adapter/examples/universal_client.py +628 -0
  145. mcp_proxy_adapter/main.py +21 -10
  146. mcp_proxy_adapter/utils/config_generator.py +727 -0
  147. mcp_proxy_adapter/version.py +5 -2
  148. mcp_proxy_adapter-6.1.1.dist-info/METADATA +205 -0
  149. mcp_proxy_adapter-6.1.1.dist-info/RECORD +197 -0
  150. mcp_proxy_adapter-6.1.1.dist-info/entry_points.txt +2 -0
  151. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.1.dist-info}/licenses/LICENSE +2 -2
  152. mcp_proxy_adapter/api/middleware/auth.py +0 -146
  153. mcp_proxy_adapter/api/middleware/auth_adapter.py +0 -235
  154. mcp_proxy_adapter/api/middleware/mtls_adapter.py +0 -305
  155. mcp_proxy_adapter/api/middleware/mtls_middleware.py +0 -296
  156. mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
  157. mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +0 -241
  158. mcp_proxy_adapter/api/middleware/roles_adapter.py +0 -365
  159. mcp_proxy_adapter/api/middleware/roles_middleware.py +0 -381
  160. mcp_proxy_adapter/api/middleware/security.py +0 -376
  161. mcp_proxy_adapter/api/middleware/token_auth_middleware.py +0 -261
  162. mcp_proxy_adapter/examples/__init__.py +0 -7
  163. mcp_proxy_adapter/examples/basic_server/README.md +0 -60
  164. mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
  165. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
  166. mcp_proxy_adapter/examples/basic_server/config.json +0 -70
  167. mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +0 -54
  168. mcp_proxy_adapter/examples/basic_server/config_http.json +0 -70
  169. mcp_proxy_adapter/examples/basic_server/config_http_only.json +0 -52
  170. mcp_proxy_adapter/examples/basic_server/config_https.json +0 -58
  171. mcp_proxy_adapter/examples/basic_server/config_mtls.json +0 -58
  172. mcp_proxy_adapter/examples/basic_server/config_ssl.json +0 -46
  173. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
  174. mcp_proxy_adapter/examples/basic_server/server.py +0 -114
  175. mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
  176. mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
  177. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -566
  178. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
  179. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
  180. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
  181. mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +0 -105
  182. mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +0 -129
  183. mcp_proxy_adapter/examples/custom_commands/config.json +0 -118
  184. mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +0 -46
  185. mcp_proxy_adapter/examples/custom_commands/config_https_only.json +0 -46
  186. mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +0 -33
  187. mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +0 -46
  188. mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +0 -33
  189. mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +0 -33
  190. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
  191. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
  192. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
  193. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
  194. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
  195. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
  196. mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
  197. mcp_proxy_adapter/examples/custom_commands/full_help_response.json +0 -1
  198. mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +0 -629
  199. mcp_proxy_adapter/examples/custom_commands/get_openapi.py +0 -103
  200. mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
  201. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
  202. mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +0 -129
  203. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
  204. mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +0 -278
  205. mcp_proxy_adapter/examples/custom_commands/server.py +0 -252
  206. mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +0 -75
  207. mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +0 -299
  208. mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +0 -278
  209. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
  210. mcp_proxy_adapter/examples/custom_commands/test_openapi.py +0 -27
  211. mcp_proxy_adapter/examples/custom_commands/test_registry.py +0 -23
  212. mcp_proxy_adapter/examples/custom_commands/test_simple.py +0 -19
  213. mcp_proxy_adapter/examples/custom_project_example/README.md +0 -103
  214. mcp_proxy_adapter/examples/custom_project_example/README_EN.md +0 -103
  215. mcp_proxy_adapter/examples/deployment/README.md +0 -49
  216. mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
  217. mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
  218. mcp_proxy_adapter/examples/deployment/config.json +0 -29
  219. mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
  220. mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
  221. mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
  222. mcp_proxy_adapter/examples/deployment/run.sh +0 -43
  223. mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
  224. mcp_proxy_adapter/examples/simple_custom_commands/README.md +0 -149
  225. mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +0 -149
  226. mcp_proxy_adapter/schemas/base_schema.json +0 -114
  227. mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
  228. mcp_proxy_adapter/schemas/roles_schema.json +0 -162
  229. mcp_proxy_adapter/tests/__init__.py +0 -0
  230. mcp_proxy_adapter/tests/api/__init__.py +0 -3
  231. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
  232. mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
  233. mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
  234. mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
  235. mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
  236. mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
  237. mcp_proxy_adapter/tests/commands/__init__.py +0 -3
  238. mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
  239. mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
  240. mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
  241. mcp_proxy_adapter/tests/conftest.py +0 -131
  242. mcp_proxy_adapter/tests/functional/__init__.py +0 -3
  243. mcp_proxy_adapter/tests/functional/test_api.py +0 -253
  244. mcp_proxy_adapter/tests/integration/__init__.py +0 -3
  245. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
  246. mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
  247. mcp_proxy_adapter/tests/performance/__init__.py +0 -3
  248. mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
  249. mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
  250. mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
  251. mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
  252. mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
  253. mcp_proxy_adapter/tests/test_base_command.py +0 -123
  254. mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
  255. mcp_proxy_adapter/tests/test_command_registry.py +0 -281
  256. mcp_proxy_adapter/tests/test_config.py +0 -127
  257. mcp_proxy_adapter/tests/test_utils.py +0 -65
  258. mcp_proxy_adapter/tests/unit/__init__.py +0 -3
  259. mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
  260. mcp_proxy_adapter/tests/unit/test_config.py +0 -270
  261. mcp_proxy_adapter-6.0.0.dist-info/METADATA +0 -201
  262. mcp_proxy_adapter-6.0.0.dist-info/RECORD +0 -179
  263. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.1.dist-info}/WHEEL +0 -0
  264. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,106 @@
1
+ """
2
+ Dynamic Calculator Command
3
+
4
+ This module demonstrates a dynamically loaded command implementation for the full application example.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ from typing import Dict, Any, Optional
11
+ from mcp_proxy_adapter.commands.base import BaseCommand
12
+ from mcp_proxy_adapter.commands.result import CommandResult
13
+
14
+
15
+ class CalculatorResult(CommandResult):
16
+ """Result class for calculator command."""
17
+
18
+ def __init__(self, operation: str, result: float, expression: str):
19
+ self.operation = operation
20
+ self.result = result
21
+ self.expression = expression
22
+
23
+ def to_dict(self) -> Dict[str, Any]:
24
+ """Convert result to dictionary."""
25
+ return {
26
+ "operation": self.operation,
27
+ "result": self.result,
28
+ "expression": self.expression,
29
+ "command_type": "dynamic_calculator"
30
+ }
31
+
32
+ def get_schema(self) -> Dict[str, Any]:
33
+ """Get result schema."""
34
+ return {
35
+ "type": "object",
36
+ "properties": {
37
+ "operation": {"type": "string", "description": "Mathematical operation"},
38
+ "result": {"type": "number", "description": "Calculation result"},
39
+ "expression": {"type": "string", "description": "Full expression"},
40
+ "command_type": {"type": "string", "description": "Command type"}
41
+ },
42
+ "required": ["operation", "result", "expression", "command_type"]
43
+ }
44
+
45
+
46
+ class DynamicCalculatorCommand(BaseCommand):
47
+ """Dynamic calculator command implementation."""
48
+
49
+ def get_name(self) -> str:
50
+ """Get command name."""
51
+ return "dynamic_calculator"
52
+
53
+ def get_description(self) -> str:
54
+ """Get command description."""
55
+ return "Dynamic calculator with basic mathematical operations"
56
+
57
+ def get_schema(self) -> Dict[str, Any]:
58
+ """Get command schema."""
59
+ return {
60
+ "type": "object",
61
+ "properties": {
62
+ "operation": {
63
+ "type": "string",
64
+ "description": "Mathematical operation (add, subtract, multiply, divide)",
65
+ "enum": ["add", "subtract", "multiply", "divide"]
66
+ },
67
+ "a": {
68
+ "type": "number",
69
+ "description": "First number"
70
+ },
71
+ "b": {
72
+ "type": "number",
73
+ "description": "Second number"
74
+ }
75
+ },
76
+ "required": ["operation", "a", "b"]
77
+ }
78
+
79
+ async def execute(self, params: Dict[str, Any]) -> CalculatorResult:
80
+ """Execute the calculator command."""
81
+ operation = params.get("operation")
82
+ a = params.get("a")
83
+ b = params.get("b")
84
+
85
+ if operation == "add":
86
+ result = a + b
87
+ expression = f"{a} + {b}"
88
+ elif operation == "subtract":
89
+ result = a - b
90
+ expression = f"{a} - {b}"
91
+ elif operation == "multiply":
92
+ result = a * b
93
+ expression = f"{a} * {b}"
94
+ elif operation == "divide":
95
+ if b == 0:
96
+ raise ValueError("Division by zero is not allowed")
97
+ result = a / b
98
+ expression = f"{a} / {b}"
99
+ else:
100
+ raise ValueError(f"Unknown operation: {operation}")
101
+
102
+ return CalculatorResult(
103
+ operation=operation,
104
+ result=result,
105
+ expression=expression
106
+ )
@@ -0,0 +1,37 @@
1
+ {
2
+ "server": {
3
+ "host": "0.0.0.0",
4
+ "port": 8001,
5
+ "debug": false,
6
+ "log_level": "INFO"
7
+ },
8
+ "ssl": {
9
+ "enabled": false
10
+ },
11
+ "security": {
12
+ "enabled": true,
13
+ "auth": {
14
+ "enabled": true,
15
+ "methods": ["api_key"],
16
+ "api_keys": {
17
+ "admin": "admin-secret-key-123",
18
+ "user": "user-secret-key-456"
19
+ }
20
+ },
21
+ "rate_limit": {
22
+ "enabled": true,
23
+ "requests_per_minute": 60,
24
+ "requests_per_hour": 1000,
25
+ "burst_limit": 10
26
+ }
27
+ },
28
+ "logging": {
29
+ "level": "INFO",
30
+ "console_output": true,
31
+ "file_output": false
32
+ },
33
+ "commands": {
34
+ "auto_discovery": true,
35
+ "commands_directory": "./commands"
36
+ }
37
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "server": {
3
+ "host": "0.0.0.0",
4
+ "port": 8000,
5
+ "debug": false,
6
+ "log_level": "INFO"
7
+ },
8
+ "ssl": {
9
+ "enabled": false
10
+ },
11
+ "security": {
12
+ "enabled": false
13
+ },
14
+ "logging": {
15
+ "level": "INFO",
16
+ "console_output": true,
17
+ "file_output": false
18
+ },
19
+ "commands": {
20
+ "auto_discovery": true,
21
+ "commands_directory": "./commands"
22
+ }
23
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "server": {
3
+ "host": "0.0.0.0",
4
+ "port": 8444,
5
+ "debug": false,
6
+ "log_level": "INFO"
7
+ },
8
+ "ssl": {
9
+ "enabled": true,
10
+ "cert_file": "./certs/server.crt",
11
+ "key_file": "./certs/server.key"
12
+ },
13
+ "security": {
14
+ "enabled": true,
15
+ "auth": {
16
+ "enabled": true,
17
+ "methods": ["api_key"],
18
+ "api_keys": {
19
+ "admin": "admin-secret-key-123",
20
+ "user": "user-secret-key-456"
21
+ }
22
+ },
23
+ "rate_limit": {
24
+ "enabled": true,
25
+ "requests_per_minute": 60,
26
+ "requests_per_hour": 1000,
27
+ "burst_limit": 10
28
+ }
29
+ },
30
+ "logging": {
31
+ "level": "INFO",
32
+ "console_output": true,
33
+ "file_output": false
34
+ },
35
+ "commands": {
36
+ "auto_discovery": true,
37
+ "commands_directory": "./commands"
38
+ }
39
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "server": {
3
+ "host": "0.0.0.0",
4
+ "port": 8443,
5
+ "debug": false,
6
+ "log_level": "INFO"
7
+ },
8
+ "ssl": {
9
+ "enabled": true,
10
+ "cert_file": "./certs/server.crt",
11
+ "key_file": "./certs/server.key"
12
+ },
13
+ "security": {
14
+ "enabled": false
15
+ },
16
+ "logging": {
17
+ "level": "INFO",
18
+ "console_output": true,
19
+ "file_output": false
20
+ },
21
+ "commands": {
22
+ "auto_discovery": true,
23
+ "commands_directory": "./commands"
24
+ }
25
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "server": {
3
+ "host": "0.0.0.0",
4
+ "port": 9443,
5
+ "debug": false,
6
+ "log_level": "INFO"
7
+ },
8
+ "ssl": {
9
+ "enabled": true,
10
+ "cert_file": "./certs/server.crt",
11
+ "key_file": "./certs/server.key",
12
+ "ca_cert": "./certs/ca.crt",
13
+ "verify_client": true,
14
+ "client_cert_required": true
15
+ },
16
+ "security": {
17
+ "enabled": true,
18
+ "auth": {
19
+ "enabled": true,
20
+ "methods": ["certificate"],
21
+ "certificate_auth": true
22
+ },
23
+ "rate_limit": {
24
+ "enabled": true,
25
+ "requests_per_minute": 60,
26
+ "requests_per_hour": 1000,
27
+ "burst_limit": 10
28
+ }
29
+ },
30
+ "logging": {
31
+ "level": "INFO",
32
+ "console_output": true,
33
+ "file_output": false
34
+ },
35
+ "commands": {
36
+ "auto_discovery": true,
37
+ "commands_directory": "./commands"
38
+ }
39
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "server": {
3
+ "host": "0.0.0.0",
4
+ "port": 9444,
5
+ "debug": false,
6
+ "log_level": "INFO"
7
+ },
8
+ "ssl": {
9
+ "enabled": true,
10
+ "cert_file": "./certs/server.crt",
11
+ "key_file": "./certs/server.key",
12
+ "ca_cert": "./certs/ca.crt",
13
+ "verify_client": true,
14
+ "client_cert_required": true
15
+ },
16
+ "security": {
17
+ "enabled": true,
18
+ "auth": {
19
+ "enabled": true,
20
+ "methods": ["certificate"],
21
+ "certificate_auth": true
22
+ },
23
+ "permissions": {
24
+ "enabled": true,
25
+ "roles_file": "./roles.json",
26
+ "default_role": "user",
27
+ "deny_by_default": true
28
+ },
29
+ "rate_limit": {
30
+ "enabled": true,
31
+ "requests_per_minute": 60,
32
+ "requests_per_hour": 1000,
33
+ "burst_limit": 10
34
+ }
35
+ },
36
+ "logging": {
37
+ "level": "INFO",
38
+ "console_output": true,
39
+ "file_output": false
40
+ },
41
+ "commands": {
42
+ "auto_discovery": true,
43
+ "commands_directory": "./commands"
44
+ }
45
+ }
@@ -0,0 +1,97 @@
1
+ """
2
+ Application Hooks
3
+
4
+ This module demonstrates application-level hooks in the full application example.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ import logging
11
+ from typing import Dict, Any, Optional
12
+ from datetime import datetime
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class ApplicationHooks:
18
+ """Application-level hooks."""
19
+
20
+ @staticmethod
21
+ def on_startup():
22
+ """Hook executed on application startup."""
23
+ logger.info("🚀 Application startup hook executed")
24
+
25
+ # Initialize application-specific resources
26
+ logger.info("📊 Initializing application metrics")
27
+ logger.info("🔐 Loading security configurations")
28
+ logger.info("📝 Setting up logging")
29
+
30
+ @staticmethod
31
+ def on_shutdown():
32
+ """Hook executed on application shutdown."""
33
+ logger.info("🛑 Application shutdown hook executed")
34
+
35
+ # Cleanup application resources
36
+ logger.info("🧹 Cleaning up resources")
37
+ logger.info("💾 Saving application state")
38
+ logger.info("📊 Finalizing metrics")
39
+
40
+ @staticmethod
41
+ def before_request(request_data: Dict[str, Any]) -> Dict[str, Any]:
42
+ """Hook executed before processing any request."""
43
+ logger.info(f"🔧 Application hook: before_request with data: {request_data}")
44
+
45
+ # Add request metadata
46
+ request_data["app_metadata"] = {
47
+ "request_id": f"req_{datetime.now().timestamp()}",
48
+ "timestamp": datetime.now().isoformat(),
49
+ "application": "full_application_example"
50
+ }
51
+
52
+ return request_data
53
+
54
+ @staticmethod
55
+ def after_request(result: Dict[str, Any]) -> Dict[str, Any]:
56
+ """Hook executed after processing any request."""
57
+ logger.info(f"🔧 Application hook: after_request with result: {result}")
58
+
59
+ # Add response metadata
60
+ result["app_response_metadata"] = {
61
+ "processed_at": datetime.now().isoformat(),
62
+ "application": "full_application_example",
63
+ "version": "1.0.0"
64
+ }
65
+
66
+ return result
67
+
68
+ @staticmethod
69
+ def on_error(error: Exception, context: Dict[str, Any]):
70
+ """Hook executed when an error occurs."""
71
+ logger.error(f"🔧 Application hook: on_error - {error} in context: {context}")
72
+
73
+ # Log error details
74
+ logger.error(f"Error type: {type(error).__name__}")
75
+ logger.error(f"Error message: {str(error)}")
76
+ logger.error(f"Context: {context}")
77
+
78
+ @staticmethod
79
+ def on_command_registered(command_name: str, command_info: Dict[str, Any]):
80
+ """Hook executed when a command is registered."""
81
+ logger.info(f"🔧 Application hook: on_command_registered - {command_name}")
82
+ logger.info(f"Command info: {command_info}")
83
+
84
+ # Track registered commands
85
+ logger.info(f"📝 Command '{command_name}' registered successfully")
86
+
87
+ @staticmethod
88
+ def on_command_executed(command_name: str, execution_time: float, success: bool):
89
+ """Hook executed when a command is executed."""
90
+ logger.info(f"🔧 Application hook: on_command_executed - {command_name}")
91
+ logger.info(f"Execution time: {execution_time}s, Success: {success}")
92
+
93
+ # Track command execution metrics
94
+ if success:
95
+ logger.info(f"✅ Command '{command_name}' executed successfully in {execution_time}s")
96
+ else:
97
+ logger.warning(f"⚠️ Command '{command_name}' failed after {execution_time}s")
@@ -0,0 +1,95 @@
1
+ """
2
+ Built-in Command Hooks
3
+
4
+ This module demonstrates hooks for built-in commands in the full application example.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ import logging
11
+ from typing import Dict, Any, Optional
12
+ from datetime import datetime
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class BuiltinCommandHooks:
18
+ """Hooks for built-in commands."""
19
+
20
+ @staticmethod
21
+ def before_echo_command(params: Dict[str, Any]) -> Dict[str, Any]:
22
+ """Hook executed before echo command."""
23
+ logger.info(f"🔧 Built-in hook: before_echo_command with params: {params}")
24
+
25
+ # Add timestamp to message
26
+ if "message" in params:
27
+ timestamp = datetime.now().isoformat()
28
+ params["message"] = f"[{timestamp}] {params['message']}"
29
+
30
+ return params
31
+
32
+ @staticmethod
33
+ def after_echo_command(result: Dict[str, Any]) -> Dict[str, Any]:
34
+ """Hook executed after echo command."""
35
+ logger.info(f"🔧 Built-in hook: after_echo_command with result: {result}")
36
+
37
+ # Add hook metadata
38
+ result["hook_metadata"] = {
39
+ "hook_type": "builtin_after_echo",
40
+ "timestamp": datetime.now().isoformat(),
41
+ "processed": True
42
+ }
43
+
44
+ return result
45
+
46
+ @staticmethod
47
+ def before_health_command(params: Dict[str, Any]) -> Dict[str, Any]:
48
+ """Hook executed before health command."""
49
+ logger.info(f"🔧 Built-in hook: before_health_command with params: {params}")
50
+
51
+ # Add custom health check parameters
52
+ params["include_detailed_info"] = True
53
+ params["check_dependencies"] = True
54
+
55
+ return params
56
+
57
+ @staticmethod
58
+ def after_health_command(result: Dict[str, Any]) -> Dict[str, Any]:
59
+ """Hook executed after health command."""
60
+ logger.info(f"🔧 Built-in hook: after_health_command with result: {result}")
61
+
62
+ # Add custom health metrics
63
+ if "status" in result and result["status"] == "healthy":
64
+ result["custom_metrics"] = {
65
+ "uptime": "24h",
66
+ "memory_usage": "45%",
67
+ "cpu_usage": "12%"
68
+ }
69
+
70
+ return result
71
+
72
+ @staticmethod
73
+ def before_config_command(params: Dict[str, Any]) -> Dict[str, Any]:
74
+ """Hook executed before config command."""
75
+ logger.info(f"🔧 Built-in hook: before_config_command with params: {params}")
76
+
77
+ # Add configuration validation
78
+ params["validate_config"] = True
79
+ params["include_secrets"] = False
80
+
81
+ return params
82
+
83
+ @staticmethod
84
+ def after_config_command(result: Dict[str, Any]) -> Dict[str, Any]:
85
+ """Hook executed after config command."""
86
+ logger.info(f"🔧 Built-in hook: after_config_command with result: {result}")
87
+
88
+ # Add configuration metadata
89
+ result["config_metadata"] = {
90
+ "last_modified": datetime.now().isoformat(),
91
+ "version": "1.0.0",
92
+ "environment": "development"
93
+ }
94
+
95
+ return result
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Full Application Example
4
+
5
+ This is a complete application that demonstrates all features of MCP Proxy Adapter framework:
6
+ - Built-in commands
7
+ - Custom commands
8
+ - Dynamically loaded commands
9
+ - Built-in command hooks
10
+ - Application hooks
11
+
12
+ Author: Vasiliy Zdanovskiy
13
+ email: vasilyvz@gmail.com
14
+ """
15
+
16
+ import sys
17
+ import argparse
18
+ import logging
19
+ from pathlib import Path
20
+
21
+ # Add the framework to the path
22
+ sys.path.insert(0, str(Path(__file__).parent.parent.parent))
23
+
24
+ from mcp_proxy_adapter.api.app import create_app
25
+ from mcp_proxy_adapter.config import Config
26
+ from mcp_proxy_adapter.commands.command_registry import CommandRegistry
27
+
28
+
29
+ class FullApplication:
30
+ """Full application example with all framework features."""
31
+
32
+ def __init__(self, config_path: str):
33
+ self.config_path = config_path
34
+ self.config = Config(config_path)
35
+ self.app = None
36
+ self.command_registry = None
37
+
38
+ # Setup logging
39
+ logging.basicConfig(level=logging.INFO)
40
+ self.logger = logging.getLogger(__name__)
41
+
42
+ def setup_hooks(self):
43
+ """Setup application hooks."""
44
+ try:
45
+ # Import hooks
46
+ from hooks.application_hooks import ApplicationHooks
47
+ from hooks.builtin_command_hooks import BuiltinCommandHooks
48
+
49
+ # Register application hooks
50
+ self.logger.info("🔧 Setting up application hooks...")
51
+
52
+ # Register built-in command hooks
53
+ self.logger.info("🔧 Setting up built-in command hooks...")
54
+
55
+ # Note: In a real implementation, these hooks would be registered
56
+ # with the framework's hook system
57
+ self.logger.info("✅ Hooks setup completed")
58
+
59
+ except ImportError as e:
60
+ self.logger.warning(f"⚠️ Could not import hooks: {e}")
61
+
62
+ def setup_custom_commands(self):
63
+ """Setup custom commands."""
64
+ try:
65
+ self.logger.info("🔧 Setting up custom commands...")
66
+
67
+ # Import custom commands
68
+ from commands.custom_echo_command import CustomEchoCommand
69
+ from commands.dynamic_calculator_command import DynamicCalculatorCommand
70
+
71
+ # Register custom commands
72
+ # Note: In a real implementation, these would be registered
73
+ # with the framework's command registry
74
+ self.logger.info("✅ Custom commands setup completed")
75
+
76
+ except ImportError as e:
77
+ self.logger.warning(f"⚠️ Could not import custom commands: {e}")
78
+
79
+ def create_application(self):
80
+ """Create the FastAPI application."""
81
+ self.logger.info("🔧 Creating application...")
82
+
83
+ # Setup hooks and commands before creating app
84
+ self.setup_hooks()
85
+ self.setup_custom_commands()
86
+
87
+ # Create application with configuration
88
+ self.app = create_app(app_config=self.config)
89
+
90
+ self.logger.info("✅ Application created successfully")
91
+
92
+ def run(self, host: str = None, port: int = None, debug: bool = False):
93
+ """Run the application."""
94
+ # Override configuration if specified
95
+ if host:
96
+ self.config.set("server.host", host)
97
+ if port:
98
+ self.config.set("server.port", port)
99
+ if debug:
100
+ self.config.set("server.debug", True)
101
+
102
+ # Create application
103
+ self.create_application()
104
+
105
+ # Get server configuration
106
+ server_host = self.config.get("server.host", "0.0.0.0")
107
+ server_port = self.config.get("server.port", 8000)
108
+ server_debug = self.config.get("server.debug", False)
109
+
110
+ print(f"🚀 Starting Full Application Example")
111
+ print(f"📋 Configuration: {self.config_path}")
112
+ print(f"🌐 Server: {server_host}:{server_port}")
113
+ print(f"🔧 Debug: {server_debug}")
114
+ print(f"🔧 Features: Built-in commands, Custom commands, Dynamic commands, Hooks")
115
+ print("=" * 60)
116
+
117
+ # Import uvicorn here to avoid dependency issues
118
+ import uvicorn
119
+ uvicorn.run(self.app, host=server_host, port=server_port, log_level="info")
120
+
121
+
122
+ def main():
123
+ """Main entry point for the full application example."""
124
+ parser = argparse.ArgumentParser(description="Full Application Example")
125
+ parser.add_argument("--config", "-c", required=True, help="Path to configuration file")
126
+ parser.add_argument("--host", help="Server host")
127
+ parser.add_argument("--port", type=int, help="Server port")
128
+ parser.add_argument("--debug", action="store_true", help="Enable debug mode")
129
+
130
+ args = parser.parse_args()
131
+
132
+ # Create and run application
133
+ app = FullApplication(args.config)
134
+ app.run(host=args.host, port=args.port, debug=args.debug)
135
+
136
+
137
+ if __name__ == "__main__":
138
+ main()
@@ -0,0 +1,21 @@
1
+ {
2
+ "roles": {
3
+ "admin": {
4
+ "permissions": ["*"],
5
+ "description": "Administrator with full access"
6
+ },
7
+ "user": {
8
+ "permissions": ["read", "write"],
9
+ "description": "Regular user with read/write access"
10
+ },
11
+ "readonly": {
12
+ "permissions": ["read"],
13
+ "description": "Read-only user"
14
+ }
15
+ },
16
+ "user_roles": {
17
+ "admin": "admin",
18
+ "user": "user",
19
+ "readonly": "readonly"
20
+ }
21
+ }