mcp-proxy-adapter 4.1.1__py3-none-any.whl → 6.0.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.
- mcp_proxy_adapter/__main__.py +32 -0
- mcp_proxy_adapter/api/app.py +290 -33
- mcp_proxy_adapter/api/handlers.py +32 -6
- mcp_proxy_adapter/api/middleware/__init__.py +38 -32
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
- mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
- mcp_proxy_adapter/api/middleware/factory.py +243 -0
- mcp_proxy_adapter/api/middleware/logging.py +32 -6
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +201 -0
- mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
- mcp_proxy_adapter/api/middleware/unified_security.py +197 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +158 -0
- mcp_proxy_adapter/commands/__init__.py +19 -4
- mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
- mcp_proxy_adapter/commands/base.py +66 -32
- mcp_proxy_adapter/commands/builtin_commands.py +95 -0
- mcp_proxy_adapter/commands/catalog_manager.py +838 -0
- mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
- mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
- mcp_proxy_adapter/commands/command_registry.py +711 -354
- mcp_proxy_adapter/commands/dependency_manager.py +245 -0
- mcp_proxy_adapter/commands/echo_command.py +81 -0
- mcp_proxy_adapter/commands/health_command.py +8 -1
- mcp_proxy_adapter/commands/help_command.py +21 -14
- mcp_proxy_adapter/commands/hooks.py +200 -167
- mcp_proxy_adapter/commands/key_management_command.py +506 -0
- mcp_proxy_adapter/commands/load_command.py +176 -0
- mcp_proxy_adapter/commands/plugins_command.py +235 -0
- mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
- mcp_proxy_adapter/commands/proxy_registration_command.py +409 -0
- mcp_proxy_adapter/commands/reload_command.py +48 -50
- mcp_proxy_adapter/commands/result.py +1 -0
- mcp_proxy_adapter/commands/role_test_command.py +141 -0
- mcp_proxy_adapter/commands/roles_management_command.py +697 -0
- mcp_proxy_adapter/commands/security_command.py +488 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +366 -0
- mcp_proxy_adapter/commands/token_management_command.py +529 -0
- mcp_proxy_adapter/commands/transport_management_command.py +144 -0
- mcp_proxy_adapter/commands/unload_command.py +158 -0
- mcp_proxy_adapter/config.py +394 -14
- mcp_proxy_adapter/core/app_factory.py +410 -0
- mcp_proxy_adapter/core/app_runner.py +272 -0
- mcp_proxy_adapter/core/auth_validator.py +606 -0
- mcp_proxy_adapter/core/certificate_utils.py +1045 -0
- mcp_proxy_adapter/core/client.py +574 -0
- mcp_proxy_adapter/core/client_manager.py +284 -0
- mcp_proxy_adapter/core/client_security.py +384 -0
- mcp_proxy_adapter/core/config_converter.py +405 -0
- mcp_proxy_adapter/core/config_validator.py +218 -0
- mcp_proxy_adapter/core/logging.py +19 -3
- mcp_proxy_adapter/core/mtls_asgi.py +156 -0
- mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
- mcp_proxy_adapter/core/protocol_manager.py +385 -0
- mcp_proxy_adapter/core/proxy_client.py +602 -0
- mcp_proxy_adapter/core/proxy_registration.py +522 -0
- mcp_proxy_adapter/core/role_utils.py +426 -0
- mcp_proxy_adapter/core/security_adapter.py +370 -0
- mcp_proxy_adapter/core/security_factory.py +239 -0
- mcp_proxy_adapter/core/security_integration.py +286 -0
- mcp_proxy_adapter/core/server_adapter.py +282 -0
- mcp_proxy_adapter/core/server_engine.py +270 -0
- mcp_proxy_adapter/core/settings.py +1 -0
- mcp_proxy_adapter/core/ssl_utils.py +234 -0
- mcp_proxy_adapter/core/transport_manager.py +292 -0
- mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
- mcp_proxy_adapter/custom_openapi.py +22 -11
- mcp_proxy_adapter/examples/__init__.py +13 -4
- mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
- mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/main.py +44 -0
- mcp_proxy_adapter/examples/commands/__init__.py +5 -0
- mcp_proxy_adapter/examples/create_certificates_simple.py +550 -0
- mcp_proxy_adapter/examples/debug_request_state.py +112 -0
- mcp_proxy_adapter/examples/debug_role_chain.py +158 -0
- mcp_proxy_adapter/examples/demo_client.py +275 -0
- mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
- mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
- mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
- mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +80 -0
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +90 -0
- mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +75 -0
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +71 -0
- mcp_proxy_adapter/examples/full_application/main.py +173 -0
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
- mcp_proxy_adapter/examples/generate_all_certificates.py +362 -0
- mcp_proxy_adapter/examples/generate_certificates.py +177 -0
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
- mcp_proxy_adapter/examples/generate_test_configs.py +331 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +334 -0
- mcp_proxy_adapter/examples/run_example.py +59 -0
- mcp_proxy_adapter/examples/run_full_test_suite.py +318 -0
- mcp_proxy_adapter/examples/run_proxy_server.py +146 -0
- mcp_proxy_adapter/examples/run_security_tests.py +544 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +247 -0
- mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
- mcp_proxy_adapter/examples/security_test_client.py +782 -0
- mcp_proxy_adapter/examples/setup_test_environment.py +328 -0
- mcp_proxy_adapter/examples/test_config.py +148 -0
- mcp_proxy_adapter/examples/test_config_generator.py +86 -0
- mcp_proxy_adapter/examples/test_examples.py +281 -0
- mcp_proxy_adapter/examples/universal_client.py +620 -0
- mcp_proxy_adapter/main.py +93 -0
- mcp_proxy_adapter/utils/config_generator.py +1008 -0
- mcp_proxy_adapter/version.py +5 -2
- mcp_proxy_adapter-6.0.1.dist-info/METADATA +679 -0
- mcp_proxy_adapter-6.0.1.dist-info/RECORD +140 -0
- mcp_proxy_adapter-6.0.1.dist-info/entry_points.txt +2 -0
- {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/licenses/LICENSE +2 -2
- mcp_proxy_adapter/api/middleware/auth.py +0 -146
- mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
- mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
- mcp_proxy_adapter/examples/README.md +0 -124
- mcp_proxy_adapter/examples/basic_server/README.md +0 -60
- mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
- mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
- mcp_proxy_adapter/examples/basic_server/config.json +0 -35
- mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
- mcp_proxy_adapter/examples/basic_server/server.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
- mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
- mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -250
- mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
- mcp_proxy_adapter/examples/custom_commands/config.json +0 -35
- mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
- mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
- mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
- mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
- mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
- mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
- mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
- mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
- mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
- mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/server.py +0 -228
- mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
- mcp_proxy_adapter/examples/deployment/README.md +0 -49
- mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
- mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
- mcp_proxy_adapter/examples/deployment/config.json +0 -29
- mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
- mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
- mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
- mcp_proxy_adapter/examples/deployment/run.sh +0 -43
- mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
- mcp_proxy_adapter/schemas/base_schema.json +0 -114
- mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
- mcp_proxy_adapter/tests/__init__.py +0 -0
- mcp_proxy_adapter/tests/api/__init__.py +0 -3
- mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
- mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
- mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
- mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
- mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
- mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
- mcp_proxy_adapter/tests/commands/__init__.py +0 -3
- mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
- mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
- mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
- mcp_proxy_adapter/tests/conftest.py +0 -131
- mcp_proxy_adapter/tests/functional/__init__.py +0 -3
- mcp_proxy_adapter/tests/functional/test_api.py +0 -253
- mcp_proxy_adapter/tests/integration/__init__.py +0 -3
- mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
- mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
- mcp_proxy_adapter/tests/performance/__init__.py +0 -3
- mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
- mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
- mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
- mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
- mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
- mcp_proxy_adapter/tests/test_base_command.py +0 -123
- mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
- mcp_proxy_adapter/tests/test_command_registry.py +0 -281
- mcp_proxy_adapter/tests/test_config.py +0 -127
- mcp_proxy_adapter/tests/test_utils.py +0 -65
- mcp_proxy_adapter/tests/unit/__init__.py +0 -3
- mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
- mcp_proxy_adapter/tests/unit/test_config.py +0 -217
- mcp_proxy_adapter-4.1.1.dist-info/METADATA +0 -200
- mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
- {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,408 @@
|
|
1
|
+
"""
|
2
|
+
Authentication Validation Commands
|
3
|
+
|
4
|
+
This module provides commands for validating different types of authentication:
|
5
|
+
- Universal authentication validation
|
6
|
+
- Certificate validation
|
7
|
+
- Token validation
|
8
|
+
- mTLS validation
|
9
|
+
- SSL validation
|
10
|
+
|
11
|
+
Author: MCP Proxy Adapter Team
|
12
|
+
Version: 1.0.0
|
13
|
+
"""
|
14
|
+
|
15
|
+
import logging
|
16
|
+
from typing import Dict, List, Any, Optional, Union
|
17
|
+
|
18
|
+
from ..commands.base import Command
|
19
|
+
from ..commands.result import SuccessResult, ErrorResult
|
20
|
+
from ..core.auth_validator import AuthValidator, AuthValidationResult
|
21
|
+
|
22
|
+
|
23
|
+
class AuthValidationCommand(Command):
|
24
|
+
"""
|
25
|
+
Authentication validation commands.
|
26
|
+
|
27
|
+
Provides commands for validating different types of authentication
|
28
|
+
using the universal AuthValidator.
|
29
|
+
"""
|
30
|
+
|
31
|
+
def __init__(self):
|
32
|
+
"""Initialize authentication validation command."""
|
33
|
+
super().__init__()
|
34
|
+
self.validator = AuthValidator()
|
35
|
+
self.logger = logging.getLogger(__name__)
|
36
|
+
|
37
|
+
async def auth_validate(self, auth_data: Dict[str, Any]) -> Union[SuccessResult, ErrorResult]:
|
38
|
+
"""
|
39
|
+
Universal authentication validation.
|
40
|
+
|
41
|
+
Validates authentication data based on the provided type.
|
42
|
+
Supports certificate, token, mTLS, and SSL validation.
|
43
|
+
|
44
|
+
Args:
|
45
|
+
auth_data: Authentication data dictionary containing:
|
46
|
+
- auth_type: Type of authentication (auto/certificate/token/mtls/ssl)
|
47
|
+
- cert_path: Path to certificate file (for certificate/mtls/ssl)
|
48
|
+
- cert_type: Type of certificate (server/client/ca)
|
49
|
+
- token: Token string (for token validation)
|
50
|
+
- token_type: Type of token (jwt/api)
|
51
|
+
- client_cert: Path to client certificate (for mTLS)
|
52
|
+
- ca_cert: Path to CA certificate (for mTLS)
|
53
|
+
- server_cert: Path to server certificate (for SSL)
|
54
|
+
|
55
|
+
Returns:
|
56
|
+
CommandResult with validation status and extracted roles
|
57
|
+
"""
|
58
|
+
try:
|
59
|
+
auth_type = auth_data.get("auth_type", "auto")
|
60
|
+
|
61
|
+
# Perform validation
|
62
|
+
result = self.validator.validate_auth(auth_data, auth_type)
|
63
|
+
|
64
|
+
if result.is_valid:
|
65
|
+
return SuccessResult(
|
66
|
+
data={
|
67
|
+
"valid": True,
|
68
|
+
"roles": result.roles,
|
69
|
+
"auth_type": auth_type
|
70
|
+
}
|
71
|
+
)
|
72
|
+
else:
|
73
|
+
error_data = result.to_json_rpc_error()
|
74
|
+
return ErrorResult(
|
75
|
+
message=error_data["message"],
|
76
|
+
code=error_data["code"]
|
77
|
+
)
|
78
|
+
|
79
|
+
except Exception as e:
|
80
|
+
self.logger.error(f"Authentication validation error: {e}")
|
81
|
+
return ErrorResult(
|
82
|
+
message=f"Internal authentication validation error: {str(e)}",
|
83
|
+
code=-32603
|
84
|
+
)
|
85
|
+
|
86
|
+
async def auth_validate_cert(self, cert_path: str, cert_type: str = "server") -> Union[SuccessResult, ErrorResult]:
|
87
|
+
"""
|
88
|
+
Validate certificate.
|
89
|
+
|
90
|
+
Validates a certificate file and extracts roles if present.
|
91
|
+
|
92
|
+
Args:
|
93
|
+
cert_path: Path to certificate file
|
94
|
+
cert_type: Type of certificate (server/client/ca)
|
95
|
+
|
96
|
+
Returns:
|
97
|
+
CommandResult with certificate validation status and roles
|
98
|
+
"""
|
99
|
+
try:
|
100
|
+
# Perform certificate validation
|
101
|
+
result = self.validator.validate_certificate(cert_path, cert_type)
|
102
|
+
|
103
|
+
if result.is_valid:
|
104
|
+
return SuccessResult(
|
105
|
+
data={
|
106
|
+
"valid": True,
|
107
|
+
"cert_path": cert_path,
|
108
|
+
"cert_type": cert_type,
|
109
|
+
"roles": result.roles
|
110
|
+
}
|
111
|
+
)
|
112
|
+
else:
|
113
|
+
error_data = result.to_json_rpc_error()
|
114
|
+
return ErrorResult(
|
115
|
+
message=error_data["message"],
|
116
|
+
code=error_data["code"]
|
117
|
+
)
|
118
|
+
|
119
|
+
except Exception as e:
|
120
|
+
self.logger.error(f"Certificate validation error: {e}")
|
121
|
+
return ErrorResult(
|
122
|
+
message=f"Internal certificate validation error: {str(e)}",
|
123
|
+
code=-32603
|
124
|
+
)
|
125
|
+
|
126
|
+
async def auth_validate_token(self, token: str, token_type: str = "jwt") -> Union[SuccessResult, ErrorResult]:
|
127
|
+
"""
|
128
|
+
Validate token.
|
129
|
+
|
130
|
+
Validates a token and extracts roles if present.
|
131
|
+
|
132
|
+
Args:
|
133
|
+
token: Token string to validate
|
134
|
+
token_type: Type of token (jwt/api)
|
135
|
+
|
136
|
+
Returns:
|
137
|
+
CommandResult with token validation status and roles
|
138
|
+
"""
|
139
|
+
try:
|
140
|
+
# Perform token validation
|
141
|
+
result = self.validator.validate_token(token, token_type)
|
142
|
+
|
143
|
+
if result.is_valid:
|
144
|
+
return SuccessResult(
|
145
|
+
data={
|
146
|
+
"valid": True,
|
147
|
+
"token_type": token_type,
|
148
|
+
"roles": result.roles
|
149
|
+
}
|
150
|
+
)
|
151
|
+
else:
|
152
|
+
error_data = result.to_json_rpc_error()
|
153
|
+
return ErrorResult(
|
154
|
+
message=error_data["message"],
|
155
|
+
code=error_data["code"]
|
156
|
+
)
|
157
|
+
|
158
|
+
except Exception as e:
|
159
|
+
self.logger.error(f"Token validation error: {e}")
|
160
|
+
return ErrorResult(
|
161
|
+
message=f"Internal token validation error: {str(e)}",
|
162
|
+
code=-32603
|
163
|
+
)
|
164
|
+
|
165
|
+
async def auth_validate_mtls(self, client_cert: str, ca_cert: str) -> Union[SuccessResult, ErrorResult]:
|
166
|
+
"""
|
167
|
+
Validate mTLS connection.
|
168
|
+
|
169
|
+
Validates client certificate against CA certificate and extracts roles.
|
170
|
+
|
171
|
+
Args:
|
172
|
+
client_cert: Path to client certificate
|
173
|
+
ca_cert: Path to CA certificate
|
174
|
+
|
175
|
+
Returns:
|
176
|
+
CommandResult with mTLS validation status and roles
|
177
|
+
"""
|
178
|
+
try:
|
179
|
+
# Perform mTLS validation
|
180
|
+
result = self.validator.validate_mtls(client_cert, ca_cert)
|
181
|
+
|
182
|
+
if result.is_valid:
|
183
|
+
return SuccessResult(
|
184
|
+
data={
|
185
|
+
"valid": True,
|
186
|
+
"client_cert": client_cert,
|
187
|
+
"ca_cert": ca_cert,
|
188
|
+
"roles": result.roles
|
189
|
+
}
|
190
|
+
)
|
191
|
+
else:
|
192
|
+
error_data = result.to_json_rpc_error()
|
193
|
+
return ErrorResult(
|
194
|
+
message=error_data["message"],
|
195
|
+
code=error_data["code"]
|
196
|
+
)
|
197
|
+
|
198
|
+
except Exception as e:
|
199
|
+
self.logger.error(f"mTLS validation error: {e}")
|
200
|
+
return ErrorResult(
|
201
|
+
message=f"Internal mTLS validation error: {str(e)}",
|
202
|
+
code=-32603
|
203
|
+
)
|
204
|
+
|
205
|
+
async def auth_validate_ssl(self, server_cert: str) -> Union[SuccessResult, ErrorResult]:
|
206
|
+
"""
|
207
|
+
Validate SSL connection.
|
208
|
+
|
209
|
+
Validates server certificate and extracts roles if present.
|
210
|
+
|
211
|
+
Args:
|
212
|
+
server_cert: Path to server certificate
|
213
|
+
|
214
|
+
Returns:
|
215
|
+
CommandResult with SSL validation status and roles
|
216
|
+
"""
|
217
|
+
try:
|
218
|
+
# Perform SSL validation
|
219
|
+
result = self.validator.validate_ssl(server_cert)
|
220
|
+
|
221
|
+
if result.is_valid:
|
222
|
+
return SuccessResult(
|
223
|
+
data={
|
224
|
+
"valid": True,
|
225
|
+
"server_cert": server_cert,
|
226
|
+
"roles": result.roles
|
227
|
+
}
|
228
|
+
)
|
229
|
+
else:
|
230
|
+
error_data = result.to_json_rpc_error()
|
231
|
+
return ErrorResult(
|
232
|
+
message=error_data["message"],
|
233
|
+
code=error_data["code"]
|
234
|
+
)
|
235
|
+
|
236
|
+
except Exception as e:
|
237
|
+
self.logger.error(f"SSL validation error: {e}")
|
238
|
+
return ErrorResult(
|
239
|
+
message=f"Internal SSL validation error: {str(e)}",
|
240
|
+
code=-32603
|
241
|
+
)
|
242
|
+
|
243
|
+
async def execute(self, **kwargs) -> Union[SuccessResult, ErrorResult]:
|
244
|
+
"""
|
245
|
+
Execute authentication validation command.
|
246
|
+
|
247
|
+
This is a placeholder method to satisfy the abstract base class.
|
248
|
+
Individual validation methods should be called directly.
|
249
|
+
|
250
|
+
Args:
|
251
|
+
**kwargs: Command parameters
|
252
|
+
|
253
|
+
Returns:
|
254
|
+
Command result
|
255
|
+
"""
|
256
|
+
return ErrorResult(
|
257
|
+
message="Method not found. Use specific validation methods instead.",
|
258
|
+
code=-32601
|
259
|
+
)
|
260
|
+
|
261
|
+
@classmethod
|
262
|
+
def get_schema(cls) -> Dict[str, Any]:
|
263
|
+
"""
|
264
|
+
Get command schema for documentation.
|
265
|
+
|
266
|
+
Returns:
|
267
|
+
Dictionary containing command schema
|
268
|
+
"""
|
269
|
+
return {
|
270
|
+
"auth_validate": {
|
271
|
+
"description": "Universal authentication validation",
|
272
|
+
"parameters": {
|
273
|
+
"auth_data": {
|
274
|
+
"type": "object",
|
275
|
+
"description": "Authentication data dictionary",
|
276
|
+
"properties": {
|
277
|
+
"auth_type": {
|
278
|
+
"type": "string",
|
279
|
+
"enum": ["auto", "certificate", "token", "mtls", "ssl"],
|
280
|
+
"description": "Type of authentication to validate"
|
281
|
+
},
|
282
|
+
"cert_path": {
|
283
|
+
"type": "string",
|
284
|
+
"description": "Path to certificate file"
|
285
|
+
},
|
286
|
+
"cert_type": {
|
287
|
+
"type": "string",
|
288
|
+
"enum": ["server", "client", "ca"],
|
289
|
+
"description": "Type of certificate"
|
290
|
+
},
|
291
|
+
"token": {
|
292
|
+
"type": "string",
|
293
|
+
"description": "Token string to validate"
|
294
|
+
},
|
295
|
+
"token_type": {
|
296
|
+
"type": "string",
|
297
|
+
"enum": ["jwt", "api"],
|
298
|
+
"description": "Type of token"
|
299
|
+
},
|
300
|
+
"client_cert": {
|
301
|
+
"type": "string",
|
302
|
+
"description": "Path to client certificate (for mTLS)"
|
303
|
+
},
|
304
|
+
"ca_cert": {
|
305
|
+
"type": "string",
|
306
|
+
"description": "Path to CA certificate (for mTLS)"
|
307
|
+
},
|
308
|
+
"server_cert": {
|
309
|
+
"type": "string",
|
310
|
+
"description": "Path to server certificate (for SSL)"
|
311
|
+
}
|
312
|
+
}
|
313
|
+
}
|
314
|
+
},
|
315
|
+
"returns": {
|
316
|
+
"type": "object",
|
317
|
+
"properties": {
|
318
|
+
"valid": {"type": "boolean"},
|
319
|
+
"roles": {"type": "array", "items": {"type": "string"}},
|
320
|
+
"auth_type": {"type": "string"}
|
321
|
+
}
|
322
|
+
}
|
323
|
+
},
|
324
|
+
"auth_validate_cert": {
|
325
|
+
"description": "Validate certificate",
|
326
|
+
"parameters": {
|
327
|
+
"cert_path": {
|
328
|
+
"type": "string",
|
329
|
+
"description": "Path to certificate file"
|
330
|
+
},
|
331
|
+
"cert_type": {
|
332
|
+
"type": "string",
|
333
|
+
"enum": ["server", "client", "ca"],
|
334
|
+
"description": "Type of certificate"
|
335
|
+
}
|
336
|
+
},
|
337
|
+
"returns": {
|
338
|
+
"type": "object",
|
339
|
+
"properties": {
|
340
|
+
"valid": {"type": "boolean"},
|
341
|
+
"cert_path": {"type": "string"},
|
342
|
+
"cert_type": {"type": "string"},
|
343
|
+
"roles": {"type": "array", "items": {"type": "string"}}
|
344
|
+
}
|
345
|
+
}
|
346
|
+
},
|
347
|
+
"auth_validate_token": {
|
348
|
+
"description": "Validate token",
|
349
|
+
"parameters": {
|
350
|
+
"token": {
|
351
|
+
"type": "string",
|
352
|
+
"description": "Token string to validate"
|
353
|
+
},
|
354
|
+
"token_type": {
|
355
|
+
"type": "string",
|
356
|
+
"enum": ["jwt", "api"],
|
357
|
+
"description": "Type of token"
|
358
|
+
}
|
359
|
+
},
|
360
|
+
"returns": {
|
361
|
+
"type": "object",
|
362
|
+
"properties": {
|
363
|
+
"valid": {"type": "boolean"},
|
364
|
+
"token_type": {"type": "string"},
|
365
|
+
"roles": {"type": "array", "items": {"type": "string"}}
|
366
|
+
}
|
367
|
+
}
|
368
|
+
},
|
369
|
+
"auth_validate_mtls": {
|
370
|
+
"description": "Validate mTLS connection",
|
371
|
+
"parameters": {
|
372
|
+
"client_cert": {
|
373
|
+
"type": "string",
|
374
|
+
"description": "Path to client certificate"
|
375
|
+
},
|
376
|
+
"ca_cert": {
|
377
|
+
"type": "string",
|
378
|
+
"description": "Path to CA certificate"
|
379
|
+
}
|
380
|
+
},
|
381
|
+
"returns": {
|
382
|
+
"type": "object",
|
383
|
+
"properties": {
|
384
|
+
"valid": {"type": "boolean"},
|
385
|
+
"client_cert": {"type": "string"},
|
386
|
+
"ca_cert": {"type": "string"},
|
387
|
+
"roles": {"type": "array", "items": {"type": "string"}}
|
388
|
+
}
|
389
|
+
}
|
390
|
+
},
|
391
|
+
"auth_validate_ssl": {
|
392
|
+
"description": "Validate SSL connection",
|
393
|
+
"parameters": {
|
394
|
+
"server_cert": {
|
395
|
+
"type": "string",
|
396
|
+
"description": "Path to server certificate"
|
397
|
+
}
|
398
|
+
},
|
399
|
+
"returns": {
|
400
|
+
"type": "object",
|
401
|
+
"properties": {
|
402
|
+
"valid": {"type": "boolean"},
|
403
|
+
"server_cert": {"type": "string"},
|
404
|
+
"roles": {"type": "array", "items": {"type": "string"}}
|
405
|
+
}
|
406
|
+
}
|
407
|
+
}
|
408
|
+
}
|
@@ -13,7 +13,6 @@ from mcp_proxy_adapter.core.errors import (
|
|
13
13
|
CommandError, InternalError, InvalidParamsError, NotFoundError, ValidationError
|
14
14
|
)
|
15
15
|
from mcp_proxy_adapter.core.logging import logger
|
16
|
-
from .hooks import hooks, HookContext
|
17
16
|
|
18
17
|
|
19
18
|
T = TypeVar("T", bound=CommandResult)
|
@@ -26,6 +25,20 @@ class Command(ABC):
|
|
26
25
|
|
27
26
|
# Command name for registration
|
28
27
|
name: ClassVar[str]
|
28
|
+
# Command version (default: 0.1)
|
29
|
+
version: ClassVar[str] = "0.1"
|
30
|
+
# Plugin filename
|
31
|
+
plugin: ClassVar[str] = ""
|
32
|
+
# Command description
|
33
|
+
descr: ClassVar[str] = ""
|
34
|
+
# Command category
|
35
|
+
category: ClassVar[str] = ""
|
36
|
+
# Command author
|
37
|
+
author: ClassVar[str] = ""
|
38
|
+
# Author email
|
39
|
+
email: ClassVar[str] = ""
|
40
|
+
# Source URL
|
41
|
+
source_url: ClassVar[str] = ""
|
29
42
|
# Result class
|
30
43
|
result_class: ClassVar[Type[CommandResult]]
|
31
44
|
|
@@ -35,7 +48,7 @@ class Command(ABC):
|
|
35
48
|
Execute command with the specified parameters.
|
36
49
|
|
37
50
|
Args:
|
38
|
-
**kwargs: Command parameters.
|
51
|
+
**kwargs: Command parameters including optional 'context' parameter.
|
39
52
|
|
40
53
|
Returns:
|
41
54
|
Command result.
|
@@ -68,8 +81,7 @@ class Command(ABC):
|
|
68
81
|
return cls.result_class.get_schema()
|
69
82
|
return {}
|
70
83
|
|
71
|
-
|
72
|
-
def validate_params(cls, params: Dict[str, Any]) -> Dict[str, Any]:
|
84
|
+
def validate_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
73
85
|
"""
|
74
86
|
Validate command parameters.
|
75
87
|
|
@@ -100,9 +112,39 @@ class Command(ABC):
|
|
100
112
|
else:
|
101
113
|
# For most parameters, remove None values to avoid issues
|
102
114
|
del validated_params[key]
|
115
|
+
|
116
|
+
# Get command schema to validate parameters
|
117
|
+
schema = self.get_schema()
|
118
|
+
if schema and "properties" in schema:
|
119
|
+
allowed_properties = schema["properties"].keys()
|
120
|
+
|
121
|
+
# Filter out parameters that are not in the schema
|
122
|
+
invalid_params = []
|
123
|
+
for param_name in list(validated_params.keys()):
|
124
|
+
if param_name not in allowed_properties:
|
125
|
+
invalid_params.append(param_name)
|
126
|
+
del validated_params[param_name]
|
127
|
+
|
128
|
+
# Log warning about invalid parameters
|
129
|
+
if invalid_params:
|
130
|
+
logger.warning(f"Command {self.__class__.__name__} received invalid parameters: {invalid_params}. "
|
131
|
+
f"Allowed parameters: {list(allowed_properties)}")
|
132
|
+
|
133
|
+
# Validate required parameters based on command schema
|
134
|
+
if schema and "required" in schema:
|
135
|
+
required_params = schema["required"]
|
136
|
+
missing_params = []
|
137
|
+
|
138
|
+
for param in required_params:
|
139
|
+
if param not in validated_params:
|
140
|
+
missing_params.append(param)
|
141
|
+
|
142
|
+
if missing_params:
|
143
|
+
raise ValidationError(
|
144
|
+
f"Missing required parameters: {', '.join(missing_params)}",
|
145
|
+
data={"missing_parameters": missing_params}
|
146
|
+
)
|
103
147
|
|
104
|
-
# This is a simple implementation that can be overridden by subclasses
|
105
|
-
# In real implementation this method would validate parameters against the schema
|
106
148
|
return validated_params
|
107
149
|
|
108
150
|
@classmethod
|
@@ -111,11 +153,14 @@ class Command(ABC):
|
|
111
153
|
Runs the command with the specified arguments.
|
112
154
|
|
113
155
|
Args:
|
114
|
-
**kwargs: Command arguments.
|
156
|
+
**kwargs: Command arguments including optional 'context' parameter.
|
115
157
|
|
116
158
|
Returns:
|
117
159
|
Command result.
|
118
160
|
"""
|
161
|
+
# Extract context from kwargs
|
162
|
+
context = kwargs.pop('context', {}) if 'context' in kwargs else {}
|
163
|
+
|
119
164
|
try:
|
120
165
|
logger.debug(f"Running command {cls.__name__} with params: {kwargs}")
|
121
166
|
|
@@ -134,35 +179,17 @@ class Command(ABC):
|
|
134
179
|
if kwargs is None:
|
135
180
|
kwargs = {}
|
136
181
|
|
137
|
-
# Parameters validation
|
138
|
-
validated_params = cls.validate_params(kwargs)
|
139
|
-
|
140
|
-
# Execute before hooks
|
141
|
-
hook_context = hooks.execute_before_hooks(command_name, validated_params)
|
142
|
-
|
143
|
-
# Check if standard processing should be skipped
|
144
|
-
if not hook_context.standard_processing:
|
145
|
-
logger.debug(f"Standard processing skipped for command {command_name} due to hook")
|
146
|
-
# Return the params as result if standard processing is disabled
|
147
|
-
return SuccessResult(data=validated_params)
|
148
|
-
|
149
182
|
# Get command with priority (custom commands first, then built-in)
|
150
|
-
|
151
|
-
if
|
183
|
+
command_class = registry.get_command(command_name)
|
184
|
+
if command_class is None:
|
152
185
|
raise NotFoundError(f"Command '{command_name}' not found")
|
153
186
|
|
154
|
-
#
|
155
|
-
|
156
|
-
|
157
|
-
command = registry.get_command_instance(command_name)
|
158
|
-
result = await command.execute(**validated_params)
|
159
|
-
else:
|
160
|
-
# Create new instance for commands without dependencies
|
161
|
-
command = priority_command_class()
|
162
|
-
result = await command.execute(**validated_params)
|
187
|
+
# Create new instance and validate parameters
|
188
|
+
command = command_class()
|
189
|
+
validated_params = command.validate_params(kwargs)
|
163
190
|
|
164
|
-
# Execute
|
165
|
-
|
191
|
+
# Execute command with validated parameters and context
|
192
|
+
result = await command.execute(**validated_params, context=context)
|
166
193
|
|
167
194
|
logger.debug(f"Command {cls.__name__} executed successfully")
|
168
195
|
return result
|
@@ -271,6 +298,13 @@ class Command(ABC):
|
|
271
298
|
|
272
299
|
return {
|
273
300
|
"name": cls.name,
|
301
|
+
"version": cls.version,
|
302
|
+
"plugin": cls.plugin,
|
303
|
+
"descr": cls.descr,
|
304
|
+
"category": cls.category,
|
305
|
+
"author": cls.author,
|
306
|
+
"email": cls.email,
|
307
|
+
"source_url": cls.source_url,
|
274
308
|
"summary": summary,
|
275
309
|
"description": description,
|
276
310
|
"params": param_info,
|
@@ -0,0 +1,95 @@
|
|
1
|
+
"""
|
2
|
+
Module for registering built-in framework commands.
|
3
|
+
|
4
|
+
This module contains the procedure for adding predefined commands
|
5
|
+
that are part of the framework.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from typing import List
|
9
|
+
from mcp_proxy_adapter.commands.command_registry import registry
|
10
|
+
from mcp_proxy_adapter.commands.help_command import HelpCommand
|
11
|
+
from mcp_proxy_adapter.commands.health_command import HealthCommand
|
12
|
+
from mcp_proxy_adapter.commands.config_command import ConfigCommand
|
13
|
+
from mcp_proxy_adapter.commands.reload_command import ReloadCommand
|
14
|
+
from mcp_proxy_adapter.commands.settings_command import SettingsCommand
|
15
|
+
from mcp_proxy_adapter.commands.load_command import LoadCommand
|
16
|
+
from mcp_proxy_adapter.commands.unload_command import UnloadCommand
|
17
|
+
from mcp_proxy_adapter.commands.plugins_command import PluginsCommand
|
18
|
+
from mcp_proxy_adapter.commands.transport_management_command import TransportManagementCommand
|
19
|
+
from mcp_proxy_adapter.commands.proxy_registration_command import ProxyRegistrationCommand
|
20
|
+
from mcp_proxy_adapter.commands.echo_command import EchoCommand
|
21
|
+
from mcp_proxy_adapter.commands.role_test_command import RoleTestCommand
|
22
|
+
from mcp_proxy_adapter.core.logging import logger
|
23
|
+
|
24
|
+
|
25
|
+
def register_builtin_commands() -> int:
|
26
|
+
"""
|
27
|
+
Register all built-in framework commands.
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
Number of built-in commands registered.
|
31
|
+
"""
|
32
|
+
logger.debug("Registering built-in framework commands...")
|
33
|
+
|
34
|
+
builtin_commands = [
|
35
|
+
HelpCommand,
|
36
|
+
HealthCommand,
|
37
|
+
ConfigCommand,
|
38
|
+
ReloadCommand,
|
39
|
+
SettingsCommand,
|
40
|
+
LoadCommand,
|
41
|
+
UnloadCommand,
|
42
|
+
PluginsCommand,
|
43
|
+
TransportManagementCommand,
|
44
|
+
ProxyRegistrationCommand,
|
45
|
+
EchoCommand,
|
46
|
+
RoleTestCommand
|
47
|
+
]
|
48
|
+
|
49
|
+
registered_count = 0
|
50
|
+
|
51
|
+
for command_class in builtin_commands:
|
52
|
+
try:
|
53
|
+
# Get command name for logging
|
54
|
+
command_name = getattr(command_class, 'name', command_class.__name__.lower())
|
55
|
+
if command_name.endswith('command'):
|
56
|
+
command_name = command_name[:-7]
|
57
|
+
|
58
|
+
# Check if command already exists (should not happen for built-in)
|
59
|
+
if registry.command_exists(command_name):
|
60
|
+
logger.warning(f"Built-in command '{command_name}' already exists, skipping")
|
61
|
+
continue
|
62
|
+
|
63
|
+
# Register the command
|
64
|
+
registry.register_builtin(command_class)
|
65
|
+
registered_count += 1
|
66
|
+
logger.debug(f"Registered built-in command: {command_name}")
|
67
|
+
|
68
|
+
except Exception as e:
|
69
|
+
logger.error(f"Failed to register built-in command {command_class.__name__}: {e}")
|
70
|
+
|
71
|
+
logger.info(f"Registered {registered_count} built-in framework commands")
|
72
|
+
return registered_count
|
73
|
+
|
74
|
+
|
75
|
+
def get_builtin_commands_list() -> list:
|
76
|
+
"""
|
77
|
+
Get list of all built-in command classes.
|
78
|
+
|
79
|
+
Returns:
|
80
|
+
List of built-in command classes.
|
81
|
+
"""
|
82
|
+
return [
|
83
|
+
HelpCommand,
|
84
|
+
HealthCommand,
|
85
|
+
ConfigCommand,
|
86
|
+
ReloadCommand,
|
87
|
+
SettingsCommand,
|
88
|
+
LoadCommand,
|
89
|
+
UnloadCommand,
|
90
|
+
PluginsCommand,
|
91
|
+
TransportManagementCommand,
|
92
|
+
ProxyRegistrationCommand,
|
93
|
+
EchoCommand,
|
94
|
+
RoleTestCommand
|
95
|
+
]
|