123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::MCP::ExplainTool Private

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
Inherits: Object
Defined in: lib/rubocop/mcp/explain_tool.rb

Overview

The rubocop_explain tool: what cops do, as --explain prints it.

Constant Summary

  • ANNOTATIONS =
    # File 'lib/rubocop/mcp/explain_tool.rb', line 23
    {
      title: "RuboCop's cop explanation", destructive_hint: false, idempotent_hint: true,
      open_world_hint: false, read_only_hint: true
    }.freeze
  • DESCRIPTION =
    # File 'lib/rubocop/mcp/explain_tool.rb', line 10
    'Explain what cops do: the problem each one targets, bad and good examples, ' \
    'its configuration as this project resolves it, and whether it autocorrects. ' \
    'Takes cop names as offenses report them, such as `Style/StringLiterals`. ' \
    'Pass the `path` of a file to see the configuration that applies to it.'
  • INPUT_SCHEMA =
    # File 'lib/rubocop/mcp/explain_tool.rb', line 15
    {
      properties: {
        cop_names: { type: 'array', items: { type: 'string' }, minItems: 1 },
        path: { type: 'string' }
      },
      required: ['cop_names'],
      additionalProperties: false
    }.freeze

Class Method Summary

Instance Method Summary

  • #to_tool Internal use only

    The tool’s block does not run in this instance, so it reaches #explain through a method object it closes over.

  • #explain(cop_names, path) private Internal use only

    Explains the cops it recognizes and then names the ones it does not, as --explain does, so a typo does not cost the explanations asked for alongside it.

::RuboCop::CLI::Command::CopNames - Included

#cop_class_for

Not memoized: the MCP server lives long enough for a plugin to register a cop after a lookup has missed it.

#department?, #department_message,
#known_cop_classes

The cops among names that exist, so a command can report on what it understood before #validate_cop_names! objects to the rest.

#unknown_cop_message, #validate_cop_names!

Constructor Details

.new(config_store) ⇒ ExplainTool

[ GitHub ]

  
# File 'lib/rubocop/mcp/explain_tool.rb', line 28

def initialize(config_store)
  @config_store = config_store
end

Instance Method Details

#explain(cop_names, path) (private)

Explains the cops it recognizes and then names the ones it does not, as --explain does, so a typo does not cost the explanations asked for alongside it. The configuration is loaded first, since that is what registers the cops of any plugins it names.

[ GitHub ]

  
# File 'lib/rubocop/mcp/explain_tool.rb', line 55

def explain(cop_names, path)
  config = path ? @config_store.for_file(path) : @config_store.for_pwd
  explanations = known_cop_classes(cop_names).map do |cop_class|
    Cop::CopExplanation.new(cop_class, config).to_s
  end
  validate_cop_names!(cop_names)

  explanations.join("\n\n")
rescue IncorrectCopNameError => e
  raise RuboCop::Error, [*explanations, e.message].join("\n\n")
end

#to_tool

The tool’s block does not run in this instance, so it reaches #explain through a method object it closes over.

[ GitHub ]

  
# File 'lib/rubocop/mcp/explain_tool.rb', line 34

def to_tool
  explain = method(:explain)

  ::MCP::Tool.define(
    name: 'rubocop_explain',
    description: DESCRIPTION,
    input_schema: INPUT_SCHEMA,
    annotations: ANNOTATIONS
  ) do |cop_names:, path: nil|
    ::MCP::Tool::Response.new([{ type: 'text', text: explain.call(cop_names, path) }])
  rescue RuboCop::Error => e
    ::MCP::Tool::Response.new([{ type: 'text', text: e.message }], error: true)
  end
end