Skip to content

Commit e8b3e0d

Browse files
committed
Cleanup
1 parent 950a3c4 commit e8b3e0d

File tree

7 files changed

+77
-26
lines changed

7 files changed

+77
-26
lines changed

samples/AuthorizationServerExample/Program.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using ModelContextProtocol;
2-
using ModelContextProtocol.AspNetCore;
2+
using ModelContextProtocol.Configuration;
33
using ModelContextProtocol.Protocol.Auth;
44
using ModelContextProtocol.Protocol.Types;
55
using ModelContextProtocol.Server.Auth;
@@ -40,9 +40,12 @@ async Task<bool> ValidateToken(string token)
4040
}
4141

4242
// 3. Create an authorization provider with the PRM and token validator
43-
var authProvider = new BasicServerAuthorizationProvider(prm, ValidateToken);
44-
45-
// 4. Configure the MCP server with authorization
43+
var authProvider = new BasicServerAuthorizationProvider(prm, ValidateToken); // 4. Configure the MCP server with authorization
44+
// WithAuthorization will automatically configure:
45+
// - Authorization provider registration
46+
// - Protected resource metadata endpoint (/.well-known/oauth-protected-resource)
47+
// - Token validation middleware
48+
// - Authorization for all MCP endpoints
4649
builder.Services.AddMcpServer(options =>
4750
{
4851
options.ServerInstructions = "This is an MCP server with OAuth authorization enabled.";
@@ -106,14 +109,8 @@ async Task<bool> ValidateToken(string token)
106109

107110
var app = builder.Build();
108111

109-
// 5. Enable authorization middleware (this must be before MapMcp)
110-
// This middleware does several things:
111-
// - Serves the PRM document at /.well-known/oauth-protected-resource
112-
// - Checks Authorization header on requests
113-
// - Returns 401 + WWW-Authenticate when authorization is missing or invalid
114-
app.UseMcpAuthorization();
115-
116-
// 6. Map MCP endpoints
112+
// 5. Map MCP endpoints
113+
// Note: Authorization is now handled automatically by WithAuthorization()
117114
app.MapMcp();
118115

119116
// Configure the server URL

src/ModelContextProtocol.AspNetCore/AuthorizationExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ public static class AuthorizationExtensions
1010
/// <summary>
1111
/// Adds MCP authorization middleware to the specified <see cref="IApplicationBuilder"/>, which enables
1212
/// OAuth 2.0 authorization for MCP servers.
13+
///
14+
/// Note: This method is called automatically when using <c>WithAuthorization()</c>, so you typically
15+
/// don't need to call it directly. It's available for advanced scenarios where more control is needed.
1316
/// </summary>
1417
/// <param name="builder">The <see cref="IApplicationBuilder"/> to add the middleware to.</param>
1518
/// <returns>A reference to this instance after the operation has completed.</returns>

src/ModelContextProtocol.AspNetCore/AuthorizationMiddleware.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ public AuthorizationMiddleware(RequestDelegate next, ILogger<AuthorizationMiddle
2525
{
2626
_next = next ?? throw new ArgumentNullException(nameof(next));
2727
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
28-
}
29-
30-
/// <summary>
28+
} /// <summary>
3129
/// Processes a request.
3230
/// </summary>
3331
/// <param name="context">The HTTP context.</param>
@@ -42,6 +40,7 @@ public async Task InvokeAsync(
4240
// Check if authorization is configured
4341
if (authProvider == null)
4442
{
43+
_logger.LogDebug("Authorization is not configured, skipping authorization middleware");
4544
// Authorization is not configured, proceed to the next middleware
4645
await _next(context);
4746
return;
@@ -54,7 +53,7 @@ public async Task InvokeAsync(
5453
_logger.LogDebug("Serving Protected Resource Metadata document");
5554
context.Response.ContentType = "application/json";
5655
await JsonSerializer.SerializeAsync(
57-
context.Response.Body,
56+
context.Response.Body,
5857
authProvider.GetProtectedResourceMetadata(),
5958
McpJsonUtilities.DefaultOptions.GetTypeInfo(typeof(ProtectedResourceMetadata)));
6059
return;

src/ModelContextProtocol.AspNetCore/HttpMcpServerBuilderExtensions.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.Extensions.DependencyInjection.Extensions;
1+
using Microsoft.AspNetCore.Hosting;
2+
using Microsoft.Extensions.DependencyInjection.Extensions;
23
using ModelContextProtocol.AspNetCore;
34
using ModelContextProtocol.Server;
45

@@ -27,6 +28,9 @@ public static IMcpServerBuilder WithHttpTransport(this IMcpServerBuilder builder
2728
builder.Services.TryAddSingleton<SseHandler>();
2829
builder.Services.AddHostedService<IdleTrackingBackgroundService>();
2930

31+
// Add our auto-registration for the authorization middleware
32+
builder.Services.AddTransient<IStartupFilter, McpAuthorizationStartupFilter>();
33+
3034
if (configureOptions is not null)
3135
{
3236
builder.Services.Configure(configureOptions);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// filepath: c:\Users\ddelimarsky\source\csharp-sdk\src\ModelContextProtocol.AspNetCore\McpAuthorizationStartupFilter.cs
2+
using Microsoft.AspNetCore.Builder;
3+
using Microsoft.AspNetCore.Hosting;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using ModelContextProtocol.Protocol.Auth;
6+
using System;
7+
8+
namespace ModelContextProtocol.AspNetCore;
9+
10+
/// <summary>
11+
/// StartupFilter that automatically adds the MCP authorization middleware when authorization is configured.
12+
/// </summary>
13+
internal class McpAuthorizationStartupFilter : IStartupFilter
14+
{
15+
/// <summary>
16+
/// Configures the middleware pipeline to include MCP authorization middleware when needed.
17+
/// </summary>
18+
/// <param name="next">The next configurator in the chain.</param>
19+
/// <returns>A new pipeline configuration action.</returns>
20+
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
21+
{
22+
return app =>
23+
{
24+
// Check if authorization provider is registered
25+
bool hasAuthProvider = app.ApplicationServices.GetService<IServerAuthorizationProvider>() != null;
26+
27+
// If authorization is configured, add the middleware
28+
if (hasAuthProvider)
29+
{
30+
app.UseMcpAuthorization();
31+
}
32+
33+
// Continue with the rest of the pipeline configuration
34+
next(app);
35+
};
36+
}
37+
}

src/ModelContextProtocol.AspNetCore/McpEndpointRouteBuilderExtensions.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,14 @@ public static IEndpointConventionBuilder MapMcp(this IEndpointRouteBuilder endpo
7575

7676
var messageEndpoint = sseGroup.MapPost("/message", sseHandler.HandleMessageRequestAsync)
7777
.WithMetadata(new AcceptsMetadata(["application/json"]))
78-
.WithMetadata(new ProducesResponseTypeMetadata(StatusCodes.Status202Accepted));
79-
80-
// Apply authorization filter directly to SSE endpoints if authorization is configured
78+
.WithMetadata(new ProducesResponseTypeMetadata(StatusCodes.Status202Accepted)); // Apply authorization filter directly to the endpoints if authorization is configured
8179
if (authProvider != null)
8280
{
83-
// Apply authorization to both endpoints using the extension method
81+
// Apply authorization to both SSE endpoints using the extension method
8482
new[] { sseEndpoint, messageEndpoint }.AddMcpAuthorization(authProvider, endpoints.ServiceProvider);
83+
84+
// Apply authorization to the Streamable HTTP endpoints using the extension method
85+
streamableHttpGroup.AddMcpAuthorization(authProvider, endpoints.ServiceProvider);
8586
}
8687
return mcpGroup;
8788
}

src/ModelContextProtocol/Configuration/McpServerAuthorizationExtensions.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,39 @@
1+
using Microsoft.Extensions.DependencyInjection;
12
using ModelContextProtocol.Protocol.Auth;
23
using ModelContextProtocol.Protocol.Types;
34
using ModelContextProtocol.Server;
45
using ModelContextProtocol.Utils;
56

6-
namespace Microsoft.Extensions.DependencyInjection;
7+
namespace ModelContextProtocol.Configuration;
78

89
/// <summary>
910
/// Extension methods for configuring authorization in MCP servers.
1011
/// </summary>
1112
public static class McpServerAuthorizationExtensions
12-
{
13+
{
1314
/// <summary>
14-
/// Adds authorization support to the MCP server.
15+
/// Adds authorization support to the MCP server and automatically configures the required middleware.
16+
/// You don't need to call UseMcpAuthorization() separately - it will be handled automatically.
1517
/// </summary>
1618
/// <param name="builder">The <see cref="IMcpServerBuilder"/> to configure.</param>
1719
/// <param name="authorizationProvider">The authorization provider that will validate tokens and provide metadata.</param>
1820
/// <returns>The <see cref="IMcpServerBuilder"/> so that additional calls can be chained.</returns>
1921
/// <exception cref="ArgumentNullException"><paramref name="builder"/> or <paramref name="authorizationProvider"/> is <see langword="null"/>.</exception>
22+
/// <remarks>
23+
/// This method automatically configures all the necessary components for authorization:
24+
/// 1. Registers the authorization provider in the DI container
25+
/// 2. Configures authorization middleware to serve the protected resource metadata
26+
/// 3. Adds authorization to MCP endpoints when they are mapped
27+
///
28+
/// You no longer need to call app.UseMcpAuthorization() explicitly.
29+
/// </remarks>
2030
public static IMcpServerBuilder WithAuthorization(
2131
this IMcpServerBuilder builder,
2232
IServerAuthorizationProvider authorizationProvider)
2333
{
2434
Throw.IfNull(builder);
25-
Throw.IfNull(authorizationProvider);
26-
35+
Throw.IfNull(authorizationProvider);
36+
2737
// Register the authorization provider in the DI container
2838
builder.Services.AddSingleton(authorizationProvider);
2939

0 commit comments

Comments
 (0)