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