Skip to content

Commit 00bb5b2

Browse files
Copilotstephentoub
andauthored
Add Description property to Implementation type per MCP spec (#966)
* Initial plan * Add Description property to Implementation type Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> * Add test to validate client Description from server perspective Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> Co-authored-by: Stephen Toub <stoub@microsoft.com>
1 parent 4b241e7 commit 00bb5b2

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

src/ModelContextProtocol.Core/Protocol/Implementation.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,22 @@ public sealed class Implementation : IBaseMetadata
3737
[JsonPropertyName("version")]
3838
public required string Version { get; set; }
3939

40+
/// <summary>
41+
/// Gets or sets an optional description of the implementation.
42+
/// </summary>
43+
/// <remarks>
44+
/// <para>
45+
/// This description helps users and developers understand what the implementation provides
46+
/// and its purpose. It should clearly explain the functionality and capabilities offered.
47+
/// </para>
48+
/// <para>
49+
/// The description is typically used in documentation, UI displays, and for providing context
50+
/// to users about the server or client they are interacting with.
51+
/// </para>
52+
/// </remarks>
53+
[JsonPropertyName("description")]
54+
public string? Description { get; set; }
55+
4056
/// <summary>
4157
/// Gets or sets an optional list of icons for this implementation.
4258
/// </summary>

tests/ModelContextProtocol.Tests/Client/McpClientTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ protected override void ConfigureServices(ServiceCollection services, IMcpServer
3434
{
3535
Name = "test-server",
3636
Version = "1.0.0",
37+
Description = "A test server for unit testing",
3738
WebsiteUrl = "https://example.com",
3839
Icons =
3940
[
@@ -52,6 +53,7 @@ public async Task CanReadServerInfo()
5253
var serverInfo = client.ServerInfo;
5354
Assert.Equal("test-server", serverInfo.Name);
5455
Assert.Equal("1.0.0", serverInfo.Version);
56+
Assert.Equal("A test server for unit testing", serverInfo.Description);
5557
Assert.Equal("https://example.com", serverInfo.WebsiteUrl);
5658
Assert.NotNull(serverInfo.Icons);
5759
Assert.Equal(2, serverInfo.Icons.Count);
@@ -69,6 +71,29 @@ public async Task CanReadServerInfo()
6971
Assert.Equal("dark", icon1.Theme);
7072
}
7173

74+
[Fact]
75+
public async Task ServerCanReadClientInfo()
76+
{
77+
var clientOptions = new McpClientOptions
78+
{
79+
ClientInfo = new Implementation
80+
{
81+
Name = "test-client",
82+
Version = "2.0.0",
83+
Description = "A test client for validating client-server communication"
84+
}
85+
};
86+
87+
await using McpClient client = await CreateMcpClientForServer(clientOptions);
88+
89+
// Verify the server received the client info with description
90+
var clientInfo = Server.ClientInfo;
91+
Assert.NotNull(clientInfo);
92+
Assert.Equal("test-client", clientInfo.Name);
93+
Assert.Equal("2.0.0", clientInfo.Version);
94+
Assert.Equal("A test client for validating client-server communication", clientInfo.Description);
95+
}
96+
7297
[Theory]
7398
[InlineData(null, 10)]
7499
[InlineData(0.7f, 50)]

tests/ModelContextProtocol.Tests/Protocol/ImplementationTests.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public static void Implementation_SerializationRoundTrip_PreservesAllProperties(
1414
Name = "test-server",
1515
Title = "Test MCP Server",
1616
Version = "1.0.0",
17+
Description = "A test MCP server implementation for demonstration purposes",
1718
Icons =
1819
[
1920
new() { Source = "https://example.com/icon.png", MimeType = "image/png", Sizes = ["48x48"] },
@@ -33,6 +34,7 @@ public static void Implementation_SerializationRoundTrip_PreservesAllProperties(
3334
Assert.Equal(original.Name, deserialized.Name);
3435
Assert.Equal(original.Title, deserialized.Title);
3536
Assert.Equal(original.Version, deserialized.Version);
37+
Assert.Equal(original.Description, deserialized.Description);
3638
Assert.Equal(original.WebsiteUrl, deserialized.WebsiteUrl);
3739
Assert.NotNull(deserialized.Icons);
3840
Assert.Equal(original.Icons.Count, deserialized.Icons.Count);
@@ -66,6 +68,7 @@ public static void Implementation_SerializationRoundTrip_WithoutOptionalProperti
6668
Assert.Equal(original.Name, deserialized.Name);
6769
Assert.Equal(original.Title, deserialized.Title);
6870
Assert.Equal(original.Version, deserialized.Version);
71+
Assert.Equal(original.Description, deserialized.Description);
6972
Assert.Equal(original.Icons, deserialized.Icons);
7073
Assert.Equal(original.WebsiteUrl, deserialized.WebsiteUrl);
7174
}
@@ -78,6 +81,7 @@ public static void Implementation_HasCorrectJsonPropertyNames()
7881
Name = "test-server",
7982
Title = "Test Server",
8083
Version = "1.0.0",
84+
Description = "Test description",
8185
Icons = [new() { Source = "https://example.com/icon.png" }],
8286
WebsiteUrl = "https://example.com"
8387
};
@@ -87,6 +91,7 @@ public static void Implementation_HasCorrectJsonPropertyNames()
8791
Assert.Contains("\"name\":", json);
8892
Assert.Contains("\"title\":", json);
8993
Assert.Contains("\"version\":", json);
94+
Assert.Contains("\"description\":", json);
9095
Assert.Contains("\"icons\":", json);
9196
Assert.Contains("\"websiteUrl\":", json);
9297
}

0 commit comments

Comments
 (0)