Skip to content

We need basic "cancel / reject / accept" elicitations requiring only confirmation / reject with no data #1284

@owengo

Description

@owengo

Initial Checks

Description

It would be nice to create very simple cancel / reject / accept elicitations like this:

# Elicitation schemas for user confirmation
class CreateDocumentConfirmation(BaseModel):
    """Schema for create document confirmation."""
    #confirm: bool   <== We don't need this, it creates  a useless box to  the click for the client

An easy fix in elicitation.py would be:

    if result.action == "accept" and result.content:
        # Validate and parse the content using the schema
        validated_data = schema.model_validate(result.content)
        return AcceptedElicitation(data=validated_data)
    elif result.action == "accept":
        validated_data = schema.model_validate({})
        return AcceptedElicitation(data=validated_data)
    elif result.action == "decline":
        return DeclinedElicitation()
    elif result.action == "cancel":
        return CancelledElicitation()
    else:
        # This should never happen, but handle it just in case
        raise ValueError(f"Unexpected elicitation action: {result.action}")

Note that the typescript sdk allows this behavior:

The behavior is possible with the typescript sdk:

   const result = await server.server.elicitInput({
       message: `${confirmationMessage}`,
        requestedSchema: {
         type: "object",
         properties: {
         },
         required: []
       }
     });  
     if (result.action === "accept") { 
       log.warn(`User accepted usage of ${toolName}`, {
         user: userEmail,
       });
       return true;
     } else {
...

Example Code

from mcp.server.fastmcp import Context, FastMCP

# Elicitation schemas for user confirmation
class CreateDocumentConfirmation(BaseModel):
    """Schema for create document confirmation."""

mcp = FastMCP("test-elicit")

@mcp.tool()
async def create_document(
    ctx: Context[ServerSession, None],
    name: str,
    html_content: str
) -> Dict[str, Any]:
    """Create a new  document"""
    user_email = await check_user_auth(ctx)
    start_time = time.time()
    
    try:
        # Request user confirmation via elicitation
        try:
            await ctx.info(f"Requesting confirmation for document creation: {name}")
            confirmation_result = await ctx.elicit(
                f"Are you sure you want to create document '{name}'?",
                CreateDocumentConfirmation
            )
            
            await ctx.info(f"Confirmation result: {confirmation_result.action}")
            if confirmation_result.action != "accept":
                return {"result": f"Document creation cancelled by user"}
                
        except Exception as elicit_error:
            await ctx.error(f"Elicitation failed: {elicit_error}")
            return {"result": f"Document creation cancelled due to confirmation error"}
 ...


So currently this example *does not work* because of the validation issue , we have a: ValueError(f"Unexpected elicitation action: {result.action}")  ( where result.action == "accept" ) .

Python & MCP Python SDK

python3.11
mcp-1.13.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs confirmationNeeds confirmation that the PR is actually required or needed.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions