Class: Ask::MCP::Adapters::ToolServer

Inherits:
Object
  • Object
show all
Defined in:
lib/ask/mcp/adapters/tool_server.rb

Overview

Converts duck-typed tool objects into MCP tool definitions and dispatches calls. This is the server-direction adapter — it takes any objects that respond to name, description, params_schema, and call(args) and exposes them over MCP.

Usage:

class MyTool
  def name; "hello" end
  def description; "Says hello" end
  def params_schema; nil end
  def call(args = {}); OpenStruct.new(ok?: true, output: "Hello!") end
end

adapter = ToolServer.new([MyTool.new])
adapter.definitions  # => [{ name: "hello", ... }]
adapter.call("hello", {})  # => { content: [...], isError: false }

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tools = []) ⇒ ToolServer

Returns a new instance of ToolServer.

Parameters:

  • tools (Array<#call, #name, #description, #params_schema>) (defaults to: [])

    tool instances to expose



26
27
28
29
# File 'lib/ask/mcp/adapters/tool_server.rb', line 26

def initialize(tools = [])
  @tools = tools
  @tool_map = tools.each_with_object({}) { |t, h| h[t.name] = t }
end

Instance Attribute Details

#toolsObject (readonly)

Returns the value of attribute tools.



23
24
25
# File 'lib/ask/mcp/adapters/tool_server.rb', line 23

def tools
  @tools
end

Instance Method Details

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

Call a tool and wrap the result in MCP format

Parameters:

  • name (String)

    tool name

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

    arguments (may have symbol or string keys)

Returns:

  • (Hash)

    { content: […], isError: true/false }



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/ask/mcp/adapters/tool_server.rb', line 48

def call(name, arguments = {})
  tool = @tool_map[name]
  unless tool
    return error_result("Tool not found: #{name}")
  end

  normalized = deep_stringify_keys(arguments)
  result = tool.call(normalized)
  wrap_result(result)
rescue StandardError => e
  if defined?(Ask::Tool::Halt) && e.is_a?(Ask::Tool::Halt)
    return { content: [{ type: "text", text: e.content.to_s }], isError: false }
  end
  error_result("#{e.class}: #{e.message}")
end

#definitionsArray<Hash>

MCP tool definitions for tools/list

Returns:

  • (Array<Hash>)


33
34
35
36
37
38
39
40
41
42
# File 'lib/ask/mcp/adapters/tool_server.rb', line 33

def definitions
  @tools.map do |tool|
    schema = tool.params_schema || { type: "object", properties: {}, required: [] }
    {
      name: tool.name,
      description: tool.description || "",
      inputSchema: schema
    }
  end
end