Input Required
Purpose and Scope
An input_required result is the server-side pattern for pausing a tool, prompt, or resource operation until the connected client can gather more input from the user. Instead of sending an out-of-band request and waiting inside the handler, the handler returns a structured waiting result. The client answers the embedded requests, retries the original operation, and the handler runs again with the submitted responses available on the request context. This keeps the operation replayable and makes the waiting state explicit in the result rather than hidden in server process memory.
Sources: docs/servers/input-required.md
Use this pattern when the server cannot safely complete the requested work from the original arguments alone. A deployment tool might need an operator confirmation, a release tool might need a tag approval, and a resource or prompt may need additional selections before returning useful content. The important design choice is that the server asks for input by returning a result, not by pushing a live question on the current call path. That makes input_required especially important for protocol revision 2026-07-28, where earlier push helpers such as ctx.mcpReq.elicitInput and ctx.mcpReq.requestSampling are not the right model for these multi-round requests.
Sources: docs/servers/input-required.md, docs/servers/elicitation.md
Relevant Source Files
docs/servers/input-required.md- Primary how-to for returninginput_required, readinginputResponses, validating accepted content, carrying request state, and understanding client capability checks.docs/servers/elicitation.md- Describes the 2025-eractx.mcpReq.elicitInputflow and explains why 2026-07-28 connections should return an input-required request instead.docs/servers/completion.md- Provides adjacent guidance for server-side user-assistance flows, especially argument completion that happens before or around prompt and resource operations.docs/servers/errors.md- Defines how recoverable tool errors differ from protocol errors, which matters when an input-required flow is declined, cancelled, malformed, or unsupported.docs/servers/logging-progress-cancellation.md- Documents request context helpers such as progress, logging, and cancellation that may appear in the same long-running handlers that need user input.docs/servers/notifications.md- Covers server notifications and 2026-era stream behavior, useful context when separating one-way updates from retry-based input-required calls.
Core Primitives
The central helper is inputRequired(spec). A handler returns that value when it needs either one or more embedded input requests, a requestState payload, or both. The documented contract is intentionally strict: calling inputRequired(spec) without at least one of inputRequests or requestState throws a TypeError. Each embedded request is checked against the client capabilities declared during connection setup, and a missing capability rejects the call with error code -32021 before the request reaches the wire. This early rejection prevents handlers from assuming a user interface exists when the client did not advertise one.
Sources: docs/servers/input-required.md
The other core primitive is ctx.mcpReq.inputResponses, which is supplied by the client on the retried call. The server must treat these responses as untrusted because they originate outside the handler and may represent accepted, declined, cancelled, absent, or malformed user input. The guide recommends using acceptedContent with a schema argument so accepted values are validated and typed before normal business logic reads them. When the handler needs to distinguish between acceptance and refusal, inputResponse exposes the response kind and action, letting the server return a deliberate cancellation or refusal message rather than silently re-prompting forever.
Sources: docs/servers/input-required.md, docs/servers/errors.md
Execution Flow
A typical flow has two handler entries. On the first entry, the handler inspects ctx.mcpReq.inputResponses and finds no accepted answer for the request key it needs. It then returns inputRequired with an inputRequests map. In the deploy example, the map contains a confirm request created with inputRequired.elicit, a message asking whether to deploy to the selected environment, and a flat JSON Schema requiring a boolean confirmation. The client receives a result whose result type indicates input is required, presents the request through its UI or request handler, and retries the original call with the answer attached.
Sources: docs/servers/input-required.md
On the second entry, the same handler should be able to complete without relying on local mutable state. It reads the confirm response from ctx.mcpReq.inputResponses, validates the accepted content, and checks whether the operator actually confirmed. If the response says yes, the tool returns ordinary content such as a deployment success message. If the response was declined or cancelled, the handler can return a tool result with isError: true and explanatory text. This distinction matters because tool errors are normal JSON-RPC results that the model can read and recover from, unlike protocol errors, which describe invalid requests the model never sees.
Sources: docs/servers/input-required.md, docs/servers/errors.md
server.registerTool(
'deploy',
{ description: 'Deploy after the operator confirms' },
async ({ env }, ctx) => {
const confirmed = acceptedContent(ctx.mcpReq.inputResponses, 'confirm');
if (confirmed?.confirm !== true) {
return inputRequired({
inputRequests: {
confirm: inputRequired.elicit({
message: `Deploy to ${env}?`,
requestedSchema: { type: 'object', properties: { confirm: { type: 'boolean' } }, required: ['confirm'] }
})
}
});
}
return { content: [{ type: 'text', text: `Deployed to ${env}` }] };
}
);Relationship to Elicitation, Completion, and Notifications
input_required is closely related to elicitation, but it is not the same control flow as calling ctx.mcpReq.elicitInput. The elicitation guide shows a 2025-era handler awaiting elicitInput, where the connected client handles elicitation/create and returns an action such as accept, decline, or cancel. The input-required guide changes the shape for 2026-07-28 connections: the handler returns the request and resumes only when the client retries the original operation. When migrating, treat elicitInput as a push helper for older protocol behavior and input_required as the retry-oriented shape for new multi-round operations.
Sources: docs/servers/input-required.md, docs/servers/elicitation.md
Completion and notifications solve different user-experience problems and should not be substituted for input-required waiting states. Completion is server-side autocomplete for prompt arguments or resource template variables; it helps the user fill a value before the main request is invoked. Notifications are one-way messages such as list-changed or resource-updated events; they tell clients cached data is stale or that a subscribed resource changed. Input-required is different because it belongs to a specific in-flight tool, prompt, or resource request and requires the client to retry that exact request with responses attached.
Sources: docs/servers/completion.md, docs/servers/notifications.md
Validation, State, and Failure Handling
For safe handlers, validate all accepted response content before using it and handle every user action explicitly. The input-required guide demonstrates passing a Zod schema to acceptedContent so a confirmation object is checked before the handler trusts it. The elicitation guide separately emphasizes that users may accept, decline, or cancel, and the errors guide explains the result shapes to use afterward. A declined action is often best expressed as a tool-level error with helpful text, because the model can read that content and decide whether to stop, ask the user again, or choose a different tool.
Sources: docs/servers/input-required.md, docs/servers/elicitation.md, docs/servers/errors.md
Long-running handlers may combine input-required decisions with progress, logging, or cancellation. The logging and progress guide shows that every handler receives a context whose ctx.mcpReq object carries request-scoped helpers such as _meta, notify, log, and cancellation signals. Input-required handlers should still preserve replayability: progress updates can describe work already performed, but the final decision after a retry should come from request arguments, input responses, and any explicit request state. Avoid designing a flow where the second entry only works because the first entry left temporary state in memory.
Sources: docs/servers/input-required.md, docs/servers/logging-progress-cancellation.md
requestState is the documented way to carry server-defined state across input-required rounds when the original arguments and response payloads are not enough. It is preferable to per-session process memory because the retry can be handled consistently even when deployments use stateless HTTP handlers, multiple workers, or per-request server instances. Keep the state minimal and treat it as part of the protocol-visible waiting flow. If the information is security sensitive or authorization dependent, store only a reference or nonce and re-check authorization on the resumed call before performing irreversible work.
Sources: docs/servers/input-required.md, docs/servers/notifications.md
Compact Reference
| Name or concept | Documented behavior | Practical guidance |
|---|---|---|
inputRequired(spec) | Returns an input-required result and throws TypeError if neither inputRequests nor requestState is present. | Build this as the handler return value when user input is missing. |
inputRequests | Map of named embedded requests such as a confirmation request. | Use stable keys like confirm so the retried handler can find the answer. |
inputRequired.elicit(...) | Creates an elicitation-style embedded request with message and requested schema. | Match the request to a client capability and keep schemas flat and clear. |
ctx.mcpReq.inputResponses | Client-supplied answers on the retried call. | Treat as untrusted and validate before using. |
acceptedContent(...) | Reads accepted response content, optionally through a schema. | Prefer the schema overload for typed handler logic. |
inputResponse(...) | Reads the response view including kind and action. | Use it to distinguish accept, decline, and cancel. |
Tool isError: true | Successful result that reports a recoverable tool failure to the model. | Use for declined or cancelled operations when the model should see the reason. |
| Protocol error | JSON-RPC error response for invalid requests. | Use when the request itself is malformed or unsupported, not for normal user refusal. |
Next Steps
Start with the input-required pattern for any 2026-era handler that needs a mid-call confirmation or form response. Then read the elicitation page if you maintain older push-style handlers, the errors page to choose between recoverable tool results and protocol errors, and the logging-progress-cancellation page for long-running operations. If your handler changes available tools, prompts, or resources while waiting for user input, review notifications as well so cache invalidation remains separate from the request retry loop. For client-side handling, pair this page with the server-requests and client-calling guides.