mcp-proxy-adapter 6.9.28__py3-none-any.whl → 6.9.29__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.

Potentially problematic release.


This version of mcp-proxy-adapter might be problematic. Click here for more details.

Files changed (212) hide show
  1. mcp_proxy_adapter/__init__.py +10 -0
  2. mcp_proxy_adapter/__main__.py +8 -21
  3. mcp_proxy_adapter/api/app.py +10 -913
  4. mcp_proxy_adapter/api/core/__init__.py +18 -0
  5. mcp_proxy_adapter/api/core/app_factory.py +243 -0
  6. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  7. mcp_proxy_adapter/api/core/registration_manager.py +166 -0
  8. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  9. mcp_proxy_adapter/api/handlers.py +78 -199
  10. mcp_proxy_adapter/api/middleware/__init__.py +1 -44
  11. mcp_proxy_adapter/api/middleware/base.py +0 -42
  12. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +0 -85
  13. mcp_proxy_adapter/api/middleware/error_handling.py +1 -127
  14. mcp_proxy_adapter/api/middleware/factory.py +0 -94
  15. mcp_proxy_adapter/api/middleware/logging.py +0 -112
  16. mcp_proxy_adapter/api/middleware/performance.py +0 -35
  17. mcp_proxy_adapter/api/middleware/protocol_middleware.py +2 -98
  18. mcp_proxy_adapter/api/middleware/transport_middleware.py +0 -37
  19. mcp_proxy_adapter/api/middleware/unified_security.py +10 -10
  20. mcp_proxy_adapter/api/middleware/user_info_middleware.py +0 -118
  21. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  22. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  23. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  24. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  25. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  26. mcp_proxy_adapter/api/schemas.py +0 -61
  27. mcp_proxy_adapter/api/tool_integration.py +0 -117
  28. mcp_proxy_adapter/api/tools.py +0 -46
  29. mcp_proxy_adapter/cli/__init__.py +12 -0
  30. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  31. mcp_proxy_adapter/cli/commands/client.py +100 -0
  32. mcp_proxy_adapter/cli/commands/config_generate.py +21 -0
  33. mcp_proxy_adapter/cli/commands/config_validate.py +36 -0
  34. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  35. mcp_proxy_adapter/cli/commands/server.py +174 -0
  36. mcp_proxy_adapter/cli/commands/sets.py +128 -0
  37. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  38. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  39. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  40. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  41. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  42. mcp_proxy_adapter/cli/main.py +63 -0
  43. mcp_proxy_adapter/cli/parser.py +324 -0
  44. mcp_proxy_adapter/cli/validators.py +231 -0
  45. mcp_proxy_adapter/client/jsonrpc_client.py +406 -0
  46. mcp_proxy_adapter/client/proxy.py +45 -0
  47. mcp_proxy_adapter/commands/__init__.py +44 -28
  48. mcp_proxy_adapter/commands/auth_validation_command.py +7 -344
  49. mcp_proxy_adapter/commands/base.py +19 -43
  50. mcp_proxy_adapter/commands/builtin_commands.py +0 -75
  51. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  52. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  53. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  54. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  55. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  56. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  57. mcp_proxy_adapter/commands/catalog_manager.py +58 -928
  58. mcp_proxy_adapter/commands/cert_monitor_command.py +0 -88
  59. mcp_proxy_adapter/commands/certificate_management_command.py +0 -45
  60. mcp_proxy_adapter/commands/command_registry.py +172 -904
  61. mcp_proxy_adapter/commands/config_command.py +0 -28
  62. mcp_proxy_adapter/commands/dependency_container.py +1 -70
  63. mcp_proxy_adapter/commands/dependency_manager.py +0 -128
  64. mcp_proxy_adapter/commands/echo_command.py +0 -34
  65. mcp_proxy_adapter/commands/health_command.py +0 -3
  66. mcp_proxy_adapter/commands/help_command.py +0 -159
  67. mcp_proxy_adapter/commands/hooks.py +0 -137
  68. mcp_proxy_adapter/commands/key_management_command.py +0 -25
  69. mcp_proxy_adapter/commands/load_command.py +7 -78
  70. mcp_proxy_adapter/commands/plugins_command.py +0 -16
  71. mcp_proxy_adapter/commands/protocol_management_command.py +0 -28
  72. mcp_proxy_adapter/commands/proxy_registration_command.py +0 -88
  73. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  74. mcp_proxy_adapter/commands/registration_status_command.py +0 -43
  75. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  76. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  77. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  78. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  79. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  80. mcp_proxy_adapter/commands/reload_command.py +0 -80
  81. mcp_proxy_adapter/commands/result.py +25 -77
  82. mcp_proxy_adapter/commands/role_test_command.py +0 -44
  83. mcp_proxy_adapter/commands/roles_management_command.py +0 -199
  84. mcp_proxy_adapter/commands/security_command.py +0 -30
  85. mcp_proxy_adapter/commands/settings_command.py +0 -68
  86. mcp_proxy_adapter/commands/ssl_setup_command.py +0 -42
  87. mcp_proxy_adapter/commands/token_management_command.py +0 -1
  88. mcp_proxy_adapter/commands/transport_management_command.py +0 -20
  89. mcp_proxy_adapter/commands/unload_command.py +0 -71
  90. mcp_proxy_adapter/config.py +15 -626
  91. mcp_proxy_adapter/core/__init__.py +5 -39
  92. mcp_proxy_adapter/core/app_factory.py +14 -36
  93. mcp_proxy_adapter/core/app_runner.py +0 -27
  94. mcp_proxy_adapter/core/auth_validator.py +1 -93
  95. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  96. mcp_proxy_adapter/core/certificate/certificate_creator.py +371 -0
  97. mcp_proxy_adapter/core/certificate/certificate_extractor.py +183 -0
  98. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  99. mcp_proxy_adapter/core/certificate/certificate_validator.py +110 -0
  100. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +70 -0
  101. mcp_proxy_adapter/core/certificate_utils.py +64 -903
  102. mcp_proxy_adapter/core/client.py +0 -6
  103. mcp_proxy_adapter/core/client_manager.py +0 -19
  104. mcp_proxy_adapter/core/client_security.py +0 -2
  105. mcp_proxy_adapter/core/config/__init__.py +18 -0
  106. mcp_proxy_adapter/core/config/config.py +195 -0
  107. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  108. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  109. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  110. mcp_proxy_adapter/core/config/simple_config.py +112 -0
  111. mcp_proxy_adapter/core/config/simple_config_generator.py +50 -0
  112. mcp_proxy_adapter/core/config/simple_config_validator.py +96 -0
  113. mcp_proxy_adapter/core/config_converter.py +0 -186
  114. mcp_proxy_adapter/core/config_validator.py +96 -1238
  115. mcp_proxy_adapter/core/errors.py +7 -42
  116. mcp_proxy_adapter/core/job_manager.py +54 -0
  117. mcp_proxy_adapter/core/logging.py +2 -22
  118. mcp_proxy_adapter/core/mtls_asgi.py +0 -20
  119. mcp_proxy_adapter/core/mtls_asgi_app.py +0 -12
  120. mcp_proxy_adapter/core/mtls_proxy.py +0 -80
  121. mcp_proxy_adapter/core/mtls_server.py +3 -173
  122. mcp_proxy_adapter/core/protocol_manager.py +1 -191
  123. mcp_proxy_adapter/core/proxy/__init__.py +22 -0
  124. mcp_proxy_adapter/core/proxy/auth_manager.py +27 -0
  125. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +137 -0
  126. mcp_proxy_adapter/core/proxy/registration_client.py +60 -0
  127. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  128. mcp_proxy_adapter/core/proxy_client.py +0 -1
  129. mcp_proxy_adapter/core/proxy_registration.py +36 -913
  130. mcp_proxy_adapter/core/role_utils.py +0 -308
  131. mcp_proxy_adapter/core/security_adapter.py +1 -36
  132. mcp_proxy_adapter/core/security_factory.py +1 -150
  133. mcp_proxy_adapter/core/security_integration.py +0 -33
  134. mcp_proxy_adapter/core/server_adapter.py +1 -40
  135. mcp_proxy_adapter/core/server_engine.py +2 -173
  136. mcp_proxy_adapter/core/settings.py +0 -127
  137. mcp_proxy_adapter/core/signal_handler.py +0 -65
  138. mcp_proxy_adapter/core/ssl_utils.py +19 -137
  139. mcp_proxy_adapter/core/transport_manager.py +0 -151
  140. mcp_proxy_adapter/core/unified_config_adapter.py +1 -193
  141. mcp_proxy_adapter/core/utils.py +1 -182
  142. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  143. mcp_proxy_adapter/core/validation/config_validator.py +211 -0
  144. mcp_proxy_adapter/core/validation/file_validator.py +73 -0
  145. mcp_proxy_adapter/core/validation/protocol_validator.py +191 -0
  146. mcp_proxy_adapter/core/validation/security_validator.py +58 -0
  147. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  148. mcp_proxy_adapter/custom_openapi.py +33 -652
  149. mcp_proxy_adapter/examples/bugfix_certificate_config.py +0 -23
  150. mcp_proxy_adapter/examples/check_config.py +0 -2
  151. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  152. mcp_proxy_adapter/examples/config_builder.py +13 -2
  153. mcp_proxy_adapter/examples/config_cli.py +0 -1
  154. mcp_proxy_adapter/examples/create_test_configs.py +0 -46
  155. mcp_proxy_adapter/examples/debug_request_state.py +0 -1
  156. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +0 -47
  157. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +0 -45
  158. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +0 -12
  159. mcp_proxy_adapter/examples/full_application/commands/help_command.py +0 -12
  160. mcp_proxy_adapter/examples/full_application/commands/list_command.py +0 -7
  161. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +0 -2
  162. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +0 -59
  163. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +0 -54
  164. mcp_proxy_adapter/examples/full_application/main.py +186 -150
  165. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +0 -107
  166. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +0 -24
  167. mcp_proxy_adapter/examples/full_application/test_server.py +0 -58
  168. mcp_proxy_adapter/examples/generate_config.py +65 -11
  169. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  170. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  171. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  172. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  173. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  174. mcp_proxy_adapter/examples/required_certificates.py +0 -2
  175. mcp_proxy_adapter/examples/run_full_test_suite.py +0 -29
  176. mcp_proxy_adapter/examples/run_proxy_server.py +31 -71
  177. mcp_proxy_adapter/examples/run_security_tests_fixed.py +0 -27
  178. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  179. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  180. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  181. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  182. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  183. mcp_proxy_adapter/examples/security_test_client.py +24 -1075
  184. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  185. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  186. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  187. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  188. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  189. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  190. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  191. mcp_proxy_adapter/examples/setup_test_environment.py +133 -1425
  192. mcp_proxy_adapter/examples/test_config.py +0 -3
  193. mcp_proxy_adapter/examples/test_config_builder.py +25 -405
  194. mcp_proxy_adapter/examples/test_examples.py +0 -1
  195. mcp_proxy_adapter/examples/test_framework_complete.py +0 -2
  196. mcp_proxy_adapter/examples/test_mcp_server.py +0 -1
  197. mcp_proxy_adapter/examples/test_protocol_examples.py +0 -1
  198. mcp_proxy_adapter/examples/universal_client.py +0 -6
  199. mcp_proxy_adapter/examples/update_config_certificates.py +0 -1
  200. mcp_proxy_adapter/examples/validate_generator_compatibility.py +0 -1
  201. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +0 -187
  202. mcp_proxy_adapter/integrations/__init__.py +25 -0
  203. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  204. mcp_proxy_adapter/main.py +70 -62
  205. mcp_proxy_adapter/openapi.py +0 -22
  206. mcp_proxy_adapter/version.py +1 -1
  207. {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.29.dist-info}/METADATA +2 -1
  208. mcp_proxy_adapter-6.9.29.dist-info/RECORD +235 -0
  209. {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.29.dist-info}/entry_points.txt +1 -1
  210. mcp_proxy_adapter-6.9.28.dist-info/RECORD +0 -149
  211. {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.29.dist-info}/WHEEL +0 -0
  212. {mcp_proxy_adapter-6.9.28.dist-info → mcp_proxy_adapter-6.9.29.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,122 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Main catalog manager for MCP Proxy Adapter.
6
+ """
7
+
8
+ import json
9
+ from pathlib import Path
10
+ from typing import Dict, List, Optional, Any
11
+ from packaging import version as pkg_version
12
+
13
+ from mcp_proxy_adapter.core.logging import get_global_logger
14
+ from mcp_proxy_adapter.commands.dependency_manager import dependency_manager
15
+ from mcp_proxy_adapter.config import config
16
+ from .command_catalog import CommandCatalog
17
+ from .catalog_loader import CatalogLoader
18
+ from .catalog_syncer import CatalogSyncer
19
+ from .dependency_manager import DependencyManager
20
+
21
+ # Try to import requests, but don't fail if not available
22
+ try:
23
+ import requests
24
+ REQUESTS_AVAILABLE = True
25
+ except ImportError:
26
+ REQUESTS_AVAILABLE = False
27
+ get_global_logger().warning(
28
+ "requests library not available, HTTP/HTTPS functionality will be limited"
29
+ )
30
+
31
+
32
+ class CatalogManager:
33
+ """
34
+ Manager for command catalog operations.
35
+
36
+ Handles loading, syncing, and managing command catalogs from various sources.
37
+ """
38
+
39
+ def __init__(self, catalog_dir: str):
40
+ """
41
+ Initialize catalog manager.
42
+
43
+ Args:
44
+ catalog_dir: Directory for catalog storage
45
+ """
46
+ self.catalog_dir = Path(catalog_dir)
47
+ self.logger = get_global_logger()
48
+
49
+ # Initialize components
50
+ self.loader = CatalogLoader()
51
+ self.syncer = CatalogSyncer(catalog_dir)
52
+ self.dependency_manager = DependencyManager()
53
+
54
+ # Load existing catalog
55
+ self.catalog: Dict[str, CommandCatalog] = {}
56
+ self._load_catalog()
57
+
58
+ def _load_catalog(self) -> None:
59
+ """Load catalog from local storage."""
60
+ catalog_file = self.catalog_dir / "catalog.json"
61
+ self.catalog = self.loader.load_catalog_from_file(catalog_file)
62
+
63
+ def _save_catalog(self) -> None:
64
+ """Save catalog to local storage."""
65
+ catalog_file = self.catalog_dir / "catalog.json"
66
+ self.loader.save_catalog_to_file(self.catalog, catalog_file)
67
+
68
+
69
+ def sync_with_servers(self, server_urls: List[str]) -> Dict[str, Any]:
70
+ """
71
+ Synchronize catalog with remote servers.
72
+
73
+ Args:
74
+ server_urls: List of server URLs to sync with
75
+
76
+ Returns:
77
+ Dictionary with sync results
78
+ """
79
+ return self.syncer.sync_with_servers(server_urls)
80
+
81
+
82
+
83
+
84
+
85
+ def _extract_metadata_from_file(self, file_path: str) -> Dict[str, Any]:
86
+ """
87
+ Extract metadata from command file.
88
+
89
+ Args:
90
+ file_path: Path to command file
91
+
92
+ Returns:
93
+ Dictionary of extracted metadata
94
+ """
95
+ metadata = {}
96
+
97
+ try:
98
+ with open(file_path, 'r', encoding='utf-8') as f:
99
+ content = f.read()
100
+
101
+ # Extract basic metadata
102
+ for line in content.split('\n'):
103
+ line = line.strip()
104
+ if line.startswith('__version__'):
105
+ metadata['version'] = line.split('=')[1].strip().strip('"\'')
106
+ elif line.startswith('__author__'):
107
+ metadata['author'] = line.split('=')[1].strip().strip('"\'')
108
+ elif line.startswith('__description__'):
109
+ metadata['description'] = line.split('=')[1].strip().strip('"\'')
110
+ elif line.startswith('__category__'):
111
+ metadata['category'] = line.split('=')[1].strip().strip('"\'')
112
+ elif line.startswith('__email__'):
113
+ metadata['email'] = line.split('=')[1].strip().strip('"\'')
114
+ elif line.startswith('__depends__'):
115
+ deps_str = line.split('=')[1].strip().strip('[]"\'')
116
+ if deps_str:
117
+ metadata['depends'] = [dep.strip().strip('"\'') for dep in deps_str.split(',')]
118
+
119
+ except Exception as e:
120
+ self.logger.error(f"Failed to extract metadata from {file_path}: {e}")
121
+
122
+ return metadata
@@ -0,0 +1,149 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Catalog synchronization utilities for MCP Proxy Adapter.
6
+ """
7
+
8
+ from pathlib import Path
9
+ from typing import Dict, List, Any, Optional
10
+ from packaging import version as pkg_version
11
+
12
+ from mcp_proxy_adapter.core.logging import get_global_logger
13
+ from .command_catalog import CommandCatalog
14
+ from .catalog_loader import CatalogLoader
15
+ from .dependency_manager import DependencyManager
16
+
17
+ # Try to import requests, but don't fail if not available
18
+ try:
19
+ import requests
20
+ REQUESTS_AVAILABLE = True
21
+ except ImportError:
22
+ REQUESTS_AVAILABLE = False
23
+
24
+
25
+ class CatalogSyncer:
26
+ """Synchronizer for command catalogs."""
27
+
28
+ def __init__(self, catalog_dir: str):
29
+ """
30
+ Initialize catalog syncer.
31
+
32
+ Args:
33
+ catalog_dir: Directory for catalog storage
34
+ """
35
+ self.catalog_dir = Path(catalog_dir)
36
+ self.logger = get_global_logger()
37
+ self.loader = CatalogLoader()
38
+ self.dependency_manager = DependencyManager()
39
+
40
+
41
+ def _should_download_command(self, command_name: str, server_cmd: CommandCatalog) -> bool:
42
+ """
43
+ Check if command should be downloaded.
44
+
45
+ Args:
46
+ command_name: Name of the command
47
+ server_cmd: Server command catalog entry
48
+
49
+ Returns:
50
+ True if command should be downloaded, False otherwise
51
+ """
52
+ # Check if command exists locally
53
+ local_file = self.catalog_dir / f"{command_name}.py"
54
+ if not local_file.exists():
55
+ return True
56
+
57
+ # Check version
58
+ try:
59
+ local_version = self._get_local_version(command_name)
60
+ if local_version:
61
+ return pkg_version.parse(server_cmd.version) > pkg_version.parse(local_version)
62
+ except Exception as e:
63
+ self.logger.warning(f"Failed to compare versions for {command_name}: {e}")
64
+
65
+ return True
66
+
67
+ def _download_command(self, command_name: str, server_cmd: CommandCatalog) -> bool:
68
+ """
69
+ Download command from server.
70
+
71
+ Args:
72
+ command_name: Name of the command
73
+ server_cmd: Server command catalog entry
74
+
75
+ Returns:
76
+ True if download successful, False otherwise
77
+ """
78
+ if not REQUESTS_AVAILABLE:
79
+ self.logger.error("requests library not available, cannot download command")
80
+ return False
81
+
82
+ try:
83
+ # Download command file
84
+ response = requests.get(server_cmd.source_url, timeout=30)
85
+ response.raise_for_status()
86
+
87
+ # Save to local file
88
+ local_file = self.catalog_dir / f"{command_name}.py"
89
+ with open(local_file, 'w', encoding='utf-8') as f:
90
+ f.write(response.text)
91
+
92
+ # Update local catalog
93
+ server_cmd.file_path = str(local_file)
94
+ self._update_local_catalog(command_name, server_cmd)
95
+
96
+ return True
97
+
98
+ except Exception as e:
99
+ self.logger.error(f"Failed to download command {command_name}: {e}")
100
+ return False
101
+
102
+ def _get_local_version(self, command_name: str) -> Optional[str]:
103
+ """
104
+ Get local version of command.
105
+
106
+ Args:
107
+ command_name: Name of the command
108
+
109
+ Returns:
110
+ Local version string or None
111
+ """
112
+ try:
113
+ local_file = self.catalog_dir / f"{command_name}.py"
114
+ if local_file.exists():
115
+ with open(local_file, 'r', encoding='utf-8') as f:
116
+ content = f.read()
117
+
118
+ # Extract version from file content
119
+ for line in content.split('\n'):
120
+ if line.strip().startswith('__version__'):
121
+ return line.split('=')[1].strip().strip('"\'')
122
+ except Exception:
123
+ pass
124
+
125
+ return None
126
+
127
+ def _update_local_catalog(self, command_name: str, command_catalog: CommandCatalog) -> None:
128
+ """
129
+ Update local catalog with command information.
130
+
131
+ Args:
132
+ command_name: Name of the command
133
+ command_catalog: Command catalog entry
134
+ """
135
+ try:
136
+ catalog_file = self.catalog_dir / "catalog.json"
137
+ if catalog_file.exists():
138
+ with open(catalog_file, 'r', encoding='utf-8') as f:
139
+ catalog_data = json.load(f)
140
+ else:
141
+ catalog_data = {}
142
+
143
+ catalog_data[command_name] = command_catalog.to_dict()
144
+
145
+ with open(catalog_file, 'w', encoding='utf-8') as f:
146
+ json.dump(catalog_data, f, indent=2, ensure_ascii=False)
147
+
148
+ except Exception as e:
149
+ self.logger.error(f"Failed to update local catalog for {command_name}: {e}")
@@ -0,0 +1,43 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Command catalog data model for MCP Proxy Adapter.
6
+ """
7
+
8
+ from typing import Dict, List, Optional, Any
9
+
10
+
11
+ class CommandCatalog:
12
+ """
13
+ Represents a command in the catalog with metadata.
14
+ """
15
+
16
+ def __init__(
17
+ self, name: str, version: str, source_url: str, file_path: Optional[str] = None
18
+ ):
19
+ """
20
+ Initialize command catalog entry.
21
+
22
+ Args:
23
+ name: Command name
24
+ version: Command version
25
+ source_url: Source URL for the command
26
+ file_path: Local file path (optional)
27
+ """
28
+ self.name = name
29
+ self.version = version
30
+ self.source_url = source_url
31
+ self.file_path = file_path
32
+ self.metadata: Dict[str, Any] = {}
33
+
34
+ # Standard metadata fields
35
+ self.plugin: Optional[str] = None
36
+ self.descr: Optional[str] = None
37
+ self.category: Optional[str] = None
38
+ self.author: Optional[str] = None
39
+ self.email: Optional[str] = None
40
+ self.depends: Optional[List[str]] = None # New field for dependencies
41
+
42
+
43
+ @classmethod
@@ -0,0 +1,37 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Dependency management for command catalogs.
6
+ """
7
+
8
+ import subprocess
9
+ import sys
10
+
11
+ from mcp_proxy_adapter.core.logging import get_global_logger
12
+
13
+
14
+ class DependencyManager:
15
+ """Manager for command dependencies."""
16
+
17
+ def __init__(self):
18
+ """Initialize dependency manager."""
19
+ self.logger = get_global_logger()
20
+
21
+
22
+
23
+ def _is_package_installed(self, package_name: str) -> bool:
24
+ """
25
+ Check if a package is installed.
26
+
27
+ Args:
28
+ package_name: Name of the package to check
29
+
30
+ Returns:
31
+ True if package is installed, False otherwise
32
+ """
33
+ try:
34
+ __import__(package_name)
35
+ return True
36
+ except ImportError:
37
+ return False