Class: GroqRuby::MCP::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/groq_ruby/mcp/client.rb

Overview

High-level MCP client. Wraps a Transport and exposes the operations a Groq agent typically needs: handshake, list tools, invoke tools, list/read resources.

Synchronous on the outside (every public method blocks until the server responds or times out), thread-safe on the inside (the transport’s reader thread fulfils a per-id Queue).

Examples:

client = GroqRuby::MCP::Client.connect(server_config)
tools = client.tools_list
result = client.tools_call(name: "read_file", arguments: {path: "/tmp/x"})
client.stop

Constant Summary collapse

DEFAULT_REQUEST_TIMEOUT =
30.0

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(transport, request_timeout: DEFAULT_REQUEST_TIMEOUT, protocol: Protocol.default) ⇒ Client

Returns a new instance of Client.

Parameters:

  • transport (Transport)
  • request_timeout (Numeric) (defaults to: DEFAULT_REQUEST_TIMEOUT)
  • protocol (Object) (defaults to: Protocol.default)

    protocol object selecting an MCP spec year



68
69
70
71
72
73
74
75
76
77
# File 'lib/groq_ruby/mcp/client.rb', line 68

def initialize(transport, request_timeout: DEFAULT_REQUEST_TIMEOUT, protocol: Protocol.default)
  @transport = transport
  @request_timeout = request_timeout
  @protocol = protocol
  @next_id = 0
  @id_mutex = Mutex.new
  @pending = {}
  @pending_mutex = Mutex.new
  @transport.on_message { |msg| handle_message(msg) }
end

Instance Attribute Details

#protocolObject (readonly)

Returns the protocol object in use.

Returns:

  • (Object)

    the protocol object in use



63
64
65
# File 'lib/groq_ruby/mcp/client.rb', line 63

def protocol
  @protocol
end

#server_capabilitiesHash (readonly)

Returns the server’s advertised capabilities.

Returns:

  • (Hash)

    the server’s advertised capabilities



61
62
63
# File 'lib/groq_ruby/mcp/client.rb', line 61

def server_capabilities
  @server_capabilities
end

#server_nameString? (readonly)

Returns the server-reported name, populated after handshake.

Returns:

  • (String, nil)

    the server-reported name, populated after handshake



57
58
59
# File 'lib/groq_ruby/mcp/client.rb', line 57

def server_name
  @server_name
end

#server_versionString? (readonly)

Returns the server-reported version, populated after handshake.

Returns:

  • (String, nil)

    the server-reported version, populated after handshake



59
60
61
# File 'lib/groq_ruby/mcp/client.rb', line 59

def server_version
  @server_version
end

Class Method Details

.build_transport(config, protocol) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



39
40
41
42
43
44
45
46
# File 'lib/groq_ruby/mcp/client.rb', line 39

def self.build_transport(config, protocol)
  case config
  when HttpServerConfig
    Transports::HttpStreamable.start(config, protocol_version: protocol.version)
  else
    Transports::Stdio.spawn(config)
  end
end

.connect(config, request_timeout: DEFAULT_REQUEST_TIMEOUT, protocol: nil) ⇒ Client

Connect to a server and complete the initialize handshake. The transport is chosen by config type — ServerConfig → stdio, HttpServerConfig → HTTP Streamable. Caller must call #stop when done.

Parameters:

  • config (ServerConfig, HttpServerConfig)
  • request_timeout (Numeric) (defaults to: DEFAULT_REQUEST_TIMEOUT)

    seconds to wait for any single response

  • protocol (Object, nil) (defaults to: nil)

    protocol object selecting an MCP spec year. If ‘nil`, a sensible default is picked from the config type (stdio → 2024-11-05, HTTP → 2025-11-25).

Returns:



32
33
34
35
36
# File 'lib/groq_ruby/mcp/client.rb', line 32

def self.connect(config, request_timeout: DEFAULT_REQUEST_TIMEOUT, protocol: nil)
  protocol ||= default_protocol_for(config)
  transport = build_transport(config, protocol)
  new(transport, request_timeout: request_timeout, protocol: protocol).tap(&:initialize_session)
end

.default_protocol_for(config) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



49
50
51
52
53
54
# File 'lib/groq_ruby/mcp/client.rb', line 49

def self.default_protocol_for(config)
  case config
  when HttpServerConfig then Protocol::V2025_11_25.new
  else Protocol::V2024_11_05.new
  end
end

Instance Method Details

#initialize_sessionHash

Run the JSON-RPC ‘initialize` handshake. Called automatically by connect; safe to call again to re-handshake.

