Allow JsonSerializerOptions parameters for user-defined and inputs and hardcode everything else to the source generator. (#182)
* Allow user-defined JsonSerializerOptions for user-defined and inputs and hardcode everything else to the source generator. * Add validation for user-defined JsonSerializerOptions. * Remove out of date comment. * Address feedback and add tests
This commit is contained in:
parent
4b38d3e71b
commit
f1af251c32
1 changed files with 632 additions and 372 deletions
|
|
@ -1,11 +1,12 @@
|
|||
using ModelContextProtocol.Protocol.Messages;
|
||||
using ModelContextProtocol.Utils;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
|
||||
namespace ModelContextProtocol.Shared;
|
||||
|
||||
internal sealed class RequestHandlers : Dictionary<string, Func<JsonRpcRequest, CancellationToken, Task<object?>>>
|
||||
internal sealed class RequestHandlers : Dictionary<string, Func<JsonRpcRequest, CancellationToken, Task<JsonNode?>>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers a handler for incoming requests of a specific method.
|
||||
|
|
@ -14,18 +15,24 @@ internal sealed class RequestHandlers : Dictionary<string, Func<JsonRpcRequest,
|
|||
/// <typeparam name="TResponse">Type of response payload (not full RPC response</typeparam>
|
||||
/// <param name="method">Method identifier to register for</param>
|
||||
/// <param name="handler">Handler to be called when a request with specified method identifier is received</param>
|
||||
public void Set<TRequest, TResponse>(string method, Func<TRequest?, CancellationToken, Task<TResponse>> handler)
|
||||
/// <param name="requestTypeInfo">The JSON contract governing request serialization.</param>
|
||||
/// <param name="responseTypeInfo">The JSON contract governing response serialization.</param>
|
||||
public void Set<TRequest, TResponse>(
|
||||
string method,
|
||||
Func<TRequest?, CancellationToken, Task<TResponse>> handler,
|
||||
JsonTypeInfo<TRequest> requestTypeInfo,
|
||||
JsonTypeInfo<TResponse> responseTypeInfo)
|
||||
{
|
||||
Throw.IfNull(method);
|
||||
Throw.IfNull(handler);
|
||||
Throw.IfNull(requestTypeInfo);
|
||||
Throw.IfNull(responseTypeInfo);
|
||||
|
||||
this[method] = async (request, cancellationToken) =>
|
||||
{
|
||||
// Convert the params JsonElement to our type using the same options
|
||||
var jsonString = JsonSerializer.Serialize(request.Params, McpJsonUtilities.DefaultOptions.GetTypeInfo<object?>());
|
||||
var typedRequest = JsonSerializer.Deserialize(jsonString, McpJsonUtilities.DefaultOptions.GetTypeInfo<TRequest>());
|
||||
|
||||
return await handler(typedRequest, cancellationToken).ConfigureAwait(false);
|
||||
TRequest? typedRequest = JsonSerializer.Deserialize(request.Params, requestTypeInfo);
|
||||
object? result = await handler(typedRequest, cancellationToken).ConfigureAwait(false);
|
||||
return JsonSerializer.SerializeToNode(result, responseTypeInfo);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue