Skip to content

Commit 1c7865f

Browse files
author
tarekgh
committed
Remove serverInfo from server/discover result body
The 2026-07-28 revision carries serverInfo in the result _meta (io.modelcontextprotocol/serverInfo), not the discover body. Since server/discover and its serverInfo were both introduced in this revision and serverInfo moved to _meta within it, no released protocol version carried serverInfo in the body, so removing the body property is not a breaking change against the finalized spec. Remove the DiscoverResult.ServerInfo property, drop the client body fallback in GetServerInfoFromDiscover (read only from _meta), and update test mocks to emit serverInfo via _meta to match real servers.
1 parent e024906 commit 1c7865f

11 files changed

Lines changed: 42 additions & 37 deletions

src/ModelContextProtocol.Core/Client/McpClientImpl.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -490,11 +490,9 @@ async Task<DiscoverResult> SendDiscoverAsync(string protocolVersion, Cancellatio
490490
}
491491

492492
/// <summary>
493-
/// Resolves the server identity from a <c>server/discover</c> result. The 2026-07-28 revision moved
494-
/// <c>serverInfo</c> from the result body into the result's
495-
/// <c>_meta/io.modelcontextprotocol/serverInfo</c> field. The body remains a fallback for servers
496-
/// that implemented the earlier draft shape. Identity is optional, so a server that provides
497-
/// neither yields <see langword="null"/>.
493+
/// Resolves the server identity from a <c>server/discover</c> result. The 2026-07-28 revision carries
494+
/// <c>serverInfo</c> in the result's <c>_meta/io.modelcontextprotocol/serverInfo</c> field rather than
495+
/// the result body. Identity is optional, so a server that omits it yields <see langword="null"/>.
498496
/// </summary>
499497
private static Implementation? GetServerInfoFromDiscover(DiscoverResult discoverResult)
500498
{
@@ -512,7 +510,7 @@ async Task<DiscoverResult> SendDiscoverAsync(string protocolVersion, Cancellatio
512510
$"Discover result metadata '{MetaKeys.ServerInfo}' must contain a server implementation.");
513511
}
514512

515-
return discoverResult.ServerInfo;
513+
return null;
516514
}
517515

518516
/// <summary>

src/ModelContextProtocol.Core/Protocol/DiscoverResult.cs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,6 @@ public sealed class DiscoverResult : Result, ICacheableResult
3131
[JsonPropertyName("capabilities")]
3232
public required ServerCapabilities Capabilities { get; set; }
3333

34-
/// <summary>
35-
/// Gets or sets information about the server implementation.
36-
/// </summary>
37-
/// <remarks>
38-
/// The 2026-07-28 specification moved <c>serverInfo</c> from the <c>server/discover</c> result
39-
/// body to each result's <c>_meta/io.modelcontextprotocol/serverInfo</c> field
40-
/// (<see cref="MetaKeys.ServerInfo"/>). This property remains so clients can read the body field
41-
/// from servers that implemented the earlier draft shape; it is omitted from serialization when
42-
/// <see langword="null"/>.
43-
/// </remarks>
44-
[JsonPropertyName("serverInfo")]
45-
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
46-
public Implementation? ServerInfo { get; set; }
47-
4834
/// <summary>
4935
/// Gets or sets optional instructions describing how to use the server and its features.
5036
/// </summary>

tests/ModelContextProtocol.AspNetCore.Tests/July2026ProtocolHttpFallbackTests.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,10 @@ await StartServerAsync(async context =>
324324
{
325325
SupportedVersions = [McpProtocolVersions.July2026ProtocolVersion],
326326
Capabilities = new ServerCapabilities(),
327-
ServerInfo = new Implementation { Name = "bad-per-request-metadata-server", Version = "1.0" },
327+
Meta = new JsonObject
328+
{
329+
[MetaKeys.ServerInfo] = JsonSerializer.SerializeToNode(new Implementation { Name = "bad-per-request-metadata-server", Version = "1.0" }, McpJsonUtilities.DefaultOptions),
330+
},
328331
TimeToLive = TimeSpan.Zero,
329332
CacheScope = CacheScope.Private,
330333
}, McpJsonUtilities.DefaultOptions),
@@ -394,7 +397,10 @@ await StartServerAsync(async context =>
394397
{
395398
SupportedVersions = [McpProtocolVersions.July2026ProtocolVersion],
396399
Capabilities = new ServerCapabilities(),
397-
ServerInfo = new Implementation { Name = "per-request-metadata-server", Version = "1.0" },
400+
Meta = new JsonObject
401+
{
402+
[MetaKeys.ServerInfo] = JsonSerializer.SerializeToNode(new Implementation { Name = "per-request-metadata-server", Version = "1.0" }, McpJsonUtilities.DefaultOptions),
403+
},
398404
TimeToLive = TimeSpan.Zero,
399405
CacheScope = CacheScope.Private,
400406
}, McpJsonUtilities.DefaultOptions),

tests/ModelContextProtocol.AspNetCore.Tests/StreamableHttpClientConformanceTests.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,10 @@ private async Task StartHeaderCapturingServer(
766766
["io.modelcontextprotocol/tasks"] = new JsonObject(),
767767
},
768768
},
769-
ServerInfo = new Implementation { Name = "header-capture", Version = "1.0" },
769+
Meta = new JsonObject
770+
{
771+
[MetaKeys.ServerInfo] = JsonSerializer.SerializeToNode(new Implementation { Name = "header-capture", Version = "1.0" }, McpJsonUtilities.DefaultOptions),
772+
},
770773
TimeToLive = TimeSpan.Zero,
771774
CacheScope = CacheScope.Private,
772775
ResultType = "complete",

tests/ModelContextProtocol.AspNetCore.Tests/StreamableHttpServerConformanceTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1160,7 +1160,6 @@ private static DiscoverResult AssertDiscoverServerInfo(JsonRpcResponse rpcRespon
11601160
var discoverResult = AssertType<DiscoverResult>(rpcResponse.Result);
11611161

11621162
// Server identity is carried in the result _meta, not the discover body.
1163-
Assert.Null(discoverResult.ServerInfo);
11641163
var serverInfoNode = discoverResult.Meta?[MetaKeys.ServerInfo];
11651164
Assert.NotNull(serverInfoNode);
11661165
var serverInfo = JsonSerializer.Deserialize<Implementation>(serverInfoNode, McpJsonUtilities.DefaultOptions);

tests/ModelContextProtocol.Tests/Client/July2026ProtocolFallbackTests.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using ModelContextProtocol.Tests.Utils;
44
using System.Diagnostics;
55
using System.Text.Json;
6+
using System.Text.Json.Nodes;
67
using System.Threading.Channels;
78

89
namespace ModelContextProtocol.Tests.Client;
@@ -351,7 +352,10 @@ private void HandleOutgoingMessage(JsonRpcMessage message)
351352
{
352353
SupportedVersions = [McpProtocolVersions.July2026ProtocolVersion],
353354
Capabilities = new ServerCapabilities(),
354-
ServerInfo = new Implementation { Name = "per-request-metadata-test-server", Version = "1.0.0" },
355+
Meta = new JsonObject
356+
{
357+
[MetaKeys.ServerInfo] = JsonSerializer.SerializeToNode(new Implementation { Name = "per-request-metadata-test-server", Version = "1.0.0" }, McpJsonUtilities.DefaultOptions),
358+
},
355359
}, McpJsonUtilities.DefaultOptions),
356360
});
357361
}

tests/ModelContextProtocol.Tests/Client/McpClientCreationTests.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using ModelContextProtocol.Tests.Utils;
55
using System.IO.Pipelines;
66
using System.Text.Json;
7+
using System.Text.Json.Nodes;
78
using System.Threading.Channels;
89

910
namespace ModelContextProtocol.Tests.Client;
@@ -179,10 +180,13 @@ public virtual Task SendMessageAsync(JsonRpcMessage message, CancellationToken c
179180
{
180181
Capabilities = new ServerCapabilities(),
181182
SupportedVersions = [McpProtocolVersions.July2026ProtocolVersion],
182-
ServerInfo = new Implementation
183+
Meta = new JsonObject
183184
{
184-
Name = "NopTransport",
185-
Version = "1.0.0"
185+
[MetaKeys.ServerInfo] = JsonSerializer.SerializeToNode(new Implementation
186+
{
187+
Name = "NopTransport",
188+
Version = "1.0.0"
189+
}, McpJsonUtilities.DefaultOptions),
186190
},
187191
}, McpJsonUtilities.DefaultOptions),
188192
});

