mcp-proxy-adapter 6.2.36__py3-none-any.whl → 6.3.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.
@@ -7,8 +7,8 @@ with invalid or insecure configurations.
7
7
 
8
8
  import os
9
9
  import json
10
- from typing import Dict, Any, List, Optional
11
- from pathlib import Path
10
+ import uuid
11
+ from typing import Dict, Any, List
12
12
 
13
13
  from mcp_proxy_adapter.core.logging import logger
14
14
 
@@ -16,220 +16,257 @@ from mcp_proxy_adapter.core.logging import logger
16
16
  class ConfigValidator:
17
17
  """
18
18
  Strict configuration validator.
19
-
19
+
20
20
  Validates configuration before startup and prevents startup
21
21
  with invalid or insecure configurations.
22
22
  """
23
-
23
+
24
24
  def __init__(self, config: Dict[str, Any]):
25
25
  """
26
26
  Initialize configuration validator.
27
-
27
+
28
28
  Args:
29
29
  config: Configuration dictionary to validate
30
30
  """
31
31
  self.config = config
32
32
  self.errors: List[str] = []
33
33
  self.warnings: List[str] = []
34
-
34
+
35
35
  def validate_all(self) -> bool:
36
36
  """
37
37
  Validate all configuration sections.
38
-
38
+
39
39
  Returns:
40
40
  True if configuration is valid, False otherwise
41
41
  """
42
42
  self.errors.clear()
43
43
  self.warnings.clear()
44
-
44
+
45
45
  # Validate basic structure
46
46
  if not self._validate_basic_structure():
47
47
  return False
48
-
48
+
49
+ # Validate UUID configuration (mandatory)
50
+ if not self._validate_uuid_config():
51
+ return False
52
+
49
53
  # Validate server configuration
50
54
  if not self._validate_server_config():
51
55
  return False
52
-
56
+
53
57
  # Validate security configuration
54
58
  if not self._validate_security_config():
55
59
  return False
56
-
60
+
57
61
  # Validate commands configuration
58
62
  if not self._validate_commands_config():
59
63
  return False
60
-
64
+
61
65
  # Validate SSL configuration
62
66
  if not self._validate_ssl_config():
63
67
  return False
64
-
68
+
65
69
  # Validate roles configuration
66
70
  if not self._validate_roles_config():
67
71
  return False
68
-
72
+
69
73
  # Log warnings if any
70
74
  if self.warnings:
71
75
  for warning in self.warnings:
72
76
  logger.warning(f"Configuration warning: {warning}")
73
-
77
+
74
78
  # Return success only if no errors
75
79
  return len(self.errors) == 0
76
-
80
+
77
81
  def _validate_basic_structure(self) -> bool:
78
82
  """Validate basic configuration structure."""
79
83
  required_sections = ["server", "logging", "commands"]
80
-
84
+
81
85
  for section in required_sections:
82
86
  if section not in self.config:
83
87
  self.errors.append(f"Missing required configuration section: {section}")
84
-
88
+
85
89
  return len(self.errors) == 0
86
-
90
+
91
+ def _validate_uuid_config(self) -> bool:
92
+ """Validate UUID configuration (mandatory parameter)."""
93
+ # Check if UUID is present in root config
94
+ service_uuid = self.config.get("uuid")
95
+
96
+ if not service_uuid:
97
+ self.errors.append(
98
+ "UUID is required in configuration. Add 'uuid' field with a valid UUID4 value."
99
+ )
100
+ return False
101
+
102
+ # Validate UUID format
103
+ try:
104
+ # Try to parse as UUID
105
+ parsed_uuid = uuid.UUID(service_uuid)
106
+
107
+ # Check if it's UUID4 (version 4)
108
+ if parsed_uuid.version != 4:
109
+ self.errors.append(
110
+ f"UUID must be version 4 (UUID4). Current version: {parsed_uuid.version}"
111
+ )
112
+ return False
113
+
114
+ except (ValueError, TypeError) as e:
115
+ self.errors.append(f"Invalid UUID format: {service_uuid}. Error: {e}")
116
+ return False
117
+
118
+ return len(self.errors) == 0
119
+
87
120
  def _validate_server_config(self) -> bool:
88
121
  """Validate server configuration."""
89
122
  server_config = self.config.get("server", {})
90
-
123
+
91
124
  # Validate host
92
125
  host = server_config.get("host")
93
126
  if not host:
94
127
  self.errors.append("Server host is required")
95
-
128
+
96
129
  # Validate port
97
130
  port = server_config.get("port")
98
131
  if not isinstance(port, int) or port < 1 or port > 65535:
99
132
  self.errors.append("Server port must be an integer between 1 and 65535")
100
-
133
+
101
134
  return len(self.errors) == 0
102
-
135
+
103
136
  def _validate_security_config(self) -> bool:
104
137
  """Validate security configuration."""
105
138
  security_config = self.config.get("security", {})
106
-
139
+
107
140
  # Check if security is enabled
108
141
  security_enabled = security_config.get("enabled", True)
109
142
  auth_enabled = self.config.get("auth_enabled", False)
110
-
143
+
111
144
  # Validate permissions configuration
112
145
  permissions_config = security_config.get("permissions", {})
113
146
  permissions_enabled = permissions_config.get("enabled", False)
114
-
147
+
115
148
  if permissions_enabled:
116
149
  # Permissions require authentication to identify users
