diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMemberTypes.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMemberTypes.cs
new file mode 100644
index 0000000..ee6fa51
--- /dev/null
+++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMemberTypes.cs
@@ -0,0 +1,164 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Diagnostics.CodeAnalysis;
+
+///
+/// Specifies the types of members that are dynamically accessed.
+///
+/// This enumeration has a attribute that allows a
+/// bitwise combination of its member values.
+///
+[Flags]
+internal enum DynamicallyAccessedMemberTypes
+{
+ ///
+ /// Specifies no members.
+ ///
+ None = 0,
+
+ ///
+ /// Specifies the default, parameterless public constructor.
+ ///
+ PublicParameterlessConstructor = 0x0001,
+
+ ///
+ /// Specifies all public constructors.
+ ///
+ PublicConstructors = 0x0002 | PublicParameterlessConstructor,
+
+ ///
+ /// Specifies all non-public constructors.
+ ///
+ NonPublicConstructors = 0x0004,
+
+ ///
+ /// Specifies all public methods.
+ ///
+ PublicMethods = 0x0008,
+
+ ///
+ /// Specifies all non-public methods.
+ ///
+ NonPublicMethods = 0x0010,
+
+ ///
+ /// Specifies all public fields.
+ ///
+ PublicFields = 0x0020,
+
+ ///
+ /// Specifies all non-public fields.
+ ///
+ NonPublicFields = 0x0040,
+
+ ///
+ /// Specifies all public nested types.
+ ///
+ PublicNestedTypes = 0x0080,
+
+ ///
+ /// Specifies all non-public nested types.
+ ///
+ NonPublicNestedTypes = 0x0100,
+
+ ///
+ /// Specifies all public properties.
+ ///
+ PublicProperties = 0x0200,
+
+ ///
+ /// Specifies all non-public properties.
+ ///
+ NonPublicProperties = 0x0400,
+
+ ///
+ /// Specifies all public events.
+ ///
+ PublicEvents = 0x0800,
+
+ ///
+ /// Specifies all non-public events.
+ ///
+ NonPublicEvents = 0x1000,
+
+ ///
+ /// Specifies all interfaces implemented by the type.
+ ///
+ Interfaces = 0x2000,
+
+ ///
+ /// Specifies all non-public constructors, including those inherited from base classes.
+ ///
+ NonPublicConstructorsWithInherited = NonPublicConstructors | 0x4000,
+
+ ///
+ /// Specifies all non-public methods, including those inherited from base classes.
+ ///
+ NonPublicMethodsWithInherited = NonPublicMethods | 0x8000,
+
+ ///
+ /// Specifies all non-public fields, including those inherited from base classes.
+ ///
+ NonPublicFieldsWithInherited = NonPublicFields | 0x10000,
+
+ ///
+ /// Specifies all non-public nested types, including those inherited from base classes.
+ ///
+ NonPublicNestedTypesWithInherited = NonPublicNestedTypes | 0x20000,
+
+ ///
+ /// Specifies all non-public properties, including those inherited from base classes.
+ ///
+ NonPublicPropertiesWithInherited = NonPublicProperties | 0x40000,
+
+ ///
+ /// Specifies all non-public events, including those inherited from base classes.
+ ///
+ NonPublicEventsWithInherited = NonPublicEvents | 0x80000,
+
+ ///
+ /// Specifies all public constructors, including those inherited from base classes.
+ ///
+ PublicConstructorsWithInherited = PublicConstructors | 0x100000,
+
+ ///
+ /// Specifies all public nested types, including those inherited from base classes.
+ ///
+ PublicNestedTypesWithInherited = PublicNestedTypes | 0x200000,
+
+ ///
+ /// Specifies all constructors, including those inherited from base classes.
+ ///
+ AllConstructors = PublicConstructorsWithInherited | NonPublicConstructorsWithInherited,
+
+ ///
+ /// Specifies all methods, including those inherited from base classes.
+ ///
+ AllMethods = PublicMethods | NonPublicMethodsWithInherited,
+
+ ///
+ /// Specifies all fields, including those inherited from base classes.
+ ///
+ AllFields = PublicFields | NonPublicFieldsWithInherited,
+
+ ///
+ /// Specifies all nested types, including those inherited from base classes.
+ ///
+ AllNestedTypes = PublicNestedTypesWithInherited | NonPublicNestedTypesWithInherited,
+
+ ///
+ /// Specifies all properties, including those inherited from base classes.
+ ///
+ AllProperties = PublicProperties | NonPublicPropertiesWithInherited,
+
+ ///
+ /// Specifies all events, including those inherited from base classes.
+ ///
+ AllEvents = PublicEvents | NonPublicEventsWithInherited,
+
+ ///
+ /// Specifies all members.
+ ///
+ All = ~None
+}
diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs
new file mode 100644
index 0000000..2d01404
--- /dev/null
+++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Diagnostics.CodeAnalysis;
+
+///
+/// Indicates that certain members on a specified are accessed dynamically,
+/// for example through .
+///
+///
+/// This allows tools to understand which members are being accessed during the execution
+/// of a program.
+///
+/// This attribute is valid on members whose type is or .
+///
+/// When this attribute is applied to a location of type , the assumption is
+/// that the string represents a fully qualified type name.
+///
+/// When this attribute is applied to a class, interface, or struct, the members specified
+/// can be accessed dynamically on instances returned from calling
+/// on instances of that class, interface, or struct.
+///
+/// If the attribute is applied to a method it's treated as a special case and it implies
+/// the attribute should be applied to the "this" parameter of the method. As such the attribute
+/// should only be used on instance methods of types assignable to System.Type (or string, but no methods
+/// will use it there).
+///
+[AttributeUsage(
+ AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter |
+ AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method |
+ AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct,
+ Inherited = false)]
+internal sealed class DynamicallyAccessedMembersAttribute : Attribute
+{
+ ///
+ /// Initializes a new instance of the class
+ /// with the specified member types.
+ ///
+ /// The types of members dynamically accessed.
+ public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
+ {
+ MemberTypes = memberTypes;
+ }
+
+ ///
+ /// Gets the which specifies the type
+ /// of members dynamically accessed.
+ ///
+ public DynamicallyAccessedMemberTypes MemberTypes { get; }
+}
diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs
new file mode 100644
index 0000000..817ec6e
--- /dev/null
+++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Diagnostics.CodeAnalysis;
+
+///
+/// Indicates that the specified method requires the ability to generate new code at runtime,
+/// for example through .
+///
+///
+/// This allows tools to understand which methods are unsafe to call when compiling ahead of time.
+///
+[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)]
+internal sealed class RequiresDynamicCodeAttribute : Attribute
+{
+ ///
+ /// Initializes a new instance of the class
+ /// with the specified message.
+ ///
+ ///
+ /// A message that contains information about the usage of dynamic code.
+ ///
+ public RequiresDynamicCodeAttribute(string message)
+ {
+ Message = message;
+ }
+
+ ///
+ /// Gets a message that contains information about the usage of dynamic code.
+ ///
+ public string Message { get; }
+
+ ///
+ /// Gets or sets an optional URL that contains more information about the method,
+ /// why it requires dynamic code, and what options a consumer has to deal with it.
+ ///
+ public string? Url { get; set; }
+}
diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCode.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCode.cs
new file mode 100644
index 0000000..e4a5344
--- /dev/null
+++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCode.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Diagnostics.CodeAnalysis;
+
+///
+/// Indicates that the specified method requires dynamic access to code that is not referenced
+/// statically, for example through .
+///
+///
+/// This allows tools to understand which methods are unsafe to call when removing unreferenced
+/// code from an application.
+///
+[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)]
+internal sealed class RequiresUnreferencedCodeAttribute : Attribute
+{
+ ///
+ /// Initializes a new instance of the class
+ /// with the specified message.
+ ///
+ ///
+ /// A message that contains information about the usage of unreferenced code.
+ ///
+ public RequiresUnreferencedCodeAttribute(string message)
+ {
+ Message = message;
+ }
+
+ ///
+ /// Gets a message that contains information about the usage of unreferenced code.
+ ///
+ public string Message { get; }
+
+ ///
+ /// Gets or sets an optional URL that contains more information about the method,
+ /// why it requires unreferenced code, and what options a consumer has to deal with it.
+ ///
+ public string? Url { get; set; }
+}
diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs
new file mode 100644
index 0000000..b06d9ed
--- /dev/null
+++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs
@@ -0,0 +1,84 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Diagnostics.CodeAnalysis;
+
+///
+/// /// Suppresses reporting of a specific rule violation, allowing multiple suppressions on a
+/// single code artifact.
+///
+///
+/// is different than
+/// in that it doesn't have a
+/// . So it is always preserved in the compiled assembly.
+///
+[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
+internal sealed class UnconditionalSuppressMessageAttribute : Attribute
+{
+ ///
+ /// Initializes a new instance of the
+ /// class, specifying the category of the tool and the identifier for an analysis rule.
+ ///
+ /// The category for the attribute.
+ /// The identifier of the analysis rule the attribute applies to.
+ public UnconditionalSuppressMessageAttribute(string category, string checkId)
+ {
+ Category = category;
+ CheckId = checkId;
+ }
+
+ ///
+ /// Gets the category identifying the classification of the attribute.
+ ///
+ ///
+ /// The property describes the tool or tool analysis category
+ /// for which a message suppression attribute applies.
+ ///
+ public string Category { get; }
+
+ ///
+ /// Gets the identifier of the analysis tool rule to be suppressed.
+ ///
+ ///
+ /// Concatenated together, the and
+ /// properties form a unique check identifier.
+ ///
+ public string CheckId { get; }
+
+ ///
+ /// Gets or sets the scope of the code that is relevant for the attribute.
+ ///
+ ///
+ /// The Scope property is an optional argument that specifies the metadata scope for which
+ /// the attribute is relevant.
+ ///
+ public string? Scope { get; set; }
+
+ ///
+ /// Gets or sets a fully qualified path that represents the target of the attribute.
+ ///
+ ///
+ /// The property is an optional argument identifying the analysis target
+ /// of the attribute. An example value is "System.IO.Stream.ctor():System.Void".
+ /// Because it is fully qualified, it can be long, particularly for targets such as parameters.
+ /// The analysis tool user interface should be capable of automatically formatting the parameter.
+ ///
+ public string? Target { get; set; }
+
+ ///
+ /// Gets or sets an optional argument expanding on exclusion criteria.
+ ///
+ ///
+ /// The property is an optional argument that specifies additional
+ /// exclusion where the literal metadata target is not sufficiently precise. For example,
+ /// the cannot be applied within a method,
+ /// and it may be desirable to suppress a violation against a statement in the method that will
+ /// give a rule violation, but not against all statements in the method.
+ ///
+ public string? MessageId { get; set; }
+
+ ///
+ /// Gets or sets the justification for suppressing the code analysis message.
+ ///
+ public string? Justification { get; set; }
+}
\ No newline at end of file
diff --git a/src/McpDotNet.Extensions.AI/McpDotNet.Extensions.AI.csproj b/src/McpDotNet.Extensions.AI/McpDotNet.Extensions.AI.csproj
index 924d3f4..da22226 100644
--- a/src/McpDotNet.Extensions.AI/McpDotNet.Extensions.AI.csproj
+++ b/src/McpDotNet.Extensions.AI/McpDotNet.Extensions.AI.csproj
@@ -9,6 +9,10 @@
All
+
+ true
+
+
McpDotNet.Extensions.AI
@@ -37,4 +41,8 @@
+
+
+
+
diff --git a/src/mcpdotnet/Client/McpClient.cs b/src/mcpdotnet/Client/McpClient.cs
index c806d91..c5f6149 100644
--- a/src/mcpdotnet/Client/McpClient.cs
+++ b/src/mcpdotnet/Client/McpClient.cs
@@ -4,10 +4,9 @@ using McpDotNet.Protocol.Messages;
using McpDotNet.Protocol.Transport;
using McpDotNet.Protocol.Types;
using McpDotNet.Shared;
-
+using McpDotNet.Utils.Json;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
-
using System.Text.Json;
namespace McpDotNet.Client;
@@ -139,7 +138,10 @@ internal sealed class McpClient : McpJsonRpcEndpoint, IMcpClient
initializationCts.Token).ConfigureAwait(false);
// Store server information
- _logger.ServerCapabilitiesReceived(EndpointName, JsonSerializer.Serialize(initializeResponse.Capabilities), JsonSerializer.Serialize(initializeResponse.ServerInfo));
+ _logger.ServerCapabilitiesReceived(EndpointName,
+ capabilities: JsonSerializer.Serialize(initializeResponse.Capabilities, JsonSerializerOptionsExtensions.JsonContext.Default.ServerCapabilities),
+ serverInfo: JsonSerializer.Serialize(initializeResponse.ServerInfo, JsonSerializerOptionsExtensions.JsonContext.Default.Implementation));
+
ServerCapabilities = initializeResponse.Capabilities;
ServerInfo = initializeResponse.ServerInfo;
ServerInstructions = initializeResponse.Instructions;
diff --git a/src/mcpdotnet/Client/McpClientExtensions.cs b/src/mcpdotnet/Client/McpClientExtensions.cs
index 1eeebb2..1f0da00 100644
--- a/src/mcpdotnet/Client/McpClientExtensions.cs
+++ b/src/mcpdotnet/Client/McpClientExtensions.cs
@@ -1,6 +1,7 @@
using McpDotNet.Protocol.Messages;
using McpDotNet.Protocol.Types;
using McpDotNet.Utils;
+using McpDotNet.Utils.Json;
using Microsoft.Extensions.AI;
using System.Runtime.CompilerServices;
using System.Text.Json;
@@ -465,6 +466,8 @@ public static class McpClientExtensions
/// Provides an AI function that calls a tool through .
private sealed class McpAIFunction(IMcpClient client, Tool tool) : AIFunction
{
+ private JsonElement? _jsonSchema;
+
///
public override string Name => tool.Name;
@@ -472,7 +475,7 @@ public static class McpClientExtensions
public override string Description => tool.Description ?? string.Empty;
///
- public override JsonElement JsonSchema =>
+ public override JsonElement JsonSchema => _jsonSchema ??=
JsonSerializer.SerializeToElement(new Dictionary
{
["type"] = "object",
@@ -480,7 +483,7 @@ public static class McpClientExtensions
["description"] = tool.Description ?? string.Empty,
["properties"] = tool.InputSchema?.Properties ?? [],
["required"] = tool.InputSchema?.Required ?? []
- });
+ }, JsonSerializerOptionsExtensions.JsonContext.Default.DictionaryStringObject);
///
protected async override Task
+
+ true
+
+
mcpdotnet
diff --git a/tests/mcpdotnet.TestSseServer/Program.cs b/tests/mcpdotnet.TestSseServer/Program.cs
index dd77be8..da44b6a 100644
--- a/tests/mcpdotnet.TestSseServer/Program.cs
+++ b/tests/mcpdotnet.TestSseServer/Program.cs
@@ -2,7 +2,6 @@
using McpDotNet.Protocol.Types;
using McpDotNet.Server;
using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
using Serilog;
using System.Text;
diff --git a/tests/mcpdotnet.Tests/Configuration/McpServerBuilderExtensionsToolsTests.cs b/tests/mcpdotnet.Tests/Configuration/McpServerBuilderExtensionsToolsTests.cs
index 5885a67..a9da91e 100644
--- a/tests/mcpdotnet.Tests/Configuration/McpServerBuilderExtensionsToolsTests.cs
+++ b/tests/mcpdotnet.Tests/Configuration/McpServerBuilderExtensionsToolsTests.cs
@@ -287,7 +287,7 @@ public class McpServerBuilderExtensionsToolsTests
var tool = result.Tools.First(t => t.Name == "TestTool");
Assert.Equal("TestTool", tool.Name);
- Assert.Empty(tool.Description);
+ Assert.Empty(tool.Description!);
Assert.NotNull(tool.InputSchema);
Assert.Equal("object", tool.InputSchema.Type);
Assert.NotNull(tool.InputSchema.Properties);
diff --git a/tests/mcpdotnet.Tests/Server/McpServerTests.cs b/tests/mcpdotnet.Tests/Server/McpServerTests.cs
index 53579bf..68fe14d 100644
--- a/tests/mcpdotnet.Tests/Server/McpServerTests.cs
+++ b/tests/mcpdotnet.Tests/Server/McpServerTests.cs
@@ -603,7 +603,7 @@ public class McpServerTests
supportsSampling ? new ClientCapabilities { Sampling = new SamplingCapability() } :
null;
- public async Task SendRequestAsync(JsonRpcRequest request, CancellationToken cancellationToken) where T : class
+ public Task SendRequestAsync(JsonRpcRequest request, CancellationToken cancellationToken) where T : class
{
CreateMessageRequestParams rp = Assert.IsType(request.Params);
@@ -627,7 +627,7 @@ public class McpServerTests
Role = "assistant",
StopReason = "endTurn",
};
- return (T)(object)result;
+ return Task.FromResult((T)(object)result);
}
public ValueTask DisposeAsync() => default;
diff --git a/tests/mcpdotnet.Tests/SseServerIntegrationTestFixture.cs b/tests/mcpdotnet.Tests/SseServerIntegrationTestFixture.cs
index daec16d..a82017e 100644
--- a/tests/mcpdotnet.Tests/SseServerIntegrationTestFixture.cs
+++ b/tests/mcpdotnet.Tests/SseServerIntegrationTestFixture.cs
@@ -3,6 +3,7 @@ using McpDotNet.Configuration;
using McpDotNet.Protocol.Transport;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
namespace McpDotNet.Tests;
@@ -37,6 +38,7 @@ public class SseServerIntegrationTestFixture : IDisposable
Start();
}
+ [MemberNotNull(nameof(_process))]
public void Start()
{
// Start the server (which is at TestSseServer.exe on windows and "dotnet TestSseServer.dll" on linux)