Skip to content

Commit 876bdbb

Browse files
committed
Run Can_UseIHttpContextAccessor_InTool in stateless mode
1 parent 7392032 commit 876bdbb

5 files changed

Lines changed: 14 additions & 8 deletions

File tree

src/ModelContextProtocol.AspNetCore/HttpMcpSession.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace ModelContextProtocol.AspNetCore;
77
internal sealed class HttpMcpSession<TTransport>(
88
string sessionId,
99
TTransport transport,
10-
(string Type, string Value, string Issuer)? userIdClaim,
10+
StatelessUserId? userId,
1111
TimeProvider timeProvider) : IAsyncDisposable
1212
where TTransport : ITransport
1313
{
@@ -17,7 +17,7 @@ internal sealed class HttpMcpSession<TTransport>(
1717

1818
public string Id { get; } = sessionId;
1919
public TTransport Transport { get; } = transport;
20-
public (string Type, string Value, string Issuer)? UserIdClaim { get; } = userIdClaim;
20+
public StatelessUserId? UserIdClaim { get; } = userId;
2121

2222
public CancellationToken SessionClosed => _disposeCts.Token;
2323

src/ModelContextProtocol.AspNetCore/StatelessSessionId.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ internal sealed class StatelessSessionId
99
public Implementation? ClientInfo { get; init; }
1010

1111
[JsonPropertyName("userIdClaim")]
12-
public (string Type, string Value, string Issuer)? UserIdClaim { get; init; }
12+
public StatelessUserId? UserIdClaim { get; init; }
1313
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
namespace ModelContextProtocol.AspNetCore;
2+
3+
internal sealed record StatelessUserId(string Type, string value, string Issuer);

src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ internal static Task RunSessionAsync(HttpContext httpContext, IMcpServer session
314314
// SignalR only checks for ClaimTypes.NameIdentifier in HttpConnectionDispatcher, but AspNetCore.Antiforgery checks that plus the sub and UPN claims.
315315
// However, we short-circuit unlike antiforgery since we expect to call this to verify MCP messages a lot more frequently than
316316
// verifying antiforgery tokens from <form> posts.
317-
internal static (string Type, string Value, string Issuer)? GetUserIdClaim(ClaimsPrincipal user)
317+
internal static StatelessUserId? GetUserIdClaim(ClaimsPrincipal user)
318318
{
319319
if (user?.Identity?.IsAuthenticated != true)
320320
{
@@ -325,7 +325,7 @@ internal static (string Type, string Value, string Issuer)? GetUserIdClaim(Claim
325325

326326
if (claim is { } idClaim)
327327
{
328-
return (idClaim.Type, idClaim.Value, idClaim.Issuer);
328+
return new(idClaim.Type, idClaim.Value, idClaim.Issuer);
329329
}
330330

331331
return null;

tests/ModelContextProtocol.AspNetCore.Tests/MapMcpTests.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,13 @@ public async Task MapMcp_ThrowsInvalidOperationException_IfWithHttpTransportIsNo
4646
[Fact]
4747
public async Task Can_UseIHttpContextAccessor_InTool()
4848
{
49-
Assert.SkipWhen(UseStreamableHttp, "IHttpContextAccessor is not currently supported with Streamable HTTP." +
50-
"TODO: Support it in stateless mode by manually capturing and flowing execution context.");
49+
Assert.SkipWhen(UseStreamableHttp && !Stateless,
50+
"""
51+
IHttpContextAccessor is not currently supported with non-stateless Streamable HTTP.
52+
TODO: Support it in stateless mode by manually capturing and flowing execution context.
53+
""");
5154

52-
Builder.Services.AddMcpServer().WithHttpTransport().WithTools<EchoHttpContextUserTools>();
55+
Builder.Services.AddMcpServer().WithHttpTransport(ConfigureStateless).WithTools<EchoHttpContextUserTools>();
5356

5457
Builder.Services.AddHttpContextAccessor();
5558

0 commit comments

Comments
 (0)