[Capability] Apply a parameter's complete schema definition (#435)

* [Capability] Apply a parameter's complete schema definition

Schema(definition:) is documented as taking precedence over the individual
keywords, and generate() unwraps it that way at method level. At parameter
level it was merged as an ordinary key instead, in both the plain and the
variadic path, so the property reached clients carrying a literal
"definition" member - not JSON Schema, read by nothing, and everything
inside it lost.

Both paths now replace the schema with the definition. The variadic one
still forces type: array afterwards, since a variadic arrives as an array
however the definition describes it, and the signature default survives a
definition that states none - it is what the handler receives when the
argument is omitted, and default is an annotation rather than a constraint.

* Fix docblock description overwriting definition on variadic params

* Apply suggestion from @chr-hertel
This commit is contained in:
Christopher Hertel 2026-08-18 15:09:58 +02:00 • committed by GitHub
commit cfe5e8f570
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -92,6 +92,58 @@ final class SchemaGeneratorTest extends TestCase
], $schema);
}
public function testUsesCompleteSchemaDefinitionFromParameterLevelSchemaAttribute(): void
{
$method = new \ReflectionMethod(SchemaGeneratorFixture::class, 'parameterLevelCompleteDefinition');
$schema = $this->schemaGenerator->generate($method);
$this->assertEquals([
'type' => 'string',
'description' => 'The region to query.',
'x-mcp-header' => 'Region',
'default' => 'eu',
], $schema['properties']['region']);
$this->assertEquals([
'type' => 'integer',
'minimum' => 1,
'maximum' => 10,
'default' => 3,
], $schema['properties']['limit']);
$this->assertArrayNotHasKey('required', $schema);
}
public function testUsesCompleteSchemaDefinitionFromVariadicParameter(): void
{
$method = new \ReflectionMethod(SchemaGeneratorFixture::class, 'variadicCompleteDefinition');
$schema = $this->schemaGenerator->generate($method);
// The array type is forced: a variadic always arrives as one.
$this->assertEquals([
'type' => 'array',
'description' => 'Tags to apply.',
'items' => ['type' => 'string'],
], $schema['properties']['tags']);
}
public function testDefinitionDescriptionWinsOverDocblockOnVariadicParameter(): void
{
$method = new \ReflectionMethod(SchemaGeneratorFixture::class, 'variadicCompleteDefinitionWithDocblockDescription');
$schema = $this->schemaGenerator->generate($method);
$this->assertSame('Tags to apply.', $schema['properties']['tags']['description']);
}
public function testKeepsTheSignatureDefaultWhenADefinitionReshapesTheParameter(): void
{
$method = new \ReflectionMethod(SchemaGeneratorFixture::class, 'definitionReshapingTheParameter');
$schema = $this->schemaGenerator->generate($method);
$this->assertSame('{}', $schema['properties']['payload']['default']);
$this->assertSame('object', $schema['properties']['payload']['type']);
}
public function testGeneratesSchemaFromMethodLevelSchemaAttributeWithProperties(): void
{
$method = new \ReflectionMethod(SchemaGeneratorFixture::class, 'methodLevelWithProperties');