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.
- mcp_proxy_adapter/__main__.py +32 -0
- mcp_proxy_adapter/api/app.py +290 -33
- mcp_proxy_adapter/api/handlers.py +32 -6
- mcp_proxy_adapter/api/middleware/__init__.py +38 -32
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
- mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
- mcp_proxy_adapter/api/middleware/factory.py +243 -0
- mcp_proxy_adapter/api/middleware/logging.py +32 -6
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +201 -0
- mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
- mcp_proxy_adapter/api/middleware/unified_security.py +197 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +158 -0
- mcp_proxy_adapter/commands/__init__.py +19 -4
- mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
- mcp_proxy_adapter/commands/base.py +66 -32
- mcp_proxy_adapter/commands/builtin_commands.py +95 -0
- mcp_proxy_adapter/commands/catalog_manager.py +838 -0
- mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
- mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
- mcp_proxy_adapter/commands/command_registry.py +711 -354
- mcp_proxy_adapter/commands/dependency_manager.py +245 -0
- mcp_proxy_adapter/commands/echo_command.py +81 -0
- mcp_proxy_adapter/commands/health_command.py +8 -1
- mcp_proxy_adapter/commands/help_command.py +21 -14
- mcp_proxy_adapter/commands/hooks.py +200 -167
- mcp_proxy_adapter/commands/key_management_command.py +506 -0
- mcp_proxy_adapter/commands/load_command.py +176 -0
- mcp_proxy_adapter/commands/plugins_command.py +235 -0
- mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
- mcp_proxy_adapter/commands/proxy_registration_command.py +409 -0
- mcp_proxy_adapter/commands/reload_command.py +48 -50
- mcp_proxy_adapter/commands/result.py +1 -0
- mcp_proxy_adapter/commands/role_test_command.py +141 -0
- mcp_proxy_adapter/commands/roles_management_command.py +697 -0
- mcp_proxy_adapter/commands/security_command.py +488 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +366 -0
- mcp_proxy_adapter/commands/token_management_command.py +529 -0
- mcp_proxy_adapter/commands/transport_management_command.py +144 -0
- mcp_proxy_adapter/commands/unload_command.py +158 -0
- mcp_proxy_adapter/config.py +394 -14
- mcp_proxy_adapter/core/app_factory.py +410 -0
- mcp_proxy_adapter/core/app_runner.py +272 -0
- mcp_proxy_adapter/core/auth_validator.py +606 -0
- mcp_proxy_adapter/core/certificate_utils.py +1045 -0
- mcp_proxy_adapter/core/client.py +574 -0
- mcp_proxy_adapter/core/client_manager.py +284 -0
- mcp_proxy_adapter/core/client_security.py +384 -0
- mcp_proxy_adapter/core/config_converter.py +405 -0
- mcp_proxy_adapter/core/config_validator.py +218 -0
- mcp_proxy_adapter/core/logging.py +19 -3
- mcp_proxy_adapter/core/mtls_asgi.py +156 -0
- mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
- mcp_proxy_adapter/core/protocol_manager.py +385 -0
- mcp_proxy_adapter/core/proxy_client.py +602 -0
- mcp_proxy_adapter/core/proxy_registration.py +522 -0
- mcp_proxy_adapter/core/role_utils.py +426 -0
- mcp_proxy_adapter/core/security_adapter.py +370 -0
- mcp_proxy_adapter/core/security_factory.py +239 -0
- mcp_proxy_adapter/core/security_integration.py +286 -0
- mcp_proxy_adapter/core/server_adapter.py +282 -0
- mcp_proxy_adapter/core/server_engine.py +270 -0
- mcp_proxy_adapter/core/settings.py +1 -0
- mcp_proxy_adapter/core/ssl_utils.py +234 -0
- mcp_proxy_adapter/core/transport_manager.py +292 -0
- mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
- mcp_proxy_adapter/custom_openapi.py +22 -11
- mcp_proxy_adapter/examples/__init__.py +13 -4
- mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
- mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/main.py +44 -0
- mcp_proxy_adapter/examples/commands/__init__.py +5 -0
- mcp_proxy_adapter/examples/create_certificates_simple.py +550 -0
- mcp_proxy_adapter/examples/debug_request_state.py +112 -0
- mcp_proxy_adapter/examples/debug_role_chain.py +158 -0
- mcp_proxy_adapter/examples/demo_client.py +275 -0
- mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
- mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
- mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
- mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +80 -0
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +90 -0
- mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +75 -0
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +71 -0
- mcp_proxy_adapter/examples/full_application/main.py +173 -0
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
- mcp_proxy_adapter/examples/generate_all_certificates.py +362 -0
- mcp_proxy_adapter/examples/generate_certificates.py +177 -0
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
- mcp_proxy_adapter/examples/generate_test_configs.py +331 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +334 -0
- mcp_proxy_adapter/examples/run_example.py +59 -0
- mcp_proxy_adapter/examples/run_full_test_suite.py +318 -0
- mcp_proxy_adapter/examples/run_proxy_server.py +146 -0
- mcp_proxy_adapter/examples/run_security_tests.py +544 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +247 -0
- mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
- mcp_proxy_adapter/examples/security_test_client.py +782 -0
- mcp_proxy_adapter/examples/setup_test_environment.py +328 -0
- mcp_proxy_adapter/examples/test_config.py +148 -0
- mcp_proxy_adapter/examples/test_config_generator.py +86 -0
- mcp_proxy_adapter/examples/test_examples.py +281 -0
- mcp_proxy_adapter/examples/universal_client.py +620 -0
- mcp_proxy_adapter/main.py +93 -0
- mcp_proxy_adapter/utils/config_generator.py +1008 -0
- mcp_proxy_adapter/version.py +5 -2
- mcp_proxy_adapter-6.0.1.dist-info/METADATA +679 -0
- mcp_proxy_adapter-6.0.1.dist-info/RECORD +140 -0
- mcp_proxy_adapter-6.0.1.dist-info/entry_points.txt +2 -0
- {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/licenses/LICENSE +2 -2
- mcp_proxy_adapter/api/middleware/auth.py +0 -146
- mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
- mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
- mcp_proxy_adapter/examples/README.md +0 -124
- mcp_proxy_adapter/examples/basic_server/README.md +0 -60
- mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
- mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
- mcp_proxy_adapter/examples/basic_server/config.json +0 -35
- mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
- mcp_proxy_adapter/examples/basic_server/server.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
- mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
- mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -250
- mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
- mcp_proxy_adapter/examples/custom_commands/config.json +0 -35
- mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
- mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
- mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
- mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
- mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
- mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
- mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
- mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
- mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
- mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/server.py +0 -228
- mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
- mcp_proxy_adapter/examples/deployment/README.md +0 -49
- mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
- mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
- mcp_proxy_adapter/examples/deployment/config.json +0 -29
- mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
- mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
- mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
- mcp_proxy_adapter/examples/deployment/run.sh +0 -43
- mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
- mcp_proxy_adapter/schemas/base_schema.json +0 -114
- mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
- mcp_proxy_adapter/tests/__init__.py +0 -0
- mcp_proxy_adapter/tests/api/__init__.py +0 -3
- mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
- mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
- mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
- mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
- mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
- mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
- mcp_proxy_adapter/tests/commands/__init__.py +0 -3
- mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
- mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
- mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
- mcp_proxy_adapter/tests/conftest.py +0 -131
- mcp_proxy_adapter/tests/functional/__init__.py +0 -3
- mcp_proxy_adapter/tests/functional/test_api.py +0 -253
- mcp_proxy_adapter/tests/integration/__init__.py +0 -3
- mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
- mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
- mcp_proxy_adapter/tests/performance/__init__.py +0 -3
- mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
- mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
- mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
- mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
- mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
- mcp_proxy_adapter/tests/test_base_command.py +0 -123
- mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
- mcp_proxy_adapter/tests/test_command_registry.py +0 -281
- mcp_proxy_adapter/tests/test_config.py +0 -127
- mcp_proxy_adapter/tests/test_utils.py +0 -65
- mcp_proxy_adapter/tests/unit/__init__.py +0 -3
- mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
- mcp_proxy_adapter/tests/unit/test_config.py +0 -217
- mcp_proxy_adapter-4.1.1.dist-info/METADATA +0 -200
- mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
- {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-4.1.1.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()
|