mcp-proxy-adapter 6.0.0__py3-none-any.whl → 6.1.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.
- mcp_proxy_adapter/api/app.py +174 -80
- mcp_proxy_adapter/api/handlers.py +16 -5
- mcp_proxy_adapter/api/middleware/__init__.py +9 -4
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
- mcp_proxy_adapter/api/middleware/factory.py +36 -12
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +32 -13
- mcp_proxy_adapter/api/middleware/unified_security.py +160 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +83 -0
- mcp_proxy_adapter/commands/__init__.py +7 -1
- mcp_proxy_adapter/commands/base.py +7 -4
- mcp_proxy_adapter/commands/builtin_commands.py +8 -2
- mcp_proxy_adapter/commands/command_registry.py +8 -0
- mcp_proxy_adapter/commands/echo_command.py +81 -0
- mcp_proxy_adapter/commands/help_command.py +21 -14
- mcp_proxy_adapter/commands/proxy_registration_command.py +326 -185
- mcp_proxy_adapter/commands/role_test_command.py +141 -0
- mcp_proxy_adapter/commands/security_command.py +488 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +2 -2
- mcp_proxy_adapter/commands/token_management_command.py +1 -1
- mcp_proxy_adapter/config.py +81 -21
- mcp_proxy_adapter/core/app_factory.py +326 -0
- mcp_proxy_adapter/core/client_security.py +384 -0
- mcp_proxy_adapter/core/logging.py +8 -3
- mcp_proxy_adapter/core/mtls_asgi.py +156 -0
- mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
- mcp_proxy_adapter/core/protocol_manager.py +139 -8
- mcp_proxy_adapter/core/proxy_client.py +602 -0
- mcp_proxy_adapter/core/proxy_registration.py +299 -47
- mcp_proxy_adapter/core/security_adapter.py +12 -15
- mcp_proxy_adapter/core/security_integration.py +285 -0
- mcp_proxy_adapter/core/server_adapter.py +345 -0
- mcp_proxy_adapter/core/server_engine.py +364 -0
- mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
- mcp_proxy_adapter/docs/EN/TROUBLESHOOTING.md +285 -0
- mcp_proxy_adapter/docs/RU/TROUBLESHOOTING.md +285 -0
- mcp_proxy_adapter/examples/README.md +230 -97
- mcp_proxy_adapter/examples/README_EN.md +258 -0
- mcp_proxy_adapter/examples/SECURITY_TESTING.md +455 -0
- mcp_proxy_adapter/examples/basic_framework/configs/http_auth.json +37 -0
- mcp_proxy_adapter/examples/basic_framework/configs/http_simple.json +23 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_auth.json +43 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_no_protocol_middleware.json +36 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +29 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_protocol_middleware.json +34 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +39 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_simple.json +35 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_with_roles.json +45 -0
- mcp_proxy_adapter/examples/basic_framework/main.py +63 -0
- mcp_proxy_adapter/examples/basic_framework/roles.json +21 -0
- mcp_proxy_adapter/examples/cert_config.json +9 -0
- mcp_proxy_adapter/examples/certs/admin.crt +32 -0
- mcp_proxy_adapter/examples/certs/admin.key +52 -0
- mcp_proxy_adapter/examples/certs/admin_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/admin_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/ca_cert.pem +23 -0
- mcp_proxy_adapter/examples/certs/ca_cert.srl +1 -0
- mcp_proxy_adapter/examples/certs/ca_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/cert_config.json +9 -0
- mcp_proxy_adapter/examples/certs/client.crt +32 -0
- mcp_proxy_adapter/examples/certs/client.key +52 -0
- mcp_proxy_adapter/examples/certs/client_admin.crt +32 -0
- mcp_proxy_adapter/examples/certs/client_admin.key +52 -0
- mcp_proxy_adapter/examples/certs/client_user.crt +32 -0
- mcp_proxy_adapter/examples/certs/client_user.key +52 -0
- mcp_proxy_adapter/examples/certs/guest_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/guest_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/mcp_proxy_adapter_ca_ca.crt +23 -0
- mcp_proxy_adapter/examples/certs/proxy_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/proxy_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/readonly.crt +32 -0
- mcp_proxy_adapter/examples/certs/readonly.key +52 -0
- mcp_proxy_adapter/examples/certs/readonly_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/readonly_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/server.crt +32 -0
- mcp_proxy_adapter/examples/certs/server.key +52 -0
- mcp_proxy_adapter/examples/certs/server_cert.pem +32 -0
- mcp_proxy_adapter/examples/certs/server_key.pem +52 -0
- mcp_proxy_adapter/examples/certs/test_ca_ca.crt +20 -0
- mcp_proxy_adapter/examples/certs/user.crt +32 -0
- mcp_proxy_adapter/examples/certs/user.key +52 -0
- mcp_proxy_adapter/examples/certs/user_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/user_key.pem +28 -0
- mcp_proxy_adapter/examples/client_configs/api_key_client.json +13 -0
- mcp_proxy_adapter/examples/client_configs/basic_auth_client.json +13 -0
- mcp_proxy_adapter/examples/client_configs/certificate_client.json +22 -0
- mcp_proxy_adapter/examples/client_configs/jwt_client.json +15 -0
- mcp_proxy_adapter/examples/client_configs/no_auth_client.json +9 -0
- mcp_proxy_adapter/examples/commands/__init__.py +1 -0
- mcp_proxy_adapter/examples/create_certificates_simple.py +307 -0
- mcp_proxy_adapter/examples/debug_request_state.py +144 -0
- mcp_proxy_adapter/examples/debug_role_chain.py +205 -0
- mcp_proxy_adapter/examples/demo_client.py +341 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +99 -0
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +106 -0
- mcp_proxy_adapter/examples/full_application/configs/http_auth.json +37 -0
- mcp_proxy_adapter/examples/full_application/configs/http_simple.json +23 -0
- mcp_proxy_adapter/examples/full_application/configs/https_auth.json +39 -0
- mcp_proxy_adapter/examples/full_application/configs/https_simple.json +25 -0
- mcp_proxy_adapter/examples/full_application/configs/mtls_no_roles.json +39 -0
- mcp_proxy_adapter/examples/full_application/configs/mtls_with_roles.json +45 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +97 -0
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +95 -0
- mcp_proxy_adapter/examples/full_application/main.py +138 -0
- mcp_proxy_adapter/examples/full_application/roles.json +21 -0
- mcp_proxy_adapter/examples/generate_all_certificates.py +429 -0
- mcp_proxy_adapter/examples/generate_certificates.py +121 -0
- mcp_proxy_adapter/examples/keys/ca_key.pem +28 -0
- mcp_proxy_adapter/examples/keys/mcp_proxy_adapter_ca_ca.key +28 -0
- mcp_proxy_adapter/examples/keys/test_ca_ca.key +28 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log +220 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.5 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log +220 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.5 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log +2 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.5 +1 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +401 -0
- mcp_proxy_adapter/examples/roles.json +38 -0
- mcp_proxy_adapter/examples/run_example.py +81 -0
- mcp_proxy_adapter/examples/run_security_tests.py +326 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +300 -0
- mcp_proxy_adapter/examples/security_test_client.py +743 -0
- mcp_proxy_adapter/examples/server_configs/config_basic_http.json +204 -0
- mcp_proxy_adapter/examples/server_configs/config_http_token.json +238 -0
- mcp_proxy_adapter/examples/server_configs/config_https.json +215 -0
- mcp_proxy_adapter/examples/server_configs/config_https_token.json +231 -0
- mcp_proxy_adapter/examples/server_configs/config_mtls.json +215 -0
- mcp_proxy_adapter/examples/server_configs/config_proxy_registration.json +250 -0
- mcp_proxy_adapter/examples/server_configs/config_simple.json +46 -0
- mcp_proxy_adapter/examples/server_configs/roles.json +38 -0
- mcp_proxy_adapter/examples/test_config_generator.py +110 -0
- mcp_proxy_adapter/examples/test_examples.py +344 -0
- mcp_proxy_adapter/examples/universal_client.py +628 -0
- mcp_proxy_adapter/main.py +21 -10
- mcp_proxy_adapter/utils/config_generator.py +727 -0
- mcp_proxy_adapter/version.py +5 -2
- mcp_proxy_adapter-6.1.1.dist-info/METADATA +205 -0
- mcp_proxy_adapter-6.1.1.dist-info/RECORD +197 -0
- mcp_proxy_adapter-6.1.1.dist-info/entry_points.txt +2 -0
- {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.1.dist-info}/licenses/LICENSE +2 -2
- mcp_proxy_adapter/api/middleware/auth.py +0 -146
- mcp_proxy_adapter/api/middleware/auth_adapter.py +0 -235
- mcp_proxy_adapter/api/middleware/mtls_adapter.py +0 -305
- mcp_proxy_adapter/api/middleware/mtls_middleware.py +0 -296
- mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
- mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +0 -241
- mcp_proxy_adapter/api/middleware/roles_adapter.py +0 -365
- mcp_proxy_adapter/api/middleware/roles_middleware.py +0 -381
- mcp_proxy_adapter/api/middleware/security.py +0 -376
- mcp_proxy_adapter/api/middleware/token_auth_middleware.py +0 -261
- mcp_proxy_adapter/examples/__init__.py +0 -7
- mcp_proxy_adapter/examples/basic_server/README.md +0 -60
- mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
- mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
- mcp_proxy_adapter/examples/basic_server/config.json +0 -70
- mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +0 -54
- mcp_proxy_adapter/examples/basic_server/config_http.json +0 -70
- mcp_proxy_adapter/examples/basic_server/config_http_only.json +0 -52
- mcp_proxy_adapter/examples/basic_server/config_https.json +0 -58
- mcp_proxy_adapter/examples/basic_server/config_mtls.json +0 -58
- mcp_proxy_adapter/examples/basic_server/config_ssl.json +0 -46
- mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
- mcp_proxy_adapter/examples/basic_server/server.py +0 -114
- mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
- mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
- mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -566
- mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
- mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +0 -105
- mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +0 -129
- mcp_proxy_adapter/examples/custom_commands/config.json +0 -118
- mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_https_only.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
- mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
- mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
- mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
- mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
- mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
- mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
- mcp_proxy_adapter/examples/custom_commands/full_help_response.json +0 -1
- mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +0 -629
- mcp_proxy_adapter/examples/custom_commands/get_openapi.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
- mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
- mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +0 -129
- mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +0 -278
- mcp_proxy_adapter/examples/custom_commands/server.py +0 -252
- mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +0 -75
- mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +0 -299
- mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +0 -278
- mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
- mcp_proxy_adapter/examples/custom_commands/test_openapi.py +0 -27
- mcp_proxy_adapter/examples/custom_commands/test_registry.py +0 -23
- mcp_proxy_adapter/examples/custom_commands/test_simple.py +0 -19
- mcp_proxy_adapter/examples/custom_project_example/README.md +0 -103
- mcp_proxy_adapter/examples/custom_project_example/README_EN.md +0 -103
- mcp_proxy_adapter/examples/deployment/README.md +0 -49
- mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
- mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
- mcp_proxy_adapter/examples/deployment/config.json +0 -29
- mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
- mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
- mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
- mcp_proxy_adapter/examples/deployment/run.sh +0 -43
- mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
- mcp_proxy_adapter/examples/simple_custom_commands/README.md +0 -149
- mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +0 -149
- mcp_proxy_adapter/schemas/base_schema.json +0 -114
- mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
- mcp_proxy_adapter/schemas/roles_schema.json +0 -162
- mcp_proxy_adapter/tests/__init__.py +0 -0
- mcp_proxy_adapter/tests/api/__init__.py +0 -3
- mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
- mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
- mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
- mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
- mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
- mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
- mcp_proxy_adapter/tests/commands/__init__.py +0 -3
- mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
- mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
- mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
- mcp_proxy_adapter/tests/conftest.py +0 -131
- mcp_proxy_adapter/tests/functional/__init__.py +0 -3
- mcp_proxy_adapter/tests/functional/test_api.py +0 -253
- mcp_proxy_adapter/tests/integration/__init__.py +0 -3
- mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
- mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
- mcp_proxy_adapter/tests/performance/__init__.py +0 -3
- mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
- mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
- mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
- mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
- mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
- mcp_proxy_adapter/tests/test_base_command.py +0 -123
- mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
- mcp_proxy_adapter/tests/test_command_registry.py +0 -281
- mcp_proxy_adapter/tests/test_config.py +0 -127
- mcp_proxy_adapter/tests/test_utils.py +0 -65
- mcp_proxy_adapter/tests/unit/__init__.py +0 -3
- mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
- mcp_proxy_adapter/tests/unit/test_config.py +0 -270
- mcp_proxy_adapter-6.0.0.dist-info/METADATA +0 -201
- mcp_proxy_adapter-6.0.0.dist-info/RECORD +0 -179
- {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.1.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.1.dist-info}/top_level.txt +0 -0
@@ -1,278 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
Proxy Connection Manager
|
4
|
-
|
5
|
-
Manages connection to the proxy server with regular health checks
|
6
|
-
and automatic re-registration when needed.
|
7
|
-
"""
|
8
|
-
|
9
|
-
import asyncio
|
10
|
-
import time
|
11
|
-
import logging
|
12
|
-
from typing import Optional, Dict, Any
|
13
|
-
from datetime import datetime, timedelta
|
14
|
-
|
15
|
-
from mcp_proxy_adapter.core.proxy_registration import register_with_proxy, unregister_from_proxy
|
16
|
-
from mcp_proxy_adapter.config import config
|
17
|
-
from mcp_proxy_adapter.core.logging import get_logger
|
18
|
-
|
19
|
-
|
20
|
-
class ProxyConnectionManager:
|
21
|
-
"""
|
22
|
-
Manages connection to proxy server with health monitoring and auto-reconnection.
|
23
|
-
"""
|
24
|
-
|
25
|
-
def __init__(self, check_interval: int = 30, max_retries: int = 3):
|
26
|
-
"""
|
27
|
-
Initialize proxy connection manager.
|
28
|
-
|
29
|
-
Args:
|
30
|
-
check_interval: Interval between health checks in seconds
|
31
|
-
max_retries: Maximum number of retry attempts
|
32
|
-
"""
|
33
|
-
self.logger = get_logger("proxy_connection_manager")
|
34
|
-
self.check_interval = check_interval
|
35
|
-
self.max_retries = max_retries
|
36
|
-
self.is_running = False
|
37
|
-
self.last_registration = None
|
38
|
-
self.registration_count = 0
|
39
|
-
self.failed_attempts = 0
|
40
|
-
self.server_url = None
|
41
|
-
self.server_id = None
|
42
|
-
|
43
|
-
# Get configuration
|
44
|
-
proxy_config = config.get("proxy_registration", {})
|
45
|
-
self.proxy_url = proxy_config.get("proxy_url", "http://localhost:3004")
|
46
|
-
self.server_id = proxy_config.get("server_id", "mcp_proxy_adapter_custom")
|
47
|
-
|
48
|
-
# Get server configuration
|
49
|
-
server_config = config.get("server", {})
|
50
|
-
server_host = server_config.get("host", "0.0.0.0")
|
51
|
-
server_port = server_config.get("port", 8000)
|
52
|
-
|
53
|
-
# Use localhost for external access if host is 0.0.0.0
|
54
|
-
if server_host == "0.0.0.0":
|
55
|
-
server_host = "localhost"
|
56
|
-
|
57
|
-
self.server_url = f"http://{server_host}:{server_port}"
|
58
|
-
|
59
|
-
self.logger.info(f"Proxy Connection Manager initialized:")
|
60
|
-
self.logger.info(f" • Server URL: {self.server_url}")
|
61
|
-
self.logger.info(f" • Proxy URL: {self.proxy_url}")
|
62
|
-
self.logger.info(f" • Server ID: {self.server_id}")
|
63
|
-
self.logger.info(f" • Check interval: {check_interval}s")
|
64
|
-
self.logger.info(f" • Max retries: {max_retries}")
|
65
|
-
|
66
|
-
async def start(self) -> None:
|
67
|
-
"""
|
68
|
-
Start the proxy connection manager.
|
69
|
-
"""
|
70
|
-
if self.is_running:
|
71
|
-
self.logger.warning("Proxy Connection Manager is already running")
|
72
|
-
return
|
73
|
-
|
74
|
-
self.is_running = True
|
75
|
-
self.logger.info("🚀 Starting Proxy Connection Manager")
|
76
|
-
|
77
|
-
# Initial registration
|
78
|
-
await self.register_with_proxy()
|
79
|
-
|
80
|
-
# Start monitoring loop
|
81
|
-
asyncio.create_task(self._monitoring_loop())
|
82
|
-
|
83
|
-
async def stop(self) -> None:
|
84
|
-
"""
|
85
|
-
Stop the proxy connection manager.
|
86
|
-
"""
|
87
|
-
if not self.is_running:
|
88
|
-
return
|
89
|
-
|
90
|
-
self.is_running = False
|
91
|
-
self.logger.info("🛑 Stopping Proxy Connection Manager")
|
92
|
-
|
93
|
-
# Unregister from proxy
|
94
|
-
await self.unregister_from_proxy()
|
95
|
-
|
96
|
-
async def register_with_proxy(self) -> bool:
|
97
|
-
"""
|
98
|
-
Register server with proxy.
|
99
|
-
|
100
|
-
Returns:
|
101
|
-
True if registration was successful, False otherwise
|
102
|
-
"""
|
103
|
-
try:
|
104
|
-
self.logger.info(f"📡 Attempting to register server with proxy at {self.proxy_url}")
|
105
|
-
|
106
|
-
success = await register_with_proxy(self.server_url)
|
107
|
-
|
108
|
-
if success:
|
109
|
-
self.last_registration = datetime.now()
|
110
|
-
self.registration_count += 1
|
111
|
-
self.failed_attempts = 0
|
112
|
-
self.logger.info(f"✅ Successfully registered with proxy (attempt #{self.registration_count})")
|
113
|
-
return True
|
114
|
-
else:
|
115
|
-
self.failed_attempts += 1
|
116
|
-
self.logger.warning(f"⚠️ Failed to register with proxy (attempt #{self.failed_attempts})")
|
117
|
-
return False
|
118
|
-
|
119
|
-
except Exception as e:
|
120
|
-
self.failed_attempts += 1
|
121
|
-
self.logger.error(f"❌ Error registering with proxy: {e}")
|
122
|
-
return False
|
123
|
-
|
124
|
-
async def unregister_from_proxy(self) -> bool:
|
125
|
-
"""
|
126
|
-
Unregister server from proxy.
|
127
|
-
|
128
|
-
Returns:
|
129
|
-
True if unregistration was successful, False otherwise
|
130
|
-
"""
|
131
|
-
try:
|
132
|
-
self.logger.info("📡 Unregistering from proxy")
|
133
|
-
|
134
|
-
success = await unregister_from_proxy()
|
135
|
-
|
136
|
-
if success:
|
137
|
-
self.logger.info("✅ Successfully unregistered from proxy")
|
138
|
-
else:
|
139
|
-
self.logger.warning("⚠️ Failed to unregister from proxy")
|
140
|
-
|
141
|
-
return success
|
142
|
-
|
143
|
-
except Exception as e:
|
144
|
-
self.logger.error(f"❌ Error unregistering from proxy: {e}")
|
145
|
-
return False
|
146
|
-
|
147
|
-
async def check_proxy_health(self) -> bool:
|
148
|
-
"""
|
149
|
-
Check if proxy is accessible and server is registered.
|
150
|
-
|
151
|
-
Returns:
|
152
|
-
True if proxy is healthy, False otherwise
|
153
|
-
"""
|
154
|
-
try:
|
155
|
-
import httpx
|
156
|
-
|
157
|
-
# Check if proxy is accessible
|
158
|
-
async with httpx.AsyncClient(timeout=5.0) as client:
|
159
|
-
response = await client.get(f"{self.proxy_url}/health")
|
160
|
-
|
161
|
-
if response.status_code == 200:
|
162
|
-
self.logger.debug("✅ Proxy health check passed")
|
163
|
-
return True
|
164
|
-
else:
|
165
|
-
self.logger.warning(f"⚠️ Proxy health check failed: {response.status_code}")
|
166
|
-
return False
|
167
|
-
|
168
|
-
except Exception as e:
|
169
|
-
self.logger.warning(f"⚠️ Proxy health check error: {e}")
|
170
|
-
return False
|
171
|
-
|
172
|
-
async def _monitoring_loop(self) -> None:
|
173
|
-
"""
|
174
|
-
Main monitoring loop that checks proxy health and re-registers if needed.
|
175
|
-
"""
|
176
|
-
self.logger.info("🔄 Starting proxy monitoring loop")
|
177
|
-
|
178
|
-
while self.is_running:
|
179
|
-
try:
|
180
|
-
# Check if we need to re-register
|
181
|
-
should_reregister = False
|
182
|
-
|
183
|
-
# Check if last registration was too long ago (more than 5 minutes)
|
184
|
-
if self.last_registration:
|
185
|
-
time_since_registration = datetime.now() - self.last_registration
|
186
|
-
if time_since_registration > timedelta(minutes=5):
|
187
|
-
self.logger.info("⏰ Last registration was more than 5 minutes ago, re-registering")
|
188
|
-
should_reregister = True
|
189
|
-
|
190
|
-
# Check proxy health
|
191
|
-
proxy_healthy = await self.check_proxy_health()
|
192
|
-
|
193
|
-
if not proxy_healthy:
|
194
|
-
self.logger.warning("⚠️ Proxy health check failed, attempting re-registration")
|
195
|
-
should_reregister = True
|
196
|
-
|
197
|
-
# Re-register if needed
|
198
|
-
if should_reregister:
|
199
|
-
if self.failed_attempts >= self.max_retries:
|
200
|
-
self.logger.error(f"❌ Max retries ({self.max_retries}) reached, stopping re-registration attempts")
|
201
|
-
break
|
202
|
-
|
203
|
-
await self.register_with_proxy()
|
204
|
-
|
205
|
-
# Log status
|
206
|
-
if self.last_registration:
|
207
|
-
time_since = datetime.now() - self.last_registration
|
208
|
-
self.logger.info(f"📊 Status: Registered {time_since.total_seconds():.0f}s ago, "
|
209
|
-
f"attempts: {self.registration_count}, "
|
210
|
-
f"failed: {self.failed_attempts}")
|
211
|
-
|
212
|
-
# Wait for next check
|
213
|
-
await asyncio.sleep(self.check_interval)
|
214
|
-
|
215
|
-
except asyncio.CancelledError:
|
216
|
-
self.logger.info("🛑 Monitoring loop cancelled")
|
217
|
-
break
|
218
|
-
except Exception as e:
|
219
|
-
self.logger.error(f"❌ Error in monitoring loop: {e}")
|
220
|
-
await asyncio.sleep(self.check_interval)
|
221
|
-
|
222
|
-
self.logger.info("🔄 Proxy monitoring loop stopped")
|
223
|
-
|
224
|
-
def get_status(self) -> Dict[str, Any]:
|
225
|
-
"""
|
226
|
-
Get current status of the connection manager.
|
227
|
-
|
228
|
-
Returns:
|
229
|
-
Dictionary with status information
|
230
|
-
"""
|
231
|
-
status = {
|
232
|
-
"is_running": self.is_running,
|
233
|
-
"server_url": self.server_url,
|
234
|
-
"proxy_url": self.proxy_url,
|
235
|
-
"server_id": self.server_id,
|
236
|
-
"registration_count": self.registration_count,
|
237
|
-
"failed_attempts": self.failed_attempts,
|
238
|
-
"check_interval": self.check_interval,
|
239
|
-
"max_retries": self.max_retries
|
240
|
-
}
|
241
|
-
|
242
|
-
if self.last_registration:
|
243
|
-
time_since = datetime.now() - self.last_registration
|
244
|
-
status["last_registration"] = self.last_registration.isoformat()
|
245
|
-
status["time_since_registration"] = time_since.total_seconds()
|
246
|
-
else:
|
247
|
-
status["last_registration"] = None
|
248
|
-
status["time_since_registration"] = None
|
249
|
-
|
250
|
-
return status
|
251
|
-
|
252
|
-
|
253
|
-
# Global instance
|
254
|
-
proxy_manager = ProxyConnectionManager()
|
255
|
-
|
256
|
-
|
257
|
-
async def start_proxy_manager() -> None:
|
258
|
-
"""
|
259
|
-
Start the global proxy connection manager.
|
260
|
-
"""
|
261
|
-
await proxy_manager.start()
|
262
|
-
|
263
|
-
|
264
|
-
async def stop_proxy_manager() -> None:
|
265
|
-
"""
|
266
|
-
Stop the global proxy connection manager.
|
267
|
-
"""
|
268
|
-
await proxy_manager.stop()
|
269
|
-
|
270
|
-
|
271
|
-
def get_proxy_manager_status() -> Dict[str, Any]:
|
272
|
-
"""
|
273
|
-
Get status of the global proxy connection manager.
|
274
|
-
|
275
|
-
Returns:
|
276
|
-
Dictionary with status information
|
277
|
-
"""
|
278
|
-
return proxy_manager.get_status()
|
@@ -1,252 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Custom Commands Server Example
|
3
|
-
|
4
|
-
This example demonstrates a MCP Proxy Adapter server
|
5
|
-
with custom commands: echo, custom help, and custom health.
|
6
|
-
Includes hooks for before and after command processing.
|
7
|
-
"""
|
8
|
-
|
9
|
-
import asyncio
|
10
|
-
import uvicorn
|
11
|
-
import sys
|
12
|
-
import os
|
13
|
-
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
14
|
-
|
15
|
-
from mcp_proxy_adapter import create_app
|
16
|
-
from mcp_proxy_adapter.core.logging import get_logger, setup_logging
|
17
|
-
from mcp_proxy_adapter.core.settings import (
|
18
|
-
Settings,
|
19
|
-
get_server_host,
|
20
|
-
get_server_port,
|
21
|
-
get_server_debug,
|
22
|
-
get_setting,
|
23
|
-
get_custom_setting_value
|
24
|
-
)
|
25
|
-
from mcp_proxy_adapter.core.ssl_utils import SSLUtils
|
26
|
-
from mcp_proxy_adapter.core.transport_manager import transport_manager
|
27
|
-
from custom_settings_manager import CustomSettingsManager, get_app_name, is_feature_enabled
|
28
|
-
|
29
|
-
# Import custom commands and hooks
|
30
|
-
from custom_help_command import CustomHelpCommand
|
31
|
-
from custom_health_command import CustomHealthCommand
|
32
|
-
from data_transform_command import DataTransformCommand
|
33
|
-
from intercept_command import InterceptCommand
|
34
|
-
from advanced_hooks import register_advanced_hooks
|
35
|
-
|
36
|
-
# Import auto-registered commands
|
37
|
-
from auto_commands.auto_echo_command import AutoEchoCommand
|
38
|
-
from auto_commands.auto_info_command import AutoInfoCommand
|
39
|
-
|
40
|
-
# Import manual registration example
|
41
|
-
from manual_echo_command import ManualEchoCommand
|
42
|
-
|
43
|
-
# Import echo command
|
44
|
-
from echo_command import EchoCommand
|
45
|
-
|
46
|
-
# Import custom OpenAPI generator
|
47
|
-
from custom_openapi_generator import custom_openapi_generator
|
48
|
-
|
49
|
-
# Import command registry for manual registration
|
50
|
-
from mcp_proxy_adapter.commands.command_registry import registry
|
51
|
-
from mcp_proxy_adapter.config import config
|
52
|
-
from mcp_proxy_adapter.commands.hooks import register_custom_commands_hook
|
53
|
-
|
54
|
-
|
55
|
-
async def initialize_commands():
|
56
|
-
"""
|
57
|
-
Initialize commands using the unified system initialization logic.
|
58
|
-
This function is used both at startup and during reload.
|
59
|
-
|
60
|
-
Returns:
|
61
|
-
Number of commands discovered.
|
62
|
-
"""
|
63
|
-
# Use the unified reload method from registry
|
64
|
-
result = await registry.reload_system()
|
65
|
-
return result["total_commands"]
|
66
|
-
|
67
|
-
|
68
|
-
def custom_commands_hook(registry):
|
69
|
-
"""Hook function for registering custom commands."""
|
70
|
-
logger = get_logger("custom_commands")
|
71
|
-
logger.info("Registering custom commands via hook...")
|
72
|
-
|
73
|
-
# Get custom commands configuration from custom settings
|
74
|
-
custom_commands_config = get_custom_setting_value("custom_commands", {})
|
75
|
-
|
76
|
-
# Register echo command (only if not already registered)
|
77
|
-
if not registry.command_exists("echo"):
|
78
|
-
registry.register_custom(EchoCommand)
|
79
|
-
logger.info("Registered: echo command")
|
80
|
-
else:
|
81
|
-
logger.debug("Command 'echo' is already registered, skipping")
|
82
|
-
|
83
|
-
# Register custom help command (will override built-in)
|
84
|
-
if custom_commands_config.get("help", {}).get("enabled", True):
|
85
|
-
registry.register_custom(CustomHelpCommand)
|
86
|
-
logger.info("Registered: custom help command")
|
87
|
-
|
88
|
-
# Register custom health command (will override built-in)
|
89
|
-
if custom_commands_config.get("health", {}).get("enabled", True):
|
90
|
-
registry.register_custom(CustomHealthCommand)
|
91
|
-
logger.info("Registered: custom health command")
|
92
|
-
|
93
|
-
# Register advanced demonstration commands
|
94
|
-
if custom_commands_config.get("data_transform", {}).get("enabled", True):
|
95
|
-
registry.register_custom(DataTransformCommand)
|
96
|
-
logger.info("Registered: data_transform command")
|
97
|
-
|
98
|
-
if custom_commands_config.get("intercept", {}).get("enabled", True):
|
99
|
-
registry.register_custom(InterceptCommand)
|
100
|
-
logger.info("Registered: intercept command")
|
101
|
-
|
102
|
-
# Register manually registered commands
|
103
|
-
if custom_commands_config.get("manual_echo", {}).get("enabled", True):
|
104
|
-
registry.register_custom(ManualEchoCommand)
|
105
|
-
logger.info("Registered: manual_echo command")
|
106
|
-
|
107
|
-
logger.info(f"Total custom commands registered: {len(registry.get_commands_by_type()['custom'])}")
|
108
|
-
|
109
|
-
|
110
|
-
def setup_hooks():
|
111
|
-
"""Setup hooks for command processing."""
|
112
|
-
logger = get_logger("custom_commands")
|
113
|
-
logger.info("Setting up hooks...")
|
114
|
-
|
115
|
-
# Register custom commands hook
|
116
|
-
from mcp_proxy_adapter.commands.hooks import register_custom_commands_hook
|
117
|
-
register_custom_commands_hook(custom_commands_hook)
|
118
|
-
|
119
|
-
logger.info("Registered: custom commands hook")
|
120
|
-
|
121
|
-
|
122
|
-
def main():
|
123
|
-
"""Run the custom commands server example with hooks."""
|
124
|
-
# Load configuration from config.json in the same directory
|
125
|
-
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
126
|
-
if os.path.exists(config_path):
|
127
|
-
from mcp_proxy_adapter.config import config
|
128
|
-
config.load_from_file(config_path)
|
129
|
-
print(f"✅ Loaded configuration from: {config_path}")
|
130
|
-
else:
|
131
|
-
print(f"⚠️ Configuration file not found: {config_path}")
|
132
|
-
print(" Using default configuration")
|
133
|
-
from mcp_proxy_adapter.config import config
|
134
|
-
config.load_config()
|
135
|
-
|
136
|
-
# Setup logging with configuration
|
137
|
-
setup_logging()
|
138
|
-
logger = get_logger("custom_commands")
|
139
|
-
|
140
|
-
# Initialize custom settings manager
|
141
|
-
custom_settings_manager = CustomSettingsManager("custom_settings.json")
|
142
|
-
|
143
|
-
# Print custom settings summary
|
144
|
-
custom_settings_manager.print_settings_summary()
|
145
|
-
|
146
|
-
# Get settings from configuration
|
147
|
-
server_settings = Settings.get_server_settings()
|
148
|
-
logging_settings = Settings.get_logging_settings()
|
149
|
-
commands_settings = Settings.get_commands_settings()
|
150
|
-
custom_settings = Settings.get_custom_setting("custom", {})
|
151
|
-
|
152
|
-
# Load transport configuration
|
153
|
-
if not transport_manager.load_config(config.config_data):
|
154
|
-
logger.error("Failed to load transport configuration")
|
155
|
-
return
|
156
|
-
|
157
|
-
# Validate transport configuration
|
158
|
-
if not transport_manager.validate_config():
|
159
|
-
logger.error("Transport configuration validation failed")
|
160
|
-
return
|
161
|
-
|
162
|
-
# Print server header and description
|
163
|
-
print("=" * 80)
|
164
|
-
print("🔧 ADVANCED MCP PROXY ADAPTER SERVER WITH HOOKS")
|
165
|
-
print("=" * 80)
|
166
|
-
print("📋 Description:")
|
167
|
-
print(f" {get_app_name()} - Advanced server with custom settings management")
|
168
|
-
print()
|
169
|
-
# Get transport info
|
170
|
-
transport_info = transport_manager.get_transport_info()
|
171
|
-
|
172
|
-
print("⚙️ Configuration:")
|
173
|
-
print(f" • Server: {server_settings['host']}:{transport_manager.get_port()}")
|
174
|
-
print(f" • Transport: {transport_info['type']}")
|
175
|
-
print(f" • Debug: {server_settings['debug']}")
|
176
|
-
print(f" • Log Level: {logging_settings['level']}")
|
177
|
-
print(f" • Log Directory: {logging_settings['log_dir']}")
|
178
|
-
print(f" • Auto Discovery: {commands_settings['auto_discovery']}")
|
179
|
-
print(f" • SSL Enabled: {transport_info['ssl_enabled']}")
|
180
|
-
if transport_info['ssl_enabled']:
|
181
|
-
ssl_config = transport_info['ssl_config']
|
182
|
-
print(f" • SSL Cert: {ssl_config.get('cert_file', 'Not specified')}")
|
183
|
-
print(f" • Client Verification: {ssl_config.get('verify_client', False)}")
|
184
|
-
print()
|
185
|
-
print("🔧 Available Commands:")
|
186
|
-
print(" • help - Custom help command (overrides built-in)")
|
187
|
-
print(" • health - Custom health command (overrides built-in)")
|
188
|
-
print(" • config - Built-in config command")
|
189
|
-
print(" • reload - Built-in reload command")
|
190
|
-
print(" • settings - Built-in settings command")
|
191
|
-
print(" • load - Built-in load command")
|
192
|
-
print(" • unload - Built-in unload command")
|
193
|
-
print(" • plugins - Built-in plugins command")
|
194
|
-
print(" • echo - Custom echo command")
|
195
|
-
print(" • data_transform - Data transformation command")
|
196
|
-
print(" • intercept - Command interception example")
|
197
|
-
print(" • manual_echo - Manually registered echo command")
|
198
|
-
print(" • test - Remote command (loaded from plugin server)")
|
199
|
-
print()
|
200
|
-
print("🎯 Features:")
|
201
|
-
print(" • Advanced JSON-RPC API")
|
202
|
-
print(" • Custom commands with hooks")
|
203
|
-
print(" • Data transformation hooks")
|
204
|
-
print(" • Command interception hooks")
|
205
|
-
print(" • Auto-registration and manual registration")
|
206
|
-
print(" • Custom OpenAPI schema generation")
|
207
|
-
print(" • Configuration-driven settings")
|
208
|
-
print(" • Custom settings management")
|
209
|
-
print("=" * 80)
|
210
|
-
print()
|
211
|
-
|
212
|
-
logger.info("Starting Advanced Custom Commands MCP Proxy Adapter Server with Hooks...")
|
213
|
-
logger.info(f"Server configuration: {server_settings}")
|
214
|
-
logger.info(f"Logging configuration: {logging_settings}")
|
215
|
-
logger.info(f"Commands configuration: {commands_settings}")
|
216
|
-
logger.info(f"Transport configuration: {transport_info}")
|
217
|
-
logger.info("This server demonstrates custom commands with hooks and remote plugin loading:")
|
218
|
-
logger.info("• Custom commands: echo, help, health, data_transform, intercept, manual_echo")
|
219
|
-
logger.info("• Built-in commands: config, reload, settings, load, unload, plugins")
|
220
|
-
logger.info("• Remote commands: test (loaded from plugin server)")
|
221
|
-
logger.info("With advanced hooks for data transformation and command interception")
|
222
|
-
|
223
|
-
# Setup hooks for command processing
|
224
|
-
setup_hooks()
|
225
|
-
|
226
|
-
# Initialize commands
|
227
|
-
import asyncio
|
228
|
-
asyncio.run(initialize_commands())
|
229
|
-
|
230
|
-
# Create application with settings from configuration
|
231
|
-
app = create_app(
|
232
|
-
title=get_app_name(),
|
233
|
-
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.",
|
234
|
-
version="2.1.0"
|
235
|
-
)
|
236
|
-
|
237
|
-
# Get uvicorn configuration from transport manager
|
238
|
-
uvicorn_config = transport_manager.get_uvicorn_config()
|
239
|
-
uvicorn_config["host"] = server_settings['host']
|
240
|
-
uvicorn_config["log_level"] = server_settings['log_level'].lower()
|
241
|
-
|
242
|
-
logger.info(f"Starting server with uvicorn config: {uvicorn_config}")
|
243
|
-
|
244
|
-
# Run the server with configuration settings
|
245
|
-
uvicorn.run(
|
246
|
-
app,
|
247
|
-
**uvicorn_config
|
248
|
-
)
|
249
|
-
|
250
|
-
|
251
|
-
if __name__ == "__main__":
|
252
|
-
main()
|
@@ -1,75 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
Simple server with fixed OpenAPI generator.
|
4
|
-
"""
|
5
|
-
|
6
|
-
import uvicorn
|
7
|
-
import asyncio
|
8
|
-
import sys
|
9
|
-
import os
|
10
|
-
from pathlib import Path
|
11
|
-
|
12
|
-
# Add current directory to path for imports
|
13
|
-
sys.path.insert(0, os.getcwd())
|
14
|
-
|
15
|
-
from fastapi import FastAPI
|
16
|
-
from mcp_proxy_adapter.custom_openapi import CustomOpenAPIGenerator
|
17
|
-
from mcp_proxy_adapter.commands.command_registry import registry
|
18
|
-
|
19
|
-
# Create FastAPI app
|
20
|
-
app = FastAPI(
|
21
|
-
title="Extended MCP Proxy Server",
|
22
|
-
description="Advanced MCP Proxy Adapter server with custom commands and hooks",
|
23
|
-
version="2.1.0"
|
24
|
-
)
|
25
|
-
|
26
|
-
async def generate_openapi_schema():
|
27
|
-
"""Generate OpenAPI schema with custom commands."""
|
28
|
-
# Initialize commands
|
29
|
-
await registry.reload_system()
|
30
|
-
|
31
|
-
# Load custom commands
|
32
|
-
custom_commands = [
|
33
|
-
"echo_command",
|
34
|
-
"custom_help_command",
|
35
|
-
"custom_health_command",
|
36
|
-
"manual_echo_command"
|
37
|
-
]
|
38
|
-
|
39
|
-
for cmd_name in custom_commands:
|
40
|
-
try:
|
41
|
-
module = __import__(cmd_name)
|
42
|
-
if hasattr(module, 'EchoCommand'):
|
43
|
-
registry.register_custom(module.EchoCommand())
|
44
|
-
elif hasattr(module, 'CustomHelpCommand'):
|
45
|
-
registry.register_custom(module.CustomHelpCommand())
|
46
|
-
elif hasattr(module, 'CustomHealthCommand'):
|
47
|
-
registry.register_custom(module.CustomHealthCommand())
|
48
|
-
elif hasattr(module, 'ManualEchoCommand'):
|
49
|
-
registry.register_custom(module.ManualEchoCommand())
|
50
|
-
except Exception as e:
|
51
|
-
print(f"Warning: Failed to load {cmd_name}: {e}")
|
52
|
-
|
53
|
-
# Generate schema
|
54
|
-
generator = CustomOpenAPIGenerator()
|
55
|
-
return generator.generate(
|
56
|
-
title="Extended MCP Proxy Server",
|
57
|
-
description="Advanced MCP Proxy Adapter server with custom commands and hooks",
|
58
|
-
version="2.1.0"
|
59
|
-
)
|
60
|
-
|
61
|
-
# Set custom OpenAPI generator
|
62
|
-
@app.on_event("startup")
|
63
|
-
async def startup_event():
|
64
|
-
"""Initialize OpenAPI schema on startup."""
|
65
|
-
app.openapi_schema = await generate_openapi_schema()
|
66
|
-
|
67
|
-
@app.get("/openapi.json")
|
68
|
-
async def get_openapi_schema():
|
69
|
-
"""Returns OpenAPI schema."""
|
70
|
-
if not hasattr(app, 'openapi_schema'):
|
71
|
-
app.openapi_schema = await generate_openapi_schema()
|
72
|
-
return app.openapi_schema
|
73
|
-
|
74
|
-
if __name__ == "__main__":
|
75
|
-
uvicorn.run(app, host="0.0.0.0", port=8000)
|