Skip to content

Commit 6f1dd69

Browse files
committed
Adding tests and some more cases
1 parent 605e1ba commit 6f1dd69

3 files changed

Lines changed: 176 additions & 8 deletions

File tree

src/ModelContextProtocol/Server/AIFunctionMcpServerTool.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ public override async Task<CallToolResponse> InvokeAsync(
197197

198198
return result switch
199199
{
200+
AIContent aiContent => new()
201+
{
202+
Content = [aiContent.ToContent()]
203+
},
200204
null => new()
201205
{
202206
Content = []
@@ -205,15 +209,11 @@ public override async Task<CallToolResponse> InvokeAsync(
205209
{
206210
Content = [new() { Text = text, Type = "text" }]
207211
},
208-
TextContent textContent => new()
209-
{
210-
Content = [textContent.ToContent()]
211-
},
212-
DataContent dataContent => new()
212+
Content content => new()
213213
{
214-
Content = [dataContent.ToContent()]
214+
Content = [content]
215215
},
216-
string[] texts => new()
216+
IEnumerable<string> texts => new()
217217
{
218218
Content = [.. texts.Select(x => new Content() { Type = "text", Text = x ?? string.Empty })]
219219
},
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
using Microsoft.Extensions.AI;
2+
using ModelContextProtocol.Protocol.Types;
3+
using ModelContextProtocol.Server;
4+
using Moq;
5+
6+
namespace ModelContextProtocol.Tests.Server;
7+
public class McpServerToolReturnTests
8+
{
9+
[Fact]
10+
public async Task CanReturnCollectionOfAIContent()
11+
{
12+
Mock<IMcpServer> mockServer = new();
13+
McpServerTool tool = McpServerTool.Create((IMcpServer server) =>
14+
{
15+
Assert.Same(mockServer.Object, server);
16+
return new List<AIContent>() {
17+
new TextContent("text"),
18+
new DataContent("data:image/png;base64,1234"),
19+
new DataContent("data:audio/wav;base64,1234")
20+
};
21+
});
22+
23+
var result = await tool.InvokeAsync(
24+
new RequestContext<CallToolRequestParams>(mockServer.Object, null),
25+
TestContext.Current.CancellationToken);
26+
27+
Assert.Equal(3, result.Content.Count);
28+
29+
Assert.Equal("text", result.Content[0].Text);
30+
Assert.Equal("text", result.Content[0].Type);
31+
32+
Assert.Equal("1234", result.Content[1].Data);
33+
Assert.Equal("image/png", result.Content[1].MimeType);
34+
Assert.Equal("image", result.Content[1].Type);
35+
36+
Assert.Equal("1234", result.Content[2].Data);
37+
Assert.Equal("audio/wav", result.Content[2].MimeType);
38+
Assert.Equal("audio", result.Content[2].Type);
39+
}
40+
41+
[Theory]
42+
[InlineData("text", "text")]
43+
[InlineData("data:image/png;base64,1234", "image")]
44+
[InlineData("data:audio/wav;base64,1234", "audio")]
45+
public async Task CanReturnSingleAIContent(string data, string type)
46+
{
47+
Mock<IMcpServer> mockServer = new();
48+
McpServerTool tool = McpServerTool.Create((IMcpServer server) =>
49+
{
50+
Assert.Same(mockServer.Object, server);
51+
return type switch
52+
{
53+
"text" => (AIContent)new TextContent(data),
54+
"image" => new DataContent(data),
55+
"audio" => new DataContent(data),
56+
_ => throw new ArgumentException("Invalid type")
57+
};
58+
});
59+
60+
var result = await tool.InvokeAsync(
61+
new RequestContext<CallToolRequestParams>(mockServer.Object, null),
62+
TestContext.Current.CancellationToken);
63+
64+
Assert.Single(result.Content);
65+
Assert.Equal(type, result.Content[0].Type);
66+
67+
if (type != "text")
68+
{
69+
Assert.NotNull(result.Content[0].MimeType);
70+
Assert.Equal(data.Split(',').Last(), result.Content[0].Data);
71+
}
72+
else
73+
{
74+
Assert.Null(result.Content[0].MimeType);
75+
Assert.Equal(data, result.Content[0].Text);
76+
}
77+
}
78+
79+
[Fact]
80+
public async Task CanReturnNullAIContent()
81+
{
82+
Mock<IMcpServer> mockServer = new();
83+
McpServerTool tool = McpServerTool.Create((IMcpServer server) =>
84+
{
85+
Assert.Same(mockServer.Object, server);
86+
return (string?)null;
87+
});
88+
var result = await tool.InvokeAsync(
89+
new RequestContext<CallToolRequestParams>(mockServer.Object, null),
90+
TestContext.Current.CancellationToken);
91+
Assert.Empty(result.Content);
92+
}
93+
94+
[Fact]
95+
public async Task CanReturnString()
96+
{
97+
Mock<IMcpServer> mockServer = new();
98+
McpServerTool tool = McpServerTool.Create((IMcpServer server) =>
99+
{
100+
Assert.Same(mockServer.Object, server);
101+
return "42";
102+
});
103+
var result = await tool.InvokeAsync(
104+
new RequestContext<CallToolRequestParams>(mockServer.Object, null),
105+
TestContext.Current.CancellationToken);
106+
Assert.Single(result.Content);
107+
Assert.Equal("42", result.Content[0].Text);
108+
Assert.Equal("text", result.Content[0].Type);
109+
}
110+
111+
[Fact]
112+
public async Task CanReturnCollectionOfStrings()
113+
{
114+
Mock<IMcpServer> mockServer = new();
115+
McpServerTool tool = McpServerTool.Create((IMcpServer server) =>
116+
{
117+
Assert.Same(mockServer.Object, server);
118+
return new List<string>() { "42", "43" };
119+
});
120+
var result = await tool.InvokeAsync(
121+
new RequestContext<CallToolRequestParams>(mockServer.Object, null),
122+
TestContext.Current.CancellationToken);
123+
Assert.Equal(2, result.Content.Count);
124+
Assert.Equal("42", result.Content[0].Text);
125+
Assert.Equal("text", result.Content[0].Type);
126+
Assert.Equal("43", result.Content[1].Text);
127+
Assert.Equal("text", result.Content[1].Type);
128+
}
129+
130+
[Fact]
131+
public async Task CanReturnMcpContent()
132+
{
133+
Mock<IMcpServer> mockServer = new();
134+
McpServerTool tool = McpServerTool.Create((IMcpServer server) =>
135+
{
136+
Assert.Same(mockServer.Object, server);
137+
return new Content { Text = "42", Type = "text" };
138+
});
139+
var result = await tool.InvokeAsync(
140+
new RequestContext<CallToolRequestParams>(mockServer.Object, null),
141+
TestContext.Current.CancellationToken);
142+
Assert.Single(result.Content);
143+
Assert.Equal("42", result.Content[0].Text);
144+
Assert.Equal("text", result.Content[0].Type);
145+
}
146+
147+
[Fact]
148+
public async Task CanReturnCollectionOfMcpContent()
149+
{
150+
Mock<IMcpServer> mockServer = new();
151+
McpServerTool tool = McpServerTool.Create((IMcpServer server) =>
152+
{
153+
Assert.Same(mockServer.Object, server);
154+
return new List<Content>() { new() { Text = "42", Type = "text" }, new() { Data = "1234", Type = "image", MimeType = "image/png" } };
155+
});
156+
var result = await tool.InvokeAsync(
157+
new RequestContext<CallToolRequestParams>(mockServer.Object, null),
158+
TestContext.Current.CancellationToken);
159+
Assert.Equal(2, result.Content.Count);
160+
Assert.Equal("42", result.Content[0].Text);
161+
Assert.Equal("text", result.Content[0].Type);
162+
Assert.Equal("1234", result.Content[1].Data);
163+
Assert.Equal("image", result.Content[1].Type);
164+
Assert.Equal("image/png", result.Content[1].MimeType);
165+
Assert.Null(result.Content[1].Text);
166+
}
167+
}

tests/ModelContextProtocol.Tests/Server/McpServerToolTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.Extensions.DependencyInjection;
1+
using Microsoft.Extensions.AI;
2+
using Microsoft.Extensions.DependencyInjection;
23
using ModelContextProtocol.Protocol.Types;
34
using ModelContextProtocol.Server;
45
using Moq;

0 commit comments

Comments
 (0)