MCP Elicitation

Request user input during server operations per MCP 2025-11-25

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

python
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": "john@example.com"}
    )

    # 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

python
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

python
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

python
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

json
{
  "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

json
{
  "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

json
{
  "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:

python
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)

Related