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.
Files changed (200) hide show
  1. mcp_proxy_adapter/__main__.py +32 -0
  2. mcp_proxy_adapter/api/app.py +290 -33
  3. mcp_proxy_adapter/api/handlers.py +32 -6
  4. mcp_proxy_adapter/api/middleware/__init__.py +38 -32
  5. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
  6. mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
  7. mcp_proxy_adapter/api/middleware/factory.py +243 -0
  8. mcp_proxy_adapter/api/middleware/logging.py +32 -6
  9. mcp_proxy_adapter/api/middleware/protocol_middleware.py +201 -0
  10. mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
  11. mcp_proxy_adapter/api/middleware/unified_security.py +197 -0
  12. mcp_proxy_adapter/api/middleware/user_info_middleware.py +158 -0
  13. mcp_proxy_adapter/commands/__init__.py +19 -4
  14. mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
  15. mcp_proxy_adapter/commands/base.py +66 -32
  16. mcp_proxy_adapter/commands/builtin_commands.py +95 -0
  17. mcp_proxy_adapter/commands/catalog_manager.py +838 -0
  18. mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
  19. mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
  20. mcp_proxy_adapter/commands/command_registry.py +711 -354
  21. mcp_proxy_adapter/commands/dependency_manager.py +245 -0
  22. mcp_proxy_adapter/commands/echo_command.py +81 -0
  23. mcp_proxy_adapter/commands/health_command.py +8 -1
  24. mcp_proxy_adapter/commands/help_command.py +21 -14
  25. mcp_proxy_adapter/commands/hooks.py +200 -167
  26. mcp_proxy_adapter/commands/key_management_command.py +506 -0
  27. mcp_proxy_adapter/commands/load_command.py +176 -0
  28. mcp_proxy_adapter/commands/plugins_command.py +235 -0
  29. mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
  30. mcp_proxy_adapter/commands/proxy_registration_command.py +409 -0
  31. mcp_proxy_adapter/commands/reload_command.py +48 -50
  32. mcp_proxy_adapter/commands/result.py +1 -0
  33. mcp_proxy_adapter/commands/role_test_command.py +141 -0
  34. mcp_proxy_adapter/commands/roles_management_command.py +697 -0
  35. mcp_proxy_adapter/commands/security_command.py +488 -0
  36. mcp_proxy_adapter/commands/ssl_setup_command.py +366 -0
  37. mcp_proxy_adapter/commands/token_management_command.py +529 -0
  38. mcp_proxy_adapter/commands/transport_management_command.py +144 -0
  39. mcp_proxy_adapter/commands/unload_command.py +158 -0
  40. mcp_proxy_adapter/config.py +394 -14
  41. mcp_proxy_adapter/core/app_factory.py +410 -0
  42. mcp_proxy_adapter/core/app_runner.py +272 -0
  43. mcp_proxy_adapter/core/auth_validator.py +606 -0
  44. mcp_proxy_adapter/core/certificate_utils.py +1045 -0
  45. mcp_proxy_adapter/core/client.py +574 -0
  46. mcp_proxy_adapter/core/client_manager.py +284 -0
  47. mcp_proxy_adapter/core/client_security.py +384 -0
  48. mcp_proxy_adapter/core/config_converter.py +405 -0
  49. mcp_proxy_adapter/core/config_validator.py +218 -0
  50. mcp_proxy_adapter/core/logging.py +19 -3
  51. mcp_proxy_adapter/core/mtls_asgi.py +156 -0
  52. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  53. mcp_proxy_adapter/core/protocol_manager.py +385 -0
  54. mcp_proxy_adapter/core/proxy_client.py +602 -0
  55. mcp_proxy_adapter/core/proxy_registration.py +522 -0
  56. mcp_proxy_adapter/core/role_utils.py +426 -0
  57. mcp_proxy_adapter/core/security_adapter.py +370 -0
  58. mcp_proxy_adapter/core/security_factory.py +239 -0
  59. mcp_proxy_adapter/core/security_integration.py +286 -0
  60. mcp_proxy_adapter/core/server_adapter.py +282 -0
  61. mcp_proxy_adapter/core/server_engine.py +270 -0
  62. mcp_proxy_adapter/core/settings.py +1 -0
  63. mcp_proxy_adapter/core/ssl_utils.py +234 -0
  64. mcp_proxy_adapter/core/transport_manager.py +292 -0
  65. mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
  66. mcp_proxy_adapter/custom_openapi.py +22 -11
  67. mcp_proxy_adapter/examples/__init__.py +13 -4
  68. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  69. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  70. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  71. mcp_proxy_adapter/examples/basic_framework/main.py +44 -0
  72. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  73. mcp_proxy_adapter/examples/create_certificates_simple.py +550 -0
  74. mcp_proxy_adapter/examples/debug_request_state.py +112 -0
  75. mcp_proxy_adapter/examples/debug_role_chain.py +158 -0
  76. mcp_proxy_adapter/examples/demo_client.py +275 -0
  77. mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
  78. mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
  79. mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
  80. mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
  81. mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
  82. mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
  83. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
  84. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  85. mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
  86. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
  87. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  88. mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
  89. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
  90. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  91. mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
  92. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +80 -0
  93. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  94. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
  95. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +75 -0
  96. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  97. mcp_proxy_adapter/examples/full_application/main.py +173 -0
  98. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
  99. mcp_proxy_adapter/examples/generate_all_certificates.py +362 -0
  100. mcp_proxy_adapter/examples/generate_certificates.py +177 -0
  101. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
  102. mcp_proxy_adapter/examples/generate_test_configs.py +331 -0
  103. mcp_proxy_adapter/examples/proxy_registration_example.py +334 -0
  104. mcp_proxy_adapter/examples/run_example.py +59 -0
  105. mcp_proxy_adapter/examples/run_full_test_suite.py +318 -0
  106. mcp_proxy_adapter/examples/run_proxy_server.py +146 -0
  107. mcp_proxy_adapter/examples/run_security_tests.py +544 -0
  108. mcp_proxy_adapter/examples/run_security_tests_fixed.py +247 -0
  109. mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
  110. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
  111. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
  112. mcp_proxy_adapter/examples/security_test_client.py +782 -0
  113. mcp_proxy_adapter/examples/setup_test_environment.py +328 -0
  114. mcp_proxy_adapter/examples/test_config.py +148 -0
  115. mcp_proxy_adapter/examples/test_config_generator.py +86 -0
  116. mcp_proxy_adapter/examples/test_examples.py +281 -0
  117. mcp_proxy_adapter/examples/universal_client.py +620 -0
  118. mcp_proxy_adapter/main.py +93 -0
  119. mcp_proxy_adapter/utils/config_generator.py +1008 -0
  120. mcp_proxy_adapter/version.py +5 -2
  121. mcp_proxy_adapter-6.0.1.dist-info/METADATA +679 -0
  122. mcp_proxy_adapter-6.0.1.dist-info/RECORD +140 -0
  123. mcp_proxy_adapter-6.0.1.dist-info/entry_points.txt +2 -0
  124. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/licenses/LICENSE +2 -2
  125. mcp_proxy_adapter/api/middleware/auth.py +0 -146
  126. mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
  127. mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
  128. mcp_proxy_adapter/examples/README.md +0 -124
  129. mcp_proxy_adapter/examples/basic_server/README.md +0 -60
  130. mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
  131. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
  132. mcp_proxy_adapter/examples/basic_server/config.json +0 -35
  133. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
  134. mcp_proxy_adapter/examples/basic_server/server.py +0 -103
  135. mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
  136. mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
  137. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -250
  138. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
  139. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
  140. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
  141. mcp_proxy_adapter/examples/custom_commands/config.json +0 -35
  142. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
  143. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
  144. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
  145. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
  146. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
  147. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
  148. mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
  149. mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
  150. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
  151. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
  152. mcp_proxy_adapter/examples/custom_commands/server.py +0 -228
  153. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
  154. mcp_proxy_adapter/examples/deployment/README.md +0 -49
  155. mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
  156. mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
  157. mcp_proxy_adapter/examples/deployment/config.json +0 -29
  158. mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
  159. mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
  160. mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
  161. mcp_proxy_adapter/examples/deployment/run.sh +0 -43
  162. mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
  163. mcp_proxy_adapter/schemas/base_schema.json +0 -114
  164. mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
  165. mcp_proxy_adapter/tests/__init__.py +0 -0
  166. mcp_proxy_adapter/tests/api/__init__.py +0 -3
  167. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
  168. mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
  169. mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
  170. mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
  171. mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
  172. mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
  173. mcp_proxy_adapter/tests/commands/__init__.py +0 -3
  174. mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
  175. mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
  176. mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
  177. mcp_proxy_adapter/tests/conftest.py +0 -131
  178. mcp_proxy_adapter/tests/functional/__init__.py +0 -3
  179. mcp_proxy_adapter/tests/functional/test_api.py +0 -253
  180. mcp_proxy_adapter/tests/integration/__init__.py +0 -3
  181. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
  182. mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
  183. mcp_proxy_adapter/tests/performance/__init__.py +0 -3
  184. mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
  185. mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
  186. mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
  187. mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
  188. mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
  189. mcp_proxy_adapter/tests/test_base_command.py +0 -123
  190. mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
  191. mcp_proxy_adapter/tests/test_command_registry.py +0 -281
  192. mcp_proxy_adapter/tests/test_config.py +0 -127
  193. mcp_proxy_adapter/tests/test_utils.py +0 -65
  194. mcp_proxy_adapter/tests/unit/__init__.py +0 -3
  195. mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
  196. mcp_proxy_adapter/tests/unit/test_config.py +0 -217
  197. mcp_proxy_adapter-4.1.1.dist-info/METADATA +0 -200
  198. mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
  199. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/WHEEL +0 -0
  200. {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
- @classmethod
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
- priority_command_class = registry.get_priority_command(command_name)
151
- if priority_command_class is None:
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
- # Check if we have a registered instance for this command
155
- if registry.has_instance(command_name):
156
- # Use existing instance with dependencies
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 after hooks
165
- hooks.execute_after_hooks(command_name, validated_params, result)
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
+ ]