Skip to content

Conversation

@chughtapan
Copy link
Contributor

@chughtapan chughtapan commented Jul 30, 2025

Motivation and Context

The use of enumNames property is not a valid JSON Schema keyword in elicitation schema.

This PR implements the changes in #1330

  • Make the existing EnumSchema "Legacy"
    • It uses a non-standard approach for adding titles to enumerated values
    • Mark it as legacy but still support it for now
  • Introduce the distinction between Untitled and Titled enums.
    • If the enumerated values are sufficient, no separate title need be specified for each value.
    • If the enumerated values are not optimal for display, a title may be specified for each value.
  • Introduce the distinction between Single and Multi-select enums.
    • If only one value can be selected, a Single select schema can be used
    • If more than one value can be selected, a Multi-select schema can be used
  • In ElicitResponse, add array as an additionalProperty type
    • Allows multiple selection of enumerated values to be returned to the server for multi select enums

How Has This Been Tested?

npm run check

Breaking Changes

No, the existing schemas remain and can be deprecated/removed in a future version

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

This came up as a request in #1035

The enumNames property is not a valid JSON Schema keyword. Updated
EnumSchema to use the standard-compliant oneOf pattern with const
and title keywords for each option, as recommended by JSON Schema
specification.
@chughtapan chughtapan requested a review from a team July 30, 2025 18:22
@chughtapan chughtapan changed the title Replace enumNames with standard-compliant oneOf pattern fix: Replace enumNames with standard-compliant oneOf pattern Jul 30, 2025
@chughtapan chughtapan changed the title fix: Replace enumNames with standard-compliant oneOf pattern fix: Replace enumNames with standard-compliant oneOf pattern in Elicitation Schema Jul 30, 2025
@cliffhall
Copy link
Member

cliffhall commented Jul 30, 2025

@chughtapan thanks for this! he current schema.json actually comes close, using const + title, but with only a oneOf proposition. But a wrinkle is that schema needs to support use of oneOf or anyOf.

For instance, when eliciting user input, with an enum of colors, you might say "Choose your favorite color" OR "Choose your favorite colors".

The actual JSON schema for an enum with title and optional description of its purpose would look something like this:

"EnumSchema": {
  "oneOf": [
    {
      "type": "object",
      "required": ["type", "oneOf"],
      "properties": {
        "type": { "const": "string" },
        "title": { "type": "string" },
        "description": { "type": "string" },
        "oneOf": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["const", "title"],
            "properties": {
              "const": { "type": "string" },
              "title": { "type": "string" }
            },
            "additionalProperties": false
          }
        }
      },
      "additionalProperties": false
    },
    {
      "type": "object",
      "required": ["type", "anyOf"],
      "properties": {
        "type": { "const": "array" },
        "title": { "type": "string" },
        "description": { "type": "string" },
        "anyOf": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["const", "title"],
            "properties": {
              "const": { "type": "string" },
              "title": { "type": "string" }
            },
            "additionalProperties": false
          }
        }
      },
      "additionalProperties": false
    }
  ]
}

Which would allow single selection...

{
 "type": "string",
 "title": "Color Selection",
 "description": "Choose your favorite color",
 "oneOf": [
   { "const": "#FF0000", "title": "Red" },
   { "const": "#00FF00", "title": "Green" },
   { "const": "#0000FF", "title": "Blue" }
 ]
}

or multi-selection...

{
  "type": "array",
  "title": "Color Selection",
  "description": "Choose your favorite colors",
  "items": {
    "oneOf": [
      { "const": "#FF0000", "title": "Red" },
      { "const": "#00FF00", "title": "Green" },
      { "const": "#0000FF", "title": "Blue" }
    ]
  }
}

as valid enums sent to the client for elicitation (or whatever purpose).

@chughtapan
Copy link
Contributor Author

@cliffhall I like your proposal, but I guess that means it's a broader change around the semantics of enums in MCP. IIUC the current expectation matches the proposed oneOf semantics. I think the current docs state that

Note that complex nested structures, arrays of objects, and other advanced JSON Schema features are intentionally not supported to simplify client implementation.

But maybe it is a valid proposal to change that only for enums and support anyOf semantics as well. Thoughts?

@cliffhall
Copy link
Member

cliffhall commented Aug 1, 2025

Note that complex nested structures, arrays of objects, and other advanced JSON Schema features are intentionally not supported to simplify client implementation.

@chughtapan For context, where in the spec did you find this particular note?

But maybe it is a valid proposal to change that only for enums and support anyOf semantics as well. Thoughts?

I think it is worthwhile running this up the flagpole. Enums are equally useful for multi-select as they are for single selection. Certainly in elicitation, it would be nice to have.

For rigor, I decided to test the EnumSchema meta-schema I defined above, against single and multiple color selection instance schemas, and use those instance schemas to validate expected inputs.

Screenshot 2025-07-31 at 11 50 23 PM Screenshot 2025-07-31 at 11 55 57 PM Screenshot 2025-08-01 at 12 02 08 AM Screenshot 2025-07-31 at 11 54 26 PM Screenshot 2025-07-31 at 11 57 49 PM Screenshot 2025-08-01 at 12 04 29 AM

@chughtapan
Copy link
Contributor Author

@cliffhall Thanks!

@chughtapan For context, where in the spec did you find this particular note?

Here: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/draft/client/elicitation.mdx?plain=1#L282

But maybe it is a valid proposal to change that only for enums and support anyOf semantics as well. Thoughts?

I think it is worthwhile running this up the flagpole. Enums are equally useful for multi-select as they are for single selection. Certainly in elicitation, it would be nice to have.

Yeah, I think I agree with you on that. Thanks for validating the schema - I'll try to implement the client logic whenever I get a moment. I think it should be trivial to automatically switch between a checkbox or a radio selection based on the schema type.

For rigor, I decided to test the EnumSchema meta-schema I defined above, against single and multiple color selection instance schemas, and use those instance schemas to validate expected inputs.

Another thought is that multi-selection enums can have far more complex validators than single choice selection. For example, choose upto two colors or can't choose black and blue together - things like that. IIUC we want to keep the elicitation schemas simple enough that clients can do the syntactic validation atleast. Do you think it's possible to add things like choose at max two or exactly two or things like that in the schema as well or we will have to fallback to server side code for that.

@cliffhall
Copy link
Member

cliffhall commented Aug 1, 2025

@cliffhall Thanks!

@chughtapan For context, where in the spec did you find this particular note?

Here: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/draft/client/elicitation.mdx?plain=1#L282

Ah, yes. We pushed back on the complex objects in the UI because generating forms of nested objects is hard and can be ugly at render time. But this is an enum as a single or multi-select dropdown (or checkboxes vs radio buttons). That won't degrade UX, and opens up possibilities for elicitation, e.g, "Choose all that apply".

Yeah, I think I agree with you on that. Thanks for validating the schema - I'll try to implement the client logic whenever I get a moment. I think it should be trivial to automatically switch between a checkbox or a radio selection based on the schema type.
👍

Another thought is that multi-selection enums can have far more complex validators than single choice selection. For example, choose upto two colors or can't choose black and blue together - things like that. IIUC we want to keep the elicitation schemas simple enough that clients can do the syntactic validation atleast. Do you think it's possible to add things like choose at max two or exactly two or things like that in the schema as well or we will have to fallback to server side code for that.

It would be possible to allow choosing up to some limit with EnumSchema as above and an instance schema that adds constraints.

{
  "type": "array",
  "title": "Color Selection",
  "description": "Choose one or two colors",
  "minItems": 1,
  "maxItems": 2,
  "items": {
    "oneOf": [
      { "const": "#FF0000", "title": "Red" },
      { "const": "#00FF00", "title": "Green" },
      { "const": "#0000FF", "title": "Blue" }
    ]
  }
}
Screenshot 2025-08-01 at 3 59 17 PM Screenshot 2025-08-01 at 3 56 50 PM Screenshot 2025-08-01 at 3 54 16 PM Screenshot 2025-08-01 at 3 55 54 PM Screenshot 2025-08-01 at 3 55 09 PM

@chughtapan
Copy link
Contributor Author

chughtapan commented Aug 2, 2025

@cliffhall I did some more digging: for choices without titles, we should always prefer to use enum instead of oneOf/anyOf because that's default serialization would create.

I created a basic script to validate the default serialization from Python to JSON: https://gist.github.com/chughtapan/2f8738f69098f35f877d1cb3de38aeb2

The outputs are here: https://gist.github.com/chughtapan/c80f175b880f0badc40b133611ab4956

I guess the current schema is pretty clean that way: enums with title just have the additional enumNames field, while the default enums dont. In our current proposal we would have to support both enums (for without title) and one/anyOf for enums with titles. Does that seem reasonable or would it make the schema too complex?

The other thought (related to multi-choice): currently we serialize enums with type: string - but that doesn't make sense for the multi-choice, they should be serialized to Arrays. So maybe those should be two independent elicitation types instead of trying to overload the same enum type?

@chughtapan
Copy link
Contributor Author

chughtapan commented Aug 2, 2025

@cliffhall Working demo: https://asciinema.org/a/anBvJdqEmTjw0JkKYOooQa5Ta

Proof-of-concept implementation: https://github.com/evalstate/fast-agent/pull/324/files
I'm thinking we should start a SEP to discuss more broadly about the exact schema?

