Skip to content

Commit 0cd7f87

Browse files
committed
Add more tests
1 parent 38b4032 commit 0cd7f87

4 files changed

Lines changed: 94 additions & 5 deletions

File tree

tests/ModelContextProtocol.Tests/Client/McpClientTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,42 @@ protected override void ConfigureServices(ServiceCollection services, IMcpServer
2727
}
2828
mcpServerBuilder.WithTools([McpServerTool.Create([McpServerTool(Destructive = false, OpenWorld = true)] (string i) => $"{i} Result", new() { Name = "ValuesSetViaAttr" })]);
2929
mcpServerBuilder.WithTools([McpServerTool.Create([McpServerTool(Destructive = false, OpenWorld = true)] (string i) => $"{i} Result", new() { Name = "ValuesSetViaOptions", Destructive = true, OpenWorld = false, ReadOnly = true })]);
30+
31+
services.Configure<McpServerOptions>(o =>
32+
{
33+
o.ServerInfo = new Implementation
34+
{
35+
Name = "test-server",
36+
Version = "1.0.0",
37+
WebsiteUrl = "https://example.com",
38+
Icons =
39+
[
40+
new Icon { Source = "https://example.com/icon-48.png", MimeType = "image/png", Sizes = ["48x48"] },
41+
new Icon { Source = "https://example.com/icon.svg", MimeType = "image/svg+xml", Sizes = ["any"] }
42+
]
43+
};
44+
});
45+
}
46+
47+
[Fact]
48+
public async Task CanReadServerInfo()
49+
{
50+
await using McpClient client = await CreateMcpClientForServer();
51+
52+
var serverInfo = client.ServerInfo;
53+
Assert.Equal("test-server", serverInfo.Name);
54+
Assert.Equal("1.0.0", serverInfo.Version);
55+
Assert.Equal("https://example.com", serverInfo.WebsiteUrl);
56+
Assert.NotNull(serverInfo.Icons);
57+
Assert.Equal(2, serverInfo.Icons.Count);
58+
59+
Assert.Equal("https://example.com/icon-48.png", serverInfo.Icons[0].Source);
60+
Assert.Equal("image/png", serverInfo.Icons[0].MimeType);
61+
var icon0Sizes = serverInfo.Icons[0].Sizes; Assert.NotNull(icon0Sizes); Assert.Contains("48x48", icon0Sizes);
62+
63+
Assert.Equal("https://example.com/icon.svg", serverInfo.Icons[1].Source);
64+
Assert.Equal("image/svg+xml", serverInfo.Icons[1].MimeType);
65+
var icon1Sizes = serverInfo.Icons[1].Sizes; Assert.NotNull(icon1Sizes); Assert.Contains("any", icon1Sizes);
3066
}
3167

3268
[Theory]

tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsPromptsTests.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,22 @@ public async Task TitleAttributeProperty_PropagatedToTitle()
179179
Assert.Equal("This is a title", prompt.Title);
180180
}
181181

