Class: McpToolkit::Configuration

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

Overview

The single, injectable configuration object for an app's MCP server.

Generic but OPINIONATED: every setting has a sensible, vendor-neutral default, so a satellite needs to override only a handful of values. The two things an app almost always sets are server_name and the auth wiring (central_app_url for a satellite, or token_authenticator for the authority).

Whether ANY scope is required is decided PER TOOL, not per app: a resource declares required_permissions_scope "notifications__read" (or the registry declares default_required_permissions_scope once for all resources). There is no app-wide permission setting here.

Accessed through McpToolkit.config (or MCPToolkit.config) and mutated in a McpToolkit.configure { |c| ... } block.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration

Vendor-neutral defaults; apps override the auth wiring + identity as needed.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/mcp_toolkit/configuration.rb', line 155

def initialize
  @server_name = "mcp-server"
  @server_version = "1.0.0"
  @server_instructions = nil

  @serializer_base = nil # set lazily in #serializer_base to avoid load-order issues

  @auth_role = :satellite
  @central_app_url = nil
  @introspect_path = "/mcp/tokens/introspect"
  @introspection_cache_ttl = 45
  @introspection_timeout = 10
  @account_resolver = ->() {  }

  @token_authenticator = nil

  @cache_store = ActiveSupport::Cache::MemoryStore.new
  @session_ttl = 3600 # 1 hour

  @sql_sanitizer = McpToolkit::SqlSanitizer.new

  @protocol_version = nil
  @parent_controller = "ActionController::Base"
  @account_meta_key = "mcp-toolkit/account-id"
  @account_id_header = "X-MCP-Account-ID"

  @registry = McpToolkit::Registry.new
end

Instance Attribute Details

#account_id_headerString

Returns:

  • (String)


144
145
146
# File 'lib/mcp_toolkit/configuration.rb', line 144

def 
  @account_id_header
end

#account_meta_keyString

Header / meta-key constants. Vendor-neutral defaults; an app on a specific central authority can rename them to match that authority's convention. These are the selectors a superuser/multi-account token uses to pin the active account.

Returns:

  • (String)


142
143
144
# File 'lib/mcp_toolkit/configuration.rb', line 142

def 
  @account_meta_key
end

#account_resolver#call

Resolves the central account id to the satellite's LOCAL scope root.

A satellite stores rows keyed by the central app's account id (synced via Kafka etc.). This callable receives the resolved central account_id and MUST return the object that Resource#scope blocks root on (typically the local Account). Return nil to signal "no local account" (=> Unauthorized).

c. = ->() { Account.find_by(synced_id: ) }

Defaults to the identity function: the resolved central account id is used directly as the scope root (suitable for an app whose scope blocks key on the central id, or for the authority itself).