@cliffhall
Copy link
Member

cliffhall commented Aug 5, 2025

I'm thinking we should start a SEP to discuss more broadly about the exact schema?

@chughtapan In order to head off an SEP that ends up with a winding discussion, let's start in this thread in the MCP Contributors Discord.

- SingleSelectEnumSchema: Supports both plain enum[] and oneOf with titles
- MultiSelectEnumSchema: Array type for multi-selection with/without titles
- DeprecatedEnumSchema: Maintains backward compatibility with enumNames

This replaces the non-standard enumNames approach with JSON Schema-compliant
patterns using oneOf/const for titled enums, while preserving backward
compatibility and adding multi-select support.
Copy link
Member

@cliffhall cliffhall left a comment

Choose a reason for hiding this comment

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

One small request for now

@chughtapan chughtapan requested a review from cliffhall August 6, 2025 16:12
@chughtapan chughtapan changed the title fix: Replace enumNames with standard-compliant oneOf pattern in Elicitation Schema SEP: Elicitation Enum Schema Improvements and Standards Compliance Aug 11, 2025
@cliffhall cliffhall changed the title SEP: Elicitation Enum Schema Improvements and Standards Compliance Elicitation Enum Schema Improvements and Standards Compliance Aug 21, 2025
@whoiskatrin
Copy link

@chughtapan @cliffhall hey guys, thanks for all this work! any updates on where this might land?

@cliffhall
Copy link
Member

@chughtapan @cliffhall hey guys, thanks for all this work! any updates on where this might land?

We have moved this into SEP-1330 which is currently under an async review by core maintainers. We're hoping for a vote this week.

@chughtapan
Copy link
Contributor Author

@cliffhall -- good catch. fixed this

@chughtapan chughtapan requested a review from cliffhall October 31, 2025 21:13
Copy link
Member

@cliffhall cliffhall left a comment

Choose a reason for hiding this comment

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

Weirdness in the PrimitiveSchemaDefinition. It's not referencing EnumSchema, it's inlining it.

@chughtapan chughtapan requested a review from cliffhall November 4, 2025 22:02
cliffhall
cliffhall previously approved these changes Nov 5, 2025
Copy link
Member

@cliffhall cliffhall left a comment

Choose a reason for hiding this comment

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

LGTM! 👍

@localden
Copy link
Contributor

@chughtapan @cliffhall

👋 just as a reminder, we're aiming to ensure that all SEPs that are on-deck for the 2025-11-25 spec release are verbiage-ready and merged by Friday, November 14, 2025. Please prioritize making the required changes (given that this is accepted with changes, per Core Maintainer review meeting) before then.

@felixweinberger
Copy link
Contributor

felixweinberger commented Nov 11, 2025

@chughtapan @cliffhall

👋 just as a reminder, we're aiming to ensure that all SEPs that are on-deck for the 2025-11-25 spec release are verbiage-ready and merged by Friday, November 14, 2025. Please prioritize making the required changes (given that this is accepted with changes, per Core Maintainer review meeting) before then.

I believe all the comments (primarily about removing reference to "deprecation") have been implemented.

Copy link
Member

@dsp-ant dsp-ant left a comment

Choose a reason for hiding this comment

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

Paul said this is good to go.

@dsp-ant dsp-ant merged commit 11ad2a7 into modelcontextprotocol:main Nov 11, 2025
2 checks passed
@cliffhall
Copy link
Member

cliffhall commented Nov 11, 2025

👋 just as a reminder, we're aiming to ensure that all SEPs that are on-deck for the 2025-11-25 spec release are verbiage-ready and merged by Friday, November 14, 2025. Please prioritize making the required changes (given that this is accepted with changes, per Core Maintainer review meeting) before then.

I believe all the comments (primarily about removing reference to "deprecation")

@localden @felixweinberger done. We've replaced the "deprecation" wording with the term "legacy". We still don't want to encourage the use of the old schema.

@felixweinberger
Copy link
Contributor

👋 just as a reminder, we're aiming to ensure that all SEPs that are on-deck for the 2025-11-25 spec release are verbiage-ready and merged by Friday, November 14, 2025. Please prioritize making the required changes (given that this is accepted with changes, per Core Maintainer review meeting) before then.

I believe all the comments (primarily about removing reference to "deprecation")

@localden @felixweinberger done. We've replaced the "deprecation" wording with the term "legacy". We still don't want to encourage the use of the old schema.

Apologies, hadn't finished my sentence there - "all comments have been implemented" is what I meant to say there.

Looks like we're good to go and this is merged - reviewing modelcontextprotocol/typescript-sdk#1077 atm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SEP-1330: Elicitation Enum Schema Improvements and Standards Compliance

7 participants