182+
[Fact]
183+
public async Task IconSourceAttributeProperty_PropagatedToIcons()
184+
{
185+
await using McpClient client = await CreateMcpClientForServer();
186+
187+
var prompts = await client.ListPromptsAsync(cancellationToken: TestContext.Current.CancellationToken);
188+
Assert.NotNull(prompts);
189+
Assert.NotEmpty(prompts);
190+
191+
McpClientPrompt prompt = prompts.First(t => t.Name == "returns_string");
192+
193+
Assert.NotNull(prompt.ProtocolPrompt.Icons);
194+
Assert.NotEmpty(prompt.ProtocolPrompt.Icons);
195+
Assert.Equal("https://example.com/prompt-icon.svg", prompt.ProtocolPrompt.Icons[0].Source);
196+
}
197+
182198
[Fact]
183199
public async Task Throws_When_Prompt_Fails()
184200
{
@@ -325,12 +341,11 @@ public static ChatMessage[] ReturnsChatMessages([Description("The first paramete
325341
new(ChatRole.User, "Summarize."),
326342
];
327343

328-
329344
[McpServerPrompt, Description("Returns chat messages")]
330345
public static ChatMessage[] ThrowsException([Description("The first parameter")] string message) =>
331346
throw new FormatException("uh oh");
332347

333-
[McpServerPrompt(Title = "This is a title"), Description("Returns chat messages")]
348+
[McpServerPrompt(Title = "This is a title", IconSource = "https://example.com/prompt-icon.svg"), Description("Returns chat messages")]
334349
public string ReturnsString([Description("The first parameter")] string message) =>
335350
$"The prompt is: {message}. The id is {id}.";
336351
}

tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsResourcesTests.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,28 @@ public async Task TitleAttributeProperty_PropagatedToTitle()
218218
Assert.Equal("This is another title", resourceTemplate.Title);
219219
}
220220

221+
[Fact]
222+
public async Task IconSourceAttributeProperty_PropagatedToIcons()
223+
{
224+
await using McpClient client = await CreateMcpClientForServer();
225+
226+
var resources = await client.ListResourcesAsync(cancellationToken: TestContext.Current.CancellationToken);
227+
Assert.NotNull(resources);
228+
Assert.NotEmpty(resources);
229+
McpClientResource resource = resources.First(t => t.Name == "some_neat_direct_resource");
230+
Assert.NotNull(resource.ProtocolResource.Icons);
231+
Assert.NotEmpty(resource.ProtocolResource.Icons);
232+
Assert.Equal("https://example.com/direct-resource-icon.svg", resource.ProtocolResource.Icons[0].Source);
233+
234+
var resourceTemplates = await client.ListResourceTemplatesAsync(cancellationToken: TestContext.Current.CancellationToken);
235+
Assert.NotNull(resourceTemplates);
236+
Assert.NotEmpty(resourceTemplates);
237+
McpClientResourceTemplate resourceTemplate = resourceTemplates.First(t => t.Name == "some_neat_templated_resource");
238+
Assert.NotNull(resourceTemplate.ProtocolResourceTemplate.Icons);
239+
Assert.NotEmpty(resourceTemplate.ProtocolResourceTemplate.Icons);
240+
Assert.Equal("https://example.com/templated-resource-icon.svg", resourceTemplate.ProtocolResourceTemplate.Icons[0].Source);
241+
}
242+
221243
[Fact]
222244
public async Task Throws_When_Resource_Fails()
223245
{
@@ -341,10 +363,10 @@ public void Register_Resources_From_Multiple_Sources()
341363
[McpServerResourceType]
342364
public sealed class SimpleResources
343365
{
344-
[McpServerResource(Title = "This is a title"), Description("Some neat direct resource")]
366+
[McpServerResource(Title = "This is a title", IconSource = "https://example.com/direct-resource-icon.svg"), Description("Some neat direct resource")]
345367
public static string SomeNeatDirectResource() => "This is a neat resource";
346368

347-
[McpServerResource(Title = "This is another title"), Description("Some neat resource with parameters")]
369+
[McpServerResource(Title = "This is another title", IconSource = "https://example.com/templated-resource-icon.svg"), Description("Some neat resource with parameters")]
348370
public static string SomeNeatTemplatedResource(string name) => $"This is a neat resource with parameters: {name}";
349371

350372
[McpServerResource]

tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsToolsTests.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,22 @@ public async Task TitleAttributeProperty_PropagatedToTitle()
645645
Assert.Equal("This is a title", tool.ProtocolTool.Annotations?.Title);
646646
}
647647

648+
[Fact]
649+
public async Task IconSourceAttributeProperty_PropagatedToIcons()
650+
{
651+
await using McpClient client = await CreateMcpClientForServer();
652+
653+
var tools = await client.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
654+
Assert.NotNull(tools);
655+
Assert.NotEmpty(tools);
656+
657+
McpClientTool tool = tools.First(t => t.Name == "echo_complex");
658+
659+
Assert.NotNull(tool.ProtocolTool.Icons);
660+
Assert.NotEmpty(tool.ProtocolTool.Icons);
661+
Assert.Equal("https://example.com/tool-icon.svg", tool.ProtocolTool.Icons[0].Source);
662+
}
663+
648664
[Fact]
649665
public async Task HandlesIProgressParameter()
650666
{
@@ -786,7 +802,7 @@ public static int ReturnCancellationToken(CancellationToken cancellationToken)
786802
return cancellationToken.GetHashCode();
787803
}
788804

789-
[McpServerTool(Title = "This is a title")]
805+
[McpServerTool(Title = "This is a title", IconSource = "https://example.com/tool-icon.svg")]
790806
public static string EchoComplex(ComplexObject complex)
791807
{
792808
return complex.Name!;

0 commit comments

Comments
 (0)