38 MCP tools that give AI agents live access to your Rails schema, models, routes & conventions.
How rails-ai-context is built, and why.
graph TD
subgraph app["Your Rails App"]
A["models + schema + routes + controllers + views + jobs + config"]
end
A -->|"31 introspectors"| gem
subgraph gem["rails-ai-context"]
direction TB
subgraph engine["Introspection Engine"]
direction LR
I["Introspectors\n31 modules\nPresets\nCached"]
AST["AST Engine\nPrism\n7 listeners\nConfidence tags"]
H["Hydration Layer\nSchema hints\ninjected into\ntool responses"]
end
engine --> R["Tool Registry\n38 tools auto-discovered via inherited\n+ custom_tools - skip_tools = active tools"]
end
R --> MCP
R --> CLI
R --> S
subgraph outputs["Output"]
direction LR
MCP["MCP Server\nstdio / HTTP\nResources\nVFS URIs"]
CLI["CLI Runner\nRake / Thor\nSame 38 tools\nNo server needed"]
S["Serializers\n14 modules\nStatic files\nPer-AI-tool"]
end
style app fill:#4a9eff,stroke:#2d7ad4,color:#fff
style gem fill:#2d2d2d,stroke:#555,color:#fff
style engine fill:#3a3a3a,stroke:#666,color:#fff
style outputs fill:#1a1a1a,stroke:#444,color:#fff
style I fill:#6c5ce7,stroke:#5a4bd1,color:#fff
style AST fill:#e17055,stroke:#c0392b,color:#fff
style H fill:#00b894,stroke:#00a381,color:#fff
style R fill:#fdcb6e,stroke:#f0b429,color:#333
style MCP fill:#0984e3,stroke:#0770c2,color:#fff
style CLI fill:#00cec9,stroke:#00b5b0,color:#fff
style S fill:#a29bfe,stroke:#8c83f0,color:#fff
sequenceDiagram
participant AI as AI Assistant
participant MCP as MCP Server
participant TR as Tool Registry
participant Cache as Cache Layer
participant App as Rails App
AI->>MCP: rails_get_schema(table: "users")
MCP->>TR: resolve tool + execute
TR->>Cache: check introspection cache
alt cache hit (TTL + fingerprint valid)
Cache-->>TR: cached context
else cache miss
Cache->>App: introspect (31 modules)
App-->>Cache: structured data
Cache-->>TR: fresh context
end
TR-->>MCP: MCP::Tool::Response
MCP-->>AI: schema with columns, indexes, hints
flowchart LR
A[Tool Call] --> B{Registered?}
B -->|Yes| C{Cache Valid?}
B -->|No| E[ToolNotFoundError]
C -->|Hit| D[Return Cached]
C -->|Miss| F[Introspect]
F --> G[Cache Result]
G --> D
D --> H[Hydrate\nSchema Hints]
H --> I[Truncate\nmax_chars]
I --> J[MCP::Tool::Response]
lib/rails_ai_context/introspectors/)31 modules that extract structured data from your Rails app. Each introspector:
{ error: msg })INTROSPECTOR_MAP with a symbol key:standard, :full)The Introspector orchestrator runs configured introspectors and merges results.
Prism AST parsing replaced all regex-based Ruby source parsing in v5.2.0.
Concurrent::Map), keyed by path + SHA256 + mtime[VERIFIED] (static literals) or [INFERRED] (dynamic expressions)lib/rails_ai_context/tools/base_tool.rb)Auto-registration via Ruby’s inherited hook:
BaseTool.inherited(subclass) fires when any file in tools/ defines a subclass@descendants (protected by @registry_mutex)BaseTool.registered_tools eager-loads all tool files and returns non-abstract classesBaseTool itself is marked abstract! — excluded from the registryDeadlock-free design: eager_load! collects constants to load inside the mutex, loads them outside (because const_get triggers Zeitwerk autoloading which calls inherited which needs the mutex), then sets the flag inside the mutex.
lib/rails_ai_context/server.rb)Built on the official mcp Ruby SDK:
MCP::Server::Transports::StreamableHTTPTransport)ActiveSupport::Notificationslib/rails_ai_context/vfs.rb)Virtual File System for rails-ai-context:// URIs:
rails-ai-context://models/Post → model details + schema
rails-ai-context://controllers/Posts → actions, filters, params
rails-ai-context://controllers/Posts/index → action source
rails-ai-context://views/posts/show.html.erb → template content
rails-ai-context://routes/posts → filtered routes
Every resolve call introspects fresh — zero stale data.
lib/rails_ai_context/hydrators/)Cross-tool semantic hydration (v5.3.0):
@post → Post by convention, injects schema hintsSchemaHint value objects from cached contextResult: controller and view tools automatically include relevant schema information without extra tool calls.
lib/rails_ai_context/serializers/)14 modules that format introspection output for different AI tools:
| Serializer | Output |
|---|---|
ClaudeSerializer |
CLAUDE.md |
ClaudeRulesSerializer |
.claude/rules/*.md |
CursorRulesSerializer |
.cursor/rules/*.mdc |
CopilotSerializer |
.github/copilot-instructions.md |
CopilotInstructionsSerializer |
.github/instructions/*.instructions.md |
OpencodeSerializer |
AGENTS.md (root) |
OpencodeRulesSerializer |
app/*/AGENTS.md |
JsonSerializer |
.ai-context.json |
MarkdownSerializer |
Base formatting |
ContextFileSerializer |
Atomic file writes with section markers |
CompactSerializerHelper |
Compact mode (≤150 lines) |
StackOverviewHelper |
Stack overview sections |
ToolGuideHelper |
MCP/CLI tool reference sections |
TestCommandDetection |
Test framework detection |
exe/rails-ai-context, lib/rails_ai_context/cli/)Thor-based CLI that works standalone (no Gemfile entry):
ToolRunner — Parses CLI args, resolves tool names, executes tools, formats output--json mode for machine-readable outputThree cache layers:
BaseTool.SHARED_CACHE) — Mutex-protected, TTL + fingerprint invalidationAstCache) — Concurrent::Map, SHA256 fingerprint per fileBaseTool.SESSION_CONTEXT) — Mutex-protected call history, resets on server restartLiveReload watches files and calls reset_all_caches! when changes are detected.
lib/rails_ai_context/fingerprinter.rb)SHA256-based change detection:
app/, config/, db/, lib/tasks/, Gemfile.lockmcp gem’s MCP::Tool, MCP::Server, transports.require_relative in the gem.<!-- BEGIN/END rails-ai-context --> to preserve user-added content.| Gem | Purpose | Required? |
|---|---|---|
mcp |
MCP SDK — server, tools, transports | Yes |
prism |
AST parsing (stdlib in Ruby 3.3+) | Yes |
concurrent-ruby |
Thread-safe caches | Yes |
zeitwerk |
Autoloading | Yes |
thor |
CLI framework | Yes |
brakeman |
Security scanning | Optional |
listen |
File watching for live reload | Optional |