Skip to main content

MCP Elicitation

Elicitation allows MCP servers to request additional information from users during tool execution. This enables interactive workflows where servers can collect structured data or direct users to external URLs.

Protocol Version

This feature implements MCP Protocol Version 2025-11-25.

Elicitation Modes

ModeDescriptionUse Case
formStructured data with JSON schemaCollecting user preferences, confirmations
urlExternal URL for out-of-band interactionOAuth flows, payments, sensitive data

Action Values

ActionDescription
acceptUser accepted and provided data
declineUser explicitly declined
cancelUser cancelled the request

Python API

Form Mode Elicitation

import asyncio
from praisonai.mcp_server.elicitation import (
    ElicitationHandler,
    ElicitationResult,
    create_form_request,
)

async def main():
    # Create handler (use ci_mode=True for non-interactive)
    handler = ElicitationHandler(
        ci_mode=True,
        ci_defaults={"name": "John", "email": "[email protected]"}
    )
    
    # Create form request
    request = create_form_request(
        message="Please provide your contact information",
        properties={
            "name": {"type": "string", "description": "Your name"},
            "email": {"type": "string", "format": "email"},
            "age": {"type": "integer", "default": 25},
        },
        required=["name", "email"],
        title="Contact Form",
    )
    
    # Process elicitation
    result = await handler.elicit(request)
    
    if result.action.value == "accept":
        print(f"Data: {result.content}")
    elif result.action.value == "decline":
        print(f"Declined: {result.validation_error}")
    else:
        print("Cancelled")

asyncio.run(main())

URL Mode Elicitation

from praisonai.mcp_server.elicitation import create_url_request

# Create URL elicitation for OAuth
request = create_url_request(
    message="Please authorize access to your GitHub account",
    url="https://github.com/login/oauth/authorize?client_id=xxx",
    elicitation_id="oauth-github-123",
)

print(request.to_dict())
# {
#     "message": "Please authorize access to your GitHub account",
#     "mode": "url",
#     "url": "https://github.com/login/oauth/authorize?client_id=xxx",
#     "elicitationId": "oauth-github-123"
# }

Using Factory Methods

from praisonai.mcp_server.elicitation import ElicitationResult

# Accept with data
result = ElicitationResult.accept({"confirmed": True, "value": 42})
print(result.to_dict())
# {"action": "accept", "content": {"confirmed": True, "value": 42}}

# Decline with error
result = ElicitationResult.decline("Invalid input provided")
print(result.to_dict())
# {"action": "decline", "validationError": "Invalid input provided"}

# Cancel
result = ElicitationResult.cancel()
print(result.to_dict())
# {"action": "cancel"}

Custom Handler

async def custom_handler(request):
    """Custom handler for elicitation requests."""
    # Implement your own logic
    if request.mode.value == "form":
        return ElicitationResult.accept({"auto_approved": True})
    return ElicitationResult.decline("URL mode not supported")

handler = ElicitationHandler()
handler.set_custom_handler(custom_handler)

MCP Protocol Messages

Form Mode Request

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "elicitation/create",
  "params": {
    "message": "Please provide your preferences",
    "requestedSchema": {
      "type": "object",
      "properties": {
        "checkAlternative": {
          "type": "boolean",
          "description": "Check another date?"
        },
        "alternativeDate": {
          "type": "string",
          "default": "2024-12-26"
        }
      },
      "required": ["checkAlternative"]
    }
  }
}

URL Mode Request

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "elicitation/create",
  "params": {
    "message": "Please confirm payment",
    "mode": "url",
    "url": "https://payments.example.com/confirm?id=123",
    "elicitationId": "payment-123"
  }
}

Response

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "action": "accept",
    "content": {
      "checkAlternative": true,
      "alternativeDate": "2024-12-26"
    }
  }
}

Security Considerations

Form Mode

  • Use for non-sensitive structured data
  • Schema validation ensures data integrity
  • Default values are supported

URL Mode

  • Use for sensitive operations (OAuth, payments)
  • Data never passes through the MCP server
  • Requires elicitationId for tracking

CI/Non-Interactive Mode

For automated environments:
handler = ElicitationHandler(
    ci_mode=True,
    ci_defaults={
        "name": "CI User",
        "confirm": True,
    }
)
In CI mode:
  • Form mode uses provided defaults
  • URL mode returns decline (cannot be automated)