mcp-proxy-adapter 6.9.17__py3-none-any.whl → 6.9.19__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 (87) hide show
  1. mcp_proxy_adapter/api/app.py +52 -52
  2. mcp_proxy_adapter/api/handlers.py +5 -5
  3. mcp_proxy_adapter/api/middleware/__init__.py +8 -8
  4. mcp_proxy_adapter/api/middleware/base.py +14 -14
  5. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +7 -7
  6. mcp_proxy_adapter/api/middleware/error_handling.py +9 -9
  7. mcp_proxy_adapter/api/middleware/factory.py +17 -17
  8. mcp_proxy_adapter/api/middleware/logging.py +6 -6
  9. mcp_proxy_adapter/api/middleware/performance.py +3 -3
  10. mcp_proxy_adapter/api/middleware/protocol_middleware.py +19 -19
  11. mcp_proxy_adapter/api/middleware/transport_middleware.py +3 -3
  12. mcp_proxy_adapter/api/middleware/unified_security.py +11 -11
  13. mcp_proxy_adapter/api/middleware/user_info_middleware.py +21 -21
  14. mcp_proxy_adapter/api/tool_integration.py +3 -2
  15. mcp_proxy_adapter/api/tools.py +4 -3
  16. mcp_proxy_adapter/commands/auth_validation_command.py +6 -5
  17. mcp_proxy_adapter/commands/base.py +10 -10
  18. mcp_proxy_adapter/commands/builtin_commands.py +6 -6
  19. mcp_proxy_adapter/commands/catalog_manager.py +74 -74
  20. mcp_proxy_adapter/commands/cert_monitor_command.py +13 -12
  21. mcp_proxy_adapter/commands/certificate_management_command.py +20 -19
  22. mcp_proxy_adapter/commands/command_registry.py +68 -67
  23. mcp_proxy_adapter/commands/config_command.py +3 -1
  24. mcp_proxy_adapter/commands/dependency_manager.py +10 -10
  25. mcp_proxy_adapter/commands/help_command.py +21 -20
  26. mcp_proxy_adapter/commands/hooks.py +27 -27
  27. mcp_proxy_adapter/commands/key_management_command.py +19 -18
  28. mcp_proxy_adapter/commands/plugins_command.py +2 -1
  29. mcp_proxy_adapter/commands/protocol_management_command.py +6 -6
  30. mcp_proxy_adapter/commands/proxy_registration_command.py +9 -9
  31. mcp_proxy_adapter/commands/registration_status_command.py +4 -4
  32. mcp_proxy_adapter/commands/reload_command.py +5 -5
  33. mcp_proxy_adapter/commands/role_test_command.py +2 -1
  34. mcp_proxy_adapter/commands/roles_management_command.py +9 -8
  35. mcp_proxy_adapter/commands/security_command.py +3 -2
  36. mcp_proxy_adapter/commands/ssl_setup_command.py +7 -6
  37. mcp_proxy_adapter/commands/token_management_command.py +12 -11
  38. mcp_proxy_adapter/commands/transport_management_command.py +2 -2
  39. mcp_proxy_adapter/config.py +3 -3
  40. mcp_proxy_adapter/core/__init__.py +1 -1
  41. mcp_proxy_adapter/core/app_runner.py +3 -3
  42. mcp_proxy_adapter/core/auth_validator.py +9 -9
  43. mcp_proxy_adapter/core/certificate_utils.py +27 -27
  44. mcp_proxy_adapter/core/client_manager.py +13 -13
  45. mcp_proxy_adapter/core/client_security.py +26 -26
  46. mcp_proxy_adapter/core/config_converter.py +18 -18
  47. mcp_proxy_adapter/core/config_validator.py +5 -1
  48. mcp_proxy_adapter/core/crl_utils.py +22 -22
  49. mcp_proxy_adapter/core/logging.py +21 -13
  50. mcp_proxy_adapter/core/mtls_asgi.py +7 -7
  51. mcp_proxy_adapter/core/mtls_asgi_app.py +9 -9
  52. mcp_proxy_adapter/core/mtls_proxy.py +9 -9
  53. mcp_proxy_adapter/core/mtls_server.py +18 -18
  54. mcp_proxy_adapter/core/protocol_manager.py +29 -29
  55. mcp_proxy_adapter/core/proxy_registration.py +67 -67
  56. mcp_proxy_adapter/core/security_adapter.py +18 -18
  57. mcp_proxy_adapter/core/security_factory.py +16 -16
  58. mcp_proxy_adapter/core/security_integration.py +6 -6
  59. mcp_proxy_adapter/core/server_adapter.py +12 -12
  60. mcp_proxy_adapter/core/server_engine.py +17 -17
  61. mcp_proxy_adapter/core/signal_handler.py +12 -12
  62. mcp_proxy_adapter/core/ssl_utils.py +12 -12
  63. mcp_proxy_adapter/core/transport_manager.py +14 -14
  64. mcp_proxy_adapter/core/unified_config_adapter.py +6 -6
  65. mcp_proxy_adapter/core/utils.py +5 -5
  66. mcp_proxy_adapter/custom_openapi.py +7 -7
  67. mcp_proxy_adapter/examples/cert_manager_bugfix.py +2 -2
  68. mcp_proxy_adapter/examples/full_application/commands/__init__.py +6 -5
  69. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +44 -0
  70. mcp_proxy_adapter/examples/full_application/commands/help_command.py +66 -0
  71. mcp_proxy_adapter/examples/full_application/commands/list_command.py +64 -0
  72. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +21 -21
  73. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +6 -6
  74. mcp_proxy_adapter/examples/full_application/main.py +28 -0
  75. mcp_proxy_adapter/examples/proxy_registration_example.py +38 -38
  76. mcp_proxy_adapter/examples/test_framework_complete.py +35 -35
  77. mcp_proxy_adapter/examples/test_mcp_server.py +2 -2
  78. mcp_proxy_adapter/examples/validate_generator_compatibility.py +386 -0
  79. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +248 -0
  80. mcp_proxy_adapter/main.py +3 -0
  81. mcp_proxy_adapter/version.py +1 -1
  82. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/METADATA +1 -1
  83. mcp_proxy_adapter-6.9.19.dist-info/RECORD +149 -0
  84. mcp_proxy_adapter-6.9.17.dist-info/RECORD +0 -144
  85. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/WHEEL +0 -0
  86. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/entry_points.txt +0 -0
  87. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/top_level.txt +0 -0
