@@ -23,12 +23,11 @@ public partial class SseIntegrationTests(ITestOutputHelper outputHelper) : Kestr
2323 Name = "In-memory Test Server" ,
2424 } ;
2525
26- private Task < IMcpClient > ConnectMcpClient ( HttpClient httpClient , McpClientOptions ? clientOptions = null )
26+ private Task < IMcpClient > ConnectMcpClient ( HttpClient ? httpClient = null , SseClientTransportOptions ? transportOptions = null )
2727 => McpClientFactory . CreateAsync (
28- new SseClientTransport ( DefaultTransportOptions , httpClient , LoggerFactory ) ,
29- clientOptions ,
30- LoggerFactory ,
31- TestContext . Current . CancellationToken ) ;
28+ new SseClientTransport ( transportOptions ?? DefaultTransportOptions , httpClient ?? HttpClient , LoggerFactory ) ,
29+ loggerFactory : LoggerFactory ,
30+ cancellationToken : TestContext . Current . CancellationToken ) ;
3231
3332 [ Fact ]
3433 public async Task ConnectAndReceiveMessage_InMemoryServer ( )
@@ -38,7 +37,7 @@ public async Task ConnectAndReceiveMessage_InMemoryServer()
3837 app . MapMcp ( ) ;
3938 await app . StartAsync ( TestContext . Current . CancellationToken ) ;
4039
41- await using var mcpClient = await ConnectMcpClient ( HttpClient ) ;
40+ await using var mcpClient = await ConnectMcpClient ( ) ;
4241
4342 // Send a test message through POST endpoint
4443 await mcpClient . SendNotificationAsync ( "test/message" , new Envelope { Message = "Hello, SSE!" } , serializerOptions : JsonContext . Default . Options , cancellationToken : TestContext . Current . CancellationToken ) ;
@@ -53,7 +52,7 @@ public async Task ConnectAndReceiveMessage_InMemoryServer_WithFullEndpointEventU
5352 MapAbsoluteEndpointUriMcp ( app ) ;
5453 await app . StartAsync ( TestContext . Current . CancellationToken ) ;
5554
56- await using var mcpClient = await ConnectMcpClient ( HttpClient ) ;
55+ await using var mcpClient = await ConnectMcpClient ( ) ;
5756
5857 // Send a test message through POST endpoint
5958 await mcpClient . SendNotificationAsync ( "test/message" , new Envelope { Message = "Hello, SSE!" } , serializerOptions : JsonContext . Default . Options , cancellationToken : TestContext . Current . CancellationToken ) ;
@@ -85,7 +84,7 @@ public async Task ConnectAndReceiveNotification_InMemoryServer()
8584 app . MapMcp ( ) ;
8685 await app . StartAsync ( TestContext . Current . CancellationToken ) ;
8786
88- await using var mcpClient = await ConnectMcpClient ( HttpClient ) ;
87+ await using var mcpClient = await ConnectMcpClient ( ) ;
8988
9089 mcpClient . RegisterNotificationHandler ( "test/notification" , ( args , ca ) =>
9190 {
@@ -109,14 +108,14 @@ public async Task AddMcpServer_CanBeCalled_MultipleTimes()
109108
110109 Builder . Services . AddMcpServer ( options =>
111110 {
112- Interlocked . Increment ( ref firstOptionsCallbackCallCount ) ;
111+ firstOptionsCallbackCallCount ++ ;
113112 } )
114113 . WithHttpTransport ( )
115114 . WithTools < EchoTool > ( ) ;
116115
117116 Builder . Services . AddMcpServer ( options =>
118117 {
119- Interlocked . Increment ( ref secondOptionsCallbackCallCount ) ;
118+ secondOptionsCallbackCallCount ++ ;
120119 } )
121120 . WithTools < SampleLlmTool > ( ) ;
122121
@@ -125,7 +124,7 @@ public async Task AddMcpServer_CanBeCalled_MultipleTimes()
125124 app . MapMcp ( ) ;
126125 await app . StartAsync ( TestContext . Current . CancellationToken ) ;
127126
128- await using var mcpClient = await ConnectMcpClient ( HttpClient ) ;
127+ await using var mcpClient = await ConnectMcpClient ( ) ;
129128
130129 // Options can be lazily initialized, but they must be instantiated by the time an MCP client can finish connecting.
131130 // Callbacks can be called multiple times if configureOptionsAsync is configured, because that uses the IOptionsFactory,
@@ -151,6 +150,78 @@ public async Task AddMcpServer_CanBeCalled_MultipleTimes()
151150 Assert . Equal ( "hello from client!" , textContent . Text ) ;
152151 }
153152
153+ [ Fact ]
154+ public async Task AdditionalHeaders_AreSent_InGetAndPostRequests ( )
155+ {
156+ Builder . Services . AddMcpServer ( )
157+ . WithHttpTransport ( ) ;
158+
159+ await using var app = Builder . Build ( ) ;
160+
161+ bool wasGetRequest = false ;
162+ bool wasPostRequest = false ;
163+
164+ app . Use ( next =>
165+ {
166+ return async context =>
167+ {
168+ Assert . Equal ( "Bearer testToken" , context . Request . Headers [ "Authorize" ] ) ;
169+ if ( context . Request . Method == HttpMethods . Get )
170+ {
171+ wasGetRequest = true ;
172+ }
173+ else if ( context . Request . Method == HttpMethods . Post )
174+ {
175+ wasPostRequest = true ;
176+ }
177+ await next ( context ) ;
178+ } ;
179+ } ) ;
180+
181+ app . MapMcp ( ) ;
182+ await app . StartAsync ( TestContext . Current . CancellationToken ) ;
183+
184+ var sseOptions = new SseClientTransportOptions ( )
185+ {
186+ Endpoint = new Uri ( "http://localhost/sse" ) ,
187+ Name = "In-memory Test Server" ,
188+ AdditionalHeaders = new ( )
189+ {
190+ [ "Authorize" ] = "Bearer testToken"
191+ } ,
192+ } ;
193+
194+ await using var mcpClient = await ConnectMcpClient ( transportOptions : sseOptions ) ;
195+
196+ Assert . True ( wasGetRequest ) ;
197+ Assert . True ( wasPostRequest ) ;
198+ }
199+
200+ [ Fact ]
201+ public async Task EmptyAdditionalHeadersKey_Throws_InvalidOpearionException ( )
202+ {
203+ Builder . Services . AddMcpServer ( )
204+ . WithHttpTransport ( ) ;
205+
206+ await using var app = Builder . Build ( ) ;
207+
208+ app . MapMcp ( ) ;
209+ await app . StartAsync ( TestContext . Current . CancellationToken ) ;
210+
211+ var sseOptions = new SseClientTransportOptions ( )
212+ {
213+ Endpoint = new Uri ( "http://localhost/sse" ) ,
214+ Name = "In-memory Test Server" ,
215+ AdditionalHeaders = new ( )
216+ {
217+ [ "" ] = ""
218+ } ,
219+ } ;
220+
221+ var ex = await Assert . ThrowsAsync < InvalidOperationException > ( ( ) => ConnectMcpClient ( transportOptions : sseOptions ) ) ;
222+ Assert . Equal ( "Failed to add header '' with value '' from AdditionalHeaders." , ex . Message ) ;
223+ }
224+
154225 private static void MapAbsoluteEndpointUriMcp ( IEndpointRouteBuilder endpoints )
155226 {
156227 var loggerFactory = endpoints . ServiceProvider . GetRequiredService < ILoggerFactory > ( ) ;
0 commit comments