mcp-proxy-adapter 4.1.1__py3-none-any.whl → 6.0.0__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 (101) hide show
  1. mcp_proxy_adapter/__main__.py +12 -0
  2. mcp_proxy_adapter/api/app.py +138 -11
  3. mcp_proxy_adapter/api/handlers.py +16 -1
  4. mcp_proxy_adapter/api/middleware/__init__.py +30 -29
  5. mcp_proxy_adapter/api/middleware/auth_adapter.py +235 -0
  6. mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
  7. mcp_proxy_adapter/api/middleware/factory.py +219 -0
  8. mcp_proxy_adapter/api/middleware/logging.py +32 -6
  9. mcp_proxy_adapter/api/middleware/mtls_adapter.py +305 -0
  10. mcp_proxy_adapter/api/middleware/mtls_middleware.py +296 -0
  11. mcp_proxy_adapter/api/middleware/protocol_middleware.py +135 -0
  12. mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +241 -0
  13. mcp_proxy_adapter/api/middleware/roles_adapter.py +365 -0
  14. mcp_proxy_adapter/api/middleware/roles_middleware.py +381 -0
  15. mcp_proxy_adapter/api/middleware/security.py +376 -0
  16. mcp_proxy_adapter/api/middleware/token_auth_middleware.py +261 -0
  17. mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
  18. mcp_proxy_adapter/commands/__init__.py +13 -4
  19. mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
  20. mcp_proxy_adapter/commands/base.py +61 -30
  21. mcp_proxy_adapter/commands/builtin_commands.py +89 -0
  22. mcp_proxy_adapter/commands/catalog_manager.py +838 -0
  23. mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
  24. mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
  25. mcp_proxy_adapter/commands/command_registry.py +703 -354
  26. mcp_proxy_adapter/commands/dependency_manager.py +245 -0
  27. mcp_proxy_adapter/commands/health_command.py +7 -0
  28. mcp_proxy_adapter/commands/hooks.py +200 -167
  29. mcp_proxy_adapter/commands/key_management_command.py +506 -0
  30. mcp_proxy_adapter/commands/load_command.py +176 -0
  31. mcp_proxy_adapter/commands/plugins_command.py +235 -0
  32. mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
  33. mcp_proxy_adapter/commands/proxy_registration_command.py +268 -0
  34. mcp_proxy_adapter/commands/reload_command.py +48 -50
  35. mcp_proxy_adapter/commands/result.py +1 -0
  36. mcp_proxy_adapter/commands/roles_management_command.py +697 -0
  37. mcp_proxy_adapter/commands/ssl_setup_command.py +483 -0
  38. mcp_proxy_adapter/commands/token_management_command.py +529 -0
  39. mcp_proxy_adapter/commands/transport_management_command.py +144 -0
  40. mcp_proxy_adapter/commands/unload_command.py +158 -0
  41. mcp_proxy_adapter/config.py +99 -2
  42. mcp_proxy_adapter/core/auth_validator.py +606 -0
  43. mcp_proxy_adapter/core/certificate_utils.py +827 -0
  44. mcp_proxy_adapter/core/config_converter.py +405 -0
  45. mcp_proxy_adapter/core/config_validator.py +218 -0
  46. mcp_proxy_adapter/core/logging.py +11 -0
  47. mcp_proxy_adapter/core/protocol_manager.py +226 -0
  48. mcp_proxy_adapter/core/proxy_registration.py +270 -0
  49. mcp_proxy_adapter/core/role_utils.py +426 -0
  50. mcp_proxy_adapter/core/security_adapter.py +373 -0
  51. mcp_proxy_adapter/core/security_factory.py +239 -0
  52. mcp_proxy_adapter/core/settings.py +1 -0
  53. mcp_proxy_adapter/core/ssl_utils.py +233 -0
  54. mcp_proxy_adapter/core/transport_manager.py +292 -0
  55. mcp_proxy_adapter/custom_openapi.py +22 -11
  56. mcp_proxy_adapter/examples/basic_server/config.json +58 -23
  57. mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +54 -0
  58. mcp_proxy_adapter/examples/basic_server/config_http.json +70 -0
  59. mcp_proxy_adapter/examples/basic_server/config_http_only.json +52 -0
  60. mcp_proxy_adapter/examples/basic_server/config_https.json +58 -0
  61. mcp_proxy_adapter/examples/basic_server/config_mtls.json +58 -0
  62. mcp_proxy_adapter/examples/basic_server/config_ssl.json +46 -0
  63. mcp_proxy_adapter/examples/basic_server/server.py +12 -1
  64. mcp_proxy_adapter/examples/custom_commands/__init__.py +1 -1
  65. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +339 -23
  66. mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +105 -0
  67. mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +129 -0
  68. mcp_proxy_adapter/examples/custom_commands/config.json +101 -18
  69. mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +46 -0
  70. mcp_proxy_adapter/examples/custom_commands/config_https_only.json +46 -0
  71. mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +33 -0
  72. mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +46 -0
  73. mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +33 -0
  74. mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +33 -0
  75. mcp_proxy_adapter/examples/custom_commands/full_help_response.json +1 -0
  76. mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +629 -0
  77. mcp_proxy_adapter/examples/custom_commands/get_openapi.py +103 -0
  78. mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +129 -0
  79. mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +278 -0
  80. mcp_proxy_adapter/examples/custom_commands/server.py +92 -68
  81. mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +75 -0
  82. mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +299 -0
  83. mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +278 -0
  84. mcp_proxy_adapter/examples/custom_commands/test_openapi.py +27 -0
  85. mcp_proxy_adapter/examples/custom_commands/test_registry.py +23 -0
  86. mcp_proxy_adapter/examples/custom_commands/test_simple.py +19 -0
  87. mcp_proxy_adapter/examples/custom_project_example/README.md +103 -0
  88. mcp_proxy_adapter/examples/custom_project_example/README_EN.md +103 -0
  89. mcp_proxy_adapter/examples/simple_custom_commands/README.md +149 -0
  90. mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +149 -0
  91. mcp_proxy_adapter/main.py +175 -0
  92. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  93. mcp_proxy_adapter/tests/unit/test_config.py +53 -0
  94. mcp_proxy_adapter/version.py +1 -1
  95. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/METADATA +2 -1
  96. mcp_proxy_adapter-6.0.0.dist-info/RECORD +179 -0
  97. mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
  98. mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
  99. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/WHEEL +0 -0
  100. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/licenses/LICENSE +0 -0
  101. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,158 @@
