Skip to content

Commit 98a0261

Browse files
authored
Tweak how McpClientTool.InvokeAsync exposes some content (#941)
Rather than always serializing to a JsonElement, which IChatClients that consume the tool won't be able to reason about, convert the content into AIContents that they can reason about.
1 parent b90f17b commit 98a0261

File tree

3 files changed

+404
-201
lines changed

3 files changed

+404
-201
lines changed

Directory.Packages.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
44
<System9Version>9.0.10</System9Version>
55
<System10Version>10.0.0-rc.2.25502.107</System10Version>
6-
<MicrosoftExtensionsAIVersion>9.10.1</MicrosoftExtensionsAIVersion>
6+
<MicrosoftExtensionsAIVersion>9.10.2</MicrosoftExtensionsAIVersion>
77
</PropertyGroup>
88

99
<!-- Product dependencies netstandard -->
@@ -60,7 +60,7 @@
6060
<PrivateAssets>all</PrivateAssets>
6161
</PackageVersion>
6262
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
63-
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="9.10.1-preview.1.25521.4" />
63+
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="9.10.2-preview.1.25552.1" />
6464
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="$(System9Version)" />
6565
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="$(System9Version)" />
6666
<PackageVersion Include="Microsoft.Extensions.Logging" Version="$(System9Version)" />

src/ModelContextProtocol.Core/Client/McpClientTool.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,26 @@ internal McpClientTool(
130130
AIFunctionArguments arguments, CancellationToken cancellationToken)
131131
{
132132
CallToolResult result = await CallAsync(arguments, _progress, JsonSerializerOptions, cancellationToken).ConfigureAwait(false);
133+
134+
// We want to translate the result content into AIContent, using AIContent as the exchange types, so
135+
// that downstream IChatClients can specialize handling based on the content (e.g. sending image content
136+
// back to the AI service as a multi-modal tool response). However, when there is additional information
137+
// carried by the CallToolResult outside of its ContentBlocks, just returning AIContent from those ContentBlocks
138+
// would lose that information. So, we only do the translation if there is no additional information to preserve.
139+
if (result.IsError is not true &&
140+
result.StructuredContent is null &&
141+
result.Meta is not { Count: > 0 })
142+
{
143+
switch (result.Content.Count)
144+
{
145+
case 1 when result.Content[0].ToAIContent() is { } aiContent:
146+
return aiContent;
147+
148+
case > 1 when result.Content.Select(c => c.ToAIContent()).ToArray() is { } aiContents && aiContents.All(static c => c is not null):
149+
return aiContents;
150+
}
151+
}
152+
133153
return JsonSerializer.SerializeToElement(result, McpJsonUtilities.JsonContext.Default.CallToolResult);
134154
}
135155

0 commit comments

Comments
 (0)