Class: RubyLLM::MCP::Auth::UrlBuilder
- Inherits:
-
Object
- Object
- RubyLLM::MCP::Auth::UrlBuilder
- Defined in:
- lib/ruby_llm/mcp/auth/url_builder.rb
Overview
Utility class for building OAuth URLs Handles discovery URLs, authorization URLs, and URL normalization
Class Method Summary collapse
-
.build_authorization_server_metadata_urls(issuer_url) ⇒ Array<String>
Build authorization server metadata URLs (RFC 8414 + OIDC compatibility).
-
.build_authorization_url(authorization_endpoint, client_id, redirect_uri, scope, state, pkce, resource) ⇒ String
Build OAuth authorization URL.
-
.build_discovery_url(server_url, discovery_type = :authorization_server) ⇒ String
Build discovery URL for OAuth server metadata.
-
.build_discovery_urls(server_url, discovery_type = :authorization_server) ⇒ Array<String>
Build ordered discovery URLs for OAuth metadata.
-
.build_protected_resource_metadata_urls(server_url) ⇒ Array<String>
Build protected resource metadata URLs (RFC 9728 / MCP Section 4.2) Ordered as required by the MCP spec: 1) Path-based well-known URI 2) Root well-known URI.
-
.default_port?(uri) ⇒ Boolean
Check if port is default for scheme.
-
.get_authorization_base_url(server_url) ⇒ String
Get authorization base URL from server URL.
-
.normalized_path_component(path) ⇒ String?
Convert URI path to a clean path component with no leading/trailing slash.
-
.origin_for(uri) ⇒ String
Build scheme://host(:port).
Class Method Details
.build_authorization_server_metadata_urls(issuer_url) ⇒ Array<String>
Build authorization server metadata URLs (RFC 8414 + OIDC compatibility)
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/ruby_llm/mcp/auth/url_builder.rb', line 53 def self.(issuer_url) uri = URI.parse(issuer_url) origin = origin_for(uri) path_component = normalized_path_component(uri.path) if path_component [ "#{origin}/.well-known/oauth-authorization-server/#{path_component}", "#{origin}/.well-known/openid-configuration/#{path_component}", "#{origin}/#{path_component}/.well-known/openid-configuration" ] else [ "#{origin}/.well-known/oauth-authorization-server", "#{origin}/.well-known/openid-configuration" ] end end |
.build_authorization_url(authorization_endpoint, client_id, redirect_uri, scope, state, pkce, resource) ⇒ String
Build OAuth authorization URL
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/ruby_llm/mcp/auth/url_builder.rb', line 81 def self.(, client_id, redirect_uri, scope, state, pkce, resource) # rubocop:disable Metrics/ParameterLists params = { response_type: "code", client_id: client_id, redirect_uri: redirect_uri, scope: scope, state: state, # CSRF protection code_challenge: pkce.code_challenge, code_challenge_method: pkce.code_challenge_method, # S256 resource: resource # RFC 8707 - Resource Indicators }.compact uri = URI.parse() uri.query = URI.encode_www_form(params) uri.to_s end |
.build_discovery_url(server_url, discovery_type = :authorization_server) ⇒ String
Build discovery URL for OAuth server metadata
13 14 15 |
# File 'lib/ruby_llm/mcp/auth/url_builder.rb', line 13 def self.build_discovery_url(server_url, discovery_type = :authorization_server) build_discovery_urls(server_url, discovery_type).first end |
.build_discovery_urls(server_url, discovery_type = :authorization_server) ⇒ Array<String>
Build ordered discovery URLs for OAuth metadata
21 22 23 24 25 26 27 28 29 30 |
# File 'lib/ruby_llm/mcp/auth/url_builder.rb', line 21 def self.build_discovery_urls(server_url, discovery_type = :authorization_server) case discovery_type when :authorization_server (server_url) when :protected_resource (server_url) else raise ArgumentError, "Unknown discovery type: #{discovery_type}" end end |
.build_protected_resource_metadata_urls(server_url) ⇒ Array<String>
Build protected resource metadata URLs (RFC 9728 / MCP Section 4.2) Ordered as required by the MCP spec:
- Path-based well-known URI
- Root well-known URI
38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/ruby_llm/mcp/auth/url_builder.rb', line 38 def self.(server_url) uri = URI.parse(server_url) origin = origin_for(uri) endpoint = "oauth-protected-resource" path_component = normalized_path_component(uri.path) urls = [] urls << "#{origin}/.well-known/#{endpoint}/#{path_component}" if path_component urls << "#{origin}/.well-known/#{endpoint}" urls.uniq end |
.default_port?(uri) ⇒ Boolean
Check if port is default for scheme
109 110 111 112 |
# File 'lib/ruby_llm/mcp/auth/url_builder.rb', line 109 def self.default_port?(uri) (uri.scheme == "http" && uri.port == 80) || (uri.scheme == "https" && uri.port == 443) end |
.get_authorization_base_url(server_url) ⇒ String
Get authorization base URL from server URL
101 102 103 104 |
# File 'lib/ruby_llm/mcp/auth/url_builder.rb', line 101 def self.(server_url) uri = URI.parse(server_url) origin_for(uri) end |
.normalized_path_component(path) ⇒ String?
Convert URI path to a clean path component with no leading/trailing slash
126 127 128 129 130 131 |
# File 'lib/ruby_llm/mcp/auth/url_builder.rb', line 126 def self.normalized_path_component(path) return nil if path.nil? || path.empty? || path == "/" cleaned = path.split("/").reject(&:empty?).join("/") cleaned.empty? ? nil : cleaned end |
.origin_for(uri) ⇒ String
Build scheme://host(:port)
117 118 119 120 121 |
# File 'lib/ruby_llm/mcp/auth/url_builder.rb', line 117 def self.origin_for(uri) origin = "#{uri.scheme}://#{uri.host}" origin += ":#{uri.port}" if uri.port && !default_port?(uri) origin end |