mcp-proxy-adapter 6.9.17__py3-none-any.whl → 6.9.18__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 (86) 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/version.py +1 -1
  81. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/METADATA +1 -1
  82. mcp_proxy_adapter-6.9.18.dist-info/RECORD +149 -0
  83. mcp_proxy_adapter-6.9.17.dist-info/RECORD +0 -144
  84. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/WHEEL +0 -0
  85. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/entry_points.txt +0 -0
  86. {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/top_level.txt +0 -0
@@ -16,7 +16,7 @@ from mcp_proxy_adapter.core.errors import (
16
16
  NotFoundError,
17
17
  ValidationError,
18
18
  )
19
- from mcp_proxy_adapter.core.logging import logger
19
+ from mcp_proxy_adapter.core.logging import get_global_logger
20
20
 
21
21
 
22
22
  T = TypeVar("T", bound=CommandResult)
@@ -131,7 +131,7 @@ class Command(ABC):
131
131
 
132
132
  # Log warning about invalid parameters
133
133
  if invalid_params:
134
- logger.warning(
134
+ get_global_logger().warning(
135
135
  f"Command {self.__class__.__name__} received invalid parameters: {invalid_params}. "
136
136
  f"Allowed parameters: {list(allowed_properties)}"
137
137
  )
@@ -168,7 +168,7 @@ class Command(ABC):
168
168
  context = kwargs.pop("context", {}) if "context" in kwargs else {}
169
169
 
170
170
  try:
171
- logger.debug(f"Running command {cls.__name__} with params: {kwargs}")
171
+ get_global_logger().debug(f"Running command {cls.__name__} with params: {kwargs}")
172
172
 
173
173
  # Import registry here to avoid circular imports
174
174
  from mcp_proxy_adapter.commands.command_registry import registry
@@ -197,31 +197,31 @@ class Command(ABC):
197
197
  # Execute command with validated parameters and context
198
198
  result = await command.execute(**validated_params, context=context)
199
199
 
200
- logger.debug(f"Command {cls.__name__} executed successfully")
200
+ get_global_logger().debug(f"Command {cls.__name__} executed successfully")
201
201
  return result
202
202
  except ValidationError as e:
203
203
  # Ошибка валидации параметров
204
- logger.error(f"Validation error in command {cls.__name__}: {e}")
204
+ get_global_logger().error(f"Validation error in command {cls.__name__}: {e}")
205
205
  return ErrorResult(message=str(e), code=e.code, details=e.data)
206
206
  except InvalidParamsError as e:
207
207
  # Ошибка в параметрах команды
208
- logger.error(f"Invalid parameters error in command {cls.__name__}: {e}")
208
+ get_global_logger().error(f"Invalid parameters error in command {cls.__name__}: {e}")
209
209
  return ErrorResult(message=str(e), code=e.code, details=e.data)
210
210
  except NotFoundError as e:
211
211
  # Ресурс не найден
212
- logger.error(f"Resource not found error in command {cls.__name__}: {e}")
212
+ get_global_logger().error(f"Resource not found error in command {cls.__name__}: {e}")
213
213
  return ErrorResult(message=str(e), code=e.code, details=e.data)
214
214
  except TimeoutError as e:
215
215
  # Превышено время ожидания
216
- logger.error(f"Timeout error in command {cls.__name__}: {e}")
216
+ get_global_logger().error(f"Timeout error in command {cls.__name__}: {e}")
217
217
  return ErrorResult(message=str(e), code=e.code, details=e.data)
218
218
  except CommandError as e:
219
219
  # Ошибка выполнения команды
220
- logger.error(f"Command error in {cls.__name__}: {e}")
220
+ get_global_logger().error(f"Command error in {cls.__name__}: {e}")
221
221
  return ErrorResult(message=str(e), code=e.code, details=e.data)
222
222
  except Exception as e:
223
223
  # Непредвиденная ошибка
224
- logger.exception(f"Unexpected error executing command {cls.__name__}: {e}")
224
+ get_global_logger().exception(f"Unexpected error executing command {cls.__name__}: {e}")
225
225
  internal_error = InternalError(f"Command execution error: {str(e)}")
226
226
  return ErrorResult(
227
227
  message=internal_error.message,
@@ -23,7 +23,7 @@ from mcp_proxy_adapter.commands.proxy_registration_command import (
23
23
  )
24
24
  from mcp_proxy_adapter.commands.echo_command import EchoCommand
25
25
  from mcp_proxy_adapter.commands.role_test_command import RoleTestCommand
26
- from mcp_proxy_adapter.core.logging import logger
26
+ from mcp_proxy_adapter.core.logging import get_global_logger
27
27
 
28
28
 
29
29
  def register_builtin_commands() -> int:
@@ -33,7 +33,7 @@ def register_builtin_commands() -> int:
33
33
  Returns:
34
34
  Number of built-in commands registered.
35
35
  """
36
- logger.debug("Registering built-in framework commands...")
36
+ get_global_logger().debug("Registering built-in framework commands...")
37
37
 
38
38
  builtin_commands = [
39
39
  HelpCommand,
@@ -63,7 +63,7 @@ def register_builtin_commands() -> int:
63
63
 
64
64
  # Check if command already exists (should not happen for built-in)
65
65
  if registry.command_exists(command_name):
66
- logger.warning(
66
+ get_global_logger().warning(
67
67
  f"Built-in command '{command_name}' already exists, skipping"
68
68
  )
69
69
  continue
@@ -71,14 +71,14 @@ def register_builtin_commands() -> int:
71
71
  # Register the command
72
72
  registry.register_builtin(command_class)
73
73
  registered_count += 1
74
- logger.debug(f"Registered built-in command: {command_name}")
74
+ get_global_logger().debug(f"Registered built-in command: {command_name}")
75
75
 
76
76
  except Exception as e:
77
- logger.error(
77
+ get_global_logger().error(
78
78
  f"Failed to register built-in command {command_class.__name__}: {e}"
79
79
  )
80
80
 
81
- logger.info(f"Registered {registered_count} built-in framework commands")
81
+ get_global_logger().info(f"Registered {registered_count} built-in framework commands")
82
82
  return registered_count
83
83
 
84
84
 
@@ -16,7 +16,7 @@ from pathlib import Path
16
16
  from typing import Dict, List, Optional, Any
17
17
  from packaging import version as pkg_version
18
18
 
19
- from mcp_proxy_adapter.core.logging import logger
19
+ from mcp_proxy_adapter.core.logging import get_global_logger
20
20
  from mcp_proxy_adapter.commands.dependency_manager import dependency_manager
21
21
  from mcp_proxy_adapter.config import config
22
22
 
@@ -27,7 +27,7 @@ try:
27
27
  REQUESTS_AVAILABLE = True
28
28
  except ImportError:
29
29
  REQUESTS_AVAILABLE = False
30
- logger.warning(
30
+ get_global_logger().warning(
31
31
  "requests library not available, HTTP/HTTPS functionality will be limited"
32
32
  )
33
33
 
@@ -128,13 +128,13 @@ class CatalogManager:
128
128
 
129
129
  def _load_catalog(self) -> None:
130
130
  """DEPRECATED: Catalog is not cached locally."""
131
- logger.warning(
131
+ get_global_logger().warning(
132
132
  "_load_catalog() is deprecated - catalog is always fetched fresh from servers"
133
133
  )
134
134
 
135
135
  def _save_catalog(self) -> None:
136
136
  """DEPRECATED: Catalog is not cached locally."""
137
- logger.warning(
137
+ get_global_logger().warning(
138
138
  "_save_catalog() is deprecated - catalog is always fetched fresh from servers"
139
139
  )
140
140
 
@@ -152,7 +152,7 @@ class CatalogManager:
152
152
  Dictionary of parsed CommandCatalog objects
153
153
  """
154
154
  if not isinstance(server_catalog, dict):
155
- logger.error(
155
+ get_global_logger().error(
156
156
  f"Invalid catalog format: expected dict, got {type(server_catalog)}"
157
157
  )
158
158
  return {}
@@ -165,7 +165,7 @@ class CatalogManager:
165
165
  commands_data = server_catalog.get("commands", [])
166
166
 
167
167
  if not isinstance(commands_data, list):
168
- logger.error(
168
+ get_global_logger().error(
169
169
  f"Invalid commands format: expected list, got {type(commands_data)}"
170
170
  )
171
171
  return {}
@@ -173,24 +173,24 @@ class CatalogManager:
173
173
  for cmd_data in commands_data:
174
174
  try:
175
175
  if not isinstance(cmd_data, dict):
176
- logger.warning(
176
+ get_global_logger().warning(
177
177
  f"Skipping invalid command data: expected dict, got {type(cmd_data)}"
178
178
  )
179
179
  continue
180
180
 
181
181
  name = cmd_data.get("name")
182
182
  if not name or not isinstance(name, str):
183
- logger.warning(f"Skipping command without valid name")
183
+ get_global_logger().warning(f"Skipping command without valid name")
184
184
  continue
185
185
 
186
186
  version = cmd_data.get("version", "0.1")
187
187
  if not isinstance(version, str):
188
- logger.warning(f"Invalid version format for {name}: {version}")
188
+ get_global_logger().warning(f"Invalid version format for {name}: {version}")
189
189
  version = "0.1"
190
190
 
191
191
  source_url = cmd_data.get("source_url", "")
192
192
  if not isinstance(source_url, str):
193
- logger.warning(f"Invalid source_url for {name}: {source_url}")
193
+ get_global_logger().warning(f"Invalid source_url for {name}: {source_url}")
194
194
  source_url = ""
195
195
 
196
196
  catalog = CommandCatalog(
@@ -208,14 +208,14 @@ class CatalogManager:
208
208
  result[name] = catalog
209
209
 
210
210
  except Exception as e:
211
- logger.error(f"Error processing command data: {e}")
211
+ get_global_logger().error(f"Error processing command data: {e}")
212
212
  continue
213
213
  else:
214
214
  # New format: {"id": {"plugin": "...", "descr": "...", ...}}
215
215
  for command_id, cmd_data in server_catalog.items():
216
216
  try:
217
217
  if not isinstance(cmd_data, dict):
218
- logger.warning(
218
+ get_global_logger().warning(
219
219
  f"Skipping invalid command data for {command_id}: expected dict, got {type(cmd_data)}"
220
220
  )
221
221
  continue
@@ -223,14 +223,14 @@ class CatalogManager:
223
223
  # Use command_id as name if name is not provided
224
224
  name = cmd_data.get("name", command_id)
225
225
  if not isinstance(name, str):
226
- logger.warning(
226
+ get_global_logger().warning(
227
227
  f"Skipping command {command_id} without valid name"
228
228
  )
229
229
  continue
230
230
 
231
231
  version = cmd_data.get("version", "0.1")
232
232
  if not isinstance(version, str):
233
- logger.warning(f"Invalid version format for {name}: {version}")
233
+ get_global_logger().warning(f"Invalid version format for {name}: {version}")
234
234
  version = "0.1"
235
235
 
236
236
  # For new format, construct source_url from server_url and plugin filename
@@ -269,7 +269,7 @@ class CatalogManager:
269
269
  result[name] = catalog
270
270
 
271
271
  except Exception as e:
272
- logger.error(f"Error processing command {command_id}: {e}")
272
+ get_global_logger().error(f"Error processing command {command_id}: {e}")
273
273
  continue
274
274
 
275
275
  return result
@@ -285,7 +285,7 @@ class CatalogManager:
285
285
  Dictionary of commands available on the server
286
286
  """
287
287
  if not REQUESTS_AVAILABLE:
288
- logger.error(
288
+ get_global_logger().error(
289
289
  "requests library not available, cannot fetch catalog from remote server"
290
290
  )
291
291
  return {}
@@ -293,55 +293,55 @@ class CatalogManager:
293
293
  try:
294
294
  # Validate URL format
295
295
  if not server_url.startswith(("http://", "https://")):
296
- logger.error(f"Invalid server URL format: {server_url}")
296
+ get_global_logger().error(f"Invalid server URL format: {server_url}")
297
297
  return {}
298
298
 
299
299
  # Fetch catalog from server (use URL as-is)
300
- logger.debug(f"Fetching catalog from: {server_url}")
300
+ get_global_logger().debug(f"Fetching catalog from: {server_url}")
301
301
 
302
302
  response = requests.get(server_url, timeout=30)
303
303
  response.raise_for_status()
304
304
 
305
305
  # Validate response content
306
306
  if not response.content:
307
- logger.error(f"Empty response from {server_url}")
307
+ get_global_logger().error(f"Empty response from {server_url}")
308
308
  return {}
309
309
 
310
310
  try:
311
311
  server_catalog = response.json()
312
312
  except json.JSONDecodeError as e:
313
- logger.error(f"Invalid JSON response from {server_url}: {e}")
313
+ get_global_logger().error(f"Invalid JSON response from {server_url}: {e}")
314
314
  return {}
315
315
 
316
316
  if not isinstance(server_catalog, dict):
317
- logger.error(
317
+ get_global_logger().error(
318
318
  f"Invalid catalog format from {server_url}: expected dict, got {type(server_catalog)}"
319
319
  )
320
320
  return {}
321
321
 
322
322
  result = self._parse_catalog_data(server_catalog, server_url)
323
323
 
324
- logger.info(
324
+ get_global_logger().info(
325
325
  f"Successfully fetched catalog from {server_url}: {len(result)} commands"
326
326
  )
327
327
  return result
328
328
 
329
329
  except requests.exceptions.Timeout:
330
- logger.error(f"Timeout while fetching catalog from {server_url}")
330
+ get_global_logger().error(f"Timeout while fetching catalog from {server_url}")
331
331
  return {}
332
332
  except requests.exceptions.ConnectionError as e:
333
- logger.error(
333
+ get_global_logger().error(
334
334
  f"Connection error while fetching catalog from {server_url}: {e}"
335
335
  )
336
336
  return {}
337
337
  except requests.exceptions.HTTPError as e:
338
- logger.error(f"HTTP error while fetching catalog from {server_url}: {e}")
338
+ get_global_logger().error(f"HTTP error while fetching catalog from {server_url}: {e}")
339
339
  return {}
340
340
  except requests.exceptions.RequestException as e:
341
- logger.error(f"Request error while fetching catalog from {server_url}: {e}")
341
+ get_global_logger().error(f"Request error while fetching catalog from {server_url}: {e}")
342
342
  return {}
343
343
  except Exception as e:
344
- logger.error(
344
+ get_global_logger().error(
345
345
  f"Unexpected error while fetching catalog from {server_url}: {e}"
346
346
  )
347
347
  return {}
@@ -367,13 +367,13 @@ class CatalogManager:
367
367
  )
368
368
 
369
369
  if not all_satisfied:
370
- logger.warning(
370
+ get_global_logger().warning(
371
371
  f"Command {command_name} has missing dependencies: {missing_deps}"
372
372
  )
373
- logger.info(f"Installed dependencies: {installed_deps}")
373
+ get_global_logger().info(f"Installed dependencies: {installed_deps}")
374
374
  return False
375
375
 
376
- logger.debug(
376
+ get_global_logger().debug(
377
377
  f"All dependencies satisfied for command {command_name}: {server_cmd.depends}"
378
378
  )
379
379
  return True
@@ -405,22 +405,22 @@ class CatalogManager:
405
405
  )
406
406
 
407
407
  if all_satisfied:
408
- logger.info(
408
+ get_global_logger().info(
409
409
  f"All dependencies already satisfied for {command_name}: {server_cmd.depends}"
410
410
  )
411
411
  return True
412
412
 
413
413
  if not auto_install:
414
- logger.warning(
414
+ get_global_logger().warning(
415
415
  f"Command {command_name} has missing dependencies: {missing_deps}"
416
416
  )
417
- logger.info(
417
+ get_global_logger().info(
418
418
  f"Auto-install is disabled. Please install manually: pip install {' '.join(missing_deps)}"
419
419
  )
420
420
  return False
421
421
 
422
422
  # Try to install missing dependencies
423
- logger.info(
423
+ get_global_logger().info(
424
424
  f"Installing missing dependencies for {command_name}: {missing_deps}"
425
425
  )
426
426
 
@@ -429,7 +429,7 @@ class CatalogManager:
429
429
  )
430
430
 
431
431
  if success:
432
- logger.info(
432
+ get_global_logger().info(
433
433
  f"Successfully installed all dependencies for {command_name}: {installed_deps}"
434
434
  )
435
435
 
@@ -438,18 +438,18 @@ class CatalogManager:
438
438
  server_cmd.depends
439
439
  )
440
440
  if all_verified:
441
- logger.info(f"All dependencies verified for {command_name}")
441
+ get_global_logger().info(f"All dependencies verified for {command_name}")
442
442
  return True
443
443
  else:
444
- logger.error(
444
+ get_global_logger().error(
445
445
  f"Failed to verify dependencies for {command_name}: {failed_verifications}"
446
446
  )
447
447
  return False
448
448
  else:
449
- logger.error(
449
+ get_global_logger().error(
450
450
  f"Failed to install dependencies for {command_name}: {failed_deps}"
451
451
  )
452
- logger.error(
452
+ get_global_logger().error(
453
453
  f"Please install manually: pip install {' '.join(failed_deps)}"
454
454
  )
455
455
  return False
@@ -471,7 +471,7 @@ class CatalogManager:
471
471
 
472
472
  # If local file doesn't exist, download
473
473
  if not local_file.exists():
474
- logger.info(f"New command found: {command_name} v{server_cmd.version}")
474
+ get_global_logger().info(f"New command found: {command_name} v{server_cmd.version}")
475
475
  return True
476
476
 
477
477
  # Try to extract version from local file
@@ -484,18 +484,18 @@ class CatalogManager:
484
484
  local_ver = pkg_version.parse(local_version)
485
485
 
486
486
  if server_ver > local_ver:
487
- logger.info(
487
+ get_global_logger().info(
488
488
  f"Newer version available for {command_name}: {local_ver} -> {server_ver}"
489
489
  )
490
490
  return True
491
491
  else:
492
- logger.debug(
492
+ get_global_logger().debug(
493
493
  f"Local version {local_ver} is same or newer than server version {server_ver}"
494
494
  )
495
495
  return False
496
496
 
497
497
  except Exception as e:
498
- logger.warning(f"Failed to compare versions for {command_name}: {e}")
498
+ get_global_logger().warning(f"Failed to compare versions for {command_name}: {e}")
499
499
  # If version comparison fails, download anyway
500
500
  return True
501
501
 
@@ -512,7 +512,7 @@ class CatalogManager:
512
512
  Returns:
513
513
  True if command was downloaded, False otherwise
514
514
  """
515
- logger.warning(
515
+ get_global_logger().warning(
516
516
  "update_command() is deprecated - always downloading fresh from server (use _download_command directly)"
517
517
  )
518
518
 
@@ -534,14 +534,14 @@ class CatalogManager:
534
534
  True if download successful, False otherwise
535
535
  """
536
536
  if not REQUESTS_AVAILABLE:
537
- logger.error(
537
+ get_global_logger().error(
538
538
  "requests library not available, cannot download command from remote server"
539
539
  )
540
540
  return False
541
541
 
542
542
  # Step 1: Check and install dependencies
543
543
  if not self._install_dependencies(command_name, server_cmd):
544
- logger.error(
544
+ get_global_logger().error(
545
545
  f"Cannot download {command_name}: failed to install dependencies"
546
546
  )
547
547
  return False
@@ -549,20 +549,20 @@ class CatalogManager:
549
549
  try:
550
550
  # Validate source URL
551
551
  if not server_cmd.source_url.startswith(("http://", "https://")):
552
- logger.error(
552
+ get_global_logger().error(
553
553
  f"Invalid source URL for {command_name}: {server_cmd.source_url}"
554
554
  )
555
555
  return False
556
556
 
557
557
  # Download command file (use source_url as-is)
558
- logger.debug(f"Downloading {command_name} from: {server_cmd.source_url}")
558
+ get_global_logger().debug(f"Downloading {command_name} from: {server_cmd.source_url}")
559
559
 
560
560
  response = requests.get(server_cmd.source_url, timeout=30)
561
561
  response.raise_for_status()
562
562
 
563
563
  # Validate response content
564
564
  if not response.content:
565
- logger.error(
565
+ get_global_logger().error(
566
566
  f"Empty response when downloading {command_name} from {server_cmd.source_url}"
567
567
  )
568
568
  return False
@@ -570,7 +570,7 @@ class CatalogManager:
570
570
  # Validate Python file content
571
571
  content = response.text
572
572
  if not content.strip():
573
- logger.error(
573
+ get_global_logger().error(
574
574
  f"Empty file content for {command_name} from {server_cmd.source_url}"
575
575
  )
576
576
  return False
@@ -587,7 +587,7 @@ class CatalogManager:
587
587
  for keyword in ["class", "def", "import", "from", '"""', "'''", "#"]
588
588
  )
589
589
  ):
590
- logger.warning(
590
+ get_global_logger().warning(
591
591
  f"File {command_name}_command.py doesn't look like a valid Python file"
592
592
  )
593
593
 
@@ -616,12 +616,12 @@ class CatalogManager:
616
616
  hasattr(module, attr) and attr.endswith("Command")
617
617
  for attr in dir(module)
618
618
  ):
619
- logger.warning(
619
+ get_global_logger().warning(
620
620
  f"Module {command_name}_command.py doesn't contain a Command class"
621
621
  )
622
622
 
623
623
  except Exception as e:
624
- logger.error(f"Failed to validate {command_name}_command.py: {e}")
624
+ get_global_logger().error(f"Failed to validate {command_name}_command.py: {e}")
625
625
  return False
626
626
 
627
627
  # If validation passed, move to final location
@@ -659,15 +659,15 @@ class CatalogManager:
659
659
  # Update full metadata
660
660
  server_cmd.metadata.update(metadata)
661
661
 
662
- logger.debug(
662
+ get_global_logger().debug(
663
663
  f"Extracted metadata for {command_name}: {metadata}"
664
664
  )
665
665
  except Exception as e:
666
- logger.warning(
666
+ get_global_logger().warning(
667
667
  f"Failed to extract metadata from {command_name}: {e}"
668
668
  )
669
669
 
670
- logger.info(
670
+ get_global_logger().info(
671
671
  f"Successfully downloaded and validated {command_name} v{server_cmd.version}"
672
672
  )
673
673
  return True
@@ -678,35 +678,35 @@ class CatalogManager:
678
678
  try:
679
679
  os.unlink(temp_file.name)
680
680
  except Exception as e:
681
- logger.warning(
681
+ get_global_logger().warning(
682
682
  f"Failed to clean up temporary file {temp_file.name}: {e}"
683
683
  )
684
684
 
685
685
  except requests.exceptions.Timeout:
686
- logger.error(
686
+ get_global_logger().error(
687
687
  f"Timeout while downloading {command_name} from {server_cmd.source_url}"
688
688
  )
689
689
  return False
690
690
  except requests.exceptions.ConnectionError as e:
691
- logger.error(
691
+ get_global_logger().error(
692
692
  f"Connection error while downloading {command_name} from {server_cmd.source_url}: {e}"
693
693
  )
694
694
  return False
695
695
  except requests.exceptions.HTTPError as e:
696
- logger.error(
696
+ get_global_logger().error(
697
697
  f"HTTP error while downloading {command_name} from {server_cmd.source_url}: {e}"
698
698
  )
699
699
  return False
700
700
  except requests.exceptions.RequestException as e:
701
- logger.error(
701
+ get_global_logger().error(
702
702
  f"Request error while downloading {command_name} from {server_cmd.source_url}: {e}"
703
703
  )
704
704
  return False
705
705
  except OSError as e:
706
- logger.error(f"File system error while downloading {command_name}: {e}")
706
+ get_global_logger().error(f"File system error while downloading {command_name}: {e}")
707
707
  return False
708
708
  except Exception as e:
709
- logger.error(f"Unexpected error while downloading {command_name}: {e}")
709
+ get_global_logger().error(f"Unexpected error while downloading {command_name}: {e}")
710
710
  return False
711
711
 
712
712
  def sync_with_servers(self, server_urls: List[str]) -> Dict[str, Any]:
@@ -719,7 +719,7 @@ class CatalogManager:
719
719
  Returns:
720
720
  Dictionary with sync results
721
721
  """
722
- logger.info(f"Loading fresh catalog from {len(server_urls)} servers")
722
+ get_global_logger().info(f"Loading fresh catalog from {len(server_urls)} servers")
723
723
 
724
724
  # Clear local catalog - always start fresh
725
725
  self.catalog = {}
@@ -750,16 +750,16 @@ class CatalogManager:
750
750
  self.catalog[command_name] = server_cmd
751
751
  else:
752
752
  # Command already exists with same or newer version
753
- logger.debug(
753
+ get_global_logger().debug(
754
754
  f"Command {command_name} already exists with same or newer version"
755
755
  )
756
756
 
757
757
  except Exception as e:
758
758
  error_msg = f"Failed to sync with {server_url}: {e}"
759
759
  results["errors"].append(error_msg)
760
- logger.error(error_msg)
760
+ get_global_logger().error(error_msg)
761
761
 
762
- logger.info(f"Fresh catalog loaded: {results}")
762
+ get_global_logger().info(f"Fresh catalog loaded: {results}")
763
763
  return results
764
764
 
765
765
  def get_local_commands(self) -> List[str]:
@@ -773,7 +773,7 @@ class CatalogManager:
773
773
  for file_path in self.commands_dir.glob("*_command.py"):
774
774
  commands.append(str(file_path))
775
775
 
776
- logger.debug(
776
+ get_global_logger().debug(
777
777
  f"Found {len(commands)} local command files: {[Path(c).name for c in commands]}"
778
778
  )
779
779
  return commands
@@ -813,11 +813,11 @@ class CatalogManager:
813
813
  del self.catalog[command_name]
814
814
  self._save_catalog()
815
815
 
816
- logger.info(f"Removed command: {command_name}")
816
+ get_global_logger().info(f"Removed command: {command_name}")
817
817
  return True
818
818
 
819
819
  except Exception as e:
820
- logger.error(f"Failed to remove command {command_name}: {e}")
820
+ get_global_logger().error(f"Failed to remove command {command_name}: {e}")
821
821
  return False
822
822
 
823
823
  def extract_metadata_from_file(self, file_path: str) -> Dict[str, Any]:
@@ -909,11 +909,11 @@ class CatalogManager:
909
909
  except json.JSONDecodeError:
910
910
  continue
911
911
 
912
- logger.debug(f"Extracted metadata from {file_path}: {metadata}")
912
+ get_global_logger().debug(f"Extracted metadata from {file_path}: {metadata}")
913
913
  return metadata
914
914
 
915
915
  except Exception as e:
916
- logger.error(f"Failed to extract metadata from {file_path}: {e}")
916
+ get_global_logger().error(f"Failed to extract metadata from {file_path}: {e}")
917
917
  return {}
918
918
 
919
919
  def update_local_command_metadata(self, command_name: str) -> bool:
@@ -957,11 +957,11 @@ class CatalogManager:
957
957
  # Save catalog
958
958
  self._save_catalog()
959
959
 
960
- logger.info(f"Updated metadata for {command_name}")
960
+ get_global_logger().info(f"Updated metadata for {command_name}")
961
961
  return True
962
962
 
963
963
  return False
964
964
 
965
965
  except Exception as e:
966
- logger.error(f"Failed to update metadata for {command_name}: {e}")
966
+ get_global_logger().error(f"Failed to update metadata for {command_name}: {e}")
967
967
  return False