Skip to content

MCP 6/18/25: Elicitation support #889

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jun 28, 2025
Merged

MCP 6/18/25: Elicitation support #889

merged 16 commits into from
Jun 28, 2025

Conversation

jlowin
Copy link
Owner

@jlowin jlowin commented Jun 20, 2025

FastMCP now supports elicitation - the ability for MCP servers to request additional information from users during tool execution. This enables interactive workflows where tools can ask for clarification, gather missing data, or prompt for user confirmation.

Closes #970
Closes #850
Closes #466
Implements a clean DX for modelcontextprotocol/modelcontextprotocol#382

Key Implementation Features

FastMCP Convenience Layer

While MCP elicitation only supports flat object schemas with primitive properties, FastMCP provides convenient abstractions:

  • Scalar Auto-wrapping: Primitive types (str, int, bool, float) are automatically wrapped in object schemas and unwrapped on response
  • Constrained Choices: Support for Literal types, Enum classes, and lists of strings as a shortcut for constrained options
  • Structured Types: Full support for dataclasses, TypedDict, and Pydantic models
  • Type Safety: FastMCP Clients receive dataclasses rather than raw JSON schemas in order to create and hydrate their responses.

Usage Examples

Simple scalar elicitation (auto-wrapped):

result = await ctx.elicit("What's your name?", response_type=str)
# FastMCP automatically wraps str in {"type": "object", "properties": {"value": {"type": "string"}}}
# and unwraps the response back to a string

Constrained choices (all equivalent, produce enum schema):

# List shortcut (FastMCP convenience - not in MCP spec)
result = await ctx.elicit("Priority?", response_type=["low", "medium", "high"])

# Literal type
result = await ctx.elicit("Priority?", response_type=Literal["low", "medium", "high"]) 

# Enum class
result = await ctx.elicit("Priority?", response_type=Priority)

Structured data:

@dataclass
class UserInfo:
    name: str
    age: int
    priority: Literal["low", "medium", "high"]

result = await ctx.elicit("Enter details:", response_type=UserInfo)

All approaches automatically generate MCP-compliant JSON schemas with proper enum constraints and handle the complexity of wrapping/unwrapping data for seamless developer experience.

Client Integration

async def handle_elicitation(message, response_type, params, context):
    # params.requestedSchema contains the generated JSON schema
    user_input = present_form_to_user(message, params.requestedSchema)
    return ElicitResult(action="accept", content=user_input)

async with Client(server, elicitation_handler=handle_elicitation) as client:
    result = await client.call_tool("interactive_tool", {})

Documentation Structure

Added comprehensive documentation following the established FastMCP pattern:

  • Server-side: /servers/elicitation - Complete usage patterns and examples
  • Client-side: /clients/elicitation - Handler implementation guide
  • Context integration: Updated /servers/context with cross-references

The implementation maintains full MCP protocol compatibility while providing the developer experience FastMCP is known for.

jlowin and others added 3 commits June 20, 2025 07:03
Added comprehensive elicitation support including:
- Client-side handler infrastructure following sampling pattern
- Server-side Context.elicit() method with type safety and validation
- Support for primitive types (str, int, float, bool) with automatic wrapping
- Support for dataclasses and other complex types
- Pattern matching with AcceptedElicitation, DeclinedElicitation, CancelledElicitation
- Comprehensive atomic test coverage for all scenarios

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@jlowin jlowin changed the title Set type adapter parent depth to 3 Elicitation support Jun 20, 2025
@jlowin jlowin added the feature label Jun 20, 2025
@jlowin jlowin added this to the MCP 6/18/25 milestone Jun 20, 2025
@jlowin jlowin changed the title Elicitation support MCP 6/18/25: Elicitation support Jun 20, 2025
@jlowin jlowin mentioned this pull request Jun 25, 2025
Base automatically changed from protocol-update to main June 26, 2025 22:45
@github-actions github-actions bot added the documentation Improvements or additions to documentation label Jun 28, 2025
@jlowin jlowin merged commit 6e81f0c into main Jun 28, 2025
9 checks passed
@jlowin jlowin deleted the elicitation branch June 28, 2025 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation feature tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Human in the loop approvals Support for Elicitation client send msg to server
1 participant