-
Notifications
You must be signed in to change notification settings - Fork 585
Description
| /// <summary> | |
| /// Gets or sets the base64-encoded string representing the binary data of the item. | |
| /// </summary> | |
| [JsonPropertyName("blob")] | |
| public required string Blob { get; set; } |
csharp-sdk/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs
Lines 377 to 381 in 4a84412
| /// <summary> | |
| /// Gets or sets the base64-encoded image data. | |
| /// </summary> | |
| [JsonPropertyName("data")] | |
| public required string Data { get; set; } |
csharp-sdk/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs
Lines 399 to 403 in 4a84412
| /// <summary> | |
| /// Gets or sets the base64-encoded audio data. | |
| /// </summary> | |
| [JsonPropertyName("data")] | |
| public required string Data { get; set; } |
Potentially more -- https://github.com/search?q=repo%3Amodelcontextprotocol%2Fcsharp-sdk%20%22base64-encoded%22&type=code
Doing this means that the UTF8 data that comes across the wire is transcoded to UTF16 just to be then base64 decoded to bytes when anyone uses it. The intermediate step to UTF16 (.NET string) is unnecessary, wastes cycles, creates garbage, and makes the API harder to use.
Instead these types should keep the data in UTF8 and then have lazy getters that will do the base64-decoding. We can tell folks to use those decoded getter properties.
https://github.com/dotnet/extensions/blob/main/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/DataContent.cs follows a similar pattern, though it uses the Uri as it's serialized representation. It seems these MCP types should use the UTF8 encoded data as their serialized representation.
The OpenAI SDK exposes a BinaryData as its representation to deal with this problem https://github.com/openai/openai-dotnet/blob/636075222205d626a770acb1af1e5cc060abd517/src/Custom/Images/GeneratedImage.cs#L23 however that's slightly less usable since it forces the caller to decode.
The proposal here would be to have these be instead:
/// <summary>
/// Gets or sets the base64-encoded UTF-8 byes representing the binary data of the item.
/// </summary>
/// <remarks>
/// This is a zero-copy representation of the wire payload of this item. Setting this value will invalidate any cached value of <see cref="Data" />.
/// </remarks>
[JsonPropertyName("blob")]
public required ReadOnlyMemory<byte> Blob { get; set; }
/// <summary>
/// Gets the decoded data represented by <see cref="Blob" />.
/// </summary>
/// <remarks>
/// Accessing this member will decode the value in <see cref="Blob" /> and cache the result.
/// </remarks>
[JsonIgnore]
public byte[] Data { get; }