rails-ai-bridge 1.1.0 → 2.1.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.
- checksums.yaml +4 -4
- data/.yardopts +8 -0
- data/CHANGELOG.md +49 -0
- data/GEMINI.md +55 -0
- data/README.md +80 -1
- data/Rakefile +3 -0
- data/SECURITY.md +13 -5
- data/UPGRADING.md +87 -0
- data/docs/roadmap-context-assistants.md +29 -0
- data/docs/roadmap-mcp-v2.md +45 -0
- data/docs/roadmaps.md +58 -0
- data/lib/generators/rails_ai_bridge/install/install_generator.rb +52 -22
- data/lib/rails_ai_bridge/assistant_formats_preference.rb +84 -0
- data/lib/rails_ai_bridge/config/auth.rb +35 -0
- data/lib/rails_ai_bridge/config/introspection.rb +85 -0
- data/lib/rails_ai_bridge/config/mcp.rb +111 -0
- data/lib/rails_ai_bridge/config/output.rb +47 -0
- data/lib/rails_ai_bridge/config/server.rb +43 -0
- data/lib/rails_ai_bridge/configuration.rb +91 -99
- data/lib/rails_ai_bridge/exclusion_helper.rb +23 -0
- data/lib/rails_ai_bridge/http_transport_app.rb +33 -3
- data/lib/rails_ai_bridge/introspector.rb +1 -1
- data/lib/rails_ai_bridge/introspectors/model_introspector.rb +12 -1
- data/lib/rails_ai_bridge/introspectors/schema/static_schema_parser.rb +131 -0
- data/lib/rails_ai_bridge/introspectors/schema_introspector.rb +31 -32
- data/lib/rails_ai_bridge/mcp/auth/base_strategy.rb +24 -0
- data/lib/rails_ai_bridge/mcp/auth/strategies/bearer_token.rb +104 -0
- data/lib/rails_ai_bridge/mcp/auth/strategies/jwt.rb +65 -0
- data/lib/rails_ai_bridge/mcp/auth_result.rb +39 -0
- data/lib/rails_ai_bridge/mcp/authenticator.rb +122 -0
- data/lib/rails_ai_bridge/mcp/http_rate_limiter.rb +40 -0
- data/lib/rails_ai_bridge/mcp/http_structured_log.rb +49 -0
- data/lib/rails_ai_bridge/resources.rb +21 -11
- data/lib/rails_ai_bridge/serializers/context_file_serializer.rb +13 -11
- data/lib/rails_ai_bridge/serializers/context_summary.rb +69 -0
- data/lib/rails_ai_bridge/serializers/formatters/action_mailbox_formatter.rb +22 -0
- data/lib/rails_ai_bridge/serializers/formatters/action_text_formatter.rb +22 -0
- data/lib/rails_ai_bridge/serializers/formatters/active_storage_formatter.rb +23 -0
- data/lib/rails_ai_bridge/serializers/formatters/api_formatter.rb +31 -0
- data/lib/rails_ai_bridge/serializers/formatters/app_overview_formatter.rb +22 -0
- data/lib/rails_ai_bridge/serializers/formatters/assets_formatter.rb +23 -0
- data/lib/rails_ai_bridge/serializers/formatters/auth_formatter.rb +34 -0
- data/lib/rails_ai_bridge/serializers/formatters/base.rb +22 -0
- data/lib/rails_ai_bridge/serializers/formatters/claude_footer_formatter.rb +31 -0
- data/lib/rails_ai_bridge/serializers/formatters/claude_header_formatter.rb +25 -0
- data/lib/rails_ai_bridge/serializers/formatters/codex_footer_formatter.rb +18 -0
- data/lib/rails_ai_bridge/serializers/formatters/codex_header_formatter.rb +23 -0
- data/lib/rails_ai_bridge/serializers/formatters/config_formatter.rb +23 -0
- data/lib/rails_ai_bridge/serializers/formatters/controllers_formatter.rb +48 -0
- data/lib/rails_ai_bridge/serializers/formatters/conventions_formatter.rb +24 -0
- data/lib/rails_ai_bridge/serializers/formatters/copilot_footer_formatter.rb +18 -0
- data/lib/rails_ai_bridge/serializers/formatters/copilot_header_formatter.rb +22 -0
- data/lib/rails_ai_bridge/serializers/formatters/devops_formatter.rb +28 -0
- data/lib/rails_ai_bridge/serializers/formatters/engines_formatter.rb +27 -0
- data/lib/rails_ai_bridge/serializers/formatters/footer_formatter.rb +18 -0
- data/lib/rails_ai_bridge/serializers/formatters/gemini_footer_formatter.rb +33 -0
- data/lib/rails_ai_bridge/serializers/formatters/gemini_header_formatter.rb +29 -0
- data/lib/rails_ai_bridge/serializers/formatters/gems_formatter.rb +26 -0
- data/lib/rails_ai_bridge/serializers/formatters/header_formatter.rb +24 -0
- data/lib/rails_ai_bridge/serializers/formatters/i18n_formatter.rb +22 -0
- data/lib/rails_ai_bridge/serializers/formatters/jobs_formatter.rb +35 -0
- data/lib/rails_ai_bridge/serializers/formatters/mcp_guide_formatter.rb +59 -0
- data/lib/rails_ai_bridge/serializers/formatters/middleware_formatter.rb +28 -0
- data/lib/rails_ai_bridge/serializers/formatters/migrations_formatter.rb +35 -0
- data/lib/rails_ai_bridge/serializers/formatters/models_formatter.rb +31 -0
- data/lib/rails_ai_bridge/serializers/formatters/multi_database_formatter.rb +35 -0
- data/lib/rails_ai_bridge/serializers/formatters/rake_tasks_formatter.rb +25 -0
- data/lib/rails_ai_bridge/serializers/formatters/routes_formatter.rb +25 -0
- data/lib/rails_ai_bridge/serializers/formatters/rules_footer_formatter.rb +18 -0
- data/lib/rails_ai_bridge/serializers/formatters/rules_header_formatter.rb +19 -0
- data/lib/rails_ai_bridge/serializers/formatters/schema_formatter.rb +24 -0
- data/lib/rails_ai_bridge/serializers/formatters/section_formatter.rb +62 -0
- data/lib/rails_ai_bridge/serializers/formatters/seeds_formatter.rb +31 -0
- data/lib/rails_ai_bridge/serializers/formatters/tests_formatter.rb +25 -0
- data/lib/rails_ai_bridge/serializers/formatters/turbo_formatter.rb +33 -0
- data/lib/rails_ai_bridge/serializers/formatters/views_formatter.rb +35 -0
- data/lib/rails_ai_bridge/serializers/markdown_serializer.rb +43 -486
- data/lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb +251 -0
- data/lib/rails_ai_bridge/serializers/providers/claude_rules_serializer.rb +156 -0
- data/lib/rails_ai_bridge/serializers/providers/claude_serializer.rb +30 -0
- data/lib/rails_ai_bridge/serializers/providers/codex_serializer.rb +120 -0
- data/lib/rails_ai_bridge/serializers/providers/codex_support_serializer.rb +68 -0
- data/lib/rails_ai_bridge/serializers/providers/copilot_instructions_serializer.rb +154 -0
- data/lib/rails_ai_bridge/serializers/providers/copilot_serializer.rb +145 -0
- data/lib/rails_ai_bridge/serializers/providers/cursor_rules_serializer.rb +248 -0
- data/lib/rails_ai_bridge/serializers/providers/gemini_serializer.rb +30 -0
- data/lib/rails_ai_bridge/serializers/providers/rules_serializer.rb +120 -0
- data/lib/rails_ai_bridge/serializers/providers/windsurf_rules_serializer.rb +94 -0
- data/lib/rails_ai_bridge/serializers/providers/windsurf_serializer.rb +125 -0
- data/lib/rails_ai_bridge/server.rb +3 -1
- data/lib/rails_ai_bridge/tasks/rails_ai_bridge.rake +2 -1
- data/lib/rails_ai_bridge/tools/get_model_details.rb +7 -103
- data/lib/rails_ai_bridge/tools/get_schema.rb +7 -91
- data/lib/rails_ai_bridge/tools/model_details/full_formatter.rb +34 -0
- data/lib/rails_ai_bridge/tools/model_details/single_model_formatter.rb +75 -0
- data/lib/rails_ai_bridge/tools/model_details/standard_formatter.rb +34 -0
- data/lib/rails_ai_bridge/tools/model_details/summary_formatter.rb +21 -0
- data/lib/rails_ai_bridge/tools/schema/full_formatter.rb +38 -0
- data/lib/rails_ai_bridge/tools/schema/standard_formatter.rb +42 -0
- data/lib/rails_ai_bridge/tools/schema/summary_formatter.rb +41 -0
- data/lib/rails_ai_bridge/tools/schema/table_formatter.rb +46 -0
- data/lib/rails_ai_bridge/version.rb +1 -1
- data/lib/rails_ai_bridge.rb +11 -7
- data/rails-ai-bridge.gemspec +7 -6
- data/tasks/prd-v2-architecture-and-quality.md +222 -0
- data/tasks/tasks-v2-architecture-and-quality.md +258 -0
- metadata +109 -36
- data/lib/rails_ai_bridge/mcp_http_auth.rb +0 -69
- data/lib/rails_ai_bridge/serializers/claude_rules_serializer.rb +0 -147
- data/lib/rails_ai_bridge/serializers/claude_serializer.rb +0 -285
- data/lib/rails_ai_bridge/serializers/codex_serializer.rb +0 -150
- data/lib/rails_ai_bridge/serializers/codex_support_serializer.rb +0 -64
- data/lib/rails_ai_bridge/serializers/copilot_instructions_serializer.rb +0 -143
- data/lib/rails_ai_bridge/serializers/copilot_serializer.rb +0 -171
- data/lib/rails_ai_bridge/serializers/cursor_rules_serializer.rb +0 -218
- data/lib/rails_ai_bridge/serializers/rules_serializer.rb +0 -157
- data/lib/rails_ai_bridge/serializers/windsurf_rules_serializer.rb +0 -84
- data/lib/rails_ai_bridge/serializers/windsurf_serializer.rb +0 -96
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 179af8f51240a13daa27c526299db931aaac585186cb55b4f1ca440c24cd66a8
|
|
4
|
+
data.tar.gz: 295dd64afcefc38f247612020fd9933246a1948123ca785293e5f2350bb39b58
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 98b696d49e6dfd9fffbac01d4cda299b2e0d518eea998bb703dafb71e5577b7d21e9f1024b6d126907808281f48f05cdb73b80c442a72c950c5a8db046198ab5
|
|
7
|
+
data.tar.gz: a0590ccdc592b161e289313d45f2820b9b793661201b318f68f89c8c4a3535c849d6422327879edd60b7e7a8c14356ab9ea35bcfb4ca9cb6caecf0fac908247d
|
data/.yardopts
ADDED
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.1.0] - 2026-04-02
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Gemini Support:** Added support for Google's Gemini AI assistant via `GEMINI.md`.
|
|
15
|
+
- **New Rake Task:** Added `rails ai:bridge:gemini` to generate Gemini-specific context.
|
|
16
|
+
- **Context Harmonization:** Refactored all provider serializers (Claude, Gemini, Codex, Copilot, Cursor, Windsurf) to use a shared `BaseProviderSerializer`.
|
|
17
|
+
- **Enhanced AI Guidance:** All context files now feature directive headers, complexity-sorted model lists, and explicit behavioral rules to improve AI code generation.
|
|
18
|
+
- **Improved Metadata:** Context files now include descriptions for key config files and standard maintenance commands (e.g., `rubocop`).
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **Internal Refactor:** Extracted common rendering logic into `RailsAiBridge::Serializers::Providers::BaseProviderSerializer` to ensure consistency and maintainability across all AI assistants.
|
|
23
|
+
|
|
24
|
+
## [2.0.0] - 2026-03-31
|
|
25
|
+
|
|
10
26
|
### Added
|
|
11
27
|
|
|
12
28
|
- **Shared runtime context provider** — MCP tools and `rails://...` resources now read through `RailsAiBridge::ContextProvider`, keeping cache invalidation and snapshot semantics aligned across both entry points.
|
|
@@ -15,15 +31,48 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
15
31
|
- **Section-level context reads** — `ContextProvider.fetch_section` and `BaseTool.cached_section` let single-section tools avoid rebuilding or materializing the full snapshot path when unnecessary.
|
|
16
32
|
- **Folder-level contributor docs** — key runtime folders now include local `README.md` guides for structure, boundaries, and extension points.
|
|
17
33
|
- **Extensibility integration coverage** — specs now prove that a custom introspector, tool, and resource can be registered and used together from the host app configuration surface.
|
|
34
|
+
- **Serializer formatter objects** — `MarkdownSerializer` is now a thin orchestrator delegating to 37 single-responsibility `Formatters::*` classes; each formatter is independently testable and injectable.
|
|
35
|
+
- **Tool response formatters** — `GetSchema` and `GetModelDetails` delegate all rendering to `Tools::Schema::*` and `Tools::ModelDetails::*` formatter classes; tool `call` methods are ≤20 lines each.
|
|
36
|
+
- **`Config::Auth`, `Config::Server`, `Config::Introspection`, `Config::Output`** — `Configuration` is now a `Forwardable` facade over four focused sub-objects; each is independently readable and injectable.
|
|
37
|
+
- **`Mcp::Authenticator`** — consolidates strategy resolution, static-token lookup, and configuration predicates into a single entry point, replacing the previous split between `McpHttpAuth` and `Mcp::HttpAuth`.
|
|
38
|
+
- **`Mcp::HttpRateLimiter`** — optional in-process sliding-window rate limiter per client IP; configured via `config.mcp.rate_limit_max_requests` and `config.mcp.rate_limit_window_seconds`. Returns 429 with `Retry-After` header when exceeded.
|
|
39
|
+
- **`Mcp::HttpStructuredLog`** — optional one-JSON-line-per-request logger for the MCP HTTP path; enabled via `config.mcp.http_log_json = true`. Logs `event`, `http_status`, `path`, `client_ip`, and `request_id`; never logs tokens or full Rack env.
|
|
40
|
+
- **`Config::Mcp`** — new `config.mcp` sub-object (5th façade sub-config) for MCP HTTP operational settings: `mode`, `security_profile`, `rate_limit_max_requests`, `rate_limit_window_seconds`, `http_log_json`, `authorize`, `require_auth_in_production`.
|
|
41
|
+
- **`config.mcp.authorize`** — optional post-auth lambda `(context, request) { truthy }`; returning falsey yields HTTP 403 on the MCP path.
|
|
42
|
+
- **`config.mcp.require_auth_in_production`** — when `true`, boot fails in production unless an auth mechanism is configured.
|
|
43
|
+
- **`HttpTransportApp`** updated — request pipeline is now: path check → auth → authorize → rate limit → structured log → transport.
|
|
44
|
+
- **`SectionFormatter` template method base** — 22 of 37 formatters now inherit from `SectionFormatter`, which handles the nil/error guard in one place; each formatter only implements `render(data)`.
|
|
45
|
+
- **`Serializers::Providers` namespace** — 10 LLM provider serializers extracted into `lib/rails_ai_bridge/serializers/providers/`, separating provider concerns from domain infrastructure (`MarkdownSerializer`, `JsonSerializer`, formatters).
|
|
46
|
+
- **`UPGRADING.md`** — new upgrade guide documenting `config.mcp` settings, rate limit semantics, structured logging, `authorize` behaviour, and the `require_auth_in_production` flag.
|
|
47
|
+
- **Contributor roadmaps** — `docs/roadmaps.md`, `docs/roadmap-mcp-v2.md`, `docs/roadmap-context-assistants.md` added.
|
|
18
48
|
|
|
19
49
|
### Changed
|
|
20
50
|
|
|
21
51
|
- **Install generator messages** — the install flow now reports created vs unchanged files correctly and the generated initializer comments reflect the current preset sizes.
|
|
22
52
|
- **Fingerprint reuse on invalidation** — context refresh reuses a single fingerprint snapshot per fetch cycle instead of scanning twice when cached context becomes stale.
|
|
53
|
+
- **`FullClaudeSerializer`, `FullRulesSerializer`, `FullCopilotSerializer`, `FullCodexSerializer` removed** — full-mode rendering is now handled by injecting header/footer formatter classes into `MarkdownSerializer` via constructor arguments; no subclassing needed.
|
|
54
|
+
- **Test suite expanded to 841 examples at ≥87% line coverage.**
|
|
23
55
|
|
|
24
56
|
### Fixed
|
|
25
57
|
|
|
26
58
|
- **Install generator output bug** — `generate_context` results are no longer iterated as raw hash pairs during install-time file generation.
|
|
59
|
+
- **`StandardFormatter` pagination hint** — navigation hint now correctly uses `offset + limit < total` (consistent with `SummaryFormatter` and `FullFormatter`), preventing a spurious hint on the last page.
|
|
60
|
+
|
|
61
|
+
### Upgrading from 1.x
|
|
62
|
+
|
|
63
|
+
**No configuration changes required.** Every `config.*` attribute from 1.x is still available unchanged — `Configuration` now delegates to focused sub-objects (`Config::Auth`, `Config::Server`, `Config::Introspection`, `Config::Output`, `Config::Mcp`) but exposes the same flat DSL.
|
|
64
|
+
|
|
65
|
+
The following internal classes were removed; they were never part of the documented public API:
|
|
66
|
+
|
|
67
|
+
| Removed | Replacement |
|
|
68
|
+
|---------|-------------|
|
|
69
|
+
| `Mcp::HttpAuth` / `McpHttpAuth` | `Mcp::Authenticator` (same behaviour, single entry point) |
|
|
70
|
+
| `FullClaudeSerializer` | Pass `header_class: Formatters::ClaudeHeaderFormatter` to `MarkdownSerializer` |
|
|
71
|
+
| `FullCopilotSerializer` | Pass `header_class: Formatters::CopilotHeaderFormatter` to `MarkdownSerializer` |
|
|
72
|
+
| `FullCodexSerializer` | Pass `header_class: Formatters::CodexHeaderFormatter` to `MarkdownSerializer` |
|
|
73
|
+
| `FullRulesSerializer` | Pass `header_class: Formatters::RulesHeaderFormatter` to `MarkdownSerializer` |
|
|
74
|
+
|
|
75
|
+
If you were only using the gem through its initializer, rake tasks, or MCP server — no action needed.
|
|
27
76
|
|
|
28
77
|
## [1.1.0] - 2026-03-20
|
|
29
78
|
|
data/GEMINI.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# GEMINI.md — rails-ai-bridge development guide
|
|
2
|
+
|
|
3
|
+
This is a Ruby gem that auto-introspects Rails applications and exposes their
|
|
4
|
+
structure to AI assistants via the Model Context Protocol (MCP).
|
|
5
|
+
|
|
6
|
+
## Architecture
|
|
7
|
+
|
|
8
|
+
- `lib/rails_ai_bridge.rb` — Main entry point, public API (Zeitwerk autoloaded)
|
|
9
|
+
- `lib/rails_ai_bridge/configuration.rb` — User-facing config with presets (:standard, :full)
|
|
10
|
+
- `lib/rails_ai_bridge/introspector.rb` — Orchestrates sub-introspectors
|
|
11
|
+
- `lib/rails_ai_bridge/introspectors/` — 27 introspectors (schema, models, routes, jobs, gems, conventions, stimulus, database_stats, controllers, views, turbo, i18n, config, active_storage, action_text, auth, api, tests, rake_tasks, assets, devops, action_mailbox, migrations, seeds, middleware, engines, multi_database)
|
|
12
|
+
- `lib/rails_ai_bridge/tools/` — 9 MCP tools using the official mcp SDK
|
|
13
|
+
- `lib/rails_ai_bridge/serializers/` — Output formatters (claude, claude_rules, cursor_rules, windsurf, windsurf_rules, copilot, copilot_instructions, rules, markdown, JSON, gemini)
|
|
14
|
+
- `lib/rails_ai_bridge/resources.rb` — MCP resources (static data AI clients read directly)
|
|
15
|
+
- `lib/rails_ai_bridge/server.rb` — MCP server configuration (stdio + HTTP transports)
|
|
16
|
+
- `lib/rails_ai_bridge/middleware.rb` — Rack middleware for auto-mounting MCP HTTP endpoint
|
|
17
|
+
- `lib/rails_ai_bridge/fingerprinter.rb` — SHA256 file fingerprinting for cache invalidation
|
|
18
|
+
- `lib/rails_ai_bridge/doctor.rb` — Diagnostic checks and AI readiness scoring
|
|
19
|
+
- `lib/rails_ai_bridge/watcher.rb` — File watcher for auto-regenerating context files
|
|
20
|
+
- `lib/rails_ai_bridge/engine.rb` — Rails Engine for auto-integration
|
|
21
|
+
- `lib/generators/rails_ai_bridge/install/` — Install generator (creates .mcp.json, initializer, context files)
|
|
22
|
+
|
|
23
|
+
## Key Design Decisions
|
|
24
|
+
|
|
25
|
+
1. **Built on official mcp SDK** — not a custom protocol implementation
|
|
26
|
+
2. **Zero-config** — Railtie auto-registers at boot, introspects without setup
|
|
27
|
+
3. **Graceful degradation** — works without DB by parsing schema.rb as text
|
|
28
|
+
4. **Read-only tools only** — all MCP tools are annotated as non-destructive
|
|
29
|
+
5. **Dual output** — static files (GEMINI.md) + live MCP server (stdio/HTTP)
|
|
30
|
+
6. **Diff-aware** — context regeneration skips unchanged files
|
|
31
|
+
7. **Per-assistant serializers** — each AI tool gets tailored output format
|
|
32
|
+
8. **Zeitwerk autoloading** — files loaded on-demand, not all upfront
|
|
33
|
+
9. **Introspector presets** — `:standard` (9 core) default, `:full` (26) for power users
|
|
34
|
+
10. **MCP auto-discovery** — `.mcp.json` generated by install generator
|
|
35
|
+
11. **Compact by default** — context files ≤150 lines, MCP tools use `detail` parameter (summary/standard/full)
|
|
36
|
+
12. **Per-tool split rules** — `.claude/rules/`, `.cursor/rules/`, `.windsurf/rules/`, `.github/instructions/`
|
|
37
|
+
|
|
38
|
+
## Testing
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
bundle exec rspec # Run specs (364 examples)
|
|
42
|
+
bundle exec rubocop # Lint
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Uses combustion gem for testing Rails engine behavior in isolation.
|
|
46
|
+
|
|
47
|
+
## Conventions
|
|
48
|
+
|
|
49
|
+
- Ruby 3.2+ features OK (pattern matching, etc.)
|
|
50
|
+
- Follow rubocop-rails-omakase style
|
|
51
|
+
- Every introspector returns a Hash, never raises (wraps errors in `{ error: msg }`)
|
|
52
|
+
- MCP tools return `MCP::Tool::Response` objects per SDK convention
|
|
53
|
+
- All tools prefixed with `rails_` per MCP naming best practices
|
|
54
|
+
- `generate_context` returns `{ written: [], skipped: [] }` hash
|
|
55
|
+
- Zeitwerk autoloads all files — no `require_relative` needed for new classes
|
data/README.md
CHANGED
|
@@ -32,7 +32,7 @@ flowchart LR
|
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
1. **Up to 27 introspectors** scan schema, models, routes, controllers, jobs, gems, conventions, and more (preset `:standard` runs 9 core ones by default; `:full` runs all).
|
|
35
|
-
2. **`rails ai:bridge`** writes bounded bridge files for Claude, Cursor, Copilot, Codex, Windsurf, and JSON.
|
|
35
|
+
2. **`rails ai:bridge`** writes bounded bridge files for Claude, Cursor, Copilot, Codex, Windsurf, Gemini, and JSON.
|
|
36
36
|
3. **`rails ai:serve`** exposes **9 MCP tools** so assistants pull detail on demand (`detail: "summary"` first, then drill down).
|
|
37
37
|
|
|
38
38
|
### Folder guides
|
|
@@ -301,6 +301,84 @@ Codex support is centered on **`AGENTS.md`** at the repository root.
|
|
|
301
301
|
|
|
302
302
|
---
|
|
303
303
|
|
|
304
|
+
## Best Practices
|
|
305
|
+
|
|
306
|
+
After testing with Cursor, Windsurf, Copilot, Codex, and Claude Code in real projects, these patterns consistently produce the best results.
|
|
307
|
+
|
|
308
|
+
### Layer 1: Commit your static files
|
|
309
|
+
|
|
310
|
+
The generated files (`.cursorrules`, `.cursor/rules/`, `AGENTS.md`, `.windsurfrules`, `CLAUDE.md`, `.github/copilot-instructions.md`) are loaded **passively** by AI tools on every session start — giving the assistant immediate project grounding before it reads a single line of your code.
|
|
311
|
+
|
|
312
|
+
**Always commit these files.** The whole team benefits, not just the developer who ran `rails ai:bridge`.
|
|
313
|
+
|
|
314
|
+
### Layer 2: Run the MCP server
|
|
315
|
+
|
|
316
|
+
Static files cover overview. The MCP server covers depth. When an assistant needs full schema details, specific model associations, or a filtered route listing, the `rails_*` tools fetch live data on demand — without inflating your initial context window.
|
|
317
|
+
|
|
318
|
+
The combination is additive:
|
|
319
|
+
|
|
320
|
+
| Setup | What you get |
|
|
321
|
+
|-------|-------------|
|
|
322
|
+
| Static files only | Passive overview: project structure always loaded |
|
|
323
|
+
| MCP server only | On-demand depth: accurate live data, no passive grounding |
|
|
324
|
+
| **Both (recommended)** | **Passive overview + on-demand depth = best coverage** |
|
|
325
|
+
|
|
326
|
+
This is the pattern that consistently outperforms either layer alone. The files reduce orientation overhead; the server handles the details when the assistant actually needs them.
|
|
327
|
+
|
|
328
|
+
### Keep files fresh — regenerate after every significant change
|
|
329
|
+
|
|
330
|
+
Static files are snapshots. An assistant working from a schema that is 20 commits out of date will still make assumptions based on the old structure. After any significant change — a new model, a migration, a refactor, a feature merged — run:
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
rails ai:bridge
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
**Rule of thumb:** treat `rails ai:bridge` the same way you treat `bundle install` after a `Gemfile` change — a routine step, not a one-time setup. Commit the regenerated files alongside the code change so the whole team stays in sync.
|
|
337
|
+
|
|
338
|
+
#### Auto-regeneration during active development
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
rails ai:watch
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Watches for file changes and regenerates relevant context files automatically. Useful when you are actively adding models, routes, or controllers and want the assistant to track along in the same session.
|
|
345
|
+
|
|
346
|
+
### Use `detail: "summary"` first with the MCP server
|
|
347
|
+
|
|
348
|
+
When the MCP server is running, start broad and drill down:
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
1. rails_get_schema(detail: "summary") → all tables, no noise
|
|
352
|
+
2. rails_get_schema(table: "orders") → full detail for one table
|
|
353
|
+
3. rails_get_model_details(model: "Order") → associations, validations, scopes
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
This keeps token usage low and answer quality high. Requesting full detail on every table at once is rarely necessary and wastes context on data the assistant does not need yet.
|
|
357
|
+
|
|
358
|
+
### Pick the right preset for your app
|
|
359
|
+
|
|
360
|
+
| Preset | Introspectors | Best for |
|
|
361
|
+
|--------|--------------|---------|
|
|
362
|
+
| `:standard` (default) | 9 core | Most apps — schema, models, routes, jobs, gems, conventions |
|
|
363
|
+
| `:full` | 27 | Full-stack apps where frontend, auth, API, and DevOps context matter |
|
|
364
|
+
|
|
365
|
+
Add individual introspectors on top of a preset for targeted additions:
|
|
366
|
+
|
|
367
|
+
```ruby
|
|
368
|
+
config.preset = :standard
|
|
369
|
+
config.introspectors += %i[views auth api]
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Check your readiness score
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
rails ai:doctor
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Prints a 0–100 AI readiness score and flags anything missing: `.mcp.json`, generated context files, MCP token in production, and more. Run it after initial setup and after major configuration changes.
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
304
382
|
## Configuration
|
|
305
383
|
|
|
306
384
|
```ruby
|
|
@@ -402,6 +480,7 @@ Frontend introspectors (views, Turbo, Stimulus, assets) degrade gracefully — t
|
|
|
402
480
|
| `rails ai:bridge:cursor` | Generate Cursor files only |
|
|
403
481
|
| `rails ai:bridge:windsurf` | Generate Windsurf files only |
|
|
404
482
|
| `rails ai:bridge:copilot` | Generate Copilot files only |
|
|
483
|
+
| `rails ai:bridge:gemini` | Generate Gemini files only |
|
|
405
484
|
| `rails ai:serve` | Start MCP server (stdio) |
|
|
406
485
|
| `rails ai:serve_http` | Start MCP server (HTTP) |
|
|
407
486
|
| `rails ai:doctor` | Run diagnostics and AI readiness score (0-100) |
|
data/Rakefile
CHANGED
data/SECURITY.md
CHANGED
|
@@ -33,14 +33,18 @@ This fork is maintained by **Ismael Marin**. If you discover a security vulnerab
|
|
|
33
33
|
|
|
34
34
|
## HTTP MCP authentication
|
|
35
35
|
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
36
|
+
- **Shared secret:** set `config.http_mcp_token` and/or `ENV["RAILS_AI_BRIDGE_MCP_TOKEN"]` (**ENV overrides** the config value when set). Clients send `Authorization: Bearer <token>`.
|
|
37
|
+
- **Custom resolver / JWT:** configure `config.mcp_token_resolver` or `config.mcp_jwt_decoder` (see [docs/GUIDE.md](docs/GUIDE.md)); clients still use a Bearer header; the gem does not ship a JWT library — you verify and decode inside your lambda.
|
|
38
|
+
- **Rack env context:** after a successful auth, `env["rails_ai_bridge.mcp.context"]` may contain **PII or claims** (e.g. JWT payload). Do not dump full Rack `env` to logs or APM; treat this key like session-derived data.
|
|
39
|
+
- When **no** auth mechanism is configured, HTTP MCP is **unauthenticated** (backward compatible for local use); configure one of the above before exposing the port beyond localhost.
|
|
40
|
+
- **Misconfiguration guard:** setting `:bearer_token` strategy without a `token_resolver` and without a static token causes **boot failure** (`ConfigurationError`) so the endpoint cannot start in an accidentally open state.
|
|
41
|
+
- **Rate limiting:** optional `config.mcp.rate_limit_max_requests` is an **in-memory, per-process** sliding window keyed by client IP (`request.ip`). It is **not** shared across Puma workers or hosts. Treat this as a light guard — use a reverse proxy, WAF, or `rack-attack` for strict distributed quotas.
|
|
42
|
+
- **MCP HTTP JSON logs:** when `config.mcp.http_log_json` is enabled, log lines include `client_ip` and path; treat log sinks like any operational data store (retention, access control).
|
|
39
43
|
|
|
40
44
|
## Production
|
|
41
45
|
|
|
42
|
-
- `config.auto_mount = true` in **production** raises at boot unless **both** `config.allow_auto_mount_in_production = true` and
|
|
43
|
-
- `rails ai:serve_http` in **production** requires
|
|
46
|
+
- `config.auto_mount = true` in **production** raises at boot unless **both** `config.allow_auto_mount_in_production = true` and an MCP auth mechanism is configured (shared token, `mcp_token_resolver`, or `mcp_jwt_decoder`).
|
|
47
|
+
- `rails ai:serve_http` in **production** requires an auth mechanism (not necessarily a static shared secret).
|
|
44
48
|
|
|
45
49
|
## Operational Security Guidance
|
|
46
50
|
|
|
@@ -48,3 +52,7 @@ This fork is maintained by **Ismael Marin**. If you discover a security vulnerab
|
|
|
48
52
|
- If you enable HTTP transport, keep it bound to `127.0.0.1` unless you add your own network isolation and authentication controls.
|
|
49
53
|
- Do **not** expose `auto_mount` on public or shared production surfaces without an explicit threat model review.
|
|
50
54
|
- Treat generated files such as `AGENTS.md`, `CLAUDE.md`, `.cursorrules`, and `.ai-context.json` as internal engineering documentation.
|
|
55
|
+
|
|
56
|
+
## Presets, exclusions, and MCP
|
|
57
|
+
|
|
58
|
+
`rails_get_schema`, `rails_get_model_details`, and other tools build on the same introspection pipeline as `rails ai:bridge`. When you use `config.excluded_tables`, `config.excluded_models`, `config.disabled_introspection_categories`, or presets such as `:regulated`, treat the HTTP/stdio MCP surface with the **same data-classification assumptions** as your committed context files: the tools remain read-only but can still reveal structure you chose to omit from markdown.
|
data/UPGRADING.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Upgrading rails-ai-bridge
|
|
2
|
+
|
|
3
|
+
## Upgrading from 1.x to 2.x
|
|
4
|
+
|
|
5
|
+
**No configuration changes required.** Every `config.*` attribute from 1.x is still available — `Configuration` now delegates to focused sub-objects but exposes the same flat DSL. See `CHANGELOG.md` for the full list of internal changes.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## New in 2.x — `config.mcp` settings
|
|
10
|
+
|
|
11
|
+
MCP HTTP operational configuration lives under `config.mcp` (a `Config::Mcp` object). All attributes are also accessible as flat delegators on `config` directly.
|
|
12
|
+
|
|
13
|
+
### Rate limiting
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
RailsAiBridge.configure do |config|
|
|
17
|
+
# Explicit ceiling: 100 requests per 60-second sliding window per client IP
|
|
18
|
+
config.mcp.rate_limit_max_requests = 100
|
|
19
|
+
config.mcp.rate_limit_window_seconds = 60
|
|
20
|
+
|
|
21
|
+
# Set to 0 to disable rate limiting entirely
|
|
22
|
+
# config.mcp.rate_limit_max_requests = 0
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
When `rate_limit_max_requests` is `nil` (default), the gem may apply an **implicit** per-IP ceiling from `security_profile` (`:strict` / `:balanced` / `:relaxed`), unless `mode` suppresses it:
|
|
27
|
+
|
|
28
|
+
- **`mode: :dev`** — no implicit limit.
|
|
29
|
+
- **`mode: :hybrid`** (default) — implicit limit only when `Rails.env.production?`.
|
|
30
|
+
- **`mode: :production`** — implicit limit in every Rails environment.
|
|
31
|
+
|
|
32
|
+
Set `config.mcp.rate_limit_max_requests = 0` to **disable** limiting entirely (including implicit). A **positive integer** always overrides the profile.
|
|
33
|
+
|
|
34
|
+
> **Note:** the rate limiter is **in-memory and per-process**. It is not shared across Puma workers or hosts. Use a reverse proxy, WAF, or `rack-attack` for strict distributed quotas.
|
|
35
|
+
|
|
36
|
+
### Structured logging
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
RailsAiBridge.configure do |config|
|
|
40
|
+
# Emit one JSON line per MCP HTTP response to Rails.logger
|
|
41
|
+
config.mcp.http_log_json = true
|
|
42
|
+
end
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Each log line includes `msg`, `event`, `http_status`, `path`, `client_ip`, and `request_id` (when present). Tokens and full Rack `env` are never logged. The flag is read **on each request** (unlike the rate-limit snapshot taken at `HttpTransportApp.build`).
|
|
46
|
+
|
|
47
|
+
### Post-auth authorization (`authorize`)
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
RailsAiBridge.configure do |config|
|
|
51
|
+
# Called after successful auth; returning falsey yields HTTP 403
|
|
52
|
+
config.mcp.authorize = ->(context, request) {
|
|
53
|
+
context[:role] == "admin"
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The lambda is read and called **on every request** (like `http_log_json`), so changes take effect immediately without rebuilding the transport app. If the lambda raises a `StandardError`, the gem treats it as a 403 and logs the error — it does not propagate as a 500.
|
|
59
|
+
|
|
60
|
+
### Production boot guard
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
RailsAiBridge.configure do |config|
|
|
64
|
+
# Raise at boot in production unless an auth mechanism is configured
|
|
65
|
+
config.mcp.require_auth_in_production = true
|
|
66
|
+
end
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
When `true` in a production environment, Rails boot fails unless at least one MCP HTTP auth mechanism is configured:
|
|
70
|
+
- `config.http_mcp_token`, or
|
|
71
|
+
- `ENV["RAILS_AI_BRIDGE_MCP_TOKEN"]`, or
|
|
72
|
+
- `config.mcp_token_resolver`, or
|
|
73
|
+
- `config.mcp_jwt_decoder`
|
|
74
|
+
|
|
75
|
+
Default is `false`.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## `strategy :bearer_token` misconfiguration guard
|
|
80
|
+
|
|
81
|
+
Rails **boot** raises `RailsAiBridge::ConfigurationError` if you configure `:bearer_token` strategy without a resolver or static token — that combination would leave HTTP MCP unauthenticated.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Resolver / JWT return values
|
|
86
|
+
|
|
87
|
+
Return **`nil`** (or `false`) when a token is invalid. Returning `false` explicitly is treated as auth failure (401).
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Roadmap: context files & assistant UX (pre–major release)
|
|
2
|
+
|
|
3
|
+
This track is **separate** from [roadmap-mcp-v2.md](roadmap-mcp-v2.md) (MCP HTTP auth, rate limits, logging). It covers **improving the static context** the gem generates (CLAUDE.md, Cursor rules, Copilot instructions, etc.) so IDEs and AI clients get **clearer, more actionable** help from the same introspection data.
|
|
4
|
+
|
|
5
|
+
**Progress summary:** [roadmaps.md](roadmaps.md).
|
|
6
|
+
|
|
7
|
+
## Goals (high level)
|
|
8
|
+
|
|
9
|
+
- Sharpen per-assistant formats (structure, length, cross-links) based on real usage feedback.
|
|
10
|
+
- Reduce duplication and noise while keeping "always-on" rules discoverable.
|
|
11
|
+
## Done
|
|
12
|
+
|
|
13
|
+
- Separate LLM provider serializers from domain infrastructure (done: `Serializers::Providers::` namespace).
|
|
14
|
+
- DRY the formatter hierarchy (done: `SectionFormatter` template method base).
|
|
15
|
+
- Align tool references and workflow hints across Claude, Cursor, Copilot, Windsurf, Codex, and **Gemini** (v2.1.0).
|
|
16
|
+
- Refactor provider serializers with a shared `BaseProviderSerializer` for consistent, high-fidelity output (v2.1.0).
|
|
17
|
+
|
|
18
|
+
## In progress
|
|
19
|
+
|
|
20
|
+
- Custom Rails directory introspection coverage gaps
|
|
21
|
+
|
|
22
|
+
## Relation to versioning
|
|
23
|
+
|
|
24
|
+
**No semver bump is implied by this doc alone.** A future **major release** (e.g. 2.0.0) should follow **after** this work when the maintainers are ready to communicate breaking or wide-ranging changes to generated files and defaults — not as a fixed milestone on the MCP roadmap.
|
|
25
|
+
|
|
26
|
+
## References
|
|
27
|
+
|
|
28
|
+
- [docs/GUIDE.md](GUIDE.md) — install, formats, MCP setup
|
|
29
|
+
- [CHANGELOG.md](../CHANGELOG.md) — user-visible changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Roadmap: MCP HTTP auth (v2 track)
|
|
2
|
+
|
|
3
|
+
High-level direction for the `RailsAiBridge::Mcp` HTTP authentication layer, rate limiting, and related docs. The detailed task list may live in your issue tracker; this file is the **human-readable** anchor for contributors.
|
|
4
|
+
|
|
5
|
+
## Engineering principles (this track)
|
|
6
|
+
|
|
7
|
+
These are **priorities** for code that lands under `lib/rails_ai_bridge/mcp/` and related Rack paths — not optional polish at the end.
|
|
8
|
+
|
|
9
|
+
1. **Tests gate implementation** — Write or extend a failing spec for the behavior, run it, then implement. No "implement first, test later" for new behavior.
|
|
10
|
+
|
|
11
|
+
2. **YARD on every public surface** — Any new or changed public Ruby class or method needs an English YARD summary, `@param`, `@return`, and `@raise` when applicable — before the change is considered done.
|
|
12
|
+
|
|
13
|
+
3. **Clear method boundaries** — Keep Rack/guard logic separate from "run host lambda safely." Strategies stay easy to read, review, and extend without growing god methods.
|
|
14
|
+
|
|
15
|
+
4. **Self-review before merge** — Run through `rails-code-review` (and security/architecture skills when touching auth or production boot).
|
|
16
|
+
|
|
17
|
+
5. **User-facing documentation per slice** — Update `CHANGELOG` `[Unreleased]`, and touch `GUIDE` / `SECURITY` / `UPGRADING` when user-visible behavior changes.
|
|
18
|
+
|
|
19
|
+
## Done (v2 snapshot)
|
|
20
|
+
|
|
21
|
+
- `Mcp::Authenticator` — consolidated strategy resolution (replaces `McpHttpAuth` + `Mcp::HttpAuth`)
|
|
22
|
+
- `Mcp::Auth::Strategies::BearerToken` — static token + optional `token_resolver`, digest compare
|
|
23
|
+
- `Mcp::Auth::Strategies::Jwt` — host-supplied `jwt_decoder`; no JWT gem bundled
|
|
24
|
+
- `Config::Auth` — flat auth sub-config (`http_mcp_token`, `mcp_token_resolver`, `mcp_jwt_decoder`)
|
|
25
|
+
- `Config::Mcp` — MCP HTTP operational config (`rate_limit_*`, `http_log_json`, `authorize`, `require_auth_in_production`, `mode`, `security_profile`)
|
|
26
|
+
- `Mcp::HttpRateLimiter` — in-process sliding window per IP, mutex, prune empty buckets
|
|
27
|
+
- `Mcp::HttpStructuredLog` — one JSON line per MCP HTTP outcome; no token logging
|
|
28
|
+
- `HttpTransportApp` — single Rack entry: path match → auth → authorize → rate limit → log → transport
|
|
29
|
+
- Boot / config validation — `:bearer_token` requires resolver or static token; `require_auth_in_production` alignment
|
|
30
|
+
- Docs: GUIDE / SECURITY / UPGRADING / CHANGELOG / roadmaps
|
|
31
|
+
|
|
32
|
+
## Next (follow-up, non-blocking)
|
|
33
|
+
|
|
34
|
+
- Log sampling (emit every Nth request instead of every request)
|
|
35
|
+
- Metrics hooks (expose request counts / rate-limit hits for APM)
|
|
36
|
+
- Heavier load testing / benchmarks
|
|
37
|
+
- Community-driven tweaks (e.g. per-route rate limits, response-size logging)
|
|
38
|
+
|
|
39
|
+
## References
|
|
40
|
+
|
|
41
|
+
- [docs/roadmaps.md](roadmaps.md) — quick progress tables for all tracks
|
|
42
|
+
- [docs/GUIDE.md](GUIDE.md) — MCP HTTP configuration
|
|
43
|
+
- [docs/roadmap-context-assistants.md](roadmap-context-assistants.md) — IDE / context file improvements
|
|
44
|
+
- [SECURITY.md](../SECURITY.md) — threat model and production notes
|
|
45
|
+
- [UPGRADING.md](../UPGRADING.md) — breaking / new config knobs
|
data/docs/roadmaps.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Roadmaps — progress index
|
|
2
|
+
|
|
3
|
+
Entry point to see **which tracks exist** and **what is left**. Details live in each linked file; update the tables here when you close slices (or track work in GitHub Issues / Projects instead).
|
|
4
|
+
|
|
5
|
+
**Audience:** These documents are mainly for **maintainers and contributors**. Gem users usually rely on [GUIDE.md](GUIDE.md), [CHANGELOG.md](../CHANGELOG.md), and the README. Keeping roadmaps **in git** is normal for open-source gems (transparency, onboarding); they are not required to *use* the gem.
|
|
6
|
+
|
|
7
|
+
## MCP HTTP track (`RailsAiBridge::Mcp`)
|
|
8
|
+
|
|
9
|
+
**Primary doc:** [roadmap-mcp-v2.md](roadmap-mcp-v2.md) (engineering principles + narrative snapshot).
|
|
10
|
+
|
|
11
|
+
| Area | Status |
|
|
12
|
+
|------|--------|
|
|
13
|
+
| Auth (`Mcp::Authenticator`, Bearer, JWT, resolver, boot guards) | Done |
|
|
14
|
+
| `authorize` + 403 | Done |
|
|
15
|
+
| In-process rate limit + bucket prune (`Mcp::HttpRateLimiter`) | Done |
|
|
16
|
+
| `mode` / `security_profile` + effective limits (`Config::Mcp`) | Done |
|
|
17
|
+
| JSON HTTP logging (`http_log_json`, `Mcp::HttpStructuredLog`) | Done |
|
|
18
|
+
| Docs (GUIDE / SECURITY / UPGRADING / CHANGELOG) for the above | Done |
|
|
19
|
+
|
|
20
|
+
**Optional / follow-up (non-blocking):** log sampling, metrics hooks, heavier load testing, community-driven tweaks.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## v2.0.0 — context files & assistant UX
|
|
25
|
+
|
|
26
|
+
**Primary doc:** [roadmap-context-assistants.md](roadmap-context-assistants.md).
|
|
27
|
+
|
|
28
|
+
| Area | Status |
|
|
29
|
+
|------|--------|
|
|
30
|
+
| Serializer formatter extraction (37 `Formatters::*` classes) | Done |
|
|
31
|
+
| `Config::Auth`, `Config::Server`, `Config::Introspection`, `Config::Output` façade | Done |
|
|
32
|
+
| `Config::Mcp` sub-object for MCP HTTP config | Done |
|
|
33
|
+
| `Mcp::Authenticator` consolidation | Done |
|
|
34
|
+
| Provider serializers extracted to `Serializers::Providers::` | Done |
|
|
35
|
+
| `SectionFormatter` template method base (DRY guard pattern) | Done |
|
|
36
|
+
| Major release (2.0.0) | Done |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## v2.1.0 — Gemini & Harmonization
|
|
41
|
+
|
|
42
|
+
| Area | Status |
|
|
43
|
+
|------|--------|
|
|
44
|
+
| Gemini Support (`GEMINI.md`, `GeminiSerializer`, Rake task) | Done |
|
|
45
|
+
| Context Harmonization (Shared `BaseProviderSerializer`) | Done |
|
|
46
|
+
| Enhanced directive guidance for all assistants | Done |
|
|
47
|
+
| Release (2.1.0) | Done |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Where to look in the repo
|
|
52
|
+
|
|
53
|
+
| Need | File |
|
|
54
|
+
|------|------|
|
|
55
|
+
| Implementation rules (tests, YARD, docs per slice) | [roadmap-mcp-v2.md](roadmap-mcp-v2.md) § Engineering principles |
|
|
56
|
+
| What the MCP stack already includes (narrative) | [roadmap-mcp-v2.md](roadmap-mcp-v2.md) § Done vs upcoming |
|
|
57
|
+
| Plan for generated context (CLAUDE.md, rules, etc.) | [roadmap-context-assistants.md](roadmap-context-assistants.md) |
|
|
58
|
+
| User-facing shipped / upcoming changes | [CHANGELOG.md](../CHANGELOG.md) `[Unreleased]` and version sections |
|
|
@@ -24,53 +24,81 @@ module RailsAiBridge
|
|
|
24
24
|
|
|
25
25
|
def create_initializer
|
|
26
26
|
standard_count = RailsAiBridge::Configuration::PRESETS[:standard].size
|
|
27
|
-
full_count
|
|
27
|
+
full_count = RailsAiBridge::Configuration::PRESETS[:full].size
|
|
28
|
+
regulated_count = RailsAiBridge::Configuration::PRESETS[:regulated].size
|
|
28
29
|
|
|
29
30
|
create_file "config/initializers/rails_ai_bridge.rb", <<~RUBY
|
|
30
31
|
# frozen_string_literal: true
|
|
31
32
|
|
|
32
33
|
RailsAiBridge.configure do |config|
|
|
33
|
-
# Introspector preset
|
|
34
|
-
# :standard
|
|
35
|
-
# :full
|
|
34
|
+
# --- Introspector preset ---
|
|
35
|
+
# :standard — #{standard_count} core introspectors (schema, models, routes, jobs, gems, conventions, controllers, tests, migrations)
|
|
36
|
+
# :full — all #{full_count} introspectors (adds views, turbo, auth, API, config, assets, devops, etc.)
|
|
37
|
+
# :regulated — #{regulated_count} introspectors — no schema/models/migrations (for apps with strict data governance)
|
|
36
38
|
# config.preset = :standard
|
|
37
39
|
|
|
38
40
|
# Or cherry-pick individual introspectors:
|
|
39
41
|
# config.introspectors += %i[views turbo auth api]
|
|
40
42
|
|
|
41
|
-
#
|
|
43
|
+
# Disable whole product categories at runtime (schema + models + migrations, api, views/turbo/i18n):
|
|
44
|
+
# config.disabled_introspection_categories << :domain_metadata
|
|
45
|
+
|
|
46
|
+
# --- Security exclusions ---
|
|
47
|
+
# Tables to hide from schema + model introspection (exact name or glob, e.g. "pii_*"):
|
|
48
|
+
# config.excluded_tables += %w[secrets audit_logs pii_*]
|
|
49
|
+
|
|
50
|
+
# Models to exclude from introspection:
|
|
42
51
|
# config.excluded_models += %w[AdminUser InternalThing]
|
|
43
52
|
|
|
44
|
-
# Paths
|
|
53
|
+
# Paths excluded from rails_search_code:
|
|
45
54
|
# config.excluded_paths += %w[vendor/bundle]
|
|
46
55
|
|
|
47
|
-
# Context
|
|
48
|
-
# :compact —
|
|
49
|
-
# :full —
|
|
56
|
+
# --- Context output ---
|
|
57
|
+
# :compact — ≤150 lines, references MCP tools for details (default)
|
|
58
|
+
# :full — full dump (good for small apps)
|
|
50
59
|
# config.context_mode = :compact
|
|
51
|
-
|
|
52
|
-
# Max lines for CLAUDE.md in compact mode
|
|
53
60
|
# config.claude_max_lines = 150
|
|
54
|
-
|
|
55
|
-
# Max response size for MCP tool results (chars). Safety net for large apps.
|
|
56
61
|
# config.max_tool_response_chars = 120_000
|
|
57
62
|
|
|
58
|
-
#
|
|
59
|
-
# The install stub uses <!-- rails-ai-bridge:omit-merge --> on line 1 — delete it when adding real rules
|
|
60
|
-
# (until then nothing is merged). See config/rails_ai_bridge/overrides.md.example for an outline.
|
|
63
|
+
# Team rules merged into compact Copilot/Codex output (remove omit-merge line when ready):
|
|
61
64
|
# config.assistant_overrides_path = "config/rails_ai_bridge/overrides.md"
|
|
62
65
|
|
|
63
|
-
# Compact
|
|
66
|
+
# Compact model list caps (0 = MCP pointer only, no names listed):
|
|
64
67
|
# config.copilot_compact_model_list_limit = 5
|
|
65
68
|
# config.codex_compact_model_list_limit = 3
|
|
66
69
|
|
|
67
|
-
#
|
|
70
|
+
# ==========================================================================
|
|
71
|
+
# HTTP MCP / auto_mount — SECURITY CRITICAL
|
|
72
|
+
# ==========================================================================
|
|
73
|
+
# Exposes read-only MCP tools over HTTP. Still reveals routes, schema, and
|
|
74
|
+
# code layout — treat as sensitive. Prefer stdio (`rails ai:serve`) for local
|
|
75
|
+
# AI clients.
|
|
76
|
+
#
|
|
77
|
+
# In production you MUST configure one auth mechanism AND set
|
|
78
|
+
# allow_auto_mount_in_production = true. Options (highest priority first):
|
|
79
|
+
#
|
|
80
|
+
# 1. JWT decoder (no JWT gem required — supply your own lambda):
|
|
81
|
+
# config.mcp_jwt_decoder = ->(token) {
|
|
82
|
+
# JWT.decode(token, credentials.jwt_secret, true, algorithm: "HS256").first
|
|
83
|
+
# rescue JWT::DecodeError
|
|
84
|
+
# nil
|
|
85
|
+
# }
|
|
86
|
+
#
|
|
87
|
+
# 2. Token resolver (Devise, database lookup, etc.):
|
|
88
|
+
# config.mcp_token_resolver = ->(token) { User.find_by(mcp_api_token: token) }
|
|
89
|
+
#
|
|
90
|
+
# 3. Static shared secret:
|
|
91
|
+
# config.http_mcp_token = "generate-a-long-random-secret"
|
|
92
|
+
# # ENV["RAILS_AI_BRIDGE_MCP_TOKEN"] overrides this when set
|
|
93
|
+
#
|
|
94
|
+
# IMPORTANT: Token comparison is timing-safe but does NOT prevent
|
|
95
|
+
# brute-force guessing. Add rate limiting on the MCP endpoint in
|
|
96
|
+
# production (e.g. Rack::Attack throttle on config.http_path).
|
|
97
|
+
#
|
|
68
98
|
# config.auto_mount = false
|
|
69
99
|
# config.allow_auto_mount_in_production = false
|
|
70
|
-
# config.
|
|
71
|
-
#
|
|
72
|
-
# config.http_path = "/mcp"
|
|
73
|
-
# config.http_port = 6029
|
|
100
|
+
# config.http_path = "/mcp"
|
|
101
|
+
# config.http_port = 6029
|
|
74
102
|
end
|
|
75
103
|
RUBY
|
|
76
104
|
|
|
@@ -140,6 +168,7 @@ module RailsAiBridge
|
|
|
140
168
|
say " rails ai:bridge:claude # Generate CLAUDE.md only"
|
|
141
169
|
say " rails ai:bridge:codex # Generate AGENTS.md only"
|
|
142
170
|
say " rails ai:bridge:cursor # Generate .cursorrules only"
|
|
171
|
+
say " rails ai:bridge:gemini # Generate GEMINI.md only"
|
|
143
172
|
say " rails ai:serve # Start MCP server (stdio)"
|
|
144
173
|
say " rails ai:inspect # Print introspection summary"
|
|
145
174
|
say ""
|
|
@@ -149,6 +178,7 @@ module RailsAiBridge
|
|
|
149
178
|
say " Cursor → .cursorrules + .cursor/rules/*.mdc (incl. rails-engineering.mdc)"
|
|
150
179
|
say " Windsurf → .windsurfrules + .windsurf/rules/*.md"
|
|
151
180
|
say " GitHub Copilot → .github/copilot-instructions.md + .github/instructions/*.instructions.md"
|
|
181
|
+
say " Gemini → GEMINI.md"
|
|
152
182
|
say ""
|
|
153
183
|
say "MCP auto-discovery:", :yellow
|
|
154
184
|
say " .mcp.json is auto-detected by Claude Code and Cursor."
|