fix(mcp): fix ignored output format - #8542
Open
vincentchalamon wants to merge 4 commits into
Open
vincentchalamon wants to merge 4 commits into
vincentchalamon wants to merge 4 commits into
Conversation
vincentchalamon
commented
Sep 18, 2026
Contributor
| Q | A |
|---|---|
| Branch? | 4.4 |
| Tickets | N/A |
| License | MIT |
| Doc PR | N/A |
StructuredContentProcessor serializes a tool result with
$format = $request->getRequestFormat('') ?: 'jsonld';
and never reads $operation->getOutputFormats(), although $operation is in scope
and FormatsResourceMetadataCollectionFactory has populated it. The MCP route
carries no _format placeholder or default either, so getRequestFormat() is always
empty and the expression is a constant 'jsonld' on every call.
McpFormatTool declares outputFormats: ['json' => ['application/json']]. The first
test asserts the metadata honours it (passes); the two others assert the payload
and structuredContent honour it (both fail, showing the JSON-LD envelope).
Declaring the format on the operation exercises the same code path as
api_platform.mcp.format, which is implemented as withOutputFormats() on the
operation -- so this single reproducer covers both ways of configuring it.
…result Read $operation->getOutputFormats() before falling back to the request format and to jsonld. The change is strictly additive: when no format is declared the array is empty and the previous expression applies unchanged, which is why the 26 existing MCP functional tests are untouched. Covers api_platform.mcp.format as well, since FormatsResourceMetadataCollectionFactory implements that option by calling withOutputFormats() on the operation.
MCP operations that declare their own formats never went through normalizeFormats(), which every HTTP operation gets in normalize(). The list form -- ['json'], meaning "reuse the already configured json format" -- was therefore left as [0 => 'json'] instead of being resolved to ['json' => ['application/json']], and the call failed once the processor started reading it. The loop now mirrors normalize() exactly, with the MCP format standing in for the resource-level defaults. Behaviour is unchanged when no format is declared: the operation still receives api_platform.mcp.format, which is what the 26 existing MCP functional tests exercise. The map form ['json' => ['application/json']] keeps passing through untouched -- normalizeFormats() accepts it as an inline mime-type declaration, which is the documented way to use a format that is not registered globally. McpFormatListTool covers the list form so both shapes stay green.
Two CI failures, both mine. PHPStan: process() receives the base Operation type, which does not declare getOutputFormats() -- only HttpOperation does. The lookup now sits behind the same McpTool/McpResource check the structuredContent flag already used, hoisted into a local so both read it. PHPUnit: the MongoDB test app loads routing_mongodb.yml, the only environment that does not import routing_test.php and therefore has no /mcp route, so the tests answered 404 instead of skipping. McpTest guards on isMongoDB() for the same reason; McpFormatTest now does too, via RecreateSchemaTrait.
vincentchalamon
marked this pull request as ready for review
September 18, 2026 09:14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.