rails-ai-context 2.0.3 → 2.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 582aebf4849cdb8617b33dff88f3822009b8960e1334bbd1aa2eb6a3f6a03350
4
- data.tar.gz: 03c8eedbf4989f07a75f878fe86380b809dd4ae1e2afd0020836a848da99b5c3
3
+ metadata.gz: 70a0eb825c34329a1f0bc9d387a4a2bfd2a42b56717305dcaa5df4c0712264f7
4
+ data.tar.gz: 5a2e229f4bbcaf39d9eebe3e3851444ceed0860b79ad4bcccf11fdba9487ac0a
5
5
  SHA512:
6
- metadata.gz: 5a2abfe4dc7c9c123dacd427354789810197c478fab741ac88e9aa0d8c95fcccc5cac2b5005f01615cf678f7229362d3e4ea5838d7c76d2210b28a8531edd9da
7
- data.tar.gz: 3f04bb928f49325badb6a956a54c1adb9dec73ac2f73b9d7f81831f5da5931ac0ef1f4494a5c71780cdabcfa159c38ff11a4bd6f7fbcbb7ac79272aaf5de4e3b
6
+ metadata.gz: eca131443eb443b24a7681233f5e5adcef9a2c2fb3f4ee6d4e665c795470bed1e0bfdfa92f4f4861136f3e7c2b34210972273b2d0b976f3ffb7fa88834ed31b7
7
+ data.tar.gz: b2e96f95e25b8e9cf9fb140446969fc7a027ff22e210321c3ade42da59aa7c6ed702ceabc0c8be62e8a56c2fa25230dcb460bfd3182716c3a1ef1cc300b836bb
data/CHANGELOG.md CHANGED
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.0.4] - 2026-03-25
9
+
10
+ ### Added
11
+
12
+ - **Orphaned table detection** — `get_schema` standard mode flags tables with no ActiveRecord model: "⚠ Orphaned tables: content_calendars, cook_comments"
13
+ - **Concern method source code** — `get_concern(name:"X", detail:"full")` shows method bodies inline, same pattern as callbacks tool.
14
+ - **analyze_feature: inherited filters** — shows `authenticate_user! (from ApplicationController)` in controller section.
15
+ - **analyze_feature: code-ready route helpers** — `cook_path(@record)`, `cooks_path` inline with routes.
16
+ - **analyze_feature: service test gaps** — checks services for missing test files, not just models/controllers/jobs.
17
+ - **All 6 serializers updated** — Claude, Cursor, Copilot, Windsurf, OpenCode all document trace mode, concern source, orphaned tables, inherited filters.
18
+
8
19
  ## [2.0.3] - 2026-03-25
9
20
 
10
21
  ### Added
@@ -344,8 +344,8 @@ module RailsAiContext
344
344
  "",
345
345
  "## Tools (25)",
346
346
  "",
347
- "**rails_get_schema** — database tables, columns, indexes, foreign keys",
348
- "- `rails_get_schema(detail:\"summary\")` — all tables with column counts",
347
+ "**rails_get_schema** — database tables, columns, indexes, foreign keys, orphaned table detection",
348
+ "- `rails_get_schema(detail:\"summary\")` — all tables with column counts + orphaned tables (tables with no ActiveRecord model)",
349
349
  "- `rails_get_schema(table:\"users\")` — full detail for one table",
350
350
  "",
351
351
  "**rails_get_model_details** — associations, validations, scopes, enums, callbacks",
@@ -381,7 +381,7 @@ module RailsAiContext
381
381
  "- `rails_validate(files:[\"app/models/cook.rb\"])` — checks Ruby, ERB, JS syntax in one call",
382
382
  "",
383
383
  "**rails_analyze_feature** — combined schema + models + controllers + routes for a feature area",
384
- "- `rails_analyze_feature(feature:\"authentication\")` — one call gets everything related to a feature",
384
+ "- `rails_analyze_feature(feature:\"authentication\")` — one call gets everything related to a feature, including inherited filters from parent controllers and code-ready route helpers",
385
385
  "",
386
386
  "**rails_get_design_system** — color palette, component patterns, canonical page examples",
387
387
  "- `rails_get_design_system(detail:\"standard\")` — colors + components + real HTML examples + design rules",
