Class: Phronomy::Tool::McpTool::HttpTransport

Inherits:
Object
  • Object
show all
Defined in:
lib/phronomy/tool/mcp_tool.rb

Overview

HTTP/HTTPS transport implementing JSON-RPC over HTTP with SSE support.

Sends JSON-RPC POST requests to the MCP server endpoint. Accepts both plain JSON responses (Content-Type: application/json) and Server-Sent Events streams (Content-Type: text/event-stream), covering both the 2024-11-05 and 2025-03-26 MCP HTTP transport specifications.

Examples:

tool = Phronomy::Tool::McpTool.from_server(
  "http://localhost:8080/mcp",
  tool_name: "weather_lookup"
)

Instance Method Summary collapse

Constructor Details

#initialize(base_url, open_timeout: 5, read_timeout: 30, headers: {}) ⇒ HttpTransport

Returns a new instance of HttpTransport.

Parameters:

  • base_url (String)

    full URL of the MCP endpoint, e.g. "http://localhost:8080/mcp"

  • open_timeout (Integer) (defaults to: 5)

    TCP connection timeout in seconds (default: 5)

  • read_timeout (Integer) (defaults to: 30)

    HTTP read timeout in seconds (default: 30)

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

    additional HTTP request headers (e.g. Authorization). Merged on top of the default Content-Type and Accept headers; caller-supplied values override defaults when keys collide.



273
274
275
276
277
278
# File 'lib/phronomy/tool/mcp_tool.rb', line 273

def initialize(base_url, open_timeout: 5, read_timeout: 30, headers: {})
  @uri = URI.parse(base_url)
  @open_timeout = open_timeout
  @read_timeout = read_timeout
  @extra_headers = headers
end

Instance Method Details

#call_tool(tool_name, args) ⇒ Object

Call a tool on the MCP server using MCP tools/call.

Parameters:

  • tool_name (String)
  • args (Hash)

Returns:

  • (Object)

    the tool result



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'lib/phronomy/tool/mcp_tool.rb', line 307

def call_tool(tool_name, args)
  response = rpc_call("tools/call", {name: tool_name, arguments: args})
  if response["error"]
    err_msg = response.dig("error", "message") || response["error"].to_s
    raise Phronomy::ToolError, "MCP HTTP server returned error: #{err_msg}"
  end
  content = response.dig("result", "content")

  if content.is_a?(Array)
    texts = content.select { |c| c["type"] == "text" }.map { |c| c["text"] }
    (texts.length == 1) ? texts.first : texts
  else
    content
  end
end

#closeObject

HTTP connections are stateless; close is a no-op, defined so that both transport classes share the same interface as StdioTransport.



282
283
# File 'lib/phronomy/tool/mcp_tool.rb', line 282

def close
end

#fetch_tool(tool_name) ⇒ Hash

Retrieve the tool definition from the server using MCP tools/list.

Parameters:

  • tool_name (String)

Returns:

  • (Hash)

    { description:, parameters: }

Raises:

  • (ArgumentError)


289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/phronomy/tool/mcp_tool.rb', line 289

def fetch_tool(tool_name)
  response = rpc_call("tools/list", {})
  tools = response.dig("result", "tools") || []
  defn = tools.find { |t| t["name"] == tool_name }
  raise ArgumentError, "Tool #{tool_name.inspect} not found on MCP server #{@uri}" unless defn

  required_names = defn.dig("inputSchema", "required") || []
  {
    description: defn["description"],
    parameters: parse_schema_params(defn.dig("inputSchema", "properties") || {}, required_names: required_names)
  }
end