Class: Silas::Mcp::Handler
- Inherits:
-
Object
- Object
- Silas::Mcp::Handler
- Defined in:
- lib/silas/mcp/handler.rb
Overview
JSON-RPC handler for the hosted MCP endpoint. tools/call runs the tool THROUGH the Ledger, so the :agent_sdk path gets the same exactly-once and effect-mode semantics as :ruby_llm. Closes over one turn + its anchor step; authenticated by a per-turn bearer token in the URL query.
Constant Summary collapse
- TOOL_PREFIX =
"mcp__silas__".freeze
Instance Method Summary collapse
-
#call(path:, query_token:, body:) ⇒ Object
Returns [status, json_string_or_nil].
-
#initialize(turn:, step:, tools:, resolver:, token:) ⇒ Handler
constructor
A new instance of Handler.
Constructor Details
#initialize(turn:, step:, tools:, resolver:, token:) ⇒ Handler
Returns a new instance of Handler.
13 14 15 16 17 18 19 |
# File 'lib/silas/mcp/handler.rb', line 13 def initialize(turn:, step:, tools:, resolver:, token:) @turn = turn @step = step @tools = tools @resolver = resolver @token = token end |
Instance Method Details
#call(path:, query_token:, body:) ⇒ Object
Returns [status, json_string_or_nil]. path/query already parsed by the server.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/silas/mcp/handler.rb', line 22 def call(path:, query_token:, body:) return [ 404, error_body("not found") ] unless path == "/mcp/#{@turn.id}" return [ 403, error_body("forbidden") ] unless ActiveSupport::SecurityUtils.secure_compare(query_token.to_s, @token) msg = JSON.parse(body) case msg["method"] when "initialize" then ok(msg["id"], initialize_result(msg)) when "notifications/initialized" then [ 202, nil ] when "tools/list" then ok(msg["id"], { "tools" => @tools.map { |d| mcp_tool(d) } }) when "tools/call" then ok(msg["id"], call_tool(msg)) else rpc_error(msg["id"], -32601, "method not found: #{msg['method']}") end rescue JSON::ParserError [ 400, error_body("bad json") ] end |