diff --git a/Directory.Packages.props b/Directory.Packages.props
index a67fc2e7f4..8a64afd25b 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -89,8 +89,8 @@
-
-
+
+
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Client/MockClientTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Client/MockClientTests.cs
index 9db986c6ea..58fd2d43d2 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Client/MockClientTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Client/MockClientTests.cs
@@ -16,7 +16,9 @@ private static McpServerOptions CreateOptions(McpServerHandlers? serverHandlers
{
return new McpServerOptions
{
- ProtocolVersion = "2024",
+ // Use a supported protocol version. preview.3 tightened validation and
+ // rejects bare '2024'; supported versions: 2024-11-05, 2025-11-25, 2026-07-28.
+ ProtocolVersion = "2025-11-25",
InitializationTimeout = TimeSpan.FromSeconds(30),
Handlers = serverHandlers ?? new(),
ServerInfo = new Implementation { Name = "Azure MCP", Version = "1.0.0-beta" }
@@ -50,7 +52,7 @@ await Invoke_Request_To_Server(
Assert.NotNull(result);
Assert.Equal("Azure MCP", result.ServerInfo.Name);
Assert.Equal("1.0.0-beta", result.ServerInfo.Version);
- Assert.Equal("2024", result.ProtocolVersion);
+ Assert.Equal("2025-11-25", result.ProtocolVersion);
});
}
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/ClientToolTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/ClientToolTests.cs
index 4a0ac6835a..8958a5bb6e 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/ClientToolTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/ClientToolTests.cs
@@ -112,7 +112,13 @@ public async Task Should_Error_When_Resources_Unsubscribe_Not_Supported()
[Fact]
public async Task Should_Not_Hang_On_Logging_SetLevel_Not_Supported()
{
- await Client.SetLoggingLevelAsync(LoggingLevel.Info, cancellationToken: TestContext.Current.CancellationToken);
+ // logging/setLevel was removed in MCP 2026-07-28 (SDK 2.0.0-preview.3).
+ // The method is no longer supported; per-request log level is now set via
+ // _meta/io.modelcontextprotocol/logLevel. The call should throw rather than hang.
+ var ex = await Assert.ThrowsAsync(
+ async () => await Client.SetLoggingLevelAsync(LoggingLevel.Info,
+ cancellationToken: TestContext.Current.CancellationToken));
+ Assert.Contains("logging/setLevel", ex.Message, StringComparison.OrdinalIgnoreCase);
}
[Fact]
diff --git a/servers/Azure.Mcp.Server/changelog-entries/1784845074408.yaml b/servers/Azure.Mcp.Server/changelog-entries/1784845074408.yaml
new file mode 100644
index 0000000000..d071b34bf4
--- /dev/null
+++ b/servers/Azure.Mcp.Server/changelog-entries/1784845074408.yaml
@@ -0,0 +1,4 @@
+changes:
+ - section: "Other Changes"
+ description: "Updated ModelContextProtocol packages to 2.0.0-preview.3."
+ subsection: "Dependency Updates"
diff --git a/servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/ConsolidatedModeTests.cs b/servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/ConsolidatedModeTests.cs
index 5ae800e00d..e78ab176f1 100644
--- a/servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/ConsolidatedModeTests.cs
+++ b/servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/ConsolidatedModeTests.cs
@@ -2,12 +2,51 @@
// Licensed under the MIT License.
using System.Net;
+using System.Text.Json.Nodes;
using Xunit;
namespace Azure.Mcp.Server.Tests.Infrastructure;
public class ConsolidatedModeTests
{
+ private const string StatelessProtocolVersion = "2026-07-28";
+
+ ///
+ /// Builds a for a 2026-07-28 stateless JSON-RPC request
+ /// containing the required _meta envelope fields. Optional extra _meta
+ /// entries (e.g. W3C trace context) can be merged in via .
+ ///
+ private static StringContent CreateStateless2026RequestContent(
+ string method,
+ int id = 1,
+ JsonObject? extraMeta = null)
+ {
+ var meta = new JsonObject
+ {
+ ["io.modelcontextprotocol/protocolVersion"] = StatelessProtocolVersion,
+ ["io.modelcontextprotocol/clientInfo"] = new JsonObject { ["name"] = "test-client", ["version"] = "1.0" },
+ ["io.modelcontextprotocol/clientCapabilities"] = new JsonObject()
+ };
+
+ if (extraMeta != null)
+ {
+ foreach (var (key, value) in extraMeta)
+ {
+ meta[key] = value?.DeepClone();
+ }
+ }
+
+ var body = new JsonObject
+ {
+ ["jsonrpc"] = "2.0",
+ ["id"] = id,
+ ["method"] = method,
+ ["params"] = new JsonObject { ["_meta"] = meta }
+ };
+
+ return new StringContent(body.ToJsonString(), System.Text.Encoding.UTF8, "application/json");
+ }
+
[Fact]
public async Task ConsolidatedMode_HttpTransport_Should_List_Tools_On_Root_Endpoint()
{
@@ -37,10 +76,10 @@ public async Task ConsolidatedMode_HttpTransport_Should_List_Tools_On_Root_Endpo
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, $"http://127.0.0.1:{port}/")
{
- Content = new StringContent("{" + "\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\",\"params\":{}" + "}", System.Text.Encoding.UTF8, "application/json")
+ Content = CreateStateless2026RequestContent("tools/list")
};
request.Headers.TryAddWithoutValidation("Accept", "application/json, text/event-stream");
- request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", "2026-07-28");
+ request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", StatelessProtocolVersion);
request.Headers.TryAddWithoutValidation("Mcp-Method", "tools/list");
request.Headers.TryAddWithoutValidation("Mcp-Name", "tools/list");
@@ -93,16 +132,17 @@ public async Task ConsolidatedMode_HttpTransport_Should_Accept_Meta_In_Request_P
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, $"http://127.0.0.1:{port}/")
{
- Content = new StringContent(
- "{" +
- "\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\",\"params\":{\"_meta\":{\"traceparent\":\"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01\",\"clientId\":\"phase2-hardening-test\"}}" +
- "}",
- System.Text.Encoding.UTF8,
- "application/json")
+ Content = CreateStateless2026RequestContent(
+ "tools/list",
+ extraMeta: new JsonObject
+ {
+ ["traceparent"] = "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
+ ["clientId"] = "phase2-hardening-test"
+ })
};
request.Headers.TryAddWithoutValidation("Accept", "application/json, text/event-stream");
- request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", "2026-07-28");
+ request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", StatelessProtocolVersion);
request.Headers.TryAddWithoutValidation("Mcp-Method", "tools/list");
request.Headers.TryAddWithoutValidation("Mcp-Name", "tools/list");
@@ -152,16 +192,11 @@ public async Task ConsolidatedMode_HttpTransport_Should_Support_ServerDiscover_W
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, $"http://127.0.0.1:{port}/")
{
- Content = new StringContent(
- "{" +
- "\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"server/discover\",\"params\":{}" +
- "}",
- System.Text.Encoding.UTF8,
- "application/json")
+ Content = CreateStateless2026RequestContent("server/discover")
};
request.Headers.TryAddWithoutValidation("Accept", "application/json, text/event-stream");
- request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", "2026-07-28");
+ request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", StatelessProtocolVersion);
request.Headers.TryAddWithoutValidation("Mcp-Method", "server/discover");
request.Headers.TryAddWithoutValidation("Mcp-Name", "server/discover");
@@ -213,10 +248,10 @@ public async Task ConsolidatedMode_HttpTransport_Should_Handle_Repeated_ToolsLis
using var request1 = new HttpRequestMessage(HttpMethod.Post, $"http://127.0.0.1:{port}/")
{
- Content = new StringContent("{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\",\"params\":{}}", System.Text.Encoding.UTF8, "application/json")
+ Content = CreateStateless2026RequestContent("tools/list", id: 1)
};
request1.Headers.TryAddWithoutValidation("Accept", "application/json, text/event-stream");
- request1.Headers.TryAddWithoutValidation("MCP-Protocol-Version", "2026-07-28");
+ request1.Headers.TryAddWithoutValidation("MCP-Protocol-Version", StatelessProtocolVersion);
request1.Headers.TryAddWithoutValidation("Mcp-Method", "tools/list");
request1.Headers.TryAddWithoutValidation("Mcp-Name", "tools/list");
@@ -225,10 +260,10 @@ public async Task ConsolidatedMode_HttpTransport_Should_Handle_Repeated_ToolsLis
using var request2 = new HttpRequestMessage(HttpMethod.Post, $"http://127.0.0.1:{port}/")
{
- Content = new StringContent("{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\",\"params\":{}}", System.Text.Encoding.UTF8, "application/json")
+ Content = CreateStateless2026RequestContent("tools/list", id: 2)
};
request2.Headers.TryAddWithoutValidation("Accept", "application/json, text/event-stream");
- request2.Headers.TryAddWithoutValidation("MCP-Protocol-Version", "2026-07-28");
+ request2.Headers.TryAddWithoutValidation("MCP-Protocol-Version", StatelessProtocolVersion);
request2.Headers.TryAddWithoutValidation("Mcp-Method", "tools/list");
request2.Headers.TryAddWithoutValidation("Mcp-Name", "tools/list");
@@ -341,22 +376,18 @@ public async Task ConsolidatedMode_HttpTransport_Should_Propagate_W3C_Trace_Cont
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, $"http://127.0.0.1:{port}/")
{
- Content = new StringContent(
- "{" +
- "\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\",\"params\":{" +
- "\"_meta\":{" +
- "\"traceparent\":\"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01\"," +
- "\"tracestate\":\"vendor1=opaquevalue1,vendor2=opaquevalue2\"," +
- "\"baggage\":\"userId=alice,serverNode=DF:28,isProduction=false\"" +
- "}" +
- "}" +
- "}",
- System.Text.Encoding.UTF8,
- "application/json")
+ Content = CreateStateless2026RequestContent(
+ "tools/list",
+ extraMeta: new JsonObject
+ {
+ ["traceparent"] = "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
+ ["tracestate"] = "vendor1=opaquevalue1,vendor2=opaquevalue2",
+ ["baggage"] = "userId=alice,serverNode=DF:28,isProduction=false"
+ })
};
request.Headers.TryAddWithoutValidation("Accept", "application/json, text/event-stream");
- request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", "2026-07-28");
+ request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", StatelessProtocolVersion);
request.Headers.TryAddWithoutValidation("Mcp-Method", "tools/list");
request.Headers.TryAddWithoutValidation("Mcp-Name", "tools/list");
@@ -634,10 +665,10 @@ public async Task ConsolidatedMode_HttpTransport_Should_Accept_NonNamedMethod_Wi
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, $"http://127.0.0.1:{port}/")
{
- Content = new StringContent("{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\",\"params\":{}}", System.Text.Encoding.UTF8, "application/json")
+ Content = CreateStateless2026RequestContent("tools/list")
};
request.Headers.TryAddWithoutValidation("Accept", "application/json, text/event-stream");
- request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", "2026-07-28");
+ request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", StatelessProtocolVersion);
request.Headers.TryAddWithoutValidation("Mcp-Method", "tools/list");
// Intentionally omit Mcp-Name — valid for a non-named method
diff --git a/servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/ServerModeCoverageTests.cs b/servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/ServerModeCoverageTests.cs
index 61caed58aa..1aa98a4fb9 100644
--- a/servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/ServerModeCoverageTests.cs
+++ b/servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/ServerModeCoverageTests.cs
@@ -115,6 +115,7 @@ public async Task NamespaceMode_Should_List_Tools_Without_Initialize()
public async Task AllMode_Should_List_Tools_Without_Initialize()
{
// "all" mode exposes every individual Azure tool directly.
+ // Uses a longer timeout because registering all tools takes more time on slow CI runners.
Assert.True(File.Exists(AzmcpPath), $"Executable not found at {AzmcpPath}. Please build the Azure.Mcp.Server project first.");
var processStartInfo = new System.Diagnostics.ProcessStartInfo
@@ -141,7 +142,8 @@ public async Task AllMode_Should_List_Tools_Without_Initialize()
await process.StandardInput.WriteLineAsync(listToolsRequest);
await process.StandardInput.FlushAsync(TestContext.Current.CancellationToken);
- var response = await ReadResponseAsync(process.StandardOutput);
+ // Allow up to 60 s: "all" mode registers every tool and is slower on macOS CI runners.
+ var response = await ReadResponseAsync(process.StandardOutput, TimeSpan.FromSeconds(60));
Assert.NotNull(response);
Assert.Contains("\"result\"", response, StringComparison.OrdinalIgnoreCase);
@@ -156,9 +158,9 @@ public async Task AllMode_Should_List_Tools_Without_Initialize()
}
}
- private static async Task ReadResponseAsync(StreamReader reader)
+ private static async Task ReadResponseAsync(StreamReader reader, TimeSpan? timeout = null)
{
- using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(15));
+ using var cts = new CancellationTokenSource(timeout ?? TimeSpan.FromSeconds(15));
try
{
return await reader.ReadLineAsync(cts.Token);
diff --git a/servers/Fabric.Mcp.Server/tests/Fabric.Mcp.Server.Tests/Infrastructure/ServerStartupTests.cs b/servers/Fabric.Mcp.Server/tests/Fabric.Mcp.Server.Tests/Infrastructure/ServerStartupTests.cs
index e668c23424..8be8292c54 100644
--- a/servers/Fabric.Mcp.Server/tests/Fabric.Mcp.Server.Tests/Infrastructure/ServerStartupTests.cs
+++ b/servers/Fabric.Mcp.Server/tests/Fabric.Mcp.Server.Tests/Infrastructure/ServerStartupTests.cs
@@ -2,12 +2,39 @@
// Licensed under the MIT License.
using System.Net;
+using System.Text.Json.Nodes;
using Xunit;
namespace Fabric.Mcp.Server.Tests.Infrastructure;
public class ServerStartupTests
{
+ private const string StatelessProtocolVersion = "2026-07-28";
+
+ ///
+ /// Builds a for a 2026-07-28 stateless JSON-RPC request
+ /// containing the required _meta envelope fields.
+ ///
+ private static StringContent CreateStateless2026RequestContent(string method, int id = 1)
+ {
+ var body = new JsonObject
+ {
+ ["jsonrpc"] = "2.0",
+ ["id"] = id,
+ ["method"] = method,
+ ["params"] = new JsonObject
+ {
+ ["_meta"] = new JsonObject
+ {
+ ["io.modelcontextprotocol/protocolVersion"] = StatelessProtocolVersion,
+ ["io.modelcontextprotocol/clientInfo"] = new JsonObject { ["name"] = "test-client", ["version"] = "1.0" },
+ ["io.modelcontextprotocol/clientCapabilities"] = new JsonObject()
+ }
+ }
+ };
+ return new StringContent(body.ToJsonString(), System.Text.Encoding.UTF8, "application/json");
+ }
+
[Fact]
public async Task Server_Should_List_Tools_Over_Http_Root_Endpoint()
{
@@ -47,10 +74,10 @@ public async Task Server_Should_List_Tools_Over_Http_Root_Endpoint()
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, $"http://127.0.0.1:{port}/")
{
- Content = new StringContent("{" + "\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\",\"params\":{}" + "}", System.Text.Encoding.UTF8, "application/json")
+ Content = CreateStateless2026RequestContent("tools/list")
};
request.Headers.TryAddWithoutValidation("Accept", "application/json, text/event-stream");
- request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", "2026-07-28");
+ request.Headers.TryAddWithoutValidation("MCP-Protocol-Version", StatelessProtocolVersion);
request.Headers.TryAddWithoutValidation("Mcp-Method", "tools/list");
request.Headers.TryAddWithoutValidation("Mcp-Name", "tools/list");