1
+ """
2
+ Module with unload command implementation.
3
+ """
4
+
5
+ from typing import Dict, Any, Optional, List
6
+
7
+ from mcp_proxy_adapter.commands.base import Command
8
+ from mcp_proxy_adapter.commands.result import CommandResult, SuccessResult
9
+ from mcp_proxy_adapter.commands.command_registry import registry
10
+
11
+
12
+ class UnloadResult(SuccessResult):
13
+ """
14
+ Result of the unload command execution.
15
+ """
16
+
17
+ def __init__(self, success: bool, command_name: str, message: str, error: Optional[str] = None):
18
+ """
19
+ Initialize unload command result.
20
+
21
+ Args:
22
+ success: Whether unloading was successful
23
+ command_name: Name of the command that was unloaded
24
+ message: Result message
25
+ error: Error message if unloading failed
26
+ """
27
+ data = {
28
+ "success": success,
29
+ "command_name": command_name
30
+ }
31
+ if error:
32
+ data["error"] = error
33
+
34
+ super().__init__(data=data, message=message)
35
+
36
+ @classmethod
37
+ def get_schema(cls) -> Dict[str, Any]:
38
+ """
39
+ Get JSON schema for result validation.
40
+
41
+ Returns:
42
+ Dict[str, Any]: JSON schema
43
+ """
44
+ return {
45
+ "type": "object",
46
+ "properties": {
47
+ "data": {
48
+ "type": "object",
49
+ "properties": {
50
+ "success": {"type": "boolean"},
51
+ "command_name": {"type": "string"},
52
+ "error": {"type": "string"}
53
+ },
54
+ "required": ["success", "command_name"]
55
+ }
56
+ },
57
+ "required": ["data"]
58
+ }
59
+
60
+
61
+ class UnloadCommand(Command):
62
+ """
63
+ Command that unloads loaded commands from registry.
64
+
65
+ This command allows removal of dynamically loaded commands from the command registry.
66
+ Only commands that were loaded via the 'load' command or from the commands directory
67
+ can be unloaded. Built-in commands and custom commands registered with higher priority
68
+ cannot be unloaded using this command.
69
+
70
+ When a command is unloaded:
71
+ - The command class is removed from the loaded commands registry
72
+ - Any command instances are also removed
73
+ - The command becomes unavailable for execution
74
+ - Built-in and custom commands with the same name remain unaffected
75
+
76
+ This is useful for:
77
+ - Removing outdated or problematic commands
78
+ - Managing memory usage by unloading unused commands
79
+ - Testing different versions of commands
80
+ - Cleaning up temporary commands loaded for testing
81
+
82
+ Note: Unloading a command does not affect other commands and does not require
83
+ a system restart. The command can be reloaded later if needed.
84
+ """
85
+
86
+ name = "unload"
87
+ result_class = UnloadResult
88
+
89
+ async def execute(self, command_name: str, **kwargs) -> UnloadResult:
90
+ """
91
+ Execute unload command.
92
+
93
+ Args:
94
+ command_name: Name of the command to unload
95
+ **kwargs: Additional parameters
96
+
97
+ Returns:
98
+ UnloadResult: Unload command result
99
+ """
100
+ # Unload command from registry
101
+ result = registry.unload_command(command_name)
102
+
103
+ return UnloadResult(
104
+ success=result.get("success", False),
105
+ command_name=result.get("command_name", command_name),
106
+ message=result.get("message", "Unknown result"),
107
+ error=result.get("error")
108
+ )
109
+
110
+ @classmethod
111
+ def get_schema(cls) -> Dict[str, Any]:
112
+ """
113
+ Get JSON schema for command parameters.
114
+
115
+ Returns:
116
+ Dict[str, Any]: JSON schema
117
+ """
118
+ return {
119
+ "type": "object",
120
+ "properties": {
121
+ "command_name": {
122
+ "type": "string",
123
+ "description": "Name of the command to unload (must be a loaded command)"
124
+ }
125
+ },
126
+ "required": ["command_name"]
127
+ }
128
+
129
+ @classmethod
130
+ def _generate_examples(cls, params: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:
131
+ """
132
+ Generate custom examples for unload command.
133
+
134
+ Args:
135
+ params: Information about command parameters
136
+
137
+ Returns:
138
+ List of examples
139
+ """
140
+ examples = [
141
+ {
142
+ "command": cls.name,
143
+ "params": {"command_name": "test_command"},
144
+ "description": "Unload a previously loaded test command"
145
+ },
146
+ {
147
+ "command": cls.name,
148
+ "params": {"command_name": "remote_command"},
149
+ "description": "Unload a command that was loaded from URL"
150
+ },
151
+ {
152
+ "command": cls.name,
153
+ "params": {"command_name": "custom_command"},
154
+ "description": "Unload a custom command loaded from local file"
155
+ }
156
+ ]
157
+
158
+ return examples
@@ -53,8 +53,105 @@ class Config:
53
53
  },
