# `Excessibility.MCP.Elicitation`
[🔗](https://github.com/lessthanseventy/excessibility/blob/v0.18.1/lib/excessibility/mcp/elicitation.ex#L1)

Handles the MCP elicitation protocol for structured user interaction.

Elicitation allows MCP tools to pause execution and ask the user a structured
question. The server sends an `elicitation/create` request to the client, which
presents the question and returns the user's response.

## Usage in Tools

Tools receive an `elicit` callback via their opts when the server supports
elicitation:

    def execute(args, opts) do
      case opts[:elicit] do
        nil ->
          # No elicitation support, proceed with defaults
          do_work(args)

        elicit ->
          schema = %{
            "type" => "object",
            "properties" => %{
              "approved" => %{"type" => "boolean", "description" => "Approve this action?"}
            }
          }

          case elicit.("Found 5 issues. Fix them?", schema) do
            {:accept, %{"approved" => true}} -> fix_issues(args)
            {:accept, _} -> {:ok, %{"status" => "skipped"}}
            :decline -> {:ok, %{"status" => "declined"}}
            :cancel -> {:error, "cancelled by user"}
          end
      end
    end

## Protocol

The elicitation flow follows JSON-RPC 2.0:

1. Server sends `elicitation/create` request with message and schema
2. Client responds with `{action: "accept"|"decline"|"cancel", content: {...}}`

# `build_callback`

```elixir
@spec build_callback((String.t() -&gt; :ok) | nil, (-&gt; String.t()) | nil) ::
  (String.t(), map() -&gt;
     {:accept, map()} | :decline | :cancel | {:error, term()})
  | nil
```

Builds an elicitation callback function for use in tool opts.

Returns `nil` if either `write_fn` or `read_fn` is nil (elicitation not supported).
Otherwise returns a 2-arity function `fn message, schema -> result` that handles
the full elicitation round-trip: building the request, writing it as JSON,
reading the response, and parsing it.

## Parameters

- `write_fn` - A 1-arity function that writes a string to the client
- `read_fn` - A 0-arity function that reads a string response from the client

# `build_request`

```elixir
@spec build_request(integer(), String.t(), map()) :: map()
```

Builds a JSON-RPC 2.0 elicitation request.

Returns a map with method `"elicitation/create"` and params containing
the message and requested schema.

# `parse_response`

```elixir
@spec parse_response(map()) ::
  {:accept, map()} | :decline | :cancel | {:error, term()}
```

Parses a JSON-RPC elicitation response.

Returns:
- `{:accept, content}` when the user accepted and provided content
- `:decline` when the user declined
- `:cancel` when the user cancelled

---

*Consult [api-reference.md](api-reference.md) for complete listing*
