BoilerplateHub

MCP Servers for Ruby on Rails

Rails has twenty years of accumulated idioms in training data, and a large share of them were removed years ago, so an agent's confident answer is often a Rails 4 answer. The frontend story in particular forked several times, from Sprockets to Webpacker to importmaps and Hotwire, and picking the wrong one produces code that never loads. An agent also needs to understand that the schema file is generated output and that ActiveRecord callbacks are the default place agents hide side effects.

Wiring MCP into a Ruby on Rails project

  • Point the database server at development or a restored staging dump, not the production replica.
  • Commit .mcp.json at the repo root so the whole team's agents share the same browser server for Turbo testing.
  • Scope the filesystem server to app/, config/, db/, and test or spec so bundled gems stay out of search results.

Servers worth adding

Filesystem MCP server

Scoped read and write access to the application directory.

Rails convention means the right file location is usually inferable, but only if the agent can actually see app/ and config/ rather than assume them.

Git MCP server

History, diffs, and blame across the repository.

Gemfile.lock history is the reliable way to establish which Rails and Ruby versions the codebase is actually on.

A Postgres MCP server

Schema inspection and read queries.

It lets the agent verify what the database really contains rather than trusting a schema.rb that may have been hand-edited.

Playwright MCP server

Drives a real browser through the running app.

Turbo Frames and Turbo Streams behave differently from full page loads, and only a browser session shows which one actually fired.

Sentry MCP server

Reads issues and stack traces from Sentry.

Background job failures in ActiveJob are invisible locally and are usually the first place a callback side effect blows up.

Skills, MCP and plugins compared →

Rule these out for Ruby on Rails

These are the failures that repeat across sessions, so each one belongs in .mcp.json.

Bypassing strong parameters with permit!

When a nested attribute fails to save, the shortest fix an agent finds is params.require(:user).permit! or passing params directly to update, which re-opens mass assignment across every column including role and admin flags. It always makes the immediate error disappear. Add to your rules file: 'Strong parameter methods list permitted keys explicitly. permit! is never acceptable, and nested attributes are permitted by naming their keys.'

Interpolating params into a where clause

Agents write where("name LIKE '%#{params[:q]}%'") because string interpolation is the natural Ruby reflex and the result reads fine. That is a SQL injection hole, and it appears most often in search and sort code where the input is user supplied by definition. Write: 'ActiveRecord conditions always use hash conditions or positional placeholders. Never interpolate a variable into a SQL string, including ORDER BY clauses built from params.'

Preloading omitted before iterating associations

A controller returns Article.all and the view renders article.author.name plus article.comments.size, quietly issuing several queries per article. Rails makes this so ergonomic that it survives code review. Add: 'Controllers pass fully preloaded relations to views using includes or preload. Add the Bullet gem in development and treat its warnings as failures rather than logging noise.'

Piling side effects into model callbacks

Asked to notify a user after a record is created, agents add an after_create that sends mail, charges a card, or posts to a webhook. It then fires from seeds, from every factory in the test suite, and from console fixes, and it cannot be skipped without skipping validations too. Write: 'Callbacks may set derived attributes on the same record only. Notifications, payments, and outbound requests are dispatched explicitly from a service object or ActiveJob in the controller or job that owns the flow.'

Hand-editing db/schema.rb

When schema.rb does not match what an agent expects, it edits the file directly instead of writing a migration, which produces a schema that no migration can reproduce and a version number that lies. The app boots, so nothing complains until the next deploy. Add: 'db/schema.rb is generated. All schema changes go through rails generate migration, and schema.rb is only ever updated as a side effect of running migrations.'

Reaching for removed Rails idioms

before_filter, attr_accessible, render :text, and Webpacker configuration all still appear in agent output, and each was removed or replaced several major versions ago. The failure mode ranges from a deprecation to a NoMethodError at boot. State your versions: 'Rails 7 or later on Ruby 3.x, using importmaps and Hotwire. Use before_action, strong parameters, and render plain. Never add Webpacker, attr_accessible, or before_filter.'

Same framework, other agents