Class: LittleGhost::MCP::Adapter

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

Overview

:nodoc:

Constant Summary collapse

MAX_TOOL_NAME_LENGTH =
64
ALIAS_DIGEST_LENGTH =
12
MAX_TOOLS =
1_000
MAX_TOOL_PAGES =
100
CONTEXT_POLL_INTERVAL =
0.05

Instance Method Summary collapse

Constructor Details

#initialize(client:, session:, name: "mcp", tool_mapper: nil, result_mapper: nil) ⇒ Adapter

Returns a new instance of Adapter.



191
192
193
194
195
196
197
# File 'lib/little_ghost/mcp/client.rb', line 191

def initialize(client:, session:, name: "mcp", tool_mapper: nil, result_mapper: nil)
  @client = client
  @session = session
  @name = String(name)
  @tool_mapper = tool_mapper
  @result_mapper = result_mapper
end

Instance Method Details

#call(mcp_tool, arguments, context:, binding:) ⇒ Object



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/little_ghost/mcp/client.rb', line 220

def call(mcp_tool, arguments, context:, binding:)
  context&.check!
  response = request(context:) do |cancellation|
    @client.call_tool(name: mcp_tool.name, arguments:, cancellation:)
  end
  result = response.is_a?(Hash) && response["result"]
  raise ProtocolError, "MCP tools/call did not return a result object" unless result.is_a?(Hash)

  content = result.fetch("content", [])
  validate_content!(content)
  value = default_value(result, content:)
  mapped = if @result_mapper
    @result_mapper.call(value, result:, mcp_tool:, arguments:, binding:)
  else
    value
  end
  context&.check!
  tool_result(mapped, result:, content:)
rescue ::MCP::CancelledError
  context&.check!
  raise CancelledError, "The MCP request was cancelled"
rescue ::MCP::Client::ServerError => error
  raise ToolError, error.message.to_s.empty? ? "MCP request failed" : error.message
rescue ::MCP::Client::ValidationError, ::MCP::Client::InputRequiredError => error
  raise ProtocolError, "MCP client rejected the response: #{error.message}"
rescue ::MCP::Client::RequestHandlerError => error
  raise ProviderError, "MCP transport failed (#{error.error_type})"
end

#tools(context: nil, binding: Tool::Binding.new) ⇒ Object



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/little_ghost/mcp/client.rb', line 199

def tools(context: nil, binding: Tool::Binding.new)
  context&.check!
  generated = discover_tools(context:).filter_map do |mcp_tool|
    context&.check!
    build_tool(mcp_tool, binding:)
  end
  validate_tool_names!(generated, context:)
  generated.freeze
rescue ::MCP::CancelledError
  context&.check!
  raise CancelledError, "The MCP request was cancelled"
rescue ::MCP::Client::ServerError => error
  raise ToolError, error.message.to_s.empty? ? "MCP request failed" : error.message
rescue ::MCP::Client::PaginationLimitError => error
  raise ProtocolError, "MCP tools/list exceeded the pagination limit: #{error.message}"
rescue ::MCP::Client::ValidationError, ::MCP::Client::InputRequiredError => error
  raise ProtocolError, "MCP client rejected the response: #{error.message}"
rescue ::MCP::Client::RequestHandlerError => error
  raise ProviderError, "MCP transport failed (#{error.error_type})"
end