mcp-proxy-adapter 6.3.4__py3-none-any.whl → 6.3.6__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 (131) hide show
  1. mcp_proxy_adapter/__init__.py +9 -5
  2. mcp_proxy_adapter/__main__.py +1 -1
  3. mcp_proxy_adapter/api/app.py +227 -176
  4. mcp_proxy_adapter/api/handlers.py +68 -60
  5. mcp_proxy_adapter/api/middleware/__init__.py +7 -5
  6. mcp_proxy_adapter/api/middleware/base.py +19 -16
  7. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
  8. mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
  9. mcp_proxy_adapter/api/middleware/factory.py +50 -52
  10. mcp_proxy_adapter/api/middleware/logging.py +46 -30
  11. mcp_proxy_adapter/api/middleware/performance.py +19 -16
  12. mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
  13. mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
  14. mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
  15. mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
  16. mcp_proxy_adapter/api/schemas.py +69 -43
  17. mcp_proxy_adapter/api/tool_integration.py +83 -63
  18. mcp_proxy_adapter/api/tools.py +60 -50
  19. mcp_proxy_adapter/commands/__init__.py +15 -6
  20. mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
  21. mcp_proxy_adapter/commands/base.py +108 -112
  22. mcp_proxy_adapter/commands/builtin_commands.py +28 -18
  23. mcp_proxy_adapter/commands/catalog_manager.py +394 -265
  24. mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
  25. mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
  26. mcp_proxy_adapter/commands/command_registry.py +275 -226
  27. mcp_proxy_adapter/commands/config_command.py +48 -33
  28. mcp_proxy_adapter/commands/dependency_container.py +22 -23
  29. mcp_proxy_adapter/commands/dependency_manager.py +65 -56
  30. mcp_proxy_adapter/commands/echo_command.py +15 -15
  31. mcp_proxy_adapter/commands/health_command.py +31 -29
  32. mcp_proxy_adapter/commands/help_command.py +97 -61
  33. mcp_proxy_adapter/commands/hooks.py +65 -49
  34. mcp_proxy_adapter/commands/key_management_command.py +148 -147
  35. mcp_proxy_adapter/commands/load_command.py +58 -40
  36. mcp_proxy_adapter/commands/plugins_command.py +80 -54
  37. mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
  38. mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
  39. mcp_proxy_adapter/commands/reload_command.py +43 -37
  40. mcp_proxy_adapter/commands/result.py +26 -33
  41. mcp_proxy_adapter/commands/role_test_command.py +26 -26
  42. mcp_proxy_adapter/commands/roles_management_command.py +176 -173
  43. mcp_proxy_adapter/commands/security_command.py +134 -122
  44. mcp_proxy_adapter/commands/settings_command.py +47 -56
  45. mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
  46. mcp_proxy_adapter/commands/token_management_command.py +129 -158
  47. mcp_proxy_adapter/commands/transport_management_command.py +41 -36
  48. mcp_proxy_adapter/commands/unload_command.py +42 -37
  49. mcp_proxy_adapter/config.py +36 -35
  50. mcp_proxy_adapter/core/__init__.py +19 -21
  51. mcp_proxy_adapter/core/app_factory.py +30 -9
  52. mcp_proxy_adapter/core/app_runner.py +81 -64
  53. mcp_proxy_adapter/core/auth_validator.py +176 -182
  54. mcp_proxy_adapter/core/certificate_utils.py +469 -426
  55. mcp_proxy_adapter/core/client.py +155 -126
  56. mcp_proxy_adapter/core/client_manager.py +60 -54
  57. mcp_proxy_adapter/core/client_security.py +120 -91
  58. mcp_proxy_adapter/core/config_converter.py +176 -143
  59. mcp_proxy_adapter/core/config_validator.py +12 -4
  60. mcp_proxy_adapter/core/crl_utils.py +21 -7
  61. mcp_proxy_adapter/core/errors.py +64 -20
  62. mcp_proxy_adapter/core/logging.py +34 -29
  63. mcp_proxy_adapter/core/mtls_asgi.py +29 -25
  64. mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
  65. mcp_proxy_adapter/core/protocol_manager.py +154 -104
  66. mcp_proxy_adapter/core/proxy_client.py +202 -144
  67. mcp_proxy_adapter/core/proxy_registration.py +7 -3
  68. mcp_proxy_adapter/core/role_utils.py +139 -125
  69. mcp_proxy_adapter/core/security_adapter.py +88 -77
  70. mcp_proxy_adapter/core/security_factory.py +50 -44
  71. mcp_proxy_adapter/core/security_integration.py +72 -24
  72. mcp_proxy_adapter/core/server_adapter.py +68 -64
  73. mcp_proxy_adapter/core/server_engine.py +71 -53
  74. mcp_proxy_adapter/core/settings.py +68 -58
  75. mcp_proxy_adapter/core/ssl_utils.py +69 -56
  76. mcp_proxy_adapter/core/transport_manager.py +72 -60
  77. mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
  78. mcp_proxy_adapter/core/utils.py +4 -2
  79. mcp_proxy_adapter/custom_openapi.py +107 -99
  80. mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
  81. mcp_proxy_adapter/examples/commands/__init__.py +1 -1
  82. mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
  83. mcp_proxy_adapter/examples/debug_request_state.py +38 -19
  84. mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
  85. mcp_proxy_adapter/examples/demo_client.py +48 -36
  86. mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
  87. mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
  88. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
  89. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  90. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
  91. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  92. mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
  93. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
  94. mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
  95. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
  96. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  97. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
  98. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  99. mcp_proxy_adapter/examples/full_application/main.py +27 -2
  100. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
  101. mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
  102. mcp_proxy_adapter/examples/generate_certificates.py +31 -16
  103. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
  104. mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
  105. mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
  106. mcp_proxy_adapter/examples/run_example.py +23 -5
  107. mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
  108. mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
  109. mcp_proxy_adapter/examples/run_security_tests.py +103 -41
  110. mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
  111. mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
  112. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
  113. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
  114. mcp_proxy_adapter/examples/security_test_client.py +196 -127
  115. mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
  116. mcp_proxy_adapter/examples/test_config.py +19 -4
  117. mcp_proxy_adapter/examples/test_config_generator.py +23 -7
  118. mcp_proxy_adapter/examples/test_examples.py +84 -56
  119. mcp_proxy_adapter/examples/universal_client.py +119 -62
  120. mcp_proxy_adapter/openapi.py +108 -115
  121. mcp_proxy_adapter/utils/config_generator.py +429 -274
  122. mcp_proxy_adapter/version.py +1 -2
  123. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.6.dist-info}/METADATA +1 -1
  124. mcp_proxy_adapter-6.3.6.dist-info/RECORD +144 -0
  125. mcp_proxy_adapter-6.3.6.dist-info/top_level.txt +2 -0
  126. mcp_proxy_adapter_issue_package/demonstrate_issue.py +178 -0
  127. mcp_proxy_adapter-6.3.4.dist-info/RECORD +0 -143
  128. mcp_proxy_adapter-6.3.4.dist-info/top_level.txt +0 -1
  129. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.6.dist-info}/WHEEL +0 -0
  130. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.6.dist-info}/entry_points.txt +0 -0
  131. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.6.dist-info}/licenses/LICENSE +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, InternalError, InvalidParamsError, NotFoundError, ValidationError
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
- "type": "object",
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 (isinstance(value, str) and value.lower() in ["null", "none", ""]):
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 ["cmdname"]: # список параметров, для которых None является допустимым значением
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(f"Command {self.__class__.__name__} received invalid parameters: {invalid_params}. "
131
- f"Allowed parameters: {list(allowed_properties)}")
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('context', {}) if 'context' in kwargs else {}
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": cls.result_class.__name__ if hasattr(cls, "result_class") else None,
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(cls, params: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:
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
- "command": cls.name,
334
- "description": f"Call {cls.name} command without parameters"
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
- "command": cls.name,
362
- "params": sample_params,
363
- "description": f"Call {cls.name} command with required parameters"
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
- "command": cls.name,
413
- "params": all_params,
414
- "description": f"Call {cls.name} command with all parameters"
415
- })
416
-
417
- return examples
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 TransportManagementCommand
19
- from mcp_proxy_adapter.commands.proxy_registration_command import ProxyRegistrationCommand
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(command_class, 'name', command_class.__name__.lower())
55
- if command_name.endswith('command'):
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(f"Built-in command '{command_name}' already exists, skipping")
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(f"Failed to register built-in command {command_class.__name__}: {e}")
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
+ ]