McpAuthZ.AspNetCore 1.0.0

dotnet add package McpAuthZ.AspNetCore --version 1.0.0
                    
NuGet\Install-Package McpAuthZ.AspNetCore -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="McpAuthZ.AspNetCore" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="McpAuthZ.AspNetCore" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="McpAuthZ.AspNetCore" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add McpAuthZ.AspNetCore --version 1.0.0
                    
#r "nuget: McpAuthZ.AspNetCore, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package McpAuthZ.AspNetCore@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=McpAuthZ.AspNetCore&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=McpAuthZ.AspNetCore&version=1.0.0
                    
Install as a Cake Tool

McpAuthZ.AspNetCore

NuGet NuGet Downloads License: MIT

ASP.NET Core library for MCP HTTP server OAuth authorization, implementing RFC 9728 (Protected Resource Metadata), RFC 6750 (Bearer Token Usage), and RFC 8707 (Resource Indicators) per the MCP specification (2025-11-25).

Installation

<PackageReference Include="McpAuthZ.AspNetCore" Version="1.0.0" />

Quick Start

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options => { /* configure your IdP */ });

builder.Services.AddMcpAuthZ(options =>
{
    options.Resource = new Uri("https://example.com/api/mcp");
    options.AuthorizationServers = [new Uri("https://auth.example.com")];
    options.McpEndpointPaths = [new PathString("/api/mcp")];
    options.AuthenticationScheme = "Bearer";
});

var app = builder.Build();

app.MapMcpProtectedResourceMetadata(); // Serves /.well-known/oauth-protected-resource/...
app.UseMcpAuthZ();                     // Enforces auth on MCP endpoints

app.MapPost("/api/mcp", (HttpContext ctx) => Results.Ok());
app.Run();

Samples

Sample Description
McpAuthZ.QuickStart Zero-dependency local dev with dotnet user-jwts — start here
McpAuthZ.Auth0Sample Full Auth0 integration with audience validation and reverse proxy

Configuration Reference

Core Properties

Property Type Default Description
Resource Uri required Canonical HTTPS resource URI (no fragment)
AuthorizationServers IReadOnlyList<Uri> required OAuth AS issuer URIs
McpEndpointPaths IReadOnlyList<PathString> [] Paths requiring authentication
AuthenticationScheme string? null Auth scheme name (null = default scheme)
Realm string "McpAuthZ" Realm for WWW-Authenticate challenges

Protected Resource Metadata (PRM)

Property Type Default Description
ScopesSupported IReadOnlyList<string> [] Scopes advertised in PRM
ResourceDocumentation Uri? null Documentation URL in PRM
IncludeBearerMethodsSupported bool true Include bearer_methods_supported in PRM
ResourceMetadataUriOverride Uri? null Override computed PRM URL

Reverse Proxy Support

Property Type Default Description
PublicOriginOverride Uri? null Public scheme+host when behind a reverse proxy
PublicPathBaseOverride PathString "" Public path prefix added by the proxy

Scope Authorization

Property Type Default Description
ConnectScopes IReadOnlyList<string> [] Required scopes for GET (SSE/Streamable HTTP)
MethodScopes IReadOnlyDictionary<string, IReadOnlyList<string>> {} Required scopes per JSON-RPC method
ToolScopes IReadOnlyDictionary<string, IReadOnlyList<string>> {} Required scopes per tool name (priority over MethodScopes)
DefaultScopes IReadOnlyList<string> [] Fallback scopes for unclassified requests
ScopeClaimTypes IReadOnlyList<string> ["scope", "scp"] Claim types to search for granted scopes
ScopeSelectionMode ScopeSelectionMode UnionGrantedAndRequired How challenge scope list is computed
IncludeScopeIn401 bool true Include scope hint in 401 challenges

Audience Validation

Property Type Default Description
AllowedAudiences IReadOnlyList<string> [] Additional valid audience values beyond Resource.AbsoluteUri
EnforceAudienceValidation bool true Enable audience validation (disable only for dev/migration)
AudienceClaimTypes IReadOnlyList<string> ["aud"] Claim types to search for audience values

Reverse Proxy Setup

When your MCP server sits behind a reverse proxy (e.g., Azure App Service with path-based routing), configure the public-facing URL so that resource_metadata URIs in challenge headers point to the correct location:

