Class: RubyLLM::MCP::Auth::Browser::HttpServer

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_llm/mcp/auth/browser/http_server.rb

Overview

HTTP server utilities for OAuth callback handling Provides lightweight HTTP server functionality without external dependencies

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(port:, logger: nil) ⇒ HttpServer

Returns a new instance of HttpServer.



12
13
14
15
# File 'lib/ruby_llm/mcp/auth/browser/http_server.rb', line 12

def initialize(port:, logger: nil)
  @port = port
  @logger = logger || MCP.logger
end

Instance Attribute Details

#loggerObject (readonly)

Returns the value of attribute logger.



10
11
12
# File 'lib/ruby_llm/mcp/auth/browser/http_server.rb', line 10

def logger
  @logger
end

#portObject (readonly)

Returns the value of attribute port.



10
11
12
# File 'lib/ruby_llm/mcp/auth/browser/http_server.rb', line 10

def port
  @port
end

Instance Method Details

#configure_client_socket(client) ⇒ Object

Configure client socket with timeout

Parameters:

  • client (TCPSocket)

    client socket



35
36
37
# File 'lib/ruby_llm/mcp/auth/browser/http_server.rb', line 35

def configure_client_socket(client)
  client.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, [5, 0].pack("l_2"))
end

#extract_request_parts(request_line) ⇒ Array<String, String>?

Extract method and path from request line

Parameters:

  • request_line (String)

    HTTP request line

Returns:

  • (Array<String, String>, nil)

    method and path, or nil if invalid



49
50
51
52
53
54
# File 'lib/ruby_llm/mcp/auth/browser/http_server.rb', line 49

def extract_request_parts(request_line)
  parts = request_line.split
  return nil unless parts.length >= 2

  parts[0..1]
end

#parse_query_params(query_string) ⇒ Hash

Parse URL query parameters

Parameters:

  • query_string (String)

    query string

Returns:

  • (Hash)

    parsed parameters



73
74
75
76
77
78
79
80
81
82
# File 'lib/ruby_llm/mcp/auth/browser/http_server.rb', line 73

def parse_query_params(query_string)
  params = {}
  query_string.split("&").each do |param|
    next if param.empty?

    key, value = param.split("=", 2)
    params[CGI.unescape(key)] = CGI.unescape(value || "")
  end
  params
end

#read_http_headers(client) ⇒ Object

Read HTTP headers from client

Parameters:

  • client (TCPSocket)

    client socket



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/ruby_llm/mcp/auth/browser/http_server.rb', line 58

def read_http_headers(client)
  header_count = 0
  loop do
    break if header_count >= 100

    line = client.gets
    break if line.nil? || line.strip.empty?

    header_count += 1
  end
end

#read_request_line(client) ⇒ String?

Read HTTP request line from client

Parameters:

  • client (TCPSocket)

    client socket

Returns:

  • (String, nil)

    request line



42
43
44
# File 'lib/ruby_llm/mcp/auth/browser/http_server.rb', line 42

def read_request_line(client)
  client.gets
end

#send_http_response(client, status, content_type, body) ⇒ Object

Send HTTP response to client

Parameters:

  • client (TCPSocket)

    client socket

  • status (Integer)

    HTTP status code

  • content_type (String)

    content type

  • body (String)

    response body



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/ruby_llm/mcp/auth/browser/http_server.rb', line 89

def send_http_response(client, status, content_type, body)
  status_text = case status
                when 200 then "OK"
                when 400 then "Bad Request"
                when 404 then "Not Found"
                else "Unknown"
                end

  response = "HTTP/1.1 #{status} #{status_text}\r\n"
  response += "Content-Type: #{content_type}\r\n"
  response += "Content-Length: #{body.bytesize}\r\n"
  response += "Connection: close\r\n"
  response += "\r\n"
  response += body

  client.write(response)
rescue IOError, Errno::EPIPE => e
  @logger.debug("Error sending response: #{e.message}")
end

#start_serverTCPServer

Start TCP server for OAuth callbacks

Returns:

  • (TCPServer)

    TCP server instance

Raises:



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/ruby_llm/mcp/auth/browser/http_server.rb', line 20

def start_server
  TCPServer.new("127.0.0.1", @port)
rescue Errno::EADDRINUSE
  raise Errors::TransportError.new(
    message: "Cannot start OAuth callback server: port #{@port} is already in use. " \
             "Please close the application using this port or choose a different callback_port."
  )
rescue StandardError => e
  raise Errors::TransportError.new(
    message: "Failed to start OAuth callback server on port #{@port}: #{e.message}"
  )
end