mcp-proxy-adapter 3.1.5__py3-none-any.whl → 4.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_proxy_adapter/api/app.py +86 -27
- mcp_proxy_adapter/api/handlers.py +1 -1
- mcp_proxy_adapter/api/middleware/error_handling.py +11 -10
- mcp_proxy_adapter/api/tool_integration.py +5 -2
- mcp_proxy_adapter/api/tools.py +3 -3
- mcp_proxy_adapter/commands/base.py +19 -1
- mcp_proxy_adapter/commands/command_registry.py +258 -6
- mcp_proxy_adapter/commands/help_command.py +54 -65
- mcp_proxy_adapter/commands/hooks.py +260 -0
- mcp_proxy_adapter/commands/reload_command.py +211 -0
- mcp_proxy_adapter/commands/reload_settings_command.py +125 -0
- mcp_proxy_adapter/commands/settings_command.py +189 -0
- mcp_proxy_adapter/config.py +16 -1
- mcp_proxy_adapter/core/__init__.py +44 -0
- mcp_proxy_adapter/core/logging.py +87 -34
- mcp_proxy_adapter/core/settings.py +376 -0
- mcp_proxy_adapter/core/utils.py +2 -2
- mcp_proxy_adapter/custom_openapi.py +81 -2
- mcp_proxy_adapter/examples/README.md +124 -0
- mcp_proxy_adapter/examples/__init__.py +7 -0
- mcp_proxy_adapter/examples/basic_server/README.md +60 -0
- mcp_proxy_adapter/examples/basic_server/__init__.py +7 -0
- mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +39 -0
- mcp_proxy_adapter/examples/basic_server/config.json +35 -0
- mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +238 -0
- mcp_proxy_adapter/examples/basic_server/server.py +98 -0
- mcp_proxy_adapter/examples/custom_commands/README.md +127 -0
- mcp_proxy_adapter/examples/custom_commands/__init__.py +27 -0
- mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +250 -0
- mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +6 -0
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +103 -0
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +111 -0
- mcp_proxy_adapter/examples/custom_commands/config.json +62 -0
- mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +169 -0
- mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +215 -0
- mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +76 -0
- mcp_proxy_adapter/examples/custom_commands/custom_settings.json +96 -0
- mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +241 -0
- mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +135 -0
- mcp_proxy_adapter/examples/custom_commands/echo_command.py +122 -0
- mcp_proxy_adapter/examples/custom_commands/hooks.py +230 -0
- mcp_proxy_adapter/examples/custom_commands/intercept_command.py +123 -0
- mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +103 -0
- mcp_proxy_adapter/examples/custom_commands/server.py +223 -0
- mcp_proxy_adapter/examples/custom_commands/test_hooks.py +176 -0
- mcp_proxy_adapter/examples/deployment/README.md +49 -0
- mcp_proxy_adapter/examples/deployment/__init__.py +7 -0
- mcp_proxy_adapter/examples/deployment/config.development.json +8 -0
- {examples/basic_example → mcp_proxy_adapter/examples/deployment}/config.json +11 -7
- mcp_proxy_adapter/examples/deployment/config.production.json +12 -0
- mcp_proxy_adapter/examples/deployment/config.staging.json +11 -0
- mcp_proxy_adapter/examples/deployment/docker-compose.yml +31 -0
- mcp_proxy_adapter/examples/deployment/run.sh +43 -0
- mcp_proxy_adapter/examples/deployment/run_docker.sh +84 -0
- mcp_proxy_adapter/openapi.py +3 -2
- mcp_proxy_adapter/tests/api/test_custom_openapi.py +617 -0
- mcp_proxy_adapter/tests/api/test_handlers.py +522 -0
- mcp_proxy_adapter/tests/api/test_schemas.py +546 -0
- mcp_proxy_adapter/tests/api/test_tool_integration.py +531 -0
- mcp_proxy_adapter/tests/commands/test_help_command.py +8 -5
- mcp_proxy_adapter/tests/integration/test_cmd_integration.py +4 -5
- mcp_proxy_adapter/tests/test_command_registry.py +37 -1
- mcp_proxy_adapter/tests/unit/test_base_command.py +391 -85
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-3.1.5.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-4.0.0.dist-info/RECORD +110 -0
- {mcp_proxy_adapter-3.1.5.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/WHEEL +1 -1
- {mcp_proxy_adapter-3.1.5.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/top_level.txt +0 -1
- examples/__init__.py +0 -19
- examples/anti_patterns/README.md +0 -51
- examples/anti_patterns/__init__.py +0 -9
- examples/anti_patterns/bad_design/README.md +0 -72
- examples/anti_patterns/bad_design/global_state.py +0 -170
- examples/anti_patterns/bad_design/monolithic_command.py +0 -272
- examples/basic_example/README.md +0 -245
- examples/basic_example/__init__.py +0 -8
- examples/basic_example/commands/__init__.py +0 -5
- examples/basic_example/commands/echo_command.py +0 -95
- examples/basic_example/commands/math_command.py +0 -151
- examples/basic_example/commands/time_command.py +0 -152
- examples/basic_example/docs/EN/README.md +0 -177
- examples/basic_example/docs/RU/README.md +0 -177
- examples/basic_example/server.py +0 -151
- examples/basic_example/tests/conftest.py +0 -243
- examples/check_vstl_schema.py +0 -106
- examples/commands/echo_command.py +0 -52
- examples/commands/echo_command_di.py +0 -152
- examples/commands/echo_result.py +0 -65
- examples/commands/get_date_command.py +0 -98
- examples/commands/new_uuid4_command.py +0 -91
- examples/complete_example/Dockerfile +0 -24
- examples/complete_example/README.md +0 -92
- examples/complete_example/__init__.py +0 -8
- examples/complete_example/commands/__init__.py +0 -5
- examples/complete_example/commands/system_command.py +0 -328
- examples/complete_example/config.json +0 -41
- examples/complete_example/configs/config.dev.yaml +0 -40
- examples/complete_example/configs/config.docker.yaml +0 -40
- examples/complete_example/docker-compose.yml +0 -35
- examples/complete_example/requirements.txt +0 -20
- examples/complete_example/server.py +0 -113
- examples/di_example/.pytest_cache/README.md +0 -8
- examples/di_example/server.py +0 -249
- examples/fix_vstl_help.py +0 -123
- examples/minimal_example/README.md +0 -65
- examples/minimal_example/__init__.py +0 -8
- examples/minimal_example/config.json +0 -14
- examples/minimal_example/main.py +0 -136
- examples/minimal_example/simple_server.py +0 -163
- examples/minimal_example/tests/conftest.py +0 -171
- examples/minimal_example/tests/test_hello_command.py +0 -111
- examples/minimal_example/tests/test_integration.py +0 -181
- examples/patch_vstl_service.py +0 -105
- examples/patch_vstl_service_mcp.py +0 -108
- examples/server.py +0 -69
- examples/simple_server.py +0 -128
- examples/test_package_3.1.4.py +0 -177
- examples/test_server.py +0 -134
- examples/tool_description_example.py +0 -82
- mcp_proxy_adapter/py.typed +0 -0
- mcp_proxy_adapter-3.1.5.dist-info/RECORD +0 -118
- {mcp_proxy_adapter-3.1.5.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,20 @@
|
|
1
1
|
"""
|
2
2
|
Module for registering and managing commands.
|
3
|
+
|
4
|
+
Example: Registering a command instance (for dependency injection)
|
5
|
+
---------------------------------------------------------------
|
6
|
+
|
7
|
+
.. code-block:: python
|
8
|
+
|
9
|
+
from mcp_proxy_adapter.commands.command_registry import registry
|
10
|
+
from my_commands import MyCommand
|
11
|
+
|
12
|
+
# Suppose MyCommand requires a service dependency
|
13
|
+
service = MyService()
|
14
|
+
my_command_instance = MyCommand(service=service)
|
15
|
+
registry.register(my_command_instance)
|
16
|
+
|
17
|
+
# Now, when the command is executed, the same instance (with dependencies) will be used
|
3
18
|
"""
|
4
19
|
|
5
20
|
import importlib
|
@@ -26,6 +41,7 @@ class CommandRegistry:
|
|
26
41
|
"""
|
27
42
|
self._commands: Dict[str, Type[Command]] = {}
|
28
43
|
self._instances: Dict[str, Command] = {}
|
44
|
+
self._custom_commands: Dict[str, Type[Command]] = {} # Custom commands with priority
|
29
45
|
|
30
46
|
def register(self, command: Union[Type[Command], Command]) -> None:
|
31
47
|
"""
|
@@ -181,7 +197,7 @@ class CommandRegistry:
|
|
181
197
|
Raises:
|
182
198
|
NotFoundError: If command is not found.
|
183
199
|
"""
|
184
|
-
command_class = self.
|
200
|
+
command_class = self.get_command_with_priority(command_name)
|
185
201
|
|
186
202
|
return {
|
187
203
|
"name": command_name,
|
@@ -204,7 +220,7 @@ class CommandRegistry:
|
|
204
220
|
Raises:
|
205
221
|
NotFoundError: If command is not found
|
206
222
|
"""
|
207
|
-
command_class = self.
|
223
|
+
command_class = self.get_command_with_priority(command_name)
|
208
224
|
return command_class.get_metadata()
|
209
225
|
|
210
226
|
def get_all_metadata(self) -> Dict[str, Dict[str, Any]]:
|
@@ -215,8 +231,13 @@ class CommandRegistry:
|
|
215
231
|
Dict with command names as keys and metadata as values
|
216
232
|
"""
|
217
233
|
metadata = {}
|
218
|
-
|
234
|
+
# Add custom commands first (they have priority)
|
235
|
+
for name, command_class in self._custom_commands.items():
|
219
236
|
metadata[name] = command_class.get_metadata()
|
237
|
+
# Add built-in commands (custom commands will override if same name)
|
238
|
+
for name, command_class in self._commands.items():
|
239
|
+
if name not in self._custom_commands: # Only add if not overridden by custom
|
240
|
+
metadata[name] = command_class.get_metadata()
|
220
241
|
return metadata
|
221
242
|
|
222
243
|
def get_all_commands_info(self) -> Dict[str, Dict[str, Any]]:
|
@@ -227,8 +248,13 @@ class CommandRegistry:
|
|
227
248
|
Dictionary with information about all commands.
|
228
249
|
"""
|
229
250
|
commands_info = {}
|
230
|
-
|
251
|
+
# Add custom commands first (they have priority)
|
252
|
+
for name in self._custom_commands:
|
231
253
|
commands_info[name] = self.get_command_info(name)
|
254
|
+
# Add built-in commands (custom commands will override if same name)
|
255
|
+
for name in self._commands:
|
256
|
+
if name not in self._custom_commands: # Only add if not overridden by custom
|
257
|
+
commands_info[name] = self.get_command_info(name)
|
232
258
|
return commands_info
|
233
259
|
|
234
260
|
def discover_commands(self, package_path: str = "mcp_proxy_adapter.commands") -> None:
|
@@ -281,13 +307,239 @@ class CommandRegistry:
|
|
281
307
|
except Exception as e:
|
282
308
|
logger.error(f"Error discovering commands: {e}")
|
283
309
|
|
310
|
+
def register_custom_command(self, command: Union[Type[Command], Command]) -> None:
|
311
|
+
"""
|
312
|
+
Register a custom command with priority over built-in commands.
|
313
|
+
|
314
|
+
Args:
|
315
|
+
command: Command class or instance to register.
|
316
|
+
|
317
|
+
Raises:
|
318
|
+
ValueError: If command with the same name is already registered.
|
319
|
+
"""
|
320
|
+
# Determine if this is a class or an instance
|
321
|
+
if isinstance(command, type) and issubclass(command, Command):
|
322
|
+
command_class = command
|
323
|
+
command_instance = None
|
324
|
+
elif isinstance(command, Command):
|
325
|
+
command_class = command.__class__
|
326
|
+
command_instance = command
|
327
|
+
else:
|
328
|
+
raise ValueError(f"Invalid command type: {type(command)}. Expected Command class or instance.")
|
329
|
+
|
330
|
+
# Get command name
|
331
|
+
if not hasattr(command_class, "name") or not command_class.name:
|
332
|
+
# Use class name if name attribute is not set
|
333
|
+
command_name = command_class.__name__.lower()
|
334
|
+
if command_name.endswith("command"):
|
335
|
+
command_name = command_name[:-7] # Remove "command" suffix
|
336
|
+
else:
|
337
|
+
command_name = command_class.name
|
338
|
+
|
339
|
+
if command_name in self._custom_commands:
|
340
|
+
logger.debug(f"Custom command '{command_name}' is already registered, skipping")
|
341
|
+
raise ValueError(f"Custom command '{command_name}' is already registered")
|
342
|
+
|
343
|
+
logger.debug(f"Registering custom command: {command_name}")
|
344
|
+
self._custom_commands[command_name] = command_class
|
345
|
+
|
346
|
+
# Store instance if provided
|
347
|
+
if command_instance:
|
348
|
+
logger.debug(f"Storing custom instance for command: {command_name}")
|
349
|
+
self._instances[command_name] = command_instance
|
350
|
+
|
351
|
+
def unregister_custom_command(self, command_name: str) -> None:
|
352
|
+
"""
|
353
|
+
Remove custom command from registry.
|
354
|
+
|
355
|
+
Args:
|
356
|
+
command_name: Command name to remove.
|
357
|
+
|
358
|
+
Raises:
|
359
|
+
NotFoundError: If command is not found.
|
360
|
+
"""
|
361
|
+
if command_name not in self._custom_commands:
|
362
|
+
raise NotFoundError(f"Custom command '{command_name}' not found")
|
363
|
+
|
364
|
+
logger.debug(f"Unregistering custom command: {command_name}")
|
365
|
+
del self._custom_commands[command_name]
|
366
|
+
|
367
|
+
# Also remove from instances if present
|
368
|
+
if command_name in self._instances:
|
369
|
+
del self._instances[command_name]
|
370
|
+
|
371
|
+
def custom_command_exists(self, command_name: str) -> bool:
|
372
|
+
"""
|
373
|
+
Check if custom command exists.
|
374
|
+
|
375
|
+
Args:
|
376
|
+
command_name: Command name to check.
|
377
|
+
|
378
|
+
Returns:
|
379
|
+
True if custom command exists, False otherwise.
|
380
|
+
"""
|
381
|
+
return command_name in self._custom_commands
|
382
|
+
|
383
|
+
def get_custom_command(self, command_name: str) -> Type[Command]:
|
384
|
+
"""
|
385
|
+
Get custom command class.
|
386
|
+
|
387
|
+
Args:
|
388
|
+
command_name: Command name.
|
389
|
+
|
390
|
+
Returns:
|
391
|
+
Command class.
|
392
|
+
|
393
|
+
Raises:
|
394
|
+
NotFoundError: If command is not found.
|
395
|
+
"""
|
396
|
+
if command_name not in self._custom_commands:
|
397
|
+
raise NotFoundError(f"Custom command '{command_name}' not found")
|
398
|
+
return self._custom_commands[command_name]
|
399
|
+
|
400
|
+
def get_all_custom_commands(self) -> Dict[str, Type[Command]]:
|
401
|
+
"""
|
402
|
+
Get all custom commands.
|
403
|
+
|
404
|
+
Returns:
|
405
|
+
Dictionary with custom command names as keys and classes as values.
|
406
|
+
"""
|
407
|
+
return self._custom_commands.copy()
|
408
|
+
|
409
|
+
def get_priority_command(self, command_name: str) -> Optional[Type[Command]]:
|
410
|
+
"""
|
411
|
+
Get command with priority (custom commands first, then built-in).
|
412
|
+
|
413
|
+
Args:
|
414
|
+
command_name: Command name.
|
415
|
+
|
416
|
+
Returns:
|
417
|
+
Command class if found, None otherwise.
|
418
|
+
"""
|
419
|
+
# First check custom commands
|
420
|
+
if command_name in self._custom_commands:
|
421
|
+
return self._custom_commands[command_name]
|
422
|
+
|
423
|
+
# Then check built-in commands
|
424
|
+
if command_name in self._commands:
|
425
|
+
return self._commands[command_name]
|
426
|
+
|
427
|
+
return None
|
428
|
+
|
429
|
+
def command_exists_with_priority(self, command_name: str) -> bool:
|
430
|
+
"""
|
431
|
+
Check if command exists (custom or built-in).
|
432
|
+
|
433
|
+
Args:
|
434
|
+
command_name: Command name to check.
|
435
|
+
|
436
|
+
Returns:
|
437
|
+
True if command exists, False otherwise.
|
438
|
+
"""
|
439
|
+
return (command_name in self._custom_commands or
|
440
|
+
command_name in self._commands)
|
441
|
+
|
442
|
+
def get_command_with_priority(self, command_name: str) -> Type[Command]:
|
443
|
+
"""
|
444
|
+
Get command with priority (custom commands first, then built-in).
|
445
|
+
|
446
|
+
Args:
|
447
|
+
command_name: Command name.
|
448
|
+
|
449
|
+
Returns:
|
450
|
+
Command class.
|
451
|
+
|
452
|
+
Raises:
|
453
|
+
NotFoundError: If command is not found.
|
454
|
+
"""
|
455
|
+
# First check custom commands
|
456
|
+
if command_name in self._custom_commands:
|
457
|
+
return self._custom_commands[command_name]
|
458
|
+
|
459
|
+
# Then check built-in commands
|
460
|
+
if command_name in self._commands:
|
461
|
+
return self._commands[command_name]
|
462
|
+
|
463
|
+
raise NotFoundError(f"Command '{command_name}' not found")
|
464
|
+
|
284
465
|
def clear(self) -> None:
|
285
466
|
"""
|
286
|
-
|
467
|
+
Clear all registered commands.
|
287
468
|
"""
|
288
|
-
logger.debug("Clearing
|
469
|
+
logger.debug("Clearing all registered commands")
|
289
470
|
self._commands.clear()
|
290
471
|
self._instances.clear()
|
472
|
+
self._custom_commands.clear()
|
473
|
+
|
474
|
+
def reload_config_and_commands(self, package_path: str = "mcp_proxy_adapter.commands") -> Dict[str, Any]:
|
475
|
+
"""
|
476
|
+
Reload configuration and rediscover commands.
|
477
|
+
|
478
|
+
Args:
|
479
|
+
package_path: Path to package with commands.
|
480
|
+
|
481
|
+
Returns:
|
482
|
+
Dictionary with reload information including:
|
483
|
+
- config_reloaded: Whether config was reloaded
|
484
|
+
- commands_discovered: Number of commands discovered
|
485
|
+
- custom_commands_preserved: Number of custom commands preserved
|
486
|
+
- total_commands: Total number of commands after reload
|
487
|
+
"""
|
488
|
+
logger.info("🔄 Starting configuration and commands reload...")
|
489
|
+
|
490
|
+
# Store current custom commands
|
491
|
+
custom_commands_backup = self._custom_commands.copy()
|
492
|
+
|
493
|
+
# Reload configuration
|
494
|
+
try:
|
495
|
+
from mcp_proxy_adapter.config import config
|
496
|
+
config.load_config()
|
497
|
+
config_reloaded = True
|
498
|
+
logger.info("✅ Configuration reloaded successfully")
|
499
|
+
except Exception as e:
|
500
|
+
logger.error(f"❌ Failed to reload configuration: {e}")
|
501
|
+
config_reloaded = False
|
502
|
+
|
503
|
+
# Reinitialize logging with new configuration
|
504
|
+
try:
|
505
|
+
from mcp_proxy_adapter.core.logging import setup_logging
|
506
|
+
setup_logging()
|
507
|
+
logger.info("✅ Logging reinitialized with new configuration")
|
508
|
+
except Exception as e:
|
509
|
+
logger.error(f"❌ Failed to reinitialize logging: {e}")
|
510
|
+
|
511
|
+
# Clear all commands except custom ones
|
512
|
+
self._commands.clear()
|
513
|
+
self._instances.clear()
|
514
|
+
|
515
|
+
# Restore custom commands
|
516
|
+
self._custom_commands = custom_commands_backup
|
517
|
+
custom_commands_preserved = len(custom_commands_backup)
|
518
|
+
|
519
|
+
# Rediscover commands
|
520
|
+
try:
|
521
|
+
commands_discovered = self.discover_commands(package_path)
|
522
|
+
logger.info(f"✅ Rediscovered {commands_discovered} commands")
|
523
|
+
except Exception as e:
|
524
|
+
logger.error(f"❌ Failed to rediscover commands: {e}")
|
525
|
+
commands_discovered = 0
|
526
|
+
|
527
|
+
# Get final counts
|
528
|
+
total_commands = len(self._commands)
|
529
|
+
built_in_commands = total_commands - custom_commands_preserved
|
530
|
+
custom_commands = custom_commands_preserved
|
531
|
+
|
532
|
+
result = {
|
533
|
+
"config_reloaded": config_reloaded,
|
534
|
+
"commands_discovered": commands_discovered,
|
535
|
+
"custom_commands_preserved": custom_commands_preserved,
|
536
|
+
"total_commands": total_commands,
|
537
|
+
"built_in_commands": built_in_commands,
|
538
|
+
"custom_commands": custom_commands
|
539
|
+
}
|
540
|
+
|
541
|
+
logger.info(f"🔄 Reload completed: {result}")
|
542
|
+
return result
|
291
543
|
|
292
544
|
|
293
545
|
# Global command registry instance
|
@@ -183,11 +183,10 @@ class HelpCommand(Command):
|
|
183
183
|
Raises:
|
184
184
|
NotFoundError: If specified command not found
|
185
185
|
"""
|
186
|
-
|
187
|
-
logger.debug(f"HelpCommand.execute начало: cmdname={cmdname}, kwargs={kwargs}")
|
186
|
+
logger.debug(f"HelpCommand.execute начало: cmdname={cmdname}, kwargs={kwargs}")
|
188
187
|
|
188
|
+
try:
|
189
189
|
# Handle case when cmdname is provided
|
190
|
-
# Important: explicitly check for None or empty string
|
191
190
|
if cmdname is not None and cmdname != "":
|
192
191
|
logger.debug(f"Обработка запроса для конкретной команды: {cmdname}")
|
193
192
|
try:
|
@@ -196,77 +195,67 @@ class HelpCommand(Command):
|
|
196
195
|
logger.debug(f"Получены метаданные для команды {cmdname}")
|
197
196
|
return HelpResult(command_info=command_metadata)
|
198
197
|
except NotFoundError:
|
199
|
-
# If command not found, raise error
|
200
198
|
logger.warning(f"Команда '{cmdname}' не найдена")
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
"
|
199
|
+
# Получаем список всех команд
|
200
|
+
all_commands = list(registry.get_all_metadata().keys())
|
201
|
+
if all_commands:
|
202
|
+
example_cmd = all_commands[0]
|
203
|
+
example = {
|
204
|
+
"command": "help",
|
205
|
+
"params": {"cmdname": example_cmd}
|
206
|
+
}
|
207
|
+
note = f"Use help with an existing command name to get detailed info. For example: help with cmdname '{example_cmd}'. To list all commands: call help without parameters."
|
208
|
+
else:
|
209
|
+
example = {"command": "help"}
|
210
|
+
note = "No commands registered. To list all commands: call help without parameters."
|
211
|
+
return HelpResult(commands_info={
|
212
|
+
"commands": {},
|
213
|
+
"error": f"Command '{cmdname}' not found",
|
214
|
+
"example": example,
|
215
|
+
"note": note
|
212
216
|
})
|
213
217
|
|
214
218
|
# Otherwise, return information about all available commands
|
215
|
-
# and tool metadata
|
216
219
|
logger.debug("Обработка запроса для всех команд")
|
217
220
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
logger.debug(f"Получены метаданные для {len(all_metadata)} команд")
|
221
|
+
# Get metadata for all commands
|
222
|
+
all_metadata = registry.get_all_metadata()
|
223
|
+
logger.debug(f"Получены метаданные для {len(all_metadata)} команд")
|
222
224
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
225
|
+
# Prepare response format with tool metadata
|
226
|
+
result = {
|
227
|
+
"tool_info": {
|
228
|
+
"name": "MCP-Proxy API Service",
|
229
|
+
"description": "JSON-RPC API for microservice command execution",
|
230
|
+
"version": "1.0.0"
|
231
|
+
},
|
232
|
+
"help_usage": {
|
233
|
+
"description": "Get information about commands",
|
234
|
+
"examples": [
|
235
|
+
{"command": "help", "description": "List of all available commands"},
|
236
|
+
{"command": "help", "params": {"cmdname": "command_name"}, "description": "Get detailed information about a specific command"}
|
237
|
+
]
|
238
|
+
},
|
239
|
+
"commands": {}
|
240
|
+
}
|
239
241
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
242
|
+
# Add brief information about commands
|
243
|
+
for name, metadata in all_metadata.items():
|
244
|
+
try:
|
245
|
+
logger.debug(f"Обработка метаданных команды {name}")
|
246
|
+
# Безопасное получение параметров с проверкой на наличие ключей
|
247
|
+
result["commands"][name] = {
|
248
|
+
"summary": metadata.get("summary", ""),
|
249
|
+
"params_count": len(metadata.get("params", {}))
|
250
|
+
}
|
251
|
+
except Exception as e:
|
252
|
+
logger.error(f"Ошибка при обработке метаданных команды {name}: {e}")
|
253
|
+
logger.debug(f"Метаданные команды {name}: {metadata}")
|
254
|
+
# Пропускаем проблемную команду
|
255
|
+
continue
|
254
256
|
|
255
|
-
|
256
|
-
|
257
|
-
except Exception as e:
|
258
|
-
logger.error(f"Ошибка при получении списка команд: {e}")
|
259
|
-
logger.debug(f"Трассировка: {traceback.format_exc()}")
|
260
|
-
# Создаем пустой результат вместо ошибки
|
261
|
-
return HelpResult(commands_info={
|
262
|
-
"tool_info": {
|
263
|
-
"name": "MCP-Proxy API Service",
|
264
|
-
"description": "JSON-RPC API for microservice command execution",
|
265
|
-
"version": "1.0.0"
|
266
|
-
},
|
267
|
-
"commands": {},
|
268
|
-
"error": str(e)
|
269
|
-
})
|
257
|
+
logger.debug(f"HelpCommand.execute завершение: возвращаем результат с {len(result['commands'])} командами")
|
258
|
+
return HelpResult(commands_info=result)
|
270
259
|
except Exception as e:
|
271
260
|
logger.error(f"Неожиданная ошибка в HelpCommand.execute: {e}")
|
272
261
|
logger.debug(f"Трассировка: {traceback.format_exc()}")
|