Перейти к основному содержимому

Elicitation

This guide explains how to use elicitation on the server side to request additional user input or external actions during tool execution.

What is Elicitation?

Elicitation allows a server tool to:

  • Request structured user input (forms with schema validation)
  • Ask the client to perform an external action (e.g. open a payment URL)
  • Pause execution until the elicitation is accepted, rejected, or completed

Typical use cases:

  • Collecting contact or configuration data
  • User confirmation steps
  • Payments or OAuth-style redirects

To use elicitation, inject Context into your tool handler and call the elicit() method with either form of URL elicit request params.

Defining a Form Elicitation

Forms use a JSON schema to define and validate structured input.

#[json_schema(de)]
struct Contact {
name: String,
email: String,
age: u32,
}

With #[json_schema] attribute macro you can control the serialization/deserialization performed by serde for your struct:

  • all - Applies also derive(serde::Serialize, serde::Deserialize).
  • serde - Applies also derive(serde::Serialize, serde::Deserialize).
  • ser - Applies also derive(serde::Serialize).
  • de - Applies also derive(serde::Deserialize).

Creating and Sending a Form Request

To create elicit request form params you need to use the ElicitRequestParams::form() method with the following with_contract() that specifies the expected JSON schema.

#[tool]
async fn generate_business_card(mut ctx: Context) -> Result<String, Error> {
let params = ElicitRequestParams::form(
"Please provide your contact information"
)
.with_schema::<Contact>();

ctx.elicit(params.into())
.await?
.map(format_contact)
}

fn format_contact(c: Contact) -> String {
format!("Name: {}, Age: {}, email: {}", c.name, c.age, c.email)
}

Execution flow:

  1. Server sends a form elicitation request
  2. Client receives and validates the data
  3. Tool resumes with the validated payload
  4. The result is mapped to the tool output

Defining a URL Elicitation

URL elicitations are used when the user must perform an external action. You can create the ElicitRequestUrlParams by leveraging the ElicitRequestParams::url() method.

#[tool]
async fn pay_a_bill(mut ctx: Context) -> Result<&'static str, Error> {
let params = ElicitRequestParams::url(
"https://www.paypal.com/us/webapps/mpp/paypal-payment",
"Please pay your bill using PayPal"
);

let elicitation_id = params.id.clone();

ctx.elicit(params.into()).await?;

// Send the `notifications/elicitation/complete`
ctx.complete_elicitation(elicitation_id).await?;

Ok("Payment successful")
}

You may also send a notifications/elicitation/complete notification when an out-of-band interaction is completed. This allows clients to react programmatically if appropriate.

примечание
  • The server controls when the elicitation is considered completed
  • The client only confirms acceptance
  • Useful for payments, SSO, external confirmations

Learn By Example

A complete working example is available here.