Skip to content

Commit 041c54e

Browse files
author
Tarek Mahmoud Sayed
committed
Add test for server rejecting invalid UTF-8 encoded header values
1 parent a313059 commit 041c54e

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

tests/ModelContextProtocol.AspNetCore.Tests/HttpHeaderConformanceTests.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,48 @@ public async Task Server_SkipsHeaderValidation_ForNonDraftVersion()
302302
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
303303
}
304304

305+
[Fact]
306+
public async Task Server_RejectsInvalidUtf8EncodedHeaderValue()
307+
{
308+
await StartAsync();
309+
await InitializeWithDraftVersionAsync();
310+
311+
// Create a separate HttpClient that sends raw UTF-8 bytes in Mcp-* headers
312+
// instead of properly base64-encoding non-ASCII values.
313+
var handler = new SocketsHttpHandler
314+
{
315+
ConnectCallback = SocketsHttpHandler.ConnectCallback,
316+
RequestHeaderEncodingSelector = (headerName, _) =>
317+
headerName.StartsWith("Mcp-", StringComparison.OrdinalIgnoreCase)
318+
? Encoding.UTF8
319+
: null
320+
};
321+
322+
using var utf8Client = new HttpClient(handler);
323+
ConfigureHttpClient(utf8Client);
324+
utf8Client.DefaultRequestHeaders.Accept.Add(new("application/json"));
325+
utf8Client.DefaultRequestHeaders.Accept.Add(new("text/event-stream"));
326+
327+
// Send a tools/call with raw UTF-8 non-ASCII in the Mcp-Name header.
328+
// Kestrel reads header bytes as Latin-1, so the UTF-8 bytes for "café☕"
329+
// will be garbled and won't match the body value, causing rejection.
330+
var callJson = CallTool("café☕", """{"region":"us-west1","priority":42,"verbose":false,"emptyVal":""}""");
331+
332+
using var request = new HttpRequestMessage(HttpMethod.Post, "");
333+
request.Content = new StringContent(callJson, Encoding.UTF8, "application/json");
334+
request.Headers.Add("MCP-Protocol-Version", "DRAFT-2026-v1");
335+
request.Headers.TryAddWithoutValidation("Mcp-Method", "tools/call");
336+
// Raw UTF-8 non-ASCII value in Mcp-Name — server must reject this
337+
request.Headers.TryAddWithoutValidation("Mcp-Name", "café☕");
338+
request.Headers.TryAddWithoutValidation("Mcp-Param-Region", "us-west1");
339+
request.Headers.TryAddWithoutValidation("Mcp-Param-Priority", "42");
340+
request.Headers.TryAddWithoutValidation("Mcp-Param-Verbose", "false");
341+
request.Headers.TryAddWithoutValidation("Mcp-Param-EmptyVal", "");
342+
343+
using var response = await utf8Client.SendAsync(request, TestContext.Current.CancellationToken);
344+
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
345+
}
346+
305347
#endregion
306348

307349
#region Client-side encoding tests (unit tests for McpHeaderEncoder)

0 commit comments

Comments
 (0)