Module: ActionMCP::Server::Elicitation

Included in:
TransportHandler
Defined in:
lib/action_mcp/server/elicitation.rb

Overview

Handles elicitation requests from the server to the client.

Two modes per MCP 2025-11-25:

- Form mode: structured data collection with JSON Schema validation
- URL mode: out-of-band interaction via external URL (sensitive data, OAuth flows)

Constant Summary collapse

URL_ELICITATION_REQUIRED_CODE =
-32_042

Instance Method Summary collapse

Instance Method Details

#send_elicitation_complete_notification(elicitation_id) ⇒ Object

Send a completion notification for a URL mode elicitation. Informs the client that the out-of-band interaction has completed.

Parameters:

  • elicitation_id (String)

    The elicitation ID from the original request



57
58
59
60
61
62
63
# File 'lib/action_mcp/server/elicitation.rb', line 57

def send_elicitation_complete_notification(elicitation_id)
  require_client_elicitation_support!(:url)
  send_jsonrpc_notification(
    "notifications/elicitation/complete",
    { elicitationId: elicitation_id }
  )
end

#send_elicitation_create(message:, requested_schema:, _meta: {}) ⇒ Object

Send a form mode elicitation request to the client.

Parameters:

  • message (String)

    Human-readable message explaining why input is needed

  • requested_schema (Hash)

    JSON Schema for the expected response (primitive types only)

  • _meta (Hash) (defaults to: {})

    Optional metadata (e.g. related task)



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/action_mcp/server/elicitation.rb', line 20

def send_elicitation_create(message:, requested_schema:, _meta: {})
  require_client_elicitation_support!(:form)

  request = ElicitationRequest.new(
    message: message,
    requested_schema: requested_schema,
    _meta: _meta
  )
  request.assert_valid!

  send_jsonrpc_request("elicitation/create", params: request.to_params)
end

#send_elicitation_create_url(message:, url:, elicitation_id: nil, _meta: {}) ⇒ Object

Send a URL mode elicitation request to the client. Used for sensitive data collection (API keys, OAuth, payments) that must not pass through the MCP client.

Parameters:

  • message (String)

    Human-readable message explaining why navigation is needed

  • url (String)

    The URL the user should navigate to

  • elicitation_id (String) (defaults to: nil)

    Unique identifier for this elicitation

  • _meta (Hash) (defaults to: {})

    Optional metadata (e.g. related task)



40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/action_mcp/server/elicitation.rb', line 40

def send_elicitation_create_url(message:, url:, elicitation_id: nil, _meta: {})
  require_client_elicitation_support!(:url)

  request = UrlElicitationRequest.new(
    message: message,
    url: url,
    elicitation_id: elicitation_id,
    _meta: _meta
  )
  request.assert_valid!

  send_jsonrpc_request("elicitation/create", params: request.to_params)
end

#send_url_elicitation_required_error(request_id, message:, elicitations:) ⇒ Object

Build a URLElicitationRequiredError response (-32042). Used when a request cannot proceed until an elicitation is completed.

Parameters:

  • request_id (String, Integer)

    The JSON-RPC request ID to respond to

  • message (String)

    Human-readable error message

  • elicitations (Array<Hash>)

    Required URL mode elicitations



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/action_mcp/server/elicitation.rb', line 70

def send_url_elicitation_required_error(request_id, message:, elicitations:)
  require_client_elicitation_support!(:url)

  elicitations.each do |e|
    raise ArgumentError, "Each elicitation must have mode: 'url'" unless e[:mode] == "url"
    raise ArgumentError, "Each elicitation must have an elicitationId" unless e[:elicitationId].present?

    UrlElicitationRequest.new(
      message: e[:message],
      url: e[:url],
      elicitation_id: e[:elicitationId]
    ).assert_valid!
  end

  error = {
    code: URL_ELICITATION_REQUIRED_CODE,
    message: message,
    data: { elicitations: elicitations }
  }

  send_jsonrpc_response(request_id, error: error)
end