Returns:

  • (Hash)

    the server’s response payload



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/groq_ruby/mcp/client.rb', line 82

def initialize_session
  result = request("initialize", @protocol.initialize_params(
    client_info: {name: "groq_ruby", version: GroqRuby::VERSION}
  ))
  info = result["serverInfo"] || {}
  @server_name = info["name"]
  @server_version = info["version"]
  @server_capabilities = result["capabilities"] || {}
  notify("notifications/initialized")
  result
end

#prompts_get(name, arguments = {}) ⇒ Hash

Render a prompt template by name with the given arguments.

Parameters:

  • name (String)
  • arguments (Hash) (defaults to: {})

Returns:

  • (Hash)

    ‘messages` array as returned by the server



131
132
133
# File 'lib/groq_ruby/mcp/client.rb', line 131

def prompts_get(name, arguments = {})
  request("prompts/get", {name: name, arguments: arguments})
end

#prompts_listArray<Prompt>

Returns every prompt template advertised by the server.

Returns:

  • (Array<Prompt>)

    every prompt template advertised by the server



122
123
124
125
# File 'lib/groq_ruby/mcp/client.rb', line 122

def prompts_list
  result = request("prompts/list", {})
  Array(result["prompts"]).map { |h| Prompt.from_hash(h) }
end

#resources_listArray<Resource>

Returns every resource advertised by the server.

Returns:

  • (Array<Resource>)

    every resource advertised by the server



109
110
111
112
# File 'lib/groq_ruby/mcp/client.rb', line 109

def resources_list
  result = request("resources/list", {})
  Array(result["resources"]).map { |h| Resource.from_hash(h) }
end

#resources_read(uri) ⇒ Hash

Read a resource by URI.

Parameters:

  • uri (String)

Returns:

  • (Hash)

    ‘contents` array as returned by the server



117
118
119
# File 'lib/groq_ruby/mcp/client.rb', line 117

def resources_read(uri)
  request("resources/read", {uri: uri})
end

#stopObject

Close the underlying transport. Idempotent.



145
146
147
# File 'lib/groq_ruby/mcp/client.rb', line 145

def stop
  @transport.stop
end

#supports?(capability) ⇒ Boolean

Returns true when the handshake reported that the server advertises the given capability (‘“tools”`, `“resources”`, `“prompts”`). Useful for probing which Bridge features to enable.

Parameters:

  • capability (String)

Returns:

  • (Boolean)


140
141
142
# File 'lib/groq_ruby/mcp/client.rb', line 140

def supports?(capability)
  @server_capabilities&.key?(capability) || false
end

#tools_call(name:, arguments: {}) ⇒ Hash

Invoke a tool on the server.

Parameters:

  • name (String)
  • arguments (Hash) (defaults to: {})

Returns:

  • (Hash)

    the server’s tool-call result (may include ‘isError`)



104
105
106
# File 'lib/groq_ruby/mcp/client.rb', line 104

def tools_call(name:, arguments: {})
  request("tools/call", {name: name, arguments: arguments})
end

#tools_listArray<Tool>

Returns every tool advertised by the server.

Returns:

  • (Array<Tool>)

    every tool advertised by the server



95
96
97
98
# File 'lib/groq_ruby/mcp/client.rb', line 95

def tools_list
  result = request("tools/list", {})
  Array(result["tools"]).map { |h| Tool.from_hash(h) }
end