Elicitation lets your server ask the client to collect structured input from the user while a tool is running—confirmations, missing parameters, or a small “form”.
Basic usage
from dedalus_mcp import get_context, tool, types
@tool(description="Deploy to environment")
async def deploy(env: str) -> str:
ctx = get_context()
server = ctx.server
if server is None:
raise RuntimeError("No active server in context")
result = await server.request_elicitation(
types.ElicitRequestParams(
message=f"Deploy to {env}?",
requestedSchema={
"type": "object",
"properties": {
"confirm": {"type": "boolean"},
},
"required": ["confirm"],
},
)
)
if result.action == "accept" and result.content and result.content.get("confirm"):
return f"Deployed to {env}"
return "Deployment cancelled"
Parameters
request_elicitation(...) takes an ElicitRequestParams with:
message: str: text shown to the user
requestedSchema: dict: a restricted JSON Schema object describing the expected fields
params = types.ElicitRequestParams(
message="Enter configuration",
requestedSchema={
"type": "object",
"properties": {
"name": {"type": "string"},
"replicas": {"type": "integer"},
"dry_run": {"type": "boolean"},
},
"required": ["name"],
},
)
result = await ctx.server.request_elicitation(params)
Schema limitations (enforced by Dedalus MCP):
- top-level
type must be "object"
properties must be a non-empty object
- property
type must be one of: "string", "number", "integer", "boolean"
- nested objects/arrays are not supported
Response actions
The client returns an ElicitResult with:
action: "accept" | "decline" | "cancel"
content: optional mapping (present when action == "accept")
result = await ctx.server.request_elicitation(params)
match result.action:
case "accept":
data = result.content or {}
return f"Got: {data}"
case "decline":
return "User declined"
case "cancel":
return "User cancelled"
Example: Progressive disclosure
Collect complex information step-by-step:
from dedalus_mcp import get_context, tool, types
@tool(description="Create new project")
async def create_project() -> str:
ctx = get_context()
server = ctx.server
if server is None:
raise RuntimeError("No active server in context")
name = await server.request_elicitation(
types.ElicitRequestParams(
message="Project name:",
requestedSchema={
"type": "object",
"properties": {"name": {"type": "string"}},
"required": ["name"],
},
)
)
if name.action != "accept" or not name.content:
return "Cancelled"
project_type = await server.request_elicitation(
types.ElicitRequestParams(
message="Project type (web/api/cli):",
requestedSchema={
"type": "object",
"properties": {"type": {"type": "string"}},
"required": ["type"],
},
)
)
if project_type.action != "accept" or not project_type.content:
return "Cancelled"
confirm = await server.request_elicitation(
types.ElicitRequestParams(
message=f"Create {project_type.content['type']} project '{name.content['name']}'?",
requestedSchema={
"type": "object",
"properties": {"confirm": {"type": "boolean"}},
"required": ["confirm"],
},
)
)
if confirm.action == "accept" and confirm.content and confirm.content.get("confirm"):
return f"Created {name.content['name']}"
return "Cancelled"
Error handling
Elicitation requires an active MCP session and a client that advertises the elicitation capability. If not, request_elicitation(...) raises McpError (typically METHOD_NOT_FOUND), and timeouts raise McpError as well.
from mcp.shared.exceptions import McpError
from dedalus_mcp import types
try:
result = await ctx.server.request_elicitation(params)
except McpError as e:
return f"Elicitation unavailable: {e}"
Last modified on January 27, 2026