Module: McpLogs::Payload

Defined in:
lib/mcp_logs/payload.rb

Overview

Turns a tool's arguments or a handler's result into something safe to store: host-redacted, host-filtered, and bounded in size.

Class Method Summary collapse

Class Method Details

.cap(value) ⇒ Object



23
24
25
26
27
28
29
30
# File 'lib/mcp_logs/payload.rb', line 23

def cap(value)
  json = value.to_json
  return [value, false] if json.bytesize <= McpLogs.max_payload_bytes

  # byteslice can cut mid-character; scrub keeps the column valid UTF-8.
  preview = json.byteslice(0, McpLogs.max_payload_bytes).scrub("")
  [{ "truncated" => true, "bytes" => json.bytesize, "preview" => preview }, true]
end

.normalize(value) ⇒ Object

ActiveSupport::ParameterFilter only walks hashes, and the columns are jsonb, so a bare scalar result gets a wrapper rather than being dropped.



19
20
21
# File 'lib/mcp_logs/payload.rb', line 19

def normalize(value)
  value.is_a?(Hash) ? value.deep_stringify_keys : { "value" => value }
end

.parameter_filterObject

Rebuilt only when reset! is called: compiling the filter's regexps on every logged call would be pure overhead on the request path.



34
35
36
37
# File 'lib/mcp_logs/payload.rb', line 34

def parameter_filter
  @parameter_filter ||=
    ActiveSupport::ParameterFilter.new(Rails.application.config.filter_parameters)
end

.prepare(value) ⇒ Object

Returns [value_to_store, truncated?]. A nil value, or payload recording turned off, stores nothing at all.



9
10
11
12
13
14
15
# File 'lib/mcp_logs/payload.rb', line 9

def prepare(value)
  return [nil, false] if value.nil?
  return [nil, false] unless McpLogs.record_payloads?

  filtered = McpLogs.payload_filter.call(parameter_filter.filter(normalize(value)))
  cap(filtered)
end

.reset!Object



39
40
41
# File 'lib/mcp_logs/payload.rb', line 39

def reset!
  @parameter_filter = nil
end