mcp-proxy-adapter 4.1.1__py3-none-any.whl → 6.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 (101) hide show
  1. mcp_proxy_adapter/__main__.py +12 -0
  2. mcp_proxy_adapter/api/app.py +138 -11
  3. mcp_proxy_adapter/api/handlers.py +16 -1
  4. mcp_proxy_adapter/api/middleware/__init__.py +30 -29
  5. mcp_proxy_adapter/api/middleware/auth_adapter.py +235 -0
  6. mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
  7. mcp_proxy_adapter/api/middleware/factory.py +219 -0
  8. mcp_proxy_adapter/api/middleware/logging.py +32 -6
  9. mcp_proxy_adapter/api/middleware/mtls_adapter.py +305 -0
  10. mcp_proxy_adapter/api/middleware/mtls_middleware.py +296 -0
  11. mcp_proxy_adapter/api/middleware/protocol_middleware.py +135 -0
  12. mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +241 -0
  13. mcp_proxy_adapter/api/middleware/roles_adapter.py +365 -0
  14. mcp_proxy_adapter/api/middleware/roles_middleware.py +381 -0
  15. mcp_proxy_adapter/api/middleware/security.py +376 -0
  16. mcp_proxy_adapter/api/middleware/token_auth_middleware.py +261 -0
  17. mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
  18. mcp_proxy_adapter/commands/__init__.py +13 -4
  19. mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
  20. mcp_proxy_adapter/commands/base.py +61 -30
  21. mcp_proxy_adapter/commands/builtin_commands.py +89 -0
  22. mcp_proxy_adapter/commands/catalog_manager.py +838 -0
  23. mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
  24. mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
  25. mcp_proxy_adapter/commands/command_registry.py +703 -354
  26. mcp_proxy_adapter/commands/dependency_manager.py +245 -0
  27. mcp_proxy_adapter/commands/health_command.py +7 -0
  28. mcp_proxy_adapter/commands/hooks.py +200 -167
  29. mcp_proxy_adapter/commands/key_management_command.py +506 -0
  30. mcp_proxy_adapter/commands/load_command.py +176 -0
  31. mcp_proxy_adapter/commands/plugins_command.py +235 -0
  32. mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
  33. mcp_proxy_adapter/commands/proxy_registration_command.py +268 -0
  34. mcp_proxy_adapter/commands/reload_command.py +48 -50
  35. mcp_proxy_adapter/commands/result.py +1 -0
  36. mcp_proxy_adapter/commands/roles_management_command.py +697 -0
  37. mcp_proxy_adapter/commands/ssl_setup_command.py +483 -0
  38. mcp_proxy_adapter/commands/token_management_command.py +529 -0
  39. mcp_proxy_adapter/commands/transport_management_command.py +144 -0
  40. mcp_proxy_adapter/commands/unload_command.py +158 -0
  41. mcp_proxy_adapter/config.py +99 -2
  42. mcp_proxy_adapter/core/auth_validator.py +606 -0
  43. mcp_proxy_adapter/core/certificate_utils.py +827 -0
  44. mcp_proxy_adapter/core/config_converter.py +405 -0
  45. mcp_proxy_adapter/core/config_validator.py +218 -0
  46. mcp_proxy_adapter/core/logging.py +11 -0
  47. mcp_proxy_adapter/core/protocol_manager.py +226 -0
  48. mcp_proxy_adapter/core/proxy_registration.py +270 -0
  49. mcp_proxy_adapter/core/role_utils.py +426 -0
  50. mcp_proxy_adapter/core/security_adapter.py +373 -0
  51. mcp_proxy_adapter/core/security_factory.py +239 -0
  52. mcp_proxy_adapter/core/settings.py +1 -0
  53. mcp_proxy_adapter/core/ssl_utils.py +233 -0
  54. mcp_proxy_adapter/core/transport_manager.py +292 -0
  55. mcp_proxy_adapter/custom_openapi.py +22 -11
  56. mcp_proxy_adapter/examples/basic_server/config.json +58 -23
  57. mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +54 -0
  58. mcp_proxy_adapter/examples/basic_server/config_http.json +70 -0
  59. mcp_proxy_adapter/examples/basic_server/config_http_only.json +52 -0
  60. mcp_proxy_adapter/examples/basic_server/config_https.json +58 -0
  61. mcp_proxy_adapter/examples/basic_server/config_mtls.json +58 -0
  62. mcp_proxy_adapter/examples/basic_server/config_ssl.json +46 -0
  63. mcp_proxy_adapter/examples/basic_server/server.py +12 -1
  64. mcp_proxy_adapter/examples/custom_commands/__init__.py +1 -1
  65. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +339 -23
  66. mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +105 -0
  67. mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +129 -0
  68. mcp_proxy_adapter/examples/custom_commands/config.json +101 -18
  69. mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +46 -0
  70. mcp_proxy_adapter/examples/custom_commands/config_https_only.json +46 -0
  71. mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +33 -0
  72. mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +46 -0
  73. mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +33 -0
  74. mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +33 -0
  75. mcp_proxy_adapter/examples/custom_commands/full_help_response.json +1 -0
  76. mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +629 -0
  77. mcp_proxy_adapter/examples/custom_commands/get_openapi.py +103 -0
  78. mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +129 -0
  79. mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +278 -0
  80. mcp_proxy_adapter/examples/custom_commands/server.py +92 -68
  81. mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +75 -0
  82. mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +299 -0
  83. mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +278 -0
  84. mcp_proxy_adapter/examples/custom_commands/test_openapi.py +27 -0
  85. mcp_proxy_adapter/examples/custom_commands/test_registry.py +23 -0
  86. mcp_proxy_adapter/examples/custom_commands/test_simple.py +19 -0
  87. mcp_proxy_adapter/examples/custom_project_example/README.md +103 -0
  88. mcp_proxy_adapter/examples/custom_project_example/README_EN.md +103 -0
  89. mcp_proxy_adapter/examples/simple_custom_commands/README.md +149 -0
  90. mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +149 -0
  91. mcp_proxy_adapter/main.py +175 -0
  92. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  93. mcp_proxy_adapter/tests/unit/test_config.py +53 -0
  94. mcp_proxy_adapter/version.py +1 -1
  95. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/METADATA +2 -1
  96. mcp_proxy_adapter-6.0.0.dist-info/RECORD +179 -0
  97. mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
  98. mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
  99. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/WHEEL +0 -0
  100. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/licenses/LICENSE +0 -0
  101. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,278 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Server startup script with proper registration sequence.
