Module: McpLogs

Defined in:
lib/mcp_logs.rb,
lib/mcp_logs/engine.rb,
lib/mcp_logs/context.rb,
lib/mcp_logs/payload.rb,
lib/mcp_logs/version.rb,
app/models/mcp_logs/call.rb,
app/models/mcp_logs/docs.rb,
lib/mcp_logs/configuration.rb,
app/jobs/mcp_logs/purge_job.rb,
app/models/mcp_logs/recorder.rb,
app/helpers/mcp_logs/calls_helper.rb,
app/models/mcp_logs/application_record.rb,
app/controllers/mcp_logs/docs_controller.rb,
app/controllers/mcp_logs/calls_controller.rb,
lib/generators/mcp_logs/install_generator.rb,
app/controllers/mcp_logs/application_controller.rb

Defined Under Namespace

Modules: CallsHelper, Context, Docs, Payload Classes: ApplicationController, ApplicationRecord, Call, CallsController, Configuration, ConfigurationError, DocsController, Engine, InstallGenerator, PurgeJob, Recorder

Constant Summary collapse

SETTINGS =

server is absent on purpose: McpLogs.server calls the configured lambda rather than returning it, so it gets an explicit reader below and only its writer is generated here.

%i[
  enabled base_controller_class tool_sections record_payloads
  max_payload_bytes payload_filter retention_days abandoned_after_hours page_size
].freeze
MISSING_BASE_CONTROLLER =
<<~MESSAGE.freeze
  McpLogs has no base_controller_class, so its pages would have no authentication.

  Set it in config/initializers/mcp_logs.rb to a controller of your own whose
  authentication the log pages should inherit:

    config.base_controller_class = "Admin::BaseController"

  Use "ActionController::Base" only if you intend /mcp_logs — every tool
  argument and response your MCP server has recorded — to be readable by
  anyone who can reach the app.
MESSAGE
VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.around_request(server_name: nil) ⇒ Object



84
85
86
# File 'lib/mcp_logs.rb', line 84

def around_request(server_name: nil)
  McpLogs::Recorder.around_request(server_name: server_name)
end

.base_controllerObject

Resolved when the engine's ApplicationController is first autoloaded, i.e. after the host's initializers have run.

There is no default. Every page this engine serves renders arguments and responses the host's MCP server has logged, so an engine that quietly descended from ActionController::Base would publish the audit log of any app that installed it without reading the whole README. Failing here costs a stranger one boot; the alternative costs them the log.



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/mcp_logs.rb', line 71

def base_controller
  configured = configuration.base_controller_class.to_s
  raise ConfigurationError, MISSING_BASE_CONTROLLER if configured.empty?

  configured.constantize
rescue NameError
  # The generated initializer ships a placeholder, so "set but not resolvable"
  # is the likeliest way a host gets here — and a bare NameError names the
  # constant without saying which setting produced it.
  raise ConfigurationError, "McpLogs base_controller_class is #{configured.inspect}, " \
                            "which does not name a controller. #{MISSING_BASE_CONTROLLER}"
end

.configurationObject



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

def configuration
  @configuration ||= Configuration.new
end

.enabled?Boolean

Returns:

  • (Boolean)


51
# File 'lib/mcp_logs.rb', line 51

def enabled? = !!configuration.enabled

.record_payloads?Boolean

Returns:

  • (Boolean)


53
# File 'lib/mcp_logs.rb', line 53

def record_payloads? = !!configuration.record_payloads

.reset_configuration!Object

Specs and hosts that reconfigure at runtime need a clean slate.



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

def reset_configuration!
  @configuration = Configuration.new
end

.serverObject

Calls the configured lambda. Returns nil when no server is configured, which the docs page renders as "no server configured" rather than raising.



57
# File 'lib/mcp_logs.rb', line 57

def server = configuration.server&.call

.server=(value) ⇒ Object



59
60
61
# File 'lib/mcp_logs.rb', line 59

def server=(value)
  configuration.server = value
end

.setup {|configuration| ... } ⇒ Object

Yields:



31
32
33
# File 'lib/mcp_logs.rb', line 31

def setup
  yield configuration
end

.with_context(request = nil, **options, &block) ⇒ Object



88
89
90
# File 'lib/mcp_logs.rb', line 88

def with_context(request = nil, **options, &block)
  McpLogs::Context.with(request, **options, &block)
end