@@ -808,10 +808,21 @@ Request additional information from users. This example shows an Elicitation dur
808808
809809<!-- snippet-source examples/snippets/servers/elicitation.py -->
810810``` python
811+ """ Elicitation examples demonstrating form and URL mode elicitation.
812+
813+ Form mode elicitation collects structured, non-sensitive data through a schema.
814+ URL mode elicitation directs users to external URLs for sensitive operations
815+ like OAuth flows, credential collection, or payment processing.
816+ """
817+
818+ import uuid
819+
811820from pydantic import BaseModel, Field
812821
813822from mcp.server.fastmcp import Context, FastMCP
814823from mcp.server.session import ServerSession
824+ from mcp.shared.exceptions import UrlElicitationRequiredError
825+ from mcp.types import ElicitRequestURLParams
815826
816827mcp = FastMCP(name = " Elicitation Example" )
817828
@@ -828,7 +839,10 @@ class BookingPreferences(BaseModel):
828839
829840@mcp.tool ()
830841async def book_table (date : str , time : str , party_size : int , ctx : Context[ServerSession, None ]) -> str :
831- """ Book a table with date availability check."""
842+ """ Book a table with date availability check.
843+
844+ This demonstrates form mode elicitation for collecting non-sensitive user input.
845+ """
832846 # Check if date is available
833847 if date == " 2024-12-25" :
834848 # Date unavailable - ask user for alternative
@@ -845,6 +859,54 @@ async def book_table(date: str, time: str, party_size: int, ctx: Context[ServerS
845859
846860 # Date available
847861 return f " [SUCCESS] Booked for { date} at { time} "
862+
863+
864+ @mcp.tool ()
865+ async def secure_payment (amount : float , ctx : Context[ServerSession, None ]) -> str :
866+ """ Process a secure payment requiring URL confirmation.
867+
868+ This demonstrates URL mode elicitation using ctx.elicit_url() for
869+ operations that require out-of-band user interaction.
870+ """
871+ elicitation_id = str (uuid.uuid4())
872+
873+ result = await ctx.elicit_url(
874+ message = f " Please confirm payment of $ { amount:.2f } " ,
875+ url = f " https://payments.example.com/confirm?amount= { amount} &id= { elicitation_id} " ,
876+ elicitation_id = elicitation_id,
877+ )
878+
879+ if result.action == " accept" :
880+ # In a real app, the payment confirmation would happen out-of-band
881+ # and you'd verify the payment status from your backend
882+ return f " Payment of $ { amount:.2f } initiated - check your browser to complete "
883+ elif result.action == " decline" :
884+ return " Payment declined by user"
885+ return " Payment cancelled"
886+
887+
888+ @mcp.tool ()
889+ async def connect_service (service_name : str , ctx : Context[ServerSession, None ]) -> str :
890+ """ Connect to a third-party service requiring OAuth authorization.
891+
892+ This demonstrates the "throw error" pattern using UrlElicitationRequiredError.
893+ Use this pattern when the tool cannot proceed without user authorization.
894+ """
895+ elicitation_id = str (uuid.uuid4())
896+
897+ # Raise UrlElicitationRequiredError to signal that the client must complete
898+ # a URL elicitation before this request can be processed.
899+ # The MCP framework will convert this to a -32042 error response.
900+ raise UrlElicitationRequiredError(
901+ [
902+ ElicitRequestURLParams(
903+ mode = " url" ,
904+ message = f " Authorization required to connect to { service_name} " ,
905+ url = f " https:// { service_name} .example.com/oauth/authorize?elicit= { elicitation_id} " ,
906+ elicitationId = elicitation_id,
907+ )
908+ ]
909+ )
848910```
849911
850912_ Full example: [ examples/snippets/servers/elicitation.py] ( https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/elicitation.py ) _
0 commit comments