class LittleGhost::MCP::HTTPTransport
HTTPTransport sends MCP JSON-RPC messages over Streamable HTTP. It applies time and response-size limits and keeps the negotiated MCP session ID.
Connections and credentials
HTTPS is required by default. allow_insecure_http is only for a local development endpoint. Scope caller-supplied credential headers to the target server. Response bodies and negotiated session IDs are validated before use.
One transport instance retains one negotiated MCP session ID and sends it with later requests. Use one transport and Client for one server and one authenticated user or service identity; never share that pair across tenants. LittleGhost does not send MCP session-termination DELETE requests, so configure server-side expiry or send the cleanup request outside this transport when the server requires explicit session termination.
Constants
- DEFAULT_MAX_RESPONSE_BYTES
-
Default upper bound for one
MCPresponse body (10 MiB).
Public Class Methods
# File lib/little_ghost/mcp/client.rb, line 40 def initialize(url:, headers: {}, timeout: 60, signer: nil, allow_insecure_http: false, max_response_bytes: DEFAULT_MAX_RESPONSE_BYTES) @uri = URI(url) unless %w[http https].include?(@uri.scheme) && @uri.host raise ConfigurationError, "MCP URL must be an HTTP(S) URL" end if @uri.scheme == "http" && !allow_insecure_http raise ConfigurationError, "MCP URL must use HTTPS unless allow_insecure_http is enabled" end @headers = headers.transform_keys(&:to_s).freeze @timeout = Float(timeout) raise ArgumentError, "timeout must be positive" unless @timeout.positive? @max_response_bytes = Integer(max_response_bytes) raise ArgumentError, "max_response_bytes must be positive" unless @max_response_bytes.positive? @signer = signer @session_id = nil end
Configures time and response-size limits. signer, when supplied, is called with each Net::HTTP request before it is sent.
Public Instance Methods
Source
# File lib/little_ghost/mcp/client.rb, line 63 def send(payload, context: nil) return perform_send(payload, timeout: @timeout) unless context response = nil stream = Support::InterruptibleStream.new( cancellation_token: context.cancellation_token, deadline: context.deadline ) do |emit| emit.call(perform_send(payload, timeout: context.remaining_time(@timeout))) end stream.each { |value| response = value } response end
Sends one JSON-RPC payload. A RunContext supplies cancellation and a deadline; without it the configured timeout applies.