Understanding Elicitation

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In the previous lessons, your tool executions were “fire-and-forget.” The LLM (or client) sent a request, the tool ran its logic, and immediately returned a result.

But what happens when a tool needs to perform a high-stakes operation, like deleting a database table or transferring money? You don’t want the server to execute that immediately. You want it to pause, ask the user for confirmation or extra details, and only then proceed.

This capability is called Elicitation.

Elicitation allows an MCP Server to ask the Client for input during the execution of a tool. It turns a one-way command into a two-way conversation.

The Compatibility Challenge

It is important to understand that Elicitation is a sophisticated feature that requires explicit support from the Host application.

The Interaction Flow

Here is how the flow works when the Host application supports Elicitation:

Implementing the Server

You will now create a system that simulates a database manager. It will allow read-only queries freely but will trigger an Elicitation flow for destructive commands.

What You Are Building

You are building a tiny server that pauses on dangerous SQL and asks the client to confirm. The client becomes the “human approval” step and sends structured input back to the server before it proceeds.

Key Concepts in db_server.py:

  • ctx: Context: Note the new argument in execute_query. By adding ctx: Context, FastMCP automatically injects the connection context, giving you access to special methods like elicit.
  • SafetyVerification: We use Pydantic to define exactly what we need from the user. We aren’t just asking “Yes or No”; we are enforcing structured data (Environment, Justification, Confirmation).
  • await ctx.elicit(...): This is the core logic. It sends a message and the schema to the client. The Python function execution creates a checkpoint here and waits.

How the Server Script Works

  • FastMCP(...) starts the MCP server and exposes tools over streamable-http.
  • SafetyVerification defines the exact input the user must provide.
  • ctx.elicit(...) pauses the tool and asks the client for that input.
  • After the client replies, the tool resumes and validates the response before returning a final result.

Implementing the Custom Client

Since standard AI clients might not support this flow yet, you must write a custom client. This client will act as the Host application, intercepting the server’s request and asking you (the user) for input via the terminal.

Key Concepts in db_client.py:

  • elicitation_handler: This is a standalone asynchronous function. It receives the message from the server. In a real desktop app, this would open a modal window. In this script, it uses input() to pause the terminal and ask you for data.
  • elicitation_callback=elicitation_handler: When initializing the ClientSession, you must register your handler. This is the crucial step that “enables” elicitation support for your client.

How the Client Script Works

  • elicitation_handler(...) is the callback the server triggers when it calls ctx.elicit(...).
  • It collects user input via input() and returns a structured response that matches SafetyVerification.
  • ClientSession(..., elicitation_callback=...) is what makes the client “elicitation-aware.”

Run It

  1. In one terminal, start the server:
See forum comments
Download course materials from Github
Previous: Introduction Next: Handling Elicitation with a Custom Client