mcp-proxy-adapter 2.1.17__py3-none-any.whl → 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. examples/__init__.py +19 -0
  2. examples/anti_patterns/README.md +51 -0
  3. examples/anti_patterns/__init__.py +9 -0
  4. examples/anti_patterns/bad_design/README.md +72 -0
  5. examples/anti_patterns/bad_design/global_state.py +170 -0
  6. examples/anti_patterns/bad_design/monolithic_command.py +272 -0
  7. examples/basic_example/README.md +131 -0
  8. examples/basic_example/__init__.py +8 -0
  9. examples/basic_example/commands/__init__.py +5 -0
  10. examples/basic_example/commands/echo_command.py +95 -0
  11. examples/basic_example/commands/math_command.py +151 -0
  12. examples/basic_example/commands/time_command.py +152 -0
  13. examples/basic_example/config.json +21 -0
  14. examples/basic_example/config.yaml +20 -0
  15. examples/basic_example/docs/EN/README.md +136 -0
  16. examples/basic_example/docs/RU/README.md +136 -0
  17. examples/basic_example/main.py +50 -0
  18. examples/basic_example/server.py +45 -0
  19. examples/basic_example/tests/conftest.py +243 -0
  20. examples/commands/echo_command.py +52 -0
  21. examples/commands/echo_result.py +65 -0
  22. examples/commands/get_date_command.py +98 -0
  23. examples/commands/new_uuid4_command.py +91 -0
  24. examples/complete_example/Dockerfile +24 -0
  25. examples/complete_example/README.md +92 -0
  26. examples/complete_example/__init__.py +8 -0
  27. examples/complete_example/commands/__init__.py +5 -0
  28. examples/complete_example/commands/system_command.py +327 -0
  29. examples/complete_example/config.json +41 -0
  30. examples/complete_example/configs/config.dev.yaml +40 -0
  31. examples/complete_example/configs/config.docker.yaml +40 -0
  32. examples/complete_example/docker-compose.yml +35 -0
  33. examples/complete_example/main.py +67 -0
  34. examples/complete_example/requirements.txt +20 -0
  35. examples/complete_example/server.py +85 -0
  36. examples/minimal_example/README.md +51 -0
  37. examples/minimal_example/__init__.py +8 -0
  38. examples/minimal_example/config.json +21 -0
  39. examples/minimal_example/config.yaml +26 -0
  40. examples/minimal_example/main.py +67 -0
  41. examples/minimal_example/simple_server.py +124 -0
  42. examples/minimal_example/tests/conftest.py +171 -0
  43. examples/minimal_example/tests/test_hello_command.py +111 -0
  44. examples/minimal_example/tests/test_integration.py +183 -0
  45. examples/server.py +69 -0
  46. examples/simple_server.py +137 -0
  47. examples/test_server.py +126 -0
  48. mcp_proxy_adapter/__init__.py +33 -1
  49. mcp_proxy_adapter/config.py +186 -0
  50. mcp_proxy_adapter/custom_openapi.py +125 -0
  51. mcp_proxy_adapter/framework.py +109 -0
  52. mcp_proxy_adapter/openapi.py +403 -0
  53. mcp_proxy_adapter/version.py +3 -0
  54. mcp_proxy_adapter-3.0.0.dist-info/METADATA +200 -0
  55. mcp_proxy_adapter-3.0.0.dist-info/RECORD +58 -0
  56. {mcp_proxy_adapter-2.1.17.dist-info → mcp_proxy_adapter-3.0.0.dist-info}/top_level.txt +1 -0
  57. mcp_proxy_adapter/adapter.py +0 -697
  58. mcp_proxy_adapter/analyzers/__init__.py +0 -1
  59. mcp_proxy_adapter/analyzers/docstring_analyzer.py +0 -199
  60. mcp_proxy_adapter/analyzers/type_analyzer.py +0 -151
  61. mcp_proxy_adapter/dispatchers/__init__.py +0 -1
  62. mcp_proxy_adapter/dispatchers/base_dispatcher.py +0 -85
  63. mcp_proxy_adapter/dispatchers/json_rpc_dispatcher.py +0 -262
  64. mcp_proxy_adapter/examples/analyze_config.py +0 -141
  65. mcp_proxy_adapter/examples/basic_integration.py +0 -155
  66. mcp_proxy_adapter/examples/docstring_and_schema_example.py +0 -69
  67. mcp_proxy_adapter/examples/extension_example.py +0 -72
  68. mcp_proxy_adapter/examples/help_best_practices.py +0 -67
  69. mcp_proxy_adapter/examples/help_usage.py +0 -64
  70. mcp_proxy_adapter/examples/mcp_proxy_client.py +0 -131
  71. mcp_proxy_adapter/examples/openapi_server.py +0 -383
  72. mcp_proxy_adapter/examples/project_structure_example.py +0 -47
  73. mcp_proxy_adapter/examples/testing_example.py +0 -64
  74. mcp_proxy_adapter/models.py +0 -47
  75. mcp_proxy_adapter/registry.py +0 -439
  76. mcp_proxy_adapter/schema.py +0 -257
  77. mcp_proxy_adapter/testing_utils.py +0 -112
  78. mcp_proxy_adapter/validators/__init__.py +0 -1
  79. mcp_proxy_adapter/validators/docstring_validator.py +0 -75
  80. mcp_proxy_adapter/validators/metadata_validator.py +0 -76
  81. mcp_proxy_adapter-2.1.17.dist-info/METADATA +0 -376
  82. mcp_proxy_adapter-2.1.17.dist-info/RECORD +0 -30
  83. {mcp_proxy_adapter-2.1.17.dist-info → mcp_proxy_adapter-3.0.0.dist-info}/WHEEL +0 -0
  84. {mcp_proxy_adapter-2.1.17.dist-info → mcp_proxy_adapter-3.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,403 @@
1
+ """
2
+ OpenAPI schema generator for MCP Microservice
3
+ """
4
+ from typing import Dict, Any, List, Optional
5
+ from dataclasses import dataclass
6
+ import inspect
7
+ import json
8
+ from pathlib import Path
9
+
10
+ from .registry import CommandRegistry, Command
11
+ from .exceptions import SchemaValidationError
12
+
13
+
14
+ @dataclass
15
+ class TypeInfo:
16
+ """Information about a type for OpenAPI schema"""
17
+ openapi_type: str
18
+ format: Optional[str] = None
19
+ items: Optional[Dict[str, Any]] = None
20
+ properties: Optional[Dict[str, Any]] = None
21
+ required: Optional[List[str]] = None
22
+
23
+
24
+ class OpenApiGenerator:
25
+ """Generates OpenAPI schema for MCP Microservice"""
26
+
27
+ PYTHON_TO_OPENAPI_TYPES = {
28
+ str: TypeInfo("string"),
29
+ int: TypeInfo("integer", "int64"),
30
+ float: TypeInfo("number", "float"),
31
+ bool: TypeInfo("boolean"),
32
+ list: TypeInfo("array"),
33
+ dict: TypeInfo("object"),
34
+ None: TypeInfo("null"),
35
+ }
36
+
37
+ def __init__(self, registry: CommandRegistry):
38
+ """
39
+ Initialize generator
40
+
41
+ Args:
42
+ registry: Command registry instance
43
+ """
44
+ self.registry = registry
45
+ self._base_schema = self._load_base_schema()
46
+
47
+ def _load_base_schema(self) -> Dict[str, Any]:
48
+ """Load base schema from file"""
49
+ schema_path = Path(__file__).parent / "schemas" / "base_schema.json"
50
+ with open(schema_path) as f:
51
+ return json.load(f)
52
+
53
+ def _get_type_info(self, python_type: Any) -> TypeInfo:
54
+ """
55
+ Get OpenAPI type info for Python type
56
+
57
+ Args:
58
+ python_type: Python type annotation
59
+
60
+ Returns:
61
+ TypeInfo object with OpenAPI type information
62
+ """
63
+ # Handle Optional types
64
+ origin = getattr(python_type, "__origin__", None)
65
+ if origin is Optional:
66
+ return self._get_type_info(python_type.__args__[0])
67
+
68
+ # Handle List and Dict
69
+ if origin is list:
70
+ item_type = self._get_type_info(python_type.__args__[0])
71
+ return TypeInfo("array", items={"type": item_type.openapi_type})
72
+
73
+ if origin is dict:
74
+ return TypeInfo("object", additionalProperties=True)
75
+
76
+ # Handle basic types
77
+ if python_type in self.PYTHON_TO_OPENAPI_TYPES:
78
+ return self.PYTHON_TO_OPENAPI_TYPES[python_type]
79
+
80
+ # Handle custom classes
81
+ if inspect.isclass(python_type):
82
+ properties = {}
83
+ required = []
84
+
85
+ for name, field in inspect.get_annotations(python_type).items():
86
+ field_info = self._get_type_info(field)
87
+ properties[name] = {
88
+ "type": field_info.openapi_type
89
+ }
90
+ if field_info.format:
91
+ properties[name]["format"] = field_info.format
92
+ required.append(name)
93
+
94
+ return TypeInfo(
95
+ "object",
96
+ properties=properties,
97
+ required=required
98
+ )
99
+
100
+ raise ValueError(f"Unsupported type: {python_type}")
101
+
102
+ def _add_command_params(self, schema: Dict[str, Any], command: Command):
103
+ """
104
+ Add command parameters to schema
105
+
106
+ Args:
107
+ schema: OpenAPI schema
108
+ command: Command instance
109
+ """
110
+ params = {}
111
+ required = []
112
+
113
+ # Get parameters from function signature
114
+ sig = inspect.signature(command.func)
115
+ for name, param in sig.parameters.items():
116
+ param_schema = {}
117
+
118
+ # Get type info
119
+ type_info = self._get_type_info(param.annotation)
120
+ param_schema["type"] = type_info.openapi_type
121
+
122
+ if type_info.format:
123
+ param_schema["format"] = type_info.format
124
+
125
+ if type_info.items:
126
+ param_schema["items"] = type_info.items
127
+
128
+ # Get description from docstring
129
+ if command.doc and command.doc.params:
130
+ for doc_param in command.doc.params:
131
+ if doc_param.arg_name == name:
132
+ param_schema["description"] = doc_param.description
133
+ break
134
+
135
+ # Handle default value
136
+ if param.default is not param.empty:
137
+ param_schema["default"] = param.default
138
+ else:
139
+ required.append(name)
140
+
141
+ params[name] = param_schema
142
+
143
+ # Add to schema
144
+ method_schema = {
145
+ "type": "object",
146
+ "properties": params
147
+ }
148
+ if required:
149
+ method_schema["required"] = required
150
+
151
+ schema["components"]["schemas"][f"Params{command.name}"] = method_schema
152
+
153
+ def _add_commands_to_schema(self, schema: Dict[str, Any]):
154
+ """
155
+ Add all commands to schema
156
+
157
+ Args:
158
+ schema: OpenAPI schema
159
+ """
160
+ for command in self.registry.get_commands():
161
+ self._add_command_params(schema, command)
162
+
163
+ def _add_cmd_endpoint(self, schema: Dict[str, Any]) -> None:
164
+ """
165
+ Add /cmd endpoint to OpenAPI schema.
166
+
167
+ Args:
168
+ schema: OpenAPI schema to update
169
+ """
170
+ schema["paths"]["/cmd"] = {
171
+ "post": {
172
+ "summary": "Execute command",
173
+ "description": "Universal endpoint for executing any command",
174
+ "operationId": "execute_command",
175
+ "requestBody": {
176
+ "content": {
177
+ "application/json": {
178
+ "schema": {"$ref": "#/components/schemas/CommandRequest"}
179
+ }
180
+ },
181
+ "required": True
182
+ },
183
+ "responses": {
184
+ "200": {
185
+ "description": "Command execution result",
186
+ "content": {
187
+ "application/json": {
188
+ "schema": {
189
+ "oneOf": [
190
+ {"$ref": "#/components/schemas/CommandSuccessResponse"},
191
+ {"$ref": "#/components/schemas/CommandErrorResponse"}
192
+ ]
193
+ }
194
+ }
195
+ }
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+ def _add_cmd_models(self, schema: Dict[str, Any]) -> None:
202
+ """
203
+ Add models for /cmd endpoint to OpenAPI schema.
204
+
205
+ Args:
206
+ schema: OpenAPI schema to update
207
+ """
208
+ # Add command request model
209
+ schema["components"]["schemas"]["CommandRequest"] = {
210
+ "type": "object",
211
+ "required": ["command"],
212
+ "properties": {
213
+ "command": {
214
+ "type": "string",
215
+ "description": "Command name to execute"
216
+ },
217
+ "params": {
218
+ "type": "object",
219
+ "description": "Command parameters (specific to command)",
220
+ "additionalProperties": True
221
+ }
222
+ }
223
+ }
224
+
225
+ # Add command success response model
226
+ schema["components"]["schemas"]["CommandSuccessResponse"] = {
227
+ "type": "object",
228
+ "required": ["result"],
229
+ "properties": {
230
+ "result": {
231
+ "type": "object",
232
+ "description": "Command execution result",
233
+ "additionalProperties": True
234
+ }
235
+ }
236
+ }
237
+
238
+ # Add command error response model
239
+ schema["components"]["schemas"]["CommandErrorResponse"] = {
240
+ "type": "object",
241
+ "required": ["error"],
242
+ "properties": {
243
+ "error": {
244
+ "type": "object",
245
+ "required": ["code", "message"],
246
+ "properties": {
247
+ "code": {
248
+ "type": "integer",
249
+ "description": "Error code"
250
+ },
251
+ "message": {
252
+ "type": "string",
253
+ "description": "Error message"
254
+ },
255
+ "data": {
256
+ "type": "object",
257
+ "description": "Additional error data",
258
+ "additionalProperties": True
259
+ }
260
+ }
261
+ }
262
+ }
263
+ }
264
+
265
+ def _add_cmd_examples(self, schema: Dict[str, Any]) -> None:
266
+ """
267
+ Add examples for /cmd endpoint to OpenAPI schema.
268
+
269
+ Args:
270
+ schema: OpenAPI schema to update
271
+ """
272
+ # Create examples section if it doesn't exist
273
+ if "examples" not in schema["components"]:
274
+ schema["components"]["examples"] = {}
275
+
276
+ # Add help command example request
277
+ schema["components"]["examples"]["help_request"] = {
278
+ "summary": "Get list of commands",
279
+ "value": {
280
+ "command": "help"
281
+ }
282
+ }
283
+
284
+ # Add help command example response
285
+ schema["components"]["examples"]["help_response"] = {
286
+ "summary": "Response with list of commands",
287
+ "value": {
288
+ "result": {
289
+ "commands": {
290
+ "help": {
291
+ "description": "Get help information about available commands"
292
+ },
293
+ "health": {
294
+ "description": "Check server health"
295
+ }
296
+ }
297
+ }
298
+ }
299
+ }
300
+
301
+ # Add specific command help example request
302
+ schema["components"]["examples"]["help_specific_request"] = {
303
+ "summary": "Get information about specific command",
304
+ "value": {
305
+ "command": "help",
306
+ "params": {
307
+ "cmdname": "health"
308
+ }
309
+ }
310
+ }
311
+
312
+ # Add error example
313
+ schema["components"]["examples"]["command_error"] = {
314
+ "summary": "Command not found error",
315
+ "value": {
316
+ "error": {
317
+ "code": -32601,
318
+ "message": "Command 'unknown_command' not found"
319
+ }
320
+ }
321
+ }
322
+
323
+ # Link examples to endpoint
324
+ schema["paths"]["/cmd"]["post"]["requestBody"]["content"]["application/json"]["examples"] = {
325
+ "help": {"$ref": "#/components/examples/help_request"},
326
+ "help_specific": {"$ref": "#/components/examples/help_specific_request"}
327
+ }
328
+
329
+ schema["paths"]["/cmd"]["post"]["responses"]["200"]["content"]["application/json"]["examples"] = {
330
+ "help": {"$ref": "#/components/examples/help_response"},
331
+ "error": {"$ref": "#/components/examples/command_error"}
332
+ }
333
+
334
+ def _validate_required_paths(self, schema: Dict[str, Any]) -> None:
335
+ """
336
+ Validate that required paths exist in schema.
337
+
338
+ Args:
339
+ schema: OpenAPI schema to validate
340
+
341
+ Raises:
342
+ SchemaValidationError: If required paths are missing
343
+ """
344
+ required_paths = ['/cmd', '/api/commands']
345
+
346
+ for path in required_paths:
347
+ if path not in schema['paths']:
348
+ raise SchemaValidationError(f"Missing required path: {path}")
349
+
350
+ def generate(self) -> Dict[str, Any]:
351
+ """
352
+ Generate complete OpenAPI schema
353
+
354
+ Returns:
355
+ OpenAPI schema as dictionary
356
+ """
357
+ schema = self._base_schema.copy()
358
+
359
+ # Add commands to schema
360
+ self._add_commands_to_schema(schema)
361
+
362
+ # Add /cmd endpoint regardless of commands
363
+ self._add_cmd_endpoint(schema)
364
+ self._add_cmd_models(schema)
365
+ self._add_cmd_examples(schema)
366
+
367
+ # Validate required paths
368
+ self._validate_required_paths(schema)
369
+
370
+ self.validate_schema(schema)
371
+ return schema
372
+
373
+ def validate_schema(self, schema: Dict[str, Any]):
374
+ """
375
+ Validate generated schema
376
+
377
+ Args:
378
+ schema: OpenAPI schema to validate
379
+
380
+ Raises:
381
+ SchemaValidationError: If schema is invalid
382
+ """
383
+ try:
384
+ # Check that required components exist
385
+ required_components = ['CommandRequest', 'CommandSuccessResponse', 'CommandErrorResponse']
386
+ for component in required_components:
387
+ if component not in schema['components']['schemas']:
388
+ raise SchemaValidationError(f"Missing required component: {component}")
389
+
390
+ # Validate that all paths return 200 status
391
+ for path in schema['paths'].values():
392
+ for method in path.values():
393
+ if '200' not in method['responses']:
394
+ raise SchemaValidationError("All endpoints must return 200 status code")
395
+
396
+ response = method['responses']['200']
397
+ if 'application/json' not in response['content']:
398
+ raise SchemaValidationError("All responses must be application/json")
399
+ except Exception as e:
400
+ raise SchemaValidationError(f"Schema validation failed: {str(e)}")
401
+
402
+ # Here we would normally use a library like openapi-spec-validator
403
+ # to validate the schema against the OpenAPI 3.0 specification
@@ -0,0 +1,3 @@
1
+ """Version information for MCP Microservice."""
2
+
3
+ __version__ = "3.0.0"
@@ -0,0 +1,200 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp_proxy_adapter
3
+ Version: 3.0.0
4
+ Summary: Reliable microservice with unified JSON-RPC endpoint
5
+ Home-page: https://github.com/yourusername/mcp-proxy-adapter
6
+ Author: MCP Team
7
+ Author-email: Vasiliy Zubarev <vasiliy.zubarev@example.com>
8
+ License: MIT License
9
+
10
+ Copyright (c) 2023-2024 Vasiliy VZ
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+ Project-URL: Documentation, https://github.com/maverikod/vvz-mcp-proxy-adapter/tree/main/docs/RU/README.md
30
+ Project-URL: Source, https://github.com/maverikod/vvz-mcp-proxy-adapter
31
+ Project-URL: Bug Reports, https://github.com/maverikod/vvz-mcp-proxy-adapter/issues
32
+ Classifier: Programming Language :: Python :: 3
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Operating System :: OS Independent
35
+ Classifier: Framework :: FastAPI
36
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
37
+ Classifier: Intended Audience :: Developers
38
+ Requires-Python: >=3.9
39
+ Description-Content-Type: text/markdown
40
+ License-File: LICENSE
41
+ Requires-Dist: fastapi<1.0.0,>=0.95.0
42
+ Requires-Dist: pydantic>=2.0.0
43
+ Requires-Dist: uvicorn<1.0.0,>=0.22.0
44
+ Requires-Dist: docstring-parser<1.0.0,>=0.15
45
+ Requires-Dist: typing-extensions<5.0.0,>=4.5.0
46
+ Requires-Dist: jsonrpc>=1.2.0
47
+ Requires-Dist: psutil>=5.9.0
48
+ Dynamic: author
49
+ Dynamic: home-page
50
+ Dynamic: license-file
51
+ Dynamic: requires-python
52
+
53
+ # MCP Proxy Adapter
54
+
55
+ **MCP Proxy Adapter** - это фреймворк для создания микросервисов на основе JSON-RPC. Он предоставляет базовую инфраструктуру для создания команд, обработки запросов и возвращения ответов через JSON-RPC API.
56
+
57
+ **MCP Proxy Adapter** - это фреймворк для создания микросервисов на основе JSON-RPC. Он предоставляет базовую инфраструктуру для создания команд, обработки запросов и возвращения ответов через JSON-RPC API.
58
+
59
+ ## Установка
60
+
61
+ ```bash
62
+ pip install mcp-proxy-adapter
63
+ ```
64
+
65
+ ## Использование
66
+
67
+ 1. Создайте свой проект и установите зависимость:
68
+
69
+ ```bash
70
+ pip install mcp-proxy-adapter
71
+ ```
72
+
73
+ 2. Создайте свои команды:
74
+
75
+ ```python
76
+ from mcp_proxy_adapter.commands.base import Command
77
+ from mcp_proxy_adapter.commands.result import SuccessResult
78
+
79
+ class YourCommand(Command):
80
+ name = "your_command"
81
+
82
+ async def execute(self, param1: str, param2: int = 0) -> SuccessResult:
83
+ # Ваша логика
84
+ result_data = {"param1": param1, "param2": param2}
85
+ return SuccessResult(data=result_data)
86
+ ```
87
+
88
+ 3. Запустите сервер:
89
+
90
+ ```python
91
+ import uvicorn
92
+ from mcp_proxy_adapter.api.app import create_app
93
+
94
+ # Регистрация ваших команд происходит автоматически
95
+ app = create_app()
96
+
97
+ uvicorn.run(app, host="0.0.0.0", port=8000)
98
+ ```
99
+
100
+ ## Структура проекта
101
+
102
+ Проект представляет собой фреймворк с базовой инфраструктурой:
103
+
104
+ * **mcp_proxy_adapter/** - основной модуль фреймворка
105
+ * **api/** - модуль API
106
+ * **commands/** - базовые классы команд
107
+ * **core/** - ядро фреймворка
108
+ * **schemas/** - JSON-схемы
109
+ * **examples/** - примеры использования фреймворка
110
+ * **basic_example/** - базовый пример
111
+ * **minimal_example/** - минимальный пример
112
+ * **complete_example/** - полный пример с Docker
113
+
114
+ ## Базовые команды
115
+
116
+ Фреймворк включает следующие базовые команды:
117
+
118
+ - `help` - получение справки по доступным командам
119
+ - `health` - проверка состояния сервиса
120
+
121
+ ## API
122
+
123
+ Фреймворк предоставляет следующие эндпоинты:
124
+
125
+ - `POST /api/jsonrpc` - основной JSON-RPC эндпоинт для выполнения команд
126
+ - `POST /api/command/{command_name}` - REST эндпоинт для выполнения конкретной команды
127
+ - `GET /api/commands` - получение списка доступных команд
128
+ - `GET /api/commands/{command_name}` - получение информации о конкретной команде
129
+ - `GET /health` - проверка состояния сервиса
130
+
131
+ ## Запуск примеров
132
+
133
+ ```bash
134
+ # Базовый пример
135
+ cd examples/basic_example
136
+ python main.py
137
+
138
+ # Минимальный пример
139
+ cd examples/minimal_example
140
+ python main.py
141
+
142
+ # Полный пример с Docker
143
+ cd examples/complete_example
144
+ docker-compose up -d
145
+ ```
146
+
147
+ ## Создание новой команды
148
+
149
+ Пример создания новой команды:
150
+
151
+ ```python
152
+ from typing import Dict, Any, ClassVar, Type
153
+ from mcp_proxy_adapter.commands.base import Command
154
+ from mcp_proxy_adapter.commands.result import SuccessResult
155
+
156
+ class CustomResult(SuccessResult):
157
+ """
158
+ Пользовательский класс результата.
159
+ """
160
+
161
+ def __init__(self, value: str):
162
+ super().__init__(data={"value": value})
163
+
164
+ @classmethod
165
+ def get_schema(cls) -> Dict[str, Any]:
166
+ return {
167
+ "type": "object",
168
+ "properties": {
169
+ "data": {
170
+ "type": "object",
171
+ "properties": {
172
+ "value": {"type": "string"}
173
+ },
174
+ "required": ["value"]
175
+ }
176
+ },
177
+ "required": ["data"]
178
+ }
179
+
180
+ class CustomCommand(Command):
181
+ """
182
+ Пользовательская команда.
183
+ """
184
+
185
+ name: ClassVar[str] = "custom"
186
+ result_class: ClassVar[Type[SuccessResult]] = CustomResult
187
+
188
+ async def execute(self, input_text: str) -> CustomResult:
189
+ return CustomResult(value=f"Processed: {input_text}")
190
+
191
+ @classmethod
192
+ def get_schema(cls) -> Dict[str, Any]:
193
+ return {
194
+ "type": "object",
195
+ "properties": {
196
+ "input_text": {"type": "string"}
197
+ },
198
+ "required": ["input_text"],
199
+ "additionalProperties": False
200
+ }
@@ -0,0 +1,58 @@
1
+ examples/__init__.py,sha256=sLYNpeoiE-X5q7fmJb7NFMmhiIn0543mgJj16q1qmk0,593
2
+ examples/server.py,sha256=gnRTE_k7C0A255dLyaJWyA4YU0H6Elc7osr_JQvsQhQ,2286
3
+ examples/simple_server.py,sha256=WzsX66Nq8pC3G2yEZ1FeXV5mW5gmeSKoQn4_yZkcF20,4104
4
+ examples/test_server.py,sha256=Uj6aNKQRmhTfsou6Rbye8ZU6wwKZCDZbatNvb5B1X1E,3485
5
+ examples/anti_patterns/README.md,sha256=1-Hby6Wf3kAC0XOV_jOvuHL-kmTypWOUfE_rEU3Knu8,2045
6
+ examples/anti_patterns/__init__.py,sha256=xbgoTIMM2LNt4P8h0jTaenUxXkA_l9I7JL_9d4BhoDU,261
7
+ examples/anti_patterns/bad_design/README.md,sha256=SJDMXZfvNMajN0JyvPBm5GtzxyiZZdtMfHslW3-LOII,2422
8
+ examples/anti_patterns/bad_design/global_state.py,sha256=UnpMCWDfl-DaZSPhWl8C9fGifXkG_sYKhjx3_HvTiSI,5161
9
+ examples/anti_patterns/bad_design/monolithic_command.py,sha256=gdp1Ok4h4dKto7nfJmhjoWTtjdCfwI-MtcKpn6il7Yo,8815
10
+ examples/basic_example/README.md,sha256=8MuXrDPawcPhot4srYzoMCBG2NPOzaWbSTpqfIFvf_I,4207
11
+ examples/basic_example/__init__.py,sha256=SXYCM5mPlVpEMdahhukXSYVepNiPNddhgypwAlhJjDU,191
12
+ examples/basic_example/config.json,sha256=ImV2B2X2r0jvchVvGDineO9GXPL0I3FBmp1hUhu6hfw,356
13
+ examples/basic_example/config.yaml,sha256=6Ct93uj5helKQW5z4D6Z5ur83PBz6c_LOO_UHMQM3f4,600
14
+ examples/basic_example/main.py,sha256=1ipCAgbLBCxSKBloW9AmEgBb_Gmq06_o2cUsMB4_3ec,1574
15
+ examples/basic_example/server.py,sha256=HuokZRD0kP1yvjtizQbBsFVXKCUIw61jpGjzsajy7TI,1200
16
+ examples/basic_example/commands/__init__.py,sha256=jD5tBWpkxH1Yk9kBHS_V3bBIMxwqqY4skr7RGuRru9s,115
17
+ examples/basic_example/commands/echo_command.py,sha256=EoXMHEf5ouKjvxvZAEiNH6hqyD6ktyyEDWYP-6Oa2D4,2128
18
+ examples/basic_example/commands/math_command.py,sha256=apJuU5EXlR965rGmAd2h8zcPWgLUSROtPeZ7Ml0H6nw,4423
19
+ examples/basic_example/commands/time_command.py,sha256=REw-8RCgq9iVUdQxnIFPmeYO_9_6-7QVLzLKLGq0Lb0,4345
20
+ examples/basic_example/docs/EN/README.md,sha256=yVn9WDJ5kk894WV-HSetSTslP98e1sZpfx2vdP2PXUk,3401
21
+ examples/basic_example/docs/RU/README.md,sha256=Ad3S2z6E8NbYVThFOmCywyHwhT1U0nY7ahtD-IhlEqE,4680
22
+ examples/basic_example/tests/conftest.py,sha256=6e85QRE50P9PMV1RXXVgtBQxy49hVLbevZ6dHFBrxRU,5917
23
+ examples/commands/echo_command.py,sha256=7RuUZfP0YlKl9gks02NiuiYEiiNPa_8lk9CAZmzijyo,1569
24
+ examples/commands/echo_result.py,sha256=q5IUEeFoi4PunzOhYD0zju2ZwETdGl35yj4DVXZfX68,1635
25
+ examples/commands/get_date_command.py,sha256=ePQzZCV-n3tLf4IYv6Gn75t0AXXplXtikCDmrIMD2Q4,2537
26
+ examples/commands/new_uuid4_command.py,sha256=lJQiPuVHtKCnOEUQukji6dwe0VOkddJ7sZXZ7XUsY6Y,2240
27
+ examples/complete_example/Dockerfile,sha256=MpwyUpA2wMeLtEVQ2ay98z-l8EX5aEFvwUSxZCCxg64,499
28
+ examples/complete_example/README.md,sha256=EupIC8DhC7dVsObbXjuERpwheVzfLR2i0y3LzCRHLYs,2784
29
+ examples/complete_example/__init__.py,sha256=JQDNMNOrQAvbQyEV7tV3XrVKBxZRYy3ODMCVyOxU404,216
30
+ examples/complete_example/config.json,sha256=KbfZnu4SMYH6B7ENQaZ_sZXrWdkmCdMcWgy47nAHh_Q,814
31
+ examples/complete_example/docker-compose.yml,sha256=kBXjXFeswZCZ4-UhI0vC0OMR_nMRRoDt3PltCi-RGb8,924
32
+ examples/complete_example/main.py,sha256=cVXHRuk_qGlnzne2_qix43PmnyM1GUb10NPSNqPgxpA,2239
33
+ examples/complete_example/requirements.txt,sha256=QHeMbXMHgkISmFoXfO09kiaXAMkg0nNBdCfwThKiHDc,403
34
+ examples/complete_example/server.py,sha256=dChcKg_-4BHkrXCocc8GD90Qpb2gC7JK5MBO9UFtuk8,2195
35
+ examples/complete_example/commands/__init__.py,sha256=cZDiwz3nLaeSCwR4oK7xlGgVsXt2WyAlIEMWCxSJPAE,121
36
+ examples/complete_example/commands/system_command.py,sha256=BUu4HxJka77BR5WgxTdkbaLM2NStctgSAesjQPz5_Z8,10703
37
+ examples/complete_example/configs/config.dev.yaml,sha256=ASIwU8xzB-kinAsLGghv8-LCER1SUC1ed6K8BktOYPQ,1282
38
+ examples/complete_example/configs/config.docker.yaml,sha256=DZWxauz5fcaiVFaphvf7zpvLI3oXjUUiXdX_bGlcBds,1389
39
+ examples/minimal_example/README.md,sha256=Ar70b3BO-UyiYxe0hDcJQ5rWRo06zOOda6e2l8adC0c,1888
40
+ examples/minimal_example/__init__.py,sha256=EloOqdgVLp7YA2DJOWMw0ZxFbVUCH2LqvZVq5RSfSbg,165
41
+ examples/minimal_example/config.json,sha256=LvxtN5nxcYT2hPyS_RiGx7NsaXHYU70rsYMIQ1e_24w,360
42
+ examples/minimal_example/config.yaml,sha256=uLf2GyY64PbmRnT_BUYnkUiUffb-Pb48lkMY9MNFaDw,795
43
+ examples/minimal_example/main.py,sha256=cVXHRuk_qGlnzne2_qix43PmnyM1GUb10NPSNqPgxpA,2239
44
+ examples/minimal_example/simple_server.py,sha256=t_Bzh-EbBk20GeZ0wXJEcom4w_YYRC2oRTyktKqL_YE,3903
45
+ examples/minimal_example/tests/conftest.py,sha256=e-ICRJNV37UaUPlevIlXAhniDcbiPyMpQJr_GQWKCgc,4166
46
+ examples/minimal_example/tests/test_hello_command.py,sha256=C48o7Hh_gy2NlLqb2KKm2HX37df8eIop0IQfOxWPVS0,3485
47
+ examples/minimal_example/tests/test_integration.py,sha256=uvu4uuwMSHUsYaerw6-2eY7_rwrftw_lxUl41MsaJF4,6179
48
+ mcp_proxy_adapter/__init__.py,sha256=B7m1YWyv_Wb87-Q-JqVpHQgwajnfIgDyZ_iIxzdTbBY,1021
49
+ mcp_proxy_adapter/config.py,sha256=IswC2aoUfqArCS6jAydn7-rg5dVODy76d0pLCeOsRyg,5534
50
+ mcp_proxy_adapter/custom_openapi.py,sha256=EFEjeQ3DudgTfb4870PWkF1upWM5RaY1PY9jxTSOwU8,4142
51
+ mcp_proxy_adapter/framework.py,sha256=T4zpn-NOEkPkiJfA5T-zmsGSyJRFd3sIUCNIyw7uUWM,3191
52
+ mcp_proxy_adapter/openapi.py,sha256=jyl5EPXcFhzFKEEMXxHeqF1U-SsYvtdlaKGU2QrekpU,13889
53
+ mcp_proxy_adapter/version.py,sha256=lhzscbXtI4rVuLccUMXqfLAo7liihKAC6f7DOJt9siI,71
54
+ mcp_proxy_adapter-3.0.0.dist-info/licenses/LICENSE,sha256=OkApFEwdgMCt_mbvUI-eIwKMSTe38K3XnU2DT5ub-wI,1072
55
+ mcp_proxy_adapter-3.0.0.dist-info/METADATA,sha256=YguOw7HmpwOlzI9TTvZPlj59zvYPt-kIwn_lTF3XpoU,7537
56
+ mcp_proxy_adapter-3.0.0.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
57
+ mcp_proxy_adapter-3.0.0.dist-info/top_level.txt,sha256=kxq3OC7vBtsFdy9dDVse4cOl-SV_QlvcTeSkuw_jw3I,27
58
+ mcp_proxy_adapter-3.0.0.dist-info/RECORD,,