class LittleGhost::MCP::Client
Client is the lower-level interface for loading tools from an MCP server. Most Agents can declare a reusable Toolset instead. Use Client directly when an application needs a custom transport.
transport = LittleGhost::MCP::HTTPTransport.new(url: "https://mcp.example/rpc") client = LittleGhost::MCP::Client.new(transport:) client.tools.map(&:tool_name) # => ["search", "fetch"]
Tool names are normalized and checked for collisions. LittleGhost limits catalog size, schema complexity, and returned media before creating Tool classes. tool_mapper and result_mapper use the same Definition, Result, and Call values as Toolset.
The server chooses its definitions and results. LittleGhost checks their structure before creating Tools, but the application still chooses which servers and operations an Agent may use.
A client and its transport represent one authenticated server session. Create a separate pair for each authenticated user or service identity. Protocol initialization and subsequent requests through one client are serialized; do not share its transport with another client.
Public Class Methods
# File lib/little_ghost/mcp/client.rb, line 195 def initialize( transport:, name: "mcp", tool_mapper: nil, result_mapper: nil ) validate_callback(tool_mapper, :tool_mapper) validate_callback(result_mapper, :result_mapper) @transport = transport @name = String(name) @tool_mapper = tool_mapper @result_mapper = result_mapper @max_tools = DEFAULT_MAX_TOOLS @max_pages = DEFAULT_MAX_PAGES @max_discovery_bytes = DEFAULT_MAX_DISCOVERY_BYTES @max_discovery_nodes = DEFAULT_MAX_DISCOVERY_NODES @max_definition_depth = DEFAULT_MAX_DEFINITION_DEPTH @max_definition_nodes = DEFAULT_MAX_DEFINITION_NODES @max_images = DEFAULT_MAX_IMAGES @max_image_bytes = DEFAULT_MAX_IMAGE_BYTES @max_total_image_bytes = DEFAULT_MAX_TOTAL_IMAGE_BYTES @request_id = 0 @mutex = Mutex.new @initialization_mutex = Mutex.new @definitions_mutex = Mutex.new @definitions_by_name = {} @initialized = false end
Public Instance Methods
# File lib/little_ghost/mcp/client.rb, line 246 def call(name, arguments, context: nil, binding: Tool::Binding.new) context&.check! ensure_initialized(context:) prepared = if name.is_a?(PreparedDefinition) name elsif name.is_a?(Definition) prepare_definition(name, context:) else definition_for_call(name, context:) end definition = prepared.definition call_value = Call.new(definition:, arguments:, context:, binding:) raw = request( "tools/call", {name: definition.source_name, arguments: call_value.arguments.to_h}, context: ) result = build_result(raw, prepared:) context&.check! mapped = if @result_mapper @result_mapper.call(result, call: call_value, binding:) else default_value(result) end context&.check! tool_result(mapped, protocol_result: result) end
Calls a generated or named Tool and returns the common Tool execution result. Names discovered through tools resolve to their stored Definition; an undiscovered name is treated as a source name.
# File lib/little_ghost/mcp/client.rb, line 227 def tools(context: nil, binding: Tool::Binding.new) context&.check! ensure_initialized(context:) definitions = list_tool_definitions(context:).map do |raw| context&.check! build_definition(raw, context:).tap { context&.check! } end tools = definitions.filter_map do |definition| context&.check! build_tool(definition, binding:).tap { context&.check! } end index_tools!(tools, context:) context&.check! tools.freeze end
Negotiates the protocol when needed, then provides Tool classes for the server’s current definitions.