.NET: Delegate MCP ContentBlock to AIContent conversion to the MCP SDK#5903
.NET: Delegate MCP ContentBlock to AIContent conversion to the MCP SDK#5903peibekwe wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Updates the .NET declarative MCP workflow integration to rely on the MCP SDK’s canonical ContentBlock.ToAIContent() conversion instead of a local hand-rolled mapping, improving compatibility with newer/previously-unhandled MCP content block subtypes (e.g., tool use/results). Includes a targeted local fallback for ResourceLinkBlock.
Changes:
- Replaced
DefaultMcpToolHandler.ConvertContentBlock’s customswitchconversion withContentBlock.ToAIContent()and aResourceLinkBlockfallback mapping toUriContent. - Expanded/adjusted unit tests to validate new conversions (ToolUse/ToolResult),
RawRepresentationpropagation, decodedDataContent.Data, andMeta→AdditionalProperties.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.Mcp/DefaultMcpToolHandler.cs | Delegates content-block conversion to MCP SDK with a local ResourceLinkBlock fallback. |
| dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.Mcp.UnitTests/DefaultMcpToolHandlerTests.cs | Updates tests to reflect SDK-driven conversions and adds coverage for additional MCP block subtypes and metadata propagation. |
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 85%
✓ Correctness
Clean delegation of ContentBlock-to-AIContent conversion to the MCP SDK v1.1.0. The SDK's ToAIContent handles all 6 known subtypes (Text, Image, Audio, EmbeddedResource, ToolUse, ToolResult), returns null for ResourceLinkBlock, and the PR adds a local fallback mapping ResourceLinkBlock to UriContent. The null-coalescing pattern
block.ToAIContent() ?? block switch { ... }is correct. RawRepresentation is set by the SDK for recognized types and by the fallback for unrecognized ones. Tests are comprehensive and match SDK behavior (e.g., DataContent.Data contains decoded bytes, not raw base64 UTF-8). No correctness issues found.
✓ Security Reliability
Clean refactor that delegates ContentBlock-to-AIContent conversion to the MCP SDK's canonical converter, adding local fallbacks for ResourceLinkBlock and unknown types. No security or reliability issues found. The change reduces attack surface by removing hand-rolled parsing (base64/data-URI handling) and relying on the SDK instead. The null-coalescing fallback chain (
block.ToAIContent() ?? switch) correctly handles all content block subtypes including future unknown ones. URI and MIME type handling in the ResourceLinkBlock fallback follows the same patterns used elsewhere in the codebase.
✓ Test Coverage
The test changes are thorough for the core delegation to the MCP SDK. Tests were added for all three previously-unsupported content block subtypes (ResourceLinkBlock, ToolUseContentBlock, ToolResultContentBlock), existing tests were strengthened with RawRepresentation and Data assertions, and Meta propagation is tested. One notable gap: the ResourceLinkBlock fallback code (lines 283 in the production file) does not propagate block.Meta to AdditionalProperties, yet no test verifies this. The comment on line 278 explicitly notes the SDK 'sets RawRepresentation + AdditionalProperties from block.Meta', but the hand-written ResourceLinkBlock path only sets RawRepresentation. A test for ResourceLinkBlock with Meta would catch this inconsistency.
✗ Design Approach
The new
ResourceLinkBlockfallback bypasses the metadata-preservation pattern that motivated the switch to the MCP SDK converter. Specifically, it setsRawRepresentationbut notAdditionalProperties, soResourceLinkBlock.Metawould be lost even though comparable conversion code in this repo consistently carries both through.
Flagged Issues
-
dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.Mcp/DefaultMcpToolHandler.cs:282dropsResourceLinkBlock.Metabecause the manual fallback only setsRawRepresentation. In the same repo, protocol-bridge conversions preserve both raw payload and metadata together (dotnet/src/Microsoft.Agents.AI.A2A/Extensions/AgentTaskStatusExtensions.cs:27-29,dotnet/src/Microsoft.Agents.AI.Workflows/WorkflowSession.cs:663-670).
Automated review by peibekwe's agents
Motivation and Context
DefaultMcpToolHandler.ConvertContentBlockpreviously hand-rolled a switch that covered only 4 of the MCP SDK's 7ContentBlocksubtypes (Text, Image, Audio, EmbeddedResource). Calling an MCP tool that returnedResourceLinkBlock,ToolUseContentBlock, orToolResultContentBlockwould fail / lose information.This PR replaces the custom switch with a call to the MCP SDK's canonical converter (
ContentBlock.ToAIContent) and adds a single local fallback for the one subtype the SDK intentionally leaves unmapped (ResourceLinkBlock).Fixes #5827
Contribution Checklist