Class: RailsAiContext::McpConfigGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_ai_context/mcp_config_generator.rb

Overview

Generates per-tool MCP config files so each AI tool auto-discovers the MCP server.

Each tool has its own config file format:

Claude Code  → .mcp.json          (mcpServers key)
Cursor       → .cursor/mcp.json   (mcpServers key)
VS Code      → .vscode/mcp.json   (servers key)
OpenCode     → opencode.json      (mcp key, type: "local", command as array)
Codex CLI    → .codex/config.toml (TOML, [mcp_servers.NAME] section)

Constant Summary collapse

TOOL_CONFIGS =
Install::AiTool.mcp_configs_by_key.freeze
SERVER_NAME =
"rails-ai-context"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tools:, output_dir:, standalone: nil, tool_mode: :mcp) ⇒ McpConfigGenerator

Returns a new instance of McpConfigGenerator.

Parameters:

  • tools (Array<Symbol>)

    selected AI tool keys (e.g. [:claude, :cursor])

  • output_dir (String)

    project root path

  • standalone (Boolean, nil) (defaults to: nil)

    true writes bare rails-ai-context commands, false writes bundle exec commands. nil (the default) detects the install mode from the app's Gemfile.lock so every entry point that writes MCP configs (standalone CLI init, rake task, Rails generator) converges on identical config content for the same app instead of rewriting each other's command form on alternate runs.

  • tool_mode (Symbol) (defaults to: :mcp)

    :mcp or :cli



31
32
33
34
35
36
# File 'lib/rails_ai_context/mcp_config_generator.rb', line 31

def initialize(tools:, output_dir:, standalone: nil, tool_mode: :mcp)
  @tools = Array(tools).map(&:to_sym)
  @output_dir = output_dir
  @standalone = standalone.nil? ? InstallMode.standalone? : standalone
  @tool_mode = tool_mode
end

Class Method Details

.remove(tools:, output_dir:) ⇒ Array<String>

Removes only the rails-ai-context entry from each tool's MCP config file, preserving other servers. Deletes the file only if no other entries remain.

Parameters:

  • tools (Array<Symbol>)

    tool keys to remove MCP entries from

  • output_dir (String)

    project root path

Returns:

  • (Array<String>)

    paths that were modified or deleted



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/rails_ai_context/mcp_config_generator.rb', line 234

def self.remove(tools:, output_dir:)
  cleaned = []
  Array(tools).map(&:to_sym).each do |tool|
    config = TOOL_CONFIGS[tool]
    next unless config

    path = File.join(output_dir, config[:path])
    next unless File.exist?(path)

    if config[:format] == :codex_toml
      cleaned << path if remove_toml_entry(path)
    else
      root_key = config[:root_key]
      cleaned << path if remove_json_entry(path, root_key)
    end
  end
  cleaned
end

Instance Method Details

#callHash

Returns { written: [paths], skipped: [paths] }.

Returns:

  • (Hash)

    { written: [paths], skipped: [paths] }



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rails_ai_context/mcp_config_generator.rb', line 39

def call
  return { written: [], skipped: [] } if @tool_mode == :cli

  written = []
  skipped = []

  @tools.each do |tool|
    config = TOOL_CONFIGS[tool]
    next unless config

    path = File.join(@output_dir, config[:path])
    result = generate_for(tool, path, config)
    case result
    when :written then written << path
    when :skipped then skipped << path
    end
  end

  { written: written, skipped: skipped }
end