Skip to content

feat(mcp): retain structured content in the AgentTool response #528

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

dbschmigelski
Copy link
Member

@dbschmigelski dbschmigelski commented Jul 24, 2025

Description

This PR implements the retention of structured content in the AgentTool response when using the MCP client. When structured content is available from MCP tools, it will now be included as the last item in the content array of the returned ToolResult.

The changes include updating the MCP dependency to version 1.11.0, modifying the MCPClient class to handle structured content in both synchronous and asynchronous tool calls. The echo server in integration tests has been enhanced to include a new tool that returns structured content for testing purposes.

The implementation ensures backward compatibility while adding the ability to access structured data returned by MCP tools. This enhancement improves the flexibility of the SDK by allowing tools to return both unstructured and structured responses in a consistent format.

The changes have been tested with both unit tests and integration tests to verify proper handling of structured content in various scenarios.

Related to: https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content

Design Decision Discussion:

We faced two potential approaches for handling structured content:

Option A:
We could have mirrored the MCP Tool Response structure by having separate 'content' and 'structuredContent' fields in our AgentTool response. This would have introduced structured content support uniformly across all tools, not just MCP tools. However, this would require a more significant change to our existing tool response interface.

Option B (Chosen Approach):
We decided to leverage our existing 'json' content type capability, which already provides a mechanism for handling structured data. This approach maintains consistency with our current content type system while still allowing us to represent structured data.

A key design decision was whether to append the structured content to existing content items or replace them entirely. We chose to append the structured content as the last item in the content array for several reasons:

  1. It preserves all information returned by the tool
  2. It maintains backward compatibility
  3. It allows consumers to access both human-readable and structured representations of the data

While appending was chosen, it's worth noting this wasn't a straightforward decision. Replacing existing content with structured content could have provided a cleaner, more direct approach to structured data handling, may result in existing applications breaking because an expected text block is no longer present.

Type of Change

New feature

Testing

How have you tested the change? Verify that the changes do not break functionality or introduce warnings in consuming repositories: agents-docs, agents-tools, agents-cli

  • I ran hatch run prepare

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • [no, open to adding if desired] I have updated the documentation accordingly
  • [n/a] I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

poshinchen
poshinchen previously approved these changes Jul 25, 2025
@dbschmigelski
Copy link
Member Author

As discussed above, the strategy implemented here was to introduce a MCPToolResult. This reduces duplication and allows users to effectively persist the structuredContent to be used not by the agent/llm, but instead by the user via a mechanic like Hooks.

Unlike other providers, Bedrock throws ValidationExceptions when additional fields are provided in the ToolResultBlock. So, some filtering was needed in the BedrockModel when presented with a toolResult.

One interesting side effect, is that now overloaded ToolResults are allowable not just by MCP but by all tool implementations. This presents a new mechanism to persist state.

In effect, we now have

Copy link
Member

@Unshure Unshure left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add an integ test for using the structuredContent toolResult in a hook?

@dbschmigelski dbschmigelski force-pushed the feat/mcp/retain_structured_content branch from b7fdec7 to 543bf8e Compare July 29, 2025 01:40
@dbschmigelski dbschmigelski merged commit 4e0e0a6 into strands-agents:main Jul 29, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants