Class: RobotLab::MCP::Transports::StreamableHTTP

Inherits:
Base
  • Object
show all
Defined in:
lib/robot_lab/mcp/transports/streamable_http.rb

Overview

Streamable HTTP transport for MCP servers

Supports session management and reconnection.

Examples:

transport = StreamableHTTP.new(
  url: "https://server.smithery.ai/neon/mcp",
  session_id: "abc123"
)

Constant Summary

Constants inherited from Base

Base::DEFAULT_TIMEOUT

Instance Attribute Summary

Attributes inherited from Base

#config, #timeout

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ StreamableHTTP

Creates a new StreamableHTTP transport.

Parameters:

  • config (Hash)

    transport configuration

Options Hash (config):

  • :url (String)

    HTTP server URL

  • :session_id (String)

    optional session identifier

  • :auth_provider (Proc)

    optional authentication callback



23
24
25
26
27
28
# File 'lib/robot_lab/mcp/transports/streamable_http.rb', line 23

def initialize(config)
  super
  @client = nil
  @connected = false
  @session_id = config[:session_id]
end

Instance Method Details

#closeself

Close the HTTP connection.

Returns:

  • (self)


95
96
97
98
99
100
101
102
103
# File 'lib/robot_lab/mcp/transports/streamable_http.rb', line 95

def close
  return self unless @connected

  @client&.close
  @connected = false
  @client = nil

  self
end

#connectself

Connect to the MCP server via HTTP.

Returns:

  • (self)

Raises:

  • (MCPError)

    if async-http gem is not available



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/robot_lab/mcp/transports/streamable_http.rb', line 34

def connect
  return self if @connected

  require "async"
  require "async/http/client"
  require "async/http/endpoint"

  url = @config[:url]

  Async do
    endpoint = Async::HTTP::Endpoint.parse(url)
    @client = Async::HTTP::Client.new(endpoint)
    @connected = true

    # Initialize MCP protocol
    result = send_initialize
    @session_id ||= result.dig(:serverInfo, :sessionId)
  end

  self
rescue LoadError => e
  raise MCPError, "async-http gem required for HTTP transport: #{e.message}"
end

#connected?Boolean

Check if the transport is connected.

Returns:

  • (Boolean)

    true if connected



108
109
110
# File 'lib/robot_lab/mcp/transports/streamable_http.rb', line 108

def connected?
  @connected
end

#send_request(message) ⇒ Hash

Send a JSON-RPC request to the MCP server.

Parameters:

  • message (Hash)

    JSON-RPC message

Returns:

  • (Hash)

    the response

Raises:



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
# File 'lib/robot_lab/mcp/transports/streamable_http.rb', line 63

def send_request(message)
  raise MCPError, "Not connected" unless @connected

  require "async"

  Async do
    headers = {
      "Content-Type" => "application/json",
      "Accept" => "application/json"
    }
    headers["X-Session-ID"] = @session_id if @session_id

    # Add auth if configured
    if @config[:auth_provider]
      auth_header = @config[:auth_provider].call
      headers["Authorization"] = auth_header if auth_header
    end

    response = @client.post(
      @config[:url],
      headers,
      [message.to_json]
    )

    body = response.read
    JSON.parse(body, symbolize_names: true)
  end.wait
end

#session_idString?

Returns the session identifier.

Returns:

  • (String, nil)

    the session ID



115
116
117
# File 'lib/robot_lab/mcp/transports/streamable_http.rb', line 115

def session_id
  @session_id
end