Module: MCPClient::HttpTransportBase

Includes:
JsonRpcCommon
Included in:
ServerHTTP::JsonRpcTransport, ServerStreamableHTTP::JsonRpcTransport
Defined in:
lib/mcp_client/http_transport_base.rb

Overview

Base module for HTTP-based JSON-RPC transports Contains common functionality shared between HTTP and Streamable HTTP transports

Instance Method Summary collapse

Methods included from JsonRpcCommon

#build_jsonrpc_notification, #build_jsonrpc_request, #ping, #process_jsonrpc_response, #with_retry

Instance Method Details

#rpc_notify(method, params = {}) ⇒ void

This method returns an undefined value.

Send a JSON-RPC notification (no response expected)

Parameters:

  • method (String)

    JSON-RPC method name

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

    parameters for the notification



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/mcp_client/http_transport_base.rb', line 34

def rpc_notify(method, params = {})
  ensure_connected

  notif = build_jsonrpc_notification(method, params)

  begin
    send_http_request(notif)
  rescue MCPClient::Errors::ServerError, MCPClient::Errors::ConnectionError, Faraday::ConnectionFailed => e
    raise MCPClient::Errors::TransportError, "Failed to send notification: #{e.message}"
  end
end

#rpc_request(method, params = {}) ⇒ Object

Generic JSON-RPC request: send method with params and return result

Parameters:

  • method (String)

    JSON-RPC method name

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

    parameters for the request

Returns:

  • (Object)

    result from JSON-RPC response

Raises:



20
21
22
23
24
25
26
27
28
# File 'lib/mcp_client/http_transport_base.rb', line 20

def rpc_request(method, params = {})
  ensure_connected

  with_retry do
    request_id = @mutex.synchronize { @request_id += 1 }
    request = build_jsonrpc_request(method, params, request_id)
    send_jsonrpc_request(request)
  end
end

#terminate_sessionBoolean

Terminate the current session with the server Sends an HTTP DELETE request with the session ID to properly close the session

Returns:

  • (Boolean)

    true if termination was successful

Raises:



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/mcp_client/http_transport_base.rb', line 50

def terminate_session
  return true unless @session_id

  conn = http_connection

  begin
    @logger.debug("Terminating session: #{@session_id}")
    response = conn.delete(@endpoint) do |req|
      # Apply base headers but prioritize session termination headers
      @headers.each { |k, v| req.headers[k] = v }
      req.headers['Mcp-Session-Id'] = @session_id
    end

    if response.success?
      @logger.debug("Session terminated successfully: #{@session_id}")
      @session_id = nil
      true
    else
      @logger.warn("Session termination failed with HTTP #{response.status}")
      @session_id = nil # Clear session ID even on HTTP error
      false
    end
  rescue Faraday::Error => e
    @logger.warn("Session termination request failed: #{e.message}")
    # Clear session ID even if termination request failed
    @session_id = nil
    false
  end
end

#valid_server_url?(url) ⇒ Boolean

Validate the server’s base URL for security

Parameters:

  • url (String)

    the URL to validate

Returns:

  • (Boolean)

    true if URL is considered safe



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/mcp_client/http_transport_base.rb', line 95

def valid_server_url?(url)
  return false unless url.is_a?(String)

  uri = URI.parse(url)

  # Only allow HTTP and HTTPS protocols
  return false unless %w[http https].include?(uri.scheme)

  # Must have a host
  return false if uri.host.nil? || uri.host.empty?

  # Don't allow localhost binding to all interfaces in production
  if uri.host == '0.0.0.0'
    @logger.warn('Server URL uses 0.0.0.0 which may be insecure. Consider using 127.0.0.1 for localhost.')
  end

  true
rescue URI::InvalidURIError
  false
end

#valid_session_id?(session_id) ⇒ Boolean

Validate session ID format for security

Parameters:

  • session_id (String)

    the session ID to validate

Returns:

  • (Boolean)

    true if session ID is valid



83
84
85
86
87
88
89
90
# File 'lib/mcp_client/http_transport_base.rb', line 83

def valid_session_id?(session_id)
  return false unless session_id.is_a?(String)
  return false if session_id.empty?

  # Session ID should be alphanumeric with optional hyphens and underscores
  # Length should be reasonable (8-128 characters)
  session_id.match?(/\A[a-zA-Z0-9\-_]{8,128}\z/)
end