3. Hide a tool behind an account feature, not a role
Visibility shouldn't depend on the user's role but on whether their account has SMS provisioned. RBAC is the wrong axis.
Problem. Visibility shouldn't depend on the user's role but on whether their account has SMS provisioned. RBAC is the wrong axis.
Solution. Use gate :predicate, :value. It calls server_context.{predicate}?(value) instead of current_user.can?. Gates AND with authorization.
class BulkSendSmsTool < McpAuthorization::Tool
tool_name "bulk_send_sms"
authorization :communications # RBAC: user must be allowed to message
gate :feature, :sms # AND account must have SMS configured
dynamic_contract Comms::BulkSendSms
end# Your server context object needs the matching predicate:
class ServerContext
def feature?(name) = account[:features].include?(name.to_s)
endResult. The tool appears only when the user passes the RBAC check and server_context.feature?(:sms) returns true. If your context doesn't define feature? at all, the gate fails open (with a dev-mode warning) โ so a missing predicate never silently hides everything.
Collected from COOKBOOK.md in the repository. Edit it there, not here.