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,281 +0,0 @@
1
- """
2
- Tests for command registry.
3
- """
4
-
5
- import pytest
6
- from unittest.mock import MagicMock, patch
7
-
8
- from mcp_proxy_adapter.commands.base import Command
9
- from mcp_proxy_adapter.commands.result import CommandResult
10
- from mcp_proxy_adapter.commands.command_registry import CommandRegistry
11
- from mcp_proxy_adapter.core.errors import NotFoundError
12
-
13
-
14
- class MockResult(CommandResult):
15
- """Test result class for testing."""
16
-
17
- def __init__(self):
18
- pass
19
-
20
- def to_dict(self):
21
- return {}
22
-
23
- @classmethod
24
- def get_schema(cls):
25
- return {}
26
-
27
-
28
- class TestCommand1(Command):
29
- """First test command."""
30
-
31
- name = "test_command1"
32
- result_class = MockResult
33
-
34
- async def execute(self, **kwargs):
35
- return MockResult()
36
-
37
-
38
- class TestCommand2(Command):
39
- """Second test command."""
40
-
41
- name = "test_command2"
42
- result_class = MockResult
43
-
44
- async def execute(self, **kwargs):
45
- return MockResult()
46
-
47
-
48
- def test_registry_initialization():
49
- """Test registry initialization."""
50
- registry = CommandRegistry()
51
- assert len(registry._commands) == 0
52
-
53
-
54
- def test_register_command():
55
- """Test registering command."""
56
- registry = CommandRegistry()
57
-
58
- # Register first command
59
- registry.register(TestCommand1)
60
- assert len(registry._commands) == 1
61
- assert "test_command1" in registry._commands
62
-
63
- # Register second command
64
- registry.register(TestCommand2)
65
- assert len(registry._commands) == 2
66
- assert "test_command2" in registry._commands
67
-
68
-
69
- def test_register_duplicated_command():
70
- """Test registering duplicated command."""
71
- registry = CommandRegistry()
72
-
73
- # Register command
74
- registry.register(TestCommand1)
75
-
76
- # Try to register again
77
- with pytest.raises(ValueError):
78
- registry.register(TestCommand1)
79
-
80
-
81
- def test_register_command_without_name():
82
- """Test registering command without name attribute."""
83
- registry = CommandRegistry()
84
-
85
- # Create command without name
86
- class CommandWithoutName(Command):
87
- result_class = MockResult
88
-
89
- async def execute(self, **kwargs):
90
- return MockResult()
91
-
92
- # Register command
93
- registry.register(CommandWithoutName)
94
-
95
- # Check if registered with class name
96
- assert "commandwithoutname" in registry._commands
97
-
98
-
99
- def test_unregister_command():
100
- """Test unregistering command."""
101
- registry = CommandRegistry()
102
-
103
- # Register command
104
- registry.register(TestCommand1)
105
- assert "test_command1" in registry._commands
106
-
107
- # Unregister command
108
- registry.unregister("test_command1")
109
- assert "test_command1" not in registry._commands
110
-
111
-
112
- def test_unregister_nonexistent_command():
113
- """Test unregistering nonexistent command."""
114
- registry = CommandRegistry()
115
-
116
- # Try to unregister nonexistent command
117
- with pytest.raises(NotFoundError):
118
- registry.unregister("nonexistent")
119
-
120
-
121
- def test_get_command():
122
- """Test getting command."""
123
- registry = CommandRegistry()
124
-
125
- # Register command
126
- registry.register(TestCommand1)
127
-
128
- # Get command
129
- command = registry.get_command("test_command1")
130
- assert command == TestCommand1
131
-
132
-
133
- def test_get_nonexistent_command():
134
- """Test getting nonexistent command."""
135
- registry = CommandRegistry()
136
-
137
- # Try to get nonexistent command
138
- with pytest.raises(NotFoundError):
139
- registry.get_command("nonexistent")
140
-
141
-
142
- def test_get_all_commands():
143
- """Test getting all commands."""
144
- registry = CommandRegistry()
145
-
146
- # Register commands
147
- registry.register(TestCommand1)
148
- registry.register(TestCommand2)
149
-
150
- # Get all commands
151
- commands = registry.get_all_commands()
152
- assert len(commands) == 2
153
- assert "test_command1" in commands
154
- assert "test_command2" in commands
155
- assert commands["test_command1"] == TestCommand1
156
- assert commands["test_command2"] == TestCommand2
157
-
158
-
159
- def test_get_command_info():
160
- """Test getting command info."""
161
- registry = CommandRegistry()
162
-
163
- # Register command
164
- registry.register(TestCommand1)
165
-
166
- # Get command info
167
- info = registry.get_command_info("test_command1")
168
-
169
- # Check info structure
170
- assert info["name"] == "test_command1"
171
- assert "description" in info
172
- assert "params" in info
173
- assert "schema" in info
174
- assert "result_schema" in info
175
-
176
-
177
- def test_get_all_commands_info():
178
- """Test getting all commands info."""
179
- registry = CommandRegistry()
180
-
181
- # Register commands
182
- registry.register(TestCommand1)
183
- registry.register(TestCommand2)
184
-
185
- # Get all commands info
186
- info = registry.get_all_commands_info()
187
-
188
- # Check info structure
189
- assert len(info) == 2
190
- assert "test_command1" in info
191
- assert "test_command2" in info
192
- assert info["test_command1"]["name"] == "test_command1"
193
- assert info["test_command2"]["name"] == "test_command2"
194
-
195
-
196
- @patch("importlib.import_module")
197
- @patch("pkgutil.iter_modules")
198
- @patch("inspect.getmembers")
199
- def test_discover_commands(mock_getmembers, mock_iter_modules, mock_import_module):
200
- """Test discovering commands."""
201
- registry = CommandRegistry()
202
-
203
- # Mock package
204
- mock_package = MagicMock()
205
- mock_package.__file__ = "/path/to/package"
206
- mock_import_module.return_value = mock_package
207
-
208
- # Mock modules
209
- mock_iter_modules.return_value = [
210
- (None, "test_command", False),
211
- (None, "other_module", False)
212
- ]
213
-
214
- # Mock command classes
215
- class DiscoveredCommand(Command):
216
- name = "discovered"
217
- result_class = MockResult
218
-
219
- async def execute(self, **kwargs):
220
- return MockResult()
221
-
222
- # Mock getmembers to return command class
223
- mock_getmembers.return_value = [
224
- ("DiscoveredCommand", DiscoveredCommand)
225
- ]
226
-
227
- # Discover commands
228
- registry.discover_commands()
229
-
230
- # Check if command was registered
231
- assert len(mock_import_module.mock_calls) > 0
232
-
233
-
234
- def test_clear_registry():
235
- """Test clearing registry."""
236
- registry = CommandRegistry()
237
-
238
- # Register commands
239
- registry.register(TestCommand1)
240
- registry.register(TestCommand2)
241
- assert len(registry._commands) == 2
242
-
243
- # Clear registry
244
- registry.clear()
245
- assert len(registry._commands) == 0
246
-
247
-
248
- def test_register_command_instance():
249
- """Test registering a command instance (with dependencies)."""
250
- registry = CommandRegistry()
251
-
252
- class Service:
253
- def __init__(self, value):
254
- self.value = value
255
-
256
- class CommandWithDependency(Command):
257
- name = "command_with_dep"
258
- result_class = MockResult
259
- def __init__(self, service: Service):
260
- self.service = service
261
- async def execute(self, **kwargs):
262
- # Return the value from the injected service
263
- result = MockResult()
264
- result.service_value = self.service.value
265
- return result
266
-
267
- service = Service(value=42)
268
- command_instance = CommandWithDependency(service=service)
269
- registry.register(command_instance)
270
-
271
- # Проверяем, что экземпляр зарегистрирован
272
- assert registry.has_instance("command_with_dep")
273
- # Проверяем, что get_command_instance возвращает именно этот экземпляр
274
- assert registry.get_command_instance("command_with_dep") is command_instance
275
- # Проверяем, что execute использует внедрённый сервис
276
- import asyncio
277
- result = asyncio.run(
278
- registry.get_command_instance("command_with_dep").execute()
279
- )
280
- assert hasattr(result, "service_value")
281
- assert result.service_value == 42
@@ -1,127 +0,0 @@
1
- """
2
- Test module for configuration class.
3
- """
4
-
5
- import os
6
- import json
7
- import tempfile
8
- from pathlib import Path
9
-
10
- import pytest
11
-
12
- from mcp_proxy_adapter.config import Config
13
-
14
-
15
- def test_config_initialization(temp_config_file):
16
- """
17
- Test configuration initialization.
18
- """
19
- config = Config(temp_config_file)
20
- assert config.config_path == temp_config_file
21
- assert isinstance(config.config_data, dict)
22
-
23
-
24
- def test_config_get_existing_values(test_config):
25
- """
26
- Test getting existing values from configuration.
27
- """
28
- # Test top-level key
29
- server_config = test_config.get("server")
30
- assert server_config.get("host") == "127.0.0.1"
31
- assert server_config.get("port") == 8888
32
-
33
- # Test nested key with dot notation
34
- assert test_config.get("server.host") == "127.0.0.1"
35
- assert test_config.get("server.port") == 8888
36
-
37
- # Test logging values
38
- assert test_config.get("logging.level") == "DEBUG"
39
- assert test_config.get("logging.file") is None
40
-
41
-
42
- def test_config_get_default_values(test_config):
43
- """
44
- Test getting default values for non-existent keys.
45
- """
46
- # Non-existent key with default
47
- assert test_config.get("non_existent", "default") == "default"
48
-
49
- # Non-existent nested key with default
50
- assert test_config.get("server.non_existent", 42) == 42
51
-
52
- # Non-existent top level with nested key
53
- assert test_config.get("non_existent.key", False) is False
54
-
55
-
56
- def test_config_set_values(test_config):
57
- """
58
- Test setting values in configuration.
59
- """
60
- # Set top-level value
61
- test_config.set("new_key", "value")
62
- assert test_config.get("new_key") == "value"
63
-
64
- # Set nested value for existing parent
65
- test_config.set("server.api_key", "secret")
66
- assert test_config.get("server.api_key") == "secret"
67
-
68
- # Set nested value with non-existent parent
69
- test_config.set("database.url", "postgres://localhost")
70
- assert test_config.get("database.url") == "postgres://localhost"
71
-
72
- # Overwrite existing value
73
- test_config.set("server.host", "0.0.0.0")
74
- assert test_config.get("server.host") == "0.0.0.0"
75
-
76
-
77
- def test_config_save_load(temp_config_file):
78
- """
79
- Test saving and loading configuration.
80
- """
81
- # Create and modify config
82
- config = Config(temp_config_file)
83
- config.set("test_key", "test_value")
84
- config.set("nested.key", 123)
85
-
86
- # Save config
87
- config.save()
88
-
89
- # Create new config instance to load from the same file
90
- new_config = Config(temp_config_file)
91
-
92
- # Verify values were saved and loaded
93
- assert new_config.get("test_key") == "test_value"
94
- assert new_config.get("nested.key") == 123
95
- assert new_config.get("server.host") == "127.0.0.1"
96
-
97
-
98
- def test_config_environment_variables():
99
- """
100
- Test environment variables override configuration values.
101
- """
102
- with tempfile.NamedTemporaryFile(suffix=".json", delete=False, mode="w") as temp:
103
- temp_path = temp.name
104
- json.dump({"server": {"host": "localhost", "port": 8000}}, temp)
105
-
106
- try:
107
- # Set environment variables
108
- os.environ["SERVICE_SERVER_HOST"] = "192.168.1.1"
109
- os.environ["SERVICE_SERVER_PORT"] = "9000"
110
- os.environ["SERVICE_LOGGING_LEVEL"] = "INFO"
111
-
112
- # Create config that should load from env vars
113
- config = Config(temp_path)
114
-
115
- # Check values are overridden by environment
116
- assert config.get("server.host") == "192.168.1.1"
117
- assert config.get("server.port") == 9000
118
- assert config.get("logging.level") == "INFO"
119
- finally:
120
- # Clean up
121
- os.unlink(temp_path)
122
- if "SERVICE_SERVER_HOST" in os.environ:
123
- del os.environ["SERVICE_SERVER_HOST"]
124
- if "SERVICE_SERVER_PORT" in os.environ:
125
- del os.environ["SERVICE_SERVER_PORT"]
126
- if "SERVICE_LOGGING_LEVEL" in os.environ:
127
- del os.environ["SERVICE_LOGGING_LEVEL"]
@@ -1,65 +0,0 @@
1
- """
2
- Test utilities for mcp_microservice.
3
- """
4
-
5
- from typing import Any, Dict
6
- from mcp_proxy_adapter.commands.result import CommandResult
7
-
8
-
9
- class MockResult(CommandResult):
10
- """
11
- Mock result class for testing.
12
-
13
- Attributes:
14
- message: Test message.
15
- timestamp: Test timestamp.
16
- """
17
-
18
- def __init__(self, message: str = "Test message", timestamp: float = 12345.0):
19
- self.message = message
20
- self.timestamp = timestamp
21
-
22
- def to_dict(self) -> Dict[str, Any]:
23
- """
24
- Converts result to dictionary for serialization.
25
-
26
- Returns:
27
- Dictionary with result data.
28
- """
29
- return {
30
- "message": self.message,
31
- "timestamp": self.timestamp
32
- }
33
-
34
- @classmethod
35
- def get_schema(cls) -> Dict[str, Any]:
36
- """
37
- Returns JSON schema for result validation.
38
-
39
- Returns:
40
- Dictionary with JSON schema.
41
- """
42
- return {
43
- "type": "object",
44
- "properties": {
45
- "message": {"type": "string", "description": "Test message"},
46
- "timestamp": {"type": "number", "description": "Test timestamp"}
47
- },
48
- "required": ["message", "timestamp"]
49
- }
50
-
51
- @classmethod
52
- def from_dict(cls, data: Dict[str, Any]) -> "MockResult":
53
- """
54
- Creates result instance from dictionary.
55
-
56
- Args:
57
- data: Dictionary with result data.
58
-
59
- Returns:
60
- MockResult instance.
61
- """
62
- return cls(
63
- message=data.get("message", ""),
64
- timestamp=data.get("timestamp", 0.0)
65
- )
@@ -1,3 +0,0 @@
1
- """
2
- Unit tests for the mcp_microservice package.
3
- """