Class: MCP::Client
- Inherits:
-
Object
- Object
- MCP::Client
- Defined in:
- lib/mcp/client.rb,
lib/mcp/client/http.rb,
lib/mcp/client/tool.rb,
lib/mcp/client/stdio.rb,
lib/mcp/client/paginated_result.rb
Defined Under Namespace
Classes: HTTP, ListPromptsResult, ListResourceTemplatesResult, ListResourcesResult, ListToolsResult, RequestHandlerError, ServerError, SessionExpiredError, Stdio, Tool, ValidationError
Instance Attribute Summary collapse
-
#transport ⇒ Object
readonly
The user may want to access additional transport-specific methods/attributes So keeping it public.
Instance Method Summary collapse
-
#call_tool(name: nil, tool: nil, arguments: nil, progress_token: nil) ⇒ Hash
Calls a tool via the transport layer and returns the full response from the server.
-
#complete(ref:, argument:, context: nil) ⇒ Hash
Requests completion suggestions from the server for a prompt argument or resource template URI.
-
#connect(client_info: nil, protocol_version: nil, capabilities: {}) ⇒ Hash?
Performs the MCP ‘initialize` handshake by delegating to the transport (e.g. `MCP::Client::HTTP`, `MCP::Client::Stdio`).
-
#connected? ⇒ Boolean
Returns true once ‘connect` has completed the handshake on the underlying transport.
-
#get_prompt(name:) ⇒ Hash
Gets a prompt from the server by name and returns its details.
-
#initialize(transport:) ⇒ Client
constructor
Initializes a new MCP::Client instance.
-
#list_prompts(cursor: nil) ⇒ MCP::Client::ListPromptsResult
Returns a single page of prompts from the server.
-
#list_resource_templates(cursor: nil) ⇒ MCP::Client::ListResourceTemplatesResult
Returns a single page of resource templates from the server.
-
#list_resources(cursor: nil) ⇒ MCP::Client::ListResourcesResult
Returns a single page of resources from the server.
-
#list_tools(cursor: nil) ⇒ MCP::Client::ListToolsResult
Returns a single page of tools from the server.
-
#ping ⇒ Hash
Sends a ‘ping` request to the server to verify the connection is alive.
-
#prompts ⇒ Array<Hash>
Returns every prompt available on the server.
-
#read_resource(uri:) ⇒ Array<Hash>
Reads a resource from the server by URI and returns the contents.
-
#resource_templates ⇒ Array<Hash>
Returns every resource template available on the server.
-
#resources ⇒ Array<Hash>
Returns every resource available on the server.
-
#server_info ⇒ Object
The server’s ‘InitializeResult` (protocol version, capabilities, server info, instructions), as reported by the transport after a successful `connect`.
-
#tools ⇒ Array<MCP::Client::Tool>
Returns every tool available on the server.
Constructor Details
#initialize(transport:) ⇒ Client
Initializes a new MCP::Client instance.
54 55 56 |
# File 'lib/mcp/client.rb', line 54 def initialize(transport:) @transport = transport end |
Instance Attribute Details
#transport ⇒ Object (readonly)
The user may want to access additional transport-specific methods/attributes So keeping it public
60 61 62 |
# File 'lib/mcp/client.rb', line 60 def transport @transport end |
Instance Method Details
#call_tool(name: nil, tool: nil, arguments: nil, progress_token: nil) ⇒ Hash
The exact requirements for ‘arguments` are determined by the transport layer in use. Consult the documentation for your transport (e.g., MCP::Client::HTTP) for details.
Calls a tool via the transport layer and returns the full response from the server.
313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/mcp/client.rb', line 313 def call_tool(name: nil, tool: nil, arguments: nil, progress_token: nil) tool_name = name || tool&.name raise ArgumentError, "Either `name:` or `tool:` must be provided." unless tool_name params = { name: tool_name, arguments: arguments } if progress_token params[:_meta] = { progressToken: progress_token } end request(method: "tools/call", params: params) end |
#complete(ref:, argument:, context: nil) ⇒ Hash
Requests completion suggestions from the server for a prompt argument or resource template URI.
352 353 354 355 356 357 358 359 |
# File 'lib/mcp/client.rb', line 352 def complete(ref:, argument:, context: nil) params = { ref: ref, argument: argument } params[:context] = context if context response = request(method: "completion/complete", params: params) response.dig("result", "completion") || { "values" => [], "hasMore" => false } end |
#connect(client_info: nil, protocol_version: nil, capabilities: {}) ⇒ Hash?
Performs the MCP ‘initialize` handshake by delegating to the transport (e.g. `MCP::Client::HTTP`, `MCP::Client::Stdio`). Returns the server’s ‘InitializeResult`.
When the transport does not respond to ‘:connect`, this is a no-op and returns `nil`.
modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle#initialization
83 84 85 86 87 88 89 90 91 |
# File 'lib/mcp/client.rb', line 83 def connect(client_info: nil, protocol_version: nil, capabilities: {}) return unless transport.respond_to?(:connect) transport.connect( client_info: client_info, protocol_version: protocol_version, capabilities: capabilities, ) end |
#connected? ⇒ Boolean
Returns true once ‘connect` has completed the handshake on the underlying transport. Transports that do not expose connection state are assumed connected and return `true`.
96 97 98 99 100 |
# File 'lib/mcp/client.rb', line 96 def connected? return transport.connected? if transport.respond_to?(:connected?) true end |
#get_prompt(name:) ⇒ Hash
Gets a prompt from the server by name and returns its details.
339 340 341 342 343 |
# File 'lib/mcp/client.rb', line 339 def get_prompt(name:) response = request(method: "prompts/get", params: { name: name }) response.fetch("result", {}) end |
#list_prompts(cursor: nil) ⇒ MCP::Client::ListPromptsResult
Returns a single page of prompts from the server.
255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/mcp/client.rb', line 255 def list_prompts(cursor: nil) params = cursor ? { cursor: cursor } : nil response = request(method: "prompts/list", params: params) result = response["result"] || {} ListPromptsResult.new( prompts: result["prompts"] || [], next_cursor: result["nextCursor"], meta: result["_meta"], ) end |
#list_resource_templates(cursor: nil) ⇒ MCP::Client::ListResourceTemplatesResult
Returns a single page of resource templates from the server.
212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/mcp/client.rb', line 212 def list_resource_templates(cursor: nil) params = cursor ? { cursor: cursor } : nil response = request(method: "resources/templates/list", params: params) result = response["result"] || {} ListResourceTemplatesResult.new( resource_templates: result["resourceTemplates"] || [], next_cursor: result["nextCursor"], meta: result["_meta"], ) end |
#list_resources(cursor: nil) ⇒ MCP::Client::ListResourcesResult
Returns a single page of resources from the server.
169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/mcp/client.rb', line 169 def list_resources(cursor: nil) params = cursor ? { cursor: cursor } : nil response = request(method: "resources/list", params: params) result = response["result"] || {} ListResourcesResult.new( resources: result["resources"] || [], next_cursor: result["nextCursor"], meta: result["_meta"], ) end |
#list_tools(cursor: nil) ⇒ MCP::Client::ListToolsResult
Returns a single page of tools from the server.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/mcp/client.rb', line 116 def list_tools(cursor: nil) params = cursor ? { cursor: cursor } : nil response = request(method: "tools/list", params: params) result = response["result"] || {} tools = (result["tools"] || []).map do |tool| Tool.new( name: tool["name"], description: tool["description"], input_schema: tool["inputSchema"], ) end ListToolsResult.new(tools: tools, next_cursor: result["nextCursor"], meta: result["_meta"]) end |
#ping ⇒ Hash
Sends a ‘ping` request to the server to verify the connection is alive. Per the MCP spec, the server responds with an empty result.
372 373 374 375 376 377 |
# File 'lib/mcp/client.rb', line 372 def ping result = request(method: Methods::PING)["result"] raise ValidationError, "Response validation failed: missing or invalid `result`" unless result.is_a?(Hash) result end |
#prompts ⇒ Array<Hash>
Returns every prompt available on the server. Iterates through all pages automatically when the server paginates, so the full collection is returned regardless of the server’s ‘page_size` setting. Use #list_prompts when you need fine-grained cursor control.
Each call will make a new request - the result is not cached.
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/mcp/client.rb', line 274 def prompts # TODO: consider renaming to `list_all_prompts`. all_prompts = [] seen = Set.new cursor = nil loop do page = list_prompts(cursor: cursor) all_prompts.concat(page.prompts) next_cursor = page.next_cursor break if next_cursor.nil? || seen.include?(next_cursor) seen << next_cursor cursor = next_cursor end all_prompts end |
#read_resource(uri:) ⇒ Array<Hash>
Reads a resource from the server by URI and returns the contents.
329 330 331 332 333 |
# File 'lib/mcp/client.rb', line 329 def read_resource(uri:) response = request(method: "resources/read", params: { uri: uri }) response.dig("result", "contents") || [] end |
#resource_templates ⇒ Array<Hash>
Returns every resource template available on the server. Iterates through all pages automatically when the server paginates, so the full collection is returned regardless of the server’s ‘page_size` setting. Use #list_resource_templates when you need fine-grained cursor control.
Each call will make a new request - the result is not cached.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/mcp/client.rb', line 231 def resource_templates # TODO: consider renaming to `list_all_resource_templates`. all_templates = [] seen = Set.new cursor = nil loop do page = list_resource_templates(cursor: cursor) all_templates.concat(page.resource_templates) next_cursor = page.next_cursor break if next_cursor.nil? || seen.include?(next_cursor) seen << next_cursor cursor = next_cursor end all_templates end |
#resources ⇒ Array<Hash>
Returns every resource available on the server. Iterates through all pages automatically when the server paginates, so the full collection is returned regardless of the server’s ‘page_size` setting. Use #list_resources when you need fine-grained cursor control.
Each call will make a new request - the result is not cached.
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/mcp/client.rb', line 188 def resources # TODO: consider renaming to `list_all_resources`. all_resources = [] seen = Set.new cursor = nil loop do page = list_resources(cursor: cursor) all_resources.concat(page.resources) next_cursor = page.next_cursor break if next_cursor.nil? || seen.include?(next_cursor) seen << next_cursor cursor = next_cursor end all_resources end |
#server_info ⇒ Object
The server’s ‘InitializeResult` (protocol version, capabilities, server info, instructions), as reported by the transport after a successful `connect`. Returns `nil` before `connect`, after `close`, or when the transport does not expose a cached handshake result.
66 67 68 |
# File 'lib/mcp/client.rb', line 66 def server_info transport.server_info if transport.respond_to?(:server_info) end |
#tools ⇒ Array<MCP::Client::Tool>
Returns every tool available on the server. Iterates through all pages automatically when the server paginates, so the full collection is returned regardless of the server’s ‘page_size` setting. Use #list_tools when you need fine-grained cursor control.
Each call will make a new request - the result is not cached.
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/mcp/client.rb', line 145 def tools # TODO: consider renaming to `list_all_tools`. all_tools = [] seen = Set.new cursor = nil loop do page = list_tools(cursor: cursor) all_tools.concat(page.tools) next_cursor = page.next_cursor break if next_cursor.nil? || seen.include?(next_cursor) seen << next_cursor cursor = next_cursor end all_tools end |