mcp-proxy-adapter 6.3.3__py3-none-any.whl → 6.3.5__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 (129) hide show
  1. mcp_proxy_adapter/__init__.py +9 -5
  2. mcp_proxy_adapter/__main__.py +1 -1
  3. mcp_proxy_adapter/api/app.py +227 -176
  4. mcp_proxy_adapter/api/handlers.py +68 -60
  5. mcp_proxy_adapter/api/middleware/__init__.py +7 -5
  6. mcp_proxy_adapter/api/middleware/base.py +19 -16
  7. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
  8. mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
  9. mcp_proxy_adapter/api/middleware/factory.py +50 -52
  10. mcp_proxy_adapter/api/middleware/logging.py +46 -30
  11. mcp_proxy_adapter/api/middleware/performance.py +19 -16
  12. mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
  13. mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
  14. mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
  15. mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
  16. mcp_proxy_adapter/api/schemas.py +69 -43
  17. mcp_proxy_adapter/api/tool_integration.py +83 -63
  18. mcp_proxy_adapter/api/tools.py +60 -50
  19. mcp_proxy_adapter/commands/__init__.py +15 -6
  20. mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
  21. mcp_proxy_adapter/commands/base.py +108 -112
  22. mcp_proxy_adapter/commands/builtin_commands.py +28 -18
  23. mcp_proxy_adapter/commands/catalog_manager.py +394 -265
  24. mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
  25. mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
  26. mcp_proxy_adapter/commands/command_registry.py +275 -226
  27. mcp_proxy_adapter/commands/config_command.py +48 -33
  28. mcp_proxy_adapter/commands/dependency_container.py +22 -23
  29. mcp_proxy_adapter/commands/dependency_manager.py +65 -56
  30. mcp_proxy_adapter/commands/echo_command.py +15 -15
  31. mcp_proxy_adapter/commands/health_command.py +31 -29
  32. mcp_proxy_adapter/commands/help_command.py +97 -61
  33. mcp_proxy_adapter/commands/hooks.py +65 -49
  34. mcp_proxy_adapter/commands/key_management_command.py +148 -147
  35. mcp_proxy_adapter/commands/load_command.py +58 -40
  36. mcp_proxy_adapter/commands/plugins_command.py +80 -54
  37. mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
  38. mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
  39. mcp_proxy_adapter/commands/reload_command.py +43 -37
  40. mcp_proxy_adapter/commands/result.py +26 -33
  41. mcp_proxy_adapter/commands/role_test_command.py +26 -26
  42. mcp_proxy_adapter/commands/roles_management_command.py +176 -173
  43. mcp_proxy_adapter/commands/security_command.py +134 -122
  44. mcp_proxy_adapter/commands/settings_command.py +47 -56
  45. mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
  46. mcp_proxy_adapter/commands/token_management_command.py +129 -158
  47. mcp_proxy_adapter/commands/transport_management_command.py +41 -36
  48. mcp_proxy_adapter/commands/unload_command.py +42 -37
  49. mcp_proxy_adapter/config.py +36 -35
  50. mcp_proxy_adapter/core/__init__.py +19 -21
  51. mcp_proxy_adapter/core/app_factory.py +30 -9
  52. mcp_proxy_adapter/core/app_runner.py +81 -64
  53. mcp_proxy_adapter/core/auth_validator.py +176 -182
  54. mcp_proxy_adapter/core/certificate_utils.py +469 -426
  55. mcp_proxy_adapter/core/client.py +155 -126
  56. mcp_proxy_adapter/core/client_manager.py +60 -54
  57. mcp_proxy_adapter/core/client_security.py +108 -88
  58. mcp_proxy_adapter/core/config_converter.py +176 -143
  59. mcp_proxy_adapter/core/config_validator.py +12 -4
  60. mcp_proxy_adapter/core/crl_utils.py +21 -7
  61. mcp_proxy_adapter/core/errors.py +64 -20
  62. mcp_proxy_adapter/core/logging.py +34 -29
  63. mcp_proxy_adapter/core/mtls_asgi.py +29 -25
  64. mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
  65. mcp_proxy_adapter/core/protocol_manager.py +154 -104
  66. mcp_proxy_adapter/core/proxy_client.py +202 -144
  67. mcp_proxy_adapter/core/proxy_registration.py +12 -2
  68. mcp_proxy_adapter/core/role_utils.py +139 -125
  69. mcp_proxy_adapter/core/security_adapter.py +88 -77
  70. mcp_proxy_adapter/core/security_factory.py +50 -44
  71. mcp_proxy_adapter/core/security_integration.py +72 -24
  72. mcp_proxy_adapter/core/server_adapter.py +68 -64
  73. mcp_proxy_adapter/core/server_engine.py +71 -53
  74. mcp_proxy_adapter/core/settings.py +68 -58
  75. mcp_proxy_adapter/core/ssl_utils.py +69 -56
  76. mcp_proxy_adapter/core/transport_manager.py +72 -60
  77. mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
  78. mcp_proxy_adapter/core/utils.py +4 -2
  79. mcp_proxy_adapter/custom_openapi.py +107 -99
  80. mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
  81. mcp_proxy_adapter/examples/commands/__init__.py +1 -1
  82. mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
  83. mcp_proxy_adapter/examples/debug_request_state.py +38 -19
  84. mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
  85. mcp_proxy_adapter/examples/demo_client.py +48 -36
  86. mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
  87. mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
  88. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
  89. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  90. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
  91. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  92. mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
  93. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
  94. mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
  95. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
  96. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  97. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
  98. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  99. mcp_proxy_adapter/examples/full_application/main.py +27 -2
  100. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
  101. mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
  102. mcp_proxy_adapter/examples/generate_certificates.py +31 -16
  103. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
  104. mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
  105. mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
  106. mcp_proxy_adapter/examples/run_example.py +23 -5
  107. mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
  108. mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
  109. mcp_proxy_adapter/examples/run_security_tests.py +103 -41
  110. mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
  111. mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
  112. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
  113. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
  114. mcp_proxy_adapter/examples/security_test_client.py +196 -127
  115. mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
  116. mcp_proxy_adapter/examples/test_config.py +19 -4
  117. mcp_proxy_adapter/examples/test_config_generator.py +23 -7
  118. mcp_proxy_adapter/examples/test_examples.py +84 -56
  119. mcp_proxy_adapter/examples/universal_client.py +119 -62
  120. mcp_proxy_adapter/openapi.py +108 -115
  121. mcp_proxy_adapter/utils/config_generator.py +429 -274
  122. mcp_proxy_adapter/version.py +1 -2
  123. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
  124. mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
  125. mcp_proxy_adapter-6.3.3.dist-info/RECORD +0 -143
  126. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
  127. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
  128. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
  129. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -13,11 +13,15 @@ from mcp_proxy_adapter.core.logging import logger
