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,211 +0,0 @@
1
- """
2
- Unit tests for config command.
3
- """
4
-
5
- import json
6
- import os
7
- import tempfile
8
- from typing import Generator
9
-
10
- import pytest
11
-
12
- from mcp_proxy_adapter.commands.config_command import ConfigCommand, ConfigResult
13
- from mcp_proxy_adapter.config import Config
14
-
15
-
16
- @pytest.fixture
17
- def temp_config_file() -> Generator[str, None, None]:
18
- """
19
- Creates temporary configuration file for tests.
20
-
21
- Returns:
22
- Path to temporary configuration file.
23
- """
24
- # Create temporary file
25
- fd, path = tempfile.mkstemp(suffix=".json")
26
-
27
- # Write test configuration
28
- test_config = {
29
- "server": {
30
- "host": "127.0.0.1",
31
- "port": 8000
32
- },
33
- "logging": {
34
- "level": "DEBUG",
35
- "file": "test.log"
36
- },
37
- "test_section": {
38
- "test_key": "test_value",
39
- "nested": {
40
- "key1": "value1",
41
- "key2": 42
42
- }
43
- }
44
- }
45
-
46
- with os.fdopen(fd, "w") as f:
47
- json.dump(test_config, f)
48
-
49
- yield path
50
-
51
- # Remove temporary file after tests
52
- os.unlink(path)
53
-
54
-
55
- @pytest.mark.unit
56
- async def test_config_command_get_all(temp_config_file: str):
57
- """
58
- Test getting all configuration values.
59
-
60
- Args:
61
- temp_config_file: Path to temporary configuration file.
62
- """
63
- # Create config instance with test file
64
- config_instance = Config(temp_config_file)
65
-
66
- # Create command with this config
67
- command = ConfigCommand()
68
-
69
- # Override the config instance used in the command
70
- from mcp_proxy_adapter.commands import config_command
71
- original_config = config_command.config_instance
72
- config_command.config_instance = config_instance
73
-
74
- try:
75
- # Execute command with get operation and no path
76
- result = await command.execute(operation="get")
77
-
78
- # Check result
79
- assert isinstance(result, ConfigResult)
80
- result_dict = result.to_dict()
81
- assert result_dict["success"] is True
82
- assert "data" in result_dict
83
- assert "config" in result_dict["data"]
84
- assert "operation" in result_dict["data"]
85
- assert result_dict["data"]["operation"] == "get"
86
-
87
- # Check all config values are present
88
- config_data = result_dict["data"]["config"]
89
- assert "server" in config_data
90
- assert "logging" in config_data
91
- assert "test_section" in config_data
92
-
93
- assert config_data["server"]["host"] == "127.0.0.1"
94
- assert config_data["logging"]["level"] == "DEBUG"
95
- assert config_data["test_section"]["test_key"] == "test_value"
96
- finally:
97
- # Restore original config instance
98
- config_command.config_instance = original_config
99
-
100
-
101
- @pytest.mark.unit
102
- async def test_config_command_get_specific(temp_config_file: str):
103
- """
104
- Test getting specific configuration value.
105
-
106
- Args:
107
- temp_config_file: Path to temporary configuration file.
108
- """
109
- # Create config instance with test file
110
- config_instance = Config(temp_config_file)
111
-
112
- # Create command with this config
113
- command = ConfigCommand()
114
-
115
- # Override the config instance used in the command
116
- from mcp_proxy_adapter.commands import config_command
117
- original_config = config_command.config_instance
118
- config_command.config_instance = config_instance
119
-
120
- try:
121
- # Execute command with get operation and specific path
122
- result = await command.execute(operation="get", path="server.host")
123
-
124
- # Check result
125
- assert isinstance(result, ConfigResult)
126
- result_dict = result.to_dict()
127
- assert result_dict["success"] is True
128
- assert "data" in result_dict
129
- assert "config" in result_dict["data"]
130
- assert "operation" in result_dict["data"]
131
- assert result_dict["data"]["operation"] == "get"
132
-
133
- # Check specific config value
134
- config_data = result_dict["data"]["config"]
135
- assert "server.host" in config_data
136
- assert config_data["server.host"] == "127.0.0.1"
137
- finally:
138
- # Restore original config instance
139
- config_command.config_instance = original_config
140
-
141
-
142
- @pytest.mark.unit
143
- async def test_config_command_set_value(temp_config_file: str):
144
- """
145
- Test setting configuration value.
146
-
147
- Args:
148
- temp_config_file: Path to temporary configuration file.
149
- """
150
- # Create config instance with test file
151
- config_instance = Config(temp_config_file)
152
-
153
- # Create command with this config
154
- command = ConfigCommand()
155
-
156
- # Override the config instance used in the command
157
- from mcp_proxy_adapter.commands import config_command
158
- original_config = config_command.config_instance
159
- config_command.config_instance = config_instance
160
-
161
- try:
162
- # Execute command with set operation
163
- result = await command.execute(
164
- operation="set",
165
- path="server.host",
166
- value="localhost"
167
- )
168
-
169
- # Check result
170
- assert isinstance(result, ConfigResult)
171
- result_dict = result.to_dict()
172
- assert result_dict["success"] is True
173
- assert "data" in result_dict
174
- assert "config" in result_dict["data"]
175
- assert "operation" in result_dict["data"]
176
- assert result_dict["data"]["operation"] == "set"
177
-
178
- # Check updated config value
179
- config_data = result_dict["data"]["config"]
180
- assert "server.host" in config_data
181
- assert config_data["server.host"] == "localhost"
182
-
183
- # Check that value was updated in config instance
184
- assert config_instance.get("server.host") == "localhost"
185
- finally:
186
- # Restore original config instance
187
- config_command.config_instance = original_config
188
-
189
-
190
- @pytest.mark.unit
191
- async def test_config_command_validate_schema():
192
- """
193
- Test validation schema for config command.
194
- """
195
- command = ConfigCommand()
196
- schema = command.get_schema()
197
-
198
- # Check schema structure
199
- assert schema["type"] == "object"
200
- assert "properties" in schema
201
- assert "operation" in schema["properties"]
202
- assert "path" in schema["properties"]
203
- assert "value" in schema["properties"]
204
-
205
- # Check operation property
206
- operation_prop = schema["properties"]["operation"]
207
- assert operation_prop["type"] == "string"
208
- assert "enum" in operation_prop
209
- assert "get" in operation_prop["enum"]
210
- assert "set" in operation_prop["enum"]
211
- assert operation_prop["default"] == "get"
@@ -1,127 +0,0 @@
1
- """
2
- Tests for the echo command.
3
- """
4
-
5
- import pytest
6
- import asyncio
7
- from typing import Dict, Any
8
- import json
9
-
10
- from mcp_proxy_adapter.tests.stubs.echo_command import EchoCommand
11
- from mcp_proxy_adapter.tests.stubs.echo_command import EchoResult
12
-
13
-
14
- @pytest.mark.unit
15
- def test_echo_command_execution():
16
- """
17
- Test execution of echo command.
18
- """
19
- # Create test parameters
20
- test_params = {
21
- "string_param": "test_value",
22
- "int_param": 42,
23
- "bool_param": True,
24
- "complex_param": {"nested": "value", "array": [1, 2, 3]}
25
- }
26
-
27
- # Create and execute command
28
- command = EchoCommand()
29
- result = asyncio.run(command.execute(**test_params))
30
-
31
- # Check result type
32
- assert isinstance(result, EchoResult)
33
-
34
- # Check result content
35
- assert result.params == test_params
36
- assert result.params["string_param"] == "test_value"
37
- assert result.params["int_param"] == 42
38
- assert result.params["bool_param"] is True
39
- assert result.params["complex_param"]["nested"] == "value"
40
- assert result.params["complex_param"]["array"] == [1, 2, 3]
41
-
42
-
43
- @pytest.mark.unit
44
- def test_echo_result_serialization():
45
- """
46
- Test serialization of echo result.
47
- """
48
- # Create test parameters
49
- test_params = {
50
- "string_param": "test_value",
51
- "int_param": 42,
52
- "bool_param": True,
53
- "complex_param": {"nested": "value", "array": [1, 2, 3]}
54
- }
55
-
56
- # Create result
57
- result = EchoResult(params=test_params)
58
-
59
- # Test to_dict method
60
- result_dict = result.to_dict()
61
- assert isinstance(result_dict, dict)
62
- assert "params" in result_dict
63
- assert result_dict["params"] == test_params
64
-
65
- # Test that result can be properly serialized to JSON
66
- json_str = json.dumps(result_dict)
67
- parsed_json = json.loads(json_str)
68
- assert parsed_json == result_dict
69
-
70
-
71
- @pytest.mark.unit
72
- def test_echo_command_schema():
73
- """
74
- Test command schema generation.
75
- """
76
- # Get schema
77
- schema = EchoCommand.get_schema()
78
-
79
- # Check schema structure
80
- assert isinstance(schema, dict)
81
- assert "type" in schema and schema["type"] == "object"
82
- assert "additionalProperties" in schema and schema["additionalProperties"] is True
83
- assert "description" in schema
84
-
85
-
86
- @pytest.mark.unit
87
- def test_echo_result_schema():
88
- """
89
- Test result schema generation.
90
- """
91
- # Get schema
92
- schema = EchoResult.get_schema()
93
-
94
- # Check schema structure
95
- assert isinstance(schema, dict)
96
- assert "type" in schema and schema["type"] == "object"
97
- assert "properties" in schema
98
- assert "params" in schema["properties"]
99
- assert "required" in schema and "params" in schema["required"]
100
- assert schema["properties"]["params"]["type"] == "object"
101
- assert schema["properties"]["params"]["additionalProperties"] is True
102
-
103
-
104
- @pytest.mark.unit
105
- def test_echo_result_from_dict():
106
- """
107
- Test creating result from dictionary.
108
- """
109
- # Create test data
110
- test_data = {
111
- "params": {
112
- "key1": "value1",
113
- "key2": 42
114
- }
115
- }
116
-
117
- # Create result from dict
118
- result = EchoResult.from_dict(test_data)
119
-
120
- # Check result
121
- assert isinstance(result, EchoResult)
122
- assert result.params == test_data["params"]
123
-
124
- # Test with empty params
125
- empty_result = EchoResult.from_dict({})
126
- assert isinstance(empty_result, EchoResult)
127
- assert empty_result.params == {}
@@ -1,136 +0,0 @@
1
- """
2
- Tests for the help command.
3
- """
4
-
5
- import pytest
6
- from unittest.mock import patch, MagicMock
7
-
8
- from mcp_proxy_adapter.commands.help_command import HelpCommand, HelpResult
9
- from mcp_proxy_adapter.core.errors import NotFoundError
10
-
11
-
12
- @pytest.fixture
13
- def mock_registry():
14
- """Mock for command registry."""
15
- with patch("mcp_proxy_adapter.commands.help_command.registry") as mock_reg:
16
- yield mock_reg
17
-
18
-
19
- async def test_help_command_without_params(mock_registry):
20
- """Test help command without parameters."""
21
- # Setup mocks
22
- mock_registry.get_all_metadata.return_value = {
23
- "help": {
24
- "name": "help",
25
- "summary": "Get help information",
26
- "description": "Get help information",
27
- "params": {},
28
- "examples": []
29
- },
30
- "health": {
31
- "name": "health",
32
- "summary": "Check server health",
33
- "description": "Check server health",
34
- "params": {},
35
- "examples": []
36
- }
37
- }
38
-
39
- # Execute command
40
- command = HelpCommand()
41
- result = await command.execute()
42
-
43
- # Check result
44
- assert isinstance(result, HelpResult)
45
- assert result.commands_info is not None
46
- assert result.command_info is None
47
-
48
- # Check content
49
- commands_dict = result.to_dict()
50
- assert "commands" in commands_dict
51
- assert "help" in commands_dict["commands"]
52
- assert "health" in commands_dict["commands"]
53
- assert "summary" in commands_dict["commands"]["help"]
54
- assert "Get help information" in commands_dict["commands"]["help"]["summary"]
55
-
56
-
57
- async def test_help_command_with_cmdname(mock_registry):
58
- """Test help command with cmdname parameter."""
59
- # Setup mocks
60
- mock_registry.get_command_metadata.return_value = {
61
- "name": "health",
62
- "description": "Check server health",
63
- "summary": "Check server health",
64
- "params": {
65
- "check_type": {
66
- "type": "string",
67
- "description": "Type of health check",
68
- "required": False,
69
- "default": "basic"
70
- }
71
- },
72
- "examples": []
73
- }
74
-
75
- # Execute command
76
- command = HelpCommand()
77
- result = await command.execute(cmdname="health")
78
-
79
- # Check result
80
- assert isinstance(result, HelpResult)
81
- assert result.commands_info is None
82
- assert result.command_info is not None
83
-
84
- # Check content
85
- command_dict = result.to_dict()
86
- assert "cmdname" in command_dict
87
- assert command_dict["cmdname"] == "health"
88
- assert "info" in command_dict
89
- assert "description" in command_dict["info"]
90
- assert "Check server health" in command_dict["info"]["description"]
91
- assert "params" in command_dict["info"]
92
- assert "check_type" in command_dict["info"]["params"]
93
-
94
-
95
- async def test_help_command_with_invalid_cmdname(mock_registry):
96
- """Test help command with invalid cmdname parameter."""
97
- # Setup mocks
98
- mock_registry.get_command_metadata.side_effect = NotFoundError("Command not found")
99
-
100
- # Execute command and check result fields
101
- command = HelpCommand()
102
- result = await command.execute(cmdname="non_existent")
103
- result_dict = result.to_dict()
104
- assert "error" in result_dict
105
- assert "example" in result_dict
106
- assert "note" in result_dict
107
- assert result_dict["error"].startswith("Command")
108
- assert result_dict["example"]["command"] == "help"
109
-
110
-
111
- def test_help_result_schema():
112
- """Test help command result schema."""
113
- schema = HelpResult.get_schema()
114
-
115
- assert schema["type"] == "object"
116
- assert "oneOf" in schema
117
- assert len(schema["oneOf"]) == 2
118
-
119
- commands_schema = schema["oneOf"][0]
120
- assert "properties" in commands_schema
121
- assert "commands" in commands_schema["properties"]
122
-
123
- command_schema = schema["oneOf"][1]
124
- assert "properties" in command_schema
125
- assert "cmdname" in command_schema["properties"]
126
- assert "info" in command_schema["properties"]
127
-
128
-
129
- def test_help_command_schema():
130
- """Test help command schema."""
131
- schema = HelpCommand.get_schema()
132
-
133
- assert schema["type"] == "object"
134
- assert "properties" in schema
135
- assert "cmdname" in schema["properties"]
136
- assert schema["properties"]["cmdname"]["type"] == "string"
@@ -1,131 +0,0 @@
1
- """
2
- Module with fixtures and configuration for tests.
3
- """
4
-
5
- import json
6
- import os
7
- import tempfile
8
- from typing import Any, Dict, Generator
9
-
10
- import pytest
11
- from fastapi.testclient import TestClient
12
-
13
- from mcp_proxy_adapter.api.app import create_app
14
- from mcp_proxy_adapter.commands.command_registry import registry
15
- from mcp_proxy_adapter.config import Config
16
-
17
-
18
- @pytest.fixture
19
- def temp_config_file() -> Generator[str, None, None]:
20
- """
21
- Creates temporary configuration file for tests.
22
-
23
- Returns:
24
- Path to temporary configuration file.
25
- """
26
- # Create temporary file
27
- fd, path = tempfile.mkstemp(suffix=".json")
28
-
29
- # Write test configuration
30
- test_config = {
31
- "server": {
32
- "host": "127.0.0.1",
33
- "port": 8888
34
- },
35
- "logging": {
36
- "level": "DEBUG",
37
- "file": None
38
- },
39
- # Отключаем аутентификацию и ограничение скорости для тестов
40
- "auth_enabled": False,
41
- "rate_limit_enabled": False
42
- }
43
-
44
- with os.fdopen(fd, "w") as f:
45
- json.dump(test_config, f)
46
-
47
- yield path
48
-
49
- # Remove temporary file after tests
50
- os.unlink(path)
51
-
52
-
53
- @pytest.fixture
54
- def test_config(temp_config_file: str) -> Config:
55
- """
56
- Creates test configuration instance.
57
-
58
- Args:
59
- temp_config_file: Path to temporary configuration file.
60
-
61
- Returns:
62
- Test configuration instance.
63
- """
64
- return Config(temp_config_file)
65
-
66
-
67
- @pytest.fixture
68
- def test_client() -> TestClient:
69
- """
70
- Creates test client for FastAPI application.
71
-
72
- Returns:
73
- FastAPI test client.
74
- """
75
- app = create_app()
76
- return TestClient(app)
77
-
78
-
79
- @pytest.fixture
80
- def clean_registry() -> Generator[None, None, None]:
81
- """
82
- Cleans command registry before test and restores it after.
83
-
84
- Yields:
85
- None
86
- """
87
- # Save current commands
88
- original_commands = dict(registry._commands)
89
-
90
- # Clear registry
91
- registry.clear()
92
-
93
- yield
94
-
95
- # Restore registry
96
- registry.clear()
97
- for name, command in original_commands.items():
98
- registry._commands[name] = command
99
-
100
-
101
- @pytest.fixture
102
- def json_rpc_request() -> Dict[str, Any]:
103
- """
104
- Creates base JSON-RPC request.
105
-
106
- Returns:
107
- Dictionary with JSON-RPC request data.
108
- """
109
- return {
110
- "jsonrpc": "2.0",
111
- "method": "test_command",
112
- "params": {},
113
- "id": "test-id"
114
- }
115
-
116
-
117
- @pytest.fixture(autouse=True)
118
- def register_test_commands():
119
- """
120
- Регистрирует тестовые команды в registry для всех тестов.
121
- """
122
- from mcp_proxy_adapter.tests.stubs.echo_command import EchoCommand
123
- from mcp_proxy_adapter.commands.command_registry import registry
124
-
125
- # Регистрируем команды для тестирования
126
- registry.register(EchoCommand)
127
-
128
- yield
129
-
130
- # Очищаем registry после тестов
131
- registry.clear()
@@ -1,3 +0,0 @@
1
- """
2
- Functional tests for the mcp_microservice package.
3
- """