ToolErrors.cs 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. using System.ComponentModel.DataAnnotations;
  2. using ModelContextProtocol;
  3. using RackPeek.Domain.Helpers;
  4. namespace RackPeek.Mcp;
  5. /// <summary>
  6. /// Runs a tool body and rethrows the domain's user-facing exceptions as
  7. /// <see cref="McpException" /> so their message reaches the calling agent as a
  8. /// tool error it can act on. Anything else falls through: the SDK reports those
  9. /// as a generic error, deliberately, so nothing internal leaks over the wire.
  10. /// </summary>
  11. internal static class ToolErrors {
  12. public static async Task<T> RunAsync<T>(Func<Task<T>> action) {
  13. try {
  14. return await action();
  15. }
  16. catch (ValidationException ex) {
  17. throw new McpException($"Invalid input: {ex.Message}");
  18. }
  19. catch (NotFoundException ex) {
  20. throw new McpException(ex.Message);
  21. }
  22. catch (ConfigLoadException ex) {
  23. // The config exists but cannot be read. Say so plainly rather than letting
  24. // the agent see a generic failure and conclude the inventory is empty.
  25. throw new McpException(ex.Message);
  26. }
  27. catch (ConflictException ex) {
  28. throw new McpException(ex.Message);
  29. }
  30. catch (InvalidOperationException ex) {
  31. // The connection use cases signal user-correctable mistakes with this
  32. // ("cannot connect a port to itself", "resource has no ports").
  33. throw new McpException(ex.Message);
  34. }
  35. }
  36. }