diff --git a/src/ModelContextProtocol.Core/AIContentExtensions.cs b/src/ModelContextProtocol.Core/AIContentExtensions.cs
index b1ba32bf..b07d36f7 100644
--- a/src/ModelContextProtocol.Core/AIContentExtensions.cs
+++ b/src/ModelContextProtocol.Core/AIContentExtensions.cs
@@ -23,6 +23,7 @@ public static class AIContentExtensions
/// satisfy sampling requests using the specified .
///
/// The with which to satisfy sampling requests.
+ /// The to use for serializing user-provided objects. If , is used.
/// The created handler delegate that can be assigned to .
///
///
@@ -36,10 +37,13 @@ public static class AIContentExtensions
///
/// is .
public static Func, CancellationToken, ValueTask> CreateSamplingHandler(
- this IChatClient chatClient)
+ this IChatClient chatClient,
+ JsonSerializerOptions? serializerOptions = null)
{
Throw.IfNull(chatClient);
+ serializerOptions ??= McpJsonUtilities.DefaultOptions;
+
return async (requestParams, progress, cancellationToken) =>
{
Throw.IfNull(requestParams);
@@ -75,7 +79,7 @@ public static class AIContentExtensions
chatResponse.FinishReason == ChatFinishReason.Length ? CreateMessageResult.StopReasonMaxTokens :
chatResponse.FinishReason == ChatFinishReason.ToolCalls ? CreateMessageResult.StopReasonToolUse :
chatResponse.FinishReason.ToString(),
- Meta = chatResponse.AdditionalProperties?.ToJsonObject(),
+ Meta = chatResponse.AdditionalProperties?.ToJsonObject(serializerOptions),
Role = lastMessage?.Role == ChatRole.User ? Role.User : Role.Assistant,
Content = contents,
};
@@ -138,8 +142,10 @@ public static class AIContentExtensions
}
/// Converts the specified dictionary to a .
- internal static JsonObject? ToJsonObject(this IReadOnlyDictionary properties) =>
- JsonSerializer.SerializeToNode(properties, McpJsonUtilities.JsonContext.Default.IReadOnlyDictionaryStringObject) as JsonObject;
+ internal static JsonObject? ToJsonObject(this IReadOnlyDictionary properties, JsonSerializerOptions options)
+ {
+ return JsonSerializer.SerializeToNode(properties, options.GetTypeInfo(typeof(IReadOnlyDictionary))) as JsonObject;
+ }
internal static AdditionalPropertiesDictionary ToAdditionalProperties(this JsonObject obj)
{
@@ -181,6 +187,7 @@ public static ChatMessage ToChatMessage(this PromptMessage promptMessage)
///
/// The tool result to convert.
/// The identifier for the function call request that triggered the tool invocation.
+ /// The to use for serialization. If , is used.
/// A object created from the tool result.
///
/// This method transforms a protocol-specific from the Model Context Protocol
@@ -189,12 +196,14 @@ public static ChatMessage ToChatMessage(this PromptMessage promptMessage)
/// serialized .
///
/// or is .
- public static ChatMessage ToChatMessage(this CallToolResult result, string callId)
+ public static ChatMessage ToChatMessage(this CallToolResult result, string callId, JsonSerializerOptions? options = null)
{
Throw.IfNull(result);
Throw.IfNull(callId);
- return new(ChatRole.Tool, [new FunctionResultContent(callId, JsonSerializer.SerializeToElement(result, McpJsonUtilities.JsonContext.Default.CallToolResult))
+ options ??= McpJsonUtilities.DefaultOptions;
+
+ return new(ChatRole.Tool, [new FunctionResultContent(callId, JsonSerializer.SerializeToElement(result, options.GetTypeInfo()))
{
RawRepresentation = result,
}]);
@@ -271,7 +280,7 @@ public static IList ToPromptMessages(this ChatMessage chatMessage
EmbeddedResourceBlock resourceContent => resourceContent.Resource.ToAIContent(),
ToolUseContentBlock toolUse => FunctionCallContent.CreateFromParsedArguments(toolUse.Input, toolUse.Id, toolUse.Name,
- static json => JsonSerializer.Deserialize(json, McpJsonUtilities.JsonContext.Default.IDictionaryStringObject)),
+ static json => JsonSerializer.Deserialize(json, McpJsonUtilities.DefaultOptions.GetTypeInfo>())),
ToolResultContentBlock toolResult => new FunctionResultContent(
toolResult.ToolUseId,
@@ -365,12 +374,15 @@ public static IList ToAIContents(this IEnumerable c
/// Creates a new from the content of an .
/// The to convert.
+ /// The to use for serialization. If , is used.
/// The created .
/// is .
- public static ContentBlock ToContentBlock(this AIContent content)
+ public static ContentBlock ToContentBlock(this AIContent content, JsonSerializerOptions? options = null)
{
Throw.IfNull(content);
+ options ??= McpJsonUtilities.DefaultOptions;
+
ContentBlock contentBlock = content switch
{
TextContent textContent => new TextContentBlock
@@ -404,7 +416,7 @@ public static ContentBlock ToContentBlock(this AIContent content)
{
Id = callContent.CallId,
Name = callContent.Name,
- Input = JsonSerializer.SerializeToElement(callContent.Arguments, McpJsonUtilities.DefaultOptions.GetTypeInfo>()!),
+ Input = JsonSerializer.SerializeToElement(callContent.Arguments, options.GetTypeInfo>()!),
},
FunctionResultContent resultContent => new ToolResultContentBlock()
@@ -412,19 +424,19 @@ public static ContentBlock ToContentBlock(this AIContent content)
ToolUseId = resultContent.CallId,
IsError = resultContent.Exception is not null,
Content =
- resultContent.Result is AIContent c ? [c.ToContentBlock()] :
- resultContent.Result is IEnumerable ec ? [.. ec.Select(c => c.ToContentBlock())] :
- [new TextContentBlock { Text = JsonSerializer.Serialize(content, McpJsonUtilities.DefaultOptions.GetTypeInfo