Class: McpAuthorization::ToolRegistry

Inherits:
Object
  • Object
show all
Defined in:
lib/mcp_authorization/tool_registry.rb

Overview

Global registry of all McpAuthorization::Tool subclasses.

Tools self-register via the inherited hook in Tool, so there is no manual registration step — defining a class that inherits from Tool is enough.

The registry is the entry point for two main operations:

  • Listinglist_tools returns JSON-serialisable tool definitions filtered by domain and the current user’s permissions.

  • Materializingtool_classes_for returns concrete MCP::Tool subclasses with per-user schemas baked in, ready to be handed to an MCP::Server for request handling.

Class Method Summary collapse

Class Method Details

.ensure_tools_loaded!Object

Force-loads tool directories so tool classes self-register. : () -> void



36
37
38
39
40
41
42
43
44
# File 'lib/mcp_authorization/tool_registry.rb', line 36

def ensure_tools_loaded!
  return if @registered_tools&.any?
  return unless defined?(Rails)

  McpAuthorization.config.tool_paths.each do |path|
    full_path = Rails.root.join(path)
    Rails.autoloaders.main.eager_load_dir(full_path) if File.directory?(full_path)
  end
end

.find_tool(name) ⇒ Object

Look up a tool by its MCP tool name across all domains. : (String) -> singleton(McpAuthorization::Tool)?



78
79
80
# File 'lib/mcp_authorization/tool_registry.rb', line 78

def find_tool(name)
  registered_tools.find { |t| t.tool_name == name }
end

.list_tools(domain:, server_context:) ⇒ Object

Tool definitions for tools/list, filtered by domain and permissions. : (domain: String, server_context: untyped) -> Array[Hash[Symbol, untyped]]



59
60
61
62
63
64
# File 'lib/mcp_authorization/tool_registry.rb', line 59

def list_tools(domain:, server_context:)
  candidates = tools_by_domain[domain] || []
  candidates.filter_map do |tool_class|
    tool_class.to_mcp_definition(server_context: server_context)
  end
end

.register(tool_class) ⇒ Object

Register a tool class. Called automatically by Tool.inherited. : (Class) -> void



21
22
23
24
# File 'lib/mcp_authorization/tool_registry.rb', line 21

def register(tool_class)
  tools = (@registered_tools ||= [])
  tools << tool_class unless tools.include?(tool_class)
end

.registered_toolsObject

All registered tool classes. Triggers eager loading on first access. : () -> Array



28
29
30
31
32
# File 'lib/mcp_authorization/tool_registry.rb', line 28

def registered_tools
  tools = (@registered_tools ||= [])
  ensure_tools_loaded! if tools.empty?
  tools
end

.reset!Object

Clear the registry. Called by the Engine’s reloader on code change. : () -> void



84
85
86
# File 'lib/mcp_authorization/tool_registry.rb', line 84

def reset!
  @registered_tools = []
end

.tool_classes_for(domain:, server_context:) ⇒ Object

Concrete MCP::Tool subclasses with per-user schemas baked in. : (domain: String, server_context: untyped) -> Array



68
69
70
71
72
73
74
# File 'lib/mcp_authorization/tool_registry.rb', line 68

def tool_classes_for(domain:, server_context:)
  candidates = tools_by_domain[domain] || []
  candidates.filter_map do |tool_class|
    next unless tool_class.permitted?(server_context)
    tool_class.materialize_for(server_context)
  end
end

.tools_by_domainObject

Groups registered tools by their domain tags. : () -> Hash[String, Array]



48
49
50
51
52
53
54
55
# File 'lib/mcp_authorization/tool_registry.rb', line 48

def tools_by_domain
  initial = Hash.new { |h, k| h[k] = [] } #: Hash[String, Array[singleton(McpAuthorization::Tool)]]
  registered_tools.each_with_object(initial) do |tool_class, map|
    (tool_class._tags || ["default"]).each do |tag|
      map[tag] << tool_class
    end
  end
end