@@ -390,13 +390,17 @@ module RailsAiContext
390
390
  "**rails_get_config** — cache store, session, timezone, middleware, initializers",
391
391
  "**rails_get_gems** — notable gems categorized by function",
392
392
  "**rails_get_conventions** — architecture patterns, directory structure",
393
- "**rails_search_code** — regex search: `rails_search_code(pattern:\"regex\", file_type:\"rb\")`",
393
+ "**rails_search_code** — regex search with trace mode for deep call-chain analysis",
394
+ "- `rails_search_code(pattern:\"regex\", file_type:\"rb\")` — basic regex search across files",
395
+ "- `rails_search_code(pattern:\"can_cook?\", match_type:\"trace\")` — trace mode: definition + class context + source + siblings + callers with route chain + test coverage",
396
+ "- `rails_search_code(pattern:\"cook\", exclude_tests: true)` — search app code only, skip test files",
394
397
  "",
395
398
  "**rails_security_scan** — Brakeman security analysis",
396
399
  "- `rails_security_scan` — run security scan, returns warnings by confidence",
397
400
  "",
398
401
  "**rails_get_concern** — concern methods and includers",
399
402
  "- `rails_get_concern(name:\"Searchable\")` — methods, included modules, includers",
403
+ "- `rails_get_concern(name:\"Searchable\", detail:\"full\")` — + method source code",
400
404
  "",
401
405
  "**rails_get_callbacks** — model callbacks in execution order",
402
406
  "- `rails_get_callbacks(model:\"User\")` — before/after/around callbacks by type",
@@ -214,11 +214,11 @@ module RailsAiContext
214
214
  "### Quick Reference",
215
215
  "| Need | Use this MCP tool | Do NOT use |",
216
216
  "|------|-------------------|------------|",
217
- "| Column types | `rails_get_schema(table:\"x\")` | Read db/schema.rb |",
217
+ "| Column types | `rails_get_schema(table:\"x\")` — includes orphaned table warnings | Read db/schema.rb |",
218
218
  "| Model associations | `rails_get_model_details(model:\"X\")` | Read app/models/x.rb |",
219
219
  "| Route paths | `rails_get_routes(controller:\"x\")` | Read config/routes.rb |",
220
- "| Feature overview | `rails_analyze_feature(feature:\"x\")` | Explore agent / Grep |",
221
- "| Find code | `rails_search_code(pattern:\"x\")` | Grep tool |",
220
+ "| Feature overview | `rails_analyze_feature(feature:\"x\")` — models + controllers (inherited filters) + routes (code-ready helpers) + services + jobs + views + tests + gaps | Explore agent / Grep |",
221
+ "| Find code | `rails_search_code(pattern:\"x\", match_type:\"trace\")` | Grep tool |",
222
222
  "| Validate edits | `rails_validate(files:[...])` | ruby -c / erb / node |",
223
223
  "| Controller logic | `rails_get_controllers(controller:\"X\", action:\"y\")` | Read controller file |",
224
224
  "| UI patterns | `rails_get_design_system` | Read view files |",
@@ -227,10 +227,11 @@ module RailsAiContext
227
227
  "| Full context | `rails_get_context(model:\"X\")` | Multiple Read calls |",
228
228
  "",
229
229
  "### More Tools",
230
- "- `rails_get_view(controller:\"x\")` | `rails_get_concern(name:\"X\")` | `rails_get_callbacks(model:\"X\")`",
230
+ "- `rails_get_view(controller:\"x\")` | `rails_get_concern(name:\"X\", detail:\"full\")` — concern methods with source code | `rails_get_callbacks(model:\"X\")`",
231
231
  "- `rails_get_helper_methods` | `rails_get_service_pattern` | `rails_get_job_pattern`",
232
232
  "- `rails_get_env` | `rails_get_partial_interface(path:\"shared/_form\")` | `rails_get_turbo_map`",
233
233
  "- `rails_get_config` | `rails_get_gems` | `rails_get_conventions` | `rails_security_scan`",
234
+ "- `rails_search_code(pattern:\"method\", match_type:\"trace\")` — **trace mode**: definition + class context + source + siblings + callers + test coverage in one call",
234
235
  "- `rails_get_edit_context(file:\"path\", near:\"keyword\")` — surgical edit helper with line numbers",
235
236
  ""
236
237
  ]
