mcp-proxy-adapter 3.0.0__py3-none-any.whl → 3.0.2__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 (85) hide show
  1. examples/basic_example/README.md +123 -9
  2. examples/basic_example/config.json +4 -0
  3. examples/basic_example/docs/EN/README.md +46 -5
  4. examples/basic_example/docs/RU/README.md +46 -5
  5. examples/basic_example/server.py +127 -21
  6. examples/complete_example/commands/system_command.py +1 -0
  7. examples/complete_example/server.py +68 -40
  8. examples/minimal_example/README.md +20 -6
  9. examples/minimal_example/config.json +7 -14
  10. examples/minimal_example/main.py +109 -40
  11. examples/minimal_example/simple_server.py +53 -14
  12. examples/minimal_example/tests/conftest.py +1 -1
  13. examples/minimal_example/tests/test_integration.py +8 -10
  14. examples/simple_server.py +12 -21
  15. examples/test_server.py +22 -14
  16. examples/tool_description_example.py +82 -0
  17. mcp_proxy_adapter/api/__init__.py +0 -0
  18. mcp_proxy_adapter/api/app.py +391 -0
  19. mcp_proxy_adapter/api/handlers.py +229 -0
  20. mcp_proxy_adapter/api/middleware/__init__.py +49 -0
  21. mcp_proxy_adapter/api/middleware/auth.py +146 -0
  22. mcp_proxy_adapter/api/middleware/base.py +79 -0
  23. mcp_proxy_adapter/api/middleware/error_handling.py +198 -0
  24. mcp_proxy_adapter/api/middleware/logging.py +96 -0
  25. mcp_proxy_adapter/api/middleware/performance.py +83 -0
  26. mcp_proxy_adapter/api/middleware/rate_limit.py +152 -0
  27. mcp_proxy_adapter/api/schemas.py +305 -0
  28. mcp_proxy_adapter/api/tool_integration.py +223 -0
  29. mcp_proxy_adapter/api/tools.py +198 -0
  30. mcp_proxy_adapter/commands/__init__.py +19 -0
  31. mcp_proxy_adapter/commands/base.py +301 -0
  32. mcp_proxy_adapter/commands/command_registry.py +231 -0
  33. mcp_proxy_adapter/commands/config_command.py +113 -0
  34. mcp_proxy_adapter/commands/health_command.py +136 -0
  35. mcp_proxy_adapter/commands/help_command.py +193 -0
  36. mcp_proxy_adapter/commands/result.py +215 -0
  37. mcp_proxy_adapter/config.py +9 -0
  38. mcp_proxy_adapter/core/__init__.py +0 -0
  39. mcp_proxy_adapter/core/errors.py +173 -0
  40. mcp_proxy_adapter/core/logging.py +205 -0
  41. mcp_proxy_adapter/core/utils.py +138 -0
  42. mcp_proxy_adapter/custom_openapi.py +47 -10
  43. mcp_proxy_adapter/py.typed +0 -0
  44. mcp_proxy_adapter/schemas/base_schema.json +114 -0
  45. mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
  46. mcp_proxy_adapter/tests/__init__.py +0 -0
  47. mcp_proxy_adapter/tests/api/__init__.py +3 -0
  48. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +115 -0
  49. mcp_proxy_adapter/tests/api/test_middleware.py +336 -0
  50. mcp_proxy_adapter/tests/commands/__init__.py +3 -0
  51. mcp_proxy_adapter/tests/commands/test_config_command.py +211 -0
  52. mcp_proxy_adapter/tests/commands/test_echo_command.py +127 -0
  53. mcp_proxy_adapter/tests/commands/test_help_command.py +133 -0
  54. mcp_proxy_adapter/tests/conftest.py +131 -0
  55. mcp_proxy_adapter/tests/functional/__init__.py +3 -0
  56. mcp_proxy_adapter/tests/functional/test_api.py +253 -0
  57. mcp_proxy_adapter/tests/integration/__init__.py +3 -0
  58. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +130 -0
  59. mcp_proxy_adapter/tests/integration/test_integration.py +255 -0
  60. mcp_proxy_adapter/tests/performance/__init__.py +3 -0
  61. mcp_proxy_adapter/tests/performance/test_performance.py +189 -0
  62. mcp_proxy_adapter/tests/stubs/__init__.py +10 -0
  63. mcp_proxy_adapter/tests/stubs/echo_command.py +104 -0
  64. mcp_proxy_adapter/tests/test_api_endpoints.py +271 -0
  65. mcp_proxy_adapter/tests/test_api_handlers.py +289 -0
  66. mcp_proxy_adapter/tests/test_base_command.py +123 -0
  67. mcp_proxy_adapter/tests/test_batch_requests.py +117 -0
  68. mcp_proxy_adapter/tests/test_command_registry.py +245 -0
  69. mcp_proxy_adapter/tests/test_config.py +127 -0
  70. mcp_proxy_adapter/tests/test_utils.py +65 -0
  71. mcp_proxy_adapter/tests/unit/__init__.py +3 -0
  72. mcp_proxy_adapter/tests/unit/test_base_command.py +130 -0
  73. mcp_proxy_adapter/tests/unit/test_config.py +217 -0
  74. mcp_proxy_adapter/version.py +1 -1
  75. {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.2.dist-info}/METADATA +1 -1
  76. mcp_proxy_adapter-3.0.2.dist-info/RECORD +109 -0
  77. examples/basic_example/config.yaml +0 -20
  78. examples/basic_example/main.py +0 -50
  79. examples/complete_example/main.py +0 -67
  80. examples/minimal_example/config.yaml +0 -26
  81. mcp_proxy_adapter/framework.py +0 -109
  82. mcp_proxy_adapter-3.0.0.dist-info/RECORD +0 -58
  83. {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.2.dist-info}/WHEEL +0 -0
  84. {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.2.dist-info}/licenses/LICENSE +0 -0
  85. {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,130 @@
1
+ """
2
+ Integration tests for /cmd endpoint and help command.
3
+ """
4
+
5
+ import pytest
6
+ from fastapi.testclient import TestClient
7
+
8
+ from mcp_proxy_adapter.api.app import app
9
+ from mcp_proxy_adapter.commands.command_registry import registry
10
+ from mcp_proxy_adapter.commands.help_command import HelpCommand
11
+
12
+
13
+ @pytest.fixture(autouse=True)
14
+ def setup_registry():
15
+ """Setup command registry for tests."""
16
+ # Store original commands
17
+ original_commands = dict(registry._commands)
18
+
19
+ # Clear registry
20
+ registry._commands.clear()
21
+
22
+ # Register help command
23
+ registry.register(HelpCommand)
24
+
25
+ yield
26
+
27
+ # Restore original commands
28
+ registry._commands.clear()
29
+ for name, command in original_commands.items():
30
+ registry._commands[name] = command
31
+
32
+
33
+ @pytest.fixture
34
+ def client():
35
+ """Test client for FastAPI app."""
36
+ return TestClient(app)
37
+
38
+
39
+ def test_cmd_help_without_params(client):
40
+ """Test /cmd endpoint with help command without parameters."""
41
+ response = client.post(
42
+ "/cmd",
43
+ json={"command": "help"}
44
+ )
45
+
46
+ assert response.status_code == 200
47
+ assert "result" in response.json()
48
+ result = response.json()["result"]
49
+
50
+ assert "commands" in result
51
+ assert "help" in result["commands"]
52
+ assert "summary" in result["commands"]["help"]
53
+
54
+
55
+ def test_cmd_help_with_cmdname(client):
56
+ """Test /cmd endpoint with help command with cmdname parameter."""
57
+ response = client.post(
58
+ "/cmd",
59
+ json={
60
+ "command": "help",
61
+ "params": {
62
+ "cmdname": "help"
63
+ }
64
+ }
65
+ )
66
+
67
+ assert response.status_code == 200
68
+ assert "result" in response.json()
69
+ result = response.json()["result"]
70
+
71
+ assert "cmdname" in result
72
+ assert result["cmdname"] == "help"
73
+ assert "info" in result
74
+ assert "description" in result["info"]
75
+ assert "params" in result["info"]
76
+ assert "cmdname" in result["info"]["params"]
77
+
78
+
79
+ def test_cmd_help_unknown_command(client):
80
+ """Test /cmd endpoint with help command for unknown command."""
81
+ response = client.post(
82
+ "/cmd",
83
+ json={
84
+ "command": "help",
85
+ "params": {
86
+ "cmdname": "unknown_command"
87
+ }
88
+ }
89
+ )
90
+
91
+ assert response.status_code == 200
92
+ assert "result" in response.json()
93
+ result = response.json()["result"]
94
+
95
+ assert "success" in result and result["success"] is False
96
+ assert "error" in result
97
+ error = result["error"]
98
+
99
+ assert error["code"] == -32601
100
+ assert "not found" in error["message"]
101
+
102
+
103
+ def test_cmd_unknown_command(client):
104
+ """Test /cmd endpoint with unknown command."""
105
+ response = client.post(
106
+ "/cmd",
107
+ json={"command": "unknown_command"}
108
+ )
109
+
110
+ assert response.status_code == 200
111
+ assert "error" in response.json()
112
+ error = response.json()["error"]
113
+
114
+ assert error["code"] == -32601
115
+ assert "не найдена" in error["message"]
116
+
117
+
118
+ def test_cmd_invalid_request(client):
119
+ """Test /cmd endpoint with invalid request format."""
120
+ response = client.post(
121
+ "/cmd",
122
+ json={"invalid": "request"}
123
+ )
124
+
125
+ assert response.status_code == 200
126
+ assert "error" in response.json()
127
+ error = response.json()["error"]
128
+
129
+ assert error["code"] == -32600
130
+ assert "Отсутствует обязательное поле 'command'" in error["message"]
@@ -0,0 +1,255 @@
1
+ """
2
+ Integration tests for the mcp_microservice package.
3
+ """
4
+
5
+ import pytest
6
+ import json
7
+ from typing import Dict, Any
8
+
9
+ from fastapi.testclient import TestClient
10
+
11
+ from mcp_proxy_adapter.commands.command_registry import registry
12
+ from mcp_proxy_adapter.tests.stubs.echo_command import EchoCommand
13
+ from mcp_proxy_adapter.api.app import create_app
14
+ from mcp_proxy_adapter.config import Config
15
+
16
+
17
+ @pytest.fixture
18
+ def integration_config():
19
+ """
20
+ Fixture for integration test configuration.
21
+
22
+ Returns:
23
+ Config instance for integration tests.
24
+ """
25
+ config = Config()
26
+ # Загружаем тестовую конфигурацию
27
+ config._config = {
28
+ "server": {
29
+ "host": "127.0.0.1",
30
+ "port": 8889
31
+ },
32
+ "logging": {
33
+ "level": "DEBUG",
34
+ "file": None
35
+ },
36
+ "auth_enabled": False,
37
+ "rate_limit_enabled": False
38
+ }
39
+ return config
40
+
41
+
42
+ @pytest.fixture
43
+ def integration_app(integration_config):
44
+ """
45
+ Fixture for integration test application.
46
+
47
+ Args:
48
+ integration_config: Configuration for integration tests.
49
+
50
+ Returns:
51
+ FastAPI application instance.
52
+ """
53
+ return create_app()
54
+
55
+
56
+ @pytest.fixture
57
+ def integration_client(integration_app):
58
+ """
59
+ Fixture for integration test client.
60
+
61
+ Args:
62
+ integration_app: FastAPI application for integration tests.
63
+
64
+ Returns:
65
+ FastAPI test client.
66
+ """
67
+ return TestClient(integration_app)
68
+
69
+
70
+ @pytest.mark.integration
71
+ def test_command_registry_with_api(integration_client, clean_registry):
72
+ """
73
+ Test integration between command registry and API.
74
+
75
+ Args:
76
+ integration_client: FastAPI test client.
77
+ clean_registry: Fixture to clean registry before and after test.
78
+ """
79
+ # Register command
80
+ registry.register(EchoCommand)
81
+
82
+ # Create JSON-RPC request
83
+ request_data = {
84
+ "jsonrpc": "2.0",
85
+ "method": "echo",
86
+ "params": {"test_key": "test_value"},
87
+ "id": "test-id"
88
+ }
89
+
90
+ # Send request
91
+ response = integration_client.post("/api/jsonrpc", json=request_data)
92
+
93
+ # Check response
94
+ assert response.status_code == 200
95
+
96
+ # Check response structure
97
+ data = response.json()
98
+ assert "jsonrpc" in data and data["jsonrpc"] == "2.0"
99
+ assert "result" in data
100
+ assert "id" in data and data["id"] == request_data["id"]
101
+
102
+ # Check result content
103
+ assert "params" in data["result"]
104
+ assert data["result"]["params"] == {"test_key": "test_value"}
105
+
106
+ # Clean up
107
+ registry.clear()
108
+
109
+
110
+ @pytest.mark.integration
111
+ def test_command_execution_through_api(integration_client, clean_registry):
112
+ """
113
+ Test command execution through API with complex parameters.
114
+
115
+ Args:
116
+ integration_client: FastAPI test client.
117
+ clean_registry: Fixture to clean registry before and after test.
118
+ """
119
+ # Register command
120
+ registry.register(EchoCommand)
121
+
122
+ # Create JSON-RPC request with parameters
123
+ request_data = {
124
+ "jsonrpc": "2.0",
125
+ "method": "echo",
126
+ "params": {"complex_param": {"nested": "value", "array": [1, 2, 3]}},
127
+ "id": "test-id"
128
+ }
129
+
130
+ # Send request
131
+ response = integration_client.post("/api/jsonrpc", json=request_data)
132
+
133
+ # Check response
134
+ assert response.status_code == 200
135
+
136
+ # Check response content
137
+ data = response.json()
138
+ assert "params" in data["result"]
139
+ assert data["result"]["params"]["complex_param"]["nested"] == "value"
140
+ assert data["result"]["params"]["complex_param"]["array"] == [1, 2, 3]
141
+
142
+ # Clean up
143
+ registry.clear()
144
+
145
+
146
+ @pytest.mark.integration
147
+ def test_api_error_handling_with_command(integration_client, clean_registry):
148
+ """
149
+ Test API error handling with command errors.
150
+
151
+ Args:
152
+ integration_client: FastAPI test client.
153
+ clean_registry: Fixture to clean registry before and after test.
154
+ """
155
+ # Register command
156
+ registry.register(EchoCommand)
157
+
158
+ # Create JSON-RPC request with parameters
159
+ request_data = {
160
+ "jsonrpc": "2.0",
161
+ "method": "echo",
162
+ "params": {"test": "value"},
163
+ "id": "test-id"
164
+ }
165
+
166
+ # Send request
167
+ response = integration_client.post("/api/jsonrpc", json=request_data)
168
+
169
+ # Check response
170
+ assert response.status_code == 200
171
+
172
+ # Clean up
173
+ registry.clear()
174
+
175
+
176
+ @pytest.mark.integration
177
+ def test_api_commands_endpoint_with_registry(integration_client, clean_registry):
178
+ """
179
+ Test API commands endpoint with loaded registry.
180
+
181
+ Args:
182
+ integration_client: FastAPI test client.
183
+ clean_registry: Fixture to clean registry before and after test.
184
+ """
185
+ # Register command
186
+ registry.register(EchoCommand)
187
+
188
+ # Get commands list
189
+ response = integration_client.get("/api/commands")
190
+
191
+ # Check response
192
+ assert response.status_code == 200
193
+
194
+ # Check response structure
195
+ data = response.json()
196
+ assert "commands" in data
197
+ assert isinstance(data["commands"], dict)
198
+
199
+ # Check that echo command is in the list
200
+ assert "echo" in data["commands"]
201
+ assert "description" in data["commands"]["echo"]
202
+
203
+ # Clean up
204
+ registry.clear()
205
+
206
+
207
+ @pytest.mark.integration
208
+ def test_batch_requests_integration(integration_client, clean_registry):
209
+ """
210
+ Test batch requests processing.
211
+
212
+ Args:
213
+ integration_client: FastAPI test client.
214
+ clean_registry: Fixture to clean registry before and after test.
215
+ """
216
+ # Register command
217
+ registry.register(EchoCommand)
218
+
219
+ # Create batch request
220
+ batch_request = [
221
+ {
222
+ "jsonrpc": "2.0",
223
+ "method": "echo",
224
+ "params": {"request_id": "1"},
225
+ "id": "1"
226
+ },
227
+ {
228
+ "jsonrpc": "2.0",
229
+ "method": "echo",
230
+ "params": {"request_id": "2"},
231
+ "id": "2"
232
+ }
233
+ ]
234
+
235
+ # Send request
236
+ response = integration_client.post("/api/jsonrpc", json=batch_request)
237
+
238
+ # Check response
239
+ assert response.status_code == 200
240
+
241
+ # Check response structure
242
+ data = response.json()
243
+ assert isinstance(data, list)
244
+ assert len(data) == 2
245
+
246
+ # Check individual responses
247
+ for i, resp in enumerate(data):
248
+ assert "jsonrpc" in resp and resp["jsonrpc"] == "2.0"
249
+ assert "result" in resp
250
+ assert "params" in resp["result"]
251
+ assert resp["result"]["params"]["request_id"] == str(i + 1)
252
+ assert resp["id"] == str(i + 1)
253
+
254
+ # Clean up
255
+ registry.clear()
@@ -0,0 +1,3 @@
1
+ """
2
+ Performance tests for the mcp_microservice package.
3
+ """
@@ -0,0 +1,189 @@
1
+ """
2
+ Performance tests for the API.
3
+ """
4
+
5
+ import asyncio
6
+ import time
7
+ from typing import Dict, Any
8
+
9
+ import pytest
10
+ import pytest_asyncio
11
+ from fastapi.testclient import TestClient
12
+ from httpx import AsyncClient, ASGITransport
13
+
14
+ from mcp_proxy_adapter.api.app import create_app
15
+ from mcp_proxy_adapter.commands.command_registry import registry
16
+ from mcp_proxy_adapter.tests.stubs.echo_command import EchoCommand
17
+
18
+
19
+ @pytest_asyncio.fixture
20
+ async def async_client(test_config):
21
+ """
22
+ Fixture for async HTTP client.
23
+
24
+ Args:
25
+ test_config: Test configuration instance.
26
+
27
+ Returns:
28
+ AsyncClient instance for making async requests.
29
+ """
30
+ app = create_app()
31
+ transport = ASGITransport(app=app)
32
+ async with AsyncClient(transport=transport, base_url="http://test") as client:
33
+ yield client
34
+
35
+
36
+ @pytest.fixture
37
+ def register_echo_command(clean_registry):
38
+ """
39
+ Fixture to register the Echo command for testing.
40
+
41
+ Args:
42
+ clean_registry: Fixture to clean registry before and after test.
43
+ """
44
+ registry.register(EchoCommand)
45
+ yield
46
+ registry.clear()
47
+
48
+
49
+ @pytest.mark.performance
50
+ @pytest.mark.asyncio
51
+ async def test_sequential_requests(async_client: AsyncClient, json_rpc_request: Dict[str, Any],
52
+ register_echo_command):
53
+ """
54
+ Test sequential API requests performance.
55
+
56
+ Args:
57
+ async_client: Async HTTP client.
58
+ json_rpc_request: Base JSON-RPC request.
59
+ register_echo_command: Fixture to register test command.
60
+ """
61
+ num_requests = 50
62
+
63
+ # Create JSON-RPC request
64
+ request_data = json_rpc_request.copy()
65
+ request_data["method"] = "echo"
66
+ request_data["params"] = {"test": "value"}
67
+
68
+ # Measure execution time
69
+ start_time = time.time()
70
+
71
+ for i in range(num_requests):
72
+ response = await async_client.post("/api/jsonrpc", json=request_data)
73
+ assert response.status_code == 200
74
+
75
+ end_time = time.time()
76
+ total_time = end_time - start_time
77
+
78
+ # Calculate requests per second
79
+ rps = num_requests / total_time
80
+
81
+ print(f"Sequential requests: {num_requests} requests in {total_time:.2f}s ({rps:.2f} req/s)")
82
+
83
+ # Check that performance is within expected range
84
+ # This threshold should be adjusted based on actual performance measurements
85
+ assert rps > 30, f"Performance too low: {rps:.2f} req/s"
86
+
87
+
88
+ @pytest.mark.performance
89
+ @pytest.mark.asyncio
90
+ async def test_concurrent_requests(async_client: AsyncClient, json_rpc_request: Dict[str, Any],
91
+ register_echo_command):
92
+ """
93
+ Test concurrent API requests performance.
94
+
95
+ Args:
96
+ async_client: Async HTTP client.
97
+ json_rpc_request: Base JSON-RPC request.
98
+ register_echo_command: Fixture to register test command.
99
+ """
100
+ num_requests = 50
101
+
102
+ # Create JSON-RPC request
103
+ request_data = json_rpc_request.copy()
104
+ request_data["method"] = "echo"
105
+ request_data["params"] = {"test": "value"}
106
+
107
+ # Create task list
108
+ tasks = []
109
+ for i in range(num_requests):
110
+ task = asyncio.create_task(async_client.post("/api/jsonrpc", json=request_data))
111
+ tasks.append(task)
112
+
113
+ # Measure execution time
114
+ start_time = time.time()
115
+
116
+ # Wait for all tasks to complete
117
+ responses = await asyncio.gather(*tasks)
118
+
119
+ end_time = time.time()
120
+ total_time = end_time - start_time
121
+
122
+ # Check that all responses are successful
123
+ for response in responses:
124
+ assert response.status_code == 200
125
+
126
+ # Calculate requests per second
127
+ rps = num_requests / total_time
128
+
129
+ print(f"Concurrent requests: {num_requests} requests in {total_time:.2f}s ({rps:.2f} req/s)")
130
+
131
+ # Check that performance is within expected range
132
+ # This threshold should be adjusted based on actual performance measurements
133
+ assert rps > 100, f"Concurrent performance too low: {rps:.2f} req/s"
134
+
135
+
136
+ @pytest.mark.performance
137
+ @pytest.mark.asyncio
138
+ async def test_batch_requests_performance(async_client: AsyncClient, json_rpc_request: Dict[str, Any],
139
+ register_echo_command):
140
+ """
141
+ Test batch requests performance.
142
+
143
+ Args:
144
+ async_client: Async HTTP client.
145
+ json_rpc_request: Base JSON-RPC request.
146
+ register_echo_command: Fixture to register test command.
147
+ """
148
+ num_batches = 10
149
+ batch_size = 5
150
+
151
+ # Create base request
152
+ base_request = json_rpc_request.copy()
153
+ base_request["method"] = "echo"
154
+ base_request["params"] = {"test": "value"}
155
+
156
+ # Prepare batch requests
157
+ batch_requests = []
158
+ for i in range(num_batches):
159
+ batch = []
160
+ for j in range(batch_size):
161
+ request = base_request.copy()
162
+ request["id"] = f"batch-{i}-{j}"
163
+ batch.append(request)
164
+ batch_requests.append(batch)
165
+
166
+ # Measure execution time
167
+ start_time = time.time()
168
+
169
+ # Execute batch requests
170
+ for batch in batch_requests:
171
+ response = await async_client.post("/api/jsonrpc", json=batch)
172
+ assert response.status_code == 200
173
+
174
+ # Check response structure
175
+ data = response.json()
176
+ assert isinstance(data, list)
177
+ assert len(data) == batch_size
178
+
179
+ end_time = time.time()
180
+ total_time = end_time - start_time
181
+
182
+ # Calculate total requests and requests per second
183
+ total_requests = num_batches * batch_size
184
+ rps = total_requests / total_time
185
+
186
+ print(f"Batch requests: {total_requests} requests in {total_time:.2f}s ({rps:.2f} req/s)")
187
+
188
+ # Check that performance is within expected range
189
+ assert rps > 50, f"Batch performance too low: {rps:.2f} req/s"
@@ -0,0 +1,10 @@
1
+ """
2
+ Test stub modules for framework tests.
3
+ """
4
+
5
+ from mcp_proxy_adapter.tests.stubs.echo_command import EchoCommand, EchoResult
6
+
7
+ __all__ = [
8
+ "EchoCommand",
9
+ "EchoResult"
10
+ ]
@@ -0,0 +1,104 @@
1
+ """
2
+ Stub module for echo command tests.
3
+ """
4
+
5
+ from typing import Any, Dict, Optional, ClassVar, Type
6
+
7
+ from mcp_proxy_adapter.commands.base import Command
8
+ from mcp_proxy_adapter.core.logging import logger
9
+
10
+
11
+ class EchoResult:
12
+ """
13
+ Result of the echo command execution (stub for tests).
14
+ """
15
+
16
+ def __init__(self, params: Dict[str, Any] = None):
17
+ """
18
+ Initialize echo result.
19
+
20
+ Args:
21
+ params: Parameters to echo back.
22
+ """
23
+ self.params = params or {}
24
+
25
+ def to_dict(self) -> Dict[str, Any]:
26
+ """
27
+ Convert result to dictionary.
28
+
29
+ Returns:
30
+ Dict[str, Any]: Result as dictionary
31
+ """
32
+ return {"params": self.params}
33
+
34
+ @classmethod
35
+ def get_schema(cls) -> Dict[str, Any]:
36
+ """
37
+ Get JSON schema for result validation.
38
+
39
+ Returns:
40
+ Dict[str, Any]: JSON schema
41
+ """
42
+ return {
43
+ "type": "object",
44
+ "properties": {
45
+ "params": {
46
+ "type": "object",
47
+ "additionalProperties": True
48
+ }
49
+ },
50
+ "required": ["params"]
51
+ }
52
+
53
+ @classmethod
54
+ def from_dict(cls, data: Dict[str, Any]) -> "EchoResult":
55
+ """
56
+ Creates result instance from dictionary.
57
+
58
+ Args:
59
+ data: Dictionary with result data.
60
+
61
+ Returns:
62
+ EchoResult instance.
63
+ """
64
+ return cls(
65
+ params=data.get("params", {})
66
+ )
67
+
68
+
69
+ class EchoCommand(Command):
70
+ """
71
+ Test stub for echo command.
72
+ """
73
+
74
+ name: ClassVar[str] = "echo"
75
+ result_class: ClassVar[Type[EchoResult]] = EchoResult
76
+
77
+ @classmethod
78
+ def get_schema(cls) -> Dict[str, Any]:
79
+ """
80
+ Returns JSON schema for command parameters validation.
81
+
82
+ Returns:
83
+ Dictionary with JSON schema.
84
+ """
85
+ return {
86
+ "type": "object",
87
+ "additionalProperties": True,
88
+ "description": "Any parameters will be echoed back in the response"
89
+ }
90
+
91
+ async def execute(self, **kwargs) -> EchoResult:
92
+ """
93
+ Executes echo command and returns the parameters back.
94
+
95
+ Args:
96
+ **kwargs: Any parameters to echo back.
97
+
98
+ Returns:
99
+ EchoResult: Command execution result with the parameters.
100
+ """
101
+ logger.debug(f"Echo command received parameters: {kwargs}")
102
+
103
+ # Simply return the parameters that were passed
104
+ return EchoResult(params=kwargs)