Class: Pgbus::MCP::BaseTool
- Inherits:
-
MCP::Tool
- Object
- MCP::Tool
- Pgbus::MCP::BaseTool
- Defined in:
- lib/pgbus/mcp/base_tool.rb
Overview
Base class for every pgbus diagnostic tool. Provides the shared read-only annotation, a JSON response helper, and access to the DataSource the tool delegates to.
The DataSource is pulled from server_context[:data_source] so the server can inject a configured instance (and tests can inject a double). Every subclass is read-only by contract — see issue #180 security requirements. Write/admin tools, if ever added, must live in a separate, explicitly opt-in surface and never inherit from this class.
Direct Known Subclasses
Tools::DlqDetailTool, Tools::DlqTool, Tools::HealthTool, Tools::JobDetailTool, Tools::JobsTool, Tools::LocksTool, Tools::ProcessesTool, Tools::QueueDetailTool, Tools::QueuesTool, Tools::RecurringTool, Tools::StatsTool, Tools::ThroughputTool
Class Method Summary collapse
-
.annotations_value ⇒ Object
MCP::Tool.inherited resets @annotations_value to nil on every subclass, so the read_only_hint set on BaseTool would not reach the concrete tools.
-
.data_source_from(server_context) ⇒ Object
Pull the injected DataSource (or build a default one).
-
.error_response(message) ⇒ Object
Wrap an error message as an MCP error response (isError: true) so the client surfaces it as a tool failure rather than a normal result.
-
.json_response(value, server_context: nil, include_payloads: false) ⇒ Object
Wrap any Ruby value as a single text-content JSON response, applying payload redaction at this boundary as a fail-safe.
-
.payloads_allowed?(server_context, include_payloads) ⇒ Boolean
Whether payloads may be returned for this call.
Class Method Details
.annotations_value ⇒ Object
MCP::Tool.inherited resets @annotations_value to nil on every subclass, so the read_only_hint set on BaseTool would not reach the concrete tools. Fall back to the nearest ancestor that defined annotations so all tools inherit the read-only contract without repeating it. (annotations_value is what MCP::Tool#to_h reads.)
32 33 34 |
# File 'lib/pgbus/mcp/base_tool.rb', line 32 def annotations_value super || (superclass.respond_to?(:annotations_value) ? superclass.annotations_value : nil) end |
.data_source_from(server_context) ⇒ Object
Pull the injected DataSource (or build a default one). Kept as a class method because MCP tool entry points (‘self.call`) are class methods.
39 40 41 |
# File 'lib/pgbus/mcp/base_tool.rb', line 39 def data_source_from(server_context) (server_context && server_context[:data_source]) || Pgbus::Web::DataSource.new end |
.error_response(message) ⇒ Object
Wrap an error message as an MCP error response (isError: true) so the client surfaces it as a tool failure rather than a normal result.
70 71 72 73 74 75 |
# File 'lib/pgbus/mcp/base_tool.rb', line 70 def error_response() ::MCP::Tool::Response.new( [{ type: "text", text: }], error: true ) end |
.json_response(value, server_context: nil, include_payloads: false) ⇒ Object
Wrap any Ruby value as a single text-content JSON response, applying payload redaction at this boundary as a fail-safe. Redaction is the default: a tool returns metadata, and any payload-bearing key (at any depth) is stripped unless this call is explicitly allowed to include payloads. A tool author who forgets about redaction therefore cannot leak message bodies — they have to opt in.
Pass server_context and the tool’s per-call include_payloads flag to enable payloads; both gates must be open (see #payloads_allowed?).
62 63 64 65 66 |
# File 'lib/pgbus/mcp/base_tool.rb', line 62 def json_response(value, server_context: nil, include_payloads: false) allow = payloads_allowed?(server_context, include_payloads) redacted = Redactor.deep_redact(value, include_payloads: allow) ::MCP::Tool::Response.new([{ type: "text", text: JSON.generate(redacted) }]) end |
.payloads_allowed?(server_context, include_payloads) ⇒ Boolean
Whether payloads may be returned for this call. Honors a per-call ‘include_payloads` argument only when the server was started with payloads globally allowed (`server_context`). Defaults to false on both axes so nothing leaks by accident.
47 48 49 50 51 |
# File 'lib/pgbus/mcp/base_tool.rb', line 47 def payloads_allowed?(server_context, include_payloads) return false unless server_context && server_context[:allow_payloads] !!include_payloads end |