13
13
 
14
14
  class TransportManagementResult(SuccessResult):
15
15
  """Result class for transport management operations."""
16
-
17
- def __init__(self, transport_info: Dict[str, Any], message: str = "Transport management operation completed"):
16
+
17
+ def __init__(
18
+ self,
19
+ transport_info: Dict[str, Any],
20
+ message: str = "Transport management operation completed",
21
+ ):
18
22
  """
19
23
  Initialize transport management result.
20
-
24
+
21
25
  Args:
22
26
  transport_info: Transport information
23
27
  message: Success message
@@ -28,18 +32,18 @@ class TransportManagementResult(SuccessResult):
28
32
  class TransportManagementCommand(Command):
29
33
  """
30
34
  Transport management command.
31
-
35
+
32
36
  This command provides functionality to manage and query transport configurations.
33
37
  """
34
-
38
+
35
39
  name = "transport_management"
36
40
  descr = "Manage and query transport configurations (HTTP, HTTPS, MTLS)"
37
-
41
+
38
42
  @classmethod
39
43
  def get_schema(cls) -> Dict[str, Any]:
40
44
  """
41
45
  Get command schema.
42
-
46
+
43
47
  Returns:
44
48
  Command schema dictionary
45
49
  """
@@ -49,25 +53,25 @@ class TransportManagementCommand(Command):
49
53
  "action": {
50
54
  "type": "string",
51
55
  "enum": ["get_info", "validate", "reload"],
52
- "description": "Action to perform"
56
+ "description": "Action to perform",
53
57
  }
54
58
  },
55
- "required": ["action"]
59
+ "required": ["action"],
56
60
  }
57
-
61
+
58
62
  async def execute(self, **params) -> TransportManagementResult:
59
63
  """
