Skip to content

Commit 048ebeb

Browse files
Add test for mixed content with ToolResultContentBlock
Adds test case to verify that when a message Content includes both a ToolResultContentBlock and another type of content block, the message uses ChatRole.User instead of ChatRole.Tool. Co-authored-by: MackinnonBuck <10456961+MackinnonBuck@users.noreply.github.com>
1 parent 893c1cb commit 048ebeb

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

tests/ModelContextProtocol.Tests/Client/McpClientTests.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,67 @@ public async Task CreateSamplingHandler_ShouldUseToolRoleForToolResultMessages()
338338
Assert.IsType<FunctionResultContent>(messagesList[2].Contents.Single());
339339
}
340340

341+
[Fact]
342+
public async Task CreateSamplingHandler_MixedContentWithToolResult_ShouldUseUserRole()
343+
{
344+
// Arrange - Tests that when Content contains both ToolResultContentBlock and other content,
345+
// the message should use ChatRole.User (not ChatRole.Tool)
346+
var mockChatClient = new Mock<IChatClient>();
347+
var requestParams = new CreateMessageRequestParams
348+
{
349+
Messages =
350+
[
351+
new SamplingMessage
352+
{
353+
Role = Role.User,
354+
Content =
355+
[
356+
new ToolResultContentBlock
357+
{
358+
ToolUseId = "call_123",
359+
Content = [new TextContentBlock { Text = "Tool result" }]
360+
},
361+
new TextContentBlock { Text = "Additional text content" }
362+
]
363+
}
364+
],
365+
MaxTokens = 100
366+
};
367+
368+
IEnumerable<ChatMessage>? capturedMessages = null;
369+
var cancellationToken = CancellationToken.None;
370+
var expectedResponse = new[] {
371+
new ChatResponseUpdate
372+
{
373+
ModelId = "test-model",
374+
FinishReason = ChatFinishReason.Stop,
375+
Role = ChatRole.Assistant,
376+
Contents = [new TextContent("Response")]
377+
}
378+
}.ToAsyncEnumerable();
379+
380+
mockChatClient
381+
.Setup(client => client.GetStreamingResponseAsync(It.IsAny<IEnumerable<ChatMessage>>(), It.IsAny<ChatOptions>(), cancellationToken))
382+
.Callback<IEnumerable<ChatMessage>, ChatOptions?, CancellationToken>((messages, _, _) => capturedMessages = messages.ToList())
383+
.Returns(expectedResponse);
384+
385+
var handler = mockChatClient.Object.CreateSamplingHandler();
386+
387+
// Act
388+
var result = await handler(requestParams, Mock.Of<IProgress<ProgressNotificationValue>>(), cancellationToken);
389+
390+
// Assert
391+
Assert.NotNull(capturedMessages);
392+
var messagesList = capturedMessages.ToList();
393+
Assert.Single(messagesList);
394+
395+
// Mixed content (ToolResultContentBlock + TextContentBlock) should use User role, not Tool role
396+
Assert.Equal(ChatRole.User, messagesList[0].Role);
397+
Assert.Equal(2, messagesList[0].Contents.Count);
398+
Assert.Contains(messagesList[0].Contents, c => c is FunctionResultContent);
399+
Assert.Contains(messagesList[0].Contents, c => c is TextContent);
400+
}
401+
341402
[Fact]
342403
public async Task ListToolsAsync_AllToolsReturned()
343404
{

0 commit comments

Comments
 (0)