@@ -9,7 +9,7 @@ from dataclasses import dataclass
9
9
  from enum import Enum
10
10
  from pathlib import Path
11
11
 
12
- from mcp_proxy_adapter.core.logging import logger
12
+ from mcp_proxy_adapter.core.logging import get_global_logger
13
13
 
14
14
 
15
15
  class TransportType(Enum):
@@ -72,7 +72,7 @@ class TransportManager:
72
72
  try:
73
73
  transport_type = TransportType(transport_type_str)
74
74
  except ValueError:
75
- logger.error(f"Invalid transport type: {transport_type_str}")
75
+ get_global_logger().error(f"Invalid transport type: {transport_type_str}")
76
76
  return False
77
77
 
78
78
  # Get port (use default if not specified)
@@ -89,13 +89,13 @@ class TransportManager:
89
89
  transport_type in [TransportType.HTTPS, TransportType.MTLS]
90
90
  and not ssl_enabled
91
91
  ):
92
- logger.error(
92
+ get_global_logger().error(
93
93
  f"SSL must be enabled for transport type: {transport_type.value}"
94
94
  )
95
95
  return False
96
96
 
97
97
  if transport_type == TransportType.HTTP and ssl_enabled:
98
- logger.warning("SSL enabled for HTTP transport - this may cause issues")
98
+ get_global_logger().warning("SSL enabled for HTTP transport - this may cause issues")
99
99
 
100
100
  # Create transport config
101
101
  self._config = TransportConfig(
@@ -111,13 +111,13 @@ class TransportManager:
111
111
 
112
112
  self._current_transport = transport_type
113
113
 
114
- logger.info(
114
+ get_global_logger().info(
115
115
  f"Transport config loaded: {transport_type.value} on port {port}"
116
116
  )
117
117
  return True
118
118
 
119
119
  except Exception as e:
120
- logger.error(f"Failed to load transport config: {e}")
120
+ get_global_logger().error(f"Failed to load transport config: {e}")
121
121
  return False
122
122
 
123
123
  def get_transport_type(self) -> Optional[TransportType]:
@@ -220,17 +220,17 @@ class TransportManager:
220
220
  True if configuration is valid, False otherwise
221
221
  """
222
222
  if not self._config:
223
- logger.error("Transport not configured")
223
+ get_global_logger().error("Transport not configured")
224
224
  return False
225
225
 
226
226
  # Validate SSL requirements
227
227
  if self._config.type in [TransportType.HTTPS, TransportType.MTLS]:
228
228
  if not self._config.ssl_enabled:
229
- logger.error(f"SSL must be enabled for {self._config.type.value}")
229
+ get_global_logger().error(f"SSL must be enabled for {self._config.type.value}")
230
230
  return False
231
231
 
232
232
  if not self._config.cert_file or not self._config.key_file:
233
- logger.error(
233
+ get_global_logger().error(
234
234
  f"SSL certificate and key required for {self._config.type.value}"
235
235
  )
236
236
  return False
@@ -242,12 +242,12 @@ class TransportManager:
242
242
  # Validate MTLS requirements
243
243
  if self._config.type == TransportType.MTLS:
244
244
  if not self._config.verify_client:
245
- logger.warning("MTLS transport should have client verification enabled")
245
+ get_global_logger().warning("MTLS transport should have client verification enabled")
246
246
 
247
247
  if not self._config.ca_cert:
248
- logger.warning("CA certificate recommended for MTLS transport")
248
+ get_global_logger().warning("CA certificate recommended for MTLS transport")
249
249
 
250
- logger.info(f"Transport configuration validated: {self._config.type.value}")
250
+ get_global_logger().info(f"Transport configuration validated: {self._config.type.value}")
251
251
  return True
252
252
 
253
253
  def validate_ssl_files(self) -> bool:
@@ -270,10 +270,10 @@ class TransportManager:
270
270
 
271
271
  for file_path in files_to_check:
272
272
  if not Path(file_path).exists():
273
- logger.error(f"SSL file not found: {file_path}")
273
+ get_global_logger().error(f"SSL file not found: {file_path}")
274
274
  return False
275
275
 
276
- logger.info(f"All SSL files validated successfully: {files_to_check}")
276
+ get_global_logger().info(f"All SSL files validated successfully: {files_to_check}")
277
277
  return True
278
278
 
279
279
  def get_hypercorn_config(self) -> Dict[str, Any]:
@@ -33,7 +33,7 @@ except ImportError:
33
33
  PermissionConfig = None
34
34
  RateLimitConfig = None
35
35
 
36
- from mcp_proxy_adapter.core.logging import logger
36
+ from mcp_proxy_adapter.core.logging import get_global_logger
37
37
 
38
38
 
39
39
  @dataclass
@@ -84,7 +84,7 @@ class UnifiedConfigAdapter:
84
84
  SecurityConfig instance or None if conversion failed
85
85
  """
86
86
  if not SECURITY_FRAMEWORK_AVAILABLE:
87
- logger.error(
87
+ get_global_logger().error(
88
88
  "mcp_security_framework not available, cannot convert configuration"
89
89
  )
90
90
  return None
@@ -93,7 +93,7 @@ class UnifiedConfigAdapter:
93
93
  # Validate configuration first
94
94
  validation_result = self.validate_configuration(config)
95
95
  if not validation_result.is_valid:
96
- logger.error(
96
+ get_global_logger().error(
97
97
  f"Configuration validation failed: {validation_result.errors}"
98
98
  )
99
99
  return None
@@ -112,11 +112,11 @@ class UnifiedConfigAdapter:
112
112
  rate_limit=rate_limit_config,
113
113
  )
114
114
 
115
- logger.info("Configuration successfully converted to SecurityConfig")
115
+ get_global_logger().info("Configuration successfully converted to SecurityConfig")
116
116
  return security_config
117
117
 
118
118
  except Exception as e:
119
- logger.error(f"Failed to convert configuration: {e}")
119
+ get_global_logger().error(f"Failed to convert configuration: {e}")
120
120
  return None
121
121
 
122
122
  def validate_configuration(self, config: Dict[str, Any]) -> ValidationResult:
@@ -569,7 +569,7 @@ class UnifiedConfigAdapter:
569
569
  "enabled": migrated_config["rate_limit_enabled"]
570
570
  }
571
571
 
572
- logger.info("Legacy configuration migrated to new format")
572
+ get_global_logger().info("Legacy configuration migrated to new format")
573
573
  return migrated_config
574
574
 
575
575
  def get_default_config(self) -> Dict[str, Any]:
@@ -12,7 +12,7 @@ import uuid
12
12
  from datetime import datetime, timezone
13
13
  from typing import Any, Dict, List, Optional, Tuple, Union
14
14
 
15
- from mcp_proxy_adapter.core.logging import logger
15
+ from mcp_proxy_adapter.core.logging import get_global_logger
16
16
 
17
17
 
18
18
  def generate_id() -> str:
@@ -80,7 +80,7 @@ def safe_json_loads(s: str, default: Any = None) -> Any:
80
80
  try:
81
81
  return json.loads(s)
82
82
  except Exception as e:
83
- logger.error(f"Error parsing JSON: {e}")
83
+ get_global_logger().error(f"Error parsing JSON: {e}")
84
84
  return default
85
85
 
86
86
 
@@ -99,7 +99,7 @@ def safe_json_dumps(obj: Any, default: str = "{}", indent: Optional[int] = None)
99
99
  try:
100
100
  return json.dumps(obj, ensure_ascii=False, indent=indent)
101
101
  except Exception as e:
102
- logger.error(f"Error serializing to JSON: {e}")
102
+ get_global_logger().error(f"Error serializing to JSON: {e}")
103
103
  return default
104
104
 
105
105
 
@@ -137,7 +137,7 @@ def ensure_directory(path: str) -> bool:
137
137
  os.makedirs(path, exist_ok=True)
138
138
  return True
139
139
  except Exception as e:
140
- logger.error(f"Error creating directory {path}: {e}")
140
+ get_global_logger().error(f"Error creating directory {path}: {e}")
141
141
  return False
142
142
 
143
143
 
@@ -159,7 +159,7 @@ def check_port_availability(host: str, port: int, timeout: float = 1.0) -> bool:
159
159
  result = sock.connect_ex((host, port))
160
160
  return result != 0 # True if connection failed (port is free)
161
161
  except Exception as e:
162
- logger.warning(f"Error checking port {port} on {host}: {e}")
162
+ get_global_logger().warning(f"Error checking port {port} on {host}: {e}")
163
163
  return True # Assume port is available if check fails
164
164
 
165
165
 
@@ -12,7 +12,7 @@ from fastapi.openapi.utils import get_openapi
12
12
 
13
13
  from mcp_proxy_adapter.commands.command_registry import registry
14
14
  from mcp_proxy_adapter.commands.base import Command
15
- from mcp_proxy_adapter.core.logging import logger
15
+ from mcp_proxy_adapter.core.logging import get_global_logger
16
16
 
17
17
 
18
18
  class CustomOpenAPIGenerator:
@@ -49,7 +49,7 @@ class CustomOpenAPIGenerator:
49
49
  with open(self.base_schema_path, "r", encoding="utf-8") as f:
50
50
  return json.load(f)
51
51
  except FileNotFoundError:
52
- logger.warning(f"Base schema file not found at {self.base_schema_path}, using fallback schema")
52
+ get_global_logger().warning(f"Base schema file not found at {self.base_schema_path}, using fallback schema")
53
53
  return self._get_fallback_schema()
54
54
 
55
55
  def _get_fallback_schema(self) -> Dict[str, Any]:
@@ -406,7 +406,7 @@ class CustomOpenAPIGenerator:
406
406
  return cmd_schema
407
407
  except Exception as e:
408
408
  # Return default schema if command schema generation fails
409
- logger.warning(f"Failed to get schema for command {cmd_class.name}: {e}")
409
+ get_global_logger().warning(f"Failed to get schema for command {cmd_class.name}: {e}")
410
410
  return {
411
411
  "type": "object",
412
412
  "title": f"Parameters for {cmd_class.name}",
@@ -569,7 +569,7 @@ class CustomOpenAPIGenerator:
569
569
  # Add commands to schema
570
570
  self._add_commands_to_schema(schema)
571
571
 
572
- logger.debug(
572
+ get_global_logger().debug(
573
573
  f"Generated OpenAPI schema with {len(registry.get_all_commands())} commands"
574
574
  )
575
575
 
@@ -620,7 +620,7 @@ def register_openapi_generator(
620
620
  generator_func: Function that generates OpenAPI schema.
621
621
  """
622
622
  _openapi_generators[name] = generator_func
623
- logger.info(f"Registered custom OpenAPI generator: {name}")
623
+ get_global_logger().info(f"Registered custom OpenAPI generator: {name}")
624
624
 
625
625
 
626
626
  def get_openapi_generator(name: str) -> Optional[Callable[[FastAPI], Dict[str, Any]]]:
@@ -669,9 +669,9 @@ def custom_openapi_with_fallback(app: FastAPI) -> Dict[str, Any]:
669
669
  # Use the first registered generator
670
670
  generator_name = list(_openapi_generators.keys())[0]
671
671
  generator_func = _openapi_generators[generator_name]
672
- logger.debug(f"Using custom OpenAPI generator: {generator_name}")
672
+ get_global_logger().debug(f"Using custom OpenAPI generator: {generator_name}")
673
673
  return generator_func(app)
674
674
 
675
675
  # Fall back to default generator
676
- logger.debug("Using default OpenAPI generator")
676
+ get_global_logger().debug("Using default OpenAPI generator")
677
677
  return custom_openapi(app)
@@ -63,7 +63,7 @@ def create_cert_manager_patch():
63
63
  - )
64
64
  + # BUGFIX: Skip CA path validation if in CA creation mode
65
65
  + if self.config.ca_creation_mode:
66
- + self.logger.info("CA creation mode enabled, skipping CA path validation")
66
+ + self.get_global_logger().info("CA creation mode enabled, skipping CA path validation")
67
67
  + return
68
68
  +
69
69
  + if not self.config.ca_cert_path:
@@ -110,7 +110,7 @@ def test_fixed_cert_manager():
110
110
 
111
111
  # BUGFIX: Skip CA path validation if in CA creation mode
112
112
  if self.config.ca_creation_mode:
113
- self.logger.info("CA creation mode enabled, skipping CA path validation")
113
+ self.get_global_logger().info("CA creation mode enabled, skipping CA path validation")
114
114
  return
115
115
 
116
116
  if not self.config.ca_cert_path:
@@ -1,7 +1,8 @@
1
- """Full Application Commands.
2
-
3
- Custom command implementations for the full application example.
4
1
  """
2
+ Commands package for full application example.
3
+ """
4
+ from .echo_command import EchoCommand
5
+ from .list_command import ListCommand
6
+ from .help_command import HelpCommand
5
7
 
6
- from .custom_echo_command import CustomEchoCommand
7
- from .dynamic_calculator_command import DynamicCalculatorCommand
8
+ __all__ = ["EchoCommand", "ListCommand", "HelpCommand"]
@@ -0,0 +1,44 @@
1
+ """
2
+ Echo command implementation.
3
+ """
4
+ from mcp_proxy_adapter.commands.base import BaseCommand
5
+ from mcp_proxy_adapter.core.errors import MicroserviceError
6
+
7
+
8
+ class EchoCommand(BaseCommand):
9
+ """Echo command that returns the input message."""
10
+
11
+ def __init__(self):
12
+ super().__init__()
13
+ self.name = "echo"
14
+ self.description = "Echo command that returns the input message"
15
+ self.version = "1.0.0"
16
+
17
+ def get_schema(self):
18
+ """Get command schema."""
19
+ return {
20
+ "type": "object",
21
+ "properties": {
22
+ "message": {
23
+ "type": "string",
24
+ "description": "Message to echo back"
25
+ }
26
+ },
27
+ "required": ["message"]
28
+ }
29
+
30
+ async def execute(self, params: dict) -> dict:
31
+ """Execute echo command."""
32
+ try:
33
+ message = params.get("message", "")
34
+ return {
35
+ "echo": message,
36
+ "timestamp": self._get_timestamp()
37
+ }
38
+ except Exception as e:
39
+ raise MicroserviceError(f"Echo command failed: {str(e)}")
40
+
41
+ def _get_timestamp(self):
42
+ """Get current timestamp."""
43
+ import time
44
+ return time.time()
@@ -0,0 +1,66 @@
1
+ """
2
+ Help command implementation.
3
+ """
4
+ from mcp_proxy_adapter.commands.base import BaseCommand
5
+ from mcp_proxy_adapter.core.errors import MicroserviceError
6
+
7
+
8
+ class HelpCommand(BaseCommand):
9
+ """Help command that provides usage information."""
10
+
11
+ def __init__(self):
12
+ super().__init__()
13
+ self.name = "help"
14
+ self.description = "Get help information"
15
+ self.version = "1.0.0"
16
+
17
+ def get_schema(self):
18
+ """Get command schema."""
19
+ return {
20
+ "type": "object",
21
+ "properties": {
22
+ "command": {
23
+ "type": "string",
24
+ "description": "Command name to get help for (optional)"
25
+ }
26
+ },
27
+ "required": []
28
+ }
29
+
30
+ async def execute(self, params: dict) -> dict:
31
+ """Execute help command."""
32
+ try:
33
+ command = params.get("command")
34
+
35
+ if command:
36
+ # Get help for specific command
37
+ help_info = self._get_command_help(command)
38
+ return {
39
+ "command": command,
40
+ "help": help_info,
41
+ "timestamp": self._get_timestamp()
42
+ }
43
+ else:
44
+ # Get general help
45
+ return {
46
+ "help": "MCP Proxy Adapter - Available commands: echo, list, health, help",
47
+ "usage": "Use 'help' with a command name to get specific help",
48
+ "timestamp": self._get_timestamp()
49
+ }
50
+ except Exception as e:
51
+ raise MicroserviceError(f"Help command failed: {str(e)}")
52
+
53
+ def _get_command_help(self, command: str) -> str:
54
+ """Get help for specific command."""
55
+ help_map = {
56
+ "echo": "Echo command - returns the input message. Usage: {'message': 'your message'}",
57
+ "list": "List command - returns available commands. Usage: {}",
58
+ "health": "Health command - returns server health status. Usage: {}",
59
+ "help": "Help command - provides usage information. Usage: {'command': 'command_name'} (optional)"
60
+ }
61
+ return help_map.get(command, f"No help available for command '{command}'")
62
+
63
+ def _get_timestamp(self):
64
+ """Get current timestamp."""
65
+ import time
66
+ return time.time()
@@ -0,0 +1,64 @@
1
+ """
2
+ List command implementation.
3
+ """
4
+ from mcp_proxy_adapter.commands.base import BaseCommand
5
+ from mcp_proxy_adapter.core.errors import MicroserviceError
6
+
7
+
8
+ class ListCommand(BaseCommand):
9
+ """List command that returns available commands."""
10
+
11
+ def __init__(self):
12
+ super().__init__()
13
+ self.name = "list"
14
+ self.description = "List available commands"
15
+ self.version = "1.0.0"
16
+
17
+ def get_schema(self):
18
+ """Get command schema."""
19
+ return {
20
+ "type": "object",
21
+ "properties": {},
22
+ "required": []
23
+ }
24
+
25
+ async def execute(self, params: dict) -> dict:
26
+ """Execute list command."""
27
+ try:
28
+ # This is a simplified list - in a real implementation,
29
+ # this would query the command registry
30
+ commands = [
31
+ {
32
+ "name": "echo",
33
+ "description": "Echo command that returns the input message",
34
+ "version": "1.0.0"
35
+ },
36
+ {
37
+ "name": "list",
38
+ "description": "List available commands",
39
+ "version": "1.0.0"
40
+ },
41
+ {
42
+ "name": "health",
43
+ "description": "Health check command",
44
+ "version": "1.0.0"
45
+ },
46
+ {
47
+ "name": "help",
48
+ "description": "Help command",
49
+ "version": "1.0.0"
50
+ }
51
+ ]
52
+
53
+ return {
54
+ "commands": commands,
55
+ "count": len(commands),
56
+ "timestamp": self._get_timestamp()
57
+ }
58
+ except Exception as e:
59
+ raise MicroserviceError(f"List command failed: {str(e)}")
60
+
61
+ def _get_timestamp(self):
62
+ """Get current timestamp."""
63
+ import time
64
+ return time.time()
@@ -18,25 +18,25 @@ class ApplicationHooks:
18
18
  @staticmethod
19
19
  def on_startup():
20
20
  """Hook executed on application startup."""
21
- logger.info("🚀 Application startup hook executed")
21
+ get_global_logger().info("🚀 Application startup hook executed")
22
22
  # Initialize application-specific resources
23
- logger.info("📊 Initializing application metrics")
24
- logger.info("🔐 Loading security configurations")
25
- logger.info("📝 Setting up logging")
23
+ get_global_logger().info("📊 Initializing application metrics")
24
+ get_global_logger().info("🔐 Loading security configurations")
25
+ get_global_logger().info("📝 Setting up logging")
26
26
 
27
27
  @staticmethod
28
28
  def on_shutdown():
29
29
  """Hook executed on application shutdown."""
30
- logger.info("🛑 Application shutdown hook executed")
30
+ get_global_logger().info("🛑 Application shutdown hook executed")
31
31
  # Cleanup application resources
32
- logger.info("🧹 Cleaning up resources")
33
- logger.info("💾 Saving application state")
34
- logger.info("📊 Finalizing metrics")
32
+ get_global_logger().info("🧹 Cleaning up resources")
33
+ get_global_logger().info("💾 Saving application state")
34
+ get_global_logger().info("📊 Finalizing metrics")
35
35
 
36
36
  @staticmethod
37
37
  def before_request(request_data: Dict[str, Any]) -> Dict[str, Any]:
38
38
  """Hook executed before processing any request."""
39
- logger.info(f"🔧 Application hook: before_request with data: {request_data}")
39
+ get_global_logger().info(f"🔧 Application hook: before_request with data: {request_data}")
40
40
  # Add request metadata
41
41
  request_data["app_metadata"] = {
42
42
  "request_id": f"req_{datetime.now().timestamp()}",
@@ -48,7 +48,7 @@ class ApplicationHooks:
48
48
  @staticmethod
49
49
  def after_request(result: Dict[str, Any]) -> Dict[str, Any]:
50
50
  """Hook executed after processing any request."""
51
- logger.info(f"🔧 Application hook: after_request with result: {result}")
51
+ get_global_logger().info(f"🔧 Application hook: after_request with result: {result}")
52
52
  # Add response metadata
53
53
  result["app_response_metadata"] = {
54
54
  "processed_at": datetime.now().isoformat(),
@@ -60,29 +60,29 @@ class ApplicationHooks:
60
60
  @staticmethod
61
61
  def on_error(error: Exception, context: Dict[str, Any]):
62
62
  """Hook executed when an error occurs."""
63
- logger.error(f"🔧 Application hook: on_error - {error} in context: {context}")
63
+ get_global_logger().error(f"🔧 Application hook: on_error - {error} in context: {context}")
64
64
  # Log error details
65
- logger.error(f"Error type: {type(error).__name__}")
66
- logger.error(f"Error message: {str(error)}")
67
- logger.error(f"Context: {context}")
65
+ get_global_logger().error(f"Error type: {type(error).__name__}")
66
+ get_global_logger().error(f"Error message: {str(error)}")
67
+ get_global_logger().error(f"Context: {context}")
68
68
 
69
69
  @staticmethod
70
70
  def on_command_registered(command_name: str, command_info: Dict[str, Any]):
71
71
  """Hook executed when a command is registered."""
72
- logger.info(f"🔧 Application hook: on_command_registered - {command_name}")
73
- logger.info(f"Command info: {command_info}")
72
+ get_global_logger().info(f"🔧 Application hook: on_command_registered - {command_name}")
73
+ get_global_logger().info(f"Command info: {command_info}")
74
74
  # Track registered commands
75
- logger.info(f"📝 Command '{command_name}' registered successfully")
75
+ get_global_logger().info(f"📝 Command '{command_name}' registered successfully")
76
76
 
77
77
  @staticmethod
78
78
  def on_command_executed(command_name: str, execution_time: float, success: bool):
79
79
  """Hook executed when a command is executed."""
80
- logger.info(f"🔧 Application hook: on_command_executed - {command_name}")
81
- logger.info(f"Execution time: {execution_time}s, Success: {success}")
80
+ get_global_logger().info(f"🔧 Application hook: on_command_executed - {command_name}")
81
+ get_global_logger().info(f"Execution time: {execution_time}s, Success: {success}")
82
82
  # Track command execution metrics
83
83
  if success:
84
- logger.info(
84
+ get_global_logger().info(
85
85
  f"✅ Command '{command_name}' executed successfully in {execution_time}s"
86
86
  )
87
87
  else:
88
- logger.warning(f"⚠️ Command '{command_name}' failed after {execution_time}s")
88
+ get_global_logger().warning(f"⚠️ Command '{command_name}' failed after {execution_time}s")
@@ -18,7 +18,7 @@ class BuiltinCommandHooks:
18
18
  @staticmethod
19
19
  def before_echo_command(params: Dict[str, Any]) -> Dict[str, Any]:
20
20
  """Hook executed before echo command."""
21
- logger.info(f"🔧 Built-in hook: before_echo_command with params: {params}")
21
+ get_global_logger().info(f"🔧 Built-in hook: before_echo_command with params: {params}")
22
22
  # Add timestamp to message
23
23
  if "message" in params:
24
24
  timestamp = datetime.now().isoformat()
@@ -28,7 +28,7 @@ class BuiltinCommandHooks:
28
28
  @staticmethod
29
29
  def after_echo_command(result: Dict[str, Any]) -> Dict[str, Any]:
30
30
  """Hook executed after echo command."""
31
- logger.info(f"🔧 Built-in hook: after_echo_command with result: {result}")
31
+ get_global_logger().info(f"🔧 Built-in hook: after_echo_command with result: {result}")
32
32
  # Add hook metadata
33
33
  result["hook_metadata"] = {
34
34
  "hook_type": "builtin_after_echo",
@@ -40,7 +40,7 @@ class BuiltinCommandHooks:
40
40
  @staticmethod
41
41
  def before_health_command(params: Dict[str, Any]) -> Dict[str, Any]:
42
42
  """Hook executed before health command."""
43
- logger.info(f"🔧 Built-in hook: before_health_command with params: {params}")
43
+ get_global_logger().info(f"🔧 Built-in hook: before_health_command with params: {params}")
44
44
  # Add custom health check parameters
45
45
  params["include_detailed_info"] = True
46
46
  params["check_dependencies"] = True
@@ -49,7 +49,7 @@ class BuiltinCommandHooks:
49
49
  @staticmethod
50
50
  def after_health_command(result: Dict[str, Any]) -> Dict[str, Any]:
51
51
  """Hook executed after health command."""
52
- logger.info(f"🔧 Built-in hook: after_health_command with result: {result}")
52
+ get_global_logger().info(f"🔧 Built-in hook: after_health_command with result: {result}")
53
53
  # Add custom health metrics
54
54
  if "status" in result and result["status"] == "healthy":
55
55
  result["custom_metrics"] = {
@@ -62,7 +62,7 @@ class BuiltinCommandHooks:
62
62
  @staticmethod
63
63
  def before_config_command(params: Dict[str, Any]) -> Dict[str, Any]:
64
64
  """Hook executed before config command."""
65
- logger.info(f"🔧 Built-in hook: before_config_command with params: {params}")
65
+ get_global_logger().info(f"🔧 Built-in hook: before_config_command with params: {params}")
66
66
  # Add configuration validation
67
67
  params["validate_config"] = True
68
68
  params["include_secrets"] = False
@@ -71,7 +71,7 @@ class BuiltinCommandHooks:
71
71
  @staticmethod
72
72
  def after_config_command(result: Dict[str, Any]) -> Dict[str, Any]:
73
73
  """Hook executed after config command."""
74
- logger.info(f"🔧 Built-in hook: after_config_command with result: {result}")
74
+ get_global_logger().info(f"🔧 Built-in hook: after_config_command with result: {result}")
75
75
  # Add configuration metadata
76
76
  result["config_metadata"] = {
77
77
  "last_modified": datetime.now().isoformat(),
@@ -30,6 +30,7 @@ class FullApplication:
30
30
  self.config_path = config_path
31
31
  try:
32
32
  self.config = Config(config_path, validate_on_load=True)
33
+ self.config.load_config() # Explicitly load the configuration
33
34
  self.logger = logging.getLogger(__name__)
34
35
  self.logger.info("✅ Configuration loaded and validated successfully")
35
36
  except Exception as e:
@@ -152,5 +153,32 @@ def get_app():
152
153
  return app
153
154
 
154
155
 
156
+ def main():
157
+ """Main entry point."""
158
+ import argparse
159
+
160
+ parser = argparse.ArgumentParser(description="MCP Proxy Adapter Full Application")
161
+ parser.add_argument("--config", required=True, help="Path to configuration file")
162
+ parser.add_argument("--port", type=int, help="Port to run server on")
163
+ parser.add_argument("--host", default="0.0.0.0", help="Host to bind to")
164
+
165
+ args = parser.parse_args()
166
+
167
+ # Create application
168
+ app_instance = FullApplication(args.config)
169
+
170
+ # Override port if specified
171
+ if args.port:
172
+ app_instance.config.config_data["server"]["port"] = args.port
173
+ print(f"🔧 Overriding port to {args.port}")
174
+
175
+ # Override host if specified
176
+ if args.host:
177
+ app_instance.config.config_data["server"]["host"] = args.host
178
+ print(f"🔧 Overriding host to {args.host}")
179
+
180
+ # Run server
181
+ app_instance.run()
182
+
155
183
  if __name__ == "__main__":
156
184
  main()