guide23 min read1mo ago

MCP Elicitation: The Complete Guide to Interactive MCP Servers (2026)

**MCP elicitation is a March 2026 addition to the Model Context Protocol that lets servers request structured input from users mid-task** — forms, approval dialogs, configuration wizards, and browser-based authentication flows. Instead of the AI guessing what a user wants, the server pauses executio

MCP Elicitation: The Complete Guide to Interactive MCP Servers (2026)
mcpelicitationinteractive servershuman-in-the-loopmodel context protocoldeveloper tools

MCP Elicitation: The Complete Guide to Interactive MCP Servers (2026)

TL;DR

MCP elicitation is a March 2026 addition to the Model Context Protocol that lets servers request structured input from users mid-task — forms, approval dialogs, configuration wizards, and browser-based authentication flows. Instead of the AI guessing what a user wants, the server pauses execution, asks a specific question through a typed form field, and waits for a real answer.

This is the human-in-the-loop pattern the MCP ecosystem was missing. Before elicitation, servers had two options: assume defaults or fail. Now they can ask.

Three things that make elicitation worth learning right now:

  1. Deployment approvals — Servers can require explicit human sign-off before executing destructive operations like database migrations or production deploys
  2. Structured data collection — Instead of parsing natural language, servers collect typed inputs (strings, numbers, booleans, enums) through validated form fields
  3. Multi-step configuration — Complex server setups that previously required editing JSON config files can now walk users through interactive wizards

Read on for the full technical deep-dive, three buildable examples, and a comparison with prompts and hooks.


Table of Contents

  1. What Is MCP Elicitation?
  2. Key Features
  3. How Elicitation Works
  4. Build an Interactive MCP Server
  5. Elicitation vs Prompts vs Hooks
  6. Best Use Cases for MCP Elicitation
  7. Pros and Cons
  8. Frequently Asked Questions

What Is MCP Elicitation?

MCP elicitation is a capability introduced in the March 2026 revision of the Model Context Protocol specification that allows MCP servers to request structured input from users during tool execution. It is the protocol's answer to a persistent gap: what happens when a server needs information it cannot infer, and getting it wrong has real consequences?

Before elicitation, MCP interactions were strictly one-directional from the user's perspective. A user (or AI client) would call a tool, the server would execute it, and results came back. If the server needed a database password, a deployment target, or confirmation before deleting records, it had no standard mechanism to ask. Developers worked around this with hardcoded configuration files, environment variables, or awkward multi-step tool chains where one tool gathered input and another executed the action.

Elicitation formalizes what developers were already doing informally. It adds a elicitation/create method to the MCP protocol that servers can invoke during any tool execution. The client receives the elicitation request, renders a UI appropriate to the input type (a text field, a dropdown, a confirmation dialog), collects the user's response, and returns it to the server. The server then continues execution with the provided data.

