rails-ai-context 5.4.0 → 5.7.0

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +77 -0
  3. data/CONTRIBUTING.md +1 -1
  4. data/README.md +101 -76
  5. data/SECURITY.md +6 -0
  6. data/app/controllers/rails_ai_context/mcp_controller.rb +1 -1
  7. data/docs/ARCHITECTURE.md +244 -0
  8. data/docs/CLI.md +234 -0
  9. data/docs/CONFIGURATION.md +235 -0
  10. data/docs/CUSTOM_TOOLS.md +214 -0
  11. data/docs/FAQ.md +240 -0
  12. data/docs/GUIDE.md +89 -41
  13. data/docs/INTROSPECTORS.md +211 -0
  14. data/docs/QUICKSTART.md +118 -0
  15. data/docs/RECIPES.md +390 -0
  16. data/docs/SECURITY.md +238 -0
  17. data/docs/SETUP.md +359 -0
  18. data/docs/STANDALONE.md +169 -0
  19. data/docs/TOOLS.md +495 -0
  20. data/docs/TROUBLESHOOTING.md +285 -0
  21. data/docs/_config.yml +15 -0
  22. data/docs/_includes/head-custom.html +16 -0
  23. data/docs/index.md +54 -0
  24. data/docs/social-preview.html +164 -0
  25. data/exe/rails-ai-context +44 -29
  26. data/lib/generators/rails_ai_context/install/install_generator.rb +42 -37
  27. data/lib/rails_ai_context/ast_cache.rb +2 -2
  28. data/lib/rails_ai_context/cli/tool_runner.rb +1 -1
  29. data/lib/rails_ai_context/configuration.rb +1 -1
  30. data/lib/rails_ai_context/doctor.rb +142 -21
  31. data/lib/rails_ai_context/mcp_config_generator.rb +293 -0
  32. data/lib/rails_ai_context/serializers/claude_rules_serializer.rb +17 -0
  33. data/lib/rails_ai_context/serializers/context_file_serializer.rb +19 -4
  34. data/lib/rails_ai_context/serializers/copilot_instructions_serializer.rb +8 -0
  35. data/lib/rails_ai_context/serializers/cursor_rules_serializer.rb +3 -3
  36. data/lib/rails_ai_context/serializers/markdown_serializer.rb +1 -1
  37. data/lib/rails_ai_context/serializers/tool_guide_helper.rb +3 -3
  38. data/lib/rails_ai_context/server.rb +23 -42
  39. data/lib/rails_ai_context/tasks/rails_ai_context.rake +40 -30
  40. data/lib/rails_ai_context/test_helper.rb +123 -0
  41. data/lib/rails_ai_context/tools/analyze_feature.rb +2 -2
  42. data/lib/rails_ai_context/tools/base_tool.rb +69 -0
  43. data/lib/rails_ai_context/tools/get_concern.rb +11 -4
  44. data/lib/rails_ai_context/tools/get_partial_interface.rb +5 -0
  45. data/lib/rails_ai_context/tools/migration_advisor.rb +1 -1
  46. data/lib/rails_ai_context/tools/query.rb +5 -5
  47. data/lib/rails_ai_context/tools/runtime_info.rb +4 -0
  48. data/lib/rails_ai_context/tools/search_code.rb +13 -9
  49. data/lib/rails_ai_context/version.rb +1 -1
  50. data/server.json +3 -3
  51. metadata +22 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43e8a71c793404bd950627b8f3319b4e909a0ba7a2cfe937a8d1027e2ede4af0
4
- data.tar.gz: f296960edc1f3f336e90b9549618fd4b48d51d31330d95a65de9304ba47aa0af
3
+ metadata.gz: 313744756e1399207abeb841866440c3de88da5863f92163fd7d344b60c479c5
4
+ data.tar.gz: 4de97686b1d62c8444a76ed78fc709aade9e0e004adae1a7a655c7d0eae8ce23
5
5
  SHA512:
