2222use ApiPlatform \JsonSchema \SchemaFactoryAwareInterface ;
2323use ApiPlatform \JsonSchema \SchemaFactoryInterface ;
2424use ApiPlatform \JsonSchema \SchemaUriPrefixTrait ;
25+ use ApiPlatform \Metadata \CollectionOperationInterface ;
26+ use ApiPlatform \Metadata \McpResource ;
27+ use ApiPlatform \Metadata \McpTool ;
2528use ApiPlatform \Metadata \Operation ;
2629use ApiPlatform \Metadata \Resource \Factory \ResourceMetadataCollectionFactoryInterface ;
2730
@@ -133,7 +136,7 @@ public function buildSchema(string $className, string $format = 'jsonld', string
133136
134137 if (!$ collectionKey ) {
135138 $ definitionName = $ schema ->getRootDefinitionKey () ?? $ this ->definitionNameFactory ->create ($ className , $ format , $ inputOrOutputClass , $ operation , $ serializerContext );
136- $ this ->decorateItemDefinition ($ definitionName , $ definitions , $ prefix , $ type , $ serializerContext );
139+ $ this ->decorateItemDefinition ($ definitionName , $ definitions , $ prefix , $ type , $ serializerContext, $ operation );
137140
138141 if (isset ($ definitions [$ definitionName ])) {
139142 $ currentDefinitions = $ schema ->getDefinitions ();
@@ -254,7 +257,7 @@ public function buildSchema(string $className, string $format = 'jsonld', string
254257 unset($ schema ['items ' ]);
255258
256259 if (isset ($ definitions [$ collectionKey ])) {
257- $ this ->decorateItemDefinition ($ collectionKey , $ definitions , $ prefix , $ type , $ serializerContext );
260+ $ this ->decorateItemDefinition ($ collectionKey , $ definitions , $ prefix , $ type , $ serializerContext, $ operation );
258261 }
259262
260263 return $ schema ;
@@ -267,13 +270,16 @@ public function setSchemaFactory(SchemaFactoryInterface $schemaFactory): void
267270 }
268271 }
269272
270- private function decorateItemDefinition (string $ definitionName , \ArrayObject $ definitions , string $ prefix , string $ type , ?array $ serializerContext ): void
273+ private function decorateItemDefinition (string $ definitionName , \ArrayObject $ definitions , string $ prefix , string $ type , ?array $ serializerContext, ? Operation $ operation = null ): void
271274 {
272275 if (!isset ($ definitions [$ definitionName ])) {
273276 return ;
274277 }
275278
276- $ hasNoId = Schema::TYPE_OUTPUT === $ type && false === ($ serializerContext ['gen_id ' ] ?? true );
279+ // A single-item MCP operation has no routed item URI: the serializer omits `@id`, so don't require it.
280+ $ isMcpItem = ($ operation instanceof McpTool || $ operation instanceof McpResource) && !$ operation instanceof CollectionOperationInterface;
281+
282+ $ hasNoId = Schema::TYPE_OUTPUT === $ type && (false === ($ serializerContext ['gen_id ' ] ?? true ) || $ isMcpItem );
277283 $ baseName = self ::ITEM_BASE_SCHEMA_NAME ;
278284 if ($ hasNoId ) {
279285 $ baseName = self ::ITEM_WITHOUT_ID_BASE_SCHEMA_NAME ;
0 commit comments