mcp-proxy-adapter 6.0.0__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 (212) hide show
  1. mcp_proxy_adapter/__main__.py +27 -7
  2. mcp_proxy_adapter/api/app.py +209 -79
  3. mcp_proxy_adapter/api/handlers.py +16 -5
  4. mcp_proxy_adapter/api/middleware/__init__.py +14 -9
  5. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
  6. mcp_proxy_adapter/api/middleware/factory.py +36 -12
  7. mcp_proxy_adapter/api/middleware/protocol_middleware.py +84 -18
  8. mcp_proxy_adapter/api/middleware/unified_security.py +197 -0
  9. mcp_proxy_adapter/api/middleware/user_info_middleware.py +158 -0
  10. mcp_proxy_adapter/commands/__init__.py +7 -1
  11. mcp_proxy_adapter/commands/base.py +7 -4
  12. mcp_proxy_adapter/commands/builtin_commands.py +8 -2
  13. mcp_proxy_adapter/commands/command_registry.py +8 -0
  14. mcp_proxy_adapter/commands/echo_command.py +81 -0
  15. mcp_proxy_adapter/commands/health_command.py +1 -1
  16. mcp_proxy_adapter/commands/help_command.py +21 -14
  17. mcp_proxy_adapter/commands/proxy_registration_command.py +326 -185
  18. mcp_proxy_adapter/commands/role_test_command.py +141 -0
  19. mcp_proxy_adapter/commands/security_command.py +488 -0
  20. mcp_proxy_adapter/commands/ssl_setup_command.py +234 -351
  21. mcp_proxy_adapter/commands/token_management_command.py +1 -1
  22. mcp_proxy_adapter/config.py +323 -40
  23. mcp_proxy_adapter/core/app_factory.py +410 -0
  24. mcp_proxy_adapter/core/app_runner.py +272 -0
  25. mcp_proxy_adapter/core/certificate_utils.py +291 -73
  26. mcp_proxy_adapter/core/client.py +574 -0
  27. mcp_proxy_adapter/core/client_manager.py +284 -0
  28. mcp_proxy_adapter/core/client_security.py +384 -0
  29. mcp_proxy_adapter/core/logging.py +8 -3
  30. mcp_proxy_adapter/core/mtls_asgi.py +156 -0
  31. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  32. mcp_proxy_adapter/core/protocol_manager.py +169 -10
  33. mcp_proxy_adapter/core/proxy_client.py +602 -0
  34. mcp_proxy_adapter/core/proxy_registration.py +299 -47
  35. mcp_proxy_adapter/core/security_adapter.py +12 -15
  36. mcp_proxy_adapter/core/security_integration.py +286 -0
  37. mcp_proxy_adapter/core/server_adapter.py +282 -0
  38. mcp_proxy_adapter/core/server_engine.py +270 -0
  39. mcp_proxy_adapter/core/ssl_utils.py +13 -12
  40. mcp_proxy_adapter/core/transport_manager.py +5 -5
  41. mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
  42. mcp_proxy_adapter/examples/__init__.py +13 -4
  43. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  44. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  45. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  46. mcp_proxy_adapter/examples/basic_framework/main.py +44 -0
  47. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  48. mcp_proxy_adapter/examples/create_certificates_simple.py +550 -0
  49. mcp_proxy_adapter/examples/debug_request_state.py +112 -0
  50. mcp_proxy_adapter/examples/debug_role_chain.py +158 -0
  51. mcp_proxy_adapter/examples/demo_client.py +275 -0
  52. mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
  53. mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
  54. mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
  55. mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
  56. mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
  57. mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
  58. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
  59. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  60. mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
  61. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
  62. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  63. mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
  64. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
  65. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  66. mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
  67. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +80 -0
  68. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  69. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
  70. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +75 -0
  71. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  72. mcp_proxy_adapter/examples/full_application/main.py +173 -0
  73. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
  74. mcp_proxy_adapter/examples/generate_all_certificates.py +362 -0
  75. mcp_proxy_adapter/examples/generate_certificates.py +177 -0
  76. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
  77. mcp_proxy_adapter/examples/generate_test_configs.py +331 -0
  78. mcp_proxy_adapter/examples/proxy_registration_example.py +334 -0
  79. mcp_proxy_adapter/examples/run_example.py +59 -0
  80. mcp_proxy_adapter/examples/run_full_test_suite.py +318 -0
  81. mcp_proxy_adapter/examples/run_proxy_server.py +146 -0
  82. mcp_proxy_adapter/examples/run_security_tests.py +544 -0
  83. mcp_proxy_adapter/examples/run_security_tests_fixed.py +247 -0
  84. mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
  85. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
  86. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
  87. mcp_proxy_adapter/examples/security_test_client.py +782 -0
  88. mcp_proxy_adapter/examples/setup_test_environment.py +328 -0
  89. mcp_proxy_adapter/examples/test_config.py +148 -0
  90. mcp_proxy_adapter/examples/test_config_generator.py +86 -0
  91. mcp_proxy_adapter/examples/test_examples.py +281 -0
  92. mcp_proxy_adapter/examples/universal_client.py +620 -0
  93. mcp_proxy_adapter/main.py +66 -148
  94. mcp_proxy_adapter/utils/config_generator.py +1008 -0
  95. mcp_proxy_adapter/version.py +5 -2
  96. mcp_proxy_adapter-6.0.1.dist-info/METADATA +679 -0
  97. mcp_proxy_adapter-6.0.1.dist-info/RECORD +140 -0
  98. mcp_proxy_adapter-6.0.1.dist-info/entry_points.txt +2 -0
  99. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/licenses/LICENSE +2 -2
  100. mcp_proxy_adapter/api/middleware/auth.py +0 -146
  101. mcp_proxy_adapter/api/middleware/auth_adapter.py +0 -235
  102. mcp_proxy_adapter/api/middleware/mtls_adapter.py +0 -305
  103. mcp_proxy_adapter/api/middleware/mtls_middleware.py +0 -296
  104. mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
  105. mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +0 -241
  106. mcp_proxy_adapter/api/middleware/roles_adapter.py +0 -365
  107. mcp_proxy_adapter/api/middleware/roles_middleware.py +0 -381
  108. mcp_proxy_adapter/api/middleware/security.py +0 -376
  109. mcp_proxy_adapter/api/middleware/token_auth_middleware.py +0 -261
  110. mcp_proxy_adapter/examples/README.md +0 -124
  111. mcp_proxy_adapter/examples/basic_server/README.md +0 -60
  112. mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
  113. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
  114. mcp_proxy_adapter/examples/basic_server/config.json +0 -70
  115. mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +0 -54
  116. mcp_proxy_adapter/examples/basic_server/config_http.json +0 -70
  117. mcp_proxy_adapter/examples/basic_server/config_http_only.json +0 -52
  118. mcp_proxy_adapter/examples/basic_server/config_https.json +0 -58
  119. mcp_proxy_adapter/examples/basic_server/config_mtls.json +0 -58
  120. mcp_proxy_adapter/examples/basic_server/config_ssl.json +0 -46
  121. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
  122. mcp_proxy_adapter/examples/basic_server/server.py +0 -114
  123. mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
  124. mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
  125. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -566
  126. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
  127. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
  128. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
  129. mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +0 -105
  130. mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +0 -129
  131. mcp_proxy_adapter/examples/custom_commands/config.json +0 -118
  132. mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +0 -46
  133. mcp_proxy_adapter/examples/custom_commands/config_https_only.json +0 -46
  134. mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +0 -33
  135. mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +0 -46
  136. mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +0 -33
  137. mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +0 -33
  138. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
  139. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
  140. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
  141. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
  142. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
  143. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
  144. mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
  145. mcp_proxy_adapter/examples/custom_commands/full_help_response.json +0 -1
  146. mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +0 -629
  147. mcp_proxy_adapter/examples/custom_commands/get_openapi.py +0 -103
  148. mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
  149. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
  150. mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +0 -129
  151. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
  152. mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +0 -278
  153. mcp_proxy_adapter/examples/custom_commands/server.py +0 -252
  154. mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +0 -75
  155. mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +0 -299
  156. mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +0 -278
  157. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
  158. mcp_proxy_adapter/examples/custom_commands/test_openapi.py +0 -27
  159. mcp_proxy_adapter/examples/custom_commands/test_registry.py +0 -23
  160. mcp_proxy_adapter/examples/custom_commands/test_simple.py +0 -19
  161. mcp_proxy_adapter/examples/custom_project_example/README.md +0 -103
  162. mcp_proxy_adapter/examples/custom_project_example/README_EN.md +0 -103
  163. mcp_proxy_adapter/examples/deployment/README.md +0 -49
  164. mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
  165. mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
  166. mcp_proxy_adapter/examples/deployment/config.json +0 -29
  167. mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
  168. mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
  169. mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
  170. mcp_proxy_adapter/examples/deployment/run.sh +0 -43
  171. mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
  172. mcp_proxy_adapter/examples/simple_custom_commands/README.md +0 -149
  173. mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +0 -149
  174. mcp_proxy_adapter/schemas/base_schema.json +0 -114
  175. mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
  176. mcp_proxy_adapter/schemas/roles_schema.json +0 -162
  177. mcp_proxy_adapter/tests/__init__.py +0 -0
  178. mcp_proxy_adapter/tests/api/__init__.py +0 -3
  179. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
  180. mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
  181. mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
  182. mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
  183. mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
  184. mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
  185. mcp_proxy_adapter/tests/commands/__init__.py +0 -3
  186. mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
  187. mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
  188. mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
  189. mcp_proxy_adapter/tests/conftest.py +0 -131
  190. mcp_proxy_adapter/tests/functional/__init__.py +0 -3
  191. mcp_proxy_adapter/tests/functional/test_api.py +0 -253
  192. mcp_proxy_adapter/tests/integration/__init__.py +0 -3
  193. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
  194. mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
  195. mcp_proxy_adapter/tests/performance/__init__.py +0 -3
  196. mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
  197. mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
  198. mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
  199. mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
  200. mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
  201. mcp_proxy_adapter/tests/test_base_command.py +0 -123
  202. mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
  203. mcp_proxy_adapter/tests/test_command_registry.py +0 -281
  204. mcp_proxy_adapter/tests/test_config.py +0 -127
  205. mcp_proxy_adapter/tests/test_utils.py +0 -65
  206. mcp_proxy_adapter/tests/unit/__init__.py +0 -3
  207. mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
  208. mcp_proxy_adapter/tests/unit/test_config.py +0 -270
  209. mcp_proxy_adapter-6.0.0.dist-info/METADATA +0 -201
  210. mcp_proxy_adapter-6.0.0.dist-info/RECORD +0 -179
  211. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/WHEEL +0 -0
  212. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/top_level.txt +0 -0
