Class: Jazari::Mcp::Handler
- Inherits:
-
Object
- Object
- Jazari::Mcp::Handler
- Defined in:
- lib/jazari/mcp/handler.rb
Overview
Transport-neutral adapter between an MCP action name and the domain.
It knows nothing about transport, authentication, or product naming. The
HOST owns tool identity — one flat action-enum tool per product, named
for that product — and the host authorizes the actor and constructs the
target BEFORE calling here. This class only maps action names onto domain
calls and shapes the reply.
That split is deliberate: two products sharing this handler still present their own tool, their own subject vocabulary, and their own permissions.
Class Method Summary collapse
-
.actions_for(scope) ⇒ Object
Actions are declared once, in Mcp::Actions, so the schema a host publishes and the behaviour implemented here cannot drift apart.
Instance Method Summary collapse
- #call(action:, target:, arguments: {}) ⇒ Object
- #handle_add_item(target, args) ⇒ Object
- #handle_check_item(target, args) ⇒ Object
- #handle_evidence(_target, args) ⇒ Object
- #handle_finish(_target, args) ⇒ Object
-
#handle_get(target, _args) ⇒ Object
-- read ---------------------------------------------------------------.
- #handle_last_run(target, _args) ⇒ Object
- #handle_remove_item(target, args) ⇒ Object
-
#handle_reset(target, args) ⇒ Object
Destructive: it discards the operator's customization.
-
#handle_set(target, args) ⇒ Object
-- runbook ------------------------------------------------------------.
-
#handle_start(target, args) ⇒ Object
-- runs ---------------------------------------------------------------.
- #handle_tick(_target, args) ⇒ Object
Class Method Details
Instance Method Details
#call(action:, target:, arguments: {}) ⇒ Object
24 25 26 27 28 29 30 31 32 33 |
# File 'lib/jazari/mcp/handler.rb', line 24 def call(action:, target:, arguments: {}) args = symbolize(arguments) descriptor = Actions.fetch(action) # raises on an unknown action reply(public_send(:"handle_#{descriptor.name}", target, args)) rescue Jazari::Error => error # The closed taxonomy crosses the wire as a code, never as a message # that could disclose a record, a query, or whether a target exists. { ok: false, error: error.code } end |
#handle_add_item(target, args) ⇒ Object
54 55 56 57 |
# File 'lib/jazari/mcp/handler.rb', line 54 def handle_add_item(target, args) Operations.add_item(target: target, expected_revision: args[:expected_revision], text: args[:text], required: args.fetch(:required, true)) end |
#handle_check_item(target, args) ⇒ Object
64 65 66 67 |
# File 'lib/jazari/mcp/handler.rb', line 64 def handle_check_item(target, args) Operations.check_item(target: target, expected_revision: args[:expected_revision], item_id: args[:item_id], done: args[:done]) end |
#handle_evidence(_target, args) ⇒ Object
93 94 95 96 97 98 |
# File 'lib/jazari/mcp/handler.rb', line 93 def handle_evidence(_target, args) run = Runs.attach_evidence(run: args.fetch(:run_id), expected_revision: args[:expected_revision], item_id: args[:item_id], kind: args.fetch(:kind), value: args.fetch(:value), actor_ref: args[:actor_ref]) run_view(run) end |
#handle_finish(_target, args) ⇒ Object
100 101 102 103 104 |
# File 'lib/jazari/mcp/handler.rb', line 100 def handle_finish(_target, args) run = Runs.close(run: args.fetch(:run_id), expected_revision: args[:expected_revision], outcome: args.fetch(:outcome, "completed")) run_view(run) end |
#handle_get(target, _args) ⇒ Object
-- read ---------------------------------------------------------------
37 |
# File 'lib/jazari/mcp/handler.rb', line 37 def handle_get(target, _args) = Operations.resolve(target: target) |
#handle_last_run(target, _args) ⇒ Object
39 40 41 42 |
# File 'lib/jazari/mcp/handler.rb', line 39 def handle_last_run(target, _args) run = Runs.last(target: target) run ? run_view(run) : { last_run: nil } end |
#handle_remove_item(target, args) ⇒ Object
59 60 61 62 |
# File 'lib/jazari/mcp/handler.rb', line 59 def handle_remove_item(target, args) Operations.remove_item(target: target, expected_revision: args[:expected_revision], item_id: args[:item_id]) end |
#handle_reset(target, args) ⇒ Object
Destructive: it discards the operator's customization. The host must gate this on explicit confirmation before calling.
71 72 73 74 75 76 77 |
# File 'lib/jazari/mcp/handler.rb', line 71 def handle_reset(target, args) unless args[:confirm] == true raise InvalidRunbook, "reset discards the customization and requires confirm: true" end Operations.reset(target: target, expected_revision: args[:expected_revision]) end |
#handle_set(target, args) ⇒ Object
-- runbook ------------------------------------------------------------
46 47 48 49 50 51 52 |
# File 'lib/jazari/mcp/handler.rb', line 46 def handle_set(target, args) Operations.customize( target: target, expected_revision: args[:expected_revision], topic: args[:topic], description: args[:description].to_s, checklist: args.fetch(:checklist, []) ) end |
#handle_start(target, args) ⇒ Object
-- runs ---------------------------------------------------------------
81 82 83 84 |
# File 'lib/jazari/mcp/handler.rb', line 81 def handle_start(target, args) result = Runs.open(target: target, actor_ref: args.fetch(:actor_ref)) run_view(result[:run]).merge(created: result[:created], idempotent_reuse: result[:idempotent_reuse]) end |
#handle_tick(_target, args) ⇒ Object
86 87 88 89 90 91 |
# File 'lib/jazari/mcp/handler.rb', line 86 def handle_tick(_target, args) run = Runs.tick(run: args.fetch(:run_id), expected_revision: args[:expected_revision], item_id: args[:item_id], done: args.fetch(:done, true), actor_ref: args[:actor_ref], note: args[:note]) run_view(run) end |