diff --git a/src/ModelContextProtocol.Core/Client/McpClient.cs b/src/ModelContextProtocol.Core/Client/McpClient.cs
index 8dad491e..5c5ad2fe 100644
--- a/src/ModelContextProtocol.Core/Client/McpClient.cs
+++ b/src/ModelContextProtocol.Core/Client/McpClient.cs
@@ -129,11 +129,12 @@ public async Task ConnectAsync(CancellationToken cancellationToken = default)
try
{
// Send initialize request
+ string requestProtocol = _options.ProtocolVersion ?? McpSession.LatestProtocolVersion;
var initializeResponse = await this.SendRequestAsync(
RequestMethods.Initialize,
new InitializeRequestParams
{
- ProtocolVersion = _options.ProtocolVersion,
+ ProtocolVersion = requestProtocol,
Capabilities = _options.Capabilities ?? new ClientCapabilities(),
ClientInfo = _options.ClientInfo ?? DefaultImplementation,
},
@@ -154,10 +155,13 @@ public async Task ConnectAsync(CancellationToken cancellationToken = default)
_serverInstructions = initializeResponse.Instructions;
// Validate protocol version
- if (initializeResponse.ProtocolVersion != _options.ProtocolVersion)
+ bool isResponseProtocolValid =
+ _options.ProtocolVersion is { } optionsProtocol ? optionsProtocol == initializeResponse.ProtocolVersion :
+ McpSession.SupportedProtocolVersions.Contains(initializeResponse.ProtocolVersion);
+ if (!isResponseProtocolValid)
{
- LogServerProtocolVersionMismatch(EndpointName, _options.ProtocolVersion, initializeResponse.ProtocolVersion);
- throw new McpException($"Server protocol version mismatch. Expected {_options.ProtocolVersion}, got {initializeResponse.ProtocolVersion}");
+ LogServerProtocolVersionMismatch(EndpointName, requestProtocol, initializeResponse.ProtocolVersion);
+ throw new McpException($"Server protocol version mismatch. Expected {requestProtocol}, got {initializeResponse.ProtocolVersion}");
}
// Send initialized notification
diff --git a/src/ModelContextProtocol.Core/Client/McpClientOptions.cs b/src/ModelContextProtocol.Core/Client/McpClientOptions.cs
index 2a5d2a84..96f36bbc 100644
--- a/src/ModelContextProtocol.Core/Client/McpClientOptions.cs
+++ b/src/ModelContextProtocol.Core/Client/McpClientOptions.cs
@@ -34,11 +34,18 @@ public class McpClientOptions
/// Gets or sets the protocol version to request from the server, using a date-based versioning scheme.
///
///
+ ///
/// The protocol version is a key part of the initialization handshake. The client and server must
- /// agree on a compatible protocol version to communicate successfully. If the server doesn't support
- /// the requested version, it will respond with a version mismatch error.
+ /// agree on a compatible protocol version to communicate successfully.
+ ///
+ ///
+ /// If non-, this version will be sent to the server, and the handshake
+ /// will fail if the version in the server's response does not match this version.
+ /// If , the client will request the latest version supported by the server
+ /// but will allow any supported version that the server advertizes in its response.
+ ///
///
- public string ProtocolVersion { get; set; } = "2024-11-05";
+ public string? ProtocolVersion { get; set; }
///
/// Gets or sets a timeout for the client-server initialization handshake sequence.
diff --git a/src/ModelContextProtocol.Core/McpSession.cs b/src/ModelContextProtocol.Core/McpSession.cs
index 248538c3..8a0ae6b1 100644
--- a/src/ModelContextProtocol.Core/McpSession.cs
+++ b/src/ModelContextProtocol.Core/McpSession.cs
@@ -28,6 +28,16 @@ internal sealed partial class McpSession : IDisposable
private static readonly Histogram s_serverOperationDuration = Diagnostics.CreateDurationHistogram(
"mcp.server.operation.duration", "Measures the duration of inbound message processing.", longBuckets: false);
+ /// The latest version of the protocol supported by this implementation.
+ internal const string LatestProtocolVersion = "2025-03-26";
+
+ /// All protocol versions supported by this implementation.
+ internal static readonly string[] SupportedProtocolVersions =
+ [
+ "2024-11-05",
+ LatestProtocolVersion,
+ ];
+
private readonly bool _isServer;
private readonly string _transportKind;
private readonly ITransport _transport;
diff --git a/src/ModelContextProtocol.Core/Protocol/PaginatedRequest.cs b/src/ModelContextProtocol.Core/Protocol/PaginatedRequest.cs
index 89b17398..3e25b3b6 100644
--- a/src/ModelContextProtocol.Core/Protocol/PaginatedRequest.cs
+++ b/src/ModelContextProtocol.Core/Protocol/PaginatedRequest.cs
@@ -6,7 +6,7 @@ namespace ModelContextProtocol.Protocol;
/// Provides a base class for paginated requests.
///
///
-/// See the schema for details
+/// See the schema for details
///
public class PaginatedRequestParams : RequestParams
{
diff --git a/src/ModelContextProtocol.Core/Server/McpServer.cs b/src/ModelContextProtocol.Core/Server/McpServer.cs
index 338c631f..808300f0 100644
--- a/src/ModelContextProtocol.Core/Server/McpServer.cs
+++ b/src/ModelContextProtocol.Core/Server/McpServer.cs
@@ -161,9 +161,20 @@ private void ConfigureInitialize(McpServerOptions options)
UpdateEndpointNameWithClientInfo();
GetSessionOrThrow().EndpointName = EndpointName;
+ // Negotiate a protocol version. If the server options provide one, use that.
+ // Otherwise, try to use whatever the client requested as long as it's supported.
+ // If it's not supported, fall back to the latest supported version.
+ string? protocolVersion = options.ProtocolVersion;
+ if (protocolVersion is null)
+ {
+ protocolVersion = request?.ProtocolVersion is string clientProtocolVersion && McpSession.SupportedProtocolVersions.Contains(clientProtocolVersion) ?
+ clientProtocolVersion :
+ McpSession.LatestProtocolVersion;
+ }
+
return new InitializeResult
{
- ProtocolVersion = options.ProtocolVersion,
+ ProtocolVersion = protocolVersion,
Instructions = options.ServerInstructions,
ServerInfo = options.ServerInfo ?? DefaultImplementation,
Capabilities = ServerCapabilities ?? new(),
diff --git a/src/ModelContextProtocol.Core/Server/McpServerOptions.cs b/src/ModelContextProtocol.Core/Server/McpServerOptions.cs
index 3d6de61b..e84a012c 100644
--- a/src/ModelContextProtocol.Core/Server/McpServerOptions.cs
+++ b/src/ModelContextProtocol.Core/Server/McpServerOptions.cs
@@ -32,8 +32,11 @@ public class McpServerOptions
///
/// The protocol version defines which features and message formats this server supports.
/// This uses a date-based versioning scheme in the format "YYYY-MM-DD".
+ /// If , the server will advertize to the client the version requested
+ /// by the client if that version is known to be supported, and otherwise will advertize the latest
+ /// version supported by the server.
///
- public string ProtocolVersion { get; set; } = "2024-11-05";
+ public string? ProtocolVersion { get; set; }
///
/// Gets or sets a timeout used for the client-server initialization handshake sequence.
diff --git a/tests/ModelContextProtocol.TestServer/Program.cs b/tests/ModelContextProtocol.TestServer/Program.cs
index 4b9d64de..dbecbf48 100644
--- a/tests/ModelContextProtocol.TestServer/Program.cs
+++ b/tests/ModelContextProtocol.TestServer/Program.cs
@@ -46,7 +46,6 @@ private static async Task Main(string[] args)
Logging = ConfigureLogging(),
Completions = ConfigureCompletions(),
},
- ProtocolVersion = "2024-11-05",
ServerInstructions = "This is a test server with only stub functionality",
};
diff --git a/tests/ModelContextProtocol.TestSseServer/Program.cs b/tests/ModelContextProtocol.TestSseServer/Program.cs
index 379e34fc..2e37c1d7 100644
--- a/tests/ModelContextProtocol.TestSseServer/Program.cs
+++ b/tests/ModelContextProtocol.TestSseServer/Program.cs
@@ -34,7 +34,6 @@ private static void ConfigureOptions(McpServerOptions options)
Resources = new(),
Prompts = new(),
};
- options.ProtocolVersion = "2024-11-05";
options.ServerInstructions = "This is a test server with only stub functionality";
Console.WriteLine("Registering handlers.");