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
@@ -1,103 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Script to get OpenAPI schema directly from the code.
4
- """
5
-
6
- import json
7
- import asyncio
8
- import sys
9
- import os
10
- from pathlib import Path
11
-
12
- # Add current directory to path for imports
13
- sys.path.insert(0, os.getcwd())
14
-
15
- from mcp_proxy_adapter.custom_openapi import CustomOpenAPIGenerator
16
- from mcp_proxy_adapter.commands.command_registry import registry
17
-
18
- async def main():
19
- """Generate and save OpenAPI schema."""
20
- try:
21
- # Initialize commands first
22
- print("🔄 Initializing commands...")
23
- result = await registry.reload_system()
24
- print(f"✅ Commands initialized: {result}")
25
-
26
- # Load custom commands manually
27
- print("🔄 Loading custom commands...")
28
- custom_commands = [
29
- "echo_command",
30
- "custom_help_command",
31
- "custom_health_command",
32
- "manual_echo_command"
33
- ]
34
-
35
- for cmd_name in custom_commands:
36
- try:
37
- # Import the command module
38
- module = __import__(cmd_name)
39
- print(f"✅ Loaded custom command: {cmd_name}")
40
-
41
- # Try to register the command if it has a command class
42
- if hasattr(module, 'EchoCommand'):
43
- registry.register_custom(module.EchoCommand())
44
- print(f"✅ Registered EchoCommand")
45
- elif hasattr(module, 'CustomHelpCommand'):
46
- registry.register_custom(module.CustomHelpCommand())
47
- print(f"✅ Registered CustomHelpCommand")
48
- elif hasattr(module, 'CustomHealthCommand'):
49
- registry.register_custom(module.CustomHealthCommand())
50
- print(f"✅ Registered CustomHealthCommand")
51
- elif hasattr(module, 'ManualEchoCommand'):
52
- registry.register_custom(module.ManualEchoCommand())
53
- print(f"✅ Registered ManualEchoCommand")
54
-
55
- except Exception as e:
56
- print(f"⚠️ Failed to load {cmd_name}: {e}")
57
-
58
- # Get commands after registration
59
- print("📋 Getting commands after registration...")
60
- commands = registry.get_all_commands()
61
- print(f" Total commands: {len(commands)}")
62
- print(f" Command names: {list(commands.keys())}")
63
-
64
- # Create generator
65
- generator = CustomOpenAPIGenerator()
66
-
67
- # Generate schema
68
- schema = generator.generate(
69
- title="Extended MCP Proxy Server",
70
- description="Advanced MCP Proxy Adapter server with custom commands and hooks",
71
- version="2.1.0"
72
- )
73
-
74
- # Save to file
75
- with open("generated_openapi.json", "w", encoding="utf-8") as f:
76
- json.dump(schema, f, indent=2, ensure_ascii=False)
77
-
78
- print("✅ OpenAPI schema generated successfully!")
79
- print(f"📄 Saved to: generated_openapi.json")
80
- print(f"📊 Schema size: {len(json.dumps(schema))} characters")
81
-
82
- # Show basic info
83
- print(f"\n📋 Schema info:")
84
- print(f" Title: {schema['info']['title']}")
85
- print(f" Version: {schema['info']['version']}")
86
-
87
- # Get commands info
88
- commands = registry.get_all_commands()
89
- print(f" Commands: {len(commands)}")
90
- print(f" Command names: {list(commands.keys())}")
91
-
92
- # Check CommandRequest enum
93
- command_enum = schema['components']['schemas'].get('CommandRequest', {}).get('properties', {}).get('command', {}).get('enum', [])
94
- print(f" Commands in schema: {len(command_enum)}")
95
- print(f" Schema commands: {command_enum}")
96
-
97
- except Exception as e:
98
- print(f"❌ Error generating schema: {e}")
99
- import traceback
100
- traceback.print_exc()
101
-
102
- if __name__ == "__main__":
103
- asyncio.run(main())
@@ -1,230 +0,0 @@
1
- """
2
- Custom Hooks Example
3
-
4
- This module demonstrates how to use hooks in the MCP Proxy Adapter framework.
5
- Hooks allow you to intercept command execution before and after processing.
6
- """
7
-
8
- import time
9
- import logging
10
- from typing import Dict, Any
11
- from datetime import datetime
12
-
13
- from mcp_proxy_adapter.commands.hooks import HookContext, HookType
14
-
15
-
16
- # Setup logging for hooks
17
- logger = logging.getLogger("mcp_proxy_adapter.examples.hooks")
18
-
19
-
20
- def echo_before_hook(context: HookContext) -> None:
21
- """
22
- Before hook for echo command.
23
-
24
- Args:
25
- context: Hook context with command information
26
- """
27
- logger.info(f"🔔 Echo command will be executed with params: {context.params}")
28
-
29
- # Add timestamp to params
30
- context.params["hook_timestamp"] = datetime.now().isoformat()
31
-
32
- # Log the message that will be echoed
33
- message = context.params.get("message", context.params.get("text", "Hello, World!"))
34
- logger.info(f"📢 Will echo message: '{message}'")
35
-
36
-
37
- def echo_after_hook(context: HookContext) -> None:
38
- """
39
- After hook for echo command.
40
-
41
- Args:
42
- context: Hook context with command information
43
- """
44
- logger.info(f"✅ Echo command completed successfully")
45
-
46
- # Log the result
47
- if context.result and hasattr(context.result, 'data'):
48
- echoed_message = context.result.data.get("message", "Unknown")
49
- timestamp = context.result.data.get("timestamp", "Unknown")
50
- logger.info(f"📤 Echoed: '{echoed_message}' at {timestamp}")
51
-
52
-
53
- def help_before_hook(context: HookContext) -> None:
54
- """
55
- Before hook for help command.
56
-
57
- Args:
58
- context: Hook context with command information
59
- """
60
- logger.info(f"🔔 Help command will be executed")
61
-
62
- # Add request tracking
63
- context.params["request_id"] = f"help_{int(time.time())}"
64
- context.params["hook_processed"] = True
65
-
66
- cmdname = context.params.get("cmdname")
67
- if cmdname:
68
- logger.info(f"📖 Will get help for command: {cmdname}")
69
- else:
70
- logger.info(f"📖 Will get help for all commands")
71
-
72
-
73
- def help_after_hook(context: HookContext) -> None:
74
- """
75
- After hook for help command.
76
-
77
- Args:
78
- context: Hook context with command information
79
- """
80
- logger.info(f"✅ Help command completed successfully")
81
-
82
- # Log the result summary
83
- if context.result and hasattr(context.result, 'to_dict'):
84
- result_dict = context.result.to_dict()
85
- total_commands = result_dict.get("total", 0)
86
- logger.info(f"📚 Help returned {total_commands} commands")
87
-
88
-
89
- def health_before_hook(context: HookContext) -> None:
90
- """
91
- Before hook for health command.
92
-
93
- Args:
94
- context: Hook context with command information
95
- """
96
- logger.info(f"🔔 Health command will be executed")
97
-
98
- # Add health check metadata
99
- context.params["health_check_id"] = f"health_{int(time.time())}"
100
- context.params["hook_enhanced"] = True
101
-
102
- logger.info(f"🏥 Starting enhanced health check")
103
-
104
-
105
- def health_after_hook(context: HookContext) -> None:
106
- """
107
- After hook for health command.
108
-
109
- Args:
110
- context: Hook context with command information
111
- """
112
- logger.info(f"✅ Health command completed successfully")
113
-
114
- # Log health status
115
- if context.result and hasattr(context.result, 'data'):
116
- status = context.result.data.get("status", "unknown")
117
- uptime = context.result.data.get("uptime", 0)
118
- logger.info(f"🏥 Health status: {status}, Uptime: {uptime:.2f}s")
119
-
120
-
121
- def global_before_hook(context: HookContext) -> None:
122
- """
123
- Global before hook for all commands.
124
-
125
- Args:
126
- context: Hook context with command information
127
- """
128
- logger.info(f"🌐 Global before hook: {context.command_name}")
129
-
130
- # Add global tracking
131
- context.params["global_hook_processed"] = True
132
- context.params["execution_start_time"] = time.time()
133
-
134
- logger.info(f"🚀 Starting execution of '{context.command_name}'")
135
-
136
-
137
- def global_after_hook(context: HookContext) -> None:
138
- """
139
- Global after hook for all commands.
140
-
141
- Args:
142
- context: Hook context with command information
143
- """
144
- start_time = context.params.get("execution_start_time", time.time())
145
- execution_time = time.time() - start_time
146
-
147
- logger.info(f"🌐 Global after hook: {context.command_name}")
148
- logger.info(f"⏱️ Execution time: {execution_time:.3f}s")
149
-
150
- # Log success/failure
151
- if context.result:
152
- logger.info(f"✅ Command '{context.command_name}' completed successfully")
153
- else:
154
- logger.warning(f"⚠️ Command '{context.command_name}' completed with issues")
155
-
156
-
157
- def performance_hook(context: HookContext) -> None:
158
- """
159
- Performance monitoring hook.
160
-
161
- Args:
162
- context: Hook context with command information
163
- """
164
- if context.hook_type == HookType.BEFORE_EXECUTION:
165
- # Store start time
166
- context.params["_performance_start"] = time.time()
167
- logger.debug(f"⏱️ Performance monitoring started for {context.command_name}")
168
-
169
- elif context.hook_type == HookType.AFTER_EXECUTION:
170
- # Calculate execution time
171
- start_time = context.params.get("_performance_start", time.time())
172
- execution_time = time.time() - start_time
173
-
174
- logger.info(f"📊 Performance: {context.command_name} took {execution_time:.3f}s")
175
-
176
- # Log slow commands
177
- if execution_time > 1.0:
178
- logger.warning(f"🐌 Slow command detected: {context.command_name} ({execution_time:.3f}s)")
179
-
180
-
181
- def security_hook(context: HookContext) -> None:
182
- """
183
- Security monitoring hook.
184
-
185
- Args:
186
- context: Hook context with command information
187
- """
188
- if context.hook_type == HookType.BEFORE_EXECUTION:
189
- # Check for sensitive data in params
190
- sensitive_keys = ["password", "token", "secret", "key"]
191
- found_sensitive = [key for key in context.params.keys() if any(s in key.lower() for s in sensitive_keys)]
192
-
193
- if found_sensitive:
194
- logger.warning(f"🔒 Security: Sensitive parameters detected in {context.command_name}: {found_sensitive}")
195
-
196
- # Add security metadata
197
- context.params["_security_checked"] = True
198
- logger.debug(f"🔒 Security check completed for {context.command_name}")
199
-
200
-
201
- def register_all_hooks(hooks_manager) -> None:
202
- """
203
- Register all hooks with the hooks manager.
204
-
205
- Args:
206
- hooks_manager: The hooks manager instance
207
- """
208
- logger.info("🔧 Registering custom hooks...")
209
-
210
- # Register command-specific hooks
211
- hooks_manager.register_before_hook("echo", echo_before_hook)
212
- hooks_manager.register_after_hook("echo", echo_after_hook)
213
-
214
- hooks_manager.register_before_hook("help", help_before_hook)
215
- hooks_manager.register_after_hook("help", help_after_hook)
216
-
217
- hooks_manager.register_before_hook("health", health_before_hook)
218
- hooks_manager.register_after_hook("health", health_after_hook)
219
-
220
- # Register global hooks
221
- hooks_manager.register_global_before_hook(global_before_hook)
222
- hooks_manager.register_global_after_hook(global_after_hook)
223
-
224
- # Register utility hooks
225
- hooks_manager.register_global_before_hook(performance_hook)
226
- hooks_manager.register_global_after_hook(performance_hook)
227
-
228
- hooks_manager.register_global_before_hook(security_hook)
229
-
230
- logger.info("✅ All hooks registered successfully")
@@ -1,123 +0,0 @@
1
- """
2
- Intercept Command Example
3
-
4
- A command that can be completely intercepted by hooks based on conditions.
5
- """
6
-
7
- from typing import Dict, Any, Optional
8
- from mcp_proxy_adapter.commands.base import Command
9
- from mcp_proxy_adapter.commands.result import CommandResult
10
-
11
-
12
- class InterceptResult(CommandResult):
13
- """
14
- Result of the intercept command execution.
15
- """
16
-
17
- def __init__(self, message: str, executed: bool, intercept_reason: Optional[str] = None,
18
- hook_data: Optional[Dict[str, Any]] = None):
19
- """
20
- Initialize intercept command result.
21
-
22
- Args:
23
- message: Result message
24
- executed: Whether the command was actually executed
25
- intercept_reason: Reason for interception (if any)
26
- hook_data: Data from hooks
27
- """
28
- self.message = message
29
- self.executed = executed
30
- self.intercept_reason = intercept_reason
31
- self.hook_data = hook_data or {}
32
-
33
- def to_dict(self) -> Dict[str, Any]:
34
- """
35
- Convert result to dictionary.
36
-
37
- Returns:
38
- Dict[str, Any]: Result as dictionary
39
- """
40
- return {
41
- "message": self.message,
42
- "executed": self.executed,
43
- "intercept_reason": self.intercept_reason,
44
- "hook_data": self.hook_data,
45
- "command_type": "intercept"
46
- }
47
-
48
- @classmethod
49
- def get_schema(cls) -> Dict[str, Any]:
50
- """
51
- Get JSON schema for the result.
52
-
53
- Returns:
54
- Dict[str, Any]: JSON schema
55
- """
56
- return {
57
- "type": "object",
58
- "properties": {
59
- "message": {"type": "string"},
60
- "executed": {"type": "boolean"},
61
- "intercept_reason": {"type": "string"},
62
- "hook_data": {"type": "object"},
63
- "command_type": {"type": "string"}
64
- }
65
- }
66
-
67
-
68
- class InterceptCommand(Command):
69
- """
70
- Intercept command for demonstrating hook interception.
71
- """
72
-
73
- name = "intercept"
74
- result_class = InterceptResult
75
-
76
- async def execute(self, action: Optional[str] = None,
77
- bypass_flag: Optional[int] = None, **kwargs) -> InterceptResult:
78
- """
79
- Execute intercept command.
80
-
81
- Args:
82
- action: Action to perform
83
- bypass_flag: Flag to determine if command should be bypassed (0 = bypass, 1 = execute)
84
- **kwargs: Additional parameters
85
-
86
- Returns:
87
- InterceptResult: Intercept command result
88
- """
89
- action = action or "default"
90
- bypass_flag = bypass_flag if bypass_flag is not None else 1
91
-
92
- # This should only execute if bypass_flag == 1
93
- # If bypass_flag == 0, hooks should intercept and return result
94
-
95
- return InterceptResult(
96
- message=f"Command executed with action: {action}",
97
- executed=True,
98
- intercept_reason=None,
99
- hook_data=kwargs
100
- )
101
-
102
- @classmethod
103
- def get_schema(cls) -> Dict[str, Any]:
104
- """
105
- Get JSON schema for command parameters.
106
-
107
- Returns:
108
- Dict[str, Any]: JSON schema
109
- """
110
- return {
111
- "type": "object",
112
- "properties": {
113
- "action": {
114
- "type": "string",
115
- "description": "Action to perform"
116
- },
117
- "bypass_flag": {
118
- "type": "integer",
119
- "enum": [0, 1],
120
- "description": "Flag to determine execution (0 = bypass, 1 = execute)"
121
- }
122
- }
123
- }
@@ -1,129 +0,0 @@
1
- """
2
- Test command for loadable commands testing.
3
-
4
- This command demonstrates the loadable commands functionality.
5
- """
6
-
7
- from typing import Any, Dict
8
-
9
- from mcp_proxy_adapter.commands.base import Command
10
- from mcp_proxy_adapter.commands.result import SuccessResult
11
-
12
-
13
- class TestCommandResult:
14
- """
15
- Result of test command execution.
16
- """
17
-
18
- def __init__(self, message: str, test_data: Dict[str, Any]):
19
- """
20
- Initialize test command result.
21
-
22
- Args:
23
- message: Result message
24
- test_data: Test data
25
- """
26
- self.message = message
27
- self.test_data = test_data
28
-
29
- def to_dict(self) -> Dict[str, Any]:
30
- """
31
- Convert result to dictionary.
32
-
33
- Returns:
34
- Dictionary representation of the result.
35
- """
36
- return {
37
- "success": True,
38
- "message": self.message,
39
- "test_data": self.test_data
40
- }
41
-
42
- @classmethod
43
- def get_schema(cls) -> Dict[str, Any]:
44
- """
45
- Get JSON schema for the result.
46
-
47
- Returns:
48
- JSON schema dictionary.
49
- """
50
- return {
51
- "type": "object",
52
- "properties": {
53
- "success": {
54
- "type": "boolean",
55
- "description": "Whether command was successful"
56
- },
57
- "message": {
58
- "type": "string",
59
- "description": "Result message"
60
- },
61
- "test_data": {
62
- "type": "object",
63
- "description": "Test data"
64
- }
65
- },
66
- "required": ["success", "message", "test_data"]
67
- }
68
-
69
-
70
- class TestCommand(Command):
71
- """
72
- Test command for loadable commands testing.
73
- """
74
-
75
- name = "test"
76
- result_class = TestCommandResult
77
-
78
- async def execute(self, **kwargs) -> TestCommandResult:
79
- """
80
- Execute test command.
81
-
82
- Args:
83
- **kwargs: Command parameters
84
-
85
- Returns:
86
- TestCommandResult with test information
87
- """
88
- # Get parameters
89
- test_param = kwargs.get("test_param", "default_value")
90
- echo_text = kwargs.get("echo_text", "Hello from loadable command!")
91
-
92
- # Create test data
93
- test_data = {
94
- "command_type": "loadable",
95
- "test_param": test_param,
96
- "echo_text": echo_text,
97
- "timestamp": "2025-08-12T09:45:00Z",
98
- "status": "working"
99
- }
100
-
101
- return TestCommandResult(
102
- message=f"Test command executed successfully with param: {test_param}",
103
- test_data=test_data
104
- )
105
-
106
- @classmethod
107
- def get_schema(cls) -> Dict[str, Any]:
108
- """
109
- Get JSON schema for command parameters.
110
-
111
- Returns:
112
- JSON schema dictionary.
113
- """
114
- return {
115
- "type": "object",
116
- "properties": {
117
- "test_param": {
118
- "type": "string",
119
- "description": "Test parameter",
120
- "default": "default_value"
121
- },
122
- "echo_text": {
123
- "type": "string",
124
- "description": "Text to echo",
125
- "default": "Hello from loadable command!"
126
- }
127
- },
128
- "additionalProperties": False
129
- }
@@ -1,103 +0,0 @@
1
- """
2
- Manually registered Echo Command
3
-
4
- This command must be manually registered in the server code.
5
- """
6
-
7
- from typing import Dict, Any, Optional
8
- from mcp_proxy_adapter.commands.base import Command
9
- from mcp_proxy_adapter.commands.result import CommandResult
10
-
11
-
12
- class ManualEchoResult(CommandResult):
13
- """
14
- Result of the manually registered echo command execution.
15
- """
16
-
17
- def __init__(self, message: str, manually_registered: bool = True):
18
- """
19
- Initialize manual echo command result.
20
-
21
- Args:
22
- message: Echoed message
23
- manually_registered: Flag indicating this was manually registered
24
- """
25
- self.message = message
26
- self.manually_registered = manually_registered
27
-
28
- def to_dict(self) -> Dict[str, Any]:
29
- """
30
- Convert result to dictionary.
31
-
32
- Returns:
33
- Dict[str, Any]: Result as dictionary
34
- """
35
- return {
36
- "message": self.message,
37
- "manually_registered": self.manually_registered,
38
- "command_type": "manual_echo"
39
- }
40
-
41
- @classmethod
42
- def get_schema(cls) -> Dict[str, Any]:
43
- """
44
- Get JSON schema for the result.
45
-
46
- Returns:
47
- Dict[str, Any]: JSON schema
48
- """
49
- return {
50
- "type": "object",
51
- "properties": {
52
- "message": {"type": "string"},
53
- "manually_registered": {"type": "boolean"},
54
- "command_type": {"type": "string"}
55
- }
56
- }
57
-
58
-
59
- class ManualEchoCommand(Command):
60
- """
61
- Manually registered echo command.
62
- """
63
-
64
- name = "manual_echo"
65
- result_class = ManualEchoResult
66
-
67
- async def execute(self, message: Optional[str] = None, **kwargs) -> ManualEchoResult:
68
- """
69
- Execute manually registered echo command.
70
-
71
- Args:
72
- message: Message to echo
73
- **kwargs: Additional parameters
74
-
75
- Returns:
76
- ManualEchoResult: Manual echo command result
77
- """
78
- if message is None:
79
- message = "Hello from manually registered command!"
80
-
81
- return ManualEchoResult(
82
- message=message,
83
- manually_registered=True
84
- )
85
-
86
- @classmethod
87
- def get_schema(cls) -> Dict[str, Any]:
88
- """
89
- Get JSON schema for command parameters.
90
-
91
- Returns:
92
- Dict[str, Any]: JSON schema
93
- """
94
- return {
95
- "type": "object",
96
- "properties": {
97
- "message": {
98
- "type": "string",
99
- "description": "Message to echo",
100
- "default": "Hello from manually registered command!"
101
- }
102
- }
103
- }