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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) 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 +65 -11
  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/py.typed +0 -0
  43. mcp_proxy_adapter/schemas/base_schema.json +114 -0
  44. mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
  45. mcp_proxy_adapter/tests/__init__.py +0 -0
  46. mcp_proxy_adapter/tests/api/__init__.py +3 -0
  47. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +115 -0
  48. mcp_proxy_adapter/tests/api/test_middleware.py +336 -0
  49. mcp_proxy_adapter/tests/commands/__init__.py +3 -0
  50. mcp_proxy_adapter/tests/commands/test_config_command.py +211 -0
  51. mcp_proxy_adapter/tests/commands/test_echo_command.py +127 -0
  52. mcp_proxy_adapter/tests/commands/test_help_command.py +133 -0
  53. mcp_proxy_adapter/tests/conftest.py +131 -0
  54. mcp_proxy_adapter/tests/functional/__init__.py +3 -0
  55. mcp_proxy_adapter/tests/functional/test_api.py +235 -0
  56. mcp_proxy_adapter/tests/integration/__init__.py +3 -0
  57. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +130 -0
  58. mcp_proxy_adapter/tests/integration/test_integration.py +255 -0
  59. mcp_proxy_adapter/tests/performance/__init__.py +3 -0
  60. mcp_proxy_adapter/tests/performance/test_performance.py +189 -0
  61. mcp_proxy_adapter/tests/stubs/__init__.py +10 -0
  62. mcp_proxy_adapter/tests/stubs/echo_command.py +104 -0
  63. mcp_proxy_adapter/tests/test_api_endpoints.py +271 -0
  64. mcp_proxy_adapter/tests/test_api_handlers.py +289 -0
  65. mcp_proxy_adapter/tests/test_base_command.py +123 -0
  66. mcp_proxy_adapter/tests/test_batch_requests.py +117 -0
  67. mcp_proxy_adapter/tests/test_command_registry.py +245 -0
  68. mcp_proxy_adapter/tests/test_config.py +127 -0
  69. mcp_proxy_adapter/tests/test_utils.py +65 -0
  70. mcp_proxy_adapter/tests/unit/__init__.py +3 -0
  71. mcp_proxy_adapter/tests/unit/test_base_command.py +130 -0
  72. mcp_proxy_adapter/tests/unit/test_config.py +217 -0
  73. mcp_proxy_adapter/version.py +1 -1
  74. {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.1.dist-info}/METADATA +1 -1
  75. mcp_proxy_adapter-3.0.1.dist-info/RECORD +109 -0
  76. examples/basic_example/config.yaml +0 -20
  77. examples/basic_example/main.py +0 -50
  78. examples/complete_example/main.py +0 -67
  79. examples/minimal_example/config.yaml +0 -26
  80. mcp_proxy_adapter/framework.py +0 -109
  81. mcp_proxy_adapter-3.0.0.dist-info/RECORD +0 -58
  82. {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.1.dist-info}/WHEEL +0 -0
  83. {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.1.dist-info}/licenses/LICENSE +0 -0
  84. {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.1.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,120 @@
1
- # Базовый пример MCP Microservice
1
+ # Basic MCP Proxy Adapter Example
2
2
 
3
- Этот пример демонстрирует базовую функциональность MCP Microservice с несколькими командами,
4
- организованными в отдельные файлы.
3
+ This example demonstrates how to use MCP Proxy Adapter to create a microservice with multiple commands organized in separate files.
4
+
5
+ ## English Documentation
6
+
7
+ ### Overview
8
+
9
+ This example shows:
10
+ - Creating a microservice using MCP Proxy Adapter
11
+ - Configuring the service using JSON configuration file
12
+ - Automatic command discovery from a package
13
+ - Implementing various command types with their result classes
14
+ - Running the service with auto-reload for development
15
+
16
+ ### Setup
17
+
18
+ 1. Make sure you have installed MCP Proxy Adapter package
19
+ 2. Install additional dependencies:
20
+ ```
21
+ pip install pytz uvicorn
22
+ ```
23
+
24
+ ### Configuration
25
+
26
+ The service uses `config.json` for configuration. The key settings are:
27
+ - Server host and port
28
+ - Logging configuration
29
+ - Command discovery settings
30
+
31
+ ### Available Commands
32
+
33
+ The example includes several commands:
34
+ - `echo` - Echo back a message
35
+ - `time` - Get current time in different formats and timezones
36
+ - `math` - Perform basic math operations
37
+
38
+ ### Running the Example
39
+
40
+ ```bash
41
+ cd examples/basic_example
42
+ python server.py
43
+ ```
44
+
45
+ The service will start on http://localhost:8000 by default, with API documentation available at http://localhost:8000/docs
46
+
47
+ ### Testing Commands
48
+
49
+ You can test commands using curl:
50
+
51
+ ```bash
52
+ # Echo command
53
+ curl -X POST http://localhost:8000/cmd -H "Content-Type: application/json" -d '{"command": "echo", "params": {"message": "Hello, world!"}}'
54
+
55
+ # Time command
56
+ curl -X POST http://localhost:8000/cmd -H "Content-Type: application/json" -d '{"command": "time", "params": {"timezone": "Europe/London"}}'
57
+
58
+ # JSON-RPC style request
59
+ curl -X POST http://localhost:8000/api/jsonrpc -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "echo", "params": {"message": "Hello RPC!"}, "id": 1}'
60
+ ```
61
+
62
+ ## Русская документация
63
+
64
+ ### Обзор
65
+
66
+ Этот пример демонстрирует:
67
+ - Создание микросервиса с использованием MCP Proxy Adapter
68
+ - Настройку сервиса с использованием JSON-файла конфигурации
69
+ - Автоматическое обнаружение команд из пакета
70
+ - Реализацию различных типов команд с их классами результатов
71
+ - Запуск сервиса с автоперезагрузкой для разработки
72
+
73
+ ### Настройка
74
+
75
+ 1. Убедитесь, что у вас установлен пакет MCP Proxy Adapter
76
+ 2. Установите дополнительные зависимости:
77
+ ```
78
+ pip install pytz uvicorn
79
+ ```
80
+
81
+ ### Конфигурация
82
+
83
+ Сервис использует `config.json` для конфигурации. Основные настройки:
84
+ - Хост и порт сервера
85
+ - Настройки логирования
86
+ - Настройки обнаружения команд
87
+
88
+ ### Доступные команды
89
+
90
+ Пример включает несколько команд:
91
+ - `echo` - Эхо-ответ сообщения
92
+ - `time` - Получение текущего времени в разных форматах и часовых поясах
93
+ - `math` - Выполнение базовых математических операций
94
+
95
+ ### Запуск примера
96
+
97
+ ```bash
98
+ cd examples/basic_example
99
+ python server.py
100
+ ```
101
+
102
+ Сервис запустится на http://localhost:8000 по умолчанию, документация API доступна по адресу http://localhost:8000/docs
103
+
104
+ ### Тестирование команд
105
+
106
+ Вы можете тестировать команды с помощью curl:
107
+
108
+ ```bash
109
+ # Команда echo
110
+ curl -X POST http://localhost:8000/cmd -H "Content-Type: application/json" -d '{"command": "echo", "params": {"message": "Привет, мир!"}}'
111
+
112
+ # Команда time
113
+ curl -X POST http://localhost:8000/cmd -H "Content-Type: application/json" -d '{"command": "time", "params": {"timezone": "Europe/Moscow"}}'
114
+
115
+ # Запрос в стиле JSON-RPC
116
+ curl -X POST http://localhost:8000/api/jsonrpc -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "echo", "params": {"message": "Привет RPC!"}, "id": 1}'
117
+ ```
5
118
 
6
119
  ## Структура примера
7
120
 
@@ -12,7 +125,7 @@ basic_example/
12
125
  │ ├── echo_command.py # Команда эхо
13
126
  │ ├── math_command.py # Математическая команда
14
127
  │ └── time_command.py # Команда времени
15
- ├── config.yaml # Файл конфигурации
128
+ ├── config.json # Файл конфигурации JSON
16
129
  ├── README.md # Документация
17
130
  └── server.py # Файл запуска сервера
18
131
  ```
@@ -124,8 +237,9 @@ curl -X POST "http://localhost:8000/api/command/time" \
124
237
 
125
238
  ## Что демонстрирует этот пример
126
239
 
127
- 1. Организация команд в отдельные файлы
128
- 2. Автоматическое обнаружение и регистрация команд
129
- 3. Различные типы команд и параметров
130
- 4. Обработка ошибок
131
- 5. Различные способы вызова команд (JSON-RPC, /cmd, /api/command/{command_name})
240
+ 1. Прямое использование FastAPI и uvicorn с MCP Proxy Adapter
241
+ 2. Организация команд в отдельные файлы
242
+ 3. Автоматическое обнаружение и регистрация команд
243
+ 4. Различные типы команд и параметров
244
+ 5. Обработка ошибок
245
+ 6. Различные способы вызова команд (JSON-RPC, /cmd, /api/command/{command_name})
@@ -17,5 +17,9 @@
17
17
  "max_bytes": 10485760,
18
18
  "backup_count": 5
19
19
  }
20
+ },
21
+ "discovery": {
22
+ "enabled": true,
23
+ "package": "commands"
20
24
  }
21
25
  }
@@ -12,14 +12,16 @@ basic_example/
12
12
  │ ├── echo_command.py # Echo command
13
13
  │ ├── math_command.py # Math command
14
14
  │ └── time_command.py # Time command
15
- ├── config.yaml # Configuration file
15
+ ├── config.json # JSON configuration file
16
16
  ├── docs/ # Documentation
17
17
  │ ├── EN/ # English documentation
18
18
  │ │ └── README.md # This file
19
19
  │ └── RU/ # Russian documentation
20
20
  │ └── README.md # Russian version of this file
21
21
  ├── logs/ # Logs directory
22
- └── server.py # Server startup file
22
+ ├── server.py # Server startup and application logic
23
+ └── tests/ # Tests directory
24
+ └── conftest.py # Test configuration and fixtures
23
25
  ```
24
26
 
25
27
  ## Running the Example
@@ -31,12 +33,48 @@ cd examples/basic_example
31
33
  # Create logs directory if it doesn't exist
32
34
  mkdir -p logs
33
35
 
34
- # Run the server
36
+ # Run the server with default configuration (config.json)
35
37
  python server.py
38
+
39
+ # Or run with a specific configuration file
40
+ python server.py --config other_config.json
36
41
  ```
37
42
 
38
43
  After starting, the server will be available at [http://localhost:8000](http://localhost:8000).
39
44
 
45
+ ## Configuration
46
+
47
+ The server reads configuration from JSON files. By default, it uses `config.json` in the same directory as `server.py`.
48
+
49
+ You can specify a different configuration file with the `--config` parameter:
50
+
51
+ ```bash
52
+ python server.py --config my_custom_config.json
53
+ ```
54
+
55
+ If the specified configuration file doesn't exist, the server will try to fall back to `config.json`.
56
+
57
+ The main configuration options are:
58
+
59
+ ```json
60
+ {
61
+ "server": {
62
+ "host": "0.0.0.0",
63
+ "port": 8000,
64
+ "debug": true,
65
+ "log_level": "info"
66
+ },
67
+ "logging": {
68
+ "level": "INFO",
69
+ "file": "logs/basic_example.log"
70
+ }
71
+ }
72
+ ```
73
+
74
+ The server can run in two modes:
75
+ - Normal mode: Uses a pre-configured application instance
76
+ - Debug mode: Uses hot reload (when `"debug": true` in config)
77
+
40
78
  ## Available Commands
41
79
 
42
80
  ### 1. `echo` - Echo Command
@@ -132,5 +170,8 @@ curl -X POST "http://localhost:8000/api/command/time" \
132
170
  1. Command organization in separate files
133
171
  2. Automatic command discovery and registration
134
172
  3. Different command types and parameter handling
135
- 4. Error handling
136
- 5. Different ways to call commands (JSON-RPC, /cmd, /api/command/{command_name})
173
+ 4. Error handling and automatic command reregistration
174
+ 5. Different ways to call commands (JSON-RPC, /cmd, /api/command/{command_name})
175
+ 6. Support for debug mode with hot reload
176
+ 7. Safe command registration for preventing conflicts
177
+ 8. JSON configuration files with command-line options
@@ -12,14 +12,16 @@ basic_example/
12
12
  │ ├── echo_command.py # Команда эхо
13
13
  │ ├── math_command.py # Математическая команда
14
14
  │ └── time_command.py # Команда времени
15
- ├── config.yaml # Файл конфигурации
15
+ ├── config.json # Файл конфигурации JSON
16
16
  ├── docs/ # Документация
17
17
  │ ├── EN/ # Английская документация
18
18
  │ │ └── README.md # Английская версия данного файла
19
19
  │ └── RU/ # Русская документация
20
20
  │ └── README.md # Этот файл
21
21
  ├── logs/ # Директория для логов
22
- └── server.py # Файл запуска сервера
22
+ ├── server.py # Файл запуска сервера и логики приложения
23
+ └── tests/ # Директория с тестами
24
+ └── conftest.py # Конфигурация и фикстуры для тестов
23
25
  ```
24
26
 
25
27
  ## Запуск примера
@@ -31,12 +33,48 @@ cd examples/basic_example
31
33
  # Создать директорию для логов, если она не существует
32
34
  mkdir -p logs
33
35
 
34
- # Запустить сервер
36
+ # Запустить сервер с конфигурацией по умолчанию (config.json)
35
37
  python server.py
38
+
39
+ # Или запустить с указанием другого файла конфигурации
40
+ python server.py --config другой_конфиг.json
36
41
  ```
37
42
 
38
43
  После запуска сервер будет доступен по адресу [http://localhost:8000](http://localhost:8000).
39
44
 
45
+ ## Конфигурация
46
+
47
+ Сервер считывает конфигурацию из JSON-файлов. По умолчанию используется `config.json` в том же каталоге, где находится `server.py`.
48
+
49
+ Вы можете указать другой файл конфигурации с помощью параметра `--config`:
50
+
51
+ ```bash
52
+ python server.py --config мой_конфиг.json
53
+ ```
54
+
55
+ Если указанный файл конфигурации не существует, сервер попытается использовать `config.json`.
56
+
57
+ Основные параметры конфигурации:
58
+
59
+ ```json
60
+ {
61
+ "server": {
62
+ "host": "0.0.0.0",
63
+ "port": 8000,
64
+ "debug": true,
65
+ "log_level": "info"
66
+ },
67
+ "logging": {
68
+ "level": "INFO",
69
+ "file": "logs/basic_example.log"
70
+ }
71
+ }
72
+ ```
73
+
74
+ Сервер может работать в двух режимах:
75
+ - Обычный режим: использует предварительно настроенный экземпляр приложения
76
+ - Режим отладки: использует горячую перезагрузку (когда `"debug": true` в конфигурации)
77
+
40
78
  ## Доступные команды
41
79
 
42
80
  ### 1. `echo` - Эхо-команда
@@ -132,5 +170,8 @@ curl -X POST "http://localhost:8000/api/command/time" \
132
170
  1. Организация команд в отдельные файлы
133
171
  2. Автоматическое обнаружение и регистрация команд
134
172
  3. Различные типы команд и параметров
135
- 4. Обработка ошибок
136
- 5. Различные способы вызова команд (JSON-RPC, /cmd, /api/command/{command_name})
173
+ 4. Обработка ошибок и автоматическая перерегистрация команд
174
+ 5. Различные способы вызова команд (JSON-RPC, /cmd, /api/command/{command_name})
175
+ 6. Поддержка режима отладки с горячей перезагрузкой
176
+ 7. Безопасная регистрация команд для предотвращения конфликтов
177
+ 8. JSON-файлы конфигурации с опциями командной строки
@@ -1,44 +1,150 @@
1
1
  """
2
- Basic MCP Microservice example.
2
+ Basic MCP Proxy Adapter example.
3
3
 
4
- This example demonstrates a microservice with multiple commands
5
- organized in separate files.
4
+ This example demonstrates how to use MCP Proxy Adapter to create
5
+ a microservice with multiple commands organized in separate files.
6
6
  """
7
7
 
8
8
  import os
9
9
  import sys
10
+ import json
11
+ import argparse
12
+ import uvicorn
10
13
  from typing import Dict, Any
14
+ from pathlib import Path
11
15
 
12
- import mcp_proxy_adapter as mcp
13
- from mcp_proxy_adapter import MicroService
16
+ from mcp_proxy_adapter import Command, CommandResult, registry
17
+ from mcp_proxy_adapter.api.app import create_app
18
+ from mcp_proxy_adapter.config import config
19
+ from mcp_proxy_adapter.core.logging import logger, setup_logging
14
20
 
15
21
  # Add commands directory to path for local imports
16
22
  sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
17
23
 
18
24
 
19
- def main():
20
- """Run microservice with command discovery."""
25
+ def parse_args():
26
+ """
27
+ Parse command line arguments.
28
+
29
+ Returns:
30
+ Parsed arguments
31
+ """
32
+ parser = argparse.ArgumentParser(description="Basic MCP Microservice Example")
33
+ parser.add_argument(
34
+ "--config",
35
+ default="config.json",
36
+ help="Path to configuration file (default: config.json)"
37
+ )
38
+ return parser.parse_args()
39
+
40
+
41
+ def setup_application(config_file=None):
42
+ """
43
+ Настраивает и возвращает FastAPI приложение.
44
+ """
45
+ # Get config file path
46
+ if config_file is None:
47
+ args = parse_args()
48
+ config_file = args.config
49
+
21
50
  # Get absolute paths
22
- current_dir = os.path.dirname(os.path.abspath(__file__))
23
- config_path = os.path.join(current_dir, "config.yaml")
51
+ current_dir = Path(__file__).parent.absolute()
52
+ config_path = current_dir / config_file
53
+
54
+ # Try alternative config file if specified one doesn't exist
55
+ if not config_path.exists() and config_file != "config.json":
56
+ fallback_path = current_dir / "config.json"
57
+ if fallback_path.exists():
58
+ logger.warning(f"Config file {config_path} not found, using {fallback_path} instead")
59
+ config_path = fallback_path
24
60
 
25
61
  # Create log directory if it doesn't exist
26
- os.makedirs(os.path.join(current_dir, "logs"), exist_ok=True)
27
-
28
- # Create microservice
29
- service = MicroService(
30
- title="Basic MCP Microservice Example",
31
- description="Example microservice with multiple commands",
32
- version="1.0.0",
33
- config_path=config_path
34
- )
62
+ logs_dir = current_dir / "logs"
63
+ logs_dir.mkdir(exist_ok=True)
64
+
65
+ # Load configuration if config file exists
66
+ if config_path.exists():
67
+ # Make sure we're only loading JSON files
68
+ if not str(config_path).lower().endswith('.json'):
69
+ logger.warning(f"Config file {config_path} is not a JSON file, only JSON format is supported")
70
+ config_path = current_dir / "config.json"
71
+ if not config_path.exists():
72
+ logger.warning(f"Default config.json not found, using default values")
73
+
74
+ if config_path.exists():
75
+ config.load_from_file(str(config_path))
76
+ logger.info(f"Loaded configuration from {config_path}")
77
+ else:
78
+ logger.warning(f"Configuration file {config_path} not found, using defaults")
79
+
80
+ # Create FastAPI app
81
+ app = create_app()
82
+ app.title = "Basic MCP Proxy Adapter Example"
83
+ app.description = "Example microservice with multiple commands using MCP Proxy Adapter"
84
+ app.version = "1.0.0"
35
85
 
36
86
  # Discover and register commands from the commands directory
37
- package_path = "commands" # Relative import path
38
- service.discover_commands(package_path)
87
+ package_path = "commands"
88
+ try:
89
+ # Clear existing commands to prevent conflicts in test environment
90
+ registered_commands = registry.get_all_commands()
91
+ for cmd_name in list(registered_commands.keys()):
92
+ try:
93
+ registry.unregister(cmd_name)
94
+ except Exception as e:
95
+ logger.debug(f"Error unregistering command {cmd_name}: {e}")
96
+
97
+ # Discover and register commands
98
+ registry.discover_commands(package_path)
99
+ logger.info(f"Discovered commands from package: {package_path}")
100
+ except Exception as e:
101
+ logger.error(f"Error discovering commands: {e}")
102
+
103
+ return app
104
+
105
+
106
+ def main():
107
+ """Run microservice with command discovery."""
108
+ # Setup logging
109
+ log_level = config.get("logging.level", "INFO")
110
+ setup_logging(log_level)
111
+
112
+ # Initialize application
113
+ app = setup_application()
114
+
115
+ # Get server configuration
116
+ host = config.get("server.host", "localhost")
117
+ port = config.get("server.port", 8000)
118
+
119
+ # Check if port is overridden by environment variable (for testing)
120
+ if "TEST_SERVER_PORT" in os.environ:
121
+ port = int(os.environ["TEST_SERVER_PORT"])
122
+ logger.info(f"Using test port from environment: {port}")
39
123
 
40
124
  # Run server
41
- service.run(reload=True)
125
+ logger.info(f"Starting server on {host}:{port}")
126
+
127
+ debug = config.get("server.debug", False)
128
+
129
+ if debug:
130
+ # In debug mode, run with hot reload using import string
131
+ uvicorn.run(
132
+ "server:setup_application",
133
+ host=host,
134
+ port=port,
135
+ reload=True,
136
+ factory=True,
137
+ log_level=config.get("logging.level", "info").lower()
138
+ )
139
+ else:
140
+ # In normal mode, run with app instance
141
+ uvicorn.run(
142
+ app,
143
+ host=host,
144
+ port=port,
145
+ reload=False,
146
+ log_level=config.get("logging.level", "info").lower()
147
+ )
42
148
 
43
149
 
44
150
  if __name__ == "__main__":
@@ -6,6 +6,7 @@ This module contains a command that returns detailed information about the syste
6
6
 
7
7
  import os
8
8
  import sys
9
+ import socket
9
10
  import platform
10
11
  import datetime
11
12
  from typing import Dict, Any, Optional, List
@@ -9,9 +9,13 @@ import os
9
9
  import sys
10
10
  import argparse
11
11
  from typing import Dict, Any
12
+ from pathlib import Path
12
13
 
13
14
  import mcp_proxy_adapter as mcp
14
15
  from mcp_proxy_adapter import MicroService
16
+ from mcp_proxy_adapter.commands.command_registry import registry
17
+ from mcp_proxy_adapter.core.logging import logger
18
+ from mcp_proxy_adapter.config import config
15
19
 
16
20
  # Add commands directory to path for local imports
17
21
  sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
@@ -53,29 +57,79 @@ def ensure_directories(config_path: str):
53
57
  os.makedirs(os.path.join(base_dir, "data"), exist_ok=True)
54
58
 
55
59
 
56
- def main():
57
- """Run microservice with command discovery."""
58
- # Parse command line arguments
59
- args = parse_args()
60
+ def setup_application(config_file=None):
61
+ """
62
+ Setup and configure the microservice application.
63
+
64
+ Args:
65
+ config_file: Path to configuration file (optional)
66
+
67
+ Returns:
68
+ Configured microservice object
69
+ """
70
+ # Parse command line arguments if config_file not provided
71
+ if config_file is None:
72
+ args = parse_args()
73
+ config_file = args.config
60
74
 
61
75
  # Get absolute path to config file
62
- current_dir = os.path.dirname(os.path.abspath(__file__))
63
- config_path = os.path.join(current_dir, args.config)
76
+ current_dir = Path(__file__).parent.absolute()
77
+ config_path = current_dir / config_file
78
+
79
+ # Fall back to config.json if specified file doesn't exist
80
+ if not config_path.exists():
81
+ config_path = current_dir / "config.json"
64
82
 
65
83
  # Create necessary directories
66
- ensure_directories(config_path)
84
+ ensure_directories(str(config_path))
85
+
86
+ # Load configuration if exists
87
+ if config_path.exists():
88
+ config.load_from_file(str(config_path))
89
+ logger.info(f"Loaded configuration from {config_path}")
90
+ else:
91
+ logger.warning(f"Configuration file {config_path} not found, using defaults")
67
92
 
68
93
  # Create microservice
69
94
  service = MicroService(
70
95
  title="Complete MCP Microservice Example",
71
96
  description="Full-featured microservice with Docker support",
72
97
  version="1.0.0",
73
- config_path=config_path
98
+ config_path=str(config_path) if config_path.exists() else None
74
99
  )
75
100
 
76
- # Discover and register commands
77
- package_path = "commands"
78
- service.discover_commands(package_path)
101
+ # Safely register commands from package
102
+ try:
103
+ # Clear any existing registrations to prevent conflicts
104
+ package_path = "commands"
105
+
106
+ # Get currently registered commands
107
+ commands = registry.get_all_commands()
108
+ for cmd_name in list(commands.keys()):
109
+ try:
110
+ registry.unregister(cmd_name)
111
+ except Exception as e:
112
+ logger.debug(f"Error unregistering command {cmd_name}: {e}")
113
+
114
+ # Discover and register commands
115
+ service.discover_commands(package_path)
116
+ logger.info(f"Discovered and registered commands from package: {package_path}")
117
+ except Exception as e:
118
+ logger.error(f"Error discovering commands: {e}")
119
+
120
+ return service
121
+
122
+
123
+ def main():
124
+ """Run microservice with command discovery."""
125
+ # Setup application
126
+ service = setup_application()
127
+
128
+ # Check if port is overridden by environment variable (for testing)
129
+ if "TEST_SERVER_PORT" in os.environ:
130
+ port = int(os.environ["TEST_SERVER_PORT"])
131
+ service.port = port
132
+ logger.info(f"Using test port from environment: {port}")
79
133
 
80
134
  # Run server with parameters from configuration
81
135
  service.run()
@@ -1,4 +1,4 @@
1
- # Минимальный пример MCP Microservice
1
+ # Минимальный пример MCP Proxy Adapter
2
2
 
3
3
  Данный пример демонстрирует минимальную конфигурацию для запуска микросервиса с одной простой командой.
4
4
 
@@ -6,9 +6,12 @@
6
6
 
7
7
  ```
8
8
  minimal_example/
9
- ├── config.yaml # Файл конфигурации
9
+ ├── config.json # Файл конфигурации в JSON формате
10
10
  ├── README.md # Документация
11
- └── simple_server.py # Пример сервера с одной командой
11
+ ├── simple_server.py # Пример сервера с одной командой
12
+ └── tests/ # Директория с интеграционными тестами
13
+ ├── conftest.py # Настройка тестов
14
+ └── test_integration.py # Интеграционные тесты
12
15
  ```
13
16
 
14
17
  ## Запуск примера
@@ -43,9 +46,20 @@ curl -X POST "http://localhost:8000/cmd" \
43
46
  -d '{"command": "hello", "params": {"name": "User"}}'
44
47
  ```
45
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
+
46
59
  ## Что демонстрирует этот пример
47
60
 
48
- 1. Создание минимального микросервиса
49
- 2. Определение простой команды
61
+ 1. Создание минимального сервиса с MCP Proxy Adapter
62
+ 2. Определение простой команды с метаданными
50
63
  3. Основные эндпоинты API
51
- 4. Работа с JSON-RPC
64
+ 4. Работа с JSON-RPC
65
+ 5. Тестирование API через интеграционные тесты
@@ -1,21 +1,14 @@
1
1
  {
2
- "service": {
3
- "name": "Minimal Example",
4
- "version": "1.0.0"
5
- },
6
2
  "server": {
7
3
  "host": "0.0.0.0",
8
4
  "port": 8000,
9
5
  "debug": true,
10
- "log_level": "info"
6
+ "log_level": "INFO"
11
7
  },
12
8
  "logging": {
13
- "level": "INFO",
14
- "file": "logs/minimal_example.log",
15
- "rotation": {
16
- "type": "size",
17
- "max_bytes": 10485760,
18
- "backup_count": 5
19
- }
20
- }
21
- }
9
+ "level": "info",
10
+ "file": null,
11
+ "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
12
+ },
13
+ "debug": true
14
+ }