using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Localization; using ModelContextProtocol; using Sozsoft.Platform.Localization; using Volo.Abp; using Volo.Abp.Authorization; using Volo.Abp.Authorization.Permissions; using Volo.Abp.DependencyInjection; namespace Sozsoft.Mcp; /// /// Arac hatalarini istemcinin gorebilecegi bicime cevirir. SDK yalnizca /// mesajini iletir; diger her istisna "An error occurred invoking" olarak gider ve model neden /// reddedildigini bilemez. Yetki reddinde eksik yetkiler adiyla, is kurali hatasinda /// () zaten yerellestirilmis mesaj iletilir. Diger istisnalar /// cevrilmez: ic ayrinti (SQL, yigin) istemciye sizmaz. /// public class McpToolErrorTranslator( IPermissionChecker permissionChecker, IStringLocalizer localizer) : ITransientDependency { public static bool CanTranslate(Exception exception) => exception is AbpAuthorizationException or UserFriendlyException; public async Task TranslateAsync(Exception exception, string? toolName) => exception is AbpAuthorizationException authorization ? new McpException(await DescribeMissingPermissionsAsync(authorization, toolName), exception) : new McpException(exception.Message, exception); /// /// CheckAsync("...") reddi yetki adini tasir; [Authorize] attribute'u tasimaz. Ikinci /// durumda aracin adi bilinen yetkileri kullanicinin yetkileriyle karsilastirilir. /// private async Task DescribeMissingPermissionsAsync(AbpAuthorizationException exception, string? toolName) { var candidates = new List(McpToolNames.KnownPermissionsOf(toolName)); if (exception.Data["PolicyName"] is string policyName && !string.IsNullOrWhiteSpace(policyName)) { candidates.Add(policyName); } var grants = await permissionChecker.IsGrantedAsync([.. candidates.Distinct(StringComparer.Ordinal)]); var missing = grants.Result .Where(result => result.Value != PermissionGrantResult.Granted) .Select(result => Describe(result.Key)) .ToList(); var target = toolName ?? McpConsts.EndpointPath; return missing.Count == 0 ? localizer[McpErrorCodes.PermissionDeniedUnspecified, target] : localizer[McpErrorCodes.PermissionDenied, target, string.Join(", ", missing)]; } /// Yetkinin gorunen adi ve kodu; rol ekraninda aranabilsin diye kod her zaman yazilir. private string Describe(string permissionName) { var displayName = localizer[permissionName]; return displayName.ResourceNotFound || displayName.Value == permissionName ? permissionName : $"{displayName.Value} ({permissionName})"; } }