diff --git a/Directory.Packages.props b/Directory.Packages.props
index 6da9521f..82cdabf9 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -75,6 +75,7 @@
+
diff --git a/tests/ModelContextProtocol.AspNetCore.Tests/ModelContextProtocol.AspNetCore.Tests.csproj b/tests/ModelContextProtocol.AspNetCore.Tests/ModelContextProtocol.AspNetCore.Tests.csproj
index 34801c73..c42dc16e 100644
--- a/tests/ModelContextProtocol.AspNetCore.Tests/ModelContextProtocol.AspNetCore.Tests.csproj
+++ b/tests/ModelContextProtocol.AspNetCore.Tests/ModelContextProtocol.AspNetCore.Tests.csproj
@@ -50,6 +50,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
+
@@ -60,4 +61,10 @@
+
+
+ PreserveNewest
+
+
+
diff --git a/tests/ModelContextProtocol.AspNetCore.Tests/PublicApiTests.ModelContextProtocol.AspNetCore.txt b/tests/ModelContextProtocol.AspNetCore.Tests/PublicApiTests.ModelContextProtocol.AspNetCore.txt
new file mode 100644
index 00000000..9d9b67a2
--- /dev/null
+++ b/tests/ModelContextProtocol.AspNetCore.Tests/PublicApiTests.ModelContextProtocol.AspNetCore.txt
@@ -0,0 +1,46 @@
+namespace ModelContextProtocol.AspNetCore.Authentication
+{
+ public static class McpAuthenticationDefaults
+ {
+ public const string AuthenticationScheme = "McpAuth";
+ public const string DisplayName = "MCP Authentication";
+ }
+ public class McpAuthenticationEvents
+ {
+ public McpAuthenticationEvents() { }
+ public System.Func OnResourceMetadataRequest { get; set; }
+ }
+ public class McpAuthenticationHandler : Microsoft.AspNetCore.Authentication.AuthenticationHandler, Microsoft.AspNetCore.Authentication.IAuthenticationHandler, Microsoft.AspNetCore.Authentication.IAuthenticationRequestHandler
+ {
+ public McpAuthenticationHandler(Microsoft.Extensions.Options.IOptionsMonitor options, Microsoft.Extensions.Logging.ILoggerFactory logger, System.Text.Encodings.Web.UrlEncoder encoder) { }
+ protected override System.Threading.Tasks.Task HandleAuthenticateAsync() { }
+ protected override System.Threading.Tasks.Task HandleChallengeAsync(Microsoft.AspNetCore.Authentication.AuthenticationProperties properties) { }
+ public System.Threading.Tasks.Task HandleRequestAsync() { }
+ }
+ public class McpAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions
+ {
+ public McpAuthenticationOptions() { }
+ public new ModelContextProtocol.AspNetCore.Authentication.McpAuthenticationEvents Events { get; set; }
+ public ModelContextProtocol.Authentication.ProtectedResourceMetadata? ResourceMetadata { get; set; }
+ public System.Uri ResourceMetadataUri { get; set; }
+ }
+ public class ResourceMetadataRequestContext : Microsoft.AspNetCore.Authentication.HandleRequestContext
+ {
+ public ResourceMetadataRequestContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, ModelContextProtocol.AspNetCore.Authentication.McpAuthenticationOptions options) { }
+ public ModelContextProtocol.Authentication.ProtectedResourceMetadata? ResourceMetadata { get; set; }
+ }
+}
+namespace ModelContextProtocol.AspNetCore
+{
+ public class HttpServerTransportOptions
+ {
+ public HttpServerTransportOptions() { }
+ public System.Func? ConfigureSessionOptions { get; set; }
+ public System.TimeSpan IdleTimeout { get; set; }
+ public int MaxIdleSessionCount { get; set; }
+ public bool PerSessionExecutionContext { get; set; }
+ public System.Func? RunSessionHandler { get; set; }
+ public bool Stateless { get; set; }
+ public System.TimeProvider TimeProvider { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/tests/ModelContextProtocol.AspNetCore.Tests/PublicApiTests.cs b/tests/ModelContextProtocol.AspNetCore.Tests/PublicApiTests.cs
new file mode 100644
index 00000000..83640bb2
--- /dev/null
+++ b/tests/ModelContextProtocol.AspNetCore.Tests/PublicApiTests.cs
@@ -0,0 +1,15 @@
+using Microsoft.AspNetCore.Builder;
+using PublicApiGenerator;
+
+namespace ModelContextProtocol.AspNetCore.Tests;
+
+public class PublicApiTests
+{
+ [Fact]
+ public void AspNetCore_PublicApi_Approved()
+ {
+ var api = typeof(McpEndpointRouteBuilderExtensions).Assembly.GeneratePublicApi(new ApiGeneratorOptions { IncludeAssemblyAttributes = false });
+ var approved = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "PublicApiTests.ModelContextProtocol.AspNetCore.txt"));
+ Assert.Equal(approved, api);
+ }
+}
diff --git a/tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj b/tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj
index 993564bf..45a91a68 100644
--- a/tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj
+++ b/tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj
@@ -58,6 +58,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
+
@@ -66,6 +67,12 @@
+
+
+ PreserveNewest
+
+
+
PreserveNewest
diff --git a/tests/ModelContextProtocol.Tests/PublicApiTests.ModelContextProtocol.Core.txt b/tests/ModelContextProtocol.Tests/PublicApiTests.ModelContextProtocol.Core.txt
new file mode 100644
index 00000000..ced58750
--- /dev/null
+++ b/tests/ModelContextProtocol.Tests/PublicApiTests.ModelContextProtocol.Core.txt
@@ -0,0 +1,1483 @@
+namespace ModelContextProtocol
+{
+ public static class AIContentExtensions
+ {
+ public static Microsoft.Extensions.AI.AIContent? ToAIContent(this ModelContextProtocol.Protocol.ContentBlock content) { }
+ public static Microsoft.Extensions.AI.AIContent ToAIContent(this ModelContextProtocol.Protocol.ResourceContents content) { }
+ public static System.Collections.Generic.IList ToAIContents(this System.Collections.Generic.IEnumerable contents) { }
+ public static System.Collections.Generic.IList ToAIContents(this System.Collections.Generic.IEnumerable contents) { }
+ public static Microsoft.Extensions.AI.ChatMessage ToChatMessage(this ModelContextProtocol.Protocol.PromptMessage promptMessage) { }
+ public static Microsoft.Extensions.AI.ChatMessage ToChatMessage(this ModelContextProtocol.Protocol.CallToolResult result, string callId) { }
+ public static System.Collections.Generic.IList ToChatMessages(this ModelContextProtocol.Protocol.GetPromptResult promptResult) { }
+ public static System.Collections.Generic.IList ToPromptMessages(this Microsoft.Extensions.AI.ChatMessage chatMessage) { }
+ }
+ [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Requires dynamic code to instantiate the generic enum converter.")]
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Requires unreferenced code to instantiate the generic enum converter.")]
+ public sealed class CustomizableJsonStringEnumConverter : System.Text.Json.Serialization.JsonConverterFactory
+ {
+ public CustomizableJsonStringEnumConverter() { }
+ public override bool CanConvert(System.Type typeToConvert) { }
+ public override System.Text.Json.Serialization.JsonConverter? CreateConverter(System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { }
+ }
+ public sealed class CustomizableJsonStringEnumConverter<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields)] TEnum> : System.Text.Json.Serialization.JsonStringEnumConverter
+ where TEnum : struct, System.Enum
+ {
+ public CustomizableJsonStringEnumConverter() { }
+ }
+ public interface IMcpEndpoint : System.IAsyncDisposable
+ {
+ string? SessionId { get; }
+ System.IAsyncDisposable RegisterNotificationHandler(string method, System.Func handler);
+ System.Threading.Tasks.Task SendMessageAsync(ModelContextProtocol.Protocol.JsonRpcMessage message, System.Threading.CancellationToken cancellationToken = default);
+ System.Threading.Tasks.Task SendRequestAsync(ModelContextProtocol.Protocol.JsonRpcRequest request, System.Threading.CancellationToken cancellationToken = default);
+ }
+ public static class McpEndpointExtensions
+ {
+ public static System.Threading.Tasks.Task NotifyProgressAsync(this ModelContextProtocol.IMcpEndpoint endpoint, ModelContextProtocol.Protocol.ProgressToken progressToken, ModelContextProtocol.ProgressNotificationValue progress, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.Task SendNotificationAsync(this ModelContextProtocol.IMcpEndpoint client, string method, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.Task SendNotificationAsync(this ModelContextProtocol.IMcpEndpoint endpoint, string method, TParameters parameters, System.Text.Json.JsonSerializerOptions? serializerOptions = null, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.ValueTask SendRequestAsync(this ModelContextProtocol.IMcpEndpoint endpoint, string method, TParameters parameters, System.Text.Json.JsonSerializerOptions? serializerOptions = null, ModelContextProtocol.Protocol.RequestId requestId = default, System.Threading.CancellationToken cancellationToken = default)
+ where TResult : notnull { }
+ }
+ public enum McpErrorCode
+ {
+ ParseError = -32700,
+ InvalidRequest = -32600,
+ MethodNotFound = -32601,
+ InvalidParams = -32602,
+ InternalError = -32603,
+ }
+ public class McpException : System.Exception
+ {
+ public McpException() { }
+ public McpException(string message) { }
+ public McpException(string message, ModelContextProtocol.McpErrorCode errorCode) { }
+ public McpException(string message, System.Exception? innerException) { }
+ public McpException(string message, System.Exception? innerException, ModelContextProtocol.McpErrorCode errorCode) { }
+ public ModelContextProtocol.McpErrorCode ErrorCode { get; }
+ }
+ public static class McpJsonUtilities
+ {
+ public static System.Text.Json.JsonSerializerOptions DefaultOptions { get; }
+ }
+ public sealed class ProgressNotificationValue
+ {
+ public ProgressNotificationValue() { }
+ public string? Message { get; init; }
+ public required float Progress { get; init; }
+ public float? Total { get; init; }
+ }
+}
+namespace ModelContextProtocol.Authentication
+{
+ public delegate System.Threading.Tasks.Task AuthorizationRedirectDelegate(System.Uri authorizationUri, System.Uri redirectUri, System.Threading.CancellationToken cancellationToken);
+ public sealed class ClientOAuthOptions
+ {
+ public ClientOAuthOptions() { }
+ public System.Collections.Generic.IDictionary AdditionalAuthorizationParameters { get; set; }
+ public System.Func, System.Uri?>? AuthServerSelector { get; set; }
+ public ModelContextProtocol.Authentication.AuthorizationRedirectDelegate? AuthorizationRedirectDelegate { get; set; }
+ public string? ClientId { get; set; }
+ public string? ClientName { get; set; }
+ public string? ClientSecret { get; set; }
+ public System.Uri? ClientUri { get; set; }
+ public required System.Uri RedirectUri { get; set; }
+ public System.Collections.Generic.IEnumerable? Scopes { get; set; }
+ }
+ public sealed class ProtectedResourceMetadata
+ {
+ public ProtectedResourceMetadata() { }
+ [System.Text.Json.Serialization.JsonPropertyName("authorization_details_types_supported")]
+ public System.Collections.Generic.List? AuthorizationDetailsTypesSupported { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("authorization_servers")]
+ public System.Collections.Generic.List AuthorizationServers { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("bearer_methods_supported")]
+ public System.Collections.Generic.List BearerMethodsSupported { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("dpop_bound_access_tokens_required")]
+ public bool? DpopBoundAccessTokensRequired { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("dpop_signing_alg_values_supported")]
+ public System.Collections.Generic.List? DpopSigningAlgValuesSupported { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("jwks_uri")]
+ public System.Uri? JwksUri { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("resource")]
+ public required System.Uri Resource { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("resource_documentation")]
+ public System.Uri? ResourceDocumentation { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("resource_name")]
+ public string? ResourceName { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("resource_policy_uri")]
+ public System.Uri? ResourcePolicyUri { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("resource_signing_alg_values_supported")]
+ public System.Collections.Generic.List? ResourceSigningAlgValuesSupported { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("resource_tos_uri")]
+ public System.Uri? ResourceTosUri { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("scopes_supported")]
+ public System.Collections.Generic.List ScopesSupported { get; set; }
+ [System.Text.Json.Serialization.JsonPropertyName("tls_client_certificate_bound_access_tokens")]
+ public bool? TlsClientCertificateBoundAccessTokens { get; set; }
+ }
+}
+namespace ModelContextProtocol.Client
+{
+ public enum HttpTransportMode
+ {
+ AutoDetect = 0,
+ StreamableHttp = 1,
+ Sse = 2,
+ }
+ public interface IClientTransport
+ {
+ string Name { get; }
+ System.Threading.Tasks.Task ConnectAsync(System.Threading.CancellationToken cancellationToken = default);
+ }
+ public interface IMcpClient : ModelContextProtocol.IMcpEndpoint, System.IAsyncDisposable
+ {
+ ModelContextProtocol.Protocol.ServerCapabilities ServerCapabilities { get; }
+ ModelContextProtocol.Protocol.Implementation ServerInfo { get; }
+ string? ServerInstructions { get; }
+ }
+ public static class McpClientExtensions
+ {
+ public static System.Threading.Tasks.ValueTask CallToolAsync(this ModelContextProtocol.Client.IMcpClient client, string toolName, System.Collections.Generic.IReadOnlyDictionary? arguments = null, System.IProgress? progress = null, System.Text.Json.JsonSerializerOptions? serializerOptions = null, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.ValueTask CompleteAsync(this ModelContextProtocol.Client.IMcpClient client, ModelContextProtocol.Protocol.Reference reference, string argumentName, string argumentValue, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Func, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask> CreateSamplingHandler(this Microsoft.Extensions.AI.IChatClient chatClient) { }
+ [System.Runtime.CompilerServices.AsyncIteratorStateMachine(typeof(ModelContextProtocol.Client.McpClientExtensions.d__4))]
+ public static System.Collections.Generic.IAsyncEnumerable EnumeratePromptsAsync(this ModelContextProtocol.Client.IMcpClient client, [System.Runtime.CompilerServices.EnumeratorCancellation] System.Threading.CancellationToken cancellationToken = default) { }
+ [System.Runtime.CompilerServices.AsyncIteratorStateMachine(typeof(ModelContextProtocol.Client.McpClientExtensions.d__7))]
+ public static System.Collections.Generic.IAsyncEnumerable EnumerateResourceTemplatesAsync(this ModelContextProtocol.Client.IMcpClient client, [System.Runtime.CompilerServices.EnumeratorCancellation] System.Threading.CancellationToken cancellationToken = default) { }
+ [System.Runtime.CompilerServices.AsyncIteratorStateMachine(typeof(ModelContextProtocol.Client.McpClientExtensions.d__9))]
+ public static System.Collections.Generic.IAsyncEnumerable EnumerateResourcesAsync(this ModelContextProtocol.Client.IMcpClient client, [System.Runtime.CompilerServices.EnumeratorCancellation] System.Threading.CancellationToken cancellationToken = default) { }
+ [System.Runtime.CompilerServices.AsyncIteratorStateMachine(typeof(ModelContextProtocol.Client.McpClientExtensions.d__2))]
+ public static System.Collections.Generic.IAsyncEnumerable EnumerateToolsAsync(this ModelContextProtocol.Client.IMcpClient client, System.Text.Json.JsonSerializerOptions? serializerOptions = null, [System.Runtime.CompilerServices.EnumeratorCancellation] System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.ValueTask GetPromptAsync(this ModelContextProtocol.Client.IMcpClient client, string name, System.Collections.Generic.IReadOnlyDictionary? arguments = null, System.Text.Json.JsonSerializerOptions? serializerOptions = null, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.ValueTask> ListPromptsAsync(this ModelContextProtocol.Client.IMcpClient client, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.ValueTask> ListResourceTemplatesAsync(this ModelContextProtocol.Client.IMcpClient client, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.ValueTask> ListResourcesAsync(this ModelContextProtocol.Client.IMcpClient client, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.ValueTask> ListToolsAsync(this ModelContextProtocol.Client.IMcpClient client, System.Text.Json.JsonSerializerOptions? serializerOptions = null, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.Task PingAsync(this ModelContextProtocol.Client.IMcpClient client, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.ValueTask ReadResourceAsync(this ModelContextProtocol.Client.IMcpClient client, System.Uri uri, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.ValueTask ReadResourceAsync(this ModelContextProtocol.Client.IMcpClient client, string uri, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.ValueTask ReadResourceAsync(this ModelContextProtocol.Client.IMcpClient client, string uriTemplate, System.Collections.Generic.IReadOnlyDictionary arguments, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.Task SetLoggingLevel(this ModelContextProtocol.Client.IMcpClient client, Microsoft.Extensions.Logging.LogLevel level, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.Task SetLoggingLevel(this ModelContextProtocol.Client.IMcpClient client, ModelContextProtocol.Protocol.LoggingLevel level, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.Task SubscribeToResourceAsync(this ModelContextProtocol.Client.IMcpClient client, System.Uri uri, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.Task SubscribeToResourceAsync(this ModelContextProtocol.Client.IMcpClient client, string uri, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.Task UnsubscribeFromResourceAsync(this ModelContextProtocol.Client.IMcpClient client, System.Uri uri, System.Threading.CancellationToken cancellationToken = default) { }
+ public static System.Threading.Tasks.Task UnsubscribeFromResourceAsync(this ModelContextProtocol.Client.IMcpClient client, string uri, System.Threading.CancellationToken cancellationToken = default) { }
+ }
+ public static class McpClientFactory
+ {
+ public static System.Threading.Tasks.Task CreateAsync(ModelContextProtocol.Client.IClientTransport clientTransport, ModelContextProtocol.Client.McpClientOptions? clientOptions = null, Microsoft.Extensions.Logging.ILoggerFactory? loggerFactory = null, System.Threading.CancellationToken cancellationToken = default) { }
+ }
+ public sealed class McpClientOptions
+ {
+ public McpClientOptions() { }
+ public ModelContextProtocol.Protocol.ClientCapabilities? Capabilities { get; set; }
+ public ModelContextProtocol.Protocol.Implementation? ClientInfo { get; set; }
+ public System.TimeSpan InitializationTimeout { get; set; }
+ public string? ProtocolVersion { get; set; }
+ }
+ public sealed class McpClientPrompt
+ {
+ public string? Description { get; }
+ public string Name { get; }
+ public ModelContextProtocol.Protocol.Prompt ProtocolPrompt { get; }
+ public string? Title { get; }
+ public System.Threading.Tasks.ValueTask GetAsync(System.Collections.Generic.IEnumerable>? arguments = null, System.Text.Json.JsonSerializerOptions? serializerOptions = null, System.Threading.CancellationToken cancellationToken = default) { }
+ }
+ public sealed class McpClientResource
+ {
+ public string? Description { get; }
+ public string? MimeType { get; }
+ public string Name { get; }
+ public ModelContextProtocol.Protocol.Resource ProtocolResource { get; }
+ public string? Title { get; }
+ public string Uri { get; }
+ public System.Threading.Tasks.ValueTask ReadAsync(System.Threading.CancellationToken cancellationToken = default) { }
+ }
+ public sealed class McpClientResourceTemplate
+ {
+ public string? Description { get; }
+ public string? MimeType { get; }
+ public string Name { get; }
+ public ModelContextProtocol.Protocol.ResourceTemplate ProtocolResourceTemplate { get; }
+ public string? Title { get; }
+ public string UriTemplate { get; }
+ public System.Threading.Tasks.ValueTask ReadAsync(System.Collections.Generic.IReadOnlyDictionary arguments, System.Threading.CancellationToken cancellationToken = default) { }
+ }
+ public sealed class McpClientTool : Microsoft.Extensions.AI.AIFunction
+ {
+ public override System.Collections.Generic.IReadOnlyDictionary AdditionalProperties { get; }
+ public override string Description { get; }
+ public override System.Text.Json.JsonElement JsonSchema { get; }
+ public override System.Text.Json.JsonSerializerOptions JsonSerializerOptions { get; }
+ public override string Name { get; }
+ public ModelContextProtocol.Protocol.Tool ProtocolTool { get; }
+ public override System.Text.Json.JsonElement? ReturnJsonSchema { get; }
+ public string? Title { get; }
+ public System.Threading.Tasks.ValueTask CallAsync(System.Collections.Generic.IReadOnlyDictionary? arguments = null, System.IProgress? progress = null, System.Text.Json.JsonSerializerOptions? serializerOptions = null, System.Threading.CancellationToken cancellationToken = default) { }
+ protected override System.Threading.Tasks.ValueTask