FastMCP: Elicitation
Relevant source files
The following files were used as context for generating this wiki page:
Elicitation is a mechanism within the FastMCP framework that allows a server-side tool to pause its execution to request interactive input from the client. This feature is essential for creating tools that require user confirmation, clarification, or additional data that was not provided in the initial tool call. The process is handled asynchronously, with the server sending an elicitation request and waiting for the client to respond.
The core of this feature is the ctx.elicit() method, which is accessible via the Context object injected into tools. On the client side, a corresponding elicitation_callback function must be implemented to handle these requests, creating a seamless, interactive loop between the server's logic and the user.
Sources: tests/server/fastmcp/test_elicitation.py, tests/server/fastmcp/test_integration.py
Core Architecture
The elicitation architecture involves a coordinated exchange between the server-side tool and the client-side session handler. When a tool needs user input, it calls ctx.elicit(), which sends a formal request to the client. The client processes this request via a registered callback, gathers the necessary input (e.g., through a UI prompt), and sends the data back. The server tool, which was paused, then resumes its execution with the new information.
Sources: tests/server/fastmcp/test_elicitation.py:18-27, tests/server/fastmcp/test_integration.py:404-405
Elicitation Flow
The following sequence diagram illustrates the complete, end-to-end flow of an elicitation request during a tool call.
This diagram shows the full lifecycle, from the initial tool call to the final result, including the pause for user interaction.
Sources: tests/server/fastmcp/test_integration.py:400-427
Server-Side Implementation
On the server, elicitation is initiated from within a tool using the elicit method on the Context object. This Context is automatically injected into any tool function that includes it as a typed parameter.
Sources: tests/server/fastmcp/test_server.py:1015-1022, tests/server/fastmcp/test_tool_manager.py:202-210
ctx.elicit()
The ctx.elicit() method is an awaitable call that takes two key arguments:
| Parameter | Type | Description |
|---|---|---|
message | str | The prompt or question to display to the user on the client side. |
schema | type[pydantic.BaseModel] | A Pydantic model that defines the structure and types of the expected data. |
The method returns an ElicitResult object containing the user's action and data.
Sources: tests/server/fastmcp/test_elicitation.py:20-22
Example Tool
The following tool demonstrates how to use ctx.elicit to ask the user a question and process the response.
# From: tests/server/fastmcp/test_elicitation.py:15-27
class AnswerSchema(BaseModel):
answer: str = Field(description="The user's answer to the question")
@mcp.tool(description="A tool that uses elicitation")
async def ask_user(prompt: str, ctx: Context[ServerSession, None]) -> str:
result = await ctx.elicit(message=f"Tool wants to ask: {prompt}", schema=AnswerSchema)
if result.action == "accept" and result.data:
return f"User answered: {result.data.answer}"
elif result.action == "decline":
return "User declined to answer"
else:
return "User cancelled"
Sources: tests/server/fastmcp/test_elicitation.py:15-27
Client-Side Handling
To support elicitation, the client must provide an elicitation_callback function when initializing the ClientSession. This asynchronous function is responsible for handling incoming ElicitRequestParams and returning an ElicitResult.
Sources: tests/server/fastmcp/test_integration.py:404-405
Data Models
The interaction is governed by two primary data models: ElicitRequestParams sent by the server and ElicitResult returned by the client.
The ElicitResult.content dictionary must conform to the JSON schema provided in ElicitRequestParams.schema.
Sources: tests/server/fastmcp/test_elicitation.py:11, tests/server/fastmcp/test_integration.py:270-276
ElicitResult
The client's response is encapsulated in an ElicitResult object with the following fields:
| Field | Type | Description |
|---|---|---|
action | str | Must be either "accept" or "decline". |
content | dict | The data payload from the client, conforming to the requested schema. |
Sources: tests/server/fastmcp/test_integration.py:270-276
Example Callback
This callback function demonstrates how a client might handle an elicitation request from a restaurant booking tool.
# From: tests/server/fastmcp/test_integration.py:270-276
async def elicitation_callback(context: RequestContext[ClientSession, None], params: ElicitRequestParams):
"""Elicitation callback for tests."""
if "No tables available" in params.message:
return ElicitResult(
action="accept",
content={"checkAlternative": True, "alternativeDate": "2024-12-26"},
)
else:
return ElicitResult(action="decline")
Sources: tests/server/fastmcp/test_integration.py:270-276
Schema and Validation
The Pydantic schema provided to ctx.elicit is critical for defining the data contract. The framework enforces strict validation rules on these schemas to ensure they are simple and suitable for user input.
Validation Rules
- Primitives Only: Schemas must only contain primitive types (
str,int,float,bool). - No Complex Types: Complex types such as
list,dict, or nestedBaseModels are disallowed and will raise aTypeErroron the server. - Optional Fields Allowed: Fields can be marked as
Optional(e.g.,str | None). This allows for non-mandatory user inputs.
Using an invalid schema, like one containing a list, will cause the ctx.elicit call to fail immediately with a TypeError before any request is sent to the client.
Sources: tests/server/fastmcp/test_elicitation.py:89-114, 137-160
Practical Example: Restaurant Booking
A common use case for elicitation is handling situations where a tool needs to confirm an alternative action with the user. The integration tests provide an example of a book_table tool. If the requested date is unavailable, the tool uses elicitation to ask the user if they want to book on an alternative date.
This flow is visualized below.
This demonstrates how elicitation enables a tool to handle conditional logic based on real-time user feedback.
Sources: examples/snippets/servers/elicitation.py, tests/server/fastmcp/test_integration.py:412-420
Summary
The elicitation feature is a powerful mechanism for building interactive, user-aware tools in the FastMCP ecosystem. It provides a structured and type-safe way for server-side processes to pause and request input from a client, enabling complex, multi-step interactions. By cleanly separating the tool's logic from the client's UI implementation, it promotes modular and maintainable code. The strict schema validation ensures that the data exchanged during these interactions is simple and reliable.