Skip to content

[MCP SDK] ToolCallHandler now returns structuredContent if applicable #225

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

xavierleune
Copy link
Contributor

Q A
Bug fix? no
New feature? yes
Docs? no
Issues Fix #...
License MIT

As per documentation we should include any structured content in a dedicated field

Structured content is returned as a JSON object in the structuredContent field of a result.
For backwards compatibility, a tool that returns structured content SHOULD also return the serialized JSON in a TextContent block.

Copy link
Contributor

@JoshuaBehrens JoshuaBehrens left a comment

Choose a reason for hiding this comment

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

I have a similar patch in local testing :)

@chr-hertel chr-hertel added the MCP SDK Issues & PRs about the MCP SDK label Jul 29, 2025
@OskarStark OskarStark changed the title [MCP SDK] ToolCallHandler now returns structuredContent if applicable [MCP SDK] ToolCallHandler now returns structuredContent if applicable Jul 30, 2025
@OskarStark OskarStark changed the title [MCP SDK] ToolCallHandler now returns structuredContent if applicable [MCP SDK] ToolCallHandler now returns structuredContent if applicable Jul 30, 2025
@OskarStark
Copy link
Contributor

Please rebase, thanks

@xavierleune xavierleune force-pushed the feature/structured-content branch from ad7601d to f81c226 Compare July 30, 2025 14:21
@xavierleune
Copy link
Contributor Author

@OskarStark done 👍

Copy link
Member

@chr-hertel chr-hertel left a comment

Choose a reason for hiding this comment

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

Two things, I think this is good timing to add a test for checking the two options for type text.

Isn't it that with the current approach we end up with something like "text": "\"foobar\"" for simple, unstructured text values?

@OskarStark
Copy link
Contributor

Open to finish this PR @xavierleune ?

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements structured content support in the MCP SDK's ToolCallHandler to comply with the MCP specification. The change allows tools to return structured data (arrays/objects) which will be included in both the structuredContent field and serialized as JSON in the text content for backwards compatibility.

  • Modified ToolCallResult to accept mixed data types instead of strings only
  • Updated ToolCallHandler to detect structured content and include it in the structuredContent field
  • Fixed a typo in the default MIME type from "text/plan" to "text/plain"

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/mcp-sdk/src/Capability/Tool/ToolCallResult.php Changed result property from string to mixed type and fixed MIME type typo
src/mcp-sdk/src/Server/RequestHandler/ToolCallHandler.php Added structured content detection and JSON encoding with proper error handling

]);
];

if ('text' === $result->type && \is_array($result->result) || \is_object($result->result)) {
Copy link
Preview

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

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

The operator precedence is incorrect. The condition should be grouped as ('text' === $result->type) && (\is_array($result->result) || \is_object($result->result)) to ensure structured content is only added for text type results.

Suggested change
if ('text' === $result->type && \is_array($result->result) || \is_object($result->result)) {
if ('text' === $result->type && (\is_array($result->result) || \is_object($result->result))) {

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
MCP SDK Issues & PRs about the MCP SDK Status: Needs Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants