rails-active-mcp 2.0.7 → 2.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +141 -0
  3. data/README.md +3 -3
  4. data/examples/rails_app_integration.md +405 -0
  5. data/exe/rails-active-mcp-server +8 -8
  6. data/gemfiles/rails_6.0.gemfile +34 -0
  7. data/gemfiles/rails_6.1.gemfile +34 -0
  8. data/gemfiles/rails_7.0.gemfile +34 -0
  9. data/gemfiles/rails_7.1.gemfile +34 -0
  10. data/gemfiles/rails_7.2.gemfile +34 -0
  11. data/lib/generators/rails_active_mcp/install/install_generator.rb +44 -94
  12. data/lib/generators/rails_active_mcp/install/templates/README.md +134 -54
  13. data/lib/generators/rails_active_mcp/install/templates/initializer.rb +44 -6
  14. data/lib/generators/rails_active_mcp/install/templates/rails-active-mcp-server +104 -0
  15. data/lib/generators/rails_active_mcp/install/templates/rails-active-mcp-wrapper +94 -0
  16. data/lib/rails_active_mcp/configuration.rb +44 -4
  17. data/lib/rails_active_mcp/console_executor.rb +185 -83
  18. data/lib/rails_active_mcp/engine.rb +2 -2
  19. data/lib/rails_active_mcp/garbage_collection_utils.rb +13 -0
  20. data/lib/rails_active_mcp/safety_checker.rb +17 -7
  21. data/lib/rails_active_mcp/sdk/server.rb +1 -1
  22. data/lib/rails_active_mcp/sdk/tools/console_execute_tool.rb +0 -2
  23. data/lib/rails_active_mcp/sdk/tools/dry_run_tool.rb +0 -2
  24. data/lib/rails_active_mcp/sdk/tools/model_info_tool.rb +1 -3
  25. data/lib/rails_active_mcp/sdk/tools/safe_query_tool.rb +0 -2
  26. data/lib/rails_active_mcp/tasks.rake +238 -82
  27. data/lib/rails_active_mcp/version.rb +1 -1
  28. data/lib/rails_active_mcp.rb +4 -3
  29. data/mcp.ru +2 -2
  30. data/rails_active_mcp.gemspec +62 -14
  31. metadata +72 -16
@@ -68,7 +68,7 @@ module RailsActiveMcp
68
68
 
69
69
  # Create log directory
70
70
  log_dir = File.join(Dir.pwd, 'log')
71
- FileUtils.mkdir_p(log_dir) unless Dir.exist?(log_dir)
71
+ FileUtils.mkdir_p(log_dir)
72
72
 
73
73
  # Redirect stderr to log file
74
74
  stderr_log = File.join(log_dir, 'rails_mcp_stderr.log')
@@ -70,8 +70,6 @@ module RailsActiveMcp
70
70
  end
71
71
  end
72
72
 
73
- private
74
-
75
73
  def self.format_success_result(result)
76
74
  output = []
77
75
  output << "Code: #{result[:code]}"
@@ -60,8 +60,6 @@ module RailsActiveMcp
60
60
  ])
61
61
  end
62
62
 
63
- private
64
-
65
63
  def self.error_response(message)
