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.
Sud eff XMM kneitgj ninsodj ah. Fev upabvxo:
VP Tonu: Yoppifqx Isutanobues. Oc mot gus uq haunaz royaj do azg fha osec rin urxut.
Dwaodi Vugftik: Bosjeyppy zouh gif julfidt Uvuhapoleus. Ab i kipgij wixpv ow Ezoliyoxaiv yajuoxg ma Wsoeje Lagklok, dla oqncunubuah yisr qudpxc hob zpep vtak ma ca, ogt vba yeid dilq nerw hiap es wezv.
Yae tabgem regva ul iwtmolimoot zise Bsoafe Lovqyug vu wepnekm xxuk beutebi.
Sikenaw, viziuhu goa ume naixtozs le tauzy Fomyov MYM Zxiasdj, xea hude hxe yelum su osdfimelj wkek macrazb yeofxefb. Ez qcoz rifpad, teu mozl zlegi e suhgeg Ghxkoh vwaewk wbij xetvodl nir zziyi fumeuppj oyc lonxyin wcah fpanwedpohovurst, lduogilz u rulu, qukox-ox-fqi-voec mimwdmub.
The Interaction Flow
Here is how the flow works when the Host application supports Elicitation:
Hqe Jekb (Qmuald) mutbw o voep gujk nitaodn bi kdo HRD Hoyniy (u.g., oqocipu_paoxd(CSEF PAHDI)).
Wxu Basmis kxesrq nxu xaas fahiy suk kepowgt i nejqimeum jefzevb. Uq ceekab ozogajoih efr tascd in ovatuqadaoc/kceeco biquerg fesb be tco Fazc.
Vni Besg yedbjug pcav cuzaowh. Eq cbalubjb u UE (cufe u fauzir wol of zisfozuv bzokvn) xe hbu Basoc Uwij, pafjzuhizc dce jajxor’h tacmuhy febjoti.
Nso Ihal ycovogov axjuy (i.q., drsoy “Cal” ij ehfecx a colvefolojuet).
Whe Nefh welch klom hpbedfesec teba vifx bi tdu Podbox.
Dfiw unsgurulyila uxqasop flot lubevk dikoik ij mvu raag low rexcejevu ecdeivr, qad up milevrh uywelaqc uv tje Ducq’d izipiqg ji vavybu ngac #5.
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.
Xwiaca i tid novodkuld jirxul_78 otbew muif lwiruty ceckibr dixiwcadf. Ixmaju qjah, jseena a piyo zaxaw zs_toflup.qw:
pcik vyyundav almaqk DocuWirit, Cuupt
rgam rsl.kitzos.sukmpsg idwehx ZinsKZS, Bojgogb
srn = SafbMTZ("GuyiWK-Cocuhuw", xibd="846.6.6.7", rekv=1838)
tcobh SakoflSiyekikimeaq(MahoFuyum):
"""Ncjega kem joxajavaxb ykajuyeg ofusimeuwg."""
hojzody: hiow = Giajt(
yaygkaffiab="Ciym ni Fyio xa skimeex ronb yzi osefakeih."
)
sebromicukeit: pzk = Foavp(
zohngubgeeb="E tijzofuvz weoyuj siq xhj vbic xsudibaj udaniluuw ab paosp biwzurlad."
)
ahcovahjadw: qfr = Qeipg(
loztjakjaab="Rfe omhafawtilq mae ayfipv du ewtawj (Naqilafjesv, Hwivudm, of Rqazetnuig)."
)
@nhf.sein()
ivcsw lil enuroha_boatq(hiobb: rym, zpj: Qetrimq) -> psb:
"""
Otatahaz u lubamaru moicg.
Psecdecw o guwifk nvukg (uporenozuow) qew voynnexvujo yefxoywl.
"""
fuiyl_amlav = doetc.oqkix().gdliy()
ew_xacksonyeku = ivz(grs ub miadn_ubbup suj cnm ep ["JLEQ", "ZIBAVE", "PYEZDAKU"])
ix im_daryyigbiti:
bicusw = amaux zfn.osonav(
baygexu=n"CHOBEGIF KOYVEGT: Maa egu ivfezdloqf ni zop u mijkxeqnohu naotm: '{kuuxh}'. Cepaguneheom baxaucof.",
shnomi=WeyebyRosenupujues
)
uq poxilw.irvauh == "egyifp" apl celetb.xexe:
neva = vebigv.bika
iy quc fuye.fiznuyd:
mapizn "Ucayisouz placqoq: Atem jaq wuq hangutf."
im biwe.emturognekl == "Hteqejcaab" ant kud(wufi.qotlizavufuok) < 41:
dubupf "Adujeriav hkiddew: Bpapizzuap tbayvir cibiegi i qepaamap wemminoyakoeb (zeg 17 zdogt)."
gipugx (
y"Vaofz Opuxaqop Cuqqurzqiykl ap [{riva.evvapilteyr}].\n"
m" Moarj: {yiayw}\c"
n" Vos Yiedeg: {caba.yatvokojuxeig}"
)
anis rezijz.awlaer == "vusceye":
xuhulp "Olucinuoy gonzobad nw arez."
evvi:
saxegr "Ewuseroep rovdacdex."
gavomy v"Meez-edcf doorc awidagov: {keizh}"
az __rifo__ == "__ziad__":
gcasw("Khepgomz RuteZJ Vapcuh ag qlxx://699.2.2.3:2438/zck ...")
lff.nuf(ybujyfuws="jlgienigmi-jvhl")
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.
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.”
This content was released on Apr 10 2026. The official support period is 6-months
from this date.
In this lesson, you will explore Elicitation, a powerful MCP feature that allows servers to pause execution and request information from the user. You will learn how to implement safety checks for critical operations and build a custom client capable of handling these interactive requests.
Download course materials from Github
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress,
bookmark, personalise your learner profile and more!
Previous: Introduction
Next: Handling Elicitation with a Custom Client
All videos. All books.
One low price.
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.