Skip to content

[Server] Extend elicitation enum schema compliance#261

Draft
chr-hertel wants to merge 1 commit intomainfrom
elicit-schema
Draft

[Server] Extend elicitation enum schema compliance#261
chr-hertel wants to merge 1 commit intomainfrom
elicit-schema

Conversation

@chr-hertel
Copy link
Member

@chr-hertel chr-hertel commented Mar 10, 2026

Tackling extended elicitations schema of modelcontextprotocol/modelcontextprotocol#1330 and conformance tests.
Also fixes #178

  • needs review by me first

@chr-hertel chr-hertel self-assigned this Mar 10, 2026
@chr-hertel chr-hertel changed the title Extend elicitation enum schema compliance [Server] Extend elicitation enum schema compliance Mar 10, 2026
@chr-hertel chr-hertel added the Server Issues & PRs related to the Server component label Mar 10, 2026
@chr-hertel chr-hertel requested a review from Copilot March 10, 2026 23:50
Copy link
Contributor

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 updates the PHP MCP conformance server and schema layer to support extended elicitation enum schemas (SEP-1330) and defaults (SEP-1034), aligning with upstream conformance expectations.

Changes:

  • Add new conformance tools to exercise server-initiated elicitation, defaults, and enum-schema variants.
  • Introduce new elicitation schema definition classes for SEP-1330 titled enums and multi-select enums.
  • Remove previously-listed elicitation checks from the conformance expected-failures baseline.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/Conformance/server.php Registers new conformance tools for elicitation scenarios.
tests/Conformance/Elements.php Implements tool handlers that send elicitation requests with defaults and enum schemas.
tests/Conformance/conformance-baseline.yml Drops elicitation checks from expected failures (implying they now pass).
src/Schema/Elicitation/ElicitationSchema.php Broadens properties PHPDoc type to AbstractSchemaDefinition.
src/Schema/Elicitation/TitledEnumSchemaDefinition.php Adds SEP-1330 single-select titled enum schema serialization.
src/Schema/Elicitation/MultiSelectEnumSchemaDefinition.php Adds multi-select enum schema serialization.
src/Schema/Elicitation/TitledMultiSelectEnumSchemaDefinition.php Adds SEP-1330 multi-select titled enum schema serialization.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +28 to 30
* @param array<string, AbstractSchemaDefinition> $properties Property definitions keyed by name
* @param string[] $required Array of required property names
*/
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The constructor PHPDoc now allows any AbstractSchemaDefinition, but ElicitationSchema::fromArray still delegates to PrimitiveSchemaDefinition::fromArray which currently rejects type: array and cannot recognize oneOf/anyOf enum shapes. This means a client deserializing an elicitation/create request containing SEP-1330 enums (or multi-select arrays) will either throw (array type) or silently downgrade titled enums to a plain StringSchemaDefinition. Consider extending the parsing path (PrimitiveSchemaDefinition + related fromArray implementations) to support these new schema shapes and updating the schema-level tests accordingly.

Copilot uses AI. Check for mistakes.
Comment on lines +28 to +40
/**
* @param string $title Human-readable title for the field
* @param list<array{const: string, title: string}> $oneOf Array of const/title pairs
* @param string|null $description Optional description/help text
* @param string|null $default Optional default value (must match a const)
*/
public function __construct(
string $title,
public readonly array $oneOf,
?string $description = null,
public readonly ?string $default = null,
) {
parent::__construct($title, $description);
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

This schema definition doesn’t provide a fromArray() constructor, and the current PrimitiveSchemaDefinition::fromArray logic will parse a {type: "string", oneOf: [...]} schema as a StringSchemaDefinition (losing the enum options). To keep request deserialization symmetric with serialization, add a fromArray() here and update the primitive schema factory to detect the SEP-1330 titled enum shape (e.g., presence of oneOf with const/title) and return this type.

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +38
final class MultiSelectEnumSchemaDefinition extends AbstractSchemaDefinition
{
/**
* @param string $title Human-readable title for the field
* @param string[] $enum Array of allowed string values
* @param string|null $description Optional description/help text
*/
public function __construct(
string $title,
public readonly array $enum,
?string $description = null,
) {
parent::__construct($title, $description);

Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

This schema definition doesn’t provide a fromArray() constructor, and the current PrimitiveSchemaDefinition::fromArray rejects type: array, so a client deserializing a multi-select enum schema will throw. Consider adding fromArray() here and extending the primitive schema factory to recognize {type: "array", items: {type: "string", enum: [...]}} as a MultiSelectEnumSchemaDefinition.

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +41
final class TitledMultiSelectEnumSchemaDefinition extends AbstractSchemaDefinition
{
/**
* @param string $title Human-readable title for the field
* @param list<array{const: string, title: string}> $anyOf Array of const/title pairs
* @param string|null $description Optional description/help text
*/
public function __construct(
string $title,
public readonly array $anyOf,
?string $description = null,
) {
parent::__construct($title, $description);

if ([] === $anyOf) {
throw new InvalidArgumentException('anyOf array must not be empty.');
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

This schema definition doesn’t provide a fromArray() constructor, and the current PrimitiveSchemaDefinition::fromArray rejects type: array, so a client deserializing {type:"array", items:{anyOf:[...]}} will throw. Consider adding fromArray() here and extending the primitive schema factory to detect the SEP-1330 titled multi-select shape (array + items.anyOf with const/title pairs) and return this type.

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +27
* @see https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1330
*/
final class TitledMultiSelectEnumSchemaDefinition extends AbstractSchemaDefinition
{
/**
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

There is an established unit test suite for elicitation schema (tests/Unit/Schema/Elicitation/*), but the new SEP-1330 schema definitions introduced here aren’t covered. Adding tests for jsonSerialize() output and for round-tripping via ElicitationSchema::fromArray / PrimitiveSchemaDefinition::fromArray would help prevent regressions and ensure both client and server can handle the new schema shapes consistently.

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

Server Issues & PRs related to the Server component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Server] Elicitation Support for PHP MCP SDK

2 participants