@@ -250,7 +250,13 @@ module RailsAiContext
250
250
  "- `rails_get_config` | `rails_get_gems` | `rails_get_conventions` | `rails_security_scan`",
251
251
  "- `rails_get_concern` | `rails_get_callbacks` | `rails_get_helper_methods` | `rails_get_service_pattern`",
252
252
  "- `rails_get_job_pattern` | `rails_get_env` | `rails_get_partial_interface` | `rails_get_turbo_map`",
253
- "- `rails_get_context(model:\"X\")` — composite cross-layer context in one call"
253
+ "- `rails_get_context(model:\"X\")` — composite cross-layer context in one call",
254
+ "",
255
+ "## Power Features",
256
+ "- `rails_search_code(pattern:\"method\", match_type:\"trace\")` — trace: definition + source + siblings + callers + tests",
257
+ "- `rails_get_concern(name:\"X\", detail:\"full\")` — concern methods with source code",
258
+ "- `rails_analyze_feature` — full-stack with inherited filters, route helpers, test gaps",
259
+ "- `rails_get_schema` — columns, indexes, defaults, encrypted hints, orphaned table warnings"
254
260
  ]
255
261
 
256
262
  lines.join("\n")
@@ -290,7 +290,13 @@ module RailsAiContext
290
290
  "- `rails_get_config` | `rails_get_gems` | `rails_get_conventions` | `rails_security_scan`",
291
291
  "- `rails_get_concern` | `rails_get_callbacks` | `rails_get_helper_methods` | `rails_get_service_pattern`",
292
292
  "- `rails_get_job_pattern` | `rails_get_env` | `rails_get_partial_interface` | `rails_get_turbo_map`",
293
- "- `rails_get_context(model:\"X\")` — composite cross-layer context in one call"
293
+ "- `rails_get_context(model:\"X\")` — composite cross-layer context in one call",
294
+ "",
295
+ "## Power Features",
296
+ "- `rails_search_code(pattern:\"method\", match_type:\"trace\")` — trace: definition + source + siblings + callers + tests",
297
+ "- `rails_get_concern(name:\"X\", detail:\"full\")` — concern methods with source code",
298
+ "- `rails_analyze_feature` — full-stack with inherited filters, route helpers, test gaps",
299
+ "- `rails_get_schema` — columns, indexes, defaults, encrypted hints, orphaned table warnings"
294
300
  ]
295
301
 
296
302
  lines.join("\n")
@@ -172,7 +172,7 @@ module RailsAiContext
172
172
  "Start with `detail:\"summary\"`, then drill into specifics.",
173
173
  "",
174
174
  "### Mandatory Workflow",
175
- "1. **Before exploring a feature**: `rails_analyze_feature(feature:\"...\")` — NOT file reads or grep",
175
+ "1. **Before exploring a feature**: `rails_analyze_feature(feature:\"...\")` — models + controllers (inherited filters) + routes (code-ready helpers) + services + jobs + views + tests + gaps",
176
176
  "2. **Before writing migrations**: `rails_get_schema(table:\"...\")` — NOT reading db/schema.rb",
177
177
  "3. **Before modifying a model**: `rails_get_model_details(model:\"...\")` — NOT reading the model file",
178
178
  "4. **Before adding routes**: `rails_get_routes(controller:\"...\")` — Read only when you will edit",
@@ -182,10 +182,10 @@ module RailsAiContext
182
182
  "### Do NOT Bypass",
183
183
  "| Instead of... | Use this MCP tool |",
184
184
  "|---------------|-------------------|",
185
- "| Reading db/schema.rb | `rails_get_schema(table:\"x\")` |",
185
+ "| Reading db/schema.rb | `rails_get_schema(table:\"x\")` — includes orphaned table warnings |",
186
186
  "| Reading model files | `rails_get_model_details(model:\"X\")` |",
187
187
  "| Reading routes.rb | `rails_get_routes(controller:\"x\")` |",
188
- "| Grep for code | `rails_search_code(pattern:\"x\")` |",
188
+ "| Grep for code | `rails_search_code(pattern:\"x\", match_type:\"trace\")` |",
189
189
  "| Reading test files | `rails_get_test_info(model:\"X\")` |",
190
190
  "| Reading controller | `rails_get_controllers(controller:\"X\", action:\"y\")` |",