66
64
  MCP::Tool::Response.new([
67
65
  { type: 'text', text: message }
@@ -40,7 +40,7 @@ module RailsActiveMcp
40
40
 
41
41
  def self.call(model:, server_context:, include_schema: true, include_associations: true,
42
42
  include_validations: true)
43
- config = RailsActiveMcp.config
43
+ RailsActiveMcp.config
44
44
 
45
45
  begin
46
46
  model_class = model.constantize
@@ -93,8 +93,6 @@ module RailsActiveMcp
93
93
  end
94
94
  end
95
95
 
96
- private
97
-
98
96
  def self.error_response(message)
99
97
  MCP::Tool::Response.new([
100
98
  { type: 'text', text: message }
@@ -64,8 +64,6 @@ module RailsActiveMcp
64
64
  end
65
65
  end
66
66
 
67
- private
68
-
69
67
  def self.error_response(message)
70
68
  MCP::Tool::Response.new([
71
69
  { type: 'text', text: message }
@@ -1,6 +1,6 @@
1
1
  namespace :rails_active_mcp do
2
- desc "Check the safety of Ruby code"
3
- task :check_safety, [:code] => :environment do |task, args|
2
+ desc 'Check the safety of Ruby code'
3
+ task :check_safety, [:code] => :environment do |_task, args|
4
4
  code = args[:code]
5
5
 
6
6
  if code.blank?
@@ -24,8 +24,8 @@ namespace :rails_active_mcp do
24
24
  end
25
25
  end
26
26
 
27
- desc "Execute Ruby code with safety checks"
28
- task :execute, [:code] => :environment do |task, args|
27
+ desc 'Execute Ruby code with safety checks'
28
+ task :execute, [:code] => :environment do |_task, args|
29
29
  code = args[:code]
30
30
 
31
31
  if code.blank?
@@ -44,111 +44,267 @@ namespace :rails_active_mcp do
44
44
  puts "Error: #{result[:error]}"
45
45
  puts "Error class: #{result[:error_class]}" if result[:error_class]
46
46
  end
47
- rescue => e
47
+ rescue StandardError => e
48
48
  puts "Failed to execute: #{e.message}"
49
49
  exit 1
50
50
  end
51
51
  end
52
52
 
53
- desc "Test MCP tools"
54
- task :test_tools => :environment do
55
- puts "Testing Rails Active MCP tools..."
53
+ desc 'Test MCP tools'
54
+ task test_tools: :environment do
55
+ puts 'Testing Rails Active MCP tools...'
56
56
 
57
- # Test SafeQueryTool
58
- puts "\n1. Testing SafeQueryTool..."
59
- if defined?(User)
60
- tool = RailsActiveMcp::Tools::SafeQueryTool.new
61
- result = tool.call(model: "User", method: "count")
62
- puts " User.count: #{result[:success] ? result[:result] : result[:error]}"
57
+ # Test console execution
58
+ puts "\n1. Testing console_execute tool:"
59
+ result = RailsActiveMcp.execute('1 + 1')
60
+ puts " Simple math: #{result[:success] ? 'PASS' : 'FAIL'}"
61
+
62
+ # Test safety checking
63
+ puts "\n2. Testing safety checking:"
64
+ safe_result = RailsActiveMcp.safe?('User.count')
65
+ dangerous_result = RailsActiveMcp.safe?('User.delete_all')
66
+ puts " Safe code detection: #{safe_result ? 'PASS' : 'FAIL'}"
67
+ puts " Dangerous code detection: #{dangerous_result ? 'FAIL' : 'PASS'}"
68
+
69
+ # Test Rails integration
70
+ puts "\n3. Testing Rails integration:"
71
+ if defined?(Rails) && Rails.respond_to?(:env)
72
+ puts " Rails environment: #{Rails.env} - PASS"
63
73
  else
64
- puts " Skipped (User model not found)"
74
+ puts ' Rails environment: NOT DETECTED - FAIL'
65
75
  end
66
76
 
67
- # Test ConsoleExecuteTool
68
- puts "\n2. Testing ConsoleExecuteTool..."
69
- tool = RailsActiveMcp::Tools::ConsoleExecuteTool.new
70
- result = tool.call(code: "1 + 1")
71
- puts " 1 + 1: #{result[:success] ? result[:return_value] : result[:error]}"
77
+ puts "\nAll tests completed!"
78
+ end
72
79
 
73
- # Test DryRunTool
74
- puts "\n3. Testing DryRunTool..."
75
- tool = RailsActiveMcp::Tools::DryRunTool.new
76
- result = tool.call(code: "User.delete_all")
77
- puts " User.delete_all analysis: #{result[:estimated_risk]} risk"
80
+ desc 'Benchmark MCP tools performance'
81
+ task benchmark: :environment do
82
+ require 'benchmark'
78
83
 
79
- puts "\nAll tools tested!"
80
- end
84
+ puts 'Rails Active MCP Performance Benchmark'
85
+ puts '=' * 50
81
86
 
82
- desc "Show configuration"
83
- task :config => :environment do
84
- config = RailsActiveMcp.config
87
+ # Benchmark safety checking
88
+ puts "\nSafety Checker Performance:"
89
+ Benchmark.bm(20) do |x|
90
+ x.report('Simple check:') do
91
+ 1000.times { RailsActiveMcp.safe?('User.count') }
92
+ end
85
93
 
86
- puts "Rails Active MCP Configuration:"
87
- puts " Enabled: #{config.enabled}"
88
- puts " Safe mode: #{config.safe_mode}"
89
- puts " Default timeout: #{config.default_timeout}s"
90
- puts " Max results: #{config.max_results}"
91
- puts " Log executions: #{config.log_executions}"
92
- puts " Audit file: #{config.audit_file}"
93
- puts " Enable mutation tools: #{config.enable_mutation_tools}"
94
- puts " Execution environment: #{config.execution_environment}"
94
+ x.report('Complex check:') do
95
+ 100.times { RailsActiveMcp.safe?('User.where(active: true).includes(:posts).limit(10)') }
96
+ end
95
97
 
96
- if config.allowed_models.any?
97
- puts " Allowed models: #{config.allowed_models.join(', ')}"
98
+ x.report('Dangerous check:') do
99
+ 1000.times { RailsActiveMcp.safe?('User.delete_all') }
100
+ end
98
101
  end
99
102
 
100
- if config.blocked_models.any?
101
- puts " Blocked models: #{config.blocked_models.join(', ')}"
102
- end
103
+ # Benchmark code execution
104
+ puts "\nCode Execution Performance:"
105
+ Benchmark.bm(20) do |x|
106
+ x.report('Simple math:') do
107
+ 100.times { RailsActiveMcp.execute('1 + 1') }
108
+ end
103
109
 
104
- if config.custom_safety_patterns.any?
105
- puts " Custom safety patterns: #{config.custom_safety_patterns.size}"
110
+ x.report('String operations:') do
111
+ 100.times { RailsActiveMcp.execute('"hello".upcase') }
112
+ end
106
113
  end
107
114
  end
108
115
 
109
- desc "View audit log"
110
- task :audit_log, [:lines] => :environment do |task, args|
111
- lines = args[:lines]&.to_i || 10
112
- audit_file = RailsActiveMcp.config.audit_file
116
+ desc 'Validate Rails Active MCP configuration'
117
+ task validate_config: :environment do
118
+ puts 'Validating Rails Active MCP configuration...'
119
+
120
+ config = RailsActiveMcp.config
121
+
122
+ if config.valid?
123
+ puts '✅ Configuration is valid'
113
124
 
114
- unless File.exist?(audit_file)
115
- puts "Audit log not found at: #{audit_file}"
125
+ puts "\nCurrent Settings:"
126
+ puts " Safe mode: #{config.safe_mode}"
127
+ puts " Command timeout: #{config.command_timeout}s"
128
+ puts " Max results: #{config.max_results}"
129
+ puts " Log executions: #{config.log_executions}"
130
+ puts " Log level: #{config.log_level}"
131
+ puts " Allowed models: #{config.allowed_models.any? ? config.allowed_models.join(', ') : 'All models allowed'}"
132
+ puts " Custom safety patterns: #{config.custom_safety_patterns.length} patterns"
133
+ else
134
+ puts '❌ Configuration is invalid'
135
+ puts 'Please check your config/initializers/rails_active_mcp.rb file'
116
136
  exit 1
117
137
  end
138
+ end
139
+
140
+ desc 'Generate example usage documentation'
141
+ task generate_examples: :environment do
142
+ examples_file = Rails.root.join('doc/rails_active_mcp_examples.md')
143
+ FileUtils.mkdir_p(File.dirname(examples_file))
144
+
145
+ content = <<~MARKDOWN
146
+ # Rails Active MCP Usage Examples
147
+
148
+ Generated on #{Date.current}
149
+
150
+ ## Safe Operations
151
+
152
+ These operations are considered safe and can be executed in safe mode:
153
+
154
+ ```ruby
155
+ # Basic model queries
156
+ User.count
157
+ User.all.limit(10)
158
+ User.where(active: true)
159
+ User.find(1)
160
+
161
+ # Associations
162
+ User.includes(:posts).limit(5)
163
+ Post.joins(:user).where(users: { active: true })
164
+
165
+ # Aggregations
166
+ Order.sum(:total_amount)
167
+ User.group(:status).count
168
+
169
+ # System information
170
+ Rails.env
171
+ Rails.version
172
+ Time.current
173
+ ```
174
+
175
+ ## Dangerous Operations (Blocked in Safe Mode)
176
+
177
+ These operations are blocked when safe_mode is enabled:
118
178
 
119
- puts "Last #{lines} entries from audit log:"
120
- puts "=" * 50
121
-
122
- File.readlines(audit_file).last(lines).each do |line|
123
- begin
124
- entry = JSON.parse(line)
125
- timestamp = entry['timestamp']
126
- code = entry['code']
127
- user = entry.dig('user', 'email') || entry.dig('user', 'environment') || 'unknown'
128
-
129
- puts "#{timestamp} [#{user}]: #{code}"
130
-
131
- if entry['type'] == 'error'
132
- puts " ERROR: #{entry['error']}"
133
- elsif entry['safety_check'] && !entry['safety_check']['safe']
134
- puts " SAFETY: #{entry['safety_check']['summary']}"
135
- end
136
- puts
137
- rescue JSON::ParserError
138
- puts "Invalid JSON entry: #{line}"
179
+ ```ruby
180
+ # Mass deletions
181
+ User.delete_all
182
+ User.destroy_all
183
+
184
+ # System commands
185
+ system('rm -rf /')
186
+ `ls -la`
187
+
188
+ # File operations
189
+ File.delete('important_file.txt')
190
+ FileUtils.rm_rf('/important/directory')
191
+
192
+ # Code evaluation
193
+ eval(user_input)
194
+ send(dynamic_method)
195
+ ```
196
+
197
+ ## Claude Desktop Usage Examples
198
+
199
+ Ask Claude these questions to interact with your Rails app:
200
+
201
+ - "How many users do we have?"
202
+ - "Show me the User model structure"
203
+ - "What are the most recent orders?"
204
+ - "Check if this code is safe: User.where(active: false).delete_all"
205
+ - "Find users created in the last week"
206
+ - "What associations does the Post model have?"
207
+
208
+ ## Configuration Examples
209
+
210
+ ### Development Configuration
211
+ ```ruby
212
+ RailsActiveMcp.configure do |config|
213
+ config.safe_mode = false
214
+ config.log_level = :debug
215
+ config.command_timeout = 60
216
+ config.max_results = 200
139
217
  end
140
- end
218
+ ```
219
+
220
+ ### Production Configuration
221
+ ```ruby
222
+ RailsActiveMcp.configure do |config|
223
+ config.safe_mode = true
224
+ config.log_level = :warn
225
+ config.command_timeout = 15
226
+ config.max_results = 50
227
+ config.allowed_models = %w[User Post Comment]
228
+ end
229
+ ```
230
+ MARKDOWN
231
+
232
+ File.write(examples_file, content)
233
+ puts "Examples generated at: #{examples_file}"
141
234
  end
142
235
 
143
- desc "Clear audit log"
144
- task :clear_audit_log => :environment do
145
- audit_file = RailsActiveMcp.config.audit_file
236
+ desc 'Install Claude Desktop configuration'
237
+ task install_claude_config: :environment do
238
+ config_template = {
239
+ mcpServers: {
240
+ 'rails-active-mcp' => {
241
+ command: Rails.root.join('bin/rails-active-mcp-wrapper').to_s,
242
+ cwd: Rails.root.to_s,
243
+ env: {
244
+ RAILS_ENV: Rails.env
245
+ }
246
+ }
247
+ }
248
+ }
146
249
 
147
- if File.exist?(audit_file)
148
- File.truncate(audit_file, 0)
149
- puts "Audit log cleared: #{audit_file}"
150
- else
151
- puts "Audit log not found: #{audit_file}"
250
+ puts 'Claude Desktop Configuration:'
251
+ puts JSON.pretty_generate(config_template)
252
+ puts ''
253
+ puts 'Add this to your Claude Desktop configuration file:'
254
+ puts ' macOS/Linux: ~/.config/claude-desktop/claude_desktop_config.json'
255
+ puts ' Windows: %APPDATA%\\Claude\\claude_desktop_config.json'
256
+ end
257
+
258
+ desc 'Show comprehensive status and diagnostics'
259
+ task status: :environment do
260
+ puts 'Rails Active MCP Status Report'
261
+ puts '=' * 50
262
+
263
+ # Basic environment info
264
+ puts "\n📋 Environment Information:"
265
+ puts " Rails version: #{Rails.version}"
266
+ puts " Ruby version: #{RUBY_VERSION}"
267
+ puts " Rails environment: #{Rails.env}"
268
+ puts " Rails Active MCP version: #{RailsActiveMcp::VERSION}"
269
+
270
+ # Configuration status
271
+ puts "\n⚙️ Configuration Status:"
272
+ config = RailsActiveMcp.config
273
+ puts " Valid: #{config.valid? ? '✅' : '❌'}"
274
+ puts " Safe mode: #{config.safe_mode ? '🔒 Enabled' : '⚠️ Disabled'}"
275
+ puts " Timeout: #{config.command_timeout}s"
276
+ puts " Max results: #{config.max_results}"
277
+
278
+ # File status
279
+ puts "\n📁 File Status:"
280
+ files_to_check = [
281
+ 'bin/rails-active-mcp-server',
282
+ 'bin/rails-active-mcp-wrapper',
283
+ 'config/initializers/rails_active_mcp.rb'
284
+ ]
285
+
286
+ files_to_check.each do |file|
287
+ full_path = Rails.root.join(file)
288
+ if File.exist?(full_path)
289
+ executable = File.executable?(full_path)
290
+ puts " #{file}: ✅ #{'(executable)' if executable}"
291
+ else
292
+ puts " #{file}: ❌ Missing"
293
+ end
294
+ end
295
+
296
+ # Test basic functionality
297
+ puts "\n🧪 Functionality Test:"
298
+ begin
299
+ test_result = RailsActiveMcp.execute('1 + 1')
300
+ puts " Basic execution: #{test_result[:success] ? '✅' : '❌'}"
301
+ rescue StandardError => e
302
+ puts " Basic execution: ❌ (#{e.message})"
152
303
  end
304
+
305
+ puts "\n🔗 Integration URLs:"
306
+ puts ' Documentation: https://github.com/goodpie/rails-active-mcp'
307
+ puts ' Issues: https://github.com/goodpie/rails-active-mcp/issues'
308
+ puts ' MCP Protocol: https://modelcontextprotocol.io'
153
309
  end
154
- end
310
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsActiveMcp
4
- VERSION = '2.0.7'
4
+ VERSION = '2.0.12'
5
5
  end
@@ -5,6 +5,7 @@ require_relative 'rails_active_mcp/version'
5
5
  require_relative 'rails_active_mcp/configuration'
6
6
  require_relative 'rails_active_mcp/safety_checker'
7
7
  require_relative 'rails_active_mcp/console_executor'
8
+ require_relative 'rails_active_mcp/garbage_collection_utils'
8
9
 
9
10
  # Load SDK server
10
11
  require_relative 'rails_active_mcp/sdk/server'
@@ -42,15 +43,15 @@ module RailsActiveMcp
42
43
  end
43
44
 
44
45
  # Logger accessor - configured by engine or defaults to stderr
45
- attr_accessor :logger
46
-
47
46
  def logger
48
47
  @logger ||= Logger.new($stderr).tap do |logger|
49
48
  logger.level = Logger::INFO
50
- logger.formatter = proc do |severity, datetime, progname, msg|
49
+ logger.formatter = proc do |severity, datetime, _progname, msg|
51
50
  "[#{datetime}] #{severity} -- RailsActiveMcp: #{msg}\n"
52
51
  end
53
52
  end
54
53
  end
54
+
55
+ attr_writer :logger
55
56
  end
56
57
  end
data/mcp.ru CHANGED
@@ -1,5 +1,5 @@
1
- require_relative "config/environment"
2
- require_relative "lib/rails_active_mcp"
1
+ require_relative 'config/environment'
2
+ require_relative 'lib/rails_active_mcp'
3
3
 
4
4
  # Run the Rails Active MCP server
5
5
  run RailsActiveMcp::McpServer.new
@@ -8,34 +8,62 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['Brandyn Britton']
9
9
  spec.email = ['brandynbb96@gmail.com']
10
10
 
11
- spec.summary = 'Rails Console access via Model Context Protocol (MCP)'
12
- spec.description = 'Secure Rails console access for AI agents through Model Context Protocol with safety features and read-only modes'
11
+ spec.summary = 'Secure Rails console access via Model Context Protocol (MCP)'
12
+ spec.description = <<~DESC
13
+ Rails Active MCP enables secure Rails console access through Model Context Protocol (MCP)#{' '}
14
+ for AI agents and development tools like Claude Desktop. Provides safe database querying,#{' '}
15
+ model introspection, and code execution with comprehensive safety checks and audit logging.
16
+
17
+ Features include:
18
+ • Safe Ruby code execution with configurable safety checks
19
+ • Read-only database query tools with result limiting
20
+ • Rails model introspection (schema, associations, validations)
21
+ • Dry-run code analysis for safety validation
22
+ • Environment-specific configuration presets
23
+ • Comprehensive audit logging and monitoring
24
+ • Claude Desktop integration out of the box
25
+ DESC
26
+
13
27
  spec.homepage = 'https://github.com/goodpie/rails-active-mcp'
14
28
  spec.license = 'MIT'
15
- spec.required_ruby_version = '>= 3.0.0'
29
+ spec.required_ruby_version = '>= 3.1.0'
16
30
 
17
- spec.metadata['homepage_uri'] = spec.homepage
18
- spec.metadata['source_code_uri'] = spec.homepage
19
- spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
31
+ spec.metadata = {
32
+ 'homepage_uri' => spec.homepage,
33
+ 'source_code_uri' => "#{spec.homepage}/tree/main",
34
+ 'changelog_uri' => "#{spec.homepage}/blob/main/changelog.md",
35
+ 'bug_tracker_uri' => "#{spec.homepage}/issues",
36
+ 'documentation_uri' => "#{spec.homepage}#readme",
37
+ 'wiki_uri' => "#{spec.homepage}/wiki",
38
+ 'mailing_list_uri' => "#{spec.homepage}/discussions",
39
+ 'funding_uri' => 'https://github.com/sponsors/goodpie',
40
+ 'rubygems_mfa_required' => 'true'
41
+ }
20
42
 
21
- # Specify which files should be added to the gem when it is released.
43
+ # Specify which files should be added to the gem when it is released
22
44
  spec.files = Dir.chdir(__dir__) do
23
45
  `git ls-files -z`.split("\x0").reject do |f|
24
46
  (File.expand_path(f) == __FILE__) ||
25
- f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
47
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile]) ||
48
+ f.match?(%r{\A(?:log|tmp|\.)/}) ||
49
+ f.end_with?('.log', '.tmp')
26
50
  end
27
- end
51
+ end + [
52
+ 'examples/rails_app_integration.md',
53
+ 'docs/DEBUGGING.md',
54
+ 'docs/README.md'
55
+ ].select { |f| File.exist?(f) }
28
56
 
29
57
  spec.bindir = 'exe'
30
58
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
59
  spec.require_paths = ['lib']
32
60
 
33
61
  # Runtime dependencies - more flexible Rails version support
34
- spec.add_runtime_dependency 'concurrent-ruby', '~> 1.3'
35
- spec.add_runtime_dependency 'rails', '>= 6.1', '< 9.0'
62
+ spec.add_dependency 'concurrent-ruby', '~> 1.3'
63
+ spec.add_dependency 'rails', '>= 6.1', '< 9.0'
36
64
 
37
65
  # MCP SDK - Core protocol implementation
38
- spec.add_runtime_dependency 'mcp', '~> 0.1.0'
66
+ spec.add_dependency 'mcp', '~> 0.1.0'
39
67
 
40
68
  # Core dependencies
41
69
  spec.add_dependency 'json', '~> 2.0'
@@ -44,11 +72,31 @@ Gem::Specification.new do |spec|
44
72
  spec.add_dependency 'webrick', '~> 1.8'
45
73
 
46
74
  # Development dependencies - keep versions consistent with Gemfile
75
+ spec.add_development_dependency 'colorize', '~> 0.8'
47
76
  spec.add_development_dependency 'factory_bot_rails', '~> 6.0'
77
+ spec.add_development_dependency 'faker', '~> 2.19'
48
78
  spec.add_development_dependency 'rspec', '~> 3.1'
49
- spec.add_development_dependency 'rspec-rails'
79
+ spec.add_development_dependency 'rspec-rails', '~> 6.0'
50
80
  spec.add_development_dependency 'rubocop', '~> 1.77'
51
81
  spec.add_development_dependency 'rubocop-rails', '~> 2.32'
52
- spec.add_development_dependency 'rubocop-rspec'
82
+ spec.add_development_dependency 'rubocop-rspec', '~> 3.0'
53
83
  spec.add_development_dependency 'sqlite3', '~> 2.7'
84
+
85
+ # Post-install message to help users get started
86
+ spec.post_install_message = <<~MSG
87
+
88
+ 🎉 Thanks for installing Rails Active MCP!
89
+
90
+ Quick Start:
91
+ 1. Add to your Rails app: rails generate rails_active_mcp:install
92
+ 2. Test the setup: rails rails_active_mcp:status
93
+ 3. Configure Claude Desktop: rails rails_active_mcp:install_claude_config
94
+
95
+ 📚 Documentation: #{spec.homepage}#readme
96
+ 🐛 Issues: #{spec.homepage}/issues
97
+ 💬 Discussions: #{spec.homepage}/discussions
98
+
99
+ Follow the project: ⭐ #{spec.homepage}
100
+
101
+ MSG
54
102
  end