Skip to content

Commit fa4e40c

Browse files
committed
fix: rewrite URL mode elicitation example with realistic flow
1 parent d58b39e commit fa4e40c

File tree

1 file changed

+32
-10
lines changed

1 file changed

+32
-10
lines changed

docs/server.md

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,28 +1007,50 @@ async def pick_color(ctx: Context[ServerSession, None]) -> str:
10071007
return "No color selected"
10081008
```
10091009

1010-
#### Elicitation Complete Notification
1010+
#### URL Mode Elicitation
10111011

1012-
For URL mode elicitations, send a completion notification after the out-of-band interaction finishes. This tells the client that the elicitation is done and it may retry any blocked requests:
1012+
URL mode elicitation directs the user to an external URL for out-of-band interactions that must not pass through the MCP client (e.g., entering sensitive data, OAuth flows). The tool call blocks while waiting for the user to complete the interaction:
10131013

10141014
```python
1015+
import asyncio
1016+
import uuid
1017+
1018+
import anyio
1019+
10151020
from mcp.server.fastmcp import Context, FastMCP
10161021
from mcp.server.session import ServerSession
10171022

1018-
mcp = FastMCP("Elicit Complete Example")
1023+
mcp = FastMCP("Weather Example")
1024+
1025+
# Simulates a database that the web form writes to on submit
1026+
completed_elicitations: dict[str, dict] = {}
10191027

10201028

10211029
@mcp.tool()
1022-
async def handle_oauth_callback(
1023-
elicitation_id: str, ctx: Context[ServerSession, None]
1024-
) -> str:
1025-
"""Called when OAuth flow completes out-of-band."""
1026-
# ... process the callback ...
1030+
async def get_weather(ctx: Context[ServerSession, None]) -> str:
1031+
"""Get weather for the user's address (collected via secure form)."""
1032+
elicitation_id = str(uuid.uuid4())
1033+
1034+
# Direct the user to a web form to enter their address
1035+
result = await ctx.elicit_url(
1036+
message="Please enter your address for a weather lookup.",
1037+
url=f"https://example.com/address-form?id={elicitation_id}",
1038+
elicitation_id=elicitation_id,
1039+
)
1040+
1041+
if result.action != "accept":
1042+
return "Weather lookup cancelled."
1043+
1044+
# Poll until the web form submits (writes to the database)
1045+
with anyio.fail_after(120):
1046+
while elicitation_id not in completed_elicitations:
1047+
await asyncio.sleep(1)
10271048

1028-
# Notify the client that the elicitation is done
1049+
# Notify the client that the out-of-band interaction is done
10291050
await ctx.session.send_elicit_complete(elicitation_id)
10301051

1031-
return "Authorization complete"
1052+
address = completed_elicitations.pop(elicitation_id)
1053+
return f"Weather for {address['street']}: 72°F and sunny"
10321054
```
10331055

10341056
### Sampling

0 commit comments

Comments
 (0)