Skip to content

Conversation

@vincent0426
Copy link
Contributor

Add support for string Enum types in elicitation schemas

Related PR: modelcontextprotocol/inspector#902

Changes Made

  • Added StrEnum to _ELICITATION_PRIMITIVE_TYPES tuple
  • Enhanced _is_primitive_field() to detect string enum types using issubclass() checks

Motivation and Context

Per https://modelcontextprotocol.io/specification/2025-06-18/client/elicitation#supported-schema-types, elicitation schemas support enum types.

Currently, python-sdk only supported basic primitive types (str, int, float, bool) in elicitation schemas, but did not recognize Enum types.

How Has This Been Tested?

  • Added test cases in test_elicitation_schema_validation() to verify enum schemas

  • Manual test with

from enum import Enum, StrEnum

from pydantic import BaseModel, Field

from mcp.server.fastmcp import Context, FastMCP
from mcp.server.session import ServerSession

mcp = FastMCP(name="Elicitation Example")


class FruitEnum(str, Enum):
    pear = "pear"
    apple = "apple"


class TestStrEnum(StrEnum):
    one = "1"
    two = "2"
    three = "3"


class BookingPreferences(BaseModel):
    """Schema for collecting user preferences."""

    checkAlternative: bool = Field(description="Would you like to check another date?")
    alternativeDate: str = Field(
        default="2024-12-26",
        description="Alternative date (YYYY-MM-DD)",
    )
    fruit: FruitEnum = FruitEnum.pear
    strenum: TestStrEnum = TestStrEnum.one


@mcp.tool()
async def book_table(date: str, time: str, party_size: int, ctx: Context[ServerSession, None]) -> str:
    """Book a table with date availability check."""
    # Check if date is available
    if date == "2024-12-25":
        # Date unavailable - ask user for alternative
        result = await ctx.elicit(
            message=(f"No tables available for {party_size} on {date}. Would you like to try another date?"),
            schema=BookingPreferences,
        )
        print(result)
        if result.action == "accept" and result.data:
            if result.data.checkAlternative:
                return f"[SUCCESS] Booked for {result.data.alternativeDate}"
            return "[CANCELLED] No booking made"
        return "[CANCELLED] Booking cancelled"

    # Date available
    return f"[SUCCESS] Booked for {date} at {time}"


@mcp.tool()
async def get_uuid(ctx: Context[ServerSession, None]) -> str:
    """Get a unique identifier."""
    result = await ctx.elicit(
        message="Please enter a unique identifier",
        schema=InvalidFormatSchema,
    )
    if result.action == "accept" and result.data:
        return f"[SUCCESS] Unique identifier: {result.data.id}"
    return "[CANCELLED] No unique identifier provided"


if __name__ == "__main__":
    mcp.run(transport="streamable-http")

Results

Screenshot 2025-11-01 at 10 36 00 PM Screenshot 2025-11-01 at 10 36 02 PM

Breaking Changes

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

The documentation doesn't explicitly specify that enums must be string enums. Should we add that clarification since both the TypeScript and Rust SDKs only support string enums?

https://github.com/modelcontextprotocol/typescript-sdk/blob/783d53be1049041cc1f0a23c070c3400208a94ff/src/types.ts#L1221-L1229

https://github.com/modelcontextprotocol/rust-sdk/blob/04e0590652d029e2cdfadee6f4c7255280dfba0e/crates/rmcp/src/model/elicitation_schema.rs#L479-L481

@vincent0426 vincent0426 force-pushed the fix/elicitation-str-enum branch from a44e8b3 to 07bef73 Compare November 2, 2025 06:06
@maxisbey maxisbey added spec P2 Moderate issues affecting some users, edge cases, potentially valuable feature bug Something isn't working labels Nov 4, 2025
@felixweinberger felixweinberger added improves spec compliance When a change improves ability of SDK users to comply with spec definition and removed spec labels Nov 12, 2025
@maxisbey
Copy link
Contributor

Hey sorry it took so long to get to this! Would you still be interested in updating this to the latest from main? There's been quite a lot changed about elicitations since this PR landed.

@vincent0426 vincent0426 force-pushed the fix/elicitation-str-enum branch from 07bef73 to 97b156d Compare December 19, 2025 18:08
@maxisbey
Copy link
Contributor

Hey! Thanks for putting this together. I took a closer look at where things stand now, and wanted to share what I found.

Since this PR was opened, SEP-1330 landed via PR #1246 (merged Nov 23), which added enum support but took a different approach - using json_schema_extra on str or list[str] fields:

class FavoriteColorSchema(BaseModel):
    favorite_color: str = Field(
        description="Select your favorite color",
        json_schema_extra={
            "oneOf": [
                {"const": "red", "title": "Red"},
                {"const": "green", "title": "Green"},
            ]
        },
    )

The tricky thing with native Python enums is that Pydantic generates $ref/$defs in the JSON schema output, which some clients might not handle well - the spec mentions that schemas should be "flat objects with primitive properties only" and that "advanced JSON Schema features are intentionally not supported."

That said, native enum support could still be valuable from a DX perspective - it's more Pythonic and gives you better type checking. It would just need some extra work to inline the $defs before sending to clients.

Given all this, I'm thinking we close this PR and instead open an issue for implementing native Python enum support properly - @vincent0426 what do you think?

AI Disclaimer

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

Labels

bug Something isn't working improves spec compliance When a change improves ability of SDK users to comply with spec definition P2 Moderate issues affecting some users, edge cases, potentially valuable feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants