Documentation
¶
Overview ¶
Package elicitation provides a Client for requesting structured user input via the MCP elicitation protocol.
The Client is a value type — its zero value is safe to use and acts as a no-op when the connected MCP client does not support elicitation. This mirrors the pattern used by progress.Tracker.
Validation and Safety ¶
SECURITY: All responses are validated against the expected JSON Schema. User input is never trusted and must be sanitized by the caller before use in API calls.
Index ¶
- Constants
- Variables
- func CancelledResult(message string) *mcp.CallToolResult
- func ConfirmAction(ctx context.Context, req *mcp.CallToolRequest, message string) *mcp.CallToolResult
- func ConfirmFailedResult(err error) *mcp.CallToolResult
- type Client
- func (c Client) Confirm(ctx context.Context, message string) (bool, error)
- func (c Client) ElicitURL(ctx context.Context, gitlabBaseURL, targetURL, message string) error
- func (c Client) GatherData(ctx context.Context, message string, schema map[string]any) (map[string]any, error)
- func (c Client) IsFormSupported() bool
- func (c Client) IsSupported() bool
- func (c Client) IsURLSupported() bool
- func (c Client) PromptNumber(ctx context.Context, message, fieldName string, minVal, maxVal float64) (float64, error)
- func (c Client) PromptText(ctx context.Context, message, fieldName string) (string, error)
- func (c Client) SelectMulti(ctx context.Context, message string, options []string, minItems, maxItems int) ([]string, error)
- func (c Client) SelectOne(ctx context.Context, message string, options []string) (string, error)
- func (c Client) SelectOneInt(ctx context.Context, message string, options []int) (int, error)
- type Flow
- func (f *Flow) Confirm(ctx context.Context, id, message string) (bool, error)
- func (f *Flow) ElicitURL(ctx context.Context, id, gitlabBaseURL, targetURL, message string) error
- func (f *Flow) GatherData(ctx context.Context, id, message string, schema map[string]any) (map[string]any, error)
- func (f *Flow) InputRequiredResult() *mcp.CallToolResult
- func (f *Flow) IsSupported() bool
- func (f *Flow) PendingError() error
- func (f *Flow) PromptNumber(ctx context.Context, id, message, fieldName string, minVal, maxVal float64) (float64, error)
- func (f *Flow) PromptText(ctx context.Context, id, message, fieldName string) (string, error)
- func (f *Flow) SelectMulti(ctx context.Context, id, message string, options []string, ...) ([]string, error)
- func (f *Flow) SelectOne(ctx context.Context, id, message string, options []string) (string, error)
- func (f *Flow) SelectOneInt(ctx context.Context, id, message string, options []int) (int, error)
- func (f *Flow) UsesMultiRoundTrip() bool
- type InputRequiredError
Constants ¶
const ConfirmExchangeID = "confirm"
ConfirmExchangeID is the stable input-request id used by single-round confirmation guards on the multi round-trip elicitation path.
Variables ¶
var ErrCancelled = errors.New("elicitation: user canceled")
ErrCancelled is returned when the user dismisses an elicitation without making an explicit choice.
var ErrDeclined = errors.New("elicitation: user declined")
ErrDeclined is returned when the user explicitly declines an elicitation.
var ErrElicitationNotSupported = errors.New("elicitation: client does not support elicitation capability")
ErrElicitationNotSupported is returned when the MCP client does not advertise the elicitation capability.
var ErrFormElicitationNotSupported = errors.New("elicitation: client does not support form elicitation")
ErrFormElicitationNotSupported is returned when the client declares url mode and not form mode, so a form request would be one "the client has not declared support for".
var ErrInputPending = errors.New("elicitation: input request pending client response")
ErrInputPending is returned by Flow prompt methods when the answer is not yet available and an input request has been queued for the client. Handlers must stop and surface Flow.InputRequiredResult (or Flow.PendingError for handlers that return errors) so the client can fulfill the request and retry the call.
var ErrMalformedAnswer = errors.New("elicitation: the answer did not satisfy the requested schema")
ErrMalformedAnswer is returned when a client accepts an elicitation request with content that does not satisfy the schema the request carried.
It is deliberately not ErrDeclined or ErrCancelled. Those two mean a person decided something; this means a client sent something the server cannot read. Reporting the second as the first invents a user decision that never happened, which is worse than reporting a failure, because a model acting on "the user cancelled" will not retry and will tell the user they refused.
var ErrURLElicitationNotSupported = errors.New("elicitation: client does not support URL elicitation")
ErrURLElicitationNotSupported is returned when the MCP client supports form elicitation but not URL mode elicitation.
Functions ¶
func CancelledResult ¶
func CancelledResult(message string) *mcp.CallToolResult
CancelledResult returns an error tool result indicating the user canceled.
It is an error result for the same reason the unsupported-client one beside it is: the operation did not run, so it produced none of the output its schema describes, and a tool declaring an outputSchema must return structured results conforming to it. A cancellation conforms to nothing.
func ConfirmAction ¶
func ConfirmAction(ctx context.Context, req *mcp.CallToolRequest, message string) *mcp.CallToolResult
ConfirmAction asks the user to confirm an action via elicitation. Returns nil if confirmed or elicitation is not supported (backward compatible). Returns a non-nil *mcp.CallToolResult if the user declined or canceled, or an input-required result when the session uses multi round-trip requests and the client has not answered yet. Any other confirmation failure fails closed with an error result: a destructive action must never proceed on a malformed or failed confirmation exchange.
func ConfirmFailedResult ¶
func ConfirmFailedResult(err error) *mcp.CallToolResult
ConfirmFailedResult returns the fail-closed error result used when a destructive-action confirmation exchange fails for a reason other than an explicit user decision (for example a malformed answer or a transport failure). It instructs the caller to re-send with explicit approval.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client sends elicitation requests to the MCP client for user input. Its zero value is an inactive client where IsSupported returns false.
The capabilities are captured when the Client is built rather than read from the session on each question. From protocol 2026-07-28 a client declares them per request, so the session is not the authority: a stateless HTTP POST is its own session, and on stdio the session carries whatever the first request happened to say.
func FromRequest ¶
func FromRequest(req *mcp.CallToolRequest) Client
FromRequest extracts the server session from a CallToolRequest and returns a Client. If the connected MCP client does not support elicitation, the returned Client is inactive (IsSupported returns false).
The capabilities come from mcp.ServerRequest.ClientCapabilities, which reads the request's own `_meta` and falls back to the session's InitializeParams for older protocol revisions. Reading InitializeParams directly is what made this panic: the SDK synthesizes InitializeParams for a request that arrives without a handshake and leaves Capabilities, a pointer, nil. Every stateless HTTP POST from a pre-2026-07-28 client took that path, so an ordinary client killed the process on any call that could elicit.
func (Client) Confirm ¶
Confirm asks the user a yes/no question and returns true if the user accepted with confirmed=true, false otherwise. Returns ErrDeclined or ErrCancelled if the user did not accept.
func (Client) ElicitURL ¶
ElicitURL sends a URL-mode elicitation request, directing the user to a GitLab page. The URL must belong to the configured GitLab instance (SSRF prevention). Per the MCP 2025-11-25 spec, URL mode requests MUST include a unique elicitationId; one is generated automatically. Returns nil on accept, ErrDeclined, ErrCancelled, or another error.
func (Client) GatherData ¶
func (c Client) GatherData(ctx context.Context, message string, schema map[string]any) (map[string]any, error)
GatherData sends an arbitrary JSON Schema to the client and returns the user's response as a map. This is the low-level method underlying the convenience methods.
SECURITY: The caller is responsible for validating and sanitizing the returned data before using it in API calls.
func (Client) IsFormSupported ¶
IsFormSupported returns true if the MCP client can render a form mode elicitation request.
The predicate mirrors the one the SDK enforces when the request is sent: a client that declares url mode and not form mode does not support form, while one that declares neither is treated as form-capable for backwards compatibility, since an empty capabilities object predates the modes. The specification's "servers MUST NOT send elicitation requests with modes that are not supported by the client" is the reason to ask before queueing rather than to discover it from the SDK's refusal afterwards.
func (Client) IsSupported ¶
IsSupported returns true if the MCP client supports elicitation.
func (Client) IsURLSupported ¶
IsURLSupported returns true if the MCP client supports URL mode elicitation.
func (Client) PromptNumber ¶
func (c Client) PromptNumber(ctx context.Context, message, fieldName string, minVal, maxVal float64) (float64, error)
PromptNumber asks the user for a numeric input within a range. minVal and maxVal define inclusive bounds; use math.Inf(-1) and math.Inf(1) for no bounds.
func (Client) PromptText ¶
PromptText asks the user for free-form text input and returns the value.
func (Client) SelectMulti ¶
func (c Client) SelectMulti(ctx context.Context, message string, options []string, minItems, maxItems int) ([]string, error)
SelectMulti asks the user to pick one or more options from a list. minItems and maxItems constrain the number of selections (0 means no limit).
type Flow ¶
type Flow struct {
// contains filtered or unexported fields
}
Flow performs elicitation exchanges for a single tool call, selecting the synchronous path for legacy sessions and the multi round-trip path for protocol >= 2026-07-28 sessions. Prompt methods take a stable id that identifies the exchange across handler re-invocations; ids must be unique within one tool call.
func FlowFromRequest ¶
func FlowFromRequest(req *mcp.CallToolRequest) (*Flow, error)
FlowFromRequest builds a Flow for the current tool call. For multi round-trip sessions it decodes the client-echoed RequestState and merges the InputResponses from the retried call. It returns an error when the echoed state is malformed.
func (*Flow) Confirm ¶
Confirm asks the user a yes/no question. See Client.Confirm.
func (*Flow) ElicitURL ¶
ElicitURL sends a URL-mode elicitation request, directing the user to a GitLab page. See Client.ElicitURL.
func (*Flow) GatherData ¶
func (f *Flow) GatherData(ctx context.Context, id, message string, schema map[string]any) (map[string]any, error)
GatherData sends an arbitrary JSON Schema to the client and returns the user's response as a map. See Client.GatherData.
func (*Flow) InputRequiredResult ¶
func (f *Flow) InputRequiredResult() *mcp.CallToolResult
InputRequiredResult builds the tool result carrying the queued input requests plus the accumulated answers encoded as opaque RequestState. The result must be returned as-is, with no content added: the protocol forbids mixing content and inputRequests in one result.
func (*Flow) IsSupported ¶
IsSupported reports whether the MCP client supports elicitation.
func (*Flow) PendingError ¶
PendingError wraps Flow.InputRequiredResult in an InputRequiredError for handlers that report outcomes through an error return.
func (*Flow) PromptNumber ¶
func (f *Flow) PromptNumber(ctx context.Context, id, message, fieldName string, minVal, maxVal float64) (float64, error)
PromptNumber asks the user for a numeric input within a range. See Client.PromptNumber.
func (*Flow) PromptText ¶
PromptText asks the user for free-form text input. See Client.PromptText.
func (*Flow) SelectMulti ¶
func (f *Flow) SelectMulti(ctx context.Context, id, message string, options []string, minItems, maxItems int) ([]string, error)
SelectMulti asks the user to pick one or more options from a list. See Client.SelectMulti.
func (*Flow) SelectOne ¶
SelectOne asks the user to pick one option from a list. See Client.SelectOne.
func (*Flow) SelectOneInt ¶
SelectOneInt asks the user to pick one integer from a list of allowed values. See Client.SelectOneInt.
func (*Flow) UsesMultiRoundTrip ¶
UsesMultiRoundTrip reports whether this flow uses the multi round-trip request mechanism (protocol >= 2026-07-28) instead of synchronous server-initiated elicitation.
type InputRequiredError ¶
type InputRequiredError struct {
// contains filtered or unexported fields
}
InputRequiredError carries an input-required tool result out of handlers that report failures through an error return. Surface wrappers unwrap it with errors.AsType and return the embedded result instead of an error.
func (*InputRequiredError) Error ¶
func (e *InputRequiredError) Error() string
Error implements the error interface.
func (*InputRequiredError) Result ¶
func (e *InputRequiredError) Result() *mcp.CallToolResult
Result returns the input-required tool result to send to the client.