Class: McpAuthorization::FacadeBuilder
- Inherits:
-
Object
- Object
- McpAuthorization::FacadeBuilder
- Defined in:
- lib/mcp_authorization/facade_builder.rb
Overview
Builds grouped facade tools for a faceted domain.
A facade is a per-request synthetic MCP::Tool subclass — one per
non-empty category — whose description carries routing signal only
(group summary + RBAC-filtered tool one-liners) and whose inputSchema
defers per-tool argument schemas out of the selection prompt. A
tools/call on a facade names the inner tool (+tool_name+) and its
arguments; dispatch resolves the real tool through
ToolRegistry.tool_class_for — re-running permitted? — and delegates
to its materialized call, so authorization, gating, and input/output
filtering apply exactly as if the tool had been called directly.
Facades are never registered in ToolRegistry; they are produced on
demand by facades_for. See docs/designs/tool-grouping-facades.md.
Defined Under Namespace
Classes: FacadeNameCollisionError, UncategorizedToolError
Constant Summary collapse
- FALLBACK_CATEGORY =
Fallback group for uncategorized tools (default mode).
:uncategorized
Class Method Summary collapse
-
.facade_for(domain:, name:, server_context:) ⇒ Object
A single facade by its tool name (e.g. "orders_tools"), or nil when the name matches no non-empty group for this caller.
-
.facade_name(category, config) ⇒ Object
The MCP tool name a category's facade is exposed under.
-
.facades_for(domain:, server_context:) ⇒ Object
All facades for a domain, one per non-empty group the caller has at least one permitted tool in.
Class Method Details
.facade_for(domain:, name:, server_context:) ⇒ Object
A single facade by its tool name (e.g. "orders_tools"), or nil when
the name matches no non-empty group for this caller. Used by
tools/call routing so one call doesn't build every facade.
: (domain: String, name: String, server_context: untyped) -> singleton(MCP::Tool)?
49 50 51 52 53 54 55 56 57 |
# File 'lib/mcp_authorization/facade_builder.rb', line 49 def facade_for(domain:, name:, server_context:) config = McpAuthorization.config.facet_config(domain) return nil unless config group_tools(domain, server_context, config).each do |category, tools| return build_facade(domain, category, tools, server_context, config) if facade_name(category, config) == name end nil end |
.facade_name(category, config) ⇒ Object
The MCP tool name a category's facade is exposed under. The suffix is
per-domain (facet config facade_suffix, default "tools"): category
:orders → orders_tools (or orders_hire, etc.).
: (Symbol, Hash[Symbol, untyped]) -> String
63 64 65 66 |
# File 'lib/mcp_authorization/facade_builder.rb', line 63 def facade_name(category, config) suffix = config[:facade_suffix] || Configuration::DEFAULT_FACADE_SUFFIX "#{category}_#{suffix}" end |
.facades_for(domain:, server_context:) ⇒ Object
All facades for a domain, one per non-empty group the caller has at
least one permitted tool in. Empty groups produce no facade — which
also guarantees no facade ever advertises an empty enum.
: (domain: String, server_context: untyped) -> Array
36 37 38 39 40 41 42 43 |
# File 'lib/mcp_authorization/facade_builder.rb', line 36 def facades_for(domain:, server_context:) config = McpAuthorization.config.facet_config(domain) return [] unless config group_tools(domain, server_context, config).map do |category, tools| build_facade(domain, category, tools, server_context, config) end end |