Class: RubyLLM::MCP::Tool

Inherits:
Tool
  • Object
show all
Defined in:
lib/ruby_llm/mcp/tool.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(adapter, tool_response, with_prefix: false) ⇒ Tool

Returns a new instance of Tool.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/ruby_llm/mcp/tool.rb', line 31

def initialize(adapter, tool_response, with_prefix: false)
  super()
  @adapter = adapter

  @with_prefix = with_prefix
  @name = format_name(tool_response["name"])
  @mcp_name = tool_response["name"]
  @description = tool_response["description"].to_s

  @input_schema = tool_response["inputSchema"]
  @output_schema = tool_response["outputSchema"]

  @annotations = tool_response["annotations"] ? Annotation.new(tool_response["annotations"]) : nil
  @apps_metadata = Extensions::Apps::ToolMetadata.new(tool_response[Extensions::Apps::Constants::META_KEY])

  @normalized_input_schema = normalize_if_invalid(@input_schema)
end

Instance Attribute Details

#adapterObject (readonly)

Returns the value of attribute adapter.



28
29
30
# File 'lib/ruby_llm/mcp/tool.rb', line 28

def adapter
  @adapter
end

#annotationsObject (readonly)

Returns the value of attribute annotations.



28
29
30
# File 'lib/ruby_llm/mcp/tool.rb', line 28

def annotations
  @annotations
end

#apps_metadataObject (readonly)

Returns the value of attribute apps_metadata.



28
29
30
# File 'lib/ruby_llm/mcp/tool.rb', line 28

def 
  @apps_metadata
end

#descriptionObject (readonly)

Returns the value of attribute description.



28
29
30
# File 'lib/ruby_llm/mcp/tool.rb', line 28

def description
  @description
end

#nameObject (readonly)

Returns the value of attribute name.



28
29
30
# File 'lib/ruby_llm/mcp/tool.rb', line 28

def name
  @name
end

#output_schemaObject (readonly)

Returns the value of attribute output_schema.



28
29
30
# File 'lib/ruby_llm/mcp/tool.rb', line 28

def output_schema
  @output_schema
end

#titleObject (readonly)

Returns the value of attribute title.



28
29
30
# File 'lib/ruby_llm/mcp/tool.rb', line 28

def title
  @title
end

#tool_responseObject (readonly)

Returns the value of attribute tool_response.



28
29
30
# File 'lib/ruby_llm/mcp/tool.rb', line 28

def tool_response
  @tool_response
end

#with_prefixObject (readonly)

Returns the value of attribute with_prefix.



28
29
30
# File 'lib/ruby_llm/mcp/tool.rb', line 28

def with_prefix
  @with_prefix
end

Instance Method Details

#display_nameObject



49
50
51
# File 'lib/ruby_llm/mcp/tool.rb', line 49

def display_name
  "#{@adapter.client.name}: #{@name}"
end

#execute(**params) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/ruby_llm/mcp/tool.rb', line 57

def execute(**params)
  result = @adapter.execute_tool(
    name: @mcp_name,
    parameters: params
  )

  if result.error?
    error = result.to_error
    return { error: error.to_s }
  end
  content = result.value["content"]
  content = [content].compact unless content.is_a?(Array)

  text_values = content.map { |c| c.is_a?(Hash) ? c["text"] : c.to_s }.compact.join("\n")

  if result.execution_error?
    return { error: "Tool execution error: #{text_values}" }
  end

  # Validate structured content if present AND output schema is defined
  if result.value.key?("structuredContent") && !@output_schema.nil?
    clean_schema = @output_schema.except("$schema")
    structured_content = result.value["structuredContent"]
    is_valid = SchemaValidator.valid?(clean_schema, structured_content)
    unless is_valid
      return { error: "Structured output is not valid: #{structured_content}" }
    end

    # Return structured content as JSON - this is the authoritative, schema-validated data
    # The LLM needs the structured data to give accurate responses
    return create_content_for_message({ "type" => "text", "text" => structured_content.to_json })
  end

  if text_values.empty?
    create_content_for_message(content.first)
  else
    create_content_for_message({ "type" => "text", "text" => text_values })
  end
end

#params_schemaObject



53
54
55
# File 'lib/ruby_llm/mcp/tool.rb', line 53

def params_schema
  @normalized_input_schema
end

#to_hObject Also known as: to_json



97
98
99
100
101
102
103
104
# File 'lib/ruby_llm/mcp/tool.rb', line 97

def to_h
  {
    name: @name,
    description: @description,
    params_schema: @normalized_input_schema,
    annotations: @annotations&.to_h
  }
end