191
191
  "| ruby -c / erb / node | `rails_validate(files:[...])` |",
@@ -195,8 +195,9 @@ module RailsAiContext
195
195
  "- `rails_get_view` | `rails_get_stimulus` | `rails_get_test_info` | `rails_analyze_feature`",
196
196
  "- `rails_get_design_system` | `rails_get_edit_context` | `rails_validate` | `rails_search_code`",
197
197
  "- `rails_get_config` | `rails_get_gems` | `rails_get_conventions` | `rails_security_scan`",
198
- "- `rails_get_concern` | `rails_get_callbacks` | `rails_get_helper_methods` | `rails_get_service_pattern`",
198
+ "- `rails_get_concern(name:\"X\", detail:\"full\")` — concern methods with source code | `rails_get_callbacks` | `rails_get_helper_methods` | `rails_get_service_pattern`",
199
199
  "- `rails_get_job_pattern` | `rails_get_env` | `rails_get_partial_interface` | `rails_get_turbo_map`",
200
+ "- `rails_search_code(pattern:\"method\", match_type:\"trace\")` — **trace mode**: definition + class context + source + siblings + callers + test coverage in one call",
200
201
  "- `rails_get_context(model:\"X\")` — composite cross-layer context in one call",
201
202
  ""
202
203
  ]
@@ -95,7 +95,13 @@ module RailsAiContext
95
95
  "- rails_get_config | rails_get_gems | rails_get_conventions | rails_security_scan",
96
96
  "- rails_get_concern | rails_get_callbacks | rails_get_helper_methods | rails_get_service_pattern",
97
97
  "- rails_get_job_pattern | rails_get_env | rails_get_partial_interface | rails_get_turbo_map",
98
- "- rails_get_context(model:\"X\") — composite cross-layer context in one call"
98
+ "- rails_get_context(model:\"X\") — composite cross-layer context in one call",
99
+ "",
100
+ "Power Features:",
101
+ "- rails_search_code(pattern:\"method\", match_type:\"trace\") — trace: definition + source + siblings + callers + tests",
102
+ "- rails_get_concern(name:\"X\", detail:\"full\") — concern methods with source code",
103
+ "- rails_analyze_feature — full-stack with inherited filters, route helpers, test gaps",
104
+ "- rails_get_schema — columns, indexes, defaults, encrypted hints, orphaned table warnings"
99
105
  ]
100
106
 
101
107
  lines.join("\n")
@@ -114,11 +114,17 @@ module RailsAiContext
114
114
  actions = info[:actions]&.join(", ") || "none"
115
115
  lines << "" << "### #{name}"
116
116
  lines << "- **Actions:** #{actions}"
117
+
118
+ # Inherited filters from parent controller
119
+ parent_filters = detect_parent_filters_for_analyze(info[:parent_class], controllers)
120
+ if parent_filters.any?
121
+ lines << "- **Inherited filters:** #{parent_filters.map { |f| "#{f[:name]} _(from #{info[:parent_class]})_" }.join(', ')}"
122
+ end
123
+
117
124
  filters = (info[:filters] || []).select { |f| f.is_a?(Hash) }.map do |f|
118
125
  label = "#{f[:kind]} #{f[:name]}"
119
126
  label += " only: #{Array(f[:only]).join(', ')}" if f[:only]&.any?
120
127
  label += " except: #{Array(f[:except]).join(', ')}" if f[:except]&.any?
121
- label += " unless: #{f[:unless]}" if f[:unless]
122
128
  label
123
129
  end
124
130
  lines << "- **Filters:** #{filters.join('; ')}" if filters.any?
@@ -139,8 +145,14 @@ module RailsAiContext
139
145
  lines << "## Routes (#{route_count})"
140
146
  matched.sort.each do |ctrl, actions|
141
147
  actions.each do |r|
142
- name_part = r[:name] ? " `#{r[:name]}`" : ""
143
- lines << "- `#{r[:verb]}` `#{r[:path]}` → #{ctrl}##{r[:action]}#{name_part}"
148
+ params = r[:path].scan(/:(\w+)/).flatten
149
+ helper = if r[:name]
150
+ args = params.any? ? "(#{params.map { |p| p == "id" ? "@record" : ":#{p}" }.join(', ')})" : ""
151
+ " `#{r[:name]}_path#{args}`"
152
+ else
153
+ ""
154
+ end
155
+ lines << "- `#{r[:verb]}` `#{r[:path]}` → #{ctrl}##{r[:action]}#{helper}"
144
156
  end
