mcp-proxy-adapter 4.1.0__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 +705 -345
  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 +17 -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 +97 -41
  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 -63
  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.0.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.0.dist-info/RECORD +0 -110
  99. {mcp_proxy_adapter-4.1.0.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/WHEEL +0 -0
  100. {mcp_proxy_adapter-4.1.0.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/licenses/LICENSE +0 -0
  101. {mcp_proxy_adapter-4.1.0.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/top_level.txt +0 -0
@@ -22,69 +22,89 @@ from mcp_proxy_adapter.core.settings import (
22
22
  get_setting,
23
23
  get_custom_setting_value
24
24
  )
25
- from .custom_settings_manager import CustomSettingsManager, get_app_name, is_feature_enabled
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
26
28
 
27
29
  # Import custom commands and hooks
28
- from .custom_help_command import CustomHelpCommand
29
- from .custom_health_command import CustomHealthCommand
30
- from .data_transform_command import DataTransformCommand
31
- from .intercept_command import InterceptCommand
32
- from .advanced_hooks import register_advanced_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
33
35
 
34
36
  # Import auto-registered commands
35
- from .auto_commands.auto_echo_command import AutoEchoCommand
36
- from .auto_commands.auto_info_command import AutoInfoCommand
37
+ from auto_commands.auto_echo_command import AutoEchoCommand
38
+ from auto_commands.auto_info_command import AutoInfoCommand
37
39
 
38
40
  # Import manual registration example
39
- from .manual_echo_command import ManualEchoCommand
41
+ from manual_echo_command import ManualEchoCommand
40
42
 
41
43
  # Import echo command
42
- from .echo_command import EchoCommand
44
+ from echo_command import EchoCommand
43
45
 
44
46
  # Import custom OpenAPI generator
45
- from .custom_openapi_generator import custom_openapi_generator
47
+ from custom_openapi_generator import custom_openapi_generator
46
48
 
47
49
  # Import command registry for manual registration
48
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
49
53
 
50
54
 
51
- def register_custom_commands():
52
- """Register custom commands with the registry."""
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."""
53
70
  logger = get_logger("custom_commands")
54
- logger.info("Registering custom commands...")
71
+ logger.info("Registering custom commands via hook...")
55
72
 
56
73
  # Get custom commands configuration from custom settings
57
74
  custom_commands_config = get_custom_setting_value("custom_commands", {})
58
75
 
59
- # Register echo command
60
- registry.register(EchoCommand)
61
- logger.info("Registered: echo command")
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")
62
82
 
63
83
  # Register custom help command (will override built-in)
64
84
  if custom_commands_config.get("help", {}).get("enabled", True):
65
- registry.register_custom_command(CustomHelpCommand)
85
+ registry.register_custom(CustomHelpCommand)
66
86
  logger.info("Registered: custom help command")
67
87
 
68
88
  # Register custom health command (will override built-in)
69
89
  if custom_commands_config.get("health", {}).get("enabled", True):
70
- registry.register_custom_command(CustomHealthCommand)
90
+ registry.register_custom(CustomHealthCommand)
71
91
  logger.info("Registered: custom health command")
72
92
 
73
93
  # Register advanced demonstration commands
74
94
  if custom_commands_config.get("data_transform", {}).get("enabled", True):
75
- registry.register(DataTransformCommand)
95
+ registry.register_custom(DataTransformCommand)
76
96
  logger.info("Registered: data_transform command")
77
97
 
78
98
  if custom_commands_config.get("intercept", {}).get("enabled", True):
79
- registry.register(InterceptCommand)
99
+ registry.register_custom(InterceptCommand)
80
100
  logger.info("Registered: intercept command")
81
101
 
82
102
  # Register manually registered commands
83
103
  if custom_commands_config.get("manual_echo", {}).get("enabled", True):
84
- registry.register(ManualEchoCommand)
104
+ registry.register_custom(ManualEchoCommand)
85
105
  logger.info("Registered: manual_echo command")
86
106
 
87
- logger.info(f"Total commands registered: {len(registry.get_all_commands())}")
107
+ logger.info(f"Total custom commands registered: {len(registry.get_commands_by_type()['custom'])}")
88
108
 
89
109
 
90
110
  def setup_hooks():
@@ -92,27 +112,11 @@ def setup_hooks():
92
112
  logger = get_logger("custom_commands")
93
113
  logger.info("Setting up hooks...")
94
114
 
95
- # Get hooks configuration from custom settings
96
- hooks_config = get_custom_setting_value("hooks", {})
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)
97
118
 
98
- # Register basic hooks
99
- # register_all_hooks(hooks) # This line was removed as per the new_code, as hooks is no longer imported.
100
- logger.info("Registered: basic hooks")
101
-
102
- # Register advanced hooks based on configuration
103
- if hooks_config.get("data_transform", {}).get("enabled", True):
104
- # register_advanced_hooks(None) # Temporarily disabled for simplicity
105
- logger.info("Registered: data transformation hooks (disabled for now)")
106
-
107
- if hooks_config.get("intercept", {}).get("enabled", True):
108
- logger.info("Registered: interception hooks")
109
-
110
- logger.info("Registered: command-specific hooks")
111
- logger.info("Registered: global hooks")
112
- logger.info("Registered: performance monitoring hooks")
113
- logger.info("Registered: security monitoring hooks")
114
- logger.info("Registered: data transformation hooks")
115
- logger.info("Registered: interception hooks")
119
+ logger.info("Registered: custom commands hook")
116
120
 
117
121
 
118
122
  def main():
@@ -126,6 +130,8 @@ def main():
126
130
  else:
127
131
  print(f"⚠️ Configuration file not found: {config_path}")
128
132
  print(" Using default configuration")
133
+ from mcp_proxy_adapter.config import config
134
+ config.load_config()
129
135
 
130
136
  # Setup logging with configuration
131
137
  setup_logging()
@@ -143,6 +149,16 @@ def main():
143
149
  commands_settings = Settings.get_commands_settings()
144
150
  custom_settings = Settings.get_custom_setting("custom", {})
145
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
+
146
162
  # Print server header and description
147
163
  print("=" * 80)
148
164
  print("🔧 ADVANCED MCP PROXY ADAPTER SERVER WITH HOOKS")
@@ -150,12 +166,21 @@ def main():
150
166
  print("📋 Description:")
151
167
  print(f" {get_app_name()} - Advanced server with custom settings management")
152
168
  print()
169
+ # Get transport info
170
+ transport_info = transport_manager.get_transport_info()
171
+
153
172
  print("⚙️ Configuration:")
154
- print(f" • Server: {server_settings['host']}:{server_settings['port']}")
173
+ print(f" • Server: {server_settings['host']}:{transport_manager.get_port()}")
174
+ print(f" • Transport: {transport_info['type']}")
155
175
  print(f" • Debug: {server_settings['debug']}")
156
176
  print(f" • Log Level: {logging_settings['level']}")
157
177
  print(f" • Log Directory: {logging_settings['log_dir']}")
158
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)}")
159
184
  print()
160
185
  print("🔧 Available Commands:")
161
186
  print(" • help - Custom help command (overrides built-in)")
@@ -163,12 +188,14 @@ def main():
163
188
  print(" • config - Built-in config command")
164
189
  print(" • reload - Built-in reload command")
165
190
  print(" • settings - Built-in settings command")
166
- print(" • reload_settings - Built-in reload 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")
167
195
  print(" • data_transform - Data transformation command")
168
196
  print(" • intercept - Command interception example")
169
197
  print(" • manual_echo - Manually registered echo command")
170
- print(" • auto_echo - Auto-registered echo command")
171
- print(" • auto_info - Auto-registered info command")
198
+ print(" • test - Remote command (loaded from plugin server)")
172
199
  print()
173
200
  print("🎯 Features:")
174
201
  print(" • Advanced JSON-RPC API")
@@ -186,23 +213,20 @@ def main():
186
213
  logger.info(f"Server configuration: {server_settings}")
187
214
  logger.info(f"Logging configuration: {logging_settings}")
188
215
  logger.info(f"Commands configuration: {commands_settings}")
189
- logger.info("This server demonstrates both auto-registration and manual registration:")
190
- logger.info(" Auto-registered: auto_echo, auto_info (from auto_commands/ package)")
191
- logger.info("• Manually registered: echo, help, health, data_transform, intercept, manual_echo")
192
- logger.info("• Built-in commands: help, health (if not overridden)")
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)")
193
221
  logger.info("With advanced hooks for data transformation and command interception")
194
222
 
195
- # Register custom commands
196
- register_custom_commands()
197
-
198
- # Discover auto-registered commands
199
- logger.info("Discovering auto-registered commands...")
200
- auto_commands_path = commands_settings.get("auto_commands_path", "mcp_proxy_adapter.examples.custom_commands.auto_commands")
201
- registry.discover_commands(auto_commands_path)
202
-
203
- # Setup hooks
223
+ # Setup hooks for command processing
204
224
  setup_hooks()
205
225
 
226
+ # Initialize commands
227
+ import asyncio
228
+ asyncio.run(initialize_commands())
229
+
206
230
  # Create application with settings from configuration
207
231
  app = create_app(
208
232
  title=get_app_name(),
@@ -210,12 +234,17 @@ def main():
210
234
  version="2.1.0"
211
235
  )
212
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
+
213
244
  # Run the server with configuration settings
214
245
  uvicorn.run(
215
246
  app,
216
- host=server_settings['host'],
217
- port=server_settings['port'],
218
- log_level=server_settings['log_level'].lower()
247
+ **uvicorn_config
219
248
  )
220
249
 
221
250
 
@@ -0,0 +1,75 @@
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)
@@ -0,0 +1,299 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Server startup script with Proxy Connection Manager.
4
+
5
+ This script starts the server and manages proxy connection with regular
6
+ health checks and automatic re-registration.
7
+ """
8
+
9
+ import asyncio
10
+ import time
11
+ import sys
12
+ import os
13
+ import uvicorn
14
+ import threading
15
+ import signal
16
+ from pathlib import Path
17
+
18
+ # Add parent directories to path
19
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
20
+
21
+ from mcp_proxy_adapter import create_app
22
+ from mcp_proxy_adapter.core.logging import get_logger, setup_logging
23
+ from mcp_proxy_adapter.core.settings import (
24
+ Settings,
25
+ get_server_host,
26
+ get_server_port,
27
+ get_server_debug,
28
+ get_setting,
29
+ get_custom_setting_value
30
+ )
31
+ from mcp_proxy_adapter.core.ssl_utils import SSLUtils
32
+ from mcp_proxy_adapter.core.transport_manager import transport_manager
33
+ from custom_settings_manager import CustomSettingsManager, get_app_name, is_feature_enabled
34
+
35
+ # Import custom commands and hooks
36
+ from custom_help_command import CustomHelpCommand
37
+ from custom_health_command import CustomHealthCommand
38
+ from data_transform_command import DataTransformCommand
39
+ from intercept_command import InterceptCommand
40
+ from advanced_hooks import register_advanced_hooks
41
+
42
+ # Import auto-registered commands
43
+ from auto_commands.auto_echo_command import AutoEchoCommand
44
+ from auto_commands.auto_info_command import AutoInfoCommand
45
+
46
+ # Import manual registration example
47
+ from manual_echo_command import ManualEchoCommand
48
+
49
+ # Import echo command
50
+ from echo_command import EchoCommand
51
+
52
+ # Import custom OpenAPI generator
53
+ from custom_openapi_generator import custom_openapi_generator
54
+
55
+ # Import command registry for manual registration
56
+ from mcp_proxy_adapter.commands.command_registry import registry
57
+ from mcp_proxy_adapter.config import config
58
+ from mcp_proxy_adapter.commands.hooks import register_custom_commands_hook
59
+
60
+ # Import proxy connection manager
61
+ from proxy_connection_manager import start_proxy_manager, stop_proxy_manager, get_proxy_manager_status
62
+
63
+
64
+ def custom_commands_hook(registry):
65
+ """Hook function for registering custom commands."""
66
+ logger = get_logger("custom_commands")
67
+ logger.info("Registering custom commands via hook...")
68
+
69
+ # Get custom commands configuration from custom settings
70
+ custom_commands_config = get_custom_setting_value("custom_commands", {})
71
+
72
+ # Register echo command (only if not already registered)
73
+ if not registry.command_exists("echo"):
74
+ registry.register_custom(EchoCommand)
75
+ logger.info("Registered: echo command")
76
+ else:
77
+ logger.debug("Command 'echo' is already registered, skipping")
78
+
79
+ # Register custom help command (will override built-in)
80
+ if custom_commands_config.get("help", {}).get("enabled", True):
81
+ registry.register_custom(CustomHelpCommand)
82
+ logger.info("Registered: custom help command")
83
+
84
+ # Register custom health command (will override built-in)
85
+ if custom_commands_config.get("health", {}).get("enabled", True):
86
+ registry.register_custom(CustomHealthCommand)
87
+ logger.info("Registered: custom health command")
88
+
89
+ # Register advanced demonstration commands
90
+ if custom_commands_config.get("data_transform", {}).get("enabled", True):
91
+ registry.register_custom(DataTransformCommand)
92
+ logger.info("Registered: data_transform command")
93
+
94
+ if custom_commands_config.get("intercept", {}).get("enabled", True):
95
+ registry.register_custom(InterceptCommand)
96
+ logger.info("Registered: intercept command")
97
+
98
+
99
+ def setup_hooks():
100
+ """Setup hooks for command processing."""
101
+ logger = get_logger("custom_commands")
102
+ logger.info("Setting up hooks...")
103
+
104
+ # Register custom commands hook
105
+ register_custom_commands_hook(custom_commands_hook)
106
+
107
+ # Note: Advanced hooks are not compatible with current API
108
+ # They will be registered automatically by the command registry
109
+ logger.info("Basic hooks setup completed")
110
+
111
+
112
+ async def initialize_commands():
113
+ """
114
+ Initialize commands using the unified system initialization logic.
115
+ This function is used both at startup and during reload.
116
+
117
+ Returns:
118
+ Number of commands discovered.
119
+ """
120
+ # Use the unified reload method from registry
121
+ result = await registry.reload_system()
122
+ return result["total_commands"]
123
+
124
+
125
+ def start_server():
126
+ """Start the server in a separate thread."""
127
+ # Initialize settings
128
+ settings = Settings()
129
+ server_settings = settings.get_server_settings()
130
+ logging_settings = settings.get_logging_settings()
131
+ commands_settings = settings.get_commands_settings()
132
+
133
+ # Setup logging - pass only the level, not the entire dict
134
+ setup_logging(logging_settings.get('level', 'INFO'))
135
+ logger = get_logger("server_startup")
136
+
137
+ # Load transport configuration
138
+ if not transport_manager.load_config(config.config_data):
139
+ logger.error("Failed to load transport configuration")
140
+ return
141
+
142
+ # Validate transport configuration
143
+ if not transport_manager.validate_config():
144
+ logger.error("Transport configuration validation failed")
145
+ return
146
+
147
+ # Print server header and description
148
+ print("=" * 80)
149
+ print("🔧 ADVANCED MCP PROXY ADAPTER SERVER WITH PROXY MANAGER")
150
+ print("=" * 80)
151
+ print("📋 Description:")
152
+ print(f" {get_app_name()} - Advanced server with proxy connection management")
153
+ print()
154
+
155
+ # Get transport info
156
+ transport_info = transport_manager.get_transport_info()
157
+
158
+ print("⚙️ Configuration:")
159
+ print(f" • Server: {server_settings['host']}:{transport_manager.get_port()}")
160
+ print(f" • Transport: {transport_info['type']}")
161
+ print(f" • Debug: {server_settings['debug']}")
162
+ print(f" • Log Level: {logging_settings.get('level', 'INFO')}")
163
+ print(f" • Log Directory: {logging_settings.get('log_dir', './logs')}")
164
+ print(f" • Auto Discovery: {commands_settings['auto_discovery']}")
165
+ print(f" • SSL Enabled: {transport_info['ssl_enabled']}")
166
+ if transport_info['ssl_enabled']:
167
+ ssl_config = transport_info['ssl_config']
168
+ print(f" • SSL Cert: {ssl_config.get('cert_file', 'Not specified')}")
169
+ print(f" • Client Verification: {ssl_config.get('verify_client', False)}")
170
+ print()
171
+ print("🔧 Available Commands:")
172
+ print(" • help - Custom help command (overrides built-in)")
173
+ print(" • health - Custom health command (overrides built-in)")
174
+ print(" • config - Built-in config command")
175
+ print(" • reload - Built-in reload command")
176
+ print(" • settings - Built-in settings command")
177
+ print(" • load - Built-in load command")
178
+ print(" • unload - Built-in unload command")
179
+ print(" • plugins - Built-in plugins command")
180
+ print(" • echo - Custom echo command")
181
+ print(" • data_transform - Data transformation command")
182
+ print(" • intercept - Command interception example")
183
+ print(" • manual_echo - Manually registered echo command")
184
+ print(" • test - Remote command (loaded from plugin server)")
185
+ print()
186
+ print("🎯 Features:")
187
+ print(" • Advanced JSON-RPC API")
188
+ print(" • Custom commands with hooks")
189
+ print(" • Data transformation hooks")
190
+ print(" • Command interception hooks")
191
+ print(" • Auto-registration and manual registration")
192
+ print(" • Custom OpenAPI schema generation")
193
+ print(" • Configuration-driven settings")
194
+ print(" • Custom settings management")
195
+ print(" • 🔄 Proxy Connection Manager with health monitoring")
196
+ print(" • 🔄 Automatic re-registration on proxy failure")
197
+ print("=" * 80)
198
+ print()
199
+
200
+ logger.info("Starting Advanced Custom Commands MCP Proxy Adapter Server with Proxy Manager...")
201
+ logger.info(f"Server configuration: {server_settings}")
202
+ logger.info(f"Logging configuration: {logging_settings}")
203
+ logger.info(f"Commands configuration: {commands_settings}")
204
+ logger.info(f"Transport configuration: {transport_info}")
205
+
206
+ # Setup hooks for command processing
207
+ setup_hooks()
208
+
209
+ # Initialize commands
210
+ asyncio.run(initialize_commands())
211
+
212
+ # Create application with settings from configuration
213
+ app = create_app(
214
+ title=get_app_name(),
215
+ description="Advanced MCP Proxy Adapter server with proxy connection management, demonstrating hook capabilities including data transformation, command interception, conditional processing, and smart interception hooks. Features custom commands with enhanced functionality, comprehensive settings management, and robust proxy connection handling.",
216
+ version="2.2.0"
217
+ )
218
+
219
+ # Get uvicorn configuration from transport manager
220
+ uvicorn_config = transport_manager.get_uvicorn_config()
221
+ uvicorn_config["host"] = server_settings['host']
222
+ uvicorn_config["log_level"] = server_settings['log_level'].lower()
223
+
224
+ logger.info(f"Starting server with uvicorn config: {uvicorn_config}")
225
+
226
+ # Run the server with configuration settings
227
+ uvicorn.run(
228
+ app,
229
+ **uvicorn_config
230
+ )
231
+
232
+
233
+ async def start_proxy_manager_after_server():
234
+ """
235
+ Start proxy manager after server is fully started and listening.
236
+ """
237
+ logger = get_logger("proxy_manager_startup")
238
+
239
+ # Wait a bit for server to fully start
240
+ await asyncio.sleep(5)
241
+
242
+ logger.info("🚀 Starting Proxy Connection Manager after server startup")
243
+
244
+ # Start proxy manager
245
+ await start_proxy_manager()
246
+
247
+ logger.info("✅ Proxy Connection Manager started successfully")
248
+
249
+
250
+ def signal_handler(signum, frame):
251
+ """Handle shutdown signals."""
252
+ print(f"\n🛑 Received signal {signum}, shutting down gracefully...")
253
+
254
+ # Stop proxy manager
255
+ asyncio.run(stop_proxy_manager())
256
+
257
+ print("✅ Graceful shutdown completed")
258
+ sys.exit(0)
259
+
260
+
261
+ def main():
262
+ """Main function to start server and proxy manager."""
263
+ # Setup signal handlers for graceful shutdown
264
+ signal.signal(signal.SIGINT, signal_handler)
265
+ signal.signal(signal.SIGTERM, signal_handler)
266
+
267
+ # Start server in a separate thread
268
+ server_thread = threading.Thread(target=start_server, daemon=True)
269
+ server_thread.start()
270
+
271
+ # Wait for server to start
272
+ time.sleep(8)
273
+
274
+ # Start proxy manager after server is ready
275
+ asyncio.run(start_proxy_manager_after_server())
276
+
277
+ # Keep main thread alive and monitor status
278
+ try:
279
+ while True:
280
+ # Get proxy manager status
281
+ status = get_proxy_manager_status()
282
+
283
+ if status["is_running"]:
284
+ time_since = status.get("time_since_registration", 0)
285
+ if time_since is not None:
286
+ print(f"📊 Proxy Status: Registered {time_since:.0f}s ago, "
287
+ f"attempts: {status['registration_count']}, "
288
+ f"failed: {status['failed_attempts']}")
289
+
290
+ time.sleep(30) # Print status every 30 seconds
291
+
292
+ except KeyboardInterrupt:
293
+ print("\n🛑 Server shutdown requested")
294
+ asyncio.run(stop_proxy_manager())
295
+ sys.exit(0)
296
+
297
+
298
+ if __name__ == "__main__":
299
+ main()