diff --git a/src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs b/src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs
index f7db4630e..0d3cf3240 100644
--- a/src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs
+++ b/src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs
@@ -704,8 +704,8 @@ private static string[] GetConfiguredSupportedProtocolVersions(string? protocolV
}
///
- /// Validates that HTTP requests using per-request metadata declare the same protocol version in both
- /// the MCP-Protocol-Version header and body _meta envelope.
+ /// Validates that HTTP requests declare matching protocol versions in the
+ /// MCP-Protocol-Version header and the corresponding body field.
///
private static bool ValidateProtocolVersionEnvelope(
HttpContext context,
@@ -719,6 +719,18 @@ private static bool ValidateProtocolVersionEnvelope(
}
var protocolVersionHeader = context.Request.Headers[McpProtocolVersionHeaderName].ToString();
+
+ if (message is JsonRpcRequest { Method: RequestMethods.Initialize, Params: JsonObject initializeParams } &&
+ initializeParams["protocolVersion"] is JsonValue initializeProtocolVersionValue &&
+ initializeProtocolVersionValue.TryGetValue(out string? initializeProtocolVersion) &&
+ !string.IsNullOrEmpty(protocolVersionHeader) &&
+ !string.Equals(protocolVersionHeader, initializeProtocolVersion, StringComparison.Ordinal))
+ {
+ errorDetail = CreateHeaderMismatchError(
+ $"Bad Request: The {McpProtocolVersionHeaderName} header value '{protocolVersionHeader}' does not match body params.protocolVersion value '{initializeProtocolVersion}'.");
+ return false;
+ }
+
bool hasProtocolVersionMeta = TryGetProtocolVersionMeta(message, out var protocolVersionMeta);
if (!McpProtocolVersions.RequiresPerRequestMetadata(protocolVersionHeader) &&
diff --git a/tests/ModelContextProtocol.AspNetCore.Tests/StreamableHttpServerConformanceTests.cs b/tests/ModelContextProtocol.AspNetCore.Tests/StreamableHttpServerConformanceTests.cs
index 2bdd9d7e6..3422405a6 100644
--- a/tests/ModelContextProtocol.AspNetCore.Tests/StreamableHttpServerConformanceTests.cs
+++ b/tests/ModelContextProtocol.AspNetCore.Tests/StreamableHttpServerConformanceTests.cs
@@ -204,6 +204,31 @@ public async Task PostRequest_Succeeds_WithValidProtocolVersionHeader()
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
+ [Theory]
+ [InlineData(false, McpProtocolVersions.March2025ProtocolVersion, McpProtocolVersions.November2025ProtocolVersion)]
+ [InlineData(false, McpProtocolVersions.November2025ProtocolVersion, McpProtocolVersions.March2025ProtocolVersion)]
+ [InlineData(true, McpProtocolVersions.March2025ProtocolVersion, McpProtocolVersions.November2025ProtocolVersion)]
+ [InlineData(true, McpProtocolVersions.November2025ProtocolVersion, McpProtocolVersions.March2025ProtocolVersion)]
+ public async Task InitializeRequest_IsBadRequest_WhenProtocolVersionHeaderDoesNotMatchBody(
+ bool stateless,
+ string protocolVersionHeader,
+ string protocolVersionBody)
+ {
+ await StartAsync(stateless);
+
+ var body = $$$$"""
+ {"jsonrpc":"2.0","id":4242,"method":"initialize","params":{"protocolVersion":"{{{{protocolVersionBody}}}}","capabilities":{},"clientInfo":{"name":"IntegrationTestClient","version":"1.0.0"}}}
+ """;
+ using var request = new HttpRequestMessage(HttpMethod.Post, "") { Content = JsonContent(body) };
+ request.Headers.Add("MCP-Protocol-Version", protocolVersionHeader);
+ using var response = await HttpClient.SendAsync(request, TestContext.Current.CancellationToken);
+
+ Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
+ var json = JsonNode.Parse(await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken));
+ Assert.Equal(4242, json!["id"]!.GetValue());
+ Assert.Equal((int)McpErrorCode.HeaderMismatch, json["error"]!["code"]!.GetValue());
+ }
+
[Fact]
public async Task GetRequest_IsBadRequest_WithInvalidProtocolVersionHeader()
{