145
157
  end
146
158
  else
@@ -321,6 +333,18 @@ module RailsAiContext
321
333
  end
322
334
  end
323
335
 
336
+ # Check services
337
+ service_dir = File.join(root, "app", "services")
338
+ if Dir.exist?(service_dir)
339
+ Dir.glob(File.join(service_dir, "**", "*.rb")).each do |path|
340
+ next unless File.basename(path, ".rb").include?(pattern)
341
+ snake = File.basename(path, ".rb")
342
+ unless test_basenames.any? { |t| t.include?(snake) }
343
+ gaps << "Service `#{snake}` — no test file found"
344
+ end
345
+ end
346
+ end
347
+
324
348
  return if gaps.empty?
325
349
 
326
350
  lines << "## Test Coverage Gaps"
@@ -330,6 +354,28 @@ module RailsAiContext
330
354
  nil
331
355
  end
332
356
 
357
+ # Detect inherited filters from parent controller
358
+ def detect_parent_filters_for_analyze(parent_class, all_controllers)
359
+ return [] unless parent_class
360
+ parent_data = all_controllers[parent_class]
361
+ if parent_data
362
+ return (parent_data[:filters] || []).select { |f| f.is_a?(Hash) && f[:kind] == "before" && !f[:only]&.any? }
363
+ end
364
+
365
+ # Fallback: read source file
366
+ path = Rails.root.join("app", "controllers", "#{parent_class.underscore}.rb")
367
+ return [] unless File.exist?(path)
368
+ source = File.read(path, encoding: "UTF-8") rescue nil
369
+ return [] unless source
370
+
371
+ source.each_line.filter_map do |line|
372
+ next if line.include?("only:") || line.include?("except:")
373
+ { name: $1 } if line.match(/\A\s*before_action\s+:(\w+)/)
374
+ end
375
+ rescue
376
+ []
377
+ end
378
+
333
379
  # --- AF6: Related Models via Associations ---
334
380
  def discover_related_models(ctx, matched_models, lines)
335
381
  return if matched_models.empty?
@@ -18,13 +18,18 @@ module RailsAiContext
18
18
  type: "string",
19
19
  enum: %w[model controller all],
20
20
  description: "Filter by concern type. model: app/models/concerns/. controller: app/controllers/concerns/. all: both (default)."
21
+ },
22
+ detail: {
23
+ type: "string",
24
+ enum: %w[summary standard full],
25
+ description: "Detail level. summary: concern names only. standard: names + method signatures (default). full: method signatures with source code."
21
26
  }
22
27
  }
23
28
  )
24
29
 
25
30
  annotations(read_only_hint: true, destructive_hint: false, idempotent_hint: true, open_world_hint: false)
26
31
 
27
- def self.call(name: nil, type: "all", server_context: nil)
32
+ def self.call(name: nil, type: "all", detail: "standard", server_context: nil)
28
33
  root = rails_app.root.to_s
29
34
  max_size = RailsAiContext.configuration.max_file_size
30
35
 
@@ -36,7 +41,7 @@ module RailsAiContext
36
41
 
37
42
  # Specific concern — full detail
38
43
  if name
39
- return show_concern(name, concern_dirs, root, max_size)
44
+ return show_concern(name, concern_dirs, root, max_size, detail)
40
45
  end
41
46
 
42
47
  # List all concerns
@@ -67,7 +72,7 @@ module RailsAiContext
67
72
  end
68
73
  end
69
74
 
70
- private_class_method def self.show_concern(name, concern_dirs, root, max_size)
75
+ private_class_method def self.show_concern(name, concern_dirs, root, max_size, detail = "standard")
71
76
  # Find the concern file — try underscore variants and nested paths
72
77
  underscore = name.underscore
73
78
  file_path = nil
@@ -121,14 +126,47 @@ module RailsAiContext
121
126
  public_methods = parse_public_methods(source)
122
127
  if public_methods.any?
123
128
  lines << "" << "## Public Methods"
