mcp-proxy-adapter 6.0.0__py3-none-any.whl → 6.1.0__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 (259) 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 +7 -2
  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/unified_security.py +152 -0
  7. mcp_proxy_adapter/api/middleware/user_info_middleware.py +83 -0
  8. mcp_proxy_adapter/commands/__init__.py +7 -1
  9. mcp_proxy_adapter/commands/base.py +7 -4
  10. mcp_proxy_adapter/commands/builtin_commands.py +8 -2
  11. mcp_proxy_adapter/commands/command_registry.py +8 -0
  12. mcp_proxy_adapter/commands/echo_command.py +81 -0
  13. mcp_proxy_adapter/commands/help_command.py +21 -14
  14. mcp_proxy_adapter/commands/proxy_registration_command.py +326 -185
  15. mcp_proxy_adapter/commands/role_test_command.py +141 -0
  16. mcp_proxy_adapter/commands/security_command.py +488 -0
  17. mcp_proxy_adapter/commands/ssl_setup_command.py +2 -2
  18. mcp_proxy_adapter/commands/token_management_command.py +1 -1
  19. mcp_proxy_adapter/config.py +81 -21
  20. mcp_proxy_adapter/core/app_factory.py +326 -0
  21. mcp_proxy_adapter/core/client_security.py +384 -0
  22. mcp_proxy_adapter/core/logging.py +8 -3
  23. mcp_proxy_adapter/core/mtls_asgi.py +156 -0
  24. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  25. mcp_proxy_adapter/core/protocol_manager.py +9 -0
  26. mcp_proxy_adapter/core/proxy_client.py +602 -0
  27. mcp_proxy_adapter/core/proxy_registration.py +299 -47
  28. mcp_proxy_adapter/core/security_adapter.py +12 -15
  29. mcp_proxy_adapter/core/security_integration.py +277 -0
  30. mcp_proxy_adapter/core/server_adapter.py +345 -0
  31. mcp_proxy_adapter/core/server_engine.py +364 -0
  32. mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
  33. mcp_proxy_adapter/examples/README.md +230 -97
  34. mcp_proxy_adapter/examples/README_EN.md +258 -0
  35. mcp_proxy_adapter/examples/SECURITY_TESTING.md +455 -0
  36. mcp_proxy_adapter/examples/__pycache__/security_configurations.cpython-312.pyc +0 -0
  37. mcp_proxy_adapter/examples/__pycache__/security_test_client.cpython-312.pyc +0 -0
  38. mcp_proxy_adapter/examples/basic_framework/configs/http_auth.json +37 -0
  39. mcp_proxy_adapter/examples/basic_framework/configs/http_simple.json +23 -0
  40. mcp_proxy_adapter/examples/basic_framework/configs/https_auth.json +39 -0
  41. mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +25 -0
  42. mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +39 -0
  43. mcp_proxy_adapter/examples/basic_framework/configs/mtls_with_roles.json +45 -0
  44. mcp_proxy_adapter/examples/basic_framework/main.py +63 -0
  45. mcp_proxy_adapter/examples/basic_framework/roles.json +21 -0
  46. mcp_proxy_adapter/examples/cert_config.json +9 -0
  47. mcp_proxy_adapter/examples/certs/admin.crt +32 -0
  48. mcp_proxy_adapter/examples/certs/admin.key +52 -0
  49. mcp_proxy_adapter/examples/certs/admin_cert.pem +21 -0
  50. mcp_proxy_adapter/examples/certs/admin_key.pem +28 -0
  51. mcp_proxy_adapter/examples/certs/ca_cert.pem +23 -0
  52. mcp_proxy_adapter/examples/certs/ca_cert.srl +1 -0
  53. mcp_proxy_adapter/examples/certs/ca_key.pem +28 -0
  54. mcp_proxy_adapter/examples/certs/cert_config.json +9 -0
  55. mcp_proxy_adapter/examples/certs/client.crt +32 -0
  56. mcp_proxy_adapter/examples/certs/client.key +52 -0
  57. mcp_proxy_adapter/examples/certs/client_admin.crt +32 -0
  58. mcp_proxy_adapter/examples/certs/client_admin.key +52 -0
  59. mcp_proxy_adapter/examples/certs/client_user.crt +32 -0
  60. mcp_proxy_adapter/examples/certs/client_user.key +52 -0
  61. mcp_proxy_adapter/examples/certs/guest_cert.pem +21 -0
  62. mcp_proxy_adapter/examples/certs/guest_key.pem +28 -0
  63. mcp_proxy_adapter/examples/certs/mcp_proxy_adapter_ca_ca.crt +23 -0
  64. mcp_proxy_adapter/examples/certs/proxy_cert.pem +21 -0
  65. mcp_proxy_adapter/examples/certs/proxy_key.pem +28 -0
  66. mcp_proxy_adapter/examples/certs/readonly.crt +32 -0
  67. mcp_proxy_adapter/examples/certs/readonly.key +52 -0
  68. mcp_proxy_adapter/examples/certs/readonly_cert.pem +21 -0
  69. mcp_proxy_adapter/examples/certs/readonly_key.pem +28 -0
  70. mcp_proxy_adapter/examples/certs/server.crt +32 -0
  71. mcp_proxy_adapter/examples/certs/server.key +52 -0
  72. mcp_proxy_adapter/examples/certs/server_cert.pem +32 -0
  73. mcp_proxy_adapter/examples/certs/server_key.pem +52 -0
  74. mcp_proxy_adapter/examples/certs/test_ca_ca.crt +20 -0
  75. mcp_proxy_adapter/examples/certs/user.crt +32 -0
  76. mcp_proxy_adapter/examples/certs/user.key +52 -0
  77. mcp_proxy_adapter/examples/certs/user_cert.pem +21 -0
  78. mcp_proxy_adapter/examples/certs/user_key.pem +28 -0
  79. mcp_proxy_adapter/examples/client_configs/api_key_client.json +13 -0
  80. mcp_proxy_adapter/examples/client_configs/basic_auth_client.json +13 -0
  81. mcp_proxy_adapter/examples/client_configs/certificate_client.json +22 -0
  82. mcp_proxy_adapter/examples/client_configs/jwt_client.json +15 -0
  83. mcp_proxy_adapter/examples/client_configs/no_auth_client.json +9 -0
  84. mcp_proxy_adapter/examples/commands/__init__.py +1 -0
  85. mcp_proxy_adapter/examples/create_certificates_simple.py +307 -0
  86. mcp_proxy_adapter/examples/debug_request_state.py +144 -0
  87. mcp_proxy_adapter/examples/debug_role_chain.py +205 -0
  88. mcp_proxy_adapter/examples/demo_client.py +341 -0
  89. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +99 -0
  90. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +106 -0
  91. mcp_proxy_adapter/examples/full_application/configs/http_auth.json +37 -0
  92. mcp_proxy_adapter/examples/full_application/configs/http_simple.json +23 -0
  93. mcp_proxy_adapter/examples/full_application/configs/https_auth.json +39 -0
  94. mcp_proxy_adapter/examples/full_application/configs/https_simple.json +25 -0
  95. mcp_proxy_adapter/examples/full_application/configs/mtls_no_roles.json +39 -0
  96. mcp_proxy_adapter/examples/full_application/configs/mtls_with_roles.json +45 -0
  97. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +97 -0
  98. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +95 -0
  99. mcp_proxy_adapter/examples/full_application/main.py +138 -0
  100. mcp_proxy_adapter/examples/full_application/roles.json +21 -0
  101. mcp_proxy_adapter/examples/generate_all_certificates.py +429 -0
  102. mcp_proxy_adapter/examples/generate_certificates.py +121 -0
  103. mcp_proxy_adapter/examples/keys/ca_key.pem +28 -0
  104. mcp_proxy_adapter/examples/keys/mcp_proxy_adapter_ca_ca.key +28 -0
  105. mcp_proxy_adapter/examples/keys/test_ca_ca.key +28 -0
  106. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log +220 -0
  107. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.1 +1 -0
  108. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.2 +1 -0
  109. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.3 +1 -0
  110. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.4 +1 -0
  111. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.5 +1 -0
  112. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log +220 -0
  113. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.1 +1 -0
  114. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.2 +1 -0
  115. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.3 +1 -0
  116. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.4 +1 -0
  117. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.5 +1 -0
  118. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log +2 -0
  119. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.1 +1 -0
  120. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.2 +1 -0
  121. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.3 +1 -0
  122. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.4 +1 -0
  123. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.5 +1 -0
  124. mcp_proxy_adapter/examples/proxy_registration_example.py +401 -0
  125. mcp_proxy_adapter/examples/roles.json +38 -0
  126. mcp_proxy_adapter/examples/run_example.py +81 -0
  127. mcp_proxy_adapter/examples/run_security_tests.py +326 -0
  128. mcp_proxy_adapter/examples/run_security_tests_fixed.py +300 -0
  129. mcp_proxy_adapter/examples/security_test_client.py +743 -0
  130. mcp_proxy_adapter/examples/server_configs/config_basic_http.json +204 -0
  131. mcp_proxy_adapter/examples/server_configs/config_http_token.json +238 -0
  132. mcp_proxy_adapter/examples/server_configs/config_https.json +215 -0
  133. mcp_proxy_adapter/examples/server_configs/config_https_token.json +231 -0
  134. mcp_proxy_adapter/examples/server_configs/config_mtls.json +215 -0
  135. mcp_proxy_adapter/examples/server_configs/config_proxy_registration.json +250 -0
  136. mcp_proxy_adapter/examples/server_configs/config_simple.json +46 -0
  137. mcp_proxy_adapter/examples/server_configs/roles.json +38 -0
  138. mcp_proxy_adapter/examples/test_examples.py +344 -0
  139. mcp_proxy_adapter/examples/universal_client.py +628 -0
  140. mcp_proxy_adapter/main.py +21 -10
  141. mcp_proxy_adapter/utils/config_generator.py +639 -0
  142. mcp_proxy_adapter/version.py +2 -1
  143. mcp_proxy_adapter-6.1.0.dist-info/METADATA +205 -0
  144. mcp_proxy_adapter-6.1.0.dist-info/RECORD +193 -0
  145. mcp_proxy_adapter-6.1.0.dist-info/entry_points.txt +2 -0
  146. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.0.dist-info}/licenses/LICENSE +2 -2
  147. mcp_proxy_adapter/api/middleware/auth.py +0 -146
  148. mcp_proxy_adapter/api/middleware/auth_adapter.py +0 -235
  149. mcp_proxy_adapter/api/middleware/mtls_adapter.py +0 -305
  150. mcp_proxy_adapter/api/middleware/mtls_middleware.py +0 -296
  151. mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
  152. mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +0 -241
  153. mcp_proxy_adapter/api/middleware/roles_adapter.py +0 -365
  154. mcp_proxy_adapter/api/middleware/roles_middleware.py +0 -381
  155. mcp_proxy_adapter/api/middleware/security.py +0 -376
  156. mcp_proxy_adapter/api/middleware/token_auth_middleware.py +0 -261
  157. mcp_proxy_adapter/examples/__init__.py +0 -7
  158. mcp_proxy_adapter/examples/basic_server/README.md +0 -60
  159. mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
  160. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
  161. mcp_proxy_adapter/examples/basic_server/config.json +0 -70
  162. mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +0 -54
  163. mcp_proxy_adapter/examples/basic_server/config_http.json +0 -70
  164. mcp_proxy_adapter/examples/basic_server/config_http_only.json +0 -52
  165. mcp_proxy_adapter/examples/basic_server/config_https.json +0 -58
  166. mcp_proxy_adapter/examples/basic_server/config_mtls.json +0 -58
  167. mcp_proxy_adapter/examples/basic_server/config_ssl.json +0 -46
  168. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
  169. mcp_proxy_adapter/examples/basic_server/server.py +0 -114
  170. mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
  171. mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
  172. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -566
  173. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
  174. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
  175. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
  176. mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +0 -105
  177. mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +0 -129
  178. mcp_proxy_adapter/examples/custom_commands/config.json +0 -118
  179. mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +0 -46
  180. mcp_proxy_adapter/examples/custom_commands/config_https_only.json +0 -46
  181. mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +0 -33
  182. mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +0 -46
  183. mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +0 -33
  184. mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +0 -33
  185. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
  186. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
  187. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
  188. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
  189. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
  190. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
  191. mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
  192. mcp_proxy_adapter/examples/custom_commands/full_help_response.json +0 -1
  193. mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +0 -629
  194. mcp_proxy_adapter/examples/custom_commands/get_openapi.py +0 -103
  195. mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
  196. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
  197. mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +0 -129
  198. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
  199. mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +0 -278
  200. mcp_proxy_adapter/examples/custom_commands/server.py +0 -252
  201. mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +0 -75
  202. mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +0 -299
  203. mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +0 -278
  204. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
  205. mcp_proxy_adapter/examples/custom_commands/test_openapi.py +0 -27
  206. mcp_proxy_adapter/examples/custom_commands/test_registry.py +0 -23
  207. mcp_proxy_adapter/examples/custom_commands/test_simple.py +0 -19
  208. mcp_proxy_adapter/examples/custom_project_example/README.md +0 -103
  209. mcp_proxy_adapter/examples/custom_project_example/README_EN.md +0 -103
  210. mcp_proxy_adapter/examples/deployment/README.md +0 -49
  211. mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
  212. mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
  213. mcp_proxy_adapter/examples/deployment/config.json +0 -29
  214. mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
  215. mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
  216. mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
  217. mcp_proxy_adapter/examples/deployment/run.sh +0 -43
  218. mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
  219. mcp_proxy_adapter/examples/simple_custom_commands/README.md +0 -149
  220. mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +0 -149
  221. mcp_proxy_adapter/schemas/base_schema.json +0 -114
  222. mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
  223. mcp_proxy_adapter/schemas/roles_schema.json +0 -162
  224. mcp_proxy_adapter/tests/__init__.py +0 -0
  225. mcp_proxy_adapter/tests/api/__init__.py +0 -3
  226. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
  227. mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
  228. mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
  229. mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
  230. mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
  231. mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
  232. mcp_proxy_adapter/tests/commands/__init__.py +0 -3
  233. mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
  234. mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
  235. mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
  236. mcp_proxy_adapter/tests/conftest.py +0 -131
  237. mcp_proxy_adapter/tests/functional/__init__.py +0 -3
  238. mcp_proxy_adapter/tests/functional/test_api.py +0 -253
  239. mcp_proxy_adapter/tests/integration/__init__.py +0 -3
  240. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
  241. mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
  242. mcp_proxy_adapter/tests/performance/__init__.py +0 -3
  243. mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
  244. mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
  245. mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
  246. mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
  247. mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
  248. mcp_proxy_adapter/tests/test_base_command.py +0 -123
  249. mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
  250. mcp_proxy_adapter/tests/test_command_registry.py +0 -281
  251. mcp_proxy_adapter/tests/test_config.py +0 -127
  252. mcp_proxy_adapter/tests/test_utils.py +0 -65
  253. mcp_proxy_adapter/tests/unit/__init__.py +0 -3
  254. mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
  255. mcp_proxy_adapter/tests/unit/test_config.py +0 -270
  256. mcp_proxy_adapter-6.0.0.dist-info/METADATA +0 -201
  257. mcp_proxy_adapter-6.0.0.dist-info/RECORD +0 -179
  258. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.0.dist-info}/WHEEL +0 -0
  259. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.0.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
- """