mcp-proxy-adapter 2.0.1__py3-none-any.whl → 6.9.50__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (269) hide show
  1. mcp_proxy_adapter/__init__.py +47 -0
  2. mcp_proxy_adapter/__main__.py +13 -0
  3. mcp_proxy_adapter/api/__init__.py +0 -0
  4. mcp_proxy_adapter/api/app.py +66 -0
  5. mcp_proxy_adapter/api/core/__init__.py +18 -0
  6. mcp_proxy_adapter/api/core/app_factory.py +400 -0
  7. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  8. mcp_proxy_adapter/api/core/registration_context.py +356 -0
  9. mcp_proxy_adapter/api/core/registration_manager.py +307 -0
  10. mcp_proxy_adapter/api/core/registration_tasks.py +84 -0
  11. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  12. mcp_proxy_adapter/api/handlers.py +181 -0
  13. mcp_proxy_adapter/api/middleware/__init__.py +21 -0
  14. mcp_proxy_adapter/api/middleware/base.py +54 -0
  15. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +73 -0
  16. mcp_proxy_adapter/api/middleware/error_handling.py +76 -0
  17. mcp_proxy_adapter/api/middleware/factory.py +147 -0
  18. mcp_proxy_adapter/api/middleware/logging.py +31 -0
  19. mcp_proxy_adapter/api/middleware/performance.py +51 -0
  20. mcp_proxy_adapter/api/middleware/protocol_middleware.py +140 -0
  21. mcp_proxy_adapter/api/middleware/transport_middleware.py +87 -0
  22. mcp_proxy_adapter/api/middleware/unified_security.py +223 -0
  23. mcp_proxy_adapter/api/middleware/user_info_middleware.py +132 -0
  24. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  25. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  26. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  27. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  28. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  29. mcp_proxy_adapter/api/schemas.py +270 -0
  30. mcp_proxy_adapter/api/tool_integration.py +131 -0
  31. mcp_proxy_adapter/api/tools.py +163 -0
  32. mcp_proxy_adapter/cli/__init__.py +12 -0
  33. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  34. mcp_proxy_adapter/cli/commands/client.py +100 -0
  35. mcp_proxy_adapter/cli/commands/config_generate.py +105 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +94 -0
  37. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  38. mcp_proxy_adapter/cli/commands/server.py +174 -0
  39. mcp_proxy_adapter/cli/commands/sets.py +132 -0
  40. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  41. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  42. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  43. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  44. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  45. mcp_proxy_adapter/cli/main.py +63 -0
  46. mcp_proxy_adapter/cli/parser.py +338 -0
  47. mcp_proxy_adapter/cli/validators.py +231 -0
  48. mcp_proxy_adapter/client/jsonrpc_client/__init__.py +9 -0
  49. mcp_proxy_adapter/client/jsonrpc_client/client.py +42 -0
  50. mcp_proxy_adapter/client/jsonrpc_client/command_api.py +45 -0
  51. mcp_proxy_adapter/client/jsonrpc_client/proxy_api.py +224 -0
  52. mcp_proxy_adapter/client/jsonrpc_client/queue_api.py +60 -0
  53. mcp_proxy_adapter/client/jsonrpc_client/transport.py +108 -0
  54. mcp_proxy_adapter/client/proxy.py +123 -0
  55. mcp_proxy_adapter/commands/__init__.py +66 -0
  56. mcp_proxy_adapter/commands/auth_validation_command.py +69 -0
  57. mcp_proxy_adapter/commands/base.py +389 -0
  58. mcp_proxy_adapter/commands/builtin_commands.py +30 -0
  59. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  60. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  61. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  62. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  63. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  64. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  65. mcp_proxy_adapter/commands/catalog_manager.py +97 -0
  66. mcp_proxy_adapter/commands/cert_monitor_command.py +552 -0
  67. mcp_proxy_adapter/commands/certificate_management_command.py +562 -0
  68. mcp_proxy_adapter/commands/command_registry.py +298 -0
  69. mcp_proxy_adapter/commands/config_command.py +102 -0
  70. mcp_proxy_adapter/commands/dependency_container.py +40 -0
  71. mcp_proxy_adapter/commands/dependency_manager.py +143 -0
  72. mcp_proxy_adapter/commands/echo_command.py +48 -0
  73. mcp_proxy_adapter/commands/health_command.py +142 -0
  74. mcp_proxy_adapter/commands/help_command.py +175 -0
  75. mcp_proxy_adapter/commands/hooks.py +172 -0
  76. mcp_proxy_adapter/commands/key_management_command.py +484 -0
  77. mcp_proxy_adapter/commands/load_command.py +123 -0
  78. mcp_proxy_adapter/commands/plugins_command.py +246 -0
  79. mcp_proxy_adapter/commands/protocol_management_command.py +216 -0
  80. mcp_proxy_adapter/commands/proxy_registration_command.py +319 -0
  81. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  82. mcp_proxy_adapter/commands/registration_status_command.py +76 -0
  83. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  84. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  85. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  86. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  87. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  88. mcp_proxy_adapter/commands/reload_command.py +136 -0
  89. mcp_proxy_adapter/commands/result.py +157 -0
  90. mcp_proxy_adapter/commands/role_test_command.py +99 -0
  91. mcp_proxy_adapter/commands/roles_management_command.py +502 -0
  92. mcp_proxy_adapter/commands/security_command.py +472 -0
  93. mcp_proxy_adapter/commands/settings_command.py +113 -0
  94. mcp_proxy_adapter/commands/ssl_setup_command.py +306 -0
  95. mcp_proxy_adapter/commands/token_management_command.py +500 -0
  96. mcp_proxy_adapter/commands/transport_management_command.py +129 -0
  97. mcp_proxy_adapter/commands/unload_command.py +92 -0
  98. mcp_proxy_adapter/config.py +32 -0
  99. mcp_proxy_adapter/core/__init__.py +8 -0
  100. mcp_proxy_adapter/core/app_factory.py +560 -0
  101. mcp_proxy_adapter/core/app_runner.py +318 -0
  102. mcp_proxy_adapter/core/auth_validator.py +508 -0
  103. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  104. mcp_proxy_adapter/core/certificate/certificate_creator.py +372 -0
  105. mcp_proxy_adapter/core/certificate/certificate_extractor.py +185 -0
  106. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  107. mcp_proxy_adapter/core/certificate/certificate_validator.py +481 -0
  108. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +65 -0
  109. mcp_proxy_adapter/core/certificate_utils.py +249 -0
  110. mcp_proxy_adapter/core/client.py +608 -0
  111. mcp_proxy_adapter/core/client_manager.py +271 -0
  112. mcp_proxy_adapter/core/client_security.py +411 -0
  113. mcp_proxy_adapter/core/config/__init__.py +18 -0
  114. mcp_proxy_adapter/core/config/config.py +237 -0
  115. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  116. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  117. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  118. mcp_proxy_adapter/core/config/simple_config.py +204 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +131 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +476 -0
  121. mcp_proxy_adapter/core/config_converter.py +252 -0
  122. mcp_proxy_adapter/core/config_validator.py +211 -0
  123. mcp_proxy_adapter/core/crl_utils.py +362 -0
  124. mcp_proxy_adapter/core/errors.py +276 -0
  125. mcp_proxy_adapter/core/job_manager.py +54 -0
  126. mcp_proxy_adapter/core/logging.py +250 -0
  127. mcp_proxy_adapter/core/mtls_asgi.py +140 -0
  128. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  129. mcp_proxy_adapter/core/mtls_proxy.py +229 -0
  130. mcp_proxy_adapter/core/mtls_server.py +154 -0
  131. mcp_proxy_adapter/core/protocol_manager.py +232 -0
  132. mcp_proxy_adapter/core/proxy/__init__.py +19 -0
  133. mcp_proxy_adapter/core/proxy/auth_manager.py +26 -0
  134. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +160 -0
  135. mcp_proxy_adapter/core/proxy/registration_client.py +186 -0
  136. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  137. mcp_proxy_adapter/core/proxy_client.py +184 -0
  138. mcp_proxy_adapter/core/proxy_registration.py +80 -0
  139. mcp_proxy_adapter/core/role_utils.py +103 -0
  140. mcp_proxy_adapter/core/security_adapter.py +343 -0
  141. mcp_proxy_adapter/core/security_factory.py +96 -0
  142. mcp_proxy_adapter/core/security_integration.py +342 -0
  143. mcp_proxy_adapter/core/server_adapter.py +251 -0
  144. mcp_proxy_adapter/core/server_engine.py +217 -0
  145. mcp_proxy_adapter/core/settings.py +260 -0
  146. mcp_proxy_adapter/core/signal_handler.py +107 -0
  147. mcp_proxy_adapter/core/ssl_utils.py +161 -0
  148. mcp_proxy_adapter/core/transport_manager.py +153 -0
  149. mcp_proxy_adapter/core/unified_config_adapter.py +471 -0
  150. mcp_proxy_adapter/core/utils.py +101 -0
  151. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  152. mcp_proxy_adapter/core/validation/config_validator.py +219 -0
  153. mcp_proxy_adapter/core/validation/file_validator.py +131 -0
  154. mcp_proxy_adapter/core/validation/protocol_validator.py +205 -0
  155. mcp_proxy_adapter/core/validation/security_validator.py +140 -0
  156. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  157. mcp_proxy_adapter/custom_openapi.py +58 -0
  158. mcp_proxy_adapter/examples/__init__.py +16 -0
  159. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  160. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  161. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  162. mcp_proxy_adapter/examples/basic_framework/main.py +52 -0
  163. mcp_proxy_adapter/examples/bugfix_certificate_config.py +261 -0
  164. mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
  165. mcp_proxy_adapter/examples/check_config.py +413 -0
  166. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  167. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  168. mcp_proxy_adapter/examples/config_builder.py +234 -0
  169. mcp_proxy_adapter/examples/config_cli.py +282 -0
  170. mcp_proxy_adapter/examples/create_test_configs.py +174 -0
  171. mcp_proxy_adapter/examples/debug_request_state.py +130 -0
  172. mcp_proxy_adapter/examples/debug_role_chain.py +191 -0
  173. mcp_proxy_adapter/examples/demo_client.py +287 -0
  174. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  175. mcp_proxy_adapter/examples/full_application/commands/__init__.py +8 -0
  176. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +45 -0
  177. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +52 -0
  178. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +32 -0
  179. mcp_proxy_adapter/examples/full_application/commands/help_command.py +54 -0
  180. mcp_proxy_adapter/examples/full_application/commands/list_command.py +57 -0
  181. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +5 -0
  182. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +29 -0
  183. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +27 -0
  184. mcp_proxy_adapter/examples/full_application/main.py +311 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +161 -0
  186. mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
  187. mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
  188. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +45 -0
  189. mcp_proxy_adapter/examples/full_application/test_server.py +163 -0
  190. mcp_proxy_adapter/examples/full_application/test_simple_server.py +62 -0
  191. mcp_proxy_adapter/examples/generate_config.py +502 -0
  192. mcp_proxy_adapter/examples/proxy_registration_example.py +335 -0
  193. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  194. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  195. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  196. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  197. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  198. mcp_proxy_adapter/examples/required_certificates.py +208 -0
  199. mcp_proxy_adapter/examples/run_example.py +77 -0
  200. mcp_proxy_adapter/examples/run_full_test_suite.py +619 -0
  201. mcp_proxy_adapter/examples/run_proxy_server.py +153 -0
  202. mcp_proxy_adapter/examples/run_security_tests_fixed.py +435 -0
  203. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  204. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  205. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  206. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  207. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  208. mcp_proxy_adapter/examples/security_test_client.py +72 -0
  209. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  210. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  211. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  212. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  213. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  214. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  215. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  216. mcp_proxy_adapter/examples/setup_test_environment.py +235 -0
  217. mcp_proxy_adapter/examples/simple_protocol_test.py +125 -0
  218. mcp_proxy_adapter/examples/test_chk_hostname_automated.py +211 -0
  219. mcp_proxy_adapter/examples/test_config.py +205 -0
  220. mcp_proxy_adapter/examples/test_config_builder.py +110 -0
  221. mcp_proxy_adapter/examples/test_examples.py +308 -0
  222. mcp_proxy_adapter/examples/test_framework_complete.py +267 -0
  223. mcp_proxy_adapter/examples/test_mcp_server.py +187 -0
  224. mcp_proxy_adapter/examples/test_protocol_examples.py +337 -0
  225. mcp_proxy_adapter/examples/universal_client.py +674 -0
  226. mcp_proxy_adapter/examples/update_config_certificates.py +135 -0
  227. mcp_proxy_adapter/examples/validate_generator_compatibility.py +385 -0
  228. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +61 -0
  229. mcp_proxy_adapter/integrations/__init__.py +25 -0
  230. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  231. mcp_proxy_adapter/main.py +311 -0
  232. mcp_proxy_adapter/openapi.py +375 -0
  233. mcp_proxy_adapter/schemas/base_schema.json +114 -0
  234. mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
  235. mcp_proxy_adapter/schemas/roles.json +37 -0
  236. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  237. mcp_proxy_adapter/version.py +5 -0
  238. mcp_proxy_adapter-6.9.50.dist-info/METADATA +1088 -0
  239. mcp_proxy_adapter-6.9.50.dist-info/RECORD +242 -0
  240. {mcp_proxy_adapter-2.0.1.dist-info → mcp_proxy_adapter-6.9.50.dist-info}/WHEEL +1 -1
  241. mcp_proxy_adapter-6.9.50.dist-info/entry_points.txt +14 -0
  242. mcp_proxy_adapter-6.9.50.dist-info/top_level.txt +1 -0
  243. adapters/__init__.py +0 -16
  244. analyzers/__init__.py +0 -14
  245. analyzers/docstring_analyzer.py +0 -199
  246. analyzers/type_analyzer.py +0 -151
  247. cli/__init__.py +0 -12
  248. cli/__main__.py +0 -79
  249. cli/command_runner.py +0 -233
  250. dispatchers/__init__.py +0 -14
  251. dispatchers/base_dispatcher.py +0 -85
  252. dispatchers/json_rpc_dispatcher.py +0 -198
  253. generators/__init__.py +0 -14
  254. generators/endpoint_generator.py +0 -172
  255. generators/openapi_generator.py +0 -254
  256. generators/rest_api_generator.py +0 -207
  257. mcp_proxy_adapter-2.0.1.dist-info/METADATA +0 -272
  258. mcp_proxy_adapter-2.0.1.dist-info/RECORD +0 -28
  259. mcp_proxy_adapter-2.0.1.dist-info/licenses/LICENSE +0 -21
  260. mcp_proxy_adapter-2.0.1.dist-info/top_level.txt +0 -7
  261. openapi_schema/__init__.py +0 -38
  262. openapi_schema/command_registry.py +0 -312
  263. openapi_schema/rest_schema.py +0 -510
  264. openapi_schema/rpc_generator.py +0 -307
  265. openapi_schema/rpc_schema.py +0 -416
  266. validators/__init__.py +0 -14
  267. validators/base_validator.py +0 -23
  268. validators/docstring_validator.py +0 -75
  269. validators/metadata_validator.py +0 -76
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Debug Request State - Проверка request.state
4
+ Этот скрипт проверяет, как middleware устанавливает информацию о пользователе в request.state.
5
+ Author: Vasiliy Zdanovskiy
6
+ email: vasilyvz@gmail.com
7
+ """
8
+ import asyncio
9
+ import json
10
+ import sys
11
+ from pathlib import Path
12
+
13
+ # Add project root to path
14
+ project_root = Path(__file__).parent.parent.parent
15
+ sys.path.insert(0, str(project_root))
16
+ from fastapi.testclient import TestClient
17
+ from mcp_proxy_adapter.api.app import create_app
18
+
19
+
20
+ async def debug_request_state():
21
+ """Debug request state handling."""
22
+ print("🔍 ОТЛАДКА REQUEST.STATE")
23
+ print("=" * 50)
24
+ # Create test app with proper configuration
25
+ config_path = (
26
+ project_root
27
+ / "mcp_proxy_adapter"
28
+ / "examples"
29
+ / "server_configs"
30
+ / "config_http_token.json"
31
+ )
32
+ with open(config_path) as f:
33
+ config = json.load(f)
34
+ # Override global config for testing
35
+ import mcp_proxy_adapter.config
36
+
37
+ mcp_proxy_adapter.config.config = config
38
+ app = create_app(config)
39
+ client = TestClient(app)
40
+ print("📋 1. ТЕСТИРОВАНИЕ БЕЗ АУТЕНТИФИКАЦИИ")
41
+ print("-" * 30)
42
+ # Test without authentication
43
+ response = client.post(
44
+ "/cmd",
45
+ json={
46
+ "jsonrpc": "2.0",
47
+ "method": "echo",
48
+ "params": {"message": "test"},
49
+ "id": 1,
50
+ },
51
+ )
52
+ print(f"Status: {response.status_code}")
53
+ print(f"Response: {response.json()}")
54
+ print("\n📋 2. ТЕСТИРОВАНИЕ С ADMIN ТОКЕНОМ")
55
+ print("-" * 30)
56
+ # Test with admin token
57
+ response = client.post(
58
+ "/cmd",
59
+ json={
60
+ "jsonrpc": "2.0",
61
+ "method": "echo",
62
+ "params": {"message": "test"},
63
+ "id": 1,
64
+ },
65
+ headers={"X-API-Key": "test-token-123"},
66
+ )
67
+ print(f"Status: {response.status_code}")
68
+ print(f"Response: {response.json()}")
69
+ print("\n📋 3. ТЕСТИРОВАНИЕ С USER ТОКЕНОМ")
70
+ print("-" * 30)
71
+ # Test with user token
72
+ response = client.post(
73
+ "/cmd",
74
+ json={
75
+ "jsonrpc": "2.0",
76
+ "method": "echo",
77
+ "params": {"message": "test"},
78
+ "id": 1,
79
+ },
80
+ headers={"X-API-Key": "user-token-456"},
81
+ )
82
+ print(f"Status: {response.status_code}")
83
+ print(f"Response: {response.json()}")
84
+ print("\n📋 4. ТЕСТИРОВАНИЕ С READONLY ТОКЕНОМ")
85
+ print("-" * 30)
86
+ # Test with readonly token
87
+ response = client.post(
88
+ "/cmd",
89
+ json={
90
+ "jsonrpc": "2.0",
91
+ "method": "echo",
92
+ "params": {"message": "test"},
93
+ "id": 1,
94
+ },
95
+ headers={"X-API-Key": "readonly-token-123"},
96
+ )
97
+ print(f"Status: {response.status_code}")
98
+ print(f"Response: {response.json()}")
99
+ print("\n📋 5. ТЕСТИРОВАНИЕ ROLE_TEST КОМАНДЫ")
100
+ print("-" * 30)
101
+ # Test role_test command with readonly token
102
+ response = client.post(
103
+ "/cmd",
104
+ json={
105
+ "jsonrpc": "2.0",
106
+ "method": "role_test",
107
+ "params": {"action": "write"},
108
+ "id": 1,
109
+ },
110
+ headers={"X-API-Key": "readonly-token-123"},
111
+ )
112
+ print(f"Status: {response.status_code}")
113
+ print(f"Response: {response.json()}")
114
+ print("\n📋 6. АНАЛИЗ ПРОБЛЕМЫ")
115
+ print("-" * 30)
116
+ print("🔍 ПРОБЛЕМА: Readonly роль получает доступ к командам")
117
+ print("\n📋 ВОЗМОЖНЫЕ ПРИЧИНЫ:")
118
+ print("1. Framework middleware не устанавливает user info в request.state")
119
+ print("2. Нет проверки прав на уровне middleware")
120
+ print("3. Команды не проверяют права доступа")
121
+ print("4. Интеграция между middleware и командами не работает")
122
+ print("\n📋 РЕКОМЕНДАЦИИ:")
123
+ print("1. Добавить CommandPermissionMiddleware")
124
+ print("2. Убедиться, что framework middleware устанавливает user info")
125
+ print("3. Добавить проверку прав в команды")
126
+ print("4. Проверить интеграцию middleware")
127
+
128
+
129
+ if __name__ == "__main__":
130
+ asyncio.run(debug_request_state())
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Debug Role Chain - Анализ цепочки блокировки ролей
4
+ Этот скрипт анализирует всю цепочку от аутентификации до блокировки доступа.
5
+ Author: Vasiliy Zdanovskiy
6
+ email: vasilyvz@gmail.com
7
+ """
8
+ import asyncio
9
+ import json
10
+ import sys
11
+ from pathlib import Path
12
+
13
+ # Add project root to path
14
+ project_root = Path(__file__).parent.parent.parent
15
+ sys.path.insert(0, str(project_root))
16
+ from mcp_security_framework import SecurityManager, AuthManager, PermissionManager
17
+ from mcp_security_framework.schemas.config import (
18
+ SecurityConfig,
19
+ AuthConfig,
20
+ PermissionConfig,
21
+ )
22
+
23
+
24
+ async def debug_role_chain():
25
+ """Debug the complete role chain from authentication to blocking."""
26
+ print("🔍 АНАЛИЗ ЦЕПОЧКИ БЛОКИРОВКИ РОЛЕЙ")
27
+ print("=" * 60)
28
+ # Load configuration
29
+ config_path = (
30
+ project_root
31
+ / "mcp_proxy_adapter"
32
+ / "examples"
33
+ / "server_configs"
34
+ / "config_http_token.json"
35
+ )
36
+ with open(config_path) as f:
37
+ config = json.load(f)
38
+ security_config = config.get("security", {})
39
+ print("📋 1. КОНФИГУРАЦИЯ API КЛЮЧЕЙ")
40
+ print("-" * 30)
41
+ api_keys = security_config.get("auth", {}).get("api_keys", {})
42
+ for key, value in api_keys.items():
43
+ print(f" {key}: {value}")
44
+ print("\n📋 2. КОНФИГУРАЦИЯ РОЛЕЙ")
45
+ print("-" * 30)
46
+ roles_config = security_config.get("permissions", {}).get("roles", {})
47
+ for role, permissions in roles_config.items():
48
+ print(f" {role}: {permissions}")
49
+ print("\n📋 3. СОЗДАНИЕ КОМПОНЕНТОВ БЕЗОПАСНОСТИ")
50
+ print("-" * 30)
51
+ # Create permission config
52
+ perm_config = PermissionConfig(
53
+ roles_file=str(
54
+ project_root
55
+ / "mcp_proxy_adapter"
56
+ / "examples"
57
+ / "server_configs"
58
+ / "roles.json"
59
+ ),
60
+ default_role="guest",
61
+ admin_role="admin",
62
+ role_hierarchy=security_config.get("permissions", {}).get("role_hierarchy", {}),
63
+ permission_cache_enabled=True,
64
+ permission_cache_ttl=300,
65
+ wildcard_permissions=False,
66
+ strict_mode=True,
67
+ roles=roles_config,
68
+ )
69
+ # Create auth config
70
+ auth_config = AuthConfig(
71
+ enabled=security_config.get("auth", {}).get("enabled", True),
72
+ methods=security_config.get("auth", {}).get("methods", ["api_key"]),
73
+ api_keys=api_keys,
74
+ user_roles=security_config.get("auth", {}).get("user_roles", {}),
75
+ jwt_secret=security_config.get("auth", {}).get("jwt_secret"),
76
+ jwt_algorithm=security_config.get("auth", {}).get("jwt_algorithm", "HS256"),
77
+ jwt_expiry_hours=security_config.get("auth", {}).get("jwt_expiry_hours", 24),
78
+ certificate_auth=security_config.get("auth", {}).get("certificate_auth", False),
79
+ certificate_roles_oid=security_config.get("auth", {}).get(
80
+ "certificate_roles_oid"
81
+ ),
82
+ certificate_permissions_oid=security_config.get("auth", {}).get(
83
+ "certificate_permissions_oid"
84
+ ),
85
+ basic_auth=security_config.get("auth", {}).get("basic_auth", False),
86
+ oauth2_config=security_config.get("auth", {}).get("oauth2_config"),
87
+ public_paths=security_config.get("auth", {}).get("public_paths", []),
88
+ )
89
+ # Create security config
90
+ security_config_obj = SecurityConfig(auth=auth_config, permissions=perm_config)
91
+ print("✅ Конфигурации созданы")
92
+ print("\n📋 4. ИНИЦИАЛИЗАЦИЯ МЕНЕДЖЕРОВ")
93
+ print("-" * 30)
94
+ # Initialize managers
95
+ permission_manager = PermissionManager(perm_config)
96
+ auth_manager = AuthManager(auth_config, permission_manager)
97
+ security_manager = SecurityManager(security_config_obj)
98
+ print("✅ Менеджеры инициализированы")
99
+ print("\n📋 5. ТЕСТИРОВАНИЕ АУТЕНТИФИКАЦИИ")
100
+ print("-" * 30)
101
+ # Test authentication with different tokens
102
+ test_tokens = {
103
+ "admin": "test-token-123",
104
+ "user": "user-token-456",
105
+ "readonly": "readonly-token-123",
106
+ "invalid": "invalid-token-999",
107
+ }
108
+ auth_results = {}
109
+ for role, token in test_tokens.items():
110
+ print(f"\n🔐 Тестирование токена для роли '{role}': {token}")
111
+ try:
112
+ result = auth_manager.authenticate_api_key(token)
113
+ auth_results[role] = result
114
+ print(
115
+ f" ✅ Аутентификация: {'УСПЕШНА' if result.is_valid else 'НЕУДАЧНА'}"
116
+ )
117
+ if result.is_valid:
118
+ print(f" 👤 Пользователь: {result.username}")
119
+ print(f" 🏷️ Роли: {result.roles}")
120
+ print(f" 🔑 Метод: {result.auth_method}")
121
+ else:
122
+ print(f" ❌ Ошибка: {result.error_message}")
123
+ except Exception as e:
124
+ print(f" ❌ Исключение: {e}")
125
+ auth_results[role] = None
126
+ print("\n📋 6. ТЕСТИРОВАНИЕ ПРАВ ДОСТУПА")
127
+ print("-" * 30)
128
+ # Test permissions for different actions
129
+ test_actions = ["read", "write", "manage", "delete"]
130
+ for role, auth_result in auth_results.items():
131
+ if auth_result and auth_result.is_valid:
132
+ print(
133
+ f"\n🔒 Тестирование прав для роли '{role}' (роли: {auth_result.roles})"
134
+ )
135
+ for action in test_actions:
136
+ try:
137
+ # Check permissions using permission manager
138
+ validation_result = permission_manager.validate_access(
139
+ auth_result.roles, [action]
140
+ )
141
+ status = (
142
+ "✅ РАЗРЕШЕНО"
143
+ if validation_result.is_valid
144
+ else "❌ ЗАБЛОКИРОВАНО"
145
+ )
146
+ print(f" {action}: {status}")
147
+ if not validation_result.is_valid:
148
+ print(f" 📝 Причина: {validation_result.error_message}")
149
+ print(
150
+ f" 🎯 Эффективные права: {validation_result.effective_permissions}"
151
+ )
152
+ print(
153
+ f" ❌ Отсутствующие права: {validation_result.missing_permissions}"
154
+ )
155
+ except Exception as e:
156
+ print(f" {action}: ❌ ОШИБКА - {e}")
157
+ print("\n📋 7. ТЕСТИРОВАНИЕ ПОЛНОЙ ЦЕПОЧКИ")
158
+ print("-" * 30)
159
+ # Test complete request validation
160
+ for role, token in test_tokens.items():
161
+ print(f"\n🔄 Полная цепочка для роли '{role}'")
162
+ request_data = {
163
+ "api_key": token,
164
+ "required_permissions": ["write"],
165
+ "client_ip": "127.0.0.1",
166
+ }
167
+ try:
168
+ result = security_manager.validate_request(request_data)
169
+ status = "✅ УСПЕШНО" if result.is_valid else "❌ ЗАБЛОКИРОВАНО"
170
+ print(f" Результат: {status}")
171
+ if not result.is_valid:
172
+ print(f" 📝 Причина: {result.error_message}")
173
+ except Exception as e:
174
+ print(f" ❌ ОШИБКА: {e}")
175
+ print("\n📋 8. АНАЛИЗ ПРОБЛЕМЫ")
176
+ print("-" * 30)
177
+ print("🔍 ПРОБЛЕМА: Readonly роль получает доступ к write операциям")
178
+ print("\n📋 ВОЗМОЖНЫЕ ПРИЧИНЫ:")
179
+ print("1. Middleware не передает информацию о пользователе в request.state")
180
+ print("2. Framework middleware не блокирует доступ на уровне middleware")
181
+ print("3. Команда role_test не получает правильный контекст пользователя")
182
+ print("4. Интеграция между middleware и командами не работает")
183
+ print("\n📋 РЕКОМЕНДАЦИИ:")
184
+ print("1. Проверить, как framework middleware устанавливает user info")
185
+ print("2. Добавить проверку прав на уровне middleware")
186
+ print("3. Убедиться, что request.state содержит user info")
187
+ print("4. Проверить интеграцию между middleware и командами")
188
+
189
+
190
+ if __name__ == "__main__":
191
+ asyncio.run(debug_role_chain())
@@ -0,0 +1,287 @@
1
+ """
2
+ Demo Client Script
3
+ This script demonstrates how to use the UniversalClient with different
4
+ authentication methods and connection types.
5
+ Author: Vasiliy Zdanovskiy
6
+ email: vasilyvz@gmail.com
7
+ """
8
+
9
+ import asyncio
10
+ import json
11
+ import sys
12
+ from pathlib import Path
13
+
14
+ # Add project root to path
15
+ sys.path.insert(0, str(Path(__file__).parent.parent))
16
+ from examples.universal_client import UniversalClient, create_client_config
17
+
18
+
19
+ async def demo_from_config_file(config_file: str):
20
+ """
21
+ Demo client using configuration from file.
22
+ Args:
23
+ config_file: Path to configuration file
24
+ """
25
+ print(f"🚀 Demo from config file: {config_file}")
26
+ print("=" * 50)
27
+ try:
28
+ # Load configuration
29
+ with open(config_file, "r") as f:
30
+ config = json.load(f)
31
+ print(
32
+ f"Configuration loaded: {config.get('security', {}).get('auth_method', 'none')} auth"
33
+ )
34
+ # Create and use client
35
+ async with UniversalClient(config) as client:
36
+ # Test connection
37
+ success = await client.test_connection()
38
+ if success:
39
+ print("✅ Connection successful!")
40
+ # Test security features
41
+ security_results = await client.test_security_features()
42
+ print("\nSecurity Features:")
43
+ for feature, status in security_results.items():
44
+ status_icon = "✅" if status else "❌"
45
+ print(f" {status_icon} {feature}: {status}")
46
+ # Make API calls
47
+ await demo_api_calls(client)
48
+ else:
49
+ print("❌ Connection failed")
50
+ except FileNotFoundError:
51
+ print(f"❌ Configuration file not found: {config_file}")
52
+ except json.JSONDecodeError:
53
+ print(f"❌ Invalid JSON in configuration file: {config_file}")
54
+ except Exception as e:
55
+ print(f"❌ Demo failed: {e}")
56
+
57
+
58
+ async def demo_api_calls(client: UniversalClient):
59
+ """Demonstrate various API calls."""
60
+ print("\n📡 API Calls Demo:")
61
+ print("-" * 30)
62
+ # Test health endpoint
63
+ try:
64
+ health = await client.get("/health")
65
+ print(f"Health: {health}")
66
+ except Exception as e:
67
+ print(f"Health check failed: {e}")
68
+ # Test status endpoint
69
+ try:
70
+ status = await client.get("/api/status")
71
+ print(f"Status: {status}")
72
+ except Exception as e:
73
+ print(f"Status check failed: {e}")
74
+ # Test JSON-RPC command
75
+ try:
76
+ command_data = {
77
+ "jsonrpc": "2.0",
78
+ "method": "test_command",
79
+ "params": {
80
+ "message": "Hello from universal client!",
81
+ "timestamp": "2024-01-01T00:00:00Z",
82
+ },
83
+ "id": 1,
84
+ }
85
+ result = await client.post("/api/jsonrpc", command_data)
86
+ print(f"Command Result: {result}")
87
+ except Exception as e:
88
+ print(f"Command execution failed: {e}")
89
+ # Test security command if available
90
+ try:
91
+ security_data = {
92
+ "jsonrpc": "2.0",
93
+ "method": "security_command",
94
+ "params": {"action": "get_status", "include_certificates": True},
95
+ "id": 2,
96
+ }
97
+ result = await client.post("/api/jsonrpc", security_data)
98
+ print(f"Security Status: {result}")
99
+ except Exception as e:
100
+ print(f"Security command failed: {e}")
101
+
102
+
103
+ async def demo_all_configs():
104
+ """Demo all available client configurations."""
105
+ print("🚀 Demo All Client Configurations")
106
+ print("=" * 50)
107
+ config_dir = Path(__file__).parent / "client_configs"
108
+ if not config_dir.exists():
109
+ print(f"❌ Config directory not found: {config_dir}")
110
+ return
111
+ config_files = list(config_dir.glob("*.json"))
112
+ if not config_files:
113
+ print(f"❌ No configuration files found in {config_dir}")
114
+ return
115
+ print(f"Found {len(config_files)} configuration files:")
116
+ for config_file in config_files:
117
+ print(f" - {config_file.name}")
118
+ print("\n" + "=" * 50)
119
+ for config_file in config_files:
120
+ await demo_from_config_file(str(config_file))
121
+ print("\n" + "-" * 50)
122
+
123
+
124
+ async def demo_programmatic_config():
125
+ """Demo client with programmatically created configuration."""
126
+ print("🚀 Demo Programmatic Configuration")
127
+ print("=" * 50)
128
+ # Create different configurations programmatically
129
+ configs = [
130
+ {
131
+ "name": "API Key Client",
132
+ "config": create_client_config(
133
+ "http://localhost:8000", "api_key", api_key="demo_api_key_123"
134
+ ),
135
+ },
136
+ {
137
+ "name": "JWT Client",
138
+ "config": create_client_config(
139
+ "http://localhost:8000",
140
+ "jwt",
141
+ username="demo_user",
142
+ password="demo_password",
143
+ secret="demo_jwt_secret",
144
+ ),
145
+ },
146
+ {
147
+ "name": "Certificate Client",
148
+ "config": create_client_config(
149
+ "https://localhost:8443",
150
+ "certificate",
151
+ cert_file="./certs/client.crt",
152
+ key_file="./keys/client.key",
153
+ ca_cert_file="./certs/ca.crt",
154
+ ),
155
+ },
156
+ {
157
+ "name": "Basic Auth Client",
158
+ "config": create_client_config(
159
+ "http://localhost:8000",
160
+ "basic",
161
+ username="demo_user",
162
+ password="demo_password",
163
+ ),
164
+ },
165
+ ]
166
+ for config_info in configs:
167
+ print(f"\n📋 Testing: {config_info['name']}")
168
+ print("-" * 30)
169
+ try:
170
+ async with UniversalClient(config_info["config"]) as client:
171
+ success = await client.test_connection()
172
+ if success:
173
+ print("✅ Connection successful!")
174
+ await demo_api_calls(client)
175
+ else:
176
+ print("❌ Connection failed")
177
+ except Exception as e:
178
+ print(f"❌ Test failed: {e}")
179
+
180
+
181
+ async def interactive_demo():
182
+ """Interactive demo with user input."""
183
+ print("🚀 Interactive Client Demo")
184
+ print("=" * 50)
185
+ print("Available authentication methods:")
186
+ print("1. No authentication")
187
+ print("2. API Key")
188
+ print("3. JWT Token")
189
+ print("4. Certificate")
190
+ print("5. Basic Authentication")
191
+ try:
192
+ choice = input("\nSelect authentication method (1-5): ").strip()
193
+ auth_methods = {
194
+ "1": "none",
195
+ "2": "api_key",
196
+ "3": "jwt",
197
+ "4": "certificate",
198
+ "5": "basic",
199
+ }
200
+ if choice not in auth_methods:
201
+ print("❌ Invalid choice")
202
+ return
203
+ auth_method = auth_methods[choice]
204
+ # Get server URL
205
+ server_url = input(
206
+ "Enter server URL (default: http://localhost:8000): "
207
+ ).strip()
208
+ if not server_url:
209
+ server_url = "http://localhost:8000"
210
+ # Create configuration based on choice
211
+ config_kwargs = {}
212
+ if auth_method == "api_key":
213
+ api_key = input("Enter API key: ").strip()
214
+ if api_key:
215
+ config_kwargs["api_key"] = api_key
216
+ elif auth_method == "jwt":
217
+ username = input("Enter username: ").strip()
218
+ password = input("Enter password: ").strip()
219
+ secret = input("Enter JWT secret: ").strip()
220
+ if username and password and secret:
221
+ config_kwargs.update(
222
+ {"username": username, "password": password, "secret": secret}
223
+ )
224
+ elif auth_method == "certificate":
225
+ cert_file = input("Enter certificate file path: ").strip()
226
+ key_file = input("Enter key file path: ").strip()
227
+ ca_cert_file = input("Enter CA certificate file path: ").strip()
228
+ if cert_file and key_file:
229
+ config_kwargs.update(
230
+ {
231
+ "cert_file": cert_file,
232
+ "key_file": key_file,
233
+ "ca_cert_file": ca_cert_file,
234
+ }
235
+ )
236
+ elif auth_method == "basic":
237
+ username = input("Enter username: ").strip()
238
+ password = input("Enter password: ").strip()
239
+ if username and password:
240
+ config_kwargs.update({"username": username, "password": password})
241
+ # Create configuration
242
+ config = create_client_config(server_url, auth_method, **config_kwargs)
243
+ print(f"\nConfiguration created for {auth_method} authentication")
244
+ print(f"Server URL: {server_url}")
245
+ # Test connection
246
+ async with UniversalClient(config) as client:
247
+ success = await client.test_connection()
248
+ if success:
249
+ print("✅ Connection successful!")
250
+ await demo_api_calls(client)
251
+ else:
252
+ print("❌ Connection failed")
253
+ except KeyboardInterrupt:
254
+ print("\n\nDemo interrupted by user")
255
+ except Exception as e:
256
+ print(f"❌ Interactive demo failed: {e}")
257
+
258
+
259
+ def main():
260
+ """Main demo function."""
261
+ if len(sys.argv) > 1:
262
+ command = sys.argv[1]
263
+ if command == "config":
264
+ if len(sys.argv) > 2:
265
+ config_file = sys.argv[2]
266
+ asyncio.run(demo_from_config_file(config_file))
267
+ else:
268
+ print("Usage: python demo_client.py config <config_file>")
269
+ elif command == "all":
270
+ asyncio.run(demo_all_configs())
271
+ elif command == "programmatic":
272
+ asyncio.run(demo_programmatic_config())
273
+ elif command == "interactive":
274
+ asyncio.run(interactive_demo())
275
+ else:
276
+ print("Unknown command. Available commands:")
277
+ print(" config <file> - Demo with config file")
278
+ print(" all - Demo all config files")
279
+ print(" programmatic - Demo programmatic configs")
280
+ print(" interactive - Interactive demo")
281
+ else:
282
+ # Default: demo all configs
283
+ asyncio.run(demo_all_configs())
284
+
285
+
286
+ if __name__ == "__main__":
287
+ main()
@@ -0,0 +1,12 @@
1
+ """Full Application Example.
2
+
3
+ This example demonstrates advanced usage of MCP Proxy Adapter including:
4
+ - Proxy registration endpoints
5
+ - Custom command hooks
6
+ - Advanced security configurations
7
+ - Role-based access control
8
+ """
9
+
10
+ # Note: main.py doesn't export get_app, it's a standalone script
11
+ # Import proxy router for use in other modules if needed
12
+ from .proxy_endpoints import router as proxy_router
@@ -0,0 +1,8 @@
1
+ """
2
+ Commands package for full application example.
3
+ """
4
+ from .echo_command import EchoCommand
5
+ from .list_command import ListCommand
6
+ from .help_command import HelpCommand
7
+
8
+ __all__ = ["EchoCommand", "ListCommand", "HelpCommand"]
@@ -0,0 +1,45 @@
1
+ """
2
+ Custom Echo Command
3
+ This module demonstrates a custom command implementation for the full application example.
4
+ Author: Vasiliy Zdanovskiy
5
+ email: vasilyvz@gmail.com
6
+ """
7
+
8
+ from mcp_proxy_adapter.commands.base import BaseCommand
9
+ from mcp_proxy_adapter.commands.result import CommandResult
10
+
11
+
12
+ class CustomEchoResult(CommandResult):
13
+ """Result class for custom echo command."""
14
+
15
+ def __init__(self, message: str, timestamp: str, echo_count: int):
16
+ self.message = message
17
+ self.timestamp = timestamp
18
+ self.echo_count = echo_count
19
+
20
+
21
+
22
+
23
+ class CustomEchoCommand(BaseCommand):
24
+ """Custom echo command implementation."""
25
+
26
+ def __init__(self):
27
+ super().__init__()
28
+ self.echo_count = 0
29
+
30
+
31
+
32
+
33
+ async def execute(self, params: Dict[str, Any]) -> CustomEchoResult:
34
+ """Execute the custom echo command."""
35
+ message = params.get("message", "Hello from custom echo!")
36
+ repeat = min(max(params.get("repeat", 1), 1), 10)
37
+ self.echo_count += 1
38
+ from datetime import datetime
39
+
40
+ timestamp = datetime.now().isoformat()
41
+ # Repeat the message
42
+ echoed_message = " ".join([message] * repeat)
43
+ return CustomEchoResult(
44
+ message=echoed_message, timestamp=timestamp, echo_count=self.echo_count
45
+ )