Skip to content

Commit 23d5d20

Browse files
Copilotjozkee
andcommitted
Add missing tests for mixed MCP/Function approval scenarios
Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com>
1 parent 598f78b commit 23d5d20

1 file changed

Lines changed: 211 additions & 0 deletions

File tree

test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/FunctionInvokingChatClientApprovalsTests.cs

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,217 @@ async IAsyncEnumerable<ChatResponseUpdate> YieldInnerClientUpdates(
11161116
}
11171117
}
11181118

1119+
[Theory]
1120+
[InlineData(false)]
1121+
[InlineData(true)]
1122+
public async Task FunctionCallReplacedWithApproval_MixedWithMcpApprovalAsync(bool useAdditionalTools)
1123+
{
1124+
AITool[] tools =
1125+
[
1126+
new ApprovalRequiredAIFunction(AIFunctionFactory.Create(() => "Result 1", "Func")),
1127+
new HostedMcpServerTool("myServer", "https://localhost/mcp")
1128+
];
1129+
1130+
var options = new ChatOptions
1131+
{
1132+
Tools = useAdditionalTools ? null : tools
1133+
};
1134+
1135+
List<ChatMessage> input =
1136+
[
1137+
new ChatMessage(ChatRole.User, "hello"),
1138+
];
1139+
1140+
List<ChatMessage> downstreamClientOutput =
1141+
[
1142+
new ChatMessage(ChatRole.Assistant,
1143+
[
1144+
new FunctionCallContent("callId1", "Func"),
1145+
new FunctionApprovalRequestContent("callId2", new McpServerToolCallContent("callId2", "McpCall", "myServer"))
1146+
])
1147+
];
1148+
1149+
List<ChatMessage> expectedOutput =
1150+
[
1151+
new ChatMessage(ChatRole.Assistant,
1152+
[
1153+
new FunctionApprovalRequestContent("callId1", new FunctionCallContent("callId1", "Func")),
1154+
new FunctionApprovalRequestContent("callId2", new McpServerToolCallContent("callId2", "McpCall", "myServer"))
1155+
])
1156+
];
1157+
1158+
await InvokeAndAssertAsync(options, input, downstreamClientOutput, expectedOutput, additionalTools: useAdditionalTools ? tools : null);
1159+
await InvokeAndAssertStreamingAsync(options, input, downstreamClientOutput, expectedOutput, additionalTools: useAdditionalTools ? tools : null);
1160+
}
1161+
1162+
[Theory]
1163+
[InlineData(false)]
1164+
[InlineData(true)]
1165+
public async Task ApprovedApprovalResponseIsExecuted_MixedWithMcpApprovalAsync(bool useAdditionalTools)
1166+
{
1167+
AITool[] tools =
1168+
[
1169+
new ApprovalRequiredAIFunction(AIFunctionFactory.Create(() => "Result 1", "Func")),
1170+
new HostedMcpServerTool("myServer", "https://localhost/mcp")
1171+
];
1172+
1173+
var options = new ChatOptions
1174+
{
1175+
Tools = useAdditionalTools ? null : tools
1176+
};
1177+
1178+
List<ChatMessage> input =
1179+
[
1180+
new ChatMessage(ChatRole.User, "hello"),
1181+
new ChatMessage(ChatRole.Assistant,
1182+
[
1183+
new FunctionApprovalRequestContent("callId1", new FunctionCallContent("callId1", "Func")),
1184+
new FunctionApprovalRequestContent("callId2", new McpServerToolCallContent("callId2", "McpCall", "myServer"))
1185+
]) { MessageId = "resp1" },
1186+
new ChatMessage(ChatRole.User,
1187+
[
1188+
new FunctionApprovalResponseContent("callId1", true, new FunctionCallContent("callId1", "Func")),
1189+
new FunctionApprovalResponseContent("callId2", true, new McpServerToolCallContent("callId2", "McpCall", "myServer"))
1190+
]),
1191+
];
1192+
1193+
List<ChatMessage> expectedDownstreamClientInput =
1194+
[
1195+
new ChatMessage(ChatRole.User, "hello"),
1196+
new ChatMessage(ChatRole.Assistant,
1197+
[
1198+
new FunctionApprovalRequestContent("callId2", new McpServerToolCallContent("callId2", "McpCall", "myServer"))
1199+
]),
1200+
new ChatMessage(ChatRole.User,
1201+
[
1202+
new FunctionApprovalResponseContent("callId2", true, new McpServerToolCallContent("callId2", "McpCall", "myServer"))
1203+
]),
1204+
new ChatMessage(ChatRole.Assistant,
1205+
[
1206+
new FunctionCallContent("callId1", "Func")
1207+
]),
1208+
new ChatMessage(ChatRole.Tool,
1209+
[
1210+
new FunctionResultContent("callId1", result: "Result 1")
1211+
]),
1212+
];
1213+
1214+
List<ChatMessage> downstreamClientOutput =
1215+
[
1216+
new ChatMessage(ChatRole.Assistant, [
1217+
new McpServerToolResultContent("callId2") { Result = new List<AIContent> { new TextContent("Result 2") } },
1218+
new TextContent("world")
1219+
])
1220+
];
1221+
1222+
List<ChatMessage> output =
1223+
[
1224+
new ChatMessage(ChatRole.Assistant,
1225+
[
1226+
new FunctionCallContent("callId1", "Func")
1227+
]),
1228+
new ChatMessage(ChatRole.Tool,
1229+
[
1230+
new FunctionResultContent("callId1", result: "Result 1")
1231+
]),
1232+
new ChatMessage(ChatRole.Assistant, [
1233+
new McpServerToolResultContent("callId2") { Result = new List<AIContent> { new TextContent("Result 2") } },
1234+
new TextContent("world")
1235+
])
1236+
];
1237+
1238+
await InvokeAndAssertAsync(options, input, downstreamClientOutput, output, expectedDownstreamClientInput, additionalTools: useAdditionalTools ? tools : null);
1239+
await InvokeAndAssertStreamingAsync(options, input, downstreamClientOutput, output, expectedDownstreamClientInput, additionalTools: useAdditionalTools ? tools : null);
1240+
}
1241+
1242+
[Theory]
1243+
[InlineData(false, false)]
1244+
[InlineData(false, true)]
1245+
[InlineData(true, false)]
1246+
[InlineData(true, true)]
1247+
public async Task RejectedApprovalResponses_MixedWithMcpApprovalAsync(bool useAdditionalTools, bool approveMcp)
1248+
{
1249+
AITool[] tools =
1250+
[
1251+
new ApprovalRequiredAIFunction(AIFunctionFactory.Create(() => "Result 1", "Func")),
1252+
new HostedMcpServerTool("myServer", "https://localhost/mcp")
1253+
];
1254+
1255+
var options = new ChatOptions
1256+
{
1257+
Tools = useAdditionalTools ? null : tools
1258+
};
1259+
1260+
List<ChatMessage> input =
1261+
[
1262+
new ChatMessage(ChatRole.User, "hello"),
1263+
new ChatMessage(ChatRole.Assistant,
1264+
[
1265+
new FunctionApprovalRequestContent("callId1", new FunctionCallContent("callId1", "Func")),
1266+
new FunctionApprovalRequestContent("callId2", new McpServerToolCallContent("callId2", "McpCall", "myServer"))
1267+
]) { MessageId = "resp1" },
1268+
new ChatMessage(ChatRole.User,
1269+
[
1270+
new FunctionApprovalResponseContent("callId1", !approveMcp, new FunctionCallContent("callId1", "Func")),
1271+
new FunctionApprovalResponseContent("callId2", approveMcp, new McpServerToolCallContent("callId2", "McpCall", "myServer"))
1272+
]),
1273+
];
1274+
1275+
List<ChatMessage> expectedDownstreamClientInput = [
1276+
new ChatMessage(ChatRole.User, "hello"),
1277+
new ChatMessage(ChatRole.Assistant,
1278+
[
1279+
new FunctionApprovalRequestContent("callId2", new McpServerToolCallContent("callId2", "McpCall", "myServer"))
1280+
]),
1281+
new ChatMessage(ChatRole.User,
1282+
[
1283+
new FunctionApprovalResponseContent("callId2", approveMcp, new McpServerToolCallContent("callId2", "McpCall", "myServer"))
1284+
]),
1285+
new ChatMessage(ChatRole.Assistant,
1286+
[
1287+
new FunctionCallContent("callId1", "Func")
1288+
]),
1289+
new ChatMessage(ChatRole.Tool,
1290+
[
1291+
approveMcp ?
1292+
new FunctionResultContent("callId1", result: "Tool call invocation rejected.") :
1293+
new FunctionResultContent("callId1", result: "Result 1")
1294+
]),
1295+
];
1296+
1297+
List<ChatMessage> downstreamClientOutput =
1298+
[
1299+
new ChatMessage(ChatRole.Assistant, [
1300+
new TextContent("world"),
1301+
.. approveMcp ?
1302+
[new McpServerToolResultContent("callId2") { Result = new List<AIContent> { new TextContent("Result 2") } }] :
1303+
Array.Empty<AIContent>()
1304+
])
1305+
];
1306+
1307+
List<ChatMessage> output = [
1308+
new ChatMessage(ChatRole.Assistant,
1309+
[
1310+
new FunctionCallContent("callId1", "Func"),
1311+
]),
1312+
new ChatMessage(ChatRole.Tool,
1313+
[
1314+
approveMcp ?
1315+
new FunctionResultContent("callId1", result: "Tool call invocation rejected.") :
1316+
new FunctionResultContent("callId1", result: "Result 1")
1317+
]),
1318+
new ChatMessage(ChatRole.Assistant, [
1319+
new TextContent("world"),
1320+
.. approveMcp ?
1321+
[new McpServerToolResultContent("callId2") { Result = new List<AIContent> { new TextContent("Result 2") } }] :
1322+
Array.Empty<AIContent>()
1323+
])
1324+
];
1325+
1326+
await InvokeAndAssertAsync(options, input, downstreamClientOutput, output, expectedDownstreamClientInput, additionalTools: useAdditionalTools ? tools : null);
1327+
await InvokeAndAssertStreamingAsync(options, input, downstreamClientOutput, output, expectedDownstreamClientInput, additionalTools: useAdditionalTools ? tools : null);
1328+
}
1329+
11191330
private static Task<List<ChatMessage>> InvokeAndAssertAsync(
11201331
ChatOptions? options,
11211332
List<ChatMessage> input,

0 commit comments

Comments
 (0)