The design philosophy borrows from established patterns in CI/CD systems (manual approval gates), infrastructure-as-code tools (Terraform's interactive apply confirmation), and web application forms. The key difference is that MCP elicitation operates within the context of an AI-assisted workflow. The AI agent handles the routine steps; the human intervenes only when their judgment or credentials are genuinely required.

This matters for security-sensitive workflows where autonomous execution is a liability. A deployment server that can push to production without asking is a risk vector. A deployment server that always pauses for human approval before the final step is a safety net. Elicitation provides the protocol-level mechanism to build that safety net into any MCP server.

The feature shipped alongside updates to the TypeScript and Python MCP SDKs, with first-party support in Claude Desktop, Claude Code, and several third-party clients. Adoption is early but accelerating — the community MCP server registry already shows dozens of servers advertising elicitation support as of late March 2026.


Key Features

1. ElicitationResult Type

Every elicitation request returns a typed ElicitationResult object. This is not a freeform string — it is a structured response with three possible actions: accept (user provided input), decline (user refused to answer), and dismiss (user closed the dialog without responding). The server code handles all three cases explicitly.

The ElicitationResult includes a content field that contains the user's input, typed according to the schema provided in the request. A number field returns a number. A boolean returns a boolean. An enum returns one of the declared values. This eliminates the parsing ambiguity that plagues natural-language input collection — the server never has to guess whether "yes" means true or is part of a sentence.

The typing system also means server developers can write validation logic with confidence. A function that expects an integer between 1 and 100 receives an integer between 1 and 100, or an explicit decline signal. No edge cases from unexpected string inputs.

2. Form Field Types

Elicitation supports a range of typed form fields designed to cover common input scenarios without requiring custom UI rendering on the client side:

  • String — Free-text input with optional minLength, maxLength, and pattern (regex) constraints
  • Number — Numeric input with optional minimum, maximum, and multipleOf constraints
  • Boolean — Yes/no toggle, rendered as a checkbox or switch
  • Enum — Dropdown or radio group from a predefined list of string values
  • Secret — Masked input for passwords, API keys, and tokens (never logged or echoed)

Each field type maps to a familiar HTML form element on the client side. The server declares the schema; the client handles rendering. This separation means the same elicitation request renders as a native dialog in Claude Desktop, a terminal prompt in Claude Code, and an HTML form in a web-based client — all without the server knowing or caring which client is running.

3. Browser URL Redirects

For authentication flows that require OAuth consent screens, SAML logins, or any browser-based interaction, elicitation supports a url redirect type. The server provides a URL; the client opens it in the user's default browser. The user completes the authentication flow in the browser, the callback returns to the client, and the elicitation resolves with the resulting token or session data.

This eliminates the most common pain point in MCP server authentication: credential management. Instead of asking users to manually copy-paste OAuth tokens into configuration files, the server initiates a standard browser-based auth flow. The user clicks "Authorize," the browser handles the redirect, and the server receives the token through the protocol. No clipboard, no config editing, no token expiration surprises.

Browser redirects also support custom callback URLs, enabling servers to implement complex multi-provider authentication (e.g., "Log in with GitHub, then authorize access to your Vercel team") as sequential elicitation steps.

4. Conditional Logic

Elicitation requests can be chained with conditional logic — the server evaluates the response to one elicitation before deciding whether to issue another. This is not a protocol-level feature but a natural consequence of the synchronous request-response pattern.

A practical example: a deployment server asks "Which environment?" (enum: staging, production). If the user selects "production," the server issues a second elicitation: "Production deploy requires approval. Type the deployment ticket number to confirm." If the user selects "staging," the server skips the confirmation and proceeds directly.

This branching pattern enables sophisticated workflows without complex upfront configuration. The server adapts its questions based on earlier answers, exactly like a well-designed web form with conditional sections. Developers building custom skills can use conditional elicitation to create context-aware tools that only ask what they need to ask.

5. Multi-Step Dialogs

Complex workflows often require more than a single input. MCP elicitation supports multi-step dialog sequences where the server issues several elicitation requests in series, building up a complete configuration or approval chain one step at a time.

Each step is an independent elicitation request. The server maintains state between steps using its own internal logic — the protocol does not prescribe a session or wizard abstraction. This gives server developers full control over the flow: they can branch, loop back, skip steps, or abort the sequence based on any combination of prior responses.

Multi-step dialogs are particularly effective for initial server configuration. Instead of requiring users to write a JSON configuration file with database URLs, API keys, and preference flags, the server walks the user through each setting with appropriate field types, validation, and help text. The result is a guided setup experience that feels like a modern software installer.

The tradeoff is user patience. Each elicitation step requires a round-trip to the user, and excessive steps will frustrate users who expect AI-assisted tools to reduce interruptions, not create them. The protocol documentation explicitly recommends limiting multi-step sequences to three to five steps for routine operations.

6. Timeout Handling

Every elicitation request accepts an optional timeout parameter specified in milliseconds. If the user does not respond within the timeout window, the elicitation resolves with a dismiss action, and the server can fall back to a default behavior or abort the operation.

Timeouts prevent a common failure mode in human-in-the-loop systems: indefinite blocking. Without timeouts, a server waiting for user approval could hold resources, database connections, or API rate-limit slots indefinitely. A 60-second timeout on a deployment approval means the deployment either proceeds with human sign-off or cancels cleanly — it never hangs.

Server developers can also implement escalating timeout strategies. A low-priority notification might use a 120-second timeout with a silent fallback. A high-stakes production deployment might use a 30-second timeout that triggers an explicit abort and logs the timeout event for audit purposes.

7. Validation

Form field validation happens at two levels: client-side (based on the JSON Schema constraints in the elicitation request) and server-side (based on custom logic after receiving the response).

Client-side validation is immediate. If a server requests a number with minimum: 1 and maximum: 100, the client prevents the user from submitting a value outside that range. String patterns, required fields, and enum constraints are all enforced before the response leaves the client.

Server-side validation handles business logic that cannot be expressed in JSON Schema. A server might validate that a provided database connection string actually connects, that an API key has the required scopes, or that a deployment target exists in the infrastructure. If server-side validation fails, the server can issue a new elicitation request with an error message, effectively asking the user to try again.

This two-layer validation model mirrors web application form design. The client catches obvious errors instantly; the server catches domain-specific errors after submission. Users get fast feedback on typos and format issues, then accurate feedback on semantic issues.

8. Security Model

Elicitation inherits the MCP protocol's existing security model and adds its own constraints. The critical rule: elicitation requests are always mediated by the client. A server cannot display UI directly to the user or access the user's input outside the elicitation response. The client is the trust boundary.

This means the client can:

  • Filter elicitation requests. Enterprise clients can block servers from requesting certain input types (e.g., no secret fields from untrusted servers).
  • Log all elicitation activity. Every request and response passes through the client, creating a complete audit trail.
  • Require user consent. Clients can prompt users before forwarding elicitation requests from new or untrusted servers, similar to browser permission dialogs.
  • Redact sensitive inputs. Secret-type fields can be redacted in client logs while still being delivered to the server.

The security model also addresses a subtle risk: social engineering through elicitation. A malicious server could use elicitation to impersonate a login dialog and harvest credentials. The mitigation is client-level UI that clearly identifies which server is requesting input and what permissions it holds — similar to how browsers display the domain name in the address bar during authentication flows.


How Elicitation Works

Understanding the technical flow of MCP elicitation requires walking through the full request-response cycle, from the moment a tool needs user input to the moment execution resumes with that input.

The Elicitation Sequence

The sequence involves three actors: the MCP client (Claude Desktop, Claude Code, or a custom client), the MCP server (the tool provider), and the user (the human at the keyboard).

Step 1: Tool invocation. The AI agent calls a tool on the MCP server. For example, deploy_to_production({ service: "api-gateway", version: "2.4.1" }).

Step 2: Server determines input is needed. The server's tool handler evaluates the request and decides that human approval is required before proceeding. This decision is made in server-side code — the protocol does not prescribe when to elicit.

Step 3: Server sends elicitation request. The server calls elicitation/create on the client, specifying the message to display, the input schema (field type, constraints, default value), and an optional timeout. The request is a JSON-RPC message over the existing MCP transport (stdio or HTTP/SSE).

{
  "method": "elicitation/create",
  "params": {
    "message": "Deploy api-gateway v2.4.1 to production?",
    "requestedSchema": {
      "type": "object",
      "properties": {
        "approved": {
          "type": "boolean",
          "description": "Approve this production deployment",
          "default": false
        },
        "reason": {
          "type": "string",
          "description": "Deployment reason (for audit log)",
          "minLength": 10
        }
      },
      "required": ["approved", "reason"]
    },
    "timeout": 60000
  }
}

Step 4: Client renders the UI. The client receives the elicitation request and renders an appropriate interface. In Claude Desktop, this appears as a modal dialog with a checkbox and a text field. In Claude Code (terminal), it appears as a series of prompts. The client does not need special instructions for rendering — it interprets the JSON Schema and maps field types to native UI elements.

Step 5: User responds. The user fills in the form fields and submits, or declines/dismisses the dialog. The client packages the response into an ElicitationResult and returns it to the server.

{
  "action": "accept",
  "content": {
    "approved": true,
    "reason": "Scheduled maintenance window — release 2.4.1 includes security patches"
  }
}

Step 6: Server resumes execution. The server receives the ElicitationResult, checks the action (accept, decline, or dismiss), and continues the tool execution accordingly. If approved, it proceeds with the deployment. If declined or dismissed, it aborts and returns an appropriate message to the AI client.

Step 7: Tool returns result. The tool execution completes and returns its result to the AI client, which presents it to the user. The full cycle — tool call, elicitation, user input, resumption, result — appears seamless from the user's perspective.

Capability Negotiation

Elicitation is an optional capability. During the MCP handshake (the initialize method), the client declares whether it supports elicitation by including "elicitation": {} in its capabilities field. If the client does not advertise elicitation support, the server must not send elicitation requests — it should fall back to default values or return an error explaining that user input is required but not available.

This capability negotiation means servers can be written to work with and without elicitation. A deployment server might require elicitation for production deploys (fail if not supported) but allow staging deploys without it (use defaults). This progressive enhancement pattern keeps servers broadly compatible while enabling richer interactions when the client supports them.

State Management

The MCP protocol is stateless between tool calls, but elicitation introduces an implicit state within a single tool execution. Between sending the elicitation request and receiving the response, the server is suspended — waiting for the user. Server developers need to manage this state carefully:

  • Database connections should use connection pools with timeouts, not held connections.
  • API rate limits should be checked before the elicitation, not after (to avoid holding a slot while waiting for the user).
  • Temporary resources (files, locks) should have cleanup logic that handles both successful completion and timeout/dismissal.

The protocol handles the transport-level suspension transparently. The server's tool handler function simply awaits the elicitation call, and the runtime manages the underlying connection lifecycle.


Build an Interactive MCP Server

The following three examples demonstrate progressively complex elicitation patterns. Each example is a complete, runnable MCP server using the TypeScript SDK.

Prerequisites

Install the MCP TypeScript SDK (version 1.12.0 or later, which includes elicitation support):

npm install @modelcontextprotocol/sdk@latest

Example 1: Simple Form Input

This server exposes a create_ticket tool that collects ticket details through an elicitation form before creating the ticket.

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
  name: "ticket-server",
  version: "1.0.0",
  capabilities: { elicitation: {} },
});

