Class: RubyLLM::MCP::Auth::TokenManager

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

Overview

Service for managing OAuth token operations Handles token exchange, refresh, and client credentials flows

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(http_client, logger) ⇒ TokenManager

Returns a new instance of TokenManager.



14
15
16
17
# File 'lib/ruby_llm/mcp/auth/token_manager.rb', line 14

def initialize(http_client, logger)
  @http_client = http_client
  @logger = logger
end

Instance Attribute Details

#http_clientObject (readonly)

Returns the value of attribute http_client.



12
13
14
# File 'lib/ruby_llm/mcp/auth/token_manager.rb', line 12

def http_client
  @http_client
end

#loggerObject (readonly)

Returns the value of attribute logger.



12
13
14
# File 'lib/ruby_llm/mcp/auth/token_manager.rb', line 12

def logger
  @logger
end

Instance Method Details

#exchange_authorization_code(server_metadata, client_info, code, pkce, server_url) ⇒ Token

Exchange authorization code for access token

Parameters:

  • server_metadata (ServerMetadata)

    server metadata

  • client_info (ClientInfo)

    client info

  • code (String)

    authorization code

  • pkce (PKCE)

    PKCE parameters

  • server_url (String)

    MCP server URL

Returns:

  • (Token)

    access token



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ruby_llm/mcp/auth/token_manager.rb', line 26

def exchange_authorization_code(, client_info, code, pkce, server_url)
  logger.debug("Exchanging authorization code for access token")

  registered_redirect_uri = client_info..redirect_uris.first
  params = build_auth_code_params(client_info, code, pkce, registered_redirect_uri, server_url)

  response = post_token_exchange(, params, client_info)
  response = retry_if_redirect_mismatch(response, , params, registered_redirect_uri, client_info)

  validate_token_response!(response, "Token exchange")
  parse_token_response(response)
end

#exchange_client_credentials(server_metadata, client_info, scope, server_url) ⇒ Token

Exchange client credentials for access token

Parameters:

  • server_metadata (ServerMetadata)

    server metadata

  • client_info (ClientInfo)

    client info with secret

  • scope (String, nil)

    requested scope

  • server_url (String)

    MCP server URL

Returns:

  • (Token)

    access token



45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/ruby_llm/mcp/auth/token_manager.rb', line 45

def exchange_client_credentials(, client_info, scope, server_url)
  logger.debug("Exchanging client credentials for access token")

  params = {
    grant_type: "client_credentials",
    client_id: client_info.client_id,
    scope: scope,
    resource: server_url
  }.compact

  response = post_token_exchange(, params, client_info)
  validate_token_response!(response, "Token exchange")
  parse_token_response(response)
end

#refresh_token(server_metadata, client_info, token, server_url) ⇒ Token?

Refresh access token using refresh token

Parameters:

  • server_metadata (ServerMetadata)

    server metadata

  • client_info (ClientInfo)

    client info

  • token (Token)

    current token with refresh_token

  • server_url (String)

    MCP server URL

Returns:

  • (Token, nil)

    new token or nil if refresh failed



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
91
92
93
# File 'lib/ruby_llm/mcp/auth/token_manager.rb', line 66

def refresh_token(, client_info, token, server_url)
  return nil unless token.refresh_token

  logger.debug("Refreshing access token")

  params = build_refresh_params(client_info, token, server_url)
  response = post_token_refresh(, params, client_info)

  # Return nil on error responses
  return nil if response.is_a?(HTTPX::ErrorResponse)

  if response.status != 200
    oauth_error = extract_oauth_error(response.body.to_s)
    raise_oauth_error!("Token refresh", oauth_error, response.status) if oauth_error
    return nil
  end

  parse_refresh_response(response, token)
rescue Errors::TransportError => e
  logger.warn(e.message)
  nil
rescue JSON::ParserError => e
  logger.warn("Invalid token refresh response: #{e.message}")
  nil
rescue HTTPX::Error => e
  logger.warn("Network error during token refresh: #{e.message}")
  nil
end