Class: ActionMCP::Configuration
- Inherits:
-
Object
- Object
- ActionMCP::Configuration
- Defined in:
- lib/action_mcp/configuration.rb
Overview
Configuration class to hold settings for the ActionMCP server.
Instance Attribute Summary collapse
-
#active_profile ⇒ Object
Get active profile (considering thread-local override).
-
#allowed_identity_keys ⇒ Object
Returns the value of attribute allowed_identity_keys.
-
#authentication_methods ⇒ Object
Returns the value of attribute authentication_methods.
-
#base_path ⇒ Object
Returns the value of attribute base_path.
-
#client_session_store_type ⇒ Object
Get effective client session store type (falls back to global session_store_type).
-
#connects_to ⇒ Object
Returns the value of attribute connects_to.
-
#gateway_class ⇒ Object
Returns the value of attribute gateway_class.
-
#list_changed ⇒ Boolean
Whether to send a listChanged notification for tools, prompts, and resources.
-
#logging_enabled ⇒ Boolean
Whether logging is enabled.
-
#logging_level ⇒ Symbol
The logging level.
-
#max_queue ⇒ Object
Returns the value of attribute max_queue.
-
#max_threads ⇒ Object
Returns the value of attribute max_threads.
-
#min_threads ⇒ Object
Returns the value of attribute min_threads.
-
#name ⇒ String
The name of the MCP Server.
-
#pagination_page_size ⇒ Object
Pagination page size.
-
#profiles ⇒ Object
Returns the value of attribute profiles.
-
#protocol_version ⇒ Object
Returns the value of attribute protocol_version.
-
#resources_subscribe ⇒ Boolean
Whether to subscribe to resources.
-
#server_session_store_type ⇒ Object
Get effective server session store type (falls back to global session_store_type).
-
#session_store_type ⇒ Object
Returns the value of attribute session_store_type.
-
#tasks_cancel_enabled ⇒ Object
Returns the value of attribute tasks_cancel_enabled.
-
#tasks_enabled ⇒ Object
Returns the value of attribute tasks_enabled.
-
#tasks_list_enabled ⇒ Object
Returns the value of attribute tasks_list_enabled.
-
#validate_structured_content ⇒ Object
Returns the value of attribute validate_structured_content.
-
#verbose_logging ⇒ Object
Returns the value of attribute verbose_logging.
-
#version ⇒ String
The version of the MCP Server.
Instance Method Summary collapse
- #apply_profile_options ⇒ Object
-
#capabilities ⇒ Object
Returns capabilities based on active profile.
- #eager_load_if_needed ⇒ Object
-
#filtered_prompts ⇒ Object
Filter prompts based on active profile.
-
#filtered_resources ⇒ Object
Filter resources based on active profile.
-
#filtered_tools ⇒ Object
Filter tools based on active profile.
-
#initialize ⇒ Configuration
constructor
A new instance of Configuration.
-
#instructions ⇒ Object
Instructions for LLMs about the server’s purpose (joined as string for MCP payload).
-
#load_profiles ⇒ Object
Load custom configuration from Rails configuration.
-
#server_info ⇒ Object
Server information (name and version only).
-
#server_instructions ⇒ Object
Custom getter/setter to ensure array elements are strings.
- #server_instructions=(value) ⇒ Object
-
#use_profile(profile_name) ⇒ Object
Switch to a specific profile.
Constructor Details
#initialize ⇒ Configuration
Returns a new instance of Configuration.
55 56 57 58 59 60 61 62 63 64 65 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 94 95 96 97 98 99 |
# File 'lib/action_mcp/configuration.rb', line 55 def initialize @logging_enabled = false @list_changed = true @logging_level = :warning @resources_subscribe = false @verbose_logging = false @active_profile = :primary @profiles = default_profiles # Authentication defaults - empty means all configured identifiers will be tried @authentication_methods = [] @protocol_version = "2025-06-18" # Default to stable version for backwards compatibility # Tasks defaults (MCP 2025-11-25) @tasks_enabled = false @tasks_list_enabled = true @tasks_cancel_enabled = true # Pagination - nil means off. Set a number to enable with that page size. # Most MCP clients (including Claude Code) don't follow nextCursor yet. @pagination_page_size = nil # Schema validation - disabled by default for backward compatibility @validate_structured_content = false # Server instructions - empty by default @server_instructions = [] # Gateway - resolved lazily to account for Zeitwerk autoloading @gateway_class_name = nil # Session Store @session_store_type = Rails.env.production? ? :active_record : :volatile @client_session_store_type = nil # defaults to session_store_type @server_session_store_type = nil # defaults to session_store_type # Whitelist of allowed identity attribute names to prevent method shadowing # and unauthorized attribute assignment. Extend this list if you use custom # identifier names in your GatewayIdentifier implementations. @allowed_identity_keys = %w[user api_key jwt bearer token account session].freeze # Path for JSON-RPC endpoint @base_path = "/" end |
Instance Attribute Details
#active_profile ⇒ Object
Get active profile (considering thread-local override)
164 165 166 |
# File 'lib/action_mcp/configuration.rb', line 164 def active_profile @active_profile end |
#allowed_identity_keys ⇒ Object
Returns the value of attribute allowed_identity_keys.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def allowed_identity_keys @allowed_identity_keys end |
#authentication_methods ⇒ Object
Returns the value of attribute authentication_methods.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def authentication_methods @authentication_methods end |
#base_path ⇒ Object
Returns the value of attribute base_path.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def base_path @base_path end |
#client_session_store_type ⇒ Object
Get effective client session store type (falls back to global session_store_type)
298 299 300 |
# File 'lib/action_mcp/configuration.rb', line 298 def client_session_store_type @client_session_store_type end |
#connects_to ⇒ Object
Returns the value of attribute connects_to.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def connects_to @connects_to end |
#gateway_class ⇒ Object
Returns the value of attribute gateway_class.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def gateway_class @gateway_class end |
#list_changed ⇒ Boolean
Returns Whether to send a listChanged notification for tools, prompts, and resources.
21 |
# File 'lib/action_mcp/configuration.rb', line 21 attr_writer :name, :version |
#logging_enabled ⇒ Boolean
Returns Whether logging is enabled.
21 |
# File 'lib/action_mcp/configuration.rb', line 21 attr_writer :name, :version |
#logging_level ⇒ Symbol
Returns The logging level.
21 |
# File 'lib/action_mcp/configuration.rb', line 21 attr_writer :name, :version |
#max_queue ⇒ Object
Returns the value of attribute max_queue.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def max_queue @max_queue end |
#max_threads ⇒ Object
Returns the value of attribute max_threads.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def max_threads @max_threads end |
#min_threads ⇒ Object
Returns the value of attribute min_threads.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def min_threads @min_threads end |
#name ⇒ String
Returns The name of the MCP Server.
21 |
# File 'lib/action_mcp/configuration.rb', line 21 attr_writer :name, :version |
#pagination_page_size ⇒ Object
Pagination page size. nil = pagination disabled, positive integer = enabled.
138 139 140 |
# File 'lib/action_mcp/configuration.rb', line 138 def pagination_page_size @pagination_page_size end |
#profiles ⇒ Object
Returns the value of attribute profiles.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def profiles @profiles end |
#protocol_version ⇒ Object
Returns the value of attribute protocol_version.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def protocol_version @protocol_version end |
#resources_subscribe ⇒ Boolean
Returns Whether to subscribe to resources.
21 |
# File 'lib/action_mcp/configuration.rb', line 21 attr_writer :name, :version |
#server_session_store_type ⇒ Object
Get effective server session store type (falls back to global session_store_type)
303 304 305 |
# File 'lib/action_mcp/configuration.rb', line 303 def server_session_store_type @server_session_store_type end |
#session_store_type ⇒ Object
Returns the value of attribute session_store_type.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def session_store_type @session_store_type end |
#tasks_cancel_enabled ⇒ Object
Returns the value of attribute tasks_cancel_enabled.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def tasks_cancel_enabled @tasks_cancel_enabled end |
#tasks_enabled ⇒ Object
Returns the value of attribute tasks_enabled.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def tasks_enabled @tasks_enabled end |
#tasks_list_enabled ⇒ Object
Returns the value of attribute tasks_list_enabled.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def tasks_list_enabled @tasks_list_enabled end |
#validate_structured_content ⇒ Object
Returns the value of attribute validate_structured_content.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def validate_structured_content @validate_structured_content end |
#verbose_logging ⇒ Object
Returns the value of attribute verbose_logging.
22 23 24 |
# File 'lib/action_mcp/configuration.rb', line 22 def verbose_logging @verbose_logging end |
#version ⇒ String
Returns The version of the MCP Server.
21 |
# File 'lib/action_mcp/configuration.rb', line 21 attr_writer :name, :version |
Instance Method Details
#apply_profile_options ⇒ Object
307 308 309 310 311 312 313 314 315 316 |
# File 'lib/action_mcp/configuration.rb', line 307 def profile = @profiles[active_profile] return unless profile && profile[:options] = profile[:options] @list_changed = [:list_changed] unless [:list_changed].nil? @logging_enabled = [:logging_enabled] unless [:logging_enabled].nil? @logging_level = [:logging_level] unless [:logging_level].nil? @resources_subscribe = [:resources_subscribe] unless [:resources_subscribe].nil? end |
#capabilities ⇒ Object
Returns capabilities based on active profile
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/action_mcp/configuration.rb', line 263 def capabilities capabilities = {} profile = @profiles[active_profile] # Check profile configuration instead of registry contents # If profile includes tools (either "all" or specific tools), advertise tools capability capabilities[:tools] = { listChanged: @list_changed } if profile && profile[:tools]&.any? # If profile includes prompts, advertise prompts capability capabilities[:prompts] = { listChanged: @list_changed } if profile && profile[:prompts]&.any? capabilities[:logging] = {} if @logging_enabled # If profile includes resources, advertise resources capability if profile && profile[:resources]&.any? capabilities[:resources] = { subscribe: @resources_subscribe, listChanged: @list_changed } end # Tasks capability (MCP 2025-11-25) if @tasks_enabled tasks_cap = { requests: { tools: { call: {} } } } tasks_cap[:list] = {} if @tasks_list_enabled tasks_cap[:cancel] = {} if @tasks_cancel_enabled capabilities[:tasks] = tasks_cap end capabilities end |
#eager_load_if_needed ⇒ Object
318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/action_mcp/configuration.rb', line 318 def eager_load_if_needed profile = @profiles[active_profile] return unless profile # Check if any component type includes "all" needs_eager_load = profile[:tools]&.include?("all") || profile[:prompts]&.include?("all") || profile[:resources]&.include?("all") return unless needs_eager_load ensure_mcp_components_loaded end |
#filtered_prompts ⇒ Object
Filter prompts based on active profile
247 248 249 250 251 252 |
# File 'lib/action_mcp/configuration.rb', line 247 def filtered_prompts return PromptsRegistry.non_abstract if should_include_all?(:prompts) prompt_names = @profiles[active_profile][:prompts] || [] PromptsRegistry.non_abstract.select { |prompt| prompt_names.include?(prompt.name) } end |
#filtered_resources ⇒ Object
Filter resources based on active profile
255 256 257 258 259 260 |
# File 'lib/action_mcp/configuration.rb', line 255 def filtered_resources return ResourceTemplatesRegistry.non_abstract if should_include_all?(:resources) resource_names = @profiles[active_profile][:resources] || [] ResourceTemplatesRegistry.non_abstract.select { |resource| resource_names.include?(resource.name) } end |
#filtered_tools ⇒ Object
Filter tools based on active profile
237 238 239 240 241 242 243 244 |
# File 'lib/action_mcp/configuration.rb', line 237 def filtered_tools return ToolsRegistry.non_abstract if should_include_all?(:tools) tool_names = @profiles[active_profile][:tools] || [] # Convert tool names to underscored format tool_names = tool_names.map { |name| name.to_s.underscore } ToolsRegistry.non_abstract.select { |tool| tool_names.include?(tool.name.underscore) } end |
#instructions ⇒ Object
Instructions for LLMs about the server’s purpose (joined as string for MCP payload)
118 119 120 121 122 |
# File 'lib/action_mcp/configuration.rb', line 118 def instructions return nil if server_instructions.nil? || server_instructions.empty? server_instructions.join("\n") end |
#load_profiles ⇒ Object
Load custom configuration from Rails configuration
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/action_mcp/configuration.rb', line 169 def load_profiles # First load defaults from the gem @profiles = default_profiles # Preserve any settings that were already set via Rails config preserved_name = @name # Try to load from config/mcp.yml in the Rails app using Rails.config_for begin app_config = Rails.application.config_for(:mcp) raise "Invalid MCP config file" unless app_config.is_a?(Hash) # Extract authentication configuration if present # Handle both symbol and string keys @authentication_methods = Array(app_config[:authentication] || app_config["authentication"]) if app_config[:authentication] || app_config["authentication"] # Extract other top-level configuration settings extract_top_level_settings(app_config) # Extract profiles configuration - merge with defaults instead of replacing # Rails.config_for returns OrderedOptions which uses symbol keys if app_config[:profiles] || app_config["profiles"] # Get profiles with either symbol or string key app_profiles = app_config[:profiles] || app_config["profiles"] # Convert to regular hash and deep symbolize keys if app_profiles.is_a?(ActiveSupport::OrderedOptions) app_profiles = app_profiles.to_h.deep_symbolize_keys elsif app_profiles.respond_to?(:deep_symbolize_keys) app_profiles = app_profiles.deep_symbolize_keys end Rails.logger.debug "[Configuration] Merging profiles: #{app_profiles.inspect}" if @verbose_logging @profiles = @profiles.deep_merge(app_profiles) end rescue StandardError => e # If the config file doesn't exist in the Rails app, just use the defaults Rails.logger.warn "[Configuration] Failed to load MCP config: #{e.class} - #{e.}" # No MCP config found in Rails app, using defaults from gem end # Apply the active profile Rails.logger.info "[ActionMCP] Loaded profiles: #{@profiles.keys.join(', ')}" if @verbose_logging Rails.logger.info "[ActionMCP] Using profile: #{@active_profile}" if @verbose_logging use_profile(@active_profile) # Restore preserved settings @name = preserved_name if preserved_name self end |
#server_info ⇒ Object
Server information (name and version only)
110 111 112 113 114 115 |
# File 'lib/action_mcp/configuration.rb', line 110 def server_info { name: name, version: version } end |
#server_instructions ⇒ Object
Custom getter/setter to ensure array elements are strings
125 126 127 |
# File 'lib/action_mcp/configuration.rb', line 125 def server_instructions @server_instructions end |
#server_instructions=(value) ⇒ Object
129 130 131 |
# File 'lib/action_mcp/configuration.rb', line 129 def server_instructions=(value) @server_instructions = parse_instructions(value) end |
#use_profile(profile_name) ⇒ Object
Switch to a specific profile
223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/action_mcp/configuration.rb', line 223 def use_profile(profile_name) profile_name = profile_name.to_sym unless @profiles.key?(profile_name) Rails.logger.warn "Profile '#{profile_name}' not found, using primary" profile_name = :primary end @active_profile = profile_name self end |