server.tool(
  "create_ticket",
  "Create a support ticket with user-provided details",
  { project: z.string().describe("Target project identifier") },
  async ({ project }, { sendElicitationRequest }) => {
    // Request ticket details from the user
    const result = await sendElicitationRequest({
      message: `Create a new ticket in project "${project}". Fill in the details:`,
      requestedSchema: {
        type: "object",
        properties: {
          title: {
            type: "string",
            description: "Ticket title",
            minLength: 5,
            maxLength: 200,
          },
          priority: {
            type: "string",
            description: "Ticket priority",
            enum: ["low", "medium", "high", "critical"],
          },
          description: {
            type: "string",
            description: "Detailed description of the issue",
            minLength: 20,
          },
        },
        required: ["title", "priority", "description"],
      },
    });

    if (result.action !== "accept") {
      return {
        content: [{ type: "text", text: "Ticket creation cancelled by user." }],
      };
    }

    const { title, priority, description } = result.content;

    // In production, this would call a ticket API
    const ticketId = `${project}-${Date.now()}`;

    return {
      content: [
        {
          type: "text",
          text: `Ticket created successfully.\n\nID: ${ticketId}\nTitle: ${title}\nPriority: ${priority}\nDescription: ${description}`,
        },
      ],
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

This example covers the fundamental pattern: declare a schema, send the request, handle accept/decline/dismiss, use the typed response. The form fields map directly to the properties in requestedSchema, and the client renders them with appropriate input widgets.

Example 2: Approval Workflow

This server implements a deployment pipeline with a mandatory human approval gate. The tool performs pre-flight checks, then pauses for approval before executing.

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
  name: "deploy-server",
  version: "1.0.0",
  capabilities: { elicitation: {} },
});

server.tool(
  "deploy_service",
  "Deploy a service to the specified environment with approval gate",
  {
    service: z.string().describe("Service name"),
    version: z.string().describe("Version tag to deploy"),
    environment: z.enum(["staging", "production"]).describe("Target environment"),
  },
  async ({ service, version, environment }, { sendElicitationRequest }) => {
    // Run pre-flight checks
    const checks = {
      testsPass: true,
      imageExists: true,
      configValid: true,
      healthCheckUrl: `https://${environment}.example.com/${service}/health`,
    };

    const checksReport = Object.entries(checks)
      .map(([k, v]) => `  ${typeof v === "boolean" ? (v ? "PASS" : "FAIL") : v}: ${k}`)
      .join("\n");

    // Skip approval for staging
    if (environment === "staging") {
      return {
        content: [
          {
            type: "text",
            text: `Deployed ${service}@${version} to staging.\n\nPre-flight:\n${checksReport}`,
          },
        ],
      };
    }

    // Production requires explicit approval
    const approval = await sendElicitationRequest({
      message: [
        `PRODUCTION DEPLOYMENT APPROVAL REQUIRED`,
        ``,
        `Service: ${service}`,
        `Version: ${version}`,
        `Environment: ${environment}`,
        ``,
        `Pre-flight checks:`,
        checksReport,
        ``,
        `Do you approve this deployment?`,
      ].join("\n"),
      requestedSchema: {
        type: "object",
        properties: {
          approved: {
            type: "boolean",
            description: "I approve this production deployment",
          },
          ticket: {
            type: "string",
            description: "JIRA ticket number (required for audit)",
            pattern: "^[A-Z]+-[0-9]+$",
          },
        },
        required: ["approved", "ticket"],
      },
      timeout: 120000, // 2 minutes to approve
    });

    if (approval.action !== "accept" || !approval.content.approved) {
      return {
        content: [
          {
            type: "text",
            text: `Production deployment of ${service}@${version} was NOT approved. No changes made.`,
          },
        ],
      };
    }

    // Execute deployment
    const deploymentId = `deploy-${Date.now()}`;

    return {
      content: [
        {
          type: "text",
          text: [
            `Production deployment APPROVED and EXECUTED.`,
            ``,
            `Deployment ID: ${deploymentId}`,
            `Service: ${service}@${version}`,
            `Approved by: user (ticket ${approval.content.ticket})`,
            `Timestamp: ${new Date().toISOString()}`,
          ].join("\n"),
        },
      ],
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

The key pattern here is conditional elicitation — the approval dialog only appears for production deployments. Staging deployments execute immediately. This demonstrates how servers can use elicitation surgically, only interrupting the user when the stakes justify it.

The pattern constraint on the ticket field (^[A-Z]+-[0-9]+$) ensures the user provides a valid JIRA-format ticket number. The client validates this before submission, preventing invalid inputs from reaching the server.

Example 3: Configuration Wizard

This server implements a multi-step setup wizard that configures a database connection through sequential elicitation steps.

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
  name: "db-config-server",
  version: "1.0.0",
  capabilities: { elicitation: {} },
});

server.tool(
  "configure_database",
  "Interactive database connection setup wizard",
  {},
  async (_args, { sendElicitationRequest }) => {
    // Step 1: Database type
    const step1 = await sendElicitationRequest({
      message: "Database Configuration — Step 1 of 3\n\nSelect your database type:",
      requestedSchema: {
        type: "object",
        properties: {
          dbType: {
            type: "string",
            description: "Database engine",
            enum: ["postgresql", "mysql", "sqlite", "mongodb"],
          },
        },
        required: ["dbType"],
      },
    });

    if (step1.action !== "accept") {
      return {
        content: [{ type: "text", text: "Configuration wizard cancelled." }],
      };
    }

    const { dbType } = step1.content;

    // Step 2: Connection details (varies by database type)
    let step2Schema: Record<string, unknown>;

    if (dbType === "sqlite") {
      step2Schema = {
        type: "object",
        properties: {
          filePath: {
            type: "string",
            description: "Path to SQLite database file",
            minLength: 1,
          },
        },
        required: ["filePath"],
      };
    } else {
      step2Schema = {
        type: "object",
        properties: {
          host: {
            type: "string",
            description: "Database host",
            default: "localhost",
          },
          port: {
            type: "number",
            description: "Database port",
            default: dbType === "postgresql" ? 5432 : dbType === "mysql" ? 3306 : 27017,
          },
          database: {
            type: "string",
            description: "Database name",
            minLength: 1,
          },
          username: {
            type: "string",
            description: "Database username",
          },
          password: {
            type: "string",
            description: "Database password (stored securely)",
            format: "secret",
          },
        },
        required: ["host", "port", "database", "username", "password"],
      };
    }

    const step2 = await sendElicitationRequest({
      message: `Database Configuration — Step 2 of 3\n\nEnter ${dbType} connection details:`,
      requestedSchema: step2Schema,
    });

    if (step2.action !== "accept") {
      return {
        content: [{ type: "text", text: "Configuration wizard cancelled at step 2." }],
      };
    }

    // Step 3: Options
    const step3 = await sendElicitationRequest({
      message: "Database Configuration — Step 3 of 3\n\nConfigure connection options:",
      requestedSchema: {
        type: "object",
        properties: {
          ssl: {
            type: "boolean",
            description: "Enable SSL/TLS connection",
            default: true,
          },
          poolSize: {
            type: "number",
            description: "Connection pool size",
            minimum: 1,
            maximum: 50,
            default: 10,
          },
          readOnly: {
            type: "boolean",
            description: "Read-only mode (prevents write operations)",
            default: false,
          },
        },
        required: ["ssl", "poolSize"],
      },
    });

    if (step3.action !== "accept") {
      return {
        content: [{ type: "text", text: "Configuration wizard cancelled at step 3." }],
      };
    }

    // Build final configuration
    const config = {
      type: dbType,
      connection: step2.content,
      options: step3.content,
    };

    return {
      content: [
        {
          type: "text",
          text: [
            "Database configuration complete.",
            "",
            "```json",
            JSON.stringify(config, null, 2),
            "```",
            "",
            `Connection type: ${dbType}`,
            `SSL: ${step3.content.ssl ? "enabled" : "disabled"}`,
            `Pool size: ${step3.content.poolSize}`,
            `Read-only: ${step3.content.readOnly ? "yes" : "no"}`,
          ].join("\n"),
        },
      ],
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

This wizard demonstrates three elicitation patterns in one server:

  1. Enum selection — Step 1 uses a constrained enum for database type selection
  2. Conditional schema — Step 2 changes its form fields based on the Step 1 answer (SQLite gets a file path; others get host/port/credentials)
  3. Typed defaults — Step 3 provides sensible defaults for connection options, reducing user effort

The three-step limit follows the protocol's recommended maximum for routine configuration wizards. Each step collects a logically grouped set of inputs, and every step handles cancellation gracefully.


Elicitation vs Prompts vs Hooks

MCP now has three distinct mechanisms for human-AI interaction during tool execution. Each serves a different purpose, and choosing the wrong one creates friction or security gaps. Here is how they compare:

DimensionElicitationPromptsHooks
---------------------------------------
DirectionServer asks user mid-executionUser sends input to AI before executionSystem runs code at lifecycle events
TimingDuring tool execution (synchronous pause)Before tool invocationBefore or after specific events
Input typeTyped form fields (string, number, boolean, enum, secret)Natural language textShell command output or exit code
Who initiatesServer codeUser or AI clientConfiguration (automatic)
Use caseApprovals, configuration, data collectionTask instructions, context settingAutomation, validation, side effects
Blocks executionYes — server waits for responseNo — prompt is consumed before execution startsYes — hooks can block or allow
Requires client supportYes — elicitation capability must be advertisedYes — all clients support promptsDepends on client (Claude Code supports hooks)
Structured dataYes — JSON Schema validatedNo — freeform textNo — stdout/stderr text and exit codes

When to Use Each

Use elicitation when:

  • The server needs specific, typed data that cannot be guessed (API keys, configuration values, approval decisions)
  • The operation is destructive or irreversible and requires explicit human sign-off
  • The input must be validated against a schema before the server processes it

Use prompts when:

  • The AI needs context or instructions to formulate a better tool call
  • The input is conversational and does not map to specific fields
  • The interaction happens before tool execution, not during it

Use hooks when:

  • The response should be automated (run a linter, send a notification, log an event)
  • The logic is the same every time and does not require human judgment
  • The integration is with external systems (CI/CD, Slack, monitoring)

The three mechanisms are complementary. A well-designed MCP workflow might use a hook to auto-format code after every edit, a prompt to give the AI project context at session start, and elicitation to request human approval before a production deployment. Mixing them is not only acceptable — it is the intended design pattern.


Best Use Cases for MCP Elicitation

Deployment Approvals

The highest-impact use case for elicitation is deployment gating. MCP servers that manage infrastructure — Kubernetes clusters, cloud functions, database migrations, CDN purges — can use elicitation to implement mandatory human approval before executing destructive operations.

The pattern is straightforward: the server performs pre-flight checks (tests passing, image built, configuration valid), presents the results to the user through an elicitation dialog, and waits for explicit boolean approval before proceeding. If the user declines or the timeout expires, the deployment aborts cleanly.

This replaces ad-hoc solutions like "type CONFIRM to continue" in CLI tools with a protocol-level mechanism that clients can render, log, and audit consistently. Enterprise teams get a standardized approval trail without building custom tooling.

Data Validation and Enrichment

Servers that process data — ETL pipelines, data transformation tools, import/export utilities — frequently encounter ambiguous inputs that require human judgment. A CSV import server might find a column that could be a date or a string. Instead of guessing, it elicits: "Column 'created' contains values like '03/22/2026'. Interpret as: (a) date MM/DD/YYYY, (b) date DD/MM/YYYY, (c) plain text?"

This pattern extends to any scenario where automated parsing is unreliable: currency format disambiguation, name/address splitting, encoding detection, and data quality decisions ("Row 47 has a negative quantity. Keep, zero out, or skip?").

Platforms like Sentimyne demonstrate why structured user input matters in review and analysis workflows — the quality of AI-generated analysis depends directly on the precision of the context it receives. Elicitation provides the mechanism to collect that precise context at the moment it is needed.

Dynamic Configuration

MCP servers often require configuration that varies between users, projects, or environments. Traditional approaches (JSON config files, environment variables, CLI flags) work but create friction — especially for servers that non-technical users interact with through AI clients.

Elicitation enables servers to configure themselves interactively on first use. A reporting server asks which database to connect to, which metrics to track, and which format to output. A notification server asks which Slack channel to post to and what severity threshold to use. These configuration values can be cached locally after the first elicitation, making subsequent interactions frictionless.

User Preferences

AI-assisted tools that generate content, format code, or produce reports benefit from user preference collection. Instead of producing output in a default style and hoping it matches expectations, the server asks upfront: "Output format: Markdown, HTML, or PDF? Tone: formal or casual? Include code examples: yes or no?"

This is particularly valuable for content and review workflows where output quality depends on subjective preferences that no amount of AI training can reliably predict. One user's "concise" is another user's "too brief." Elicitation makes the preference explicit rather than implicit.

Credential Collection

Servers that integrate with authenticated APIs need credentials. Elicitation's secret field type provides a secure mechanism for collecting API keys, tokens, and passwords during tool execution. The input is masked in the client UI, can be redacted from client-side logs, and is delivered to the server through the encrypted MCP transport.

This is safer than the alternatives: storing credentials in plaintext config files, passing them as environment variables visible to all processes, or asking the AI to relay them through the conversation (where they appear in chat logs and model context windows).

Multi-Tenant Routing

Servers that operate across multiple accounts, workspaces, or tenants can use elicitation to disambiguate context. "You have access to 3 GitHub organizations. Which one should this operation target?" This is cleaner than requiring the organization name as a tool parameter (which the AI might guess incorrectly) and safer than defaulting to the first available option.


Pros and Cons

Pros

  • Provides a standardized, protocol-level mechanism for human-in-the-loop interactions in MCP workflows
  • Eliminates ambiguity by collecting typed, schema-validated inputs instead of parsing natural language
  • Enables security-critical approval gates for destructive operations without custom tooling
  • Works across all MCP clients that advertise elicitation support — one server implementation, multiple UIs
  • Secret field type handles credentials more securely than config files or environment variables
  • Conditional and multi-step patterns support complex workflows without sacrificing simplicity for basic use cases
  • Timeout handling prevents indefinite blocking, keeping automated workflows responsive

Cons

  • Client support is still uneven — not all MCP clients have implemented elicitation as of March 2026
  • Excessive elicitation creates a "dialog fatigue" experience that defeats the purpose of AI-assisted automation
  • Multi-step wizards with more than three to five steps frustrate users and should be avoided
  • The security model depends entirely on client-side enforcement — a compromised client undermines all protections
  • No built-in state persistence between elicitation steps; server developers must manage state manually
  • Browser URL redirects add complexity for OAuth flows and require careful callback URL handling
  • Servers that require elicitation become unusable in fully autonomous (no-human) pipelines

Frequently Asked Questions

What is MCP elicitation?

MCP elicitation is a feature in the Model Context Protocol (introduced March 2026) that allows MCP servers to request structured user input during tool execution. Instead of guessing or using hardcoded defaults, a server can pause, ask the user a specific question through a typed form field, and resume execution with the user's answer. It supports text, numbers, booleans, dropdowns, and masked password fields.

Does MCP elicitation work in Claude Code?

Yes. Claude Code supports MCP elicitation as of March 2026. Elicitation requests render as terminal prompts — text fields appear as standard input prompts, booleans as y/n questions, and enums as numbered selection lists. Claude Desktop also supports elicitation with native dialog boxes. Third-party client support varies.

How is elicitation different from MCP prompts?

Prompts are user-to-server templates that provide context before tool execution. Elicitation is server-to-user requests that collect input during tool execution. Prompts flow in one direction (user provides context); elicitation flows in the other (server asks for data). Prompts use natural language; elicitation uses typed form fields with JSON Schema validation.

Can elicitation be used for OAuth authentication?

Yes. Elicitation supports a URL redirect type that opens a browser window for the user to complete an OAuth consent flow. The server provides the authorization URL, the client opens it in the default browser, and the callback returns the token to the server through the elicitation response. This eliminates manual token copy-paste workflows.

Is elicitation secure for collecting passwords and API keys?

Elicitation includes a secret field type that masks input in the client UI and can be redacted from client-side logs. The input is transmitted through the existing MCP transport (stdio or HTTP/SSE with TLS). While this is more secure than plaintext config files or chat messages, the security depends on the client's implementation. Enterprise deployments should verify that their MCP client properly handles secret-type fields.

What happens if a user does not respond to an elicitation request?

The server can specify a timeout in milliseconds. If the user does not respond within the timeout window, the elicitation resolves with a dismiss action. The server code handles this case explicitly — typically by aborting the operation or falling back to a safe default. Without a timeout, the server waits indefinitely, which is why the protocol documentation recommends always setting a timeout for production servers.

Can I use elicitation in fully automated pipelines?

Not directly. Elicitation requires a human to respond, which makes it incompatible with fully autonomous pipelines. However, servers can check for elicitation client support during capability negotiation and fall back to default values or environment variables when elicitation is not available. This lets the same server work interactively (with humans) and autonomously (in CI/CD pipelines).

How many elicitation steps should a workflow have?

The MCP protocol documentation recommends limiting multi-step sequences to three to five steps for routine operations. Each step requires a round-trip to the user, and excessive steps create dialog fatigue. If a workflow requires more than five inputs, consider collecting them in a single form with multiple fields rather than sequential single-field dialogs.



Back to Blog

Frequently Asked Questions

What is MCP elicitation?
MCP elicitation is a feature in the Model Context Protocol (introduced March 2026) that allows MCP servers to request structured user input during tool execution. Instead of guessing or using hardcoded defaults, a server can pause, ask the user a specific question through a typed form field, and resume execution with the user's answer. It supports text, numbers, booleans, dropdowns, and masked password fields.
Does MCP elicitation work in Claude Code?
Yes. Claude Code supports MCP elicitation as of March 2026. Elicitation requests render as terminal prompts — text fields appear as standard input prompts, booleans as y/n questions, and enums as numbered selection lists. Claude Desktop also supports elicitation with native dialog boxes. Third-party client support varies.
How is elicitation different from MCP prompts?
Prompts are user-to-server templates that provide context before tool execution. Elicitation is server-to-user requests that collect input during tool execution. Prompts flow in one direction (user provides context); elicitation flows in the other (server asks for data). Prompts use natural language; elicitation uses typed form fields with JSON Schema validation.
Can elicitation be used for OAuth authentication?
Yes. Elicitation supports a URL redirect type that opens a browser window for the user to complete an OAuth consent flow. The server provides the authorization URL, the client opens it in the default browser, and the callback returns the token to the server through the elicitation response. This eliminates manual token copy-paste workflows.
Is elicitation secure for collecting passwords and API keys?
Elicitation includes a secret field type that masks input in the client UI and can be redacted from client-side logs. The input is transmitted through the existing MCP transport (stdio or HTTP/SSE with TLS). While this is more secure than plaintext config files or chat messages, the security depends on the client's implementation. Enterprise deployments should verify that their MCP client properly handles secret-type fields.
What happens if a user does not respond to an elicitation request?
The server can specify a timeout in milliseconds. If the user does not respond within the timeout window, the elicitation resolves with a dismiss action. The server code handles this case explicitly — typically by aborting the operation or falling back to a safe default. Without a timeout, the server waits indefinitely, which is why the protocol documentation recommends always setting a timeout for production servers.
Can I use elicitation in fully automated pipelines?
Not directly. Elicitation requires a human to respond, which makes it incompatible with fully autonomous pipelines. However, servers can check for elicitation client support during capability negotiation and fall back to default values or environment variables when elicitation is not available. This lets the same server work interactively (with humans) and autonomously (in CI/CD pipelines).
How many elicitation steps should a workflow have?
The MCP protocol documentation recommends limiting multi-step sequences to three to five steps for routine operations. Each step requires a round-trip to the user, and excessive steps create dialog fatigue. If a workflow requires more than five inputs, consider collecting them in a single form with multiple fields rather than sequential single-field dialogs.

Stay in the Loop

Join 1,000+ developers. Get the best new Skills & MCPs weekly.

No spam. Unsubscribe anytime.