@@ -1,211 +0,0 @@
1
- """
2
- Unit tests for config command.
3
- """
4
-
5
- import json
6
- import os
7
- import tempfile
8
- from typing import Generator
9
-
10
- import pytest
11
-
12
- from mcp_proxy_adapter.commands.config_command import ConfigCommand, ConfigResult
13
- from mcp_proxy_adapter.config import Config
14
-
15
-
16
- @pytest.fixture
17
- def temp_config_file() -> Generator[str, None, None]:
18
- """
19
- Creates temporary configuration file for tests.
20
-
21
- Returns:
22
- Path to temporary configuration file.
23
- """
24
- # Create temporary file
25
- fd, path = tempfile.mkstemp(suffix=".json")
26
-
27
- # Write test configuration
28
- test_config = {
29
- "server": {
30
- "host": "127.0.0.1",
31
- "port": 8000
32
- },
33
- "logging": {
34
- "level": "DEBUG",
35
- "file": "test.log"
36
- },
37
- "test_section": {
38
- "test_key": "test_value",
39
- "nested": {
40
- "key1": "value1",
41
- "key2": 42
42
- }
43
- }
44
- }
45
-
46
- with os.fdopen(fd, "w") as f:
47
- json.dump(test_config, f)
48
-
49
- yield path
50
-
51
- # Remove temporary file after tests
52
- os.unlink(path)
53
-
54
-
55
- @pytest.mark.unit
56
- async def test_config_command_get_all(temp_config_file: str):
57
- """
58
- Test getting all configuration values.
59
-
60
- Args:
61
- temp_config_file: Path to temporary configuration file.
62
- """
63
- # Create config instance with test file
64
- config_instance = Config(temp_config_file)
65
-
66
- # Create command with this config
67
- command = ConfigCommand()
68
-
69
- # Override the config instance used in the command
70
- from mcp_proxy_adapter.commands import config_command
71
- original_config = config_command.config_instance
72
- config_command.config_instance = config_instance
73
-
74
- try:
75
- # Execute command with get operation and no path
76
- result = await command.execute(operation="get")
77
-
78
- # Check result
79
- assert isinstance(result, ConfigResult)
80
- result_dict = result.to_dict()
81
- assert result_dict["success"] is True
82
- assert "data" in result_dict
83
- assert "config" in result_dict["data"]
84
- assert "operation" in result_dict["data"]
85
- assert result_dict["data"]["operation"] == "get"
86
-
87
- # Check all config values are present
88
- config_data = result_dict["data"]["config"]
89
- assert "server" in config_data
90
- assert "logging" in config_data
91
- assert "test_section" in config_data
92
-
93
- assert config_data["server"]["host"] == "127.0.0.1"
94
- assert config_data["logging"]["level"] == "DEBUG"
95
- assert config_data["test_section"]["test_key"] == "test_value"
96
- finally:
97
- # Restore original config instance
98
- config_command.config_instance = original_config
99
-
100
-
101
- @pytest.mark.unit
102
- async def test_config_command_get_specific(temp_config_file: str):
103
- """
104
- Test getting specific configuration value.
105
-
106
- Args:
107
- temp_config_file: Path to temporary configuration file.
108
- """
109
- # Create config instance with test file
110
- config_instance = Config(temp_config_file)
111
-
112
- # Create command with this config
113
- command = ConfigCommand()
114
-
115
- # Override the config instance used in the command
116
- from mcp_proxy_adapter.commands import config_command
117
- original_config = config_command.config_instance
118
- config_command.config_instance = config_instance
119
-
120
- try:
121
- # Execute command with get operation and specific path
122
- result = await command.execute(operation="get", path="server.host")
123
-
124
- # Check result
125
- assert isinstance(result, ConfigResult)
126
- result_dict = result.to_dict()
127
- assert result_dict["success"] is True
128
- assert "data" in result_dict
129
- assert "config" in result_dict["data"]
130
- assert "operation" in result_dict["data"]
131
- assert result_dict["data"]["operation"] == "get"
132
-
133
- # Check specific config value
134
- config_data = result_dict["data"]["config"]
135
- assert "server.host" in config_data
136
- assert config_data["server.host"] == "127.0.0.1"
137
- finally:
138
- # Restore original config instance
139
- config_command.config_instance = original_config
140
-
141
-
142
- @pytest.mark.unit
143
- async def test_config_command_set_value(temp_config_file: str):
144
- """
145
- Test setting configuration value.
146
-
147
- Args:
148
- temp_config_file: Path to temporary configuration file.
149
- """
150
- # Create config instance with test file
151
- config_instance = Config(temp_config_file)
152
-
153
- # Create command with this config
154
- command = ConfigCommand()
155
-
156
- # Override the config instance used in the command
157
- from mcp_proxy_adapter.commands import config_command
158
- original_config = config_command.config_instance
159
- config_command.config_instance = config_instance
160
-
161
- try:
162
- # Execute command with set operation
163
- result = await command.execute(
164
- operation="set",
165
- path="server.host",
166
- value="localhost"
167
- )
168
-
169
- # Check result
170
- assert isinstance(result, ConfigResult)
171
- result_dict = result.to_dict()
172
- assert result_dict["success"] is True
173
- assert "data" in result_dict
174
- assert "config" in result_dict["data"]
175
- assert "operation" in result_dict["data"]
176
- assert result_dict["data"]["operation"] == "set"
177
-
178
- # Check updated config value
179
- config_data = result_dict["data"]["config"]
180
- assert "server.host" in config_data
181
- assert config_data["server.host"] == "localhost"
182
-
183
- # Check that value was updated in config instance
184
- assert config_instance.get("server.host") == "localhost"
185
- finally:
186
- # Restore original config instance
187
- config_command.config_instance = original_config
188
-
189
-
190
- @pytest.mark.unit
191
- async def test_config_command_validate_schema():
192
- """
193
- Test validation schema for config command.
194
- """
195
- command = ConfigCommand()
196
- schema = command.get_schema()
197
-
198
- # Check schema structure
199
- assert schema["type"] == "object"
200
- assert "properties" in schema
201
- assert "operation" in schema["properties"]
202
- assert "path" in schema["properties"]
203
- assert "value" in schema["properties"]
204
-
205
- # Check operation property
206
- operation_prop = schema["properties"]["operation"]
207
- assert operation_prop["type"] == "string"
208
- assert "enum" in operation_prop
209
- assert "get" in operation_prop["enum"]
210
- assert "set" in operation_prop["enum"]
211
- assert operation_prop["default"] == "get"
@@ -1,127 +0,0 @@
1
- """
2
- Tests for the echo command.
3
- """
4
-
5
- import pytest
6
- import asyncio
7
- from typing import Dict, Any
8
- import json
9
-
10
- from mcp_proxy_adapter.tests.stubs.echo_command import EchoCommand
11
- from mcp_proxy_adapter.tests.stubs.echo_command import EchoResult
12
-
13
-
14
- @pytest.mark.unit
15
- def test_echo_command_execution():
16
- """
17
- Test execution of echo command.
18
- """
19
- # Create test parameters
20
- test_params = {
21
- "string_param": "test_value",
22
- "int_param": 42,
23
- "bool_param": True,
24
- "complex_param": {"nested": "value", "array": [1, 2, 3]}
25
- }
26
-
27
- # Create and execute command
28
- command = EchoCommand()
29
- result = asyncio.run(command.execute(**test_params))
30
-
31
- # Check result type
32
- assert isinstance(result, EchoResult)
33
-
34
- # Check result content
35
- assert result.params == test_params
36
- assert result.params["string_param"] == "test_value"
37
- assert result.params["int_param"] == 42
38
- assert result.params["bool_param"] is True
39
- assert result.params["complex_param"]["nested"] == "value"
40
- assert result.params["complex_param"]["array"] == [1, 2, 3]
41
-
42
-
43
- @pytest.mark.unit
44
- def test_echo_result_serialization():
45
- """
46
- Test serialization of echo result.
47
- """
48
- # Create test parameters
49
- test_params = {
50
- "string_param": "test_value",
51
- "int_param": 42,
52
- "bool_param": True,
53
- "complex_param": {"nested": "value", "array": [1, 2, 3]}
54
- }
55
-
56
- # Create result
57
- result = EchoResult(params=test_params)
58
-
59
- # Test to_dict method
60
- result_dict = result.to_dict()
61
- assert isinstance(result_dict, dict)
62
- assert "params" in result_dict
63
- assert result_dict["params"] == test_params
64
-
65
- # Test that result can be properly serialized to JSON
66
- json_str = json.dumps(result_dict)
67
- parsed_json = json.loads(json_str)
68
- assert parsed_json == result_dict
69
-
70
-
71
- @pytest.mark.unit
72
- def test_echo_command_schema():
73
- """
74
- Test command schema generation.
75
- """
76
- # Get schema
77
- schema = EchoCommand.get_schema()
78
-
79
- # Check schema structure
80
- assert isinstance(schema, dict)
81
- assert "type" in schema and schema["type"] == "object"
82
- assert "additionalProperties" in schema and schema["additionalProperties"] is True
83
- assert "description" in schema
84
-
85
-
86
- @pytest.mark.unit
87
- def test_echo_result_schema():
88
- """
89
- Test result schema generation.
90
- """
91
- # Get schema
92
- schema = EchoResult.get_schema()
93
-
94
- # Check schema structure
95
- assert isinstance(schema, dict)
96
- assert "type" in schema and schema["type"] == "object"
97
- assert "properties" in schema
98
- assert "params" in schema["properties"]
99
- assert "required" in schema and "params" in schema["required"]
100
- assert schema["properties"]["params"]["type"] == "object"
101
- assert schema["properties"]["params"]["additionalProperties"] is True
102
-
103
-
104
- @pytest.mark.unit
105
- def test_echo_result_from_dict():
106
- """
107
- Test creating result from dictionary.
108
- """
109
- # Create test data
110
- test_data = {
111
- "params": {
112
- "key1": "value1",
113
- "key2": 42
114
- }
115
- }
116
-
117
- # Create result from dict
118
- result = EchoResult.from_dict(test_data)
119
-
120
- # Check result
121
- assert isinstance(result, EchoResult)
122
- assert result.params == test_data["params"]
123
-
124
- # Test with empty params
125
- empty_result = EchoResult.from_dict({})
126
- assert isinstance(empty_result, EchoResult)
127
- assert empty_result.params == {}
@@ -1,136 +0,0 @@
1
- """
2
- Tests for the help command.
3
- """
4
-
5
- import pytest
6
- from unittest.mock import patch, MagicMock
7
-
8
- from mcp_proxy_adapter.commands.help_command import HelpCommand, HelpResult
9
- from mcp_proxy_adapter.core.errors import NotFoundError
10
-
11
-
12
- @pytest.fixture
13
- def mock_registry():
14
- """Mock for command registry."""
15
- with patch("mcp_proxy_adapter.commands.help_command.registry") as mock_reg:
16
- yield mock_reg
17
-
18
-
19
- async def test_help_command_without_params(mock_registry):
20
- """Test help command without parameters."""
21
- # Setup mocks
22
- mock_registry.get_all_metadata.return_value = {
23
- "help": {
24
- "name": "help",
25
- "summary": "Get help information",
26
- "description": "Get help information",
27
- "params": {},
28
- "examples": []
29
- },
30
- "health": {
31
- "name": "health",
32
- "summary": "Check server health",
33
- "description": "Check server health",
34
- "params": {},
35
- "examples": []
36
- }
37
- }
38
-
39
- # Execute command
40
- command = HelpCommand()
41
- result = await command.execute()
42
-
43
- # Check result
44
- assert isinstance(result, HelpResult)
45
- assert result.commands_info is not None
46
- assert result.command_info is None
47
-
48
- # Check content
49
- commands_dict = result.to_dict()
50
- assert "commands" in commands_dict
51
- assert "help" in commands_dict["commands"]
52
- assert "health" in commands_dict["commands"]
53
- assert "summary" in commands_dict["commands"]["help"]
54
- assert "Get help information" in commands_dict["commands"]["help"]["summary"]
55
-
56
-
57
- async def test_help_command_with_cmdname(mock_registry):
58
- """Test help command with cmdname parameter."""
59
- # Setup mocks
60
- mock_registry.get_command_metadata.return_value = {
61
- "name": "health",
62
- "description": "Check server health",
63
- "summary": "Check server health",
64
- "params": {
65
- "check_type": {
66
- "type": "string",
67
- "description": "Type of health check",
68
- "required": False,
69
- "default": "basic"
70
- }
71
- },
72
- "examples": []
73
- }
74
-
75
- # Execute command
76
- command = HelpCommand()
77
- result = await command.execute(cmdname="health")
78
-
79
- # Check result
80
- assert isinstance(result, HelpResult)
81
- assert result.commands_info is None
82
- assert result.command_info is not None
83
-
84
- # Check content
85
- command_dict = result.to_dict()
86
- assert "cmdname" in command_dict
87
- assert command_dict["cmdname"] == "health"
88
- assert "info" in command_dict
89
- assert "description" in command_dict["info"]
90
- assert "Check server health" in command_dict["info"]["description"]
91
- assert "params" in command_dict["info"]
92
- assert "check_type" in command_dict["info"]["params"]
93
-
94
-
95
- async def test_help_command_with_invalid_cmdname(mock_registry):
96
- """Test help command with invalid cmdname parameter."""
97
- # Setup mocks
98
- mock_registry.get_command_metadata.side_effect = NotFoundError("Command not found")
99
-
100
- # Execute command and check result fields
101
- command = HelpCommand()
102
- result = await command.execute(cmdname="non_existent")
103
- result_dict = result.to_dict()
104
- assert "error" in result_dict
105
- assert "example" in result_dict
106
- assert "note" in result_dict
107
- assert result_dict["error"].startswith("Command")
108
- assert result_dict["example"]["command"] == "help"
109
-
110
-
111
- def test_help_result_schema():
112
- """Test help command result schema."""
113
- schema = HelpResult.get_schema()
114
-
115
- assert schema["type"] == "object"
116
- assert "oneOf" in schema
117
- assert len(schema["oneOf"]) == 2
118
-
119
- commands_schema = schema["oneOf"][0]
120
- assert "properties" in commands_schema
121
- assert "commands" in commands_schema["properties"]
122
-
123
- command_schema = schema["oneOf"][1]
124
- assert "properties" in command_schema
125
- assert "cmdname" in command_schema["properties"]
126
- assert "info" in command_schema["properties"]
127
-
128
-
129
- def test_help_command_schema():
130
- """Test help command schema."""
131
- schema = HelpCommand.get_schema()
132
-
133
- assert schema["type"] == "object"
134
- assert "properties" in schema
135
- assert "cmdname" in schema["properties"]
136
- assert schema["properties"]["cmdname"]["type"] == "string"
@@ -1,131 +0,0 @@
1
- """
2
- Module with fixtures and configuration for tests.
3
- """
4
-
5
- import json
6
- import os
7
- import tempfile
8
- from typing import Any, Dict, Generator
9
-
10
- import pytest
11
- from fastapi.testclient import TestClient
12
-
13
- from mcp_proxy_adapter.api.app import create_app
14
- from mcp_proxy_adapter.commands.command_registry import registry
15
- from mcp_proxy_adapter.config import Config
16
-
17
-
18
- @pytest.fixture
19
- def temp_config_file() -> Generator[str, None, None]:
20
- """
21
- Creates temporary configuration file for tests.
22
-
23
- Returns:
24
- Path to temporary configuration file.
25
- """
26
- # Create temporary file
27
- fd, path = tempfile.mkstemp(suffix=".json")
28
-
29
- # Write test configuration
30
- test_config = {
31
- "server": {
32
- "host": "127.0.0.1",
33
- "port": 8888
34
- },
35
- "logging": {
36
- "level": "DEBUG",
37
- "file": None
38
- },
39
- # Отключаем аутентификацию и ограничение скорости для тестов
40
- "auth_enabled": False,
41
- "rate_limit_enabled": False
42
- }
43
-
44
- with os.fdopen(fd, "w") as f:
45
- json.dump(test_config, f)
46
-
47
- yield path
48
-
49
- # Remove temporary file after tests
50
- os.unlink(path)
51
-
52
-
53
- @pytest.fixture
54
- def test_config(temp_config_file: str) -> Config:
55
- """
56
- Creates test configuration instance.
57
-
58
- Args:
59
- temp_config_file: Path to temporary configuration file.
60
-
61
- Returns:
62
- Test configuration instance.
63
- """
64
- return Config(temp_config_file)
65
-
66
-
67
- @pytest.fixture
68
- def test_client() -> TestClient:
69
- """
70
- Creates test client for FastAPI application.
71
-
72
- Returns:
73
- FastAPI test client.
74
- """
75
- app = create_app()
76
- return TestClient(app)
77
-
78
-
79
- @pytest.fixture
80
- def clean_registry() -> Generator[None, None, None]:
81
- """
82
- Cleans command registry before test and restores it after.
83
-
84
- Yields:
85
- None
86
- """
87
- # Save current commands
88
- original_commands = dict(registry._commands)
89
-
90
- # Clear registry
91
- registry.clear()
92
-
93
- yield
94
-
95
- # Restore registry
96
- registry.clear()
97
- for name, command in original_commands.items():
98
- registry._commands[name] = command
99
-
100
-
101
- @pytest.fixture
102
- def json_rpc_request() -> Dict[str, Any]:
103
- """
104
- Creates base JSON-RPC request.
105
-
106
- Returns:
107
- Dictionary with JSON-RPC request data.
108
- """
109
- return {
110
- "jsonrpc": "2.0",
111
- "method": "test_command",
112
- "params": {},
113
- "id": "test-id"
114
- }
115
-
116
-
117
- @pytest.fixture(autouse=True)
118
- def register_test_commands():
119
- """
120
- Регистрирует тестовые команды в registry для всех тестов.
121
- """
122
- from mcp_proxy_adapter.tests.stubs.echo_command import EchoCommand
123
- from mcp_proxy_adapter.commands.command_registry import registry
124
-
125
- # Регистрируем команды для тестирования
126
- registry.register(EchoCommand)
127
-
128
- yield
129
-
130
- # Очищаем registry после тестов
131
- registry.clear()
@@ -1,3 +0,0 @@
1
- """
2
- Functional tests for the mcp_microservice package.
3
- """