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.
-
#allowed_origins ⇒ Object
Returns the value of attribute allowed_origins.
-
#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.
-
#mcp_apps_enabled ⇒ Object
Returns the value of attribute mcp_apps_enabled.
-
#mcp_apps_views_path ⇒ Object
Returns the value of attribute mcp_apps_views_path.
-
#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.
-
#tasks_result_poll_interval ⇒ Object
Returns the value of attribute tasks_result_poll_interval.
-
#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.
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 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/action_mcp/configuration.rb', line 58 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-11-25" # Tasks defaults (MCP 2025-11-25) @tasks_enabled = false @tasks_list_enabled = true @tasks_cancel_enabled = true @tasks_result_poll_interval = 0.25 # MCP Apps extension defaults to explicit opt-in. @mcp_apps_enabled = false # Directory holding compiled view bundles + manifest.json, relative to # Rails.root unless absolute. @mcp_apps_views_path = ".action_mcp/views" # 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 # 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 = "/" # Browser origins allowed to reach a local server. Remote deployments must # explicitly add their trusted origin hosts. @allowed_origins = %w[localhost 127.0.0.1 ::1].freeze end |
Instance Attribute Details
#active_profile ⇒ Object
Get active profile (considering thread-local override)
181 182 183 |
# File 'lib/action_mcp/configuration.rb', line 181 def active_profile @active_profile end |
#allowed_identity_keys ⇒ Object
Returns the value of attribute allowed_identity_keys.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def allowed_identity_keys @allowed_identity_keys end |
#allowed_origins ⇒ Object
Returns the value of attribute allowed_origins.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def allowed_origins @allowed_origins end |
#authentication_methods ⇒ Object
Returns the value of attribute authentication_methods.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def authentication_methods @authentication_methods end |
#base_path ⇒ Object
Returns the value of attribute base_path.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def base_path @base_path end |
#client_session_store_type ⇒ Object
Get effective client session store type (falls back to global session_store_type)
321 322 323 |
# File 'lib/action_mcp/configuration.rb', line 321 def client_session_store_type @client_session_store_type end |
#connects_to ⇒ Object
Returns the value of attribute connects_to.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def connects_to @connects_to end |
#gateway_class ⇒ Object
Returns the value of attribute gateway_class.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def gateway_class @gateway_class end |
#list_changed ⇒ Boolean
Returns Whether to send a listChanged notification for tools, prompts, and resources.
20 |
# File 'lib/action_mcp/configuration.rb', line 20 attr_writer :name, :version |
#logging_enabled ⇒ Boolean
Returns Whether logging is enabled.
20 |
# File 'lib/action_mcp/configuration.rb', line 20 attr_writer :name, :version |
#logging_level ⇒ Symbol
Returns The logging level.
20 |
# File 'lib/action_mcp/configuration.rb', line 20 attr_writer :name, :version |
#max_queue ⇒ Object
Returns the value of attribute max_queue.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def max_queue @max_queue end |
#max_threads ⇒ Object
Returns the value of attribute max_threads.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def max_threads @max_threads end |
#mcp_apps_enabled ⇒ Object
Returns the value of attribute mcp_apps_enabled.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def mcp_apps_enabled @mcp_apps_enabled end |
#mcp_apps_views_path ⇒ Object
Returns the value of attribute mcp_apps_views_path.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def mcp_apps_views_path @mcp_apps_views_path end |
#min_threads ⇒ Object
Returns the value of attribute min_threads.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def min_threads @min_threads end |
#name ⇒ String
Returns The name of the MCP Server.
20 |
# File 'lib/action_mcp/configuration.rb', line 20 attr_writer :name, :version |
#pagination_page_size ⇒ Object
Pagination page size. nil = pagination disabled, positive integer = enabled.
149 150 151 |
# File 'lib/action_mcp/configuration.rb', line 149 def pagination_page_size @pagination_page_size end |
#profiles ⇒ Object
Returns the value of attribute profiles.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def profiles @profiles end |
#protocol_version ⇒ Object
Returns the value of attribute protocol_version.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def protocol_version @protocol_version end |
#resources_subscribe ⇒ Boolean
Returns Whether to subscribe to resources.
20 |
# File 'lib/action_mcp/configuration.rb', line 20 attr_writer :name, :version |
#server_session_store_type ⇒ Object
Get effective server session store type (falls back to global session_store_type)
326 327 328 |
# File 'lib/action_mcp/configuration.rb', line 326 def server_session_store_type @server_session_store_type end |
#session_store_type ⇒ Object
Returns the value of attribute session_store_type.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def session_store_type @session_store_type end |
#tasks_cancel_enabled ⇒ Object
Returns the value of attribute tasks_cancel_enabled.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def tasks_cancel_enabled @tasks_cancel_enabled end |
#tasks_enabled ⇒ Object
Returns the value of attribute tasks_enabled.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def tasks_enabled @tasks_enabled end |
#tasks_list_enabled ⇒ Object
Returns the value of attribute tasks_list_enabled.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def tasks_list_enabled @tasks_list_enabled end |
#tasks_result_poll_interval ⇒ Object
Returns the value of attribute tasks_result_poll_interval.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def tasks_result_poll_interval @tasks_result_poll_interval end |
#verbose_logging ⇒ Object
Returns the value of attribute verbose_logging.
21 22 23 |
# File 'lib/action_mcp/configuration.rb', line 21 def verbose_logging @verbose_logging end |
#version ⇒ String
Returns The version of the MCP Server.
20 |
# File 'lib/action_mcp/configuration.rb', line 20 attr_writer :name, :version |
Instance Method Details
#apply_profile_options ⇒ Object
330 331 332 333 334 335 336 337 338 339 340 |
# File 'lib/action_mcp/configuration.rb', line 330 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? @mcp_apps_enabled = boolean_config_value([:mcp_apps_enabled]) unless [:mcp_apps_enabled].nil? end |
#capabilities ⇒ Object
Returns capabilities based on active profile
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/action_mcp/configuration.rb', line 280 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 capabilities[:completions] = {} # 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 if @mcp_apps_enabled capabilities[:extensions] ||= {} capabilities[:extensions][Apps::EXTENSION_KEY] = Apps.extension_settings end capabilities end |
#eager_load_if_needed ⇒ Object
342 343 344 345 346 347 348 349 350 351 352 353 354 |
# File 'lib/action_mcp/configuration.rb', line 342 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
264 265 266 267 268 269 |
# File 'lib/action_mcp/configuration.rb', line 264 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
272 273 274 275 276 277 |
# File 'lib/action_mcp/configuration.rb', line 272 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
254 255 256 257 258 259 260 261 |
# File 'lib/action_mcp/configuration.rb', line 254 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)
129 130 131 132 133 |
# File 'lib/action_mcp/configuration.rb', line 129 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
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 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/action_mcp/configuration.rb', line 186 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)
121 122 123 124 125 126 |
# File 'lib/action_mcp/configuration.rb', line 121 def server_info { name: name, version: version } end |
#server_instructions ⇒ Object
Custom getter/setter to ensure array elements are strings
136 137 138 |
# File 'lib/action_mcp/configuration.rb', line 136 def server_instructions @server_instructions end |
#server_instructions=(value) ⇒ Object
140 141 142 |
# File 'lib/action_mcp/configuration.rb', line 140 def server_instructions=(value) @server_instructions = parse_instructions(value) end |
#use_profile(profile_name) ⇒ Object
Switch to a specific profile
240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/action_mcp/configuration.rb', line 240 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 |