builder.Services.AddMcpAuthZ(options =>
{
    // The externally-reachable resource URI (must match what clients use)
    options.Resource = new Uri("https://abc.azure.com/sanjayd/api/mcp");
    options.AuthorizationServers = [new Uri("https://login.microsoftonline.com/tenant-id/v2.0")];
    options.McpEndpointPaths = [new PathString("/api/mcp")];

    // Tell the library the public origin and path prefix
    options.PublicOriginOverride = new Uri("https://abc.azure.com");
    options.PublicPathBaseOverride = new PathString("/sanjayd");
});

Scope Mapping

Map JSON-RPC methods and tools to required scopes:

builder.Services.AddMcpAuthZ(options =>
{
    options.Resource = new Uri("https://example.com/api/mcp");
    options.AuthorizationServers = [new Uri("https://auth.example.com")];
    options.McpEndpointPaths = [new PathString("/api/mcp")];

    // Scopes for SSE/Streamable HTTP connections
    options.ConnectScopes = ["mcp:connect"];

    // Scopes per JSON-RPC method
    options.MethodScopes = new Dictionary<string, IReadOnlyList<string>>
    {
        ["resources/list"] = ["resources:read"],
        ["prompts/list"] = ["prompts:read"]
    };

    // Scopes per tool name (takes priority for tools/call requests)
    options.ToolScopes = new Dictionary<string, IReadOnlyList<string>>
    {
        ["search"] = ["tools:search"],
        ["execute"] = ["tools:execute"]
    };

    // Fallback for unrecognized methods
    options.DefaultScopes = ["mcp:default"];
});

Audience Validation

The library validates that tokens were issued specifically for your resource (RFC 8707). Resource.AbsoluteUri is always an implicitly valid audience value.

builder.Services.AddMcpAuthZ(options =>
{
    options.Resource = new Uri("https://example.com/api/mcp");
    options.AuthorizationServers = [new Uri("https://auth.example.com")];
    options.McpEndpointPaths = [new PathString("/api/mcp")];

    // Azure AD tokens may use api:// format as the audience
    options.AllowedAudiences = ["api://my-client-id"];

    // Default: true (MCP spec requires validation)
    // Set to false only during development when your IdP doesn't yet emit aud claims
    options.EnforceAudienceValidation = true;
});

Extensibility

All default implementations are registered via TryAddSingleton. Register your own implementation before AddMcpAuthZ() to replace any default:

// Replace the default audience validator with a custom one
builder.Services.AddSingleton<IMcpAudienceValidator, MyCustomAudienceValidator>();

// Replace the default scope reader (e.g., for non-standard claim formats)
builder.Services.AddSingleton<IMcpGrantedScopeReader, MyCustomScopeReader>();

// Then register the library (won't overwrite your registrations)
builder.Services.AddMcpAuthZ(options => { /* ... */ });

Replaceable Interfaces

Interface Purpose
IMcpProtectedResourceMetadataProvider PRM JSON generation
IMcpPublicUrlProvider Public URL computation for challenges
IMcpAudienceValidator Audience claim validation
IMcpRequestClassifier JSON-RPC request classification
IMcpRequiredScopeResolver Required scope resolution
IMcpGrantedScopeReader Granted scope extraction from claims
IScopeSelectionStrategy Challenge scope list computation

Named Options (Multi-tenancy)

Serve multiple MCP endpoints with independent configurations:

builder.Services.AddMcpAuthZ("tenant-a", options =>
{
    options.Resource = new Uri("https://example.com/tenant-a/mcp");
    options.AuthorizationServers = [new Uri("https://auth-a.example.com")];
    options.McpEndpointPaths = [new PathString("/tenant-a/mcp")];
});

builder.Services.AddMcpAuthZ("tenant-b", options =>
{
    options.Resource = new Uri("https://example.com/tenant-b/mcp");
    options.AuthorizationServers = [new Uri("https://auth-b.example.com")];
    options.McpEndpointPaths = [new PathString("/tenant-b/mcp")];
});

var app = builder.Build();
app.MapMcpProtectedResourceMetadata("tenant-a");
app.MapMcpProtectedResourceMetadata("tenant-b");
app.UseMcpAuthZ("tenant-a");
app.UseMcpAuthZ("tenant-b");

License

See LICENSE for details.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 88 2/22/2026