Implement SEP-1036: URL mode elicitation for secure out-of-band interactions (#1580)
Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com> Co-authored-by: Felix Weinberger <fweinberger@anthropic.com>
This commit is contained in:
parent
27279bc157
commit
02b7889929
1 changed files with 1372 additions and 15 deletions
64
README.md
64
README.md
|
|
@ -808,10 +808,21 @@ Request additional information from users. This example shows an Elicitation dur
|
|||
|
||||
<!-- snippet-source examples/snippets/servers/elicitation.py -->
|
||||
```python
|
||||
"""Elicitation examples demonstrating form and URL mode elicitation.
|
||||
|
||||
Form mode elicitation collects structured, non-sensitive data through a schema.
|
||||
URL mode elicitation directs users to external URLs for sensitive operations
|
||||
like OAuth flows, credential collection, or payment processing.
|
||||
"""
|
||||
|
||||
import uuid
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from mcp.server.fastmcp import Context, FastMCP
|
||||
from mcp.server.session import ServerSession
|
||||
from mcp.shared.exceptions import UrlElicitationRequiredError
|
||||
from mcp.types import ElicitRequestURLParams
|
||||
|
||||
mcp = FastMCP(name="Elicitation Example")
|
||||
|
||||
|
|
@ -828,7 +839,10 @@ class BookingPreferences(BaseModel):
|
|||
|
||||
@mcp.tool()
|
||||
async def book_table(date: str, time: str, party_size: int, ctx: Context[ServerSession, None]) -> str:
|
||||
"""Book a table with date availability check."""
|
||||
"""Book a table with date availability check.
|
||||
|
||||
This demonstrates form mode elicitation for collecting non-sensitive user input.
|
||||
"""
|
||||
# Check if date is available
|
||||
if date == "2024-12-25":
|
||||
# Date unavailable - ask user for alternative
|
||||
|
|
@ -845,6 +859,54 @@ async def book_table(date: str, time: str, party_size: int, ctx: Context[ServerS
|
|||
|
||||
# Date available
|
||||
return f"[SUCCESS] Booked for {date} at {time}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def secure_payment(amount: float, ctx: Context[ServerSession, None]) -> str:
|
||||
"""Process a secure payment requiring URL confirmation.
|
||||
|
||||
This demonstrates URL mode elicitation using ctx.elicit_url() for
|
||||
operations that require out-of-band user interaction.
|
||||
"""
|
||||
elicitation_id = str(uuid.uuid4())
|
||||
|
||||
result = await ctx.elicit_url(
|
||||
message=f"Please confirm payment of ${amount:.2f}",
|
||||
url=f"https://payments.example.com/confirm?amount={amount}&id={elicitation_id}",
|
||||
elicitation_id=elicitation_id,
|
||||
)
|
||||
|
||||
if result.action == "accept":
|
||||
# In a real app, the payment confirmation would happen out-of-band
|
||||
# and you'd verify the payment status from your backend
|
||||
return f"Payment of ${amount:.2f} initiated - check your browser to complete"
|
||||
elif result.action == "decline":
|
||||
return "Payment declined by user"
|
||||
return "Payment cancelled"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def connect_service(service_name: str, ctx: Context[ServerSession, None]) -> str:
|
||||
"""Connect to a third-party service requiring OAuth authorization.
|
||||
|
||||
This demonstrates the "throw error" pattern using UrlElicitationRequiredError.
|
||||
Use this pattern when the tool cannot proceed without user authorization.
|
||||
"""
|
||||
elicitation_id = str(uuid.uuid4())
|
||||
|
||||
# Raise UrlElicitationRequiredError to signal that the client must complete
|
||||
# a URL elicitation before this request can be processed.
|
||||
# The MCP framework will convert this to a -32042 error response.
|
||||
raise UrlElicitationRequiredError(
|
||||
[
|
||||
ElicitRequestURLParams(
|
||||
mode="url",
|
||||
message=f"Authorization required to connect to {service_name}",
|
||||
url=f"https://{service_name}.example.com/oauth/authorize?elicit={elicitation_id}",
|
||||
elicitationId=elicitation_id,
|
||||
)
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
_Full example: [examples/snippets/servers/elicitation.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/elicitation.py)_
|
||||
|
|
|
|||
Loading…
Reference in a new issue