60
64
  Execute transport management command.
61
-
65
+
62
66
  Args:
63
67
  params: Command parameters
64
-
68
+
65
69
  Returns:
66
70
  Transport management result
67
71
  """
68
72
  try:
69
73
  action = params.get("action", "get_info")
70
-
74
+
71
75
  if action == "get_info":
72
76
  return await self._get_transport_info()
73
77
  elif action == "validate":
@@ -77,56 +81,57 @@ class TransportManagementCommand(Command):
77
81
  else:
78
82
  return TransportManagementResult(
79
83
  transport_info={"error": f"Unknown action: {action}"},
80
- message=f"Unknown action: {action}"
84
+ message=f"Unknown action: {action}",
81
85
  )
82
-
86
+
83
87
  except Exception as e:
84
88
  logger.error(f"Transport management command error: {e}")
85
89
  return TransportManagementResult(
86
90
  transport_info={"error": str(e)},
87
- message=f"Transport management failed: {e}"
91
+ message=f"Transport management failed: {e}",
88
92
  )
89
-
93
+
90
94
  async def _get_transport_info(self) -> TransportManagementResult:
91
95
  """
92
96
  Get transport information.
93
-
97
+
94
98
  Returns:
95
99
  Transport information result
96
100
  """
97
101
  transport_info = transport_manager.get_transport_info()
98
-
102
+
99
103
  return TransportManagementResult(
100
104
  transport_info=transport_info,
101
- message="Transport information retrieved successfully"
105
+ message="Transport information retrieved successfully",
102
106
  )
103
-
107
+
104
108
  async def _validate_transport(self) -> TransportManagementResult:
105
109
  """
106
110
  Validate transport configuration.
107
-
111
+
108
112
  Returns:
109
113
  Validation result
110
114
  """
111
115
  is_valid = transport_manager.validate_config()
112
-
116
+
113
117
  transport_info = transport_manager.get_transport_info()
114
118
  transport_info["validation"] = {
115
119
  "is_valid": is_valid,
116
- "timestamp": "2025-08-15T12:00:00Z"
120
+ "timestamp": "2025-08-15T12:00:00Z",
117
121
  }
118
-
119
- message = "Transport configuration validated successfully" if is_valid else "Transport configuration validation failed"
120
-
121
- return TransportManagementResult(
122
- transport_info=transport_info,
123
- message=message
122
+
123
+ message = (
124
+ "Transport configuration validated successfully"
125
+ if is_valid
126
+ else "Transport configuration validation failed"
124
127
  )
125
-
128
+
129
+ return TransportManagementResult(transport_info=transport_info, message=message)
130
+
126
131
  async def _reload_transport(self) -> TransportManagementResult:
127
132
  """
128
133
  Reload transport configuration.
129
-
134
+
130
135
  Returns:
131
136
  Reload result
132
137
  """
@@ -135,10 +140,10 @@ class TransportManagementCommand(Command):
135
140
  transport_info = transport_manager.get_transport_info()
136
141
  transport_info["reload"] = {
137
142
  "status": "completed",
138
- "timestamp": "2025-08-15T12:00:00Z"
143
+ "timestamp": "2025-08-15T12:00:00Z",
139
144
  }
140
-
145
+
141
146
  return TransportManagementResult(
142
147
  transport_info=transport_info,
143
- message="Transport configuration reload completed"
144
- )
148
+ message="Transport configuration reload completed",
149
+ )
@@ -13,31 +13,34 @@ class UnloadResult(SuccessResult):
13
13
  """
