mcp-proxy-adapter 4.1.1__py3-none-any.whl → 6.0.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 (200) hide show
  1. mcp_proxy_adapter/__main__.py +32 -0
  2. mcp_proxy_adapter/api/app.py +290 -33
  3. mcp_proxy_adapter/api/handlers.py +32 -6
  4. mcp_proxy_adapter/api/middleware/__init__.py +38 -32
  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 +201 -0
  10. mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
  11. mcp_proxy_adapter/api/middleware/unified_security.py +197 -0
  12. mcp_proxy_adapter/api/middleware/user_info_middleware.py +158 -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 +8 -1
  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 +366 -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 +394 -14
  41. mcp_proxy_adapter/core/app_factory.py +410 -0
  42. mcp_proxy_adapter/core/app_runner.py +272 -0
  43. mcp_proxy_adapter/core/auth_validator.py +606 -0
  44. mcp_proxy_adapter/core/certificate_utils.py +1045 -0
  45. mcp_proxy_adapter/core/client.py +574 -0
  46. mcp_proxy_adapter/core/client_manager.py +284 -0
  47. mcp_proxy_adapter/core/client_security.py +384 -0
  48. mcp_proxy_adapter/core/config_converter.py +405 -0
  49. mcp_proxy_adapter/core/config_validator.py +218 -0
  50. mcp_proxy_adapter/core/logging.py +19 -3
  51. mcp_proxy_adapter/core/mtls_asgi.py +156 -0
  52. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  53. mcp_proxy_adapter/core/protocol_manager.py +385 -0
  54. mcp_proxy_adapter/core/proxy_client.py +602 -0
  55. mcp_proxy_adapter/core/proxy_registration.py +522 -0
  56. mcp_proxy_adapter/core/role_utils.py +426 -0
  57. mcp_proxy_adapter/core/security_adapter.py +370 -0
  58. mcp_proxy_adapter/core/security_factory.py +239 -0
  59. mcp_proxy_adapter/core/security_integration.py +286 -0
  60. mcp_proxy_adapter/core/server_adapter.py +282 -0
  61. mcp_proxy_adapter/core/server_engine.py +270 -0
  62. mcp_proxy_adapter/core/settings.py +1 -0
  63. mcp_proxy_adapter/core/ssl_utils.py +234 -0
  64. mcp_proxy_adapter/core/transport_manager.py +292 -0
  65. mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
  66. mcp_proxy_adapter/custom_openapi.py +22 -11
  67. mcp_proxy_adapter/examples/__init__.py +13 -4
  68. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  69. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  70. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  71. mcp_proxy_adapter/examples/basic_framework/main.py +44 -0
  72. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  73. mcp_proxy_adapter/examples/create_certificates_simple.py +550 -0
  74. mcp_proxy_adapter/examples/debug_request_state.py +112 -0
  75. mcp_proxy_adapter/examples/debug_role_chain.py +158 -0
  76. mcp_proxy_adapter/examples/demo_client.py +275 -0
  77. mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
  78. mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
  79. mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
  80. mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
  81. mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
  82. mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
  83. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
  84. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  85. mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
  86. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
  87. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  88. mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
  89. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
  90. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  91. mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
  92. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +80 -0
  93. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  94. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
  95. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +75 -0
  96. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  97. mcp_proxy_adapter/examples/full_application/main.py +173 -0
  98. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
  99. mcp_proxy_adapter/examples/generate_all_certificates.py +362 -0
  100. mcp_proxy_adapter/examples/generate_certificates.py +177 -0
  101. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
  102. mcp_proxy_adapter/examples/generate_test_configs.py +331 -0
  103. mcp_proxy_adapter/examples/proxy_registration_example.py +334 -0
  104. mcp_proxy_adapter/examples/run_example.py +59 -0
  105. mcp_proxy_adapter/examples/run_full_test_suite.py +318 -0
  106. mcp_proxy_adapter/examples/run_proxy_server.py +146 -0
  107. mcp_proxy_adapter/examples/run_security_tests.py +544 -0
  108. mcp_proxy_adapter/examples/run_security_tests_fixed.py +247 -0
  109. mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
  110. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
  111. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
  112. mcp_proxy_adapter/examples/security_test_client.py +782 -0
  113. mcp_proxy_adapter/examples/setup_test_environment.py +328 -0
  114. mcp_proxy_adapter/examples/test_config.py +148 -0
  115. mcp_proxy_adapter/examples/test_config_generator.py +86 -0
  116. mcp_proxy_adapter/examples/test_examples.py +281 -0
  117. mcp_proxy_adapter/examples/universal_client.py +620 -0
  118. mcp_proxy_adapter/main.py +93 -0
  119. mcp_proxy_adapter/utils/config_generator.py +1008 -0
  120. mcp_proxy_adapter/version.py +5 -2
  121. mcp_proxy_adapter-6.0.1.dist-info/METADATA +679 -0
  122. mcp_proxy_adapter-6.0.1.dist-info/RECORD +140 -0
  123. mcp_proxy_adapter-6.0.1.dist-info/entry_points.txt +2 -0
  124. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/licenses/LICENSE +2 -2
  125. mcp_proxy_adapter/api/middleware/auth.py +0 -146
  126. mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
  127. mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
  128. mcp_proxy_adapter/examples/README.md +0 -124
  129. mcp_proxy_adapter/examples/basic_server/README.md +0 -60
  130. mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
  131. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
  132. mcp_proxy_adapter/examples/basic_server/config.json +0 -35
  133. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
  134. mcp_proxy_adapter/examples/basic_server/server.py +0 -103
  135. mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
  136. mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
  137. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -250
  138. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
  139. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
  140. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
  141. mcp_proxy_adapter/examples/custom_commands/config.json +0 -35
  142. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
  143. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
  144. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
  145. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
  146. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
  147. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
  148. mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
  149. mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
  150. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
  151. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
  152. mcp_proxy_adapter/examples/custom_commands/server.py +0 -228
  153. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
  154. mcp_proxy_adapter/examples/deployment/README.md +0 -49
  155. mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
  156. mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
  157. mcp_proxy_adapter/examples/deployment/config.json +0 -29
  158. mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
  159. mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
  160. mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
  161. mcp_proxy_adapter/examples/deployment/run.sh +0 -43
  162. mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
  163. mcp_proxy_adapter/schemas/base_schema.json +0 -114
  164. mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
  165. mcp_proxy_adapter/tests/__init__.py +0 -0
  166. mcp_proxy_adapter/tests/api/__init__.py +0 -3
  167. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
  168. mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
  169. mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
  170. mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
  171. mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
  172. mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
  173. mcp_proxy_adapter/tests/commands/__init__.py +0 -3
  174. mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
  175. mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
  176. mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
  177. mcp_proxy_adapter/tests/conftest.py +0 -131
  178. mcp_proxy_adapter/tests/functional/__init__.py +0 -3
  179. mcp_proxy_adapter/tests/functional/test_api.py +0 -253
  180. mcp_proxy_adapter/tests/integration/__init__.py +0 -3
  181. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
  182. mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
  183. mcp_proxy_adapter/tests/performance/__init__.py +0 -3
  184. mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
  185. mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
  186. mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
  187. mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
  188. mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
  189. mcp_proxy_adapter/tests/test_base_command.py +0 -123
  190. mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
  191. mcp_proxy_adapter/tests/test_command_registry.py +0 -281
  192. mcp_proxy_adapter/tests/test_config.py +0 -127
  193. mcp_proxy_adapter/tests/test_utils.py +0 -65
  194. mcp_proxy_adapter/tests/unit/__init__.py +0 -3
  195. mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
  196. mcp_proxy_adapter/tests/unit/test_config.py +0 -217
  197. mcp_proxy_adapter-4.1.1.dist-info/METADATA +0 -200
  198. mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
  199. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/WHEEL +0 -0
  200. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.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
- """