Class: Ask::MCP::Client
- Inherits:
-
Object
- Object
- Ask::MCP::Client
- Defined in:
- lib/ask/mcp/client.rb
Constant Summary collapse
- PROTOCOL_VERSION =
Deprecated: use Ask::MCP::PROTOCOL_VERSION (the canonical constant). Kept as an alias so existing consumers don't break.
Ask::MCP::PROTOCOL_VERSION
Instance Attribute Summary collapse
-
#capabilities ⇒ Object
readonly
Returns the value of attribute capabilities.
-
#server_info ⇒ Object
readonly
Returns the value of attribute server_info.
-
#transport ⇒ Object
readonly
Returns the value of attribute transport.
Instance Method Summary collapse
- #call_tool(name, arguments = {}) ⇒ Object
- #get_prompt(name, arguments = {}) ⇒ Object
-
#initialize(transport, options = {}) ⇒ Client
constructor
A new instance of Client.
- #initialized? ⇒ Boolean
-
#listen(notifications) ⇒ Object
Open a long-lived notification stream (2026-07-28 subscriptions/listen).
-
#on_elicitation(&handler) ⇒ Object
Handle a server request for user input (client/elicitation, 2025-06-18+).
-
#on_request(method, &handler) ⇒ Object
Register a handler for a server-initiated request (a JSON-RPC Request the server sends to the client, such as elicitation/create or sampling/createMessage).
-
#on_sampling(&handler) ⇒ Object
Handle a sampling request (client/sampling).
- #prompts ⇒ Object
- #read_resource(uri) ⇒ Object
- #resources ⇒ Object
- #start ⇒ Object
- #stop ⇒ Object
- #tools ⇒ Object
Constructor Details
#initialize(transport, options = {}) ⇒ Client
Returns a new instance of Client.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/ask/mcp/client.rb', line 12 def initialize(transport, = {}) @transport = transport @options = @capabilities = {} @server_info = {} @tools_cache = nil @resources_cache = nil @prompts_cache = nil @pending_requests = {} @pending_mutex = Mutex.new @pending_condition = ConditionVariable.new @request_handlers = {} @next_id = 0 @initialized = false # Negotiated protocol version; nil until start() resolves it. @protocol_version = nil @stateless = false end |
Instance Attribute Details
#capabilities ⇒ Object (readonly)
Returns the value of attribute capabilities.
10 11 12 |
# File 'lib/ask/mcp/client.rb', line 10 def capabilities @capabilities end |
#server_info ⇒ Object (readonly)
Returns the value of attribute server_info.
10 11 12 |
# File 'lib/ask/mcp/client.rb', line 10 def server_info @server_info end |
#transport ⇒ Object (readonly)
Returns the value of attribute transport.
10 11 12 |
# File 'lib/ask/mcp/client.rb', line 10 def transport @transport end |
Instance Method Details
#call_tool(name, arguments = {}) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/ask/mcp/client.rb', line 68 def call_tool(name, arguments = {}) if @options[:validate] && @tools_cache tool = @tools_cache[name] if tool && tool.input_schema && !tool.input_schema.empty? Validator.new(tool.input_schema).validate!(arguments) end end headers = mcp_param_headers(name, arguments) response = send_request("tools/call", { name: name, arguments: arguments }, headers: headers) response[:content] || response end |
#get_prompt(name, arguments = {}) ⇒ Object
85 86 87 88 |
# File 'lib/ask/mcp/client.rb', line 85 def get_prompt(name, arguments = {}) response = send_request("prompts/get", { name: name, arguments: arguments }) response[:messages] || response end |
#initialized? ⇒ Boolean
90 91 92 |
# File 'lib/ask/mcp/client.rb', line 90 def initialized? @initialized end |
#listen(notifications) ⇒ Object
Open a long-lived notification stream (2026-07-28 subscriptions/listen).
notifications is a filter Hash, e.g.
{ toolsListChanged: true, resourceSubscriptions: ["file:///x"] }
Notifications flow into the client's message handling (which resets
caches on list_changed). Only supported on transports that implement
#listen (StreamableHTTP).
132 133 134 |
# File 'lib/ask/mcp/client.rb', line 132 def listen(notifications) @transport.listen(notifications) end |
#on_elicitation(&handler) ⇒ Object
Handle a server request for user input (client/elicitation, 2025-06-18+). The handler receives the elicitation params (including the Elicitation schema with titled/untitled, single/multi-select enums and default values in 2025-11-25) and returns an ElicitationResponse hash, e.g. { message: "42" } or structured content. Declare client support via Ask::MCP::Client.new(transport, client_capabilities: { elicitation: {} })
111 112 113 |
# File 'lib/ask/mcp/client.rb', line 111 def on_elicitation(&handler) on_request("elicitation/create", &handler) end |
#on_request(method, &handler) ⇒ Object
Register a handler for a server-initiated request (a JSON-RPC Request the server sends to the client, such as elicitation/create or sampling/createMessage). The handler receives the request params and must return the result hash to send back. The handler runs on the transport reader thread, so long-blocking handlers block message processing — return promptly.
100 101 102 |
# File 'lib/ask/mcp/client.rb', line 100 def on_request(method, &handler) @request_handlers[method] = handler end |
#on_sampling(&handler) ⇒ Object
Handle a sampling request (client/sampling). The handler receives the
CreateMessageRequest params — including tools and toolChoice when
the server offers tool calling (2025-11-25, SEP-1577) — and returns a
CreateMessageResult hash, e.g.
{ role: "assistant", content: { type: "text", text: "..." } }
Declare client support via
Ask::MCP::Client.new(transport, client_capabilities: { sampling: {} })
122 123 124 |
# File 'lib/ask/mcp/client.rb', line 122 def on_sampling(&handler) on_request("sampling/createMessage", &handler) end |
#prompts ⇒ Object
60 61 62 63 64 65 66 |
# File 'lib/ask/mcp/client.rb', line 60 def prompts return @prompts_cache if @prompts_cache && !@options[:no_cache] response = send_request("prompts/list") prompts = (response[:prompts] || []).map { |p| Prompt.from_h(p) } @prompts_cache = index_by_name(prompts) end |
#read_resource(uri) ⇒ Object
80 81 82 83 |
# File 'lib/ask/mcp/client.rb', line 80 def read_resource(uri) response = send_request("resources/read", { uri: uri }) response[:contents] || response end |
#resources ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/ask/mcp/client.rb', line 52 def resources return @resources_cache if @resources_cache && !@options[:no_cache] response = send_request("resources/list") resources = (response[:resources] || []).map { |r| Resource.from_h(r) } @resources_cache = index_by_uri(resources) end |
#start ⇒ Object
31 32 33 34 35 36 |
# File 'lib/ask/mcp/client.rb', line 31 def start @transport. { || () } @transport.start negotiate_protocol self end |
#stop ⇒ Object
38 39 40 41 |
# File 'lib/ask/mcp/client.rb', line 38 def stop @transport.stop @initialized = false end |
#tools ⇒ Object
43 44 45 46 47 48 49 50 |
# File 'lib/ask/mcp/client.rb', line 43 def tools return @tools_cache if @tools_cache && !@options[:no_cache] response = send_request("tools/list") tools = (response[:tools] || []).map { |t| Tool.from_h(t) } tools = reject_invalid_mcp_header_tools(tools) @tools_cache = index_by_name(tools) end |