14
14
  Result of the unload command execution.
15
15
  """
16
-
17
- def __init__(self, success: bool, command_name: str, message: str, error: Optional[str] = None):
16
+
17
+ def __init__(
18
+ self,
19
+ success: bool,
20
+ command_name: str,
21
+ message: str,
22
+ error: Optional[str] = None,
23
+ ):
18
24
  """
19
25
  Initialize unload command result.
20
-
26
+
21
27
  Args:
22
28
  success: Whether unloading was successful
23
29
  command_name: Name of the command that was unloaded
24
30
  message: Result message
25
31
  error: Error message if unloading failed
26
32
  """
27
- data = {
28
- "success": success,
29
- "command_name": command_name
30
- }
33
+ data = {"success": success, "command_name": command_name}
31
34
  if error:
32
35
  data["error"] = error
33
-
36
+
34
37
  super().__init__(data=data, message=message)
35
-
38
+
36
39
  @classmethod
37
40
  def get_schema(cls) -> Dict[str, Any]:
38
41
  """
39
42
  Get JSON schema for result validation.
40
-
43
+
41
44
  Returns:
42
45
  Dict[str, Any]: JSON schema
43
46
  """
@@ -49,69 +52,69 @@ class UnloadResult(SuccessResult):
49
52
  "properties": {
50
53
  "success": {"type": "boolean"},
51
54
  "command_name": {"type": "string"},
52
- "error": {"type": "string"}
55
+ "error": {"type": "string"},
53
56
  },
54
- "required": ["success", "command_name"]
57
+ "required": ["success", "command_name"],
55
58
  }
56
59
  },
57
- "required": ["data"]
60
+ "required": ["data"],
58
61
  }
59
62
 
60
63
 
61
64
  class UnloadCommand(Command):
62
65
  """
63
66
  Command that unloads loaded commands from registry.
64
-
67
+
65
68
  This command allows removal of dynamically loaded commands from the command registry.
66
69
  Only commands that were loaded via the 'load' command or from the commands directory
67
70
  can be unloaded. Built-in commands and custom commands registered with higher priority
68
71
  cannot be unloaded using this command.
69
-
72
+
70
73
  When a command is unloaded:
71
74
  - The command class is removed from the loaded commands registry
72
75
  - Any command instances are also removed
73
76
  - The command becomes unavailable for execution
74
77
  - Built-in and custom commands with the same name remain unaffected
75
-
78
+
76
79
  This is useful for:
77
80
  - Removing outdated or problematic commands
78
81
  - Managing memory usage by unloading unused commands
79
82
  - Testing different versions of commands
80
83
  - Cleaning up temporary commands loaded for testing
81
-
84
+
82
85
  Note: Unloading a command does not affect other commands and does not require
83
86
  a system restart. The command can be reloaded later if needed.
84
87
  """
85
-
88
+
86
89
  name = "unload"
87
90
  result_class = UnloadResult
88
-
91
+
89
92
  async def execute(self, command_name: str, **kwargs) -> UnloadResult:
90
93
  """
91
94
  Execute unload command.
92
-
95
+
93
96
  Args:
94
97
  command_name: Name of the command to unload
95
98
  **kwargs: Additional parameters
96
-
99
+
97
100
  Returns:
98
101
  UnloadResult: Unload command result
99
102
  """
100
103
  # Unload command from registry
101
104
  result = registry.unload_command(command_name)
102
-
105
+
103
106
  return UnloadResult(
104
107
  success=result.get("success", False),
105
108
  command_name=result.get("command_name", command_name),
106
109
  message=result.get("message", "Unknown result"),
107
- error=result.get("error")
110
+ error=result.get("error"),
108
111
  )
109
-
112
+
110
113
  @classmethod
111
114
  def get_schema(cls) -> Dict[str, Any]:
112
115
  """
113
116
  Get JSON schema for command parameters.
114
-
117
+
115
118
  Returns:
116
119
  Dict[str, Any]: JSON schema