6
- metadata.gz: bc10e825ef820ad955e89ded454469104160f954b967958866876794b1c114d9b708564e99781f1252cf4faa683d468bf5143823ee3418080de43ef745508ab2
7
- data.tar.gz: 127d4159c5d88da79ae7fcb7389ffb84cca28621e0181da7b7e495e6af6fe0f8c0073b37dff3087a67be78c236e6f09e36aaef82e070461406e8a2027d88d2a8
6
+ metadata.gz: 0df4cd4cd7c0e99f8c1e662baae65a960819ed8bea551e8bb536bf06cf2b1ba6c42fee462668e990c2bf48572d5b65b66b6f38c730f643c2cd6e19b751ab7a9c
7
+ data.tar.gz: 88df4ee906be73bb71212bf47acc88e09efe0ac82a87abef786a3f9a829c5aed57bdb63d19c58d6f5a4361d8ebf5955b3ce29a09235a84aa01e9c204e7ee9471
data/CHANGELOG.md CHANGED
@@ -5,6 +5,83 @@ 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
+ ## [5.7.0] — 2026-04-09
9
+
10
+ ### Quickstart — Two commands. Problem gone.
11
+
12
+ ```bash
13
+ gem "rails-ai-context", group: :development
14
+ rails generate rails_ai_context:install
15
+ ```
16
+
17
+ ### Fixed — Bug Fixes from Codebase Audit
18
+
19
+ 6 bug fixes discovered via automated codebase audit (bug-finder, code-reviewer, doc-consistency-checker agents).
20
+
21
+ - **AnalyzeFeature service/mailer method extraction** (HIGH) — `\A` (start-of-string) anchor in `scan` regex replaced with `^` (start-of-line). Services and mailers now correctly list all methods instead of always returning empty arrays.
22
+
23
+ - **SearchCode exact_match + definition double-escaping** (HIGH) — Word boundaries (`\b`) were applied before `Regexp.escape`, producing unmatchable regex when combining `exact_match: true` with `match_type: "definition"` or `"class"`. Boundaries now applied per-match_type after escaping.
24
+
25
+ - **MigrationAdvisor empty string column bypass** (MEDIUM) — Empty string `""` column names bypassed the "column required" validation (Ruby truthiness). Now normalized via `.presence` so empty strings become `nil` and are caught.
26
+
27
+ - **GetConcern class method block tracking** — Regex no longer matches `def self.method` as a `class_methods do` block entry, preventing instance methods after `def self.` from being incorrectly skipped.
28
+
29
+ - **AstCache eviction comment accuracy** — Comment corrected from "evicts oldest entries" to "arbitrary selection" since `Concurrent::Map` has no ordering guarantee.
30
+
31
+ - **SECURITY.md supported versions** — Added missing 5.6.x row to supported versions table.
32
+
33
+ - **CONFIGURATION.md preset count** — Fixed stale `:standard` preset count from 13 to 17.
34
+
35
+ ## [5.6.0] — 2026-04-09
36
+
37
+ ### Added — Auto-Registration, TestHelper & Bug Fixes
38
+
39
+ Developer experience improvements inspired by action_mcp patterns, plus 5 security/correctness bug fixes.
40
+
41
+ - **Auto-registration via `inherited` hook** — Tools are now auto-discovered from `BaseTool` subclasses. No manual list to maintain — drop a file in `tools/` and it's registered. `Server.builtin_tools` is the new public API. Thread-safe via `@registry_mutex` with deadlock-free design (const_get runs outside mutex to avoid recursive locking from inherited). `Server::TOOLS` preserved as deprecated `const_missing` shim for backwards compatibility.
42
+
43
+ - **`abstract!` pattern** — `BaseTool.abstract!` excludes a class from the registry. `BaseTool` itself is abstract. Subclasses are concrete by default.
44
+
45
+ - **TestHelper module** (`lib/rails_ai_context/test_helper.rb`) — Reusable test helper for custom_tools users. Methods: `execute_tool` (by name, short name, or class), `execute_tool_with_error`, `assert_tool_findable`, `assert_tool_response_includes`, `assert_tool_response_excludes`, `extract_response_text`. Works with both RSpec and Minitest. Supports fuzzy name resolution (`schema` → `rails_get_schema`).
46
+
47
+ ### Fixed
48
+
49
+ - **SQL comment stripping validation bypass** (HIGH) — `#` comment stripping now restricted to line-start only, preventing validation bypass via hash characters in string literals. PostgreSQL JSONB operators (`#>>`) preserved.
50
+
51
+ - **SHARED_CACHE read outside mutex** (MEDIUM) — `redact_results` now uses `cached_context` for thread-safe access to encrypted column data.
52
+
53
+ - **McpController double-checked locking** (MEDIUM) — Removed unsynchronized read outside mutex, fixing unsafe pattern on non-GVL Rubies (JRuby/TruffleRuby).
54
+
55
+ - **PG EXPLAIN parser bare rescue** (LOW) — Changed from `rescue` to `rescue JSON::ParserError`, preventing silent swallowing of bugs in `extract_pg_nodes`.
56
+
57
+ - **GetConcern `class_methods` block closing** (LOW) — Indent-based tracking to detect the closing `end`, so `def self.` methods after the block are no longer lost.
58
+
59
+ - **Query spec graceful degradation** — Replaced permanently-pending spec (sqlite3 2.x removed `set_progress_handler`) with a spec that verifies queries execute correctly without it.
60
+
61
+ ## [5.5.0] — 2026-04-08
62
+
63
+ ### Added — Universal MCP Auto-Discovery & Per-Tool Context Optimization (#51-#56)
64
+
65
+ Every AI tool now gets its own MCP config file — auto-detected on project open. No manual setup needed for any supported tool.
66
+
67
+ - **McpConfigGenerator** (`lib/rails_ai_context/mcp_config_generator.rb`) — Shared infrastructure for per-tool MCP config generation. Writes `.mcp.json` (Claude Code), `.cursor/mcp.json` (Cursor), `.vscode/mcp.json` (GitHub Copilot), `opencode.json` (OpenCode), `.codex/config.toml` (Codex CLI). Merge-safe — only manages the `rails-ai-context` entry, preserves other servers. Supports standalone mode and CLI skip.
68
+
69
+ - **Codex CLI support** (#51) — 5th supported AI tool. Reuses `AGENTS.md` (shared with OpenCode) and `OpencodeRulesSerializer` for directory-level split rules. Config via `.codex/config.toml` (TOML format) with `[mcp_servers.rails-ai-context.env]` subsection that snapshots Ruby environment variables at install time — required because Codex CLI `env_clear()`s the process before spawning MCP servers. Works with all Ruby version managers (rbenv, rvm, asdf, mise, chruby, system). Added to all 3 install paths (generator, CLI, rake), doctor checks, and search exclusions.
70
+
71
+ - **Cursor improvements** (#52) — `.cursor/mcp.json` auto-generated for MCP auto-discovery. MCP tools rule changed from `alwaysApply: true` to `alwaysApply: false` with descriptive text for agent-requested (Type 3) loading.
72
+
73
+ - **OpenCode improvements** (#53) — `opencode.json` auto-generated for MCP auto-discovery.
74
+
75
+ - **Claude Code improvements** (#54) — `paths:` YAML frontmatter added to `.claude/rules/` schema, models, and components rules for conditional loading. Context and mcp-tools rules remain unconditional.
76
+
77
+ - **Copilot improvements** (#55) — `.vscode/mcp.json` auto-generated for MCP auto-discovery. `name:` and `description:` YAML frontmatter added to all `.github/instructions/` files. Updated `excludeAgent` spec to validate `code-review`, `coding-agent`, and `workspace` per GitHub Copilot docs.
78
+
79
+ - **All 3 install paths updated** — Install generator, standalone CLI (`rails-ai-context init`), and rake task (`rails ai:setup`) all delegate to McpConfigGenerator. Codex added as option "5" in interactive tool selection.
80
+
81
+ - **Doctor expanded** — `check_mcp_json` now validates per-tool MCP configs based on configured `ai_tools` (JSON parse validation + TOML existence check).
82
+
83
+ - **Search exclusions** — `.codex/`, `.vscode/mcp.json`, `opencode.json` added to `search_code` tool exclusions.
84
+
8
85
  ## [5.4.0] — 2026-04-08
9
86
 
10
87
  ### Added — Phase 3: Dynamic VFS & Live Resource Architecture (Ground Truth Engine Blueprint #39)
data/CONTRIBUTING.md CHANGED
@@ -41,7 +41,7 @@ lib/rails_ai_context/
41
41
  1. Create `lib/rails_ai_context/tools/your_tool.rb` inheriting from `BaseTool` (auto-loaded by Zeitwerk)
42
42
  2. Define `tool_name`, `description`, `input_schema`, and `annotations`
43
43
  3. Implement `def self.call(...)` returning `text_response(string)`
44
- 4. Register in `Server::TOOLS`
44
+ 4. Auto-registered no manual list to update (BaseTool.inherited tracks it)
45
45
  5. Write specs in `spec/lib/rails_ai_context/tools/your_tool_spec.rb`
46
46
 
47
47
  ## Adding a Prism Listener
data/README.md CHANGED
@@ -9,7 +9,8 @@
9
9
  <a href="https://cursor.com"><img src="https://img.shields.io/badge/Cursor-000000?style=for-the-badge&logo=cursor&logoColor=white" alt="Cursor"></a>
10
10
  <a href="https://github.com/features/copilot"><img src="https://img.shields.io/badge/GitHub_Copilot-000000?style=for-the-badge&logo=githubcopilot&logoColor=white" alt="GitHub Copilot"></a>
11
11
  <a href="https://opencode.ai"><img src="https://img.shields.io/badge/OpenCode-4285F4?style=for-the-badge&logoColor=white" alt="OpenCode"></a>
12
- <a href="#-cli--works-everywhere"><img src="https://img.shields.io/badge/Any_Terminal-4EAA25?style=for-the-badge&logo=gnubash&logoColor=white" alt="Any Terminal"></a>
12
+ <a href="https://codex.openai.com"><img src="https://img.shields.io/badge/Codex_CLI-412991?style=for-the-badge&logo=openai&logoColor=white" alt="Codex CLI"></a>
13
+ <a href="docs/CLI.md"><img src="https://img.shields.io/badge/Any_Terminal-4EAA25?style=for-the-badge&logo=gnubash&logoColor=white" alt="Any Terminal"></a>
13
14
 
14
15
 
15
16
 
@@ -20,7 +21,7 @@
20
21
  <br>
21
22
  [![Ruby](https://img.shields.io/badge/Ruby-3.2%20%7C%203.3%20%7C%203.4-CC342D)](https://github.com/crisnahine/rails-ai-context)
22
23
  [![Rails](https://img.shields.io/badge/Rails-7.1%20%7C%207.2%20%7C%208.0-CC0000)](https://github.com/crisnahine/rails-ai-context)
23
- [![Tests](https://img.shields.io/badge/Tests-1813%20passing-brightgreen)](https://github.com/crisnahine/rails-ai-context/actions)
24
+ [![Tests](https://img.shields.io/badge/Tests-1889%20passing-brightgreen)](https://github.com/crisnahine/rails-ai-context/actions)
24
25
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
25
26
 
26
27
  </div>
@@ -131,7 +132,7 @@ Compare what AI outputs with and without these tools wired in. The difference is
131
132
 
132
133
  ### MCP Server (stdio)
133
134
 
134
- AI calls tools directly via the protocol. Auto-discovered through `.mcp.json`.
135
+ AI calls tools directly via the protocol. Each AI tool gets its own config file — auto-detected on project open.
135
136
 
136
137
  ```
137
138
  rails ai:serve
@@ -186,20 +187,18 @@ rails 'ai:tool[analyze_feature]' feature=billing
186
187
  <br>
187
188
 
188
189
  ```bash
189
- # Step 1: Check what exists
190
190
  rails 'ai:tool[schema]' table=users
191
- # → 20 columns, types, indexes, encrypted hints, defaults
192
-
193
- # Step 2: Understand the model
194
- rails 'ai:tool[model_details]' model=User
195
- # → associations, validations, scopes, enums, callbacks, Devise modules
196
-
197
- # Step 3: See the full feature
198
- rails 'ai:tool[analyze_feature]' feature=subscription
199
- # → models + controllers + routes + services + jobs + views + tests in one shot
191
+ ```
192
+ ```
193
+ ## Table: users
194
+ | Column | Type | Null | Default |
195
+ |---------------------|---------|------|---------|
196
+ | email | string | NO | [unique] |
197
+ | subscription_status | string | yes | "free" |
198
+ | created_at | datetime| NO | |
200
199
  ```
201
200
 
202
- AI writes a correct migration, model change, and controller update on the **first attempt**.
201
+ AI sees `subscription_status` already exists. Checks the model, then generates a correct migration **first attempt**.
203
202
 
204
203
  </details>
205
204
 
@@ -209,19 +208,18 @@ AI writes a correct migration, model change, and controller update on the **firs
209
208
  <br>
210
209
 
211
210
  ```bash
212
- # Trace what happens
213
211
  rails 'ai:tool[controllers]' controller=CooksController action=create
214
- # → source code + inherited filters + strong params + render map + side effects
215
-
216
- # Check the routes
217
- rails 'ai:tool[routes]' controller=cooks
218
- # → code-ready helpers (cook_path(@record)) + required params
212
+ ```
213
+ ```
214
+ # CooksController#create
219
215
 
220
- # Validate after fixing
221
- rails 'ai:tool[validate]' files=app/controllers/cooks_controller.rb level=rails
222
- # syntax + semantics + Brakeman security scan
216
+ Filters: before_action :authenticate_user!, before_action :set_cook (only: show, edit)
217
+ Strong params: cook_params → name, specialty, bio
218
+ Renders: redirect_to @cook | render :new
223
219
  ```
224
220
 
221
+ AI sees the inherited `authenticate_user!` filter, the actual strong params, and the render paths. No guessing.
222
+
225
223
  </details>
226
224
 
227
225
  <details>
@@ -251,7 +249,7 @@ rails 'ai:tool[stimulus]' controller=chart
251
249
 
252
250
  Every tool is **read-only** and returns data verified against your actual app — not guesses, not training data.
253
251
 
254
- <details>
252
+ <details open>
255
253
  <summary><strong>Search & Trace</strong></summary>
256
254
 
257
255
  | Tool | What it does |
@@ -261,7 +259,7 @@ Every tool is **read-only** and returns data verified against your actual app
261
259
 
262
260
  </details>
263
261
 
264
- <details>
262
+ <details open>
265
263
  <summary><strong>Understand</strong></summary>
266
264
 
267
265
  | Tool | What it does |
@@ -272,7 +270,7 @@ Every tool is **read-only** and returns data verified against your actual app
272
270
 
273
271
  </details>
274
272
 
275
- <details>
273
+ <details open>
276
274
  <summary><strong>Schema & Models</strong></summary>
277
275
 
278
276
  | Tool | What it does |
@@ -284,7 +282,7 @@ Every tool is **read-only** and returns data verified against your actual app
284
282
 
285
283
  </details>
286
284
 
287
- <details>
285
+ <details open>
288
286
  <summary><strong>Controllers & Routes</strong></summary>
289
287
 
290
288
  | Tool | What it does |
@@ -294,7 +292,7 @@ Every tool is **read-only** and returns data verified against your actual app
294
292
 
295
293
  </details>
296
294
 
297
- <details>
295
+ <details open>
298
296
  <summary><strong>Views & Frontend</strong></summary>
299
297
 
300
298
  | Tool | What it does |
@@ -307,7 +305,7 @@ Every tool is **read-only** and returns data verified against your actual app
307
305
 
308
306
  </details>
309
307
 
310
- <details>
308
+ <details open>
311
309
  <summary><strong>Testing & Quality</strong></summary>
312
310
 
313
311
  | Tool | What it does |
@@ -320,7 +318,7 @@ Every tool is **read-only** and returns data verified against your actual app
320
318
 
321
319
  </details>
322
320
 
323
- <details>
321
+ <details open>
324
322
  <summary><strong>App Config & Services</strong></summary>
325
323
 
326
324
  | Tool | What it does |
@@ -336,7 +334,7 @@ Every tool is **read-only** and returns data verified against your actual app
336
334
 
337
335
  </details>
338
336
 
339
- <details>
337
+ <details open>
340
338
  <summary><strong>Data & Debugging</strong></summary>
341
339
 
342
340
  | Tool | What it does |
@@ -353,7 +351,7 @@ Every tool is **read-only** and returns data verified against your actual app
353
351
 
354
352
  </details>
355
353
 
356
- > **[Full parameter docs →](docs/GUIDE.md)**
354
+ > **[All 38 tools with parameters →](docs/TOOLS.md)** &nbsp;|&nbsp; **[Real-world recipes →](docs/RECIPES.md)**
357
355
 
358
356
  <br>
359
357
 
@@ -397,26 +395,21 @@ Enabled by default. Disable with `config.anti_hallucination_rules = false` if yo
397
395
 
398
396
  ## How it works
399
397
 
400
- ```
401
- ┌─────────────────────────────────────────────────────────┐
402
- Your Rails App
403
- │ models + schema + routes + controllers + views + jobs │
404
- └────────────────────────┬────────────────────────────────┘
405
- │ introspects (31 introspectors)
406
-
407
- ┌─────────────────────────────────────────────────────────┐
408
- │ rails-ai-context │
409
- │ Prism AST parsing. Cached. Confidence-tagged results. │
410
- │ VFS: rails-ai-context:// URIs introspected fresh. │
411
- └────────┬──────────────────┬──────────────┬──────────────┘
412
- │ │ │
413
- ▼ ▼ ▼
414
- ┌──────────────────┐ ┌────────────┐ ┌────────────────────┐
415
- │ Static Files │ │ MCP Server │ │ CLI Tools │
416
- │ CLAUDE.md │ │ 38 tools │ │ Same 38 tools │
417
- │ .cursor/rules/ │ │ 5 templates│ │ No server needed │
418
- │ .github/instr... │ │ stdio/HTTP │ │ rails 'ai:tool[X]' │
419
- └──────────────────┘ └────────────┘ └────────────────────┘
398
+ ```mermaid
399
+ graph TD
400
+ A["Your Rails App\nmodels + schema + routes + controllers + views + jobs"] -->|"31 introspectors"| B
401
+
402
+ B["rails-ai-context\nPrism AST parsing · Cached · Confidence-tagged\nVFS: rails-ai-context:// URIs introspected fresh"]
403
+
404
+ B --> C["MCP Server\nstdio / HTTP\n38 tools · 5 templates"]
405
+ B --> D["CLI Tools\nRake / Thor\nSame 38 tools"]
406
+ B --> E["Static Files\nCLAUDE.md · .cursor/rules/\n.github/instructions/"]
407
+
408
+ style A fill:#4a9eff,stroke:#2d7ad4,color:#fff
409
+ style B fill:#2d2d2d,stroke:#555,color:#fff
410
+ style C fill:#0984e3,stroke:#0770c2,color:#fff
411
+ style D fill:#00cec9,stroke:#00b5b0,color:#fff
412
+ style E fill:#a29bfe,stroke:#8c83f0,color:#fff
420
413
  ```
421
414
 
422
415
  <br>
@@ -438,7 +431,7 @@ cd your-rails-app
438
431
  rails-ai-context init
439
432
  ```
440
433
 
441
- Both paths ask which AI tools you use and whether you want MCP or CLI mode. `.mcp.json` is auto-detected by Claude Code and Cursor.
434
+ Both paths ask which AI tools you use (Claude Code, Cursor, GitHub Copilot, OpenCode, Codex CLI) and whether you want MCP or CLI mode. Each tool gets its own MCP config file — auto-detected on project open.
442
435
 
443
436
  <br>
444
437
 
@@ -455,6 +448,58 @@ Both paths ask which AI tools you use and whether you want MCP or CLI mode. `.mc
455
448
 
456
449
  <br>
457
450
 
451
+ ## Documentation
452
+
453
+ | | |
454
+ |:------|:------------|
455
+ | **[Quickstart](docs/QUICKSTART.md)** | 5-minute getting started |
456
+ | **[Tools Reference](docs/TOOLS.md)** | All 38 tools with every parameter |
457
+ | **[Recipes](docs/RECIPES.md)** | Real-world workflows and examples |
458
+ | **[Custom Tools](docs/CUSTOM_TOOLS.md)** | Build and test your own MCP tools |
459
+ | **[Configuration](docs/CONFIGURATION.md)** | 40+ config options with defaults |
460
+ | **[AI Tool Setup](docs/SETUP.md)** | Claude, Cursor, Copilot, OpenCode, Codex |
461
+ | **[Architecture](docs/ARCHITECTURE.md)** | System design and internals |
462
+ | **[Introspectors](docs/INTROSPECTORS.md)** | All 31 introspectors and AST engine |
463
+ | **[Security](docs/SECURITY.md)** | 4-layer SQL safety and file blocking |
464
+ | **[CLI Reference](docs/CLI.md)** | Commands and argument syntax |
465
+ | **[Standalone](docs/STANDALONE.md)** | Use without Gemfile entry |
466
+ | **[Troubleshooting](docs/TROUBLESHOOTING.md)** | Common issues and fixes |
467
+ | **[FAQ](docs/FAQ.md)** | Frequently asked questions |
468
+
469
+ <br>
470
+
471
+ ## Build your own tools
472
+
473
+ Register custom MCP tools alongside the 38 built-in ones:
474
+
475
+ ```ruby
476
+ # app/mcp_tools/rails_get_business_metrics.rb
477
+ class RailsGetBusinessMetrics < MCP::Tool
478
+ tool_name "rails_get_business_metrics"
479
+ description "Key business metrics for this app"
480
+
481
+ def call(period: "week")
482
+ MCP::Tool::Response.new([{ type: "text", text: "Users this #{period}: #{User.recent.count}" }])
483
+ end
484
+ end
485
+
486
+ # config/initializers/rails_ai_context.rb
487
+ config.custom_tools = [RailsGetBusinessMetrics]
488
+ ```
489
+
490
+ Test with the built-in `TestHelper` (works with RSpec and Minitest):
491
+
492
+ ```ruby
493
+ include RailsAiContext::TestHelper
494
+
495
+ response = execute_tool("business_metrics", period: "month")
496
+ assert_tool_response_includes(response, "Users")
497
+ ```
498
+
499
+ > **[Custom Tools Guide →](docs/CUSTOM_TOOLS.md)**
500
+
501
+ <br>
502
+
458
503
  ## Configuration
459
504
 
460
505
  ```ruby
@@ -468,31 +513,13 @@ if defined?(RailsAiContext)
468
513
  end
469
514
  ```
470
515
 
471
- <details>
472
- <summary><strong>All configuration options</strong></summary>
473
-
474
- <br>
475
-
476
- | Option | Default | Description |
477
- |:-------|:--------|:------------|
478
- | `preset` | `:full` | `:full` (31 introspectors) or `:standard` (17) |
479
- | `context_mode` | `:compact` | `:compact` (150 lines) or `:full` |
480
- | `generate_root_files` | `true` | Set `false` for split rules only |
481
- | `anti_hallucination_rules` | `true` | Embed 6-rule verification protocol in generated context files |
482
- | `cache_ttl` | `60` | Cache TTL in seconds |
483
- | `max_tool_response_chars` | `200_000` | Safety cap for tool responses |
484
- | `live_reload` | `:auto` | `:auto`, `true`, or `false` |
485
- | `custom_tools` | `[]` | Additional MCP tool classes |
486
- | `skip_tools` | `[]` | Built-in tools to exclude |
487
- | `excluded_models` | `[]` | Models to skip during introspection |
488
-
489
- </details>
516
+ > **[All 40+ configuration options →](docs/CONFIGURATION.md)**
490
517
 
491
518
  <br>
492
519
 
493
520
  ## Observability
494
521
 
495
- Every MCP tool call and resource read fires an `ActiveSupport::Notifications` event. Subscribe with standard Rails patterns:
522
+ Every MCP tool call fires an `ActiveSupport::Notifications` event:
496
523
 
497
524
  ```ruby
498
525
  ActiveSupport::Notifications.subscribe("rails_ai_context.tools.call") do |event|
@@ -500,8 +527,6 @@ ActiveSupport::Notifications.subscribe("rails_ai_context.tools.call") do |event|
500
527
  end
501
528
  ```
502
529
 
503
- Events: `rails_ai_context.tools.call`, `rails_ai_context.resources.read`, and more. All 38 tools declare `output_schema` in the MCP protocol, so clients know the response format before calling.
504
-
505
530
  <br>
506
531
 
507
532
  ## Requirements
@@ -518,7 +543,7 @@ Events: `rails_ai_context.tools.call`, `rails_ai_context.resources.read`, and mo
518
543
  ## About
519
544
 
520
545
  Built by a Rails developer with 10+ years of production experience.<br>
521
- 1813 tests. 38 tools. 5 resource templates. 31 introspectors. Standalone or in-Gemfile.<br>
546
+ 1889 tests. 38 tools. 5 resource templates. 31 introspectors. Standalone or in-Gemfile.<br>
522
547
  MIT licensed. [Contributions welcome.](CONTRIBUTING.md)
523
548
 
524
549
  <br>
data/SECURITY.md CHANGED
@@ -4,6 +4,12 @@
4
4
 
5
5
  | Version | Supported |
6
6
  |---------|--------------------|
7
+ | 5.7.x | :white_check_mark: |
8
+ | 5.6.x | :white_check_mark: |
9
+ | 5.5.x | :white_check_mark: |
10
+ | 5.4.x | :white_check_mark: |
11
+ | 5.3.x | :white_check_mark: |
12
+ | 5.2.x | :white_check_mark: |
7
13
  | 5.1.x | :white_check_mark: |
8
14
  | 5.0.x | :white_check_mark: |
9
15
  | 4.7.x | :white_check_mark: |
@@ -18,7 +18,7 @@ module RailsAiContext
18
18
  # Class-level memoization — transport persists across requests.
19
19
  # Thread-safe: MCP::Server and transport are stateless for reads.
20
20
  def mcp_transport
21
- @mcp_transport || @transport_mutex.synchronize do
21
+ @transport_mutex.synchronize do
22
22
  @mcp_transport ||= begin
23
23
  server = RailsAiContext::Server.new(Rails.application, transport: :http).build
24
24
  MCP::Server::Transports::StreamableHTTPTransport.new(server)