124
- public_methods.each { |m| lines << "- `#{m}`" }
129
+ if detail == "full"
130
+ public_methods.each do |m|
131
+ method_name = m.to_s.split("(").first
132
+ method_source = extract_method_source(source, method_name)
133
+ if method_source
134
+ lines << "### #{m}"
135
+ lines << "```ruby"
136
+ lines << method_source
137
+ lines << "```"
138
+ lines << ""
139
+ else
140
+ lines << "- `#{m}`"
141
+ end
142
+ end
143
+ else
144
+ public_methods.each { |m| lines << "- `#{m}`" }
145
+ end
125
146
  end
126
147
 
127
148
  # Parse class methods (inside class_methods block or def self.)
128
149
  class_methods = parse_class_methods(source)
129
150
  if class_methods.any?
130
151
  lines << "" << "## Class Methods"
131
- class_methods.each { |m| lines << "- `#{m}`" }
152
+ if detail == "full"
153
+ class_methods.each do |m|
154
+ method_name = m.to_s.split("(").first
155
+ # Try both `def method_name` and `def self.method_name`
156
+ method_source = extract_method_source(source, method_name) || extract_method_source(source, "self.#{method_name}")
157
+ if method_source
158
+ lines << "### #{m}"
159
+ lines << "```ruby"
160
+ lines << method_source
161
+ lines << "```"
162
+ lines << ""
163
+ else
164
+ lines << "- `#{m}`"
165
+ end
166
+ end
167
+ else
168
+ class_methods.each { |m| lines << "- `#{m}`" }
169
+ end
132
170
  end
133
171
 
134
172
  # Parse callbacks defined in the concern
@@ -345,6 +383,25 @@ module RailsAiContext
345
383
  []
346
384
  end
347
385
 
386
+ # Extract method source from raw source string using indentation-based matching
387
+ private_class_method def self.extract_method_source(source, method_name)
388
+ source_lines = source.lines
389
+ start_idx = source_lines.index { |l| l.match?(/\A\s*def\s+#{Regexp.escape(method_name.to_s)}\b/) }
390
+ return nil unless start_idx
391
+
392
+ def_indent = source_lines[start_idx][/\A\s*/].length
393
+ result = []
394
+
395
+ source_lines[start_idx..].each_with_index do |line, i|
396
+ result << line.rstrip
397
+ break if i > 0 && line.match?(/\A\s{#{def_indent}}end\b/)
398
+ end
399
+
400
+ result.join("\n")
401
+ rescue
402
+ nil
403
+ end
404
+
348
405
  private_class_method def self.find_includers(concern_name, root, concern_type)
349
406
  includers = []
350
407
  search_dirs = []
@@ -160,6 +160,14 @@ module RailsAiContext
160
160
  lines << cols
161
161
  lines << ""
162
162
  end
163
+
164
+ # Detect orphaned tables (no ActiveRecord model maps to them)
165
+ orphaned = paginated.select { |name| models_for_table(name).empty? }
166
+ if orphaned.any?
167
+ lines << "\u26A0 **Orphaned tables** (no ActiveRecord model): #{orphaned.join(', ')}"
168
+ lines << ""
169
+ end
170
+
163
171
  lines << "_Use `detail:\"summary\"` for all #{total} tables, `detail:\"full\"` for indexes/FKs, or `table:\"name\"` for one table._" if total > limit
164
172
  text_response(lines.join("\n"))
165
173
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsAiContext
4
- VERSION = "2.0.3"
4
+ VERSION = "2.0.4"
5
5
  end
data/server.json CHANGED
@@ -7,11 +7,11 @@
7
7
  "url": "https://github.com/crisnahine/rails-ai-context",
8
8
  "source": "github"
9
9
  },
10
- "version": "2.0.3",
10
+ "version": "2.0.4",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "mcpb",
14
- "identifier": "https://github.com/crisnahine/rails-ai-context/releases/download/v2.0.3/rails-ai-context-mcp.mcpb",
14
+ "identifier": "https://github.com/crisnahine/rails-ai-context/releases/download/v2.0.4/rails-ai-context-mcp.mcpb",
15
15
  "fileSha256": "dd711a0ad6c4de943ae4da94eaf59a6dc9494b9d57f726e24649ed4e2f156990",
16
16
  "transport": {
17
17
  "type": "stdio"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-ai-context
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - crisnahine