tests/ModelContextProtocol.Tests/Client/MrtrIntegrationTests.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,10 @@ public async Task LegacyRequestOnMrtrSession_LogsWarning()
195195
{
196196
SupportedVersions = new List<string> { "2026-07-28" },
197197
Capabilities = new ServerCapabilities(),
198-
ServerInfo = new Implementation { Name = "MockMrtrServer", Version = "1.0" },
198+
Meta = new JsonObject
199+
{
200+
[MetaKeys.ServerInfo] = JsonSerializer.SerializeToNode(new Implementation { Name = "MockMrtrServer", Version = "1.0" }, McpJsonUtilities.DefaultOptions),
201+
},
199202
}, McpJsonUtilities.DefaultOptions),
200203
};
201204
await WriteJsonRpcAsync(serverWriter, discoverResponse);
@@ -445,7 +448,10 @@ public async Task IncompleteResultRetry_OmittingRequestState_StripsStaleStateFro
445448
{
446449
SupportedVersions = ["2026-07-28"],
447450
Capabilities = new ServerCapabilities { Tools = new() },
448-
ServerInfo = new Implementation { Name = "MrtrServer", Version = "1.0" }
451+
Meta = new JsonObject
452+
{
453+
[MetaKeys.ServerInfo] = JsonSerializer.SerializeToNode(new Implementation { Name = "MrtrServer", Version = "1.0" }, McpJsonUtilities.DefaultOptions),
454+
},
449455
}, McpJsonUtilities.DefaultOptions),
450456
};
451457
await WriteJsonRpcAsync(serverWriter, discoverResponse);

tests/ModelContextProtocol.Tests/Protocol/CacheableResultWarningTests.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,10 @@ private static async Task PerformHandshakeAsync(
292292
{
293293
SupportedVersions = [serverProtocolVersion],
294294
Capabilities = new ServerCapabilities(),
295-
ServerInfo = new Implementation { Name = "MockServer", Version = "1.0" },
295+
Meta = new JsonObject
296+
{
297+
[MetaKeys.ServerInfo] = JsonSerializer.SerializeToNode(new Implementation { Name = "MockServer", Version = "1.0" }, McpJsonUtilities.DefaultOptions),
298+
},
296299
}, McpJsonUtilities.DefaultOptions),
297300
}, cancellationToken);
298301
}

tests/ModelContextProtocol.Tests/Protocol/DiscoverProtocolTests.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ public static void DiscoverResult_SerializationRoundTrip_PreservesAllProperties(
4444
{
4545
Tools = new ToolsCapability { ListChanged = true },
4646
},
47-
ServerInfo = new Implementation { Name = "test-server", Version = "2.0" },
4847
Instructions = "Use this server for testing.",
4948
};
5049

@@ -55,7 +54,6 @@ public static void DiscoverResult_SerializationRoundTrip_PreservesAllProperties(
5554
Assert.Equal(["2025-11-25", "2026-07-28"], deserialized.SupportedVersions);
5655
Assert.NotNull(deserialized.Capabilities.Tools);
5756
Assert.True(deserialized.Capabilities.Tools.ListChanged);
58-
Assert.Equal("test-server", deserialized.ServerInfo?.Name);
5957
Assert.Equal("Use this server for testing.", deserialized.Instructions);
6058
}
6159

@@ -66,7 +64,6 @@ public static void DiscoverResult_SerializationRoundTrip_WithMinimalProperties()
6664
{
6765
SupportedVersions = new List<string> { "2026-07-28" },
6866
Capabilities = new ServerCapabilities(),
69-
ServerInfo = new Implementation { Name = "minimal-server", Version = "1.0" },
7067
};
7168

7269
var json = JsonSerializer.Serialize(original, McpJsonUtilities.DefaultOptions);

0 commit comments

Comments
 (0)