54
54
  "commands": {
55
55
  "auto_discovery": True,
56
- "discovery_path": "mcp_proxy_adapter.commands", # Path to package with commands (e.g., "myproject.commands")
57
- "custom_commands_path": None
56
+ "commands_directory": "./commands", # Path to directory with command files
57
+ "catalog_directory": "./catalog", # Path to command catalog directory
58
+ "plugin_servers": [], # List of plugin server URLs
59
+ "auto_install_dependencies": True # Automatically install plugin dependencies
60
+ },
61
+ "ssl": {
62
+ "enabled": False,
63
+ "mode": "https_only",
64
+ "cert_file": None,
65
+ "key_file": None,
66
+ "ca_cert": None,
67
+ "verify_client": False,
68
+ "client_cert_required": False,
69
+ "cipher_suites": ["TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256"],
70
+ "min_tls_version": "1.2",
71
+ "max_tls_version": "1.3",
72
+ "token_auth": {
73
+ "enabled": False,
74
+ "header_name": "Authorization",
75
+ "token_prefix": "Bearer",
76
+ "tokens_file": "tokens.json",
77
+ "token_expiry": 3600,
78
+ "jwt_secret": "",
79
+ "jwt_algorithm": "HS256"
80
+ }
81
+ },
82
+ "roles": {
83
+ "enabled": True,
84
+ "config_file": "schemas/roles_schema.json",
85
+ "default_policy": {
86
+ "deny_by_default": True,
87
+ "require_role_match": True,
88
+ "case_sensitive": False,
89
+ "allow_wildcard": True
90
+ },
91
+ "auto_load": True,
92
+ "validation_enabled": True
93
+ },
94
+ "transport": {
95
+ "type": "http",
96
+ "port": None,
97
+ "ssl": {
98
+ "enabled": False,
99
+ "cert_file": None,
100
+ "key_file": None,
101
+ "ca_cert": None,
102
+ "verify_client": False,
103
+ "client_cert_required": False
104
+ }
105
+ },
106
+ "proxy_registration": {
107
+ "enabled": False,
108
+ "proxy_url": "http://localhost:3004",
109
+ "server_id": "mcp_proxy_adapter",
110
+ "server_name": "MCP Proxy Adapter",
111
+ "description": "JSON-RPC API for interacting with MCP Proxy",
112
+ "registration_timeout": 30,
113
+ "retry_attempts": 3,
114
+ "retry_delay": 5,
115
+ "auto_register_on_startup": True,
116
+ "auto_unregister_on_shutdown": True
117
+ },
118
+ "debug": {
119
+ "enabled": False,
120
+ "level": "WARNING"
121
+ },
122
+ "security": {
123
+ "framework": "mcp_security_framework",
124
+ "enabled": True,
125
+ "auth": {
126
+ "enabled": True,
127
+ "methods": ["api_key"],
128
+ "api_keys": {},
129
+ "jwt_secret": "",
130
+ "jwt_algorithm": "HS256"
131
+ },
132
+ "ssl": {
133
+ "enabled": False,
134
+ "cert_file": None,
135
+ "key_file": None,
136
+ "ca_cert": None,
137
+ "min_tls_version": "TLSv1.2",
138
+ "verify_client": False,
139
+ "client_cert_required": False
140
+ },
141
+ "permissions": {
142
+ "enabled": True,
143
+ "roles_file": "roles.json",
144
+ "default_role": "user",
145
+ "deny_by_default": True
146
+ },
147
+ "rate_limit": {
148
+ "enabled": True,
149
+ "requests_per_minute": 60,
150
+ "requests_per_hour": 1000,
151
+ "burst_limit": 10,
152
+ "by_ip": True,
153
+ "by_user": True
154
+ }
58
155
  }
59
156
  }
60
157