117
120
  """
@@ -120,20 +123,22 @@ class UnloadCommand(Command):
120
123
  "properties": {
121
124
  "command_name": {
122
125
  "type": "string",
123
- "description": "Name of the command to unload (must be a loaded command)"
126
+ "description": "Name of the command to unload (must be a loaded command)",
124
127
  }
125
128
  },
126
- "required": ["command_name"]
129
+ "required": ["command_name"],
127
130
  }
128
-
131
+
129
132
  @classmethod
130
- def _generate_examples(cls, params: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:
133
+ def _generate_examples(
134
+ cls, params: Dict[str, Dict[str, Any]]
135
+ ) -> List[Dict[str, Any]]:
131
136
  """
132
137
  Generate custom examples for unload command.
133
-
138
+
134
139
  Args:
135
140
  params: Information about command parameters
136
-
141
+
137
142
  Returns:
138
143
  List of examples
139
144
  """
@@ -141,18 +146,18 @@ class UnloadCommand(Command):
141
146
  {
142
147
  "command": cls.name,
143
148
  "params": {"command_name": "test_command"},
144
- "description": "Unload a previously loaded test command"
149
+ "description": "Unload a previously loaded test command",
145
150
  },
146
151
  {
147
152
  "command": cls.name,
148
153
  "params": {"command_name": "remote_command"},
149
- "description": "Unload a command that was loaded from URL"
154
+ "description": "Unload a command that was loaded from URL",
150
155
  },
151
156
  {
152
157
  "command": cls.name,
153
158
  "params": {"command_name": "custom_command"},
154
- "description": "Unload a custom command loaded from local file"
155
- }
159
+ "description": "Unload a custom command loaded from local file",
160
+ },
156
161
  ]
157
-
158
- return examples
162
+
163
+ return examples
@@ -39,7 +39,7 @@ class Config:
39
39
  "host": "0.0.0.0",
40
40
  "port": 8000,
41
41
  "debug": False,
42
- "log_level": "INFO"
42
+ "log_level": "INFO",
43
43
  },
44
44
  "logging": {
45
45
  "level": "INFO",
@@ -53,7 +53,7 @@ class Config:
53
53
  "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
54
54
  "date_format": "%Y-%m-%d %H:%M:%S",
55
55
  "console_output": True,
56
- "file_output": True
56
+ "file_output": True,
57
57
  },
58
58
  "commands": {
59
59
  "auto_discovery": True,
@@ -63,7 +63,7 @@ class Config:
63
63
  "auto_install_dependencies": True,
64
64
  "enabled_commands": ["health", "echo", "list", "help"],
65
65
  "disabled_commands": [],
66
- "custom_commands_path": "./commands"
66
+ "custom_commands_path": "./commands",
67
67
  },
68
68
  "ssl": {
69
69
  "enabled": False,
@@ -75,7 +75,7 @@ class Config:
75
75
  "client_cert_required": False,
76
76
  "cipher_suites": [
77
77
  "TLS_AES_256_GCM_SHA384",
78
- "TLS_CHACHA20_POLY1305_SHA256"
78
+ "TLS_CHACHA20_POLY1305_SHA256",
79
79
  ],
80
80
  "min_tls_version": "TLSv1.2",
81
81
  "max_tls_version": "1.3",
@@ -86,8 +86,8 @@ class Config:
86
86
  "tokens_file": "tokens.json",
87
87
  "token_expiry": 3600,
88
88
  "jwt_secret": "",
89
- "jwt_algorithm": "HS256"
90
- }
89
+ "jwt_algorithm": "HS256",
90
+ },
91
91
  },
92
92
  "roles": {
93
93
  "enabled": False,
@@ -96,10 +96,10 @@ class Config:
96
96
  "deny_by_default": False,
97
97
  "require_role_match": False,
98
98
  "case_sensitive": False,
99
- "allow_wildcard": False
99
+ "allow_wildcard": False,
100
100
  },
101
101
  "auto_load": False,
102
- "validation_enabled": False
102
+ "validation_enabled": False,
103
103
  },
104
104
  "transport": {
105
105
  "type": "http",
@@ -110,8 +110,8 @@ class Config:
110
110
  "key_file": None,
111
111
  "ca_cert": None,
112
112
  "verify_client": False,
113
- "client_cert_required": False
114
- }
113
+ "client_cert_required": False,
114
+ },
115
115
  },
116
116
  "proxy_registration": {
117
117
  "enabled": False,
@@ -124,12 +124,9 @@ class Config:
124
124
  "retry_attempts": 3,
125
125
  "retry_delay": 5,
126
126
  "auto_register_on_startup": True,
127
- "auto_unregister_on_shutdown": True
128
- },
129
- "debug": {
130
- "enabled": False,
131
- "level": "WARNING"
127
+ "auto_unregister_on_shutdown": True,
132
128
  },
129
+ "debug": {"enabled": False, "level": "WARNING"},
133
130
  "security": {
134
131
  "framework": "mcp_security_framework",
135
132
  "enabled": False,
@@ -150,7 +147,7 @@ class Config:
150
147
  "basic_auth": False,
151
148
  "oauth2_config": None,
152
149
  "public_paths": ["/health", "/docs", "/openapi.json"],
153
- "security_headers": None
150
+ "security_headers": None,
154
151
  },
155
152
  "ssl": {
156
153
  "enabled": False,
@@ -165,7 +162,7 @@ class Config:
165
162
  "cipher_suite": None,
166
163
  "check_hostname": True,
167
164
  "check_expiry": True,
168
- "expiry_warning_days": 30
165
+ "expiry_warning_days": 30,
169
166
  },
170
167
  "certificates": {
171
168
  "enabled": False,
@@ -181,7 +178,7 @@ class Config:
181
178
  "crl_url": None,
182
179
  "crl_validity_days": 30,
183
180
  "auto_renewal": False,
184
- "renewal_threshold_days": 30
181
+ "renewal_threshold_days": 30,
185
182
  },
186
183
  "permissions": {
187
184
  "enabled": False,
@@ -193,7 +190,7 @@ class Config:
193
190
  "permission_cache_ttl": 300,
194
191
  "wildcard_permissions": False,
195
192
  "strict_mode": False,
196
- "roles": None
193
+ "roles": None,
197
194
  },
198
195
  "rate_limit": {
199
196
  "enabled": False,
@@ -205,7 +202,7 @@ class Config:
205
202
  "redis_config": None,
206
203
  "cleanup_interval": 300,
207
204
  "exempt_paths": ["/health", "/docs", "/openapi.json"],
208
- "exempt_roles": ["admin"]
205
+ "exempt_roles": ["admin"],
209
206
  },
210
207
  "logging": {
211
208
  "enabled": True,
@@ -219,21 +216,21 @@ class Config:
219
216
  "json_format": False,
220
217
  "include_timestamp": True,
221
218
  "include_level": True,
222
- "include_module": True
223
- }
219
+ "include_module": True,
220
+ },
224
221
  },
225
222
  "protocols": {
226
223
  "enabled": True,
227
224
  "allowed_protocols": ["http", "jsonrpc"],
228
225
  "default_protocol": "http",
229
- "auto_discovery": True
230
- }
226
+ "auto_discovery": True,
227
+ },
231
228
  }
232
229
 
233
230
  # Try to load configuration from file
234
231
  if os.path.exists(self.config_path):
235
232
  try:
236
- with open(self.config_path, 'r', encoding='utf-8') as f:
233
+ with open(self.config_path, "r", encoding="utf-8") as f:
237
234
  file_config = json.load(f)
238
235
  self._update_nested_dict(self.config_data, file_config)
239
236
  except Exception as e:
@@ -261,7 +258,7 @@ class Config:
261
258
  prefix = "SERVICE_"
262
259
  for key, value in os.environ.items():
263
260
  if key.startswith(prefix):
264
- parts = key[len(prefix):].lower().split("_", 1)
261
+ parts = key[len(prefix) :].lower().split("_", 1)
265
262
  if len(parts) == 2:
266
263
  section, param = parts
267
264
  if section not in self.config_data:
@@ -357,7 +354,7 @@ class Config:
357
354
  self.config_path is used.
358
355
  """
359
356
  save_path = path or self.config_path
360
- with open(save_path, 'w', encoding='utf-8') as f:
357
+ with open(save_path, "w", encoding="utf-8") as f:
361
358
  json.dump(self.config_data, f, indent=2)
362
359
 
363
360
  def _update_nested_dict(self, d: Dict, u: Dict) -> Dict:
@@ -444,13 +441,15 @@ class Config:
444
441
  True if feature is enabled, False otherwise
445
442
  """
446
443
  if feature == "ssl":
447
- return (self.get("ssl.enabled", False) or
448
- self.get("security.ssl.enabled", False))
444
+ return self.get("ssl.enabled", False) or self.get(
445
+ "security.ssl.enabled", False
446
+ )
449
447
  elif feature == "auth":
450
448
  return self.get("security.auth.enabled", False)
451
449
  elif feature == "roles":
452
- return (self.get("security.permissions.enabled", False) or
453
- self.get("roles.enabled", False))
450
+ return self.get("security.permissions.enabled", False) or self.get(
451
+ "roles.enabled", False
452
+ )
454
453
  elif feature == "proxy_registration":
455
454
  return self.get("proxy_registration.enabled", False)
456
455
  elif feature == "security":
@@ -535,11 +534,13 @@ class Config:
535
534
  elif mode == "certificate":
536
535
  self.set("proxy_registration.auth_method", "certificate")
537
536
  if "cert_file" in kwargs:
538
- self.set("proxy_registration.certificate.cert_file",
539
- kwargs["cert_file"])
537
+ self.set(
538
+ "proxy_registration.certificate.cert_file", kwargs["cert_file"]
539
+ )
540
540
  if "key_file" in kwargs:
541
- self.set("proxy_registration.certificate.key_file",
542
- kwargs["key_file"])
541
+ self.set(
542
+ "proxy_registration.certificate.key_file", kwargs["key_file"]
543
+ )
543
544
  elif mode == "api_key":
544
545
  self.set("proxy_registration.auth_method", "api_key")
545
546
  if "key" in kwargs:
@@ -12,7 +12,6 @@ __all__ = [
12
12
  "InvalidParamsError",
13
13
  "CommandExecutionError",
14
14
  "ConfigurationError",
15
-
16
15
  # Logging
17
16
  "setup_logging",
18
17
  "get_logger",
@@ -20,25 +19,24 @@ __all__ = [
20
19
  "RequestLogger",
21
20
  "CustomFormatter",
22
21
  "RequestContextFilter",
23
-
24
22
  # Settings
25
- "Settings",
26
- "ServerSettings",
27
- "LoggingSettings",
28
- "CommandsSettings",
29
- "get_server_host",
30
- "get_server_port",
31
- "get_server_debug",
32
- "get_logging_level",
33
- "get_logging_dir",
34
- "get_auto_discovery",
35
- "get_discovery_path",
36
- "get_setting",
37
- "set_setting",
38
- "reload_settings",
39
- "add_custom_settings",
40
- "get_custom_settings",
41
- "get_custom_setting_value",
42
- "set_custom_setting_value",
43
- "clear_custom_settings"
23
+ "Settings",
24
+ "ServerSettings",
25
+ "LoggingSettings",
26
+ "CommandsSettings",
27
+ "get_server_host",
28
+ "get_server_port",
29
+ "get_server_debug",
30
+ "get_logging_level",
31
+ "get_logging_dir",
32
+ "get_auto_discovery",
33
+ "get_discovery_path",
34
+ "get_setting",
35
+ "set_setting",
36
+ "reload_settings",
37
+ "add_custom_settings",
38
+ "get_custom_settings",
39
+ "get_custom_setting_value",
40
+ "set_custom_setting_value",
41
+ "clear_custom_settings",
44
42
  ]