barrel_mcp_elicitation (barrel_mcp v3.0.1)

View Source

Elicitation requests, in both modes, and the registry behind URL mode.

Form mode collects structured data through the client. Secrets (passwords, API keys, tokens, payment credentials) **MUST** go through URL mode instead, where the interaction happens out of band (2026-07-28/client/elicitation.mdx:30). The two have separate constructors, form/2 and url/3, so one cannot be sent as the other.

URL checks are syntactic: https outside a development flag, no scheme but http(s), no userinfo. A pre-authenticated URL is not detectable and stays the caller's obligation (2025-11-25/client/elicitation.mdx:716).

2025-11-25 URL mode carries an elicitationId and signals completion with notifications/elicitation/complete, which the server "MUST only send to the client that initiated" it, keyed on something other than a session id alone (elicitation.mdx:403,580). Entries here are owned by the principal; the session is only where to deliver. 2026-07-28 dropped the id and registers nothing.

Summary

Functions

Mark an elicitation complete and notify the client that started it. Authorised against the owning principal, and terminal.

Drop every elicitation waiting on a session that has ended.

Build a form-mode elicitation/create params map. Schema is the restricted subset the spec allows: a flat object of primitives.

Run the URL checks and return the host. Both ends use it: the client must not offer a URL that fails them either.

Read one elicitation, for the principal that owns it. Someone else's id reads as not found.

Build a URL-mode elicitation/create params map, registering an elicitationId when the era needs one. {error, Reason} when the URL fails a check: {bad_scheme, S}, insecure_url, url_has_credentials, url_has_no_host, malformed_url.

Types

action/0

-type action() :: accept | decline | cancel.

Functions

complete(Id, Ctx)

-spec complete(binary(), barrel_mcp_ctx:ctx() | term()) -> ok | {error, not_found | already_complete}.

Mark an elicitation complete and notify the client that started it. Authorised against the owning principal, and terminal.

count()

-spec count() -> non_neg_integer().

forget_session(SessionId)

-spec forget_session(binary()) -> ok.

Drop every elicitation waiting on a session that has ended.

form(Message, Schema)

-spec form(binary(), map()) -> map().

Equivalent to form(Message, Schema, #{}).

form(Message, Schema, Extra)

-spec form(binary(), map(), map()) -> map().

Build a form-mode elicitation/create params map. Schema is the restricted subset the spec allows: a flat object of primitives.

Never for secrets; use url/3. Unchecked, because a schema may name its properties anything.

handle_call(Msg, From, State)

handle_cast(Msg, State)

handle_info(Msg, State)

init(_)

inspect_url(Url)

-spec inspect_url(binary()) -> {ok, binary()} | {error, term()}.

Run the URL checks and return the host. Both ends use it: the client must not offer a URL that fails them either.

lookup(Id, Principal)

-spec lookup(binary(), term()) -> {ok, map()} | {error, not_found}.

Read one elicitation, for the principal that owns it. Someone else's id reads as not found.

start_link()

terminate(Reason, State)

url(Message, Url, Ctx)

-spec url(binary(), binary(), barrel_mcp_ctx:ctx()) -> {ok, map()} | {error, term()}.

Equivalent to url(Message, Url, Ctx, #{}).

url(Message, Url, Ctx, Extra)

-spec url(binary(), binary(), barrel_mcp_ctx:ctx(), map()) -> {ok, map()} | {error, term()}.

Build a URL-mode elicitation/create params map, registering an elicitationId when the era needs one. {error, Reason} when the URL fails a check: {bad_scheme, S}, insecure_url, url_has_credentials, url_has_no_host, malformed_url.

Unchecked, and yours to honour: the URL "MUST NOT include sensitive information about the end-user" and "MUST NOT" be "pre-authenticated to access a protected resource" (2025-11-25/client/elicitation.mdx:715).