mcp_authorization v0.7.1

Quick example

Define reusable types as .rbs files. These are plain RBS -- no comment markers.

On this page

1. Define shared types๐Ÿ”—

Define reusable types as .rbs files. These are plain RBS -- no comment markers.

# sig/shared/error.rbs
type error_code = "not_found"
               | "invalid_transition"
               | "already_at_stage"

type error = {
  success: false,
  error: { code: error_code, message: String, hint: String }
}
# sig/shared/applicant.rbs
type applicant = {
  id: String,
  name: String,
  current_stage: String,
  applied_at: String
}

2. Define a handler๐Ÿ”—

A handler includes McpAuthorization::DSL, imports shared types, and defines its own types. The #: annotation on def call is the input schema -- tag params with @requires to control who sees them.

# app/service/workflows/advance_step.rb
module Workflows
  class AdvanceStep
    # @rbs import error

    include McpAuthorization::DSL

    # @rbs type success = {
    #   success: true,
    #   applicant_id: String,
    #   current_stage: String
    # }

    # @rbs type rerouted_success = {
    #   success: true,
    #   applicant_id: String,
    #   previous_stage: String,
    #   current_stage: String,
    #   audit_trail: Array[String]
    # }

    # @rbs type output = success
    #                   | rerouted_success  @requires(:backward_routing)
    #                   | error

    def description
      if can?(:backward_routing)
        "Advance an applicant to any stage, or reroute them backward."
      else
        "Advance an applicant to the next stage."
      end
    end

    #: (
    #:   applicant_id: String,
    #:   workflow_id: String,
    #:   ?stage_id: String?    @requires(:backward_routing),
    #:   ?reason: String?      @requires(:backward_routing)
    #: ) -> Hash[Symbol, untyped]
    def call(applicant_id:, workflow_id:, stage_id: nil, reason: nil)
      # your logic here
    end
  end
end

3. Declare a tool๐Ÿ”—

# app/mcp/workflows/advance_step_tool.rb
module Workflows
  class AdvanceStepTool < McpAuthorization::Tool
    tool_name "advance_step"
    authorization :manage_workflows
    not_destructive!
    tags "operator"
    dynamic_contract Workflows::AdvanceStep
  end
end

4. See the difference๐Ÿ”—

A user without :backward_routing:

advance_step โ€” "Advance an applicant to the next stage."
  input:  applicant_id, workflow_id
  output: success | error

A user with :backward_routing:

advance_step โ€” "Advance an applicant to any stage, or reroute them backward."
  input:  applicant_id, workflow_id, stage_id, reason
  output: success | rerouted_success | error

Same tool, same endpoint. The feature flag shapes the schema.

Collected from README.md in the repository. Edit it there, not here.