mcp-proxy-adapter 6.3.4__py3-none-any.whl → 6.3.5__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/__init__.py +9 -5
- mcp_proxy_adapter/__main__.py +1 -1
- mcp_proxy_adapter/api/app.py +227 -176
- mcp_proxy_adapter/api/handlers.py +68 -60
- mcp_proxy_adapter/api/middleware/__init__.py +7 -5
- mcp_proxy_adapter/api/middleware/base.py +19 -16
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
- mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
- mcp_proxy_adapter/api/middleware/factory.py +50 -52
- mcp_proxy_adapter/api/middleware/logging.py +46 -30
- mcp_proxy_adapter/api/middleware/performance.py +19 -16
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
- mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
- mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
- mcp_proxy_adapter/api/schemas.py +69 -43
- mcp_proxy_adapter/api/tool_integration.py +83 -63
- mcp_proxy_adapter/api/tools.py +60 -50
- mcp_proxy_adapter/commands/__init__.py +15 -6
- mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
- mcp_proxy_adapter/commands/base.py +108 -112
- mcp_proxy_adapter/commands/builtin_commands.py +28 -18
- mcp_proxy_adapter/commands/catalog_manager.py +394 -265
- mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
- mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
- mcp_proxy_adapter/commands/command_registry.py +275 -226
- mcp_proxy_adapter/commands/config_command.py +48 -33
- mcp_proxy_adapter/commands/dependency_container.py +22 -23
- mcp_proxy_adapter/commands/dependency_manager.py +65 -56
- mcp_proxy_adapter/commands/echo_command.py +15 -15
- mcp_proxy_adapter/commands/health_command.py +31 -29
- mcp_proxy_adapter/commands/help_command.py +97 -61
- mcp_proxy_adapter/commands/hooks.py +65 -49
- mcp_proxy_adapter/commands/key_management_command.py +148 -147
- mcp_proxy_adapter/commands/load_command.py +58 -40
- mcp_proxy_adapter/commands/plugins_command.py +80 -54
- mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
- mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
- mcp_proxy_adapter/commands/reload_command.py +43 -37
- mcp_proxy_adapter/commands/result.py +26 -33
- mcp_proxy_adapter/commands/role_test_command.py +26 -26
- mcp_proxy_adapter/commands/roles_management_command.py +176 -173
- mcp_proxy_adapter/commands/security_command.py +134 -122
- mcp_proxy_adapter/commands/settings_command.py +47 -56
- mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
- mcp_proxy_adapter/commands/token_management_command.py +129 -158
- mcp_proxy_adapter/commands/transport_management_command.py +41 -36
- mcp_proxy_adapter/commands/unload_command.py +42 -37
- mcp_proxy_adapter/config.py +36 -35
- mcp_proxy_adapter/core/__init__.py +19 -21
- mcp_proxy_adapter/core/app_factory.py +30 -9
- mcp_proxy_adapter/core/app_runner.py +81 -64
- mcp_proxy_adapter/core/auth_validator.py +176 -182
- mcp_proxy_adapter/core/certificate_utils.py +469 -426
- mcp_proxy_adapter/core/client.py +155 -126
- mcp_proxy_adapter/core/client_manager.py +60 -54
- mcp_proxy_adapter/core/client_security.py +108 -88
- mcp_proxy_adapter/core/config_converter.py +176 -143
- mcp_proxy_adapter/core/config_validator.py +12 -4
- mcp_proxy_adapter/core/crl_utils.py +21 -7
- mcp_proxy_adapter/core/errors.py +64 -20
- mcp_proxy_adapter/core/logging.py +34 -29
- mcp_proxy_adapter/core/mtls_asgi.py +29 -25
- mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
- mcp_proxy_adapter/core/protocol_manager.py +154 -104
- mcp_proxy_adapter/core/proxy_client.py +202 -144
- mcp_proxy_adapter/core/proxy_registration.py +7 -3
- mcp_proxy_adapter/core/role_utils.py +139 -125
- mcp_proxy_adapter/core/security_adapter.py +88 -77
- mcp_proxy_adapter/core/security_factory.py +50 -44
- mcp_proxy_adapter/core/security_integration.py +72 -24
- mcp_proxy_adapter/core/server_adapter.py +68 -64
- mcp_proxy_adapter/core/server_engine.py +71 -53
- mcp_proxy_adapter/core/settings.py +68 -58
- mcp_proxy_adapter/core/ssl_utils.py +69 -56
- mcp_proxy_adapter/core/transport_manager.py +72 -60
- mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
- mcp_proxy_adapter/core/utils.py +4 -2
- mcp_proxy_adapter/custom_openapi.py +107 -99
- mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/commands/__init__.py +1 -1
- mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
- mcp_proxy_adapter/examples/debug_request_state.py +38 -19
- mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
- mcp_proxy_adapter/examples/demo_client.py +48 -36
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
- mcp_proxy_adapter/examples/generate_certificates.py +31 -16
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
- mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
- mcp_proxy_adapter/examples/run_example.py +23 -5
- mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
- mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
- mcp_proxy_adapter/examples/run_security_tests.py +103 -41
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
- mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/security_test_client.py +196 -127
- mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
- mcp_proxy_adapter/examples/test_config.py +19 -4
- mcp_proxy_adapter/examples/test_config_generator.py +23 -7
- mcp_proxy_adapter/examples/test_examples.py +84 -56
- mcp_proxy_adapter/examples/universal_client.py +119 -62
- mcp_proxy_adapter/openapi.py +108 -115
- mcp_proxy_adapter/utils/config_generator.py +429 -274
- mcp_proxy_adapter/version.py +1 -2
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
- mcp_proxy_adapter-6.3.4.dist-info/RECORD +0 -143
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -10,7 +10,11 @@ from docstring_parser import parse
|
|
10
10
|
|
11
11
|
from mcp_proxy_adapter.commands.result import CommandResult, SuccessResult, ErrorResult
|
12
12
|
from mcp_proxy_adapter.core.errors import (
|
13
|
-
CommandError,
|
13
|
+
CommandError,
|
14
|
+
InternalError,
|
15
|
+
InvalidParamsError,
|
16
|
+
NotFoundError,
|
17
|
+
ValidationError,
|
14
18
|
)
|
15
19
|
from mcp_proxy_adapter.core.logging import logger
|
16
20
|
|
@@ -22,7 +26,7 @@ class Command(ABC):
|
|
22
26
|
"""
|
23
27
|
Base abstract class for all commands.
|
24
28
|
"""
|
25
|
-
|
29
|
+
|
26
30
|
# Command name for registration
|
27
31
|
name: ClassVar[str]
|
28
32
|
# Command version (default: 0.1)
|
@@ -41,112 +45,114 @@ class Command(ABC):
|
|
41
45
|
source_url: ClassVar[str] = ""
|
42
46
|
# Result class
|
43
47
|
result_class: ClassVar[Type[CommandResult]]
|
44
|
-
|
48
|
+
|
45
49
|
@abstractmethod
|
46
50
|
async def execute(self, **kwargs) -> CommandResult:
|
47
51
|
"""
|
48
52
|
Execute command with the specified parameters.
|
49
|
-
|
53
|
+
|
50
54
|
Args:
|
51
55
|
**kwargs: Command parameters including optional 'context' parameter.
|
52
|
-
|
56
|
+
|
53
57
|
Returns:
|
54
58
|
Command result.
|
55
59
|
"""
|
56
60
|
pass
|
57
|
-
|
61
|
+
|
58
62
|
@classmethod
|
59
63
|
def get_schema(cls) -> Dict[str, Any]:
|
60
64
|
"""
|
61
65
|
Get JSON schema for command parameters.
|
62
|
-
|
66
|
+
|
63
67
|
Returns:
|
64
68
|
JSON schema.
|
65
69
|
"""
|
66
|
-
return {
|
67
|
-
|
68
|
-
"properties": {},
|
69
|
-
"additionalProperties": False
|
70
|
-
}
|
71
|
-
|
70
|
+
return {"type": "object", "properties": {}, "additionalProperties": False}
|
71
|
+
|
72
72
|
@classmethod
|
73
73
|
def get_result_schema(cls) -> Dict[str, Any]:
|
74
74
|
"""
|
75
75
|
Get JSON schema for command result.
|
76
|
-
|
76
|
+
|
77
77
|
Returns:
|
78
78
|
JSON schema.
|
79
79
|
"""
|
80
80
|
if hasattr(cls, "result_class") and cls.result_class:
|
81
81
|
return cls.result_class.get_schema()
|
82
82
|
return {}
|
83
|
-
|
83
|
+
|
84
84
|
def validate_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
85
85
|
"""
|
86
86
|
Validate command parameters.
|
87
|
-
|
87
|
+
|
88
88
|
Args:
|
89
89
|
params: Parameters to validate.
|
90
|
-
|
90
|
+
|
91
91
|
Returns:
|
92
92
|
Validated parameters.
|
93
|
-
|
93
|
+
|
94
94
|
Raises:
|
95
95
|
ValidationError: If parameters are invalid.
|
96
96
|
"""
|
97
97
|
# Ensure params is a dictionary, even if None was passed
|
98
98
|
if params is None:
|
99
99
|
params = {}
|
100
|
-
|
100
|
+
|
101
101
|
# Create a copy to avoid modifying the input dictionary during iteration
|
102
102
|
validated_params = params.copy()
|
103
|
-
|
103
|
+
|
104
104
|
# Handle None values and empty strings in parameters
|
105
105
|
for key, value in list(validated_params.items()):
|
106
106
|
# Process None values or empty strings - this helps with JavaScript null/undefined conversions
|
107
|
-
if value is None or (
|
107
|
+
if value is None or (
|
108
|
+
isinstance(value, str) and value.lower() in ["null", "none", ""]
|
109
|
+
):
|
108
110
|
# For commands that specifically handle None values, keep the parameter
|
109
111
|
# (like help), keep the parameter but ensure it's a proper Python None
|
110
|
-
if key in [
|
112
|
+
if key in [
|
113
|
+
"cmdname"
|
114
|
+
]: # список параметров, для которых None является допустимым значением
|
111
115
|
validated_params[key] = None
|
112
116
|
else:
|
113
117
|
# For most parameters, remove None values to avoid issues
|
114
118
|
del validated_params[key]
|
115
|
-
|
119
|
+
|
116
120
|
# Get command schema to validate parameters
|
117
121
|
schema = self.get_schema()
|
118
122
|
if schema and "properties" in schema:
|
119
123
|
allowed_properties = schema["properties"].keys()
|
120
|
-
|
124
|
+
|
121
125
|
# Filter out parameters that are not in the schema
|
122
126
|
invalid_params = []
|
123
127
|
for param_name in list(validated_params.keys()):
|
124
128
|
if param_name not in allowed_properties:
|
125
129
|
invalid_params.append(param_name)
|
126
130
|
del validated_params[param_name]
|
127
|
-
|
131
|
+
|
128
132
|
# Log warning about invalid parameters
|
129
133
|
if invalid_params:
|
130
|
-
logger.warning(
|
131
|
-
|
132
|
-
|
134
|
+
logger.warning(
|
135
|
+
f"Command {self.__class__.__name__} received invalid parameters: {invalid_params}. "
|
136
|
+
f"Allowed parameters: {list(allowed_properties)}"
|
137
|
+
)
|
138
|
+
|
133
139
|
# Validate required parameters based on command schema
|
134
140
|
if schema and "required" in schema:
|
135
141
|
required_params = schema["required"]
|
136
142
|
missing_params = []
|
137
|
-
|
143
|
+
|
138
144
|
for param in required_params:
|
139
145
|
if param not in validated_params:
|
140
146
|
missing_params.append(param)
|
141
|
-
|
147
|
+
|
142
148
|
if missing_params:
|
143
149
|
raise ValidationError(
|
144
150
|
f"Missing required parameters: {', '.join(missing_params)}",
|
145
|
-
data={"missing_parameters": missing_params}
|
151
|
+
data={"missing_parameters": missing_params},
|
146
152
|
)
|
147
|
-
|
153
|
+
|
148
154
|
return validated_params
|
149
|
-
|
155
|
+
|
150
156
|
@classmethod
|
151
157
|
async def run(cls, **kwargs) -> CommandResult:
|
152
158
|
"""
|
@@ -159,14 +165,14 @@ class Command(ABC):
|
|
159
165
|
Command result.
|
160
166
|
"""
|
161
167
|
# Extract context from kwargs
|
162
|
-
context = kwargs.pop(
|
163
|
-
|
168
|
+
context = kwargs.pop("context", {}) if "context" in kwargs else {}
|
169
|
+
|
164
170
|
try:
|
165
171
|
logger.debug(f"Running command {cls.__name__} with params: {kwargs}")
|
166
|
-
|
172
|
+
|
167
173
|
# Import registry here to avoid circular imports
|
168
174
|
from mcp_proxy_adapter.commands.command_registry import registry
|
169
|
-
|
175
|
+
|
170
176
|
# Get command name
|
171
177
|
if not hasattr(cls, "name") or not cls.name:
|
172
178
|
command_name = cls.__name__.lower()
|
@@ -174,65 +180,45 @@ class Command(ABC):
|
|
174
180
|
command_name = command_name[:-7]
|
175
181
|
else:
|
176
182
|
command_name = cls.name
|
177
|
-
|
183
|
+
|
178
184
|
# Ensure kwargs is never None
|
179
185
|
if kwargs is None:
|
180
186
|
kwargs = {}
|
181
|
-
|
187
|
+
|
182
188
|
# Get command with priority (custom commands first, then built-in)
|
183
189
|
command_class = registry.get_command(command_name)
|
184
190
|
if command_class is None:
|
185
191
|
raise NotFoundError(f"Command '{command_name}' not found")
|
186
|
-
|
192
|
+
|
187
193
|
# Create new instance and validate parameters
|
188
194
|
command = command_class()
|
189
195
|
validated_params = command.validate_params(kwargs)
|
190
|
-
|
196
|
+
|
191
197
|
# Execute command with validated parameters and context
|
192
198
|
result = await command.execute(**validated_params, context=context)
|
193
|
-
|
199
|
+
|
194
200
|
logger.debug(f"Command {cls.__name__} executed successfully")
|
195
201
|
return result
|
196
202
|
except ValidationError as e:
|
197
203
|
# Ошибка валидации параметров
|
198
204
|
logger.error(f"Validation error in command {cls.__name__}: {e}")
|
199
|
-
return ErrorResult(
|
200
|
-
message=str(e),
|
201
|
-
code=e.code,
|
202
|
-
details=e.data
|
203
|
-
)
|
205
|
+
return ErrorResult(message=str(e), code=e.code, details=e.data)
|
204
206
|
except InvalidParamsError as e:
|
205
207
|
# Ошибка в параметрах команды
|
206
208
|
logger.error(f"Invalid parameters error in command {cls.__name__}: {e}")
|
207
|
-
return ErrorResult(
|
208
|
-
message=str(e),
|
209
|
-
code=e.code,
|
210
|
-
details=e.data
|
211
|
-
)
|
209
|
+
return ErrorResult(message=str(e), code=e.code, details=e.data)
|
212
210
|
except NotFoundError as e:
|
213
211
|
# Ресурс не найден
|
214
212
|
logger.error(f"Resource not found error in command {cls.__name__}: {e}")
|
215
|
-
return ErrorResult(
|
216
|
-
message=str(e),
|
217
|
-
code=e.code,
|
218
|
-
details=e.data
|
219
|
-
)
|
213
|
+
return ErrorResult(message=str(e), code=e.code, details=e.data)
|
220
214
|
except TimeoutError as e:
|
221
215
|
# Превышено время ожидания
|
222
216
|
logger.error(f"Timeout error in command {cls.__name__}: {e}")
|
223
|
-
return ErrorResult(
|
224
|
-
message=str(e),
|
225
|
-
code=e.code,
|
226
|
-
details=e.data
|
227
|
-
)
|
217
|
+
return ErrorResult(message=str(e), code=e.code, details=e.data)
|
228
218
|
except CommandError as e:
|
229
219
|
# Ошибка выполнения команды
|
230
220
|
logger.error(f"Command error in {cls.__name__}: {e}")
|
231
|
-
return ErrorResult(
|
232
|
-
message=str(e),
|
233
|
-
code=e.code,
|
234
|
-
details=e.data
|
235
|
-
)
|
221
|
+
return ErrorResult(message=str(e), code=e.code, details=e.data)
|
236
222
|
except Exception as e:
|
237
223
|
# Непредвиденная ошибка
|
238
224
|
logger.exception(f"Unexpected error executing command {cls.__name__}: {e}")
|
@@ -240,9 +226,9 @@ class Command(ABC):
|
|
240
226
|
return ErrorResult(
|
241
227
|
message=internal_error.message,
|
242
228
|
code=internal_error.code,
|
243
|
-
details={"original_error": str(e)}
|
229
|
+
details={"original_error": str(e)},
|
244
230
|
)
|
245
|
-
|
231
|
+
|
246
232
|
@classmethod
|
247
233
|
def get_param_info(cls) -> Dict[str, Dict[str, Any]]:
|
248
234
|
"""
|
@@ -253,49 +239,49 @@ class Command(ABC):
|
|
253
239
|
"""
|
254
240
|
signature = inspect.signature(cls.execute)
|
255
241
|
params = {}
|
256
|
-
|
242
|
+
|
257
243
|
for name, param in signature.parameters.items():
|
258
244
|
if name == "self":
|
259
245
|
continue
|
260
|
-
|
246
|
+
|
261
247
|
param_info = {
|
262
248
|
"name": name,
|
263
|
-
"required": param.default == inspect.Parameter.empty
|
249
|
+
"required": param.default == inspect.Parameter.empty,
|
264
250
|
}
|
265
|
-
|
251
|
+
|
266
252
|
if param.annotation != inspect.Parameter.empty:
|
267
253
|
param_info["type"] = str(param.annotation)
|
268
|
-
|
254
|
+
|
269
255
|
if param.default != inspect.Parameter.empty:
|
270
256
|
param_info["default"] = param.default
|
271
|
-
|
257
|
+
|
272
258
|
params[name] = param_info
|
273
|
-
|
259
|
+
|
274
260
|
return params
|
275
|
-
|
261
|
+
|
276
262
|
@classmethod
|
277
263
|
def get_metadata(cls) -> Dict[str, Any]:
|
278
264
|
"""
|
279
265
|
Returns complete metadata about the command.
|
280
|
-
|
266
|
+
|
281
267
|
Provides a single access point to all command metadata.
|
282
|
-
|
268
|
+
|
283
269
|
Returns:
|
284
270
|
Dict with command metadata
|
285
271
|
"""
|
286
272
|
# Get and format docstring
|
287
273
|
doc = cls.__doc__ or ""
|
288
274
|
description = inspect.cleandoc(doc) if doc else ""
|
289
|
-
|
275
|
+
|
290
276
|
# Extract first line for summary
|
291
277
|
summary = description.split("\n")[0] if description else ""
|
292
|
-
|
278
|
+
|
293
279
|
# Get parameters information
|
294
280
|
param_info = cls.get_param_info()
|
295
|
-
|
281
|
+
|
296
282
|
# Generate examples based on parameters
|
297
283
|
examples = cls._generate_examples(param_info)
|
298
|
-
|
284
|
+
|
299
285
|
return {
|
300
286
|
"name": cls.name,
|
301
287
|
"version": cls.version,
|
@@ -311,29 +297,35 @@ class Command(ABC):
|
|
311
297
|
"examples": examples,
|
312
298
|
"schema": cls.get_schema(),
|
313
299
|
"result_schema": cls.get_result_schema(),
|
314
|
-
"result_class":
|
300
|
+
"result_class": (
|
301
|
+
cls.result_class.__name__ if hasattr(cls, "result_class") else None
|
302
|
+
),
|
315
303
|
}
|
316
|
-
|
304
|
+
|
317
305
|
@classmethod
|
318
|
-
def _generate_examples(
|
306
|
+
def _generate_examples(
|
307
|
+
cls, params: Dict[str, Dict[str, Any]]
|
308
|
+
) -> List[Dict[str, Any]]:
|
319
309
|
"""
|
320
310
|
Generates usage examples of the command based on its parameters.
|
321
|
-
|
311
|
+
|
322
312
|
Args:
|
323
313
|
params: Information about command parameters
|
324
|
-
|
314
|
+
|
325
315
|
Returns:
|
326
316
|
List of examples
|
327
317
|
"""
|
328
318
|
examples = []
|
329
|
-
|
319
|
+
|
330
320
|
# Simple example without parameters, if all parameters are optional
|
331
321
|
if not any(param.get("required", False) for param in params.values()):
|
332
|
-
examples.append(
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
322
|
+
examples.append(
|
323
|
+
{
|
324
|
+
"command": cls.name,
|
325
|
+
"description": f"Call {cls.name} command without parameters",
|
326
|
+
}
|
327
|
+
)
|
328
|
+
|
337
329
|
# Example with all required parameters
|
338
330
|
required_params = {k: v for k, v in params.items() if v.get("required", False)}
|
339
331
|
if required_params:
|
@@ -341,7 +333,7 @@ class Command(ABC):
|
|
341
333
|
for param_name, param_info in required_params.items():
|
342
334
|
# Try to generate sample value based on type
|
343
335
|
param_type = param_info.get("type", "")
|
344
|
-
|
336
|
+
|
345
337
|
if "str" in param_type:
|
346
338
|
sample_params[param_name] = f"sample_{param_name}"
|
347
339
|
elif "int" in param_type:
|
@@ -356,13 +348,15 @@ class Command(ABC):
|
|
356
348
|
sample_params[param_name] = {}
|
357
349
|
else:
|
358
350
|
sample_params[param_name] = "..."
|
359
|
-
|
360
|
-
examples.append(
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
351
|
+
|
352
|
+
examples.append(
|
353
|
+
{
|
354
|
+
"command": cls.name,
|
355
|
+
"params": sample_params,
|
356
|
+
"description": f"Call {cls.name} command with required parameters",
|
357
|
+
}
|
358
|
+
)
|
359
|
+
|
366
360
|
# Example with all parameters (including optional ones)
|
367
361
|
if len(params) > len(required_params):
|
368
362
|
all_params = {}
|
@@ -371,7 +365,7 @@ class Command(ABC):
|
|
371
365
|
if param_info.get("required", False):
|
372
366
|
# Try to generate sample value based on type
|
373
367
|
param_type = param_info.get("type", "")
|
374
|
-
|
368
|
+
|
375
369
|
if "str" in param_type:
|
376
370
|
all_params[param_name] = f"sample_{param_name}"
|
377
371
|
elif "int" in param_type:
|
@@ -392,7 +386,7 @@ class Command(ABC):
|
|
392
386
|
all_params[param_name] = param_info["default"]
|
393
387
|
else:
|
394
388
|
param_type = param_info.get("type", "")
|
395
|
-
|
389
|
+
|
396
390
|
if "str" in param_type:
|
397
391
|
all_params[param_name] = f"optional_{param_name}"
|
398
392
|
elif "int" in param_type:
|
@@ -407,11 +401,13 @@ class Command(ABC):
|
|
407
401
|
all_params[param_name] = {}
|
408
402
|
else:
|
409
403
|
all_params[param_name] = None
|
410
|
-
|
411
|
-
examples.append(
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
404
|
+
|
405
|
+
examples.append(
|
406
|
+
{
|
407
|
+
"command": cls.name,
|
408
|
+
"params": all_params,
|
409
|
+
"description": f"Call {cls.name} command with all parameters",
|
410
|
+
}
|
411
|
+
)
|
412
|
+
|
413
|
+
return examples
|
@@ -15,8 +15,12 @@ from mcp_proxy_adapter.commands.settings_command import SettingsCommand
|
|
15
15
|
from mcp_proxy_adapter.commands.load_command import LoadCommand
|
16
16
|
from mcp_proxy_adapter.commands.unload_command import UnloadCommand
|
17
17
|
from mcp_proxy_adapter.commands.plugins_command import PluginsCommand
|
18
|
-
from mcp_proxy_adapter.commands.transport_management_command import
|
19
|
-
|
18
|
+
from mcp_proxy_adapter.commands.transport_management_command import (
|
19
|
+
TransportManagementCommand,
|
20
|
+
)
|
21
|
+
from mcp_proxy_adapter.commands.proxy_registration_command import (
|
22
|
+
ProxyRegistrationCommand,
|
23
|
+
)
|
20
24
|
from mcp_proxy_adapter.commands.echo_command import EchoCommand
|
21
25
|
from mcp_proxy_adapter.commands.role_test_command import RoleTestCommand
|
22
26
|
from mcp_proxy_adapter.core.logging import logger
|
@@ -25,12 +29,12 @@ from mcp_proxy_adapter.core.logging import logger
|
|
25
29
|
def register_builtin_commands() -> int:
|
26
30
|
"""
|
27
31
|
Register all built-in framework commands.
|
28
|
-
|
32
|
+
|
29
33
|
Returns:
|
30
34
|
Number of built-in commands registered.
|
31
35
|
"""
|
32
36
|
logger.debug("Registering built-in framework commands...")
|
33
|
-
|
37
|
+
|
34
38
|
builtin_commands = [
|
35
39
|
HelpCommand,
|
36
40
|
HealthCommand,
|
@@ -43,31 +47,37 @@ def register_builtin_commands() -> int:
|
|
43
47
|
TransportManagementCommand,
|
44
48
|
ProxyRegistrationCommand,
|
45
49
|
EchoCommand,
|
46
|
-
RoleTestCommand
|
50
|
+
RoleTestCommand,
|
47
51
|
]
|
48
|
-
|
52
|
+
|
49
53
|
registered_count = 0
|
50
|
-
|
54
|
+
|
51
55
|
for command_class in builtin_commands:
|
52
56
|
try:
|
53
57
|
# Get command name for logging
|
54
|
-
command_name = getattr(
|
55
|
-
|
58
|
+
command_name = getattr(
|
59
|
+
command_class, "name", command_class.__name__.lower()
|
60
|
+
)
|
61
|
+
if command_name.endswith("command"):
|
56
62
|
command_name = command_name[:-7]
|
57
|
-
|
63
|
+
|
58
64
|
# Check if command already exists (should not happen for built-in)
|
59
65
|
if registry.command_exists(command_name):
|
60
|
-
logger.warning(
|
66
|
+
logger.warning(
|
67
|
+
f"Built-in command '{command_name}' already exists, skipping"
|
68
|
+
)
|
61
69
|
continue
|
62
|
-
|
70
|
+
|
63
71
|
# Register the command
|
64
72
|
registry.register_builtin(command_class)
|
65
73
|
registered_count += 1
|
66
74
|
logger.debug(f"Registered built-in command: {command_name}")
|
67
|
-
|
75
|
+
|
68
76
|
except Exception as e:
|
69
|
-
logger.error(
|
70
|
-
|
77
|
+
logger.error(
|
78
|
+
f"Failed to register built-in command {command_class.__name__}: {e}"
|
79
|
+
)
|
80
|
+
|
71
81
|
logger.info(f"Registered {registered_count} built-in framework commands")
|
72
82
|
return registered_count
|
73
83
|
|
@@ -75,7 +85,7 @@ def register_builtin_commands() -> int:
|
|
75
85
|
def get_builtin_commands_list() -> list:
|
76
86
|
"""
|
77
87
|
Get list of all built-in command classes.
|
78
|
-
|
88
|
+
|
79
89
|
Returns:
|
80
90
|
List of built-in command classes.
|
81
91
|
"""
|
@@ -91,5 +101,5 @@ def get_builtin_commands_list() -> list:
|
|
91
101
|
TransportManagementCommand,
|
92
102
|
ProxyRegistrationCommand,
|
93
103
|
EchoCommand,
|
94
|
-
RoleTestCommand
|
95
|
-
]
|
104
|
+
RoleTestCommand,
|
105
|
+
]
|