Fix some issues with Native AOT (#130)
* Fix some issues with Native AOT - An anonymous type was being used in McpClient for the initialize result message. Switched to use the type for that purpose that already existed. - A bunch of the request params / result types were not in the source context or referenced from types that were or from custom converters. Added all the request/result types to the context. - Improved the warning message for WithTools.
This commit is contained in:
parent
9330774795
commit
2c1672cc1a
7 changed files with 53 additions and 27 deletions
|
|
@ -6,7 +6,6 @@ using ModelContextProtocol.Protocol.Types;
|
|||
using ModelContextProtocol.Shared;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ModelContextProtocol.Client;
|
||||
|
|
@ -126,11 +125,11 @@ internal sealed class McpClient : McpJsonRpcEndpoint, IMcpClient
|
|||
new JsonRpcRequest
|
||||
{
|
||||
Method = "initialize",
|
||||
Params = new
|
||||
Params = new InitializeRequestParams()
|
||||
{
|
||||
protocolVersion = _options.ProtocolVersion,
|
||||
capabilities = _options.Capabilities ?? new ClientCapabilities(),
|
||||
clientInfo = _options.ClientInfo
|
||||
ProtocolVersion = _options.ProtocolVersion,
|
||||
Capabilities = _options.Capabilities ?? new ClientCapabilities(),
|
||||
ClientInfo = _options.ClientInfo
|
||||
}
|
||||
},
|
||||
initializationCts.Token).ConfigureAwait(false);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ namespace ModelContextProtocol;
|
|||
/// </summary>
|
||||
public static partial class McpServerBuilderExtensions
|
||||
{
|
||||
private const string RequiresUnreferencedCodeMessage = "This method requires dynamic lookup of method metadata and might not work in Native AOT.";
|
||||
private const string WithToolsRequiresUnreferencedCodeMessage =
|
||||
$"The non-generic {nameof(WithTools)} and {nameof(WithToolsFromAssembly)} methods require dynamic lookup of method metadata" +
|
||||
$"and may not work in Native AOT. Use the generic {nameof(WithTools)} method instead.";
|
||||
|
||||
/// <summary>Adds <see cref="McpServerTool"/> instances to the service collection backing <paramref name="builder"/>.</summary>
|
||||
/// <typeparam name="TTool">The tool type.</typeparam>
|
||||
|
|
@ -59,7 +61,7 @@ public static partial class McpServerBuilderExtensions
|
|||
/// types, where the methods are attributed as <see cref="McpServerToolAttribute"/>, and adds an <see cref="McpServerTool"/>
|
||||
/// instance for each. For instance methods, an instance will be constructed for each invocation of the tool.
|
||||
/// </remarks>
|
||||
[RequiresUnreferencedCode(RequiresUnreferencedCodeMessage)]
|
||||
[RequiresUnreferencedCode(WithToolsRequiresUnreferencedCodeMessage)]
|
||||
public static IMcpServerBuilder WithTools(this IMcpServerBuilder builder, params IEnumerable<Type> toolTypes)
|
||||
{
|
||||
Throw.IfNull(builder);
|
||||
|
|
@ -95,7 +97,7 @@ public static partial class McpServerBuilderExtensions
|
|||
/// <param name="builder">The builder instance.</param>
|
||||
/// <param name="toolAssembly">The assembly to load the types from. Null to get the current assembly</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <see langword="null"/>.</exception>
|
||||
[RequiresUnreferencedCode(RequiresUnreferencedCodeMessage)]
|
||||
[RequiresUnreferencedCode(WithToolsRequiresUnreferencedCodeMessage)]
|
||||
public static IMcpServerBuilder WithToolsFromAssembly(this IMcpServerBuilder builder, Assembly? toolAssembly = null)
|
||||
{
|
||||
Throw.IfNull(builder);
|
||||
|
|
|
|||
33
src/ModelContextProtocol/Protocol/Messages/JsonRpcRequest.cs
Normal file
33
src/ModelContextProtocol/Protocol/Messages/JsonRpcRequest.cs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ModelContextProtocol.Protocol.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// A request message in the JSON-RPC protocol.
|
||||
/// </summary>
|
||||
public record JsonRpcRequest : IJsonRpcMessageWithId
|
||||
{
|
||||
/// <summary>
|
||||
/// JSON-RPC protocol version. Always "2.0".
|
||||
/// </summary>
|
||||
[JsonPropertyName("jsonrpc")]
|
||||
public string JsonRpc { get; init; } = "2.0";
|
||||
|
||||
/// <summary>
|
||||
/// Request identifier. Must be a string or number and unique within the session.
|
||||
/// </summary>
|
||||
[JsonPropertyName("id")]
|
||||
public RequestId Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the method to invoke.
|
||||
/// </summary>
|
||||
[JsonPropertyName("method")]
|
||||
public required string Method { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional parameters for the method.
|
||||
/// </summary>
|
||||
[JsonPropertyName("params")]
|
||||
public object? Params { get; init; }
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using ModelContextProtocol.Logging;
|
||||
using ModelContextProtocol.Protocol.Messages;
|
||||
using ModelContextProtocol.Protocol.Transport;
|
||||
|
|
|
|||
|
|
@ -105,21 +105,52 @@ public static partial class McpJsonUtilities
|
|||
UseStringEnumConverter = true,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
NumberHandling = JsonNumberHandling.AllowReadingFromString)]
|
||||
|
||||
// JSON
|
||||
[JsonSerializable(typeof(JsonDocument))]
|
||||
[JsonSerializable(typeof(JsonElement))]
|
||||
[JsonSerializable(typeof(JsonNode))]
|
||||
|
||||
// JSON-RPC
|
||||
[JsonSerializable(typeof(IJsonRpcMessage))]
|
||||
[JsonSerializable(typeof(JsonRpcRequest))]
|
||||
[JsonSerializable(typeof(JsonRpcNotification))]
|
||||
[JsonSerializable(typeof(JsonRpcResponse))]
|
||||
[JsonSerializable(typeof(JsonRpcError))]
|
||||
[JsonSerializable(typeof(ServerCapabilities))]
|
||||
[JsonSerializable(typeof(ClientCapabilities))]
|
||||
[JsonSerializable(typeof(Implementation))]
|
||||
[JsonSerializable(typeof(CreateMessageResult))]
|
||||
[JsonSerializable(typeof(ListRootsResult))]
|
||||
[JsonSerializable(typeof(InitializeResult))]
|
||||
|
||||
// MCP Request Params / Results
|
||||
[JsonSerializable(typeof(CallToolRequestParams))]
|
||||
[JsonSerializable(typeof(CallToolResponse))]
|
||||
[JsonSerializable(typeof(CompleteRequestParams))]
|
||||
[JsonSerializable(typeof(CompleteResult))]
|
||||
[JsonSerializable(typeof(CreateMessageRequestParams))]
|
||||
[JsonSerializable(typeof(CreateMessageResult))]
|
||||
[JsonSerializable(typeof(EmptyResult))]
|
||||
[JsonSerializable(typeof(GetPromptRequestParams))]
|
||||
[JsonSerializable(typeof(GetPromptResult))]
|
||||
[JsonSerializable(typeof(InitializeRequestParams))]
|
||||
[JsonSerializable(typeof(InitializeResult))]
|
||||
[JsonSerializable(typeof(ListPromptsRequestParams))]
|
||||
[JsonSerializable(typeof(ListPromptsResult))]
|
||||
[JsonSerializable(typeof(ListResourcesRequestParams))]
|
||||
[JsonSerializable(typeof(ListResourcesResult))]
|
||||
[JsonSerializable(typeof(ListResourceTemplatesRequestParams))]
|
||||
[JsonSerializable(typeof(ListResourceTemplatesResult))]
|
||||
[JsonSerializable(typeof(ListRootsRequestParams))]
|
||||
[JsonSerializable(typeof(ListRootsResult))]
|
||||
[JsonSerializable(typeof(ListToolsRequestParams))]
|
||||
[JsonSerializable(typeof(ListToolsResult))]
|
||||
[JsonSerializable(typeof(LoggingMessageNotificationParams))]
|
||||
[JsonSerializable(typeof(PingResult))]
|
||||
[JsonSerializable(typeof(ReadResourceRequestParams))]
|
||||
[JsonSerializable(typeof(ReadResourceResult))]
|
||||
[JsonSerializable(typeof(ResourceUpdatedNotificationParams))]
|
||||
[JsonSerializable(typeof(SetLevelRequestParams))]
|
||||
[JsonSerializable(typeof(SubscribeRequestParams))]
|
||||
[JsonSerializable(typeof(UnsubscribeFromResourceRequestParams))]
|
||||
[JsonSerializable(typeof(UnsubscribeRequestParams))]
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
internal sealed partial class JsonContext : JsonSerializerContext;
|
||||
|
||||
private static JsonElement ParseJsonElement(ReadOnlySpan<byte> utf8Json)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ModelContextProtocol.Protocol.Types;
|
||||
using ModelContextProtocol.Server;
|
||||
using Moq;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Text.Json;
|
|||
using ModelContextProtocol.Protocol.Messages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using ModelContextProtocol.Protocol.Types;
|
||||
|
||||
namespace ModelContextProtocol.Tests.Utils;
|
||||
|
||||
|
|
@ -288,19 +289,14 @@ public sealed class InMemoryTestSseServer : IAsyncDisposable
|
|||
var jsonRpcResponse = new JsonRpcResponse()
|
||||
{
|
||||
Id = jsonRpcRequest.Id,
|
||||
Result = new
|
||||
Result = new InitializeResult()
|
||||
{
|
||||
protocolVersion = "2024-11-05",
|
||||
capabilities = new
|
||||
ProtocolVersion = "2024-11-05",
|
||||
Capabilities = new(),
|
||||
ServerInfo = new()
|
||||
{
|
||||
experimental = (object?)null,
|
||||
roots = (object?)null,
|
||||
sampling = (object?)null
|
||||
},
|
||||
serverInfo = new
|
||||
{
|
||||
name = "ExampleServer",
|
||||
version = "1.0.0"
|
||||
Name = "ExampleServer",
|
||||
Version = "1.0.0"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue