mcp-proxy-adapter 3.1.6__py3-none-any.whl → 4.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 (118) hide show
  1. mcp_proxy_adapter/api/app.py +65 -27
  2. mcp_proxy_adapter/api/handlers.py +1 -1
  3. mcp_proxy_adapter/api/middleware/error_handling.py +11 -10
  4. mcp_proxy_adapter/api/tool_integration.py +5 -2
  5. mcp_proxy_adapter/api/tools.py +3 -3
  6. mcp_proxy_adapter/commands/base.py +19 -1
  7. mcp_proxy_adapter/commands/command_registry.py +243 -6
  8. mcp_proxy_adapter/commands/hooks.py +260 -0
  9. mcp_proxy_adapter/commands/reload_command.py +211 -0
  10. mcp_proxy_adapter/commands/reload_settings_command.py +125 -0
  11. mcp_proxy_adapter/commands/settings_command.py +189 -0
  12. mcp_proxy_adapter/config.py +16 -1
  13. mcp_proxy_adapter/core/__init__.py +44 -0
  14. mcp_proxy_adapter/core/logging.py +87 -34
  15. mcp_proxy_adapter/core/settings.py +376 -0
  16. mcp_proxy_adapter/core/utils.py +2 -2
  17. mcp_proxy_adapter/custom_openapi.py +81 -2
  18. mcp_proxy_adapter/examples/README.md +124 -0
  19. mcp_proxy_adapter/examples/__init__.py +7 -0
  20. mcp_proxy_adapter/examples/basic_server/README.md +60 -0
  21. mcp_proxy_adapter/examples/basic_server/__init__.py +7 -0
  22. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +39 -0
  23. mcp_proxy_adapter/examples/basic_server/config.json +35 -0
  24. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +238 -0
  25. mcp_proxy_adapter/examples/basic_server/server.py +98 -0
  26. mcp_proxy_adapter/examples/custom_commands/README.md +127 -0
  27. mcp_proxy_adapter/examples/custom_commands/__init__.py +27 -0
  28. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +250 -0
  29. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +6 -0
  30. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +103 -0
  31. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +111 -0
  32. mcp_proxy_adapter/examples/custom_commands/config.json +62 -0
  33. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +169 -0
  34. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +215 -0
  35. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +76 -0
  36. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +96 -0
  37. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +241 -0
  38. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +135 -0
  39. mcp_proxy_adapter/examples/custom_commands/echo_command.py +122 -0
  40. mcp_proxy_adapter/examples/custom_commands/hooks.py +230 -0
  41. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +123 -0
  42. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +103 -0
  43. mcp_proxy_adapter/examples/custom_commands/server.py +223 -0
  44. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +176 -0
  45. mcp_proxy_adapter/examples/deployment/README.md +49 -0
  46. mcp_proxy_adapter/examples/deployment/__init__.py +7 -0
  47. mcp_proxy_adapter/examples/deployment/config.development.json +8 -0
  48. {examples/basic_example → mcp_proxy_adapter/examples/deployment}/config.json +11 -7
  49. mcp_proxy_adapter/examples/deployment/config.production.json +12 -0
  50. mcp_proxy_adapter/examples/deployment/config.staging.json +11 -0
  51. mcp_proxy_adapter/examples/deployment/docker-compose.yml +31 -0
  52. mcp_proxy_adapter/examples/deployment/run.sh +43 -0
  53. mcp_proxy_adapter/examples/deployment/run_docker.sh +84 -0
  54. mcp_proxy_adapter/openapi.py +3 -2
  55. mcp_proxy_adapter/tests/api/test_custom_openapi.py +617 -0
  56. mcp_proxy_adapter/tests/api/test_handlers.py +522 -0
  57. mcp_proxy_adapter/tests/api/test_schemas.py +546 -0
  58. mcp_proxy_adapter/tests/api/test_tool_integration.py +531 -0
  59. mcp_proxy_adapter/tests/unit/test_base_command.py +391 -85
  60. mcp_proxy_adapter/version.py +1 -1
  61. {mcp_proxy_adapter-3.1.6.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/METADATA +1 -1
  62. mcp_proxy_adapter-4.0.0.dist-info/RECORD +110 -0
  63. {mcp_proxy_adapter-3.1.6.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/WHEEL +1 -1
  64. {mcp_proxy_adapter-3.1.6.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/top_level.txt +0 -1
  65. examples/__init__.py +0 -19
  66. examples/anti_patterns/README.md +0 -51
  67. examples/anti_patterns/__init__.py +0 -9
  68. examples/anti_patterns/bad_design/README.md +0 -72
  69. examples/anti_patterns/bad_design/global_state.py +0 -170
  70. examples/anti_patterns/bad_design/monolithic_command.py +0 -272
  71. examples/basic_example/README.md +0 -245
  72. examples/basic_example/__init__.py +0 -8
  73. examples/basic_example/commands/__init__.py +0 -5
  74. examples/basic_example/commands/echo_command.py +0 -95
  75. examples/basic_example/commands/math_command.py +0 -151
  76. examples/basic_example/commands/time_command.py +0 -152
  77. examples/basic_example/docs/EN/README.md +0 -177
  78. examples/basic_example/docs/RU/README.md +0 -177
  79. examples/basic_example/server.py +0 -151
  80. examples/basic_example/tests/conftest.py +0 -243
  81. examples/check_vstl_schema.py +0 -106
  82. examples/commands/echo_command.py +0 -52
  83. examples/commands/echo_command_di.py +0 -152
  84. examples/commands/echo_result.py +0 -65
  85. examples/commands/get_date_command.py +0 -98
  86. examples/commands/new_uuid4_command.py +0 -91
  87. examples/complete_example/Dockerfile +0 -24
  88. examples/complete_example/README.md +0 -92
  89. examples/complete_example/__init__.py +0 -8
  90. examples/complete_example/commands/__init__.py +0 -5
  91. examples/complete_example/commands/system_command.py +0 -328
  92. examples/complete_example/config.json +0 -41
  93. examples/complete_example/configs/config.dev.yaml +0 -40
  94. examples/complete_example/configs/config.docker.yaml +0 -40
  95. examples/complete_example/docker-compose.yml +0 -35
  96. examples/complete_example/requirements.txt +0 -20
  97. examples/complete_example/server.py +0 -113
  98. examples/di_example/.pytest_cache/README.md +0 -8
  99. examples/di_example/server.py +0 -249
  100. examples/fix_vstl_help.py +0 -123
  101. examples/minimal_example/README.md +0 -65
  102. examples/minimal_example/__init__.py +0 -8
  103. examples/minimal_example/config.json +0 -14
  104. examples/minimal_example/main.py +0 -136
  105. examples/minimal_example/simple_server.py +0 -163
  106. examples/minimal_example/tests/conftest.py +0 -171
  107. examples/minimal_example/tests/test_hello_command.py +0 -111
  108. examples/minimal_example/tests/test_integration.py +0 -181
  109. examples/patch_vstl_service.py +0 -105
  110. examples/patch_vstl_service_mcp.py +0 -108
  111. examples/server.py +0 -69
  112. examples/simple_server.py +0 -128
  113. examples/test_package_3.1.4.py +0 -177
  114. examples/test_server.py +0 -134
  115. examples/tool_description_example.py +0 -82
  116. mcp_proxy_adapter/py.typed +0 -0
  117. mcp_proxy_adapter-3.1.6.dist-info/RECORD +0 -118
  118. {mcp_proxy_adapter-3.1.6.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,65 +0,0 @@
1
- # Минимальный пример MCP Proxy Adapter
2
-
3
- Данный пример демонстрирует минимальную конфигурацию для запуска микросервиса с одной простой командой.
4
-
5
- ## Структура примера
6
-
7
- ```
8
- minimal_example/
9
- ├── config.json # Файл конфигурации в JSON формате
10
- ├── README.md # Документация
11
- ├── simple_server.py # Пример сервера с одной командой
12
- └── tests/ # Директория с интеграционными тестами
13
- ├── conftest.py # Настройка тестов
14
- └── test_integration.py # Интеграционные тесты
15
- ```
16
-
17
- ## Запуск примера
18
-
19
- ```bash
20
- # Перейти в директорию проекта
21
- cd examples/minimal_example
22
-
23
- # Запустить сервер
24
- python simple_server.py
25
- ```
26
-
27
- После запуска сервер будет доступен по адресу [http://localhost:8000](http://localhost:8000).
28
-
29
- ## Тестирование API
30
-
31
- ### Через веб-интерфейс
32
-
33
- Откройте в браузере [http://localhost:8000/docs](http://localhost:8000/docs) для доступа к интерактивной документации Swagger UI.
34
-
35
- ### Через командную строку
36
-
37
- ```bash
38
- # Вызов команды hello через JSON-RPC
39
- curl -X POST "http://localhost:8000/api/jsonrpc" \
40
- -H "Content-Type: application/json" \
41
- -d '{"jsonrpc": "2.0", "method": "hello", "params": {"name": "User"}, "id": 1}'
42
-
43
- # Вызов команды hello через упрощенный эндпоинт
44
- curl -X POST "http://localhost:8000/cmd" \
45
- -H "Content-Type: application/json" \
46
- -d '{"command": "hello", "params": {"name": "User"}}'
47
- ```
48
-
49
- ### Запуск интеграционных тестов
50
-
51
- ```bash
52
- # Запуск всех тестов
53
- pytest tests/test_integration.py -v
54
-
55
- # Запуск конкретного теста
56
- pytest tests/test_integration.py::TestHelloCommandIntegration::test_jsonrpc_hello_default -v
57
- ```
58
-
59
- ## Что демонстрирует этот пример
60
-
61
- 1. Создание минимального сервиса с MCP Proxy Adapter
62
- 2. Определение простой команды с метаданными
63
- 3. Основные эндпоинты API
64
- 4. Работа с JSON-RPC
65
- 5. Тестирование API через интеграционные тесты
@@ -1,8 +0,0 @@
1
- """
2
- Minimal example for MCP Microservice.
3
-
4
- This package contains a minimal example of using MCP Microservice framework
5
- with a single echo command.
6
- """
7
-
8
- __all__ = []
@@ -1,14 +0,0 @@
1
- {
2
- "server": {
3
- "host": "0.0.0.0",
4
- "port": 8000,
5
- "debug": true,
6
- "log_level": "INFO"
7
- },
8
- "logging": {
9
- "level": "info",
10
- "file": null,
11
- "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
12
- },
13
- "debug": true
14
- }
@@ -1,136 +0,0 @@
1
- """
2
- Минимальный пример приложения MCP Proxy Adapter.
3
- """
4
-
5
- import os
6
- import sys
7
- import uvicorn
8
- import logging
9
- import json
10
- from pathlib import Path
11
-
12
- from mcp_proxy_adapter import create_app, Command, SuccessResult
13
- from mcp_proxy_adapter.commands.command_registry import registry
14
- from mcp_proxy_adapter.core.logging import logger
15
- from mcp_proxy_adapter.config import config
16
-
17
-
18
- class HelloCommand(Command):
19
- """Простая команда, возвращающая приветствие."""
20
-
21
- name = "hello"
22
-
23
- async def execute(self, name: str = "World") -> SuccessResult:
24
- """Выполняет команду с переданным именем."""
25
- logger.info(f"Executing hello command with name: {name}")
26
- return SuccessResult({"message": f"Hello, {name}!"})
27
-
28
-
29
- def ensure_config():
30
- """Проверяет наличие конфигурационного файла и создает его при необходимости."""
31
- config_path = Path("config.json")
32
-
33
- if not config_path.exists():
34
- config_data = {
35
- "server": {
36
- "host": "0.0.0.0",
37
- "port": 8000,
38
- "debug": True,
39
- "log_level": "INFO"
40
- },
41
- "logging": {
42
- "level": "info",
43
- "file": "logs/minimal_example.log",
44
- "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
45
- },
46
- "debug": True
47
- }
48
-
49
- # Создаем директорию для логов
50
- logs_dir = Path("logs")
51
- logs_dir.mkdir(exist_ok=True)
52
-
53
- # Записываем конфигурацию
54
- with open(config_path, "w") as f:
55
- json.dump(config_data, f, indent=2)
56
-
57
- logger.info(f"Created default configuration at {config_path}")
58
-
59
-
60
- def setup_application():
61
- """
62
- Настраивает и возвращает FastAPI приложение.
63
- """
64
- # Проверяем наличие конфигурационного файла
65
- ensure_config()
66
-
67
- # Определяем путь к конфигурационному файлу
68
- config_path = Path("config.json").absolute()
69
-
70
- # Загружаем конфигурацию из файла
71
- if config_path.exists():
72
- config.load_from_file(str(config_path))
73
- logger.info(f"Loaded configuration from {config_path}")
74
-
75
- # Создаем приложение
76
- app = create_app()
77
-
78
- # Корректно регистрируем команду
79
- try:
80
- # Проверяем, есть ли уже команда в реестре
81
- if registry.command_exists(HelloCommand.name):
82
- # Если команда существует, удаляем ее
83
- logger.info(f"Command '{HelloCommand.name}' already exists, re-registering it")
84
- registry.unregister(HelloCommand.name)
85
-
86
- # Регистрируем команду
87
- registry.register(HelloCommand)
88
- logger.info(f"Command '{HelloCommand.name}' successfully registered")
89
-
90
- # Выводим список всех зарегистрированных команд
91
- commands = registry.get_all_commands()
92
- logger.info(f"Total registered commands: {len(commands)}")
93
- except Exception as e:
94
- logger.error(f"Error registering command: {e}")
95
-
96
- return app
97
-
98
-
99
- def main():
100
- """
101
- Основная функция для запуска приложения.
102
- """
103
- try:
104
- # Настраиваем приложение
105
- app = setup_application()
106
-
107
- # Получаем настройки сервера из конфигурации
108
- host = config.get("server.host", "0.0.0.0")
109
- port = config.get("server.port", 8000)
110
- debug = config.get("server.debug", False)
111
-
112
- logger.info(f"Starting server on {host}:{port} (debug: {debug})")
113
-
114
- if debug:
115
- # В режиме отладки запускаем с перезагрузкой, используя строку импорта
116
- uvicorn.run(
117
- "main:setup_application",
118
- host=host,
119
- port=port,
120
- reload=True,
121
- factory=True
122
- )
123
- else:
124
- # В обычном режиме запускаем экземпляр приложения
125
- uvicorn.run(
126
- app,
127
- host=host,
128
- port=port
129
- )
130
- except Exception as e:
131
- logger.exception(f"Error during application startup: {e}")
132
- sys.exit(1)
133
-
134
-
135
- if __name__ == "__main__":
136
- main()
@@ -1,163 +0,0 @@
1
- """
2
- Минимальный пример использования MCP Proxy Adapter.
3
-
4
- Этот пример демонстрирует минимальную конфигурацию для запуска микросервиса
5
- с одной простой командой.
6
- """
7
-
8
- import os
9
- import uvicorn
10
- from typing import Dict, Any, List
11
-
12
- from mcp_proxy_adapter import Command, SuccessResult, create_app, registry
13
- from mcp_proxy_adapter.core.logging import setup_logging
14
- from mcp_proxy_adapter.config import config
15
-
16
-
17
- class HelloResult(SuccessResult):
18
- """
19
- Результат выполнения команды hello.
20
-
21
- Атрибуты:
22
- message (str): Приветственное сообщение
23
- """
24
-
25
- def __init__(self, message: str):
26
- """
27
- Инициализация результата команды.
28
-
29
- Args:
30
- message: Приветственное сообщение
31
- """
32
- self.message = message
33
-
34
- def to_dict(self) -> Dict[str, Any]:
35
- """
36
- Преобразование результата в словарь.
37
-
38
- Returns:
39
- Словарь с результатом выполнения команды
40
- """
41
- return {"message": self.message}
42
-
43
- @classmethod
44
- def get_schema(cls) -> Dict[str, Any]:
45
- """
46
- Получение JSON-схемы для результата.
47
-
48
- Returns:
49
- JSON-схема результата
50
- """
51
- return {
52
- "type": "object",
53
- "properties": {
54
- "message": {"type": "string", "description": "Приветственное сообщение"}
55
- },
56
- "required": ["message"]
57
- }
58
-
59
-
60
- class HelloCommand(Command):
61
- """
62
- Команда, возвращающая приветственное сообщение.
63
-
64
- Эта команда принимает имя пользователя и возвращает приветственное сообщение.
65
- """
66
-
67
- # Имя команды для регистрации
68
- name = "hello"
69
- # Класс результата команды
70
- result_class = HelloResult
71
-
72
- async def execute(self, name: str = "World") -> HelloResult:
73
- """
74
- Выполнение команды.
75
-
76
- Args:
77
- name: Имя для приветствия (по умолчанию "World")
78
-
79
- Returns:
80
- Результат выполнения команды с приветственным сообщением
81
- """
82
- return HelloResult(f"Hello, {name}!")
83
-
84
- @classmethod
85
- def get_schema(cls) -> Dict[str, Any]:
86
- """
87
- Получение JSON-схемы для параметров команды.
88
-
89
- Returns:
90
- JSON-схема параметров команды
91
- """
92
- return {
93
- "type": "object",
94
- "properties": {
95
- "name": {
96
- "type": "string",
97
- "description": "Имя для приветствия"
98
- }
99
- },
100
- "additionalProperties": False
101
- }
102
-
103
- @classmethod
104
- def _generate_examples(cls, params: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:
105
- """
106
- Генерирует примеры использования команды.
107
-
108
- Args:
109
- params: Информация о параметрах команды
110
-
111
- Returns:
112
- Список примеров
113
- """
114
- return [
115
- {
116
- "command": "hello",
117
- "description": "Приветствие по умолчанию"
118
- },
119
- {
120
- "command": "hello",
121
- "params": {"name": "User"},
122
- "description": "Приветствие с указанным именем"
123
- }
124
- ]
125
-
126
-
127
- def main():
128
- """Запуск микросервиса."""
129
- # Определяем путь к конфигурационному файлу
130
- current_dir = os.path.dirname(os.path.abspath(__file__))
131
- config_path = os.path.join(current_dir, "config.json")
132
-
133
- # Загружаем конфигурацию, если файл существует
134
- if os.path.exists(config_path):
135
- config.load_from_file(config_path)
136
-
137
- # Настраиваем логирование
138
- setup_logging("INFO")
139
-
140
- # Создаем приложение FastAPI
141
- app = create_app()
142
- app.title = "Minimal Example"
143
- app.description = "Минимальный пример использования MCP Proxy Adapter"
144
- app.version = "1.0.0"
145
-
146
- # Регистрируем команду
147
- registry.register(HelloCommand)
148
-
149
- # Определяем порт из переменной окружения или используем 8000 по умолчанию
150
- port = int(os.environ.get("TEST_SERVER_PORT", 8000))
151
-
152
- # Запускаем сервер
153
- uvicorn.run(
154
- app,
155
- host="0.0.0.0",
156
- port=port,
157
- reload=False, # Отключаем автоперезагрузку для тестов
158
- log_level="info"
159
- )
160
-
161
-
162
- if __name__ == "__main__":
163
- main()
@@ -1,171 +0,0 @@
1
- """
2
- Pytest configuration and fixtures for minimal example tests.
3
- """
4
-
5
- import os
6
- import sys
7
- import time
8
- import socket
9
- import asyncio
10
- import threading
11
- import multiprocessing
12
- from typing import Callable, Tuple, Dict, Any
13
-
14
- import pytest
15
- import requests
16
-
17
- # Add parent directory to path for imports
18
- sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
19
-
20
- # Import the server module from the parent directory
21
- import simple_server
22
-
23
-
24
- def find_free_port() -> int:
25
- """
26
- Find a free port on localhost.
27
-
28
- Returns:
29
- Free port number
30
- """
31
- with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
32
- sock.bind(('localhost', 0))
33
- return sock.getsockname()[1]
34
-
35
-
36
- class ServerProcess:
37
- """Helper class to manage server process."""
38
-
39
- def __init__(self, port: int):
40
- """
41
- Initialize server process with a specified port.
42
-
43
- Args:
44
- port: Port number to use
45
- """
46
- self.port = port
47
- self.process = None
48
-
49
- def start(self) -> None:
50
- """Start the server in a separate process."""
51
- def run_server():
52
- # Set the test port via environment variable
53
- os.environ["TEST_SERVER_PORT"] = str(self.port)
54
- simple_server.main()
55
-
56
- self.process = multiprocessing.Process(target=run_server)
57
- self.process.daemon = True
58
- self.process.start()
59
-
60
- # Wait for server to start
61
- self._wait_for_server()
62
-
63
- def stop(self) -> None:
64
- """Stop the server process."""
65
- if self.process and self.process.is_alive():
66
- self.process.terminate()
67
- self.process.join(timeout=2)
68
-
69
- def _wait_for_server(self, max_attempts: int = 10) -> None:
70
- """
71
- Wait for the server to become available.
72
-
73
- Args:
74
- max_attempts: Maximum number of connection attempts
75
- """
76
- for i in range(max_attempts):
77
- try:
78
- response = requests.get(f"http://localhost:{self.port}/health")
79
- if response.status_code == 200:
80
- return
81
- except requests.ConnectionError:
82
- pass
83
-
84
- time.sleep(0.5)
85
-
86
- raise TimeoutError(f"Server did not start within {max_attempts * 0.5} seconds")
87
-
88
-
89
- @pytest.fixture
90
- def server_port() -> int:
91
- """
92
- Fixture that provides a free port for the test server.
93
-
94
- Returns:
95
- Port number
96
- """
97
- return find_free_port()
98
-
99
-
100
- @pytest.fixture
101
- def server(server_port: int) -> ServerProcess:
102
- """
103
- Fixture that provides a running server instance.
104
-
105
- Args:
106
- server_port: Port to run the server on
107
-
108
- Returns:
109
- Server process object
110
- """
111
- server_process = ServerProcess(server_port)
112
- server_process.start()
113
-
114
- yield server_process
115
-
116
- server_process.stop()
117
-
118
-
119
- @pytest.fixture
120
- def api_url(server_port: int) -> str:
121
- """
122
- Fixture that provides the base API URL.
123
-
124
- Args:
125
- server_port: Server port
126
-
127
- Returns:
128
- Base API URL
129
- """
130
- return f"http://localhost:{server_port}"
131
-
132
-
133
- @pytest.fixture
134
- def jsonrpc_client(api_url: str) -> Callable:
135
- """
136
- Fixture that provides a JSON-RPC client function.
137
-
138
- Args:
139
- api_url: Base API URL
140
-
141
- Returns:
142
- Function to make JSON-RPC requests
143
- """
144
- def make_request(method: str, params: Dict[str, Any], request_id: int = 1) -> Dict[str, Any]:
145
- """
146
- Make a JSON-RPC request.
147
-
148
- Args:
149
- method: Method name
150
- params: Method parameters
151
- request_id: Request ID
152
-
153
- Returns:
154
- JSON-RPC response
155
- """
156
- payload = {
157
- "jsonrpc": "2.0",
158
- "method": method,
159
- "params": params,
160
- "id": request_id
161
- }
162
-
163
- response = requests.post(
164
- f"{api_url}/api/jsonrpc",
165
- json=payload,
166
- headers={"Content-Type": "application/json"}
167
- )
168
-
169
- return response.json()
170
-
171
- return make_request
@@ -1,111 +0,0 @@
1
- """
2
- Unit tests for the HelloCommand in the minimal example.
3
- """
4
-
5
- import pytest
6
-
7
- from simple_server import HelloCommand, HelloResult
8
-
9
-
10
- class TestHelloCommand:
11
- """Tests for HelloCommand class."""
12
-
13
- @pytest.mark.asyncio
14
- async def test_execute_with_default_name(self):
15
- """Test HelloCommand.execute with default name parameter."""
16
- # Create command instance
17
- command = HelloCommand()
18
-
19
- # Execute command with default parameter
20
- result = await command.execute()
21
-
22
- # Check result type
23
- assert isinstance(result, HelloResult)
24
-
25
- # Check message content
26
- assert result.message == "Hello, World!"
27
-
28
- # Check serialization
29
- assert result.to_dict() == {"message": "Hello, World!"}
30
-
31
- @pytest.mark.asyncio
32
- async def test_execute_with_custom_name(self):
33
- """Test HelloCommand.execute with custom name parameter."""
34
- # Create command instance
35
- command = HelloCommand()
36
-
37
- # Execute command with custom parameter
38
- result = await command.execute(name="Test")
39
-
40
- # Check result
41
- assert isinstance(result, HelloResult)
42
- assert result.message == "Hello, Test!"
43
-
44
- # Check serialization
45
- assert result.to_dict() == {"message": "Hello, Test!"}
46
-
47
- @pytest.mark.asyncio
48
- async def test_execute_with_empty_name(self):
49
- """Test HelloCommand.execute with empty name parameter."""
50
- # Create command instance
51
- command = HelloCommand()
52
-
53
- # Execute command with empty parameter
54
- result = await command.execute(name="")
55
-
56
- # Check result
57
- assert isinstance(result, HelloResult)
58
- assert result.message == "Hello, !"
59
-
60
- # Check serialization
61
- assert result.to_dict() == {"message": "Hello, !"}
62
-
63
-
64
- class TestHelloResult:
65
- """Tests for HelloResult class."""
66
-
67
- def test_init(self):
68
- """Test HelloResult initialization."""
69
- # Create result instance
70
- result = HelloResult("Hello, Test!")
71
-
72
- # Check attributes
73
- assert result.message == "Hello, Test!"
74
-
75
- def test_to_dict(self):
76
- """Test HelloResult.to_dict method."""
77
- # Create result instance
78
- result = HelloResult("Hello, Test!")
79
-
80
- # Check serialization
81
- assert result.to_dict() == {"message": "Hello, Test!"}
82
-
83
- def test_get_schema(self):
84
- """Test HelloResult.get_schema method."""
85
- # Get schema
86
- schema = HelloResult.get_schema()
87
-
88
- # Check schema structure
89
- assert schema["type"] == "object"
90
- assert "properties" in schema
91
- assert "message" in schema["properties"]
92
- assert schema["properties"]["message"]["type"] == "string"
93
- assert "required" in schema
94
- assert "message" in schema["required"]
95
-
96
-
97
- class TestHelloCommandSchema:
98
- """Tests for HelloCommand schema."""
99
-
100
- def test_get_schema(self):
101
- """Test HelloCommand.get_schema method."""
102
- # Get schema
103
- schema = HelloCommand.get_schema()
104
-
105
- # Check schema structure
106
- assert schema["type"] == "object"
107
- assert "properties" in schema
108
- assert "name" in schema["properties"]
109
- assert schema["properties"]["name"]["type"] == "string"
110
- assert "additionalProperties" in schema
111
- assert schema["additionalProperties"] is False