4
+ First starts the server, then registers with proxy after server is ready.
5
+ """
6
+
7
+ import asyncio
8
+ import time
9
+ import sys
10
+ import os
11
+ import uvicorn
12
+ import threading
13
+ from pathlib import Path
14
+
15
+ # Add parent directories to path
16
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
17
+
18
+ from mcp_proxy_adapter import create_app
19
+ from mcp_proxy_adapter.core.logging import get_logger, setup_logging
20
+ from mcp_proxy_adapter.core.settings import (
21
+ Settings,
22
+ get_server_host,
23
+ get_server_port,
24
+ get_server_debug,
25
+ get_setting,
26
+ get_custom_setting_value
27
+ )
28
+ from mcp_proxy_adapter.core.ssl_utils import SSLUtils
29
+ from mcp_proxy_adapter.core.transport_manager import transport_manager
30
+ from mcp_proxy_adapter.core.proxy_registration import register_with_proxy
31
+ from custom_settings_manager import CustomSettingsManager, get_app_name, is_feature_enabled
32
+
33
+ # Import custom commands and hooks
34
+ from custom_help_command import CustomHelpCommand
35
+ from custom_health_command import CustomHealthCommand
36
+ from data_transform_command import DataTransformCommand
37
+ from intercept_command import InterceptCommand
38
+ from advanced_hooks import register_advanced_hooks
39
+
40
+ # Import auto-registered commands
41
+ from auto_commands.auto_echo_command import AutoEchoCommand
42
+ from auto_commands.auto_info_command import AutoInfoCommand
43
+
44
+ # Import manual registration example
45
+ from manual_echo_command import ManualEchoCommand
46
+
47
+ # Import echo command
48
+ from echo_command import EchoCommand
49
+
50
+ # Import custom OpenAPI generator
51
+ from custom_openapi_generator import custom_openapi_generator
52
+
53
+ # Import command registry for manual registration
54
+ from mcp_proxy_adapter.commands.command_registry import registry
55
+ from mcp_proxy_adapter.config import config
56
+ from mcp_proxy_adapter.commands.hooks import register_custom_commands_hook
57
+
58
+
59
+ def custom_commands_hook(registry):
60
+ """Hook function for registering custom commands."""
61
+ logger = get_logger("custom_commands")
62
+ logger.info("Registering custom commands via hook...")
63
+
64
+ # Get custom commands configuration from custom settings
65
+ custom_commands_config = get_custom_setting_value("custom_commands", {})
66
+
67
+ # Register echo command (only if not already registered)
68
+ if not registry.command_exists("echo"):
69
+ registry.register_custom(EchoCommand)
70
+ logger.info("Registered: echo command")
71
+ else:
72
+ logger.debug("Command 'echo' is already registered, skipping")
73
+
74
+ # Register custom help command (will override built-in)
75
+ if custom_commands_config.get("help", {}).get("enabled", True):
76
+ registry.register_custom(CustomHelpCommand)
77
+ logger.info("Registered: custom help command")
78
+
79
+ # Register custom health command (will override built-in)
80
+ if custom_commands_config.get("health", {}).get("enabled", True):
81
+ registry.register_custom(CustomHealthCommand)
82
+ logger.info("Registered: custom health command")
83
+
84
+ # Register advanced demonstration commands
85
+ if custom_commands_config.get("data_transform", {}).get("enabled", True):
86
+ registry.register_custom(DataTransformCommand)
87
+ logger.info("Registered: data_transform command")
88
+
89
+ if custom_commands_config.get("intercept", {}).get("enabled", True):
90
+ registry.register_custom(InterceptCommand)
91
+ logger.info("Registered: intercept command")
92
+
93
+
94
+ def setup_hooks():
95
+ """Setup hooks for command processing."""
96
+ logger = get_logger("custom_commands")
97
+ logger.info("Setting up hooks...")
98
+
99
+ # Register custom commands hook
100
+ register_custom_commands_hook(custom_commands_hook)
101
+
102
+ # Note: Advanced hooks are not compatible with current API
103
+ # They will be registered automatically by the command registry
104
+ logger.info("Basic hooks setup completed")
105
+
106
+
107
+ async def initialize_commands():
108
+ """
109
+ Initialize commands using the unified system initialization logic.
110
+ This function is used both at startup and during reload.
111
+
112
+ Returns:
113
+ Number of commands discovered.
114
+ """
115
+ # Use the unified reload method from registry
116
+ result = await registry.reload_system()
117
+ return result["total_commands"]
118
+
119
+
120
+ async def register_with_proxy_after_startup():
121
+ """
122
+ Register with proxy after server is fully started and listening.
123
+ """
124
+ logger = get_logger("proxy_registration")
125
+
126
+ # Wait a bit for server to fully start
127
+ await asyncio.sleep(3)
128
+
129
+ # Get server configuration
130
+ server_config = config.get("server", {})
131
+ server_host = server_config.get("host", "0.0.0.0")
132
+ server_port = server_config.get("port", 8000)
133
+
134
+ # Use localhost for external access if host is 0.0.0.0
135
+ if server_host == "0.0.0.0":
136
+ server_host = "localhost"
137
+
138
+ server_url = f"http://{server_host}:{server_port}"
139
+
140
+ logger.info(f"Attempting to register server with proxy at {server_url}")
141
+
142
+ # Attempt registration
143
+ registration_success = await register_with_proxy(server_url)
144
+ if registration_success:
145
+ logger.info("✅ Successfully registered with proxy after server startup")
146
+ else:
147
+ logger.warning("⚠️ Failed to register with proxy after server startup")
148
+
149
+
150
+ def start_server():
151
+ """Start the server in a separate thread."""
152
+ # Initialize settings
153
+ settings = Settings()
154
+ server_settings = settings.get_server_settings()
155
+ logging_settings = settings.get_logging_settings()
156
+ commands_settings = settings.get_commands_settings()
157
+
158
+ # Setup logging - pass only the level, not the entire dict
159
+ setup_logging(logging_settings.get('level', 'INFO'))
160
+ logger = get_logger("server_startup")
161
+
162
+ # Load transport configuration
163
+ if not transport_manager.load_config(config.config_data):
164
+ logger.error("Failed to load transport configuration")
165
+ return
166
+
167
+ # Validate transport configuration
168
+ if not transport_manager.validate_config():
169
+ logger.error("Transport configuration validation failed")
170
+ return
171
+
172
+ # Print server header and description
173
+ print("=" * 80)
174
+ print("🔧 ADVANCED MCP PROXY ADAPTER SERVER WITH HOOKS")
175
+ print("=" * 80)
176
+ print("📋 Description:")
177
+ print(f" {get_app_name()} - Advanced server with custom settings management")
178
+ print()
179
+
180
+ # Get transport info
181
+ transport_info = transport_manager.get_transport_info()
182
+
183
+ print("⚙️ Configuration:")
184
+ print(f" • Server: {server_settings['host']}:{transport_manager.get_port()}")
185
+ print(f" • Transport: {transport_info['type']}")
186
+ print(f" • Debug: {server_settings['debug']}")
187
+ print(f" • Log Level: {logging_settings.get('level', 'INFO')}")
188
+ print(f" • Log Directory: {logging_settings.get('log_dir', './logs')}")
189
+ print(f" • Auto Discovery: {commands_settings['auto_discovery']}")
190
+ print(f" • SSL Enabled: {transport_info['ssl_enabled']}")
191
+ if transport_info['ssl_enabled']:
192
+ ssl_config = transport_info['ssl_config']
193
+ print(f" • SSL Cert: {ssl_config.get('cert_file', 'Not specified')}")
194
+ print(f" • Client Verification: {ssl_config.get('verify_client', False)}")
195
+ print()
196
+ print("🔧 Available Commands:")
197
+ print(" • help - Custom help command (overrides built-in)")
198
+ print(" • health - Custom health command (overrides built-in)")
199
+ print(" • config - Built-in config command")
200
+ print(" • reload - Built-in reload command")
201
+ print(" • settings - Built-in settings command")
202
+ print(" • load - Built-in load command")
203
+ print(" • unload - Built-in unload command")
204
+ print(" • plugins - Built-in plugins command")
205
+ print(" • echo - Custom echo command")
206
+ print(" • data_transform - Data transformation command")
207
+ print(" • intercept - Command interception example")
208
+ print(" • manual_echo - Manually registered echo command")
209
+ print(" • test - Remote command (loaded from plugin server)")
210
+ print()
211
+ print("🎯 Features:")
212
+ print(" • Advanced JSON-RPC API")
213
+ print(" • Custom commands with hooks")
214
+ print(" • Data transformation hooks")
215
+ print(" • Command interception hooks")
216
+ print(" • Auto-registration and manual registration")
217
+ print(" • Custom OpenAPI schema generation")
218
+ print(" • Configuration-driven settings")
219
+ print(" • Custom settings management")
220
+ print("=" * 80)
221
+ print()
222
+
223
+ logger.info("Starting Advanced Custom Commands MCP Proxy Adapter Server with Hooks...")
224
+ logger.info(f"Server configuration: {server_settings}")
225
+ logger.info(f"Logging configuration: {logging_settings}")
226
+ logger.info(f"Commands configuration: {commands_settings}")
227
+ logger.info(f"Transport configuration: {transport_info}")
228
+
229
+ # Setup hooks for command processing
230
+ setup_hooks()
231
+
232
+ # Initialize commands
233
+ asyncio.run(initialize_commands())
234
+
235
+ # Create application with settings from configuration
236
+ app = create_app(
237
+ title=get_app_name(),
238
+ description="Advanced MCP Proxy Adapter server with custom settings management, demonstrating hook capabilities including data transformation, command interception, conditional processing, and smart interception hooks. Features custom commands with enhanced functionality and comprehensive settings management.",
239
+ version="2.1.0"
240
+ )
241
+
242
+ # Get uvicorn configuration from transport manager
243
+ uvicorn_config = transport_manager.get_uvicorn_config()
244
+ uvicorn_config["host"] = server_settings['host']
245
+ uvicorn_config["log_level"] = server_settings['log_level'].lower()
246
+
247
+ logger.info(f"Starting server with uvicorn config: {uvicorn_config}")
248
+
249
+ # Run the server with configuration settings
250
+ uvicorn.run(
251
+ app,
252
+ **uvicorn_config
253
+ )
254
+
255
+
256
+ def main():
257
+ """Main function to start server and register with proxy."""
258
+ # Start server in a separate thread
259
+ server_thread = threading.Thread(target=start_server, daemon=True)
260
+ server_thread.start()
261
+
262
+ # Wait for server to start
263
+ time.sleep(5)
264
+
265
+ # Register with proxy after server is ready
266
+ asyncio.run(register_with_proxy_after_startup())
267
+
268
+ # Keep main thread alive
269
+ try:
270
+ while True:
271
+ time.sleep(1)
272
+ except KeyboardInterrupt:
273
+ print("\n🛑 Server shutdown requested")
274
+ sys.exit(0)
275
+
276
+
277
+ if __name__ == "__main__":
278
+ main()
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simple test server to get OpenAPI schema.
4
+ """
5
+
6
+ import uvicorn
7
+ from fastapi import FastAPI
8
+ from mcp_proxy_adapter.custom_openapi import custom_openapi_with_fallback
9
+
10
+ # Create FastAPI app
11
+ app = FastAPI(
12
+ title="Test MCP Proxy Server",
13
+ description="Test server for OpenAPI schema",
14
+ version="1.0.0"
15
+ )
16
+
17
+ # Set custom OpenAPI generator
18
+ app.openapi = lambda: custom_openapi_with_fallback(app)
19
+
20
+ # Add OpenAPI endpoint
21
+ @app.get("/openapi.json")
22
+ async def get_openapi_schema():
23
+ """Returns OpenAPI schema."""
24
+ return custom_openapi_with_fallback(app)
25
+
26
+ if __name__ == "__main__":
27
+ uvicorn.run(app, host="0.0.0.0", port=8001)
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test script to understand registry issues.
4
+ """
5
+
6
+ import sys
7
+ import os
8
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
9
+
10
+ print("1. Importing registry directly...")
11
+ from mcp_proxy_adapter.commands.command_registry import registry
12
+ print(f" Registry type: {type(registry)}")
13
+ print(f" Registry has reload_system: {hasattr(registry, 'reload_system')}")
14
+ print(f" Registry methods: {[m for m in dir(registry) if not m.startswith('_')]}")
15
+
16
+ print("2. Testing reload_system...")
17
+ try:
18
+ result = registry.reload_system()
19
+ print(f" ✅ reload_system worked: {result}")
20
+ except Exception as e:
21
+ print(f" ❌ reload_system failed: {e}")
22
+ import traceback
23
+ traceback.print_exc()
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simple test in custom_commands directory.
4
+ """
5
+
6
+ import sys
7
+ import os
8
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
9
+
10
+ print("1. Importing registry directly...")
11
+ from mcp_proxy_adapter.commands.command_registry import registry
12
+ print(f" Registry has reload_system: {hasattr(registry, 'reload_system')}")
13
+
14
+ print("2. Testing reload_system...")
15
+ try:
16
+ result = registry.reload_system()
17
+ print(f" ✅ reload_system worked: {result}")
18
+ except Exception as e:
19
+ print(f" ❌ reload_system failed: {e}")
@@ -0,0 +1,103 @@
1
+ # Пример пользовательского проекта с командами
2
+
3
+ Этот пример показывает, как создать свой проект с командами и настроить `discovery_path` для их автоматического обнаружения.
4
+
5
+ ## Структура проекта
6
+
7
+ ```
8
+ myproject/
9
+ ├── config.json
10
+ ├── main.py
11
+ ├── myproject/
12
+ │ ├── __init__.py
13
+ │ └── commands/
14
+ │ ├── __init__.py
15
+ │ ├── echo_command.py
16
+ │ └── info_command.py
17
+ └── README.md
18
+ ```
19
+
20
+ ## Конфигурация
21
+
22
+ В файле `config.json` указываем путь к нашим командам:
23
+
24
+ ```json
25
+ {
26
+ "server": {
27
+ "host": "127.0.0.1",
28
+ "port": 8001,
29
+ "debug": true,
30
+ "log_level": "DEBUG"
31
+ },
32
+ "logging": {
33
+ "level": "DEBUG",
34
+ "log_dir": "./logs",
35
+ "log_file": "myproject.log"
36
+ },
37
+ "commands": {
38
+ "auto_discovery": true,
39
+ "discovery_path": "myproject.commands"
40
+ }
41
+ }
42
+ ```
43
+
44
+ ## Команды
45
+
46
+ ### echo_command.py
47
+
48
+ ```python
49
+ from mcp_proxy_adapter.commands.base import Command
50
+ from mcp_proxy_adapter.commands.result import CommandResult
51
+
52
+ class EchoCommand(Command):
53
+ """Echo command that returns the input text."""
54
+
55
+ name = "echo"
56
+
57
+ def execute(self, text: str) -> CommandResult:
58
+ return CommandResult(success=True, data={"echo": text})
59
+
60
+ @classmethod
61
+ def get_param_info(cls) -> dict:
62
+ return {
63
+ "text": {
64
+ "type": "string",
65
+ "description": "Text to echo",
66
+ "required": True
67
+ }
68
+ }
69
+ ```
70
+
71
+ ### info_command.py
72
+
73
+ ```python
74
+ from mcp_proxy_adapter.commands.base import Command
75
+ from mcp_proxy_adapter.commands.result import CommandResult
76
+
77
+ class InfoCommand(Command):
78
+ """Info command that returns project information."""
79
+
80
+ name = "info"
81
+
82
+ def execute(self) -> CommandResult:
83
+ return CommandResult(
84
+ success=True,
85
+ data={
86
+ "project": "myproject",
87
+ "version": "1.0.0",
88
+ "description": "Example project with custom commands"
89
+ }
90
+ )
91
+
92
+ @classmethod
93
+ def get_param_info(cls) -> dict:
94
+ return {}
95
+ ```
96
+
97
+ ## Запуск
98
+
99
+ ```bash
100
+ python main.py
101
+ ```
102
+
103
+ При запуске сервис автоматически обнаружит команды из пакета `myproject.commands` благодаря настройке `discovery_path` в конфигурации.
@@ -0,0 +1,103 @@
1
+ # Custom Project Example with Commands
2
+
3
+ This example shows how to create your own project with commands and configure `discovery_path` for their automatic discovery.
4
+
5
+ ## Project Structure
6
+
7
+ ```
8
+ myproject/
9
+ ├── config.json
10
+ ├── main.py
11
+ ├── myproject/
12
+ │ ├── __init__.py
13
+ │ └── commands/
14
+ │ ├── __init__.py
15
+ │ ├── echo_command.py
16
+ │ └── info_command.py
17
+ └── README.md
18
+ ```
19
+
20
+ ## Configuration
21
+
22
+ In the `config.json` file, specify the path to our commands:
23
+
24
+ ```json
25
+ {
26
+ "server": {
27
+ "host": "127.0.0.1",
28
+ "port": 8001,
29
+ "debug": true,
30
+ "log_level": "DEBUG"
31
+ },
32
+ "logging": {
33
+ "level": "DEBUG",
34
+ "log_dir": "./logs",
35
+ "log_file": "myproject.log"
36
+ },
37
+ "commands": {
38
+ "auto_discovery": true,
39
+ "discovery_path": "myproject.commands"
40
+ }
41
+ }
42
+ ```
43
+
44
+ ## Commands
45
+
46
+ ### echo_command.py
47
+
48
+ ```python
49
+ from mcp_proxy_adapter.commands.base import Command
50
+ from mcp_proxy_adapter.commands.result import CommandResult
51
+
52
+ class EchoCommand(Command):
53
+ """Echo command that returns the input text."""
54
+
55
+ name = "echo"
56
+
57
+ def execute(self, text: str) -> CommandResult:
58
+ return CommandResult(success=True, data={"echo": text})
59
+
60
+ @classmethod
61
+ def get_param_info(cls) -> dict:
62
+ return {
63
+ "text": {
64
+ "type": "string",
65
+ "description": "Text to echo",
66
+ "required": True
67
+ }
68
+ }
69
+ ```
70
+
71
+ ### info_command.py
72
+
73
+ ```python
74
+ from mcp_proxy_adapter.commands.base import Command
75
+ from mcp_proxy_adapter.commands.result import CommandResult
76
+
77
+ class InfoCommand(Command):
78
+ """Info command that returns project information."""
79
+
80
+ name = "info"
81
+
82
+ def execute(self) -> CommandResult:
83
+ return CommandResult(
84
+ success=True,
85
+ data={
86
+ "project": "myproject",
87
+ "version": "1.0.0",
88
+ "description": "Example project with custom commands"
89
+ }
90
+ )
91
+
92
+ @classmethod
93
+ def get_param_info(cls) -> dict:
94
+ return {}
95
+ ```
96
+
97
+ ## Running
98
+
99
+ ```bash
100
+ python main.py
101
+ ```
102
+
103
+ When starting, the service will automatically discover commands from the `myproject.commands` package thanks to the `discovery_path` configuration setting.