Quick example
Define reusable types as .rbs files. These are plain RBS -- no comment markers.
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
end3. 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
end4. See the difference๐
A user without :backward_routing:
advance_step โ "Advance an applicant to the next stage."
input: applicant_id, workflow_id
output: success | errorA 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 | errorSame tool, same endpoint. The feature flag shapes the schema.
Collected from README.md in the repository. Edit it there, not here.