sozsoft-platform/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/McpToolArgumentNormalizer.cs
2026-10-18 01:31:09 +03:00

69 lines
2.6 KiB
C#

using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
namespace Sozsoft.Mcp;
/// <summary>
/// Model metin parametresine tirnaksiz deger (<c>section: 4.2</c>) ya da JSON metni yerine dogrudan
/// dizi/nesne (<c>filter: ["Status","=","Open"]</c>) gonderebilir. SDK her parametreyi ayri ayri
/// <c>string</c> olarak bagladigi icin bu deger <see cref="JsonException"/> ("Cannot get the value of a
/// token type 'Number' / 'StartArray' as a string") ile duser. Deger cagri araca ulasmadan, aracin kendi
/// semasina bakilarak ham JSON metnine cevrilir — JSON bekleyen parametre ayni metni alir; string icin
/// ozel converter kullanilmaz, cunku arac semasindaki <c>"type": "string"</c> bilgisini siler.
/// </summary>
internal static class McpToolArgumentNormalizer
{
public static void Normalize(CallToolRequestParams? parameters, McpServerTool? tool)
{
if (parameters?.Arguments is not { Count: > 0 } arguments
|| tool is null
|| !tool.ProtocolTool.InputSchema.TryGetProperty("properties", out var properties)
|| properties.ValueKind != JsonValueKind.Object)
{
return;
}
Dictionary<string, JsonElement>? normalized = null;
foreach (var (name, value) in arguments)
{
if (value.ValueKind is JsonValueKind.String or JsonValueKind.Null or JsonValueKind.Undefined
|| !properties.TryGetProperty(name, out var schema)
|| !IsStringOnly(schema))
{
continue;
}
normalized ??= new Dictionary<string, JsonElement>(arguments);
normalized[name] = JsonSerializer.SerializeToElement(value.GetRawText());
}
if (normalized is not null)
{
parameters.Arguments = normalized;
}
}
// Nullable metin parametresi semada ["string", "null"] olarak gelir; baska tip de kabul eden bir
// birlesim tipi donusturulmez, degeri SDK oldugu gibi baglar.
private static bool IsStringOnly(JsonElement schema)
{
if (!schema.TryGetProperty("type", out var type))
{
return false;
}
return type.ValueKind switch
{
JsonValueKind.String => type.GetString() == "string",
JsonValueKind.Array => type.EnumerateArray()
.Select(item => item.GetString())
.Where(item => item != "null")
.SequenceEqual(["string"]),
_ => false
};
}
}