Skip to content

Commit 70789ac

Browse files
committed
Enhance content validation in CallToolResult processing to ensure "type" discriminator presence and normalize text-only items
1 parent b5dfb61 commit 70789ac

File tree

1 file changed

+42
-2
lines changed

1 file changed

+42
-2
lines changed

dotnet/src/Microsoft.Agents.AI.AGUI/Shared/ChatResponseUpdateAGUIExtensions.cs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,12 +605,52 @@ private static string NormalizeToCallToolResult(string raw, JsonSerializerOption
605605
using var doc = JsonDocument.Parse(raw);
606606
var root = doc.RootElement;
607607

608-
// Already a CallToolResult-like object with a content array whose items have "type".
608+
// CallToolResult-like object with a content array.
609+
// Validate that every item carries a "type" discriminator before returning as-is;
610+
// the MCP SDK may strip the discriminator when mapping TextContentBlock →
611+
// Microsoft.Extensions.AI.TextContent, producing {"content":[{"text":"..."}]}.
609612
if (root.ValueKind == JsonValueKind.Object &&
610613
root.TryGetProperty("content", out var existing) &&
611614
existing.ValueKind == JsonValueKind.Array)
612615
{
613-
return raw;
616+
bool needsNormalization = false;
617+
foreach (var item in existing.EnumerateArray())
618+
{
619+
if (item.ValueKind != JsonValueKind.Object || !item.TryGetProperty("type", out _))
620+
{
621+
needsNormalization = true;
622+
break;
623+
}
624+
}
625+
626+
if (!needsNormalization)
627+
{
628+
return raw;
629+
}
630+
631+
// Rebuild the content array, injecting "type":"text" for any text-only items.
632+
var sb = new StringBuilder("{\"content\":[");
633+
bool first = true;
634+
foreach (var item in existing.EnumerateArray())
635+
{
636+
if (!first) { sb.Append(','); }
637+
first = false;
638+
639+
if (item.ValueKind == JsonValueKind.Object &&
640+
!item.TryGetProperty("type", out _) &&
641+
item.TryGetProperty("text", out var itemTextProp) &&
642+
itemTextProp.ValueKind == JsonValueKind.String)
643+
{
644+
string encodedText = JsonSerializer.Serialize(itemTextProp.GetString(), options.GetTypeInfo(typeof(string)));
645+
sb.Append($"{{\"type\":\"text\",\"text\":{encodedText}}}");
646+
}
647+
else
648+
{
649+
sb.Append(item.GetRawText());
650+
}
651+
}
652+
sb.Append("]}");
653+
return sb.ToString();
614654
}
615655

616656
// Single object with a "text" property (Microsoft.Extensions.AI TextContent — type stripped).

0 commit comments

Comments
 (0)