/ examples / mcp_server / mcp_elicitation_example.py
mcp_elicitation_example.py
  1  #!/usr/bin/env python3
  2  """
  3  MCP Elicitation Example
  4  
  5  Demonstrates the Elicitation API per MCP 2025-11-25 specification.
  6  Elicitation allows servers to request additional information from users.
  7  
  8  Supports two modes:
  9  - Form mode: Structured data collection with JSON schema validation
 10  - URL mode: External URLs for sensitive interactions (OAuth, payments)
 11  
 12  Usage:
 13      python mcp_elicitation_example.py
 14  """
 15  
 16  import asyncio
 17  from praisonai.mcp_server.elicitation import (
 18      ElicitationHandler,
 19      ElicitationResult,
 20      create_form_request,
 21      create_url_request,
 22  )
 23  
 24  
 25  async def main():
 26      print("=" * 60)
 27      print("MCP Elicitation Example (2025-11-25 Specification)")
 28      print("=" * 60)
 29      
 30      # Create handler in CI mode (non-interactive) with defaults
 31      handler = ElicitationHandler(
 32          ci_mode=True,
 33          ci_defaults={
 34              "name": "John Doe",
 35              "email": "john@example.com",
 36              "confirm": True,
 37          }
 38      )
 39      
 40      # 1. Form mode elicitation
 41      print("\n1. Form Mode Elicitation")
 42      print("-" * 40)
 43      
 44      form_request = create_form_request(
 45          message="Please provide your contact information",
 46          properties={
 47              "name": {
 48                  "type": "string",
 49                  "description": "Your full name",
 50              },
 51              "email": {
 52                  "type": "string",
 53                  "format": "email",
 54                  "description": "Your email address",
 55              },
 56              "age": {
 57                  "type": "integer",
 58                  "description": "Your age",
 59                  "default": 25,
 60              },
 61          },
 62          required=["name", "email"],
 63          title="Contact Form",
 64      )
 65      
 66      print(f"   Request message: {form_request.message}")
 67      print(f"   Request dict: {form_request.to_dict()}")
 68      
 69      result = await handler.elicit(form_request)
 70      print(f"\n   Response action: {result.action.value}")
 71      print(f"   Response content: {result.content}")
 72      print(f"   MCP format: {result.to_dict()}")
 73      
 74      # 2. URL mode elicitation
 75      print("\n2. URL Mode Elicitation")
 76      print("-" * 40)
 77      
 78      url_request = create_url_request(
 79          message="Please authorize access to your GitHub account",
 80          url="https://github.com/login/oauth/authorize?client_id=xxx",
 81          elicitation_id="oauth-github-123",
 82      )
 83      
 84      print(f"   Request message: {url_request.message}")
 85      print(f"   Request URL: {url_request.url}")
 86      print(f"   Elicitation ID: {url_request.elicitation_id}")
 87      print(f"   Request dict: {url_request.to_dict()}")
 88      
 89      # URL mode returns decline in CI mode (cannot be automated)
 90      result = await handler.elicit(url_request)
 91      print(f"\n   Response action: {result.action.value}")
 92      print("   (URL mode cannot be completed in CI mode)")
 93      
 94      # 3. Using factory methods
 95      print("\n3. ElicitationResult Factory Methods")
 96      print("-" * 40)
 97      
 98      # Accept with data
 99      accept_result = ElicitationResult.accept({"confirmed": True, "value": 42})
100      print(f"   Accept: {accept_result.to_dict()}")
101      
102      # Decline with error
103      decline_result = ElicitationResult.decline("Invalid input provided")
104      print(f"   Decline: {decline_result.to_dict()}")
105      
106      # Cancel
107      cancel_result = ElicitationResult.cancel()
108      print(f"   Cancel: {cancel_result.to_dict()}")
109      
110      # 4. Custom handler
111      print("\n4. Custom Elicitation Handler")
112      print("-" * 40)
113      
114      async def custom_handler(request):
115          """Custom handler that auto-approves everything."""
116          print(f"   Custom handler received: {request.message}")
117          return ElicitationResult.accept({"auto_approved": True})
118      
119      custom_elicit = ElicitationHandler()
120      custom_elicit.set_custom_handler(custom_handler)
121      
122      test_request = create_form_request(
123          message="Test custom handler",
124          properties={"test": {"type": "string"}},
125      )
126      
127      result = await custom_elicit.elicit(test_request)
128      print(f"   Custom result: {result.to_dict()}")
129      
130      print("\n" + "=" * 60)
131      print("Elicitation Example Complete!")
132      print("=" * 60)
133  
134  
135  if __name__ == "__main__":
136      asyncio.run(main())