Class: RuboCop::MCP::Server Private
Do not use. This class is for internal use only.
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | lib/rubocop/mcp/server.rb |
Overview
RuboCop MCP Server.
Class Method Summary
- .new(config_store) ⇒ Server constructor Internal use only
Instance Method Summary
- #start Internal use only
- #autocorrection_tool private Internal use only
-
#build_summary(target_files, files)
private
Internal use only
Note
It is useful for RuboCop’s result summary to be shown in the LLM’s responses during interactions, so the summary is returned in a form that is easy for the LLM to reason about. -
#build_tool(name:, description:, title:, destructive_hint:, idempotent_hint:, read_only_hint:, safety_required:)
private
Internal use only
Metrics/ParameterLists.
- #inspection_tool private Internal use only
- #process_files(path, filter_empty: false) private Internal use only
- #read_file(file) private Internal use only
- #run_autocorrection(path, source_code, safety) private Internal use only
- #run_inspection(path, source_code) private Internal use only
- #write_file(file, content) private Internal use only
Instance Method Details
#autocorrection_tool (private)
[ GitHub ]# File 'lib/rubocop/mcp/server.rb', line 46
def autocorrection_tool build_tool( name: 'rubocop_autocorrection', description: 'Autocorrect RuboCop offenses in Ruby code. ' \ 'Provide `source_code` to correct inline code or `path` to correct files. ' \ 'Set `safety` to false to include unsafe corrections.', title: "RuboCop's autocorrection", destructive_hint: true, idempotent_hint: false, read_only_hint: false, safety_required: true ) do |path, source_code, safety| run_autocorrection(path, source_code, safety) end end
#build_summary(target_files, files) (private)
|
Note
|
It is useful for RuboCop’s result summary to be shown in the LLM’s responses during interactions, so the summary is returned in a form that is easy for the LLM to reason about. Since LLM execution is non-deterministic, it is also sensible to compute the summary deterministically at this stage. |
# File 'lib/rubocop/mcp/server.rb', line 125
def build_summary(target_files, files) summary = { target_file_count: target_files.count } if files.first&.key?(:offenses) summary[:offense_count] = files.sum { |f| f[:offenses].size } else summary[:corrected_file_count] = files.count { |f| f[:corrected] } end summary end
#build_tool(name:, description:, title:, destructive_hint:, idempotent_hint:, read_only_hint:, safety_required:) (private)
Metrics/ParameterLists
# File 'lib/rubocop/mcp/server.rb', line 136
def build_tool( name:, description:, title:, destructive_hint:, idempotent_hint:, read_only_hint:, safety_required: ) if safety_required safety_property = { safety: { type: 'boolean' } } required = ['safety'] else safety_property = {} required = nil end ::MCP::Tool.define( name: name, description: description, input_schema: { properties: { path: { type: 'string' }, source_code: { type: 'string' } }.merge(safety_property), required: required }.compact, annotations: { title: title, destructive_hint: destructive_hint, idempotent_hint: idempotent_hint, open_world_hint: false, read_only_hint: read_only_hint } ) do |path: nil, source_code: nil, safety: true| result = yield(path, source_code, safety) ::MCP::Tool::Response.new([{ type: 'text', text: result }]) end end
#inspection_tool (private)
[ GitHub ]# File 'lib/rubocop/mcp/server.rb', line 31
def inspection_tool build_tool( name: 'rubocop_inspection', description: 'Inspect Ruby code for offenses. ' \ 'Provide `source_code` to check inline code or `path` to check files.', title: "RuboCop's inspection", destructive_hint: false, idempotent_hint: true, read_only_hint: true, safety_required: false ) do |path, source_code| run_inspection(path, source_code) end end
#process_files(path, filter_empty: false) (private)
[ GitHub ]# File 'lib/rubocop/mcp/server.rb', line 93
def process_files(path, filter_empty: false) target_finder = RuboCop::TargetFinder.new(@config_store, @options) target_files = target_finder.find(path ? [path] : [], :only_recognized_file_types) all_files = target_files.map { |file| yield(file, read_file(file)) } files = filter_empty ? all_files.reject { |f| f[:offenses]&.empty? } : all_files { files: files, summary: build_summary(target_files, all_files) }.to_json end
#read_file(file) (private)
[ GitHub ]# File 'lib/rubocop/mcp/server.rb', line 102
def read_file(file) config = @config_store.for_file(file) RuboCop::ProcessedSource.from_file( file, config.target_ruby_version, parser_engine: config.parser_engine ).raw_source rescue Errno::ENOENT raise RuboCop::Error, "No such file or directory: #{file}" end
#run_autocorrection(path, source_code, safety) (private)
[ GitHub ]# File 'lib/rubocop/mcp/server.rb', line 75
def run_autocorrection(path, source_code, safety) command = safety ? 'rubocop.formatAutocorrects' : 'rubocop.formatAutocorrectsAll' if source_code @runtime.format(path || 'example.rb', source_code, command: command).tap do |corrected| write_file(path, corrected) if path end else process_files(path) do |file, source| @runtime.format(file, source, command: command).then do |corrected| write_file(file, corrected) { path: PathUtil.relative_path(file), corrected: source != corrected } end end end end
#run_inspection(path, source_code) (private)
[ GitHub ]# File 'lib/rubocop/mcp/server.rb', line 62
def run_inspection(path, source_code) if source_code offenses = @runtime.offenses(path || 'example.rb', source_code, source_code.encoding) offenses.to_json else process_files(path, filter_empty: true) do |file, source| offenses = @runtime.offenses(file, source, source.encoding) { path: PathUtil.relative_path(file), offenses: offenses } end end end
#start
[ GitHub ]# File 'lib/rubocop/mcp/server.rb', line 18
def start # No `protocol_version` is specified because draft feature by default can be used. server = ::MCP::Server.new( name: 'rubocop_mcp_server', version: RuboCop::Version::STRING, tools: [inspection_tool, autocorrection_tool] ) ::MCP::Server::Transports::StdioTransport.new(server).open end
#write_file(file, content) (private)
[ GitHub ]# File 'lib/rubocop/mcp/server.rb', line 111
def write_file(file, content) File.write(file, content) rescue Errno::EACCES raise RuboCop::Error, "Permission denied: #{file}" rescue Errno::ENOSPC raise RuboCop::Error, "No space left on device: #{file}" rescue Errno::EROFS raise RuboCop::Error, "Read-only file system: #{file}" end