117
150
  auth_config = security_config.get("auth", {})
118
151
  if not auth_config.get("enabled", False):
119
- self.errors.append("Permissions are enabled but authentication is disabled. Permissions require authentication to identify users.")
152
+ self.errors.append(
153
+ "Permissions are enabled but authentication is disabled. Permissions require authentication to identify users."
154
+ )
120
155
  return False
121
-
156
+
122
157
  # Check if there are any authentication methods available
123
158
  auth_methods = auth_config.get("methods", [])
124
159
  if not auth_methods:
125
- self.errors.append("Permissions are enabled but no authentication methods are configured. At least one authentication method is required.")
160
+ self.errors.append(
161
+ "Permissions are enabled but no authentication methods are configured. At least one authentication method is required."
162
+ )
126
163
  return False
127
-
164
+
128
165
  if security_enabled and auth_enabled:
129
166
  # Validate auth configuration
130
167
  auth_config = security_config.get("auth", {})
131
168
  if not auth_config.get("enabled", False):
132
169
  self.errors.append("Security is enabled but auth is disabled")
133
170
  return False
134
-
171
+
135
172
  # Validate API keys if auth is enabled
136
173
  if auth_config.get("enabled", False):
137
174
  api_keys = auth_config.get("api_keys", {})
138
175
  if not api_keys:
139
176
  self.errors.append("API keys are required when authentication is enabled")
140
177
  return False
141
-
178
+
142
179
  # Validate API key format
143
180
  for key, value in api_keys.items():
144
181
  if not key or not value:
145
182
  self.errors.append("API keys must have non-empty key and value")
146
183
  return False
147
-
184
+
148
185
  return len(self.errors) == 0
149
-
186
+
150
187
  def _validate_commands_config(self) -> bool:
151
188
  """Validate commands configuration."""
152
189
  commands_config = self.config.get("commands", {})
153
-
190
+
154
191
  # Validate commands directory if auto_discovery is enabled
155
192
  if commands_config.get("auto_discovery", True):
156
193
  commands_dir = commands_config.get("commands_directory", "./commands")
157
194
  if not os.path.exists(commands_dir):
158
195
  self.warnings.append(f"Commands directory does not exist: {commands_dir}")
159
-
196
+
160
197
  return True
161
-
198
+
162
199
  def _validate_ssl_config(self) -> bool:
163
200
  """Validate SSL configuration."""
164
201
  ssl_config = self.config.get("ssl", {})
165
202
  ssl_enabled = ssl_config.get("enabled", False)
166
-
203
+
167
204
  if ssl_enabled:
168
205
  # Validate certificate files
169
206
  cert_file = ssl_config.get("cert_file")
170
207
  key_file = ssl_config.get("key_file")
171
-
208
+
172
209
  if not cert_file or not key_file:
173
210
  self.errors.append("SSL certificate and key files are required when SSL is enabled")
174
211
  return False
175
-
212
+
176
213
  if not os.path.exists(cert_file):
177
214
  self.errors.append(f"SSL certificate file not found: {cert_file}")
178
-
215
+
179
216
  if not os.path.exists(key_file):
180
217
  self.errors.append(f"SSL private key file not found: {key_file}")
181
-
218
+
182
219
  return len(self.errors) == 0
183
-
220
+
184
221
  def _validate_roles_config(self) -> bool:
185
222
  """Validate roles configuration."""
186
223
  roles_config = self.config.get("roles", {})
187
224
  roles_enabled = roles_config.get("enabled", False)
188
-
225
+
189
226
  if roles_enabled:
190
227
  config_file = roles_config.get("config_file")
191
228
  if not config_file:
192
229
  self.errors.append("Roles config file is required when roles are enabled")
193
230
  return False
194
-
231
+
195
232
  if not os.path.exists(config_file):
196
233
  self.errors.append(f"Roles config file not found: {config_file}")
197
234
  return False
198
-
235
+
199
236
  # Validate roles schema file
200
237
  try:
201
- with open(config_file, 'r') as f:
238
+ with open(config_file, "r") as f:
202
239
  roles_schema = json.load(f)
203
-
240
+
204
241
  if "roles" not in roles_schema:
205
242
  self.errors.append("Roles config file must contain 'roles' section")
206
243
  return False
207
-
244
+
208
245
  except (json.JSONDecodeError, IOError) as e:
209
246
  self.errors.append(f"Failed to read roles config file: {e}")
210
247
  return False
211
-
248
+
212
249
  return len(self.errors) == 0
213
-
250
+
214
251
  def get_errors(self) -> List[str]:
215
252
  """Get validation errors."""
216
253
  return self.errors.copy()
217
-
254
+
218
255
  def get_warnings(self) -> List[str]:
219
256
  """Get validation warnings."""
220
257
  return self.warnings.copy()
221
-
258
+
222
259
  def print_validation_report(self):
223
260
  """Print validation report."""
224
261
  if self.errors:
225
262
  logger.error("Configuration validation failed:")
226
263
  for error in self.errors:
227
264
  logger.error(f" - {error}")
228
-
265
+
229
266
  if self.warnings:
230
267
  logger.warning("Configuration warnings:")
231
268
  for warning in self.warnings:
232
269
  logger.warning(f" - {warning}")
233
-
270
+
234
271
  if not self.errors and not self.warnings:
235
272
  logger.info("Configuration validation passed")