Class: Hitch::MCP::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/hitch/mcp/configuration.rb

Constant Summary collapse

DEFAULT_MAX_REQUEST_BYTES =
1_048_576
DEFAULT_MAX_RESULT_BYTES =
1_048_576
DEFAULT_REQUEST_LIMIT =
{ to: 120, within: 60 }.freeze
SETTING =
"mcp.rate_limit_store"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration

Returns a new instance of Configuration.



14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/hitch/mcp/configuration.rb', line 14

def initialize
  @enabled = false
  @registry = nil
  @registry_snapshot = nil
  @registry_mutex = Mutex.new
  @server_info = nil
  @normalized_server_info = nil
  @scope_resolver = nil
  @request_limit = DEFAULT_REQUEST_LIMIT
  @rate_limit_store = nil
  @max_request_bytes = DEFAULT_MAX_REQUEST_BYTES
  @max_result_bytes = DEFAULT_MAX_RESULT_BYTES
end

Instance Attribute Details

#enabledObject

Returns the value of attribute enabled.



11
12
13
# File 'lib/hitch/mcp/configuration.rb', line 11

def enabled
  @enabled
end

#max_request_bytesObject

Returns the value of attribute max_request_bytes.



11
12
13
# File 'lib/hitch/mcp/configuration.rb', line 11

def max_request_bytes
  @max_request_bytes
end

#max_result_bytesObject

Returns the value of attribute max_result_bytes.



11
12
13
# File 'lib/hitch/mcp/configuration.rb', line 11

def max_result_bytes
  @max_result_bytes
end

#registryObject

Returns the value of attribute registry.



11
12
13
# File 'lib/hitch/mcp/configuration.rb', line 11

def registry
  @registry
end

#request_limitObject

Returns the value of attribute request_limit.



11
12
13
# File 'lib/hitch/mcp/configuration.rb', line 11

def request_limit
  @request_limit
end

#scope_resolverObject

Returns the value of attribute scope_resolver.



11
12
13
# File 'lib/hitch/mcp/configuration.rb', line 11

def scope_resolver
  @scope_resolver
end

Instance Method Details

#prepare_registry!(supported_scopes:) ⇒ Object

Framework lifecycle, not a host knob: the engine's to_prepare hook rebuilds the snapshot; the endpoint reads it per request.



136
137
138
139
140
141
142
143
144
# File 'lib/hitch/mcp/configuration.rb', line 136

def prepare_registry!(supported_scopes:)
  @registry_mutex.synchronize do
    @registry_snapshot = nil
    @registry_snapshot = Hitch::MCP::Internal::RegistryRuntime.build_snapshot(
      registry_name: @registry,
      supported_scopes:
    )
  end
end

#rate_limit_storeObject



92
93
94
# File 'lib/hitch/mcp/configuration.rb', line 92

def rate_limit_store
  Hitch::RateLimitStore.resolve(@rate_limit_store)
end

#rate_limit_store=(value) ⇒ Object

Nil means "whatever this application already configured", which is what ActionController::RateLimiting does. Hosts that want MCP admission kept out of their general cache pass their own ActiveSupport::Cache store.



88
89
90
# File 'lib/hitch/mcp/configuration.rb', line 88

def rate_limit_store=(value)
  @rate_limit_store = Hitch::RateLimitStore.validate!(value, setting: SETTING)
end

#registry_snapshot!Object



146
147
148
149
150
# File 'lib/hitch/mcp/configuration.rb', line 146

def registry_snapshot!
  @registry_mutex.synchronize do
    @registry_snapshot || raise(ArgumentError, "MCP registry is unavailable")
  end
end

#server_infoObject

Returns the validated, frozen, string-keyed identity hash. Normalized lazily so the reloadable validator constant is only touched after boot; the engine's to_prepare hook forces this read, so a malformed value fails the boot rather than the first request.



53
54
55
56
57
58
59
60
# File 'lib/hitch/mcp/configuration.rb', line 53

def server_info
  @normalized_server_info ||= Hitch::MCP::Internal::ServerInfo.normalize(
    @server_info || {
      "name" => Rails.application.class.module_parent_name.underscore.dasherize,
      "version" => "1.0.0"
    }
  )
end

#server_info=(value) ⇒ Object



62
63
64
65
66
67
68
69
70
71
# File 'lib/hitch/mcp/configuration.rb', line 62

def server_info=(value)
  unless value.nil? || value.is_a?(Hash)
    raise ArgumentError, "mcp.server_info must be a Hash"
  end

  # New value first: a reader interleaving between these two writes
  # re-memoizes at worst the NEW value, never pins the old one.
  @server_info = value
  @normalized_server_info = nil
end

#validate!Object



112
113
114
115
116
117
118
119
120
# File 'lib/hitch/mcp/configuration.rb', line 112

def validate!
  return true unless enabled

  unless registry.is_a?(String) && !registry.empty?
    raise ArgumentError, "mcp.registry is required when mcp.enabled is true"
  end

  true
end

#validate_rate_limit_store!Object

Resolved separately from validate! because the application's cache store is assembled by Rails' own initializers; this runs from to_prepare, once config.cache_store is settled. The raw setting is passed, not the resolving reader: reading it here would ask ActionController::Base for the default store during initialization, which is the premature load this avoids.



128
129
130
131
132
# File 'lib/hitch/mcp/configuration.rb', line 128

def validate_rate_limit_store!
  return true unless Rails.env.production?

  Hitch::RateLimitStore.assert_shared_at_boot!(@rate_limit_store, setting: SETTING)
end