Class: SolidLoop::Mcp::Toolset
- Inherits:
-
Object
- Object
- SolidLoop::Mcp::Toolset
- Includes:
- Transport
- Defined in:
- lib/solid_loop/mcp/toolset.rb
Overview
In-process MCP server: a toolset IS both the server and its transport.
deliver dispatches initialize / tools/list / tools/call without HTTP,
preserving the JSON boundary (string keys) so local and remote behavior
cannot drift. See docs/guides/mcp_transports.md.
class SearchTools < SolidLoop::Mcp::Toolset
server_name "search"
tool "fetch_url",
description: "Fetch a URL and return a text summary",
input_schema: { type: "object", properties: {} } do |args, ctx|
Search::Fetch.call(loop: ctx.loop).to_json
end
end
Defined Under Namespace
Modules: SchemaValidator Classes: PromptDefinition, PublicToolError, ToolDefinition
Constant Summary collapse
- OPAQUE_TOOL_ERROR =
Opaque text returned for an unexpected internal exception.
"Internal error executing tool".freeze
Class Method Summary collapse
- .own_prompts ⇒ Object
- .own_tools ⇒ Object
-
.prompt(prompt_name, description:, arguments: [], &block) ⇒ Object
A reusable, parameterized message template served via prompts/get.
- .prompts ⇒ Object
- .server_name(value = nil) ⇒ Object
- .tool(tool_name, description:, input_schema:, &block) ⇒ Object
-
.tools ⇒ Object
Declared tools, including those inherited from parent toolsets.
Instance Method Summary collapse
- #deliver(payload, session_id: nil, context: nil) ⇒ Object
-
#on_initialize(_params, _context) ⇒ Object
Toolsets are stateless by default (nil => SolidLoop synthesizes a session id).
Class Method Details
.own_prompts ⇒ Object
170 171 172 |
# File 'lib/solid_loop/mcp/toolset.rb', line 170 def own_prompts @own_prompts ||= {} end |
.own_tools ⇒ Object
161 162 163 |
# File 'lib/solid_loop/mcp/toolset.rb', line 161 def own_tools @own_tools ||= {} end |
.prompt(prompt_name, description:, arguments: [], &block) ⇒ Object
A reusable, parameterized message template served via prompts/get. The block returns a String (wrapped into a single user message) or a ready-made messages array.
prompt "audit_report",
description: "Skeleton for a period audit",
arguments: [ { name: "period", description: "e.g. 2026-Q1", required: true } ] do |args, ctx|
"Audit the #{args['period']} period and list anomalies."
end
144 145 146 147 148 149 150 151 152 153 |
# File 'lib/solid_loop/mcp/toolset.rb', line 144 def prompt(prompt_name, description:, arguments: [], &block) raise ArgumentError, "prompt '#{prompt_name}' requires a block" unless block own_prompts[prompt_name.to_s] = PromptDefinition.new( name: prompt_name.to_s, description: description, arguments: arguments, handler: block ) end |
.prompts ⇒ Object
165 166 167 168 |
# File 'lib/solid_loop/mcp/toolset.rb', line 165 def prompts parent = superclass.respond_to?(:prompts) ? superclass.prompts : {} parent.merge(own_prompts) end |
.server_name(value = nil) ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/solid_loop/mcp/toolset.rb', line 111 def server_name(value = nil) @server_name = value.to_s if value klass = self while klass.respond_to?(:own_tools) explicit = klass.instance_variable_get(:@server_name) return explicit if explicit klass = klass.superclass end name.to_s.demodulize.underscore end |
.tool(tool_name, description:, input_schema:, &block) ⇒ Object
124 125 126 127 128 129 130 131 132 133 |
# File 'lib/solid_loop/mcp/toolset.rb', line 124 def tool(tool_name, description:, input_schema:, &block) raise ArgumentError, "tool '#{tool_name}' requires a block" unless block own_tools[tool_name.to_s] = ToolDefinition.new( name: tool_name.to_s, description: description, input_schema: input_schema, handler: block ) end |
.tools ⇒ Object
Declared tools, including those inherited from parent toolsets.
156 157 158 159 |
# File 'lib/solid_loop/mcp/toolset.rb', line 156 def tools parent = superclass.respond_to?(:tools) ? superclass.tools : {} parent.merge(own_tools) end |
Instance Method Details
#deliver(payload, session_id: nil, context: nil) ⇒ Object
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/solid_loop/mcp/toolset.rb', line 175 def deliver(payload, session_id: nil, context: nil) request = json_boundary(payload) body = case request["method"] when "initialize" then handle_initialize(request, context) { |sid| session_id = sid } when "tools/list" then success_envelope(request, "tools" => tool_specs) when "tools/call" then handle_tools_call(request, context) when "prompts/list" then success_envelope(request, "prompts" => prompt_specs) when "prompts/get" then handle_prompts_get(request, context) else error_envelope(request, -32601, "Method not found: #{request['method']}") end Result.new( body: body, session_id: session_id, raw_request: payload, raw_response: body, status: 200 ) end |
#on_initialize(_params, _context) ⇒ Object
Toolsets are stateless by default (nil => SolidLoop synthesizes a session id). Override to mint a real session id and receive it back on subsequent calls.
200 201 202 |
# File 'lib/solid_loop/mcp/toolset.rb', line 200 def on_initialize(_params, _context) nil end |