Returns:

  • (#call)


78
79
80
# File 'lib/mcp_toolkit/configuration.rb', line 78

def 
  @account_resolver
end

#auth_roleSymbol

Returns :satellite (introspect tokens against a central app) or :authority (be the introspection provider + authenticate local tokens). A single app MAY be both — set :authority and still configure a central_app_url if it also exposes its own tools as a satellite.

Returns:

  • (Symbol)

    :satellite (introspect tokens against a central app) or :authority (be the introspection provider + authenticate local tokens). A single app MAY be both — set :authority and still configure a central_app_url if it also exposes its own tools as a satellite.



49
50
51
# File 'lib/mcp_toolkit/configuration.rb', line 49

def auth_role
  @auth_role
end

#cache_storeActiveSupport::Cache::Store, #read

The cache store backing sessions and introspection results. Must satisfy the ActiveSupport::Cache::Store contract (read/write/delete with expires_in:). Defaults to an in-process MemoryStore; a real deployment should set this to Rails.cache (or any shared store) so sessions survive across Puma workers.

Returns:

  • (ActiveSupport::Cache::Store, #read)


106
107
108
# File 'lib/mcp_toolkit/configuration.rb', line 106

def cache_store
  @cache_store
end

#central_app_urlString?

Returns base URL of the central auth app. The satellite POSTs <central_app_url>/mcp/tokens/introspect.

Returns:

  • (String, nil)

    base URL of the central auth app. The satellite POSTs <central_app_url>/mcp/tokens/introspect.



55
56
57
# File 'lib/mcp_toolkit/configuration.rb', line 55

def central_app_url
  @central_app_url
end

#introspect_pathString?

Returns the introspect path appended to central_app_url.

Returns:

  • (String, nil)

    the introspect path appended to central_app_url.



57
58
59
# File 'lib/mcp_toolkit/configuration.rb', line 57

def introspect_path
  @introspect_path
end

#introspection_cache_ttlInteger

Returns seconds to cache an introspection result (positive AND negative) so a burst of tool calls does not hammer the central app.

Returns:

  • (Integer)

    seconds to cache an introspection result (positive AND negative) so a burst of tool calls does not hammer the central app.



60
61
62
# File 'lib/mcp_toolkit/configuration.rb', line 60

def introspection_cache_ttl
  @introspection_cache_ttl
end

#introspection_timeoutInteger

Returns HTTP open/read timeout for the introspection call.

Returns:

  • (Integer)

    HTTP open/read timeout for the introspection call.



62
63
64
# File 'lib/mcp_toolkit/configuration.rb', line 62

def introspection_timeout
  @introspection_timeout
end

#parent_controllerString

The parent class (as a String, resolved via constantize) of the gem-provided McpToolkit::ServerController that McpToolkit::Engine mounts. Doorkeeper-style indirection so a satellite mounting the engine can keep ActionController::Base (NOT ::API) — e.g. for a logstasher helper_method hook — by setting c.parent_controller = "ApplicationController".

Returns:

  • (String)


134
135
136
# File 'lib/mcp_toolkit/configuration.rb', line 134

def parent_controller
  @parent_controller
end

#protocol_versionString?

Returns protocol version to pin on the underlying MCP::Server. nil lets the gem negotiate (recommended). Set only to force an older spec.

Returns:

  • (String, nil)

    protocol version to pin on the underlying MCP::Server. nil lets the gem negotiate (recommended). Set only to force an older spec.



125
126
127
# File 'lib/mcp_toolkit/configuration.rb', line 125

def protocol_version
  @protocol_version
end

#registryMcpToolkit::Registry

The resource registry for this configuration. Each config carries its own so tests (and, in principle, multiple mounted servers) don't collide. The process-wide convenience McpToolkit.registry delegates to the active config's registry.



152
153
154
# File 'lib/mcp_toolkit/configuration.rb', line 152

def registry
  @registry
end

#serializer_baseObject

The serializer base, lazily defaulting to the gem's bundled DSL base. Lazy so McpToolkit::Serializer::Base is referenced after it has been required, regardless of file load order.



187
188
189
# File 'lib/mcp_toolkit/configuration.rb', line 187

def serializer_base
  @serializer_base ||= McpToolkit::Serializer::Base
end

#server_instructionsString?

Returns human-readable instructions returned on initialize.

Returns:

  • (String, nil)

    human-readable instructions returned on initialize.



26
27
28
# File 'lib/mcp_toolkit/configuration.rb', line 26

def server_instructions
  @server_instructions
end

#server_nameString

Returns the MCP server name advertised in initialize.

Returns:

  • (String)

    the MCP server name advertised in initialize.



22
23
24
# File 'lib/mcp_toolkit/configuration.rb', line 22

def server_name
  @server_name
end

#server_versionString

Returns the MCP server version advertised in initialize.

Returns:

  • (String)

    the MCP server version advertised in initialize.



24
25
26
# File 'lib/mcp_toolkit/configuration.rb', line 24

def server_version
  @server_version
end

#session_ttlInteger

Returns session sliding-TTL in seconds.

Returns:

  • (Integer)

    session sliding-TTL in seconds.



109
110
111
# File 'lib/mcp_toolkit/configuration.rb', line 109

def session_ttl
  @session_ttl
end

#sql_sanitizer#sanitize_sql_like

Escapes LIKE wildcards in matches / does_not_match filter values so they match literally. Must respond to sanitize_sql_like(string). Defaults to the ActiveRecord-backed McpToolkit::SqlSanitizer; a non-Rails host (or a test) can inject its own.

Returns:

  • (#sanitize_sql_like)


119
120
121
# File 'lib/mcp_toolkit/configuration.rb', line 119

def sql_sanitizer
  @sql_sanitizer
end

#token_authenticator#call?

Looks up + verifies a plaintext bearer token locally, returning a token object (duck-typed, see below) or nil. This is the authority's McpToken.authenticate(plaintext) equivalent. Required for the :authority role; unused by a pure satellite.

c.token_authenticator = ->(plaintext) { McpToken.authenticate(plaintext) }

The returned token object must respond to the methods McpToolkit::Auth::Authority#introspection_payload reads (see that module for the contract): kind, account_id, account_ids, expires_at, scopes. A touch_last_used! method, if present, is called.

Returns:

  • (#call, nil)


95
96
97
# File 'lib/mcp_toolkit/configuration.rb', line 95

def token_authenticator
  @token_authenticator
end

Instance Method Details

#authority?Boolean

Returns whether this app authenticates tokens locally / answers introspection.

Returns:

  • (Boolean)

    whether this app authenticates tokens locally / answers introspection.



198
199
200
# File 'lib/mcp_toolkit/configuration.rb', line 198

def authority?
  auth_role.to_sym == :authority
end

#introspect_urlObject

Full introspection URL the satellite POSTs to. Raises a clear error if the central URL was never configured.



204
205
206
207
208
# File 'lib/mcp_toolkit/configuration.rb', line 204

def introspect_url
  raise McpToolkit::Errors::ConfigurationError, "central_app_url is not configured" if central_app_url.to_s.empty?

  "#{central_app_url.chomp("/")}#{introspect_path}"
end

#satellite?Boolean

Returns whether this app introspects tokens against a central app.

Returns:

  • (Boolean)

    whether this app introspects tokens against a central app.



192
193
194
# File 'lib/mcp_toolkit/configuration.rb', line 192

def satellite?
  auth_role.to_sym == :satellite || central_app_url
end