2
.
09
.
2025
2
.
09
.
2025
Ruby on Rails
LLM

MCP Template for Rails applications

Paweł Strzałkowski
Chief Technology Officer
MCP Template for Rails applications by Paweł Strzałkowski

After building several MCP servers with Rails using different approaches in my previous posts in this series, I started noticing a pattern. Every time I wanted to create a new MCP-enabled Rails application, I had to go through the same setup steps: add the gem, create the controller, configure routes, set up tool autoloading, prepare MCP response formatting. It was becoming repetitive.

This repetition got me thinking about one of Rails core principles: Convention over Configuration. What if integrating MCP with Rails could be as simple as scaffolding a regular Rails application?

The Rails Way of Thinking

Rails has always been about reducing boilerplate and focusing on the essential parts of your application. When you scaffold a model, you get the controller, views, routes, and tests automatically generated. The framework handles the repetitive parts so you can focus on your business logic.

The same principle should apply to MCP integration. But rather than just automating setup, what if we could enhance Rails scaffolding to generate AI tools alongside the standard files?

Enhancing Rails Scaffolding with MCP Tools

The premise isn't just about automation - it's about extending Rails capabilities. What if rails generate scaffold could create not only controllers and views, but also MCP tools that make your models immediately accessible to AI assistants?

I built a Rails application template that does exactly this. The template is available at https://github.com/pstrzalk/mcp-on-rails and you can use it to create a new Rails application like this:

$ git clone https://github.com/pstrzalk/mcp-on-rails.git
$ rails new myapp -m mcp-on-rails/mcp

This creates a Rails application that serves MCP requests at /mcp using streamable HTTP transport, but more importantly, it enhances the scaffolding process to automatically generate MCP tools.

Alternatively, you may apply this template to an existing application:

$ git clone https://github.com/pstrzalk/mcp-on-rails.git
$ cd your-project/
$ rails app:template LOCATION=../mcp-on-rails/mcp

Generator Hooks: Extending Rails Functionality

The key insight was using Rails generator hook system to extend existing functionality rather than replacing it. This is the same pattern used by gems like jbuilder - they enhance the scaffold generator without overriding it.

When you run rails generate scaffold Post title:string content:text, the enhanced scaffolding process creates the standard Rails files plus five MCP tools:

  • Show tool for retrieving individual records
  • Index tool with filtering and listing the last N records
  • Create tool with validation
  • Update tool with partial updates
  • Delete tool

The beauty of this approach is that it feels like a natural extension of Rails. You're not learning a new workflow - you're using the same scaffolding commands you already know, just with enhanced output.

Smart Tool Generation

The generated tools include intelligent features based on your model structure. For models with references, the tools automatically handle relationships. If you scaffold Comment post:references content:text, the create tool will require a post_id parameter, and the index tool will allow filtering by post.

Type mapping is handled automatically. String fields become type: "string" in the JSON schema, integers become type: "integer", and so on.

Error handling is comprehensive, covering validation errors, not found errors, and general exceptions with meaningful messages.

Generate MCP Tools with ActiveRecord models

Let's say you're building a blog application. After creating the Rails app with the MCP template, you scaffold your models:

$ rails generate scaffold Post title:string content:text author:string
$ rails generate scaffold Comment post:references content:text author:string

You now have a fully functional blog, but also a complete set of MCP tools. An AI assistant can immediately:

  • List the most recent posts (with configurable count)
  • Create new posts with validation
  • Filter comments by post
  • Update existing content
  • Delete records

All without writing a single line of MCP-specific code. The scaffolding process handled both the web interface and the AI interface.

Scaffolded MCP Tools

The full list of MCP Tools generated alongside the ActiveRecord objects is:

app/tools/posts/
  - create_tool.rb
  - delete_tool.rb
  - index_tool.rb
  - show_tool.rb
  - update_tool.rb
app/tools/comments/
  - create_tool.rb
  - delete_tool.rb
  - index_tool.rb
  - show_tool.rb
  - update_tool.rb

Let’s take a look at some example implementations. Remember, those have been scaffolded automatically!

# app/tools/posts/create_tool.rb

module Posts
  class CreateTool < MCP::Tool
    tool_name "post-create-tool"
    description "Create a new Post entity"

    input_schema(
      properties: {
        title: { type: "string" },
        body: { type: "string" }
      },
      required: []
    )

    def self.call(title: nil, body: nil, server_context:)
      post = Post.new(
        title: title,
        body: body
      )

      if post.save
        MCP::Tool::Response.new([ { type: "text", text: "Created #{post.to_mcp_response}" } ])
      else
        MCP::Tool::Response.new([ { type: "text", text: "Post was not created due to the following errors: #{post.errors.full_messages.join(', ')}" } ])
      end
    rescue StandardError => e
      MCP::Tool::Response.new([ { type: "text", text: "An error occurred, what happened was #{e.message}" } ])
    end
  end
end

Additionally, when you look at the comments-related tools, you may see that they include the post_id parameter, as the underlying ActiveRecord object does.

module Comments
  class IndexTool < MCP::Tool
    tool_name "comment-index-tool"
    description "List the last count of Comments entities. The count parameter is an integer and defaults to 10. post_id property may be used to filter by integer identifier of the related Post entity."

    input_schema(
      properties: {
        count: { type: "integer" },
        post_id: { type: "integer" }
      },
      required: []
    )

    def self.call(count: 10, post_id: nil, server_context:)
      comments = Comment.all
      comments = comments.where(post_id: post_id) if post_id.present?
      comments = comments.last(count)

      response = comments.map(&:to_mcp_response).join("\n")
      response = "Nothing was found" unless response.present?

      MCP::Tool::Response.new([ { type: "text", text: response } ])
    rescue StandardError => e
      MCP::Tool::Response.new([ { type: "text", text: "An error occurred, what happened was #{e.message}" } ])
    end
  end
end

Should tools implement CRUD actions?

While the template generates CRUD tools automatically, it's important to understand that effective MCP tools often need to go beyond simple database operations. LLMs aren't particularly good at following long procedural lists of small partial steps. They work better when given tools accomplish bigger, more meaningful tasks.

For example, instead of having an AI assistant call three separate tools to create a post, add tags, and notify subscribers, you might want a single "publish post" tool that handles all these operations together. Similarly, instead of multiple calls to search, filter, and format results, a "generate report" tool could handle the entire workflow.

This is where the custom tool generator becomes valuable. While scaffolding gives you the basic CRUD operations, real-world applications often need tools that:

  • Aggregate multiple database operations into business workflows
  • Handle complex validation and business rules
  • Integrate with external services as part of larger processes
  • Provide domain-specific functionality that maps to how users actually think about the problem

The CRUD tools serve as building blocks, but the most effective MCP integrations often involve creating higher-level tools that encapsulate complete user intentions rather than exposing low-level data operations.

Custom tool generator

The template also includes a generator for custom tools when you need functionality beyond basic CRUD:

$ rails generate mcp_tool EmailSender recipient:string subject:string body:text

This creates a tool with the proper structure and type mapping, ready for you to implement your custom logic.

Scaffolding as a learning exercise

It's worth noting that having Active Record scaffolding generate MCP tools serves an important educational purpose. Just as early Ruby on Rails taught developers about CRUD operations in web development - lessons that helped us progress to thinking at scale and building more complex products - this approach teaches Rails developers how to think about MCP integration. The scaffolded tools provide a solid foundation for understanding how AI assistants can interact with your data, even if your production tools end up being more sophisticated.

The future of MCP in Rails ecosystem

The Model Context Protocol is still evolving, and so is the Rails ecosystem around it. This template represents one approach to enhancing Rails built-in capabilities, but there's room for many more patterns and tools.

What interests me most is how this changes the development workflow. When every scaffolded model automatically becomes available to AI assistants, it opens up new possibilities for how we build and interact with web applications.

The MCP Rails template is available at https://github.com/pstrzalk/mcp-on-rails. I'm looking forward to seeing how the Rails community adopts and evolves these enhanced scaffolding patterns.

Articles in this series

Paweł Strzałkowski
Chief Technology Officer

Check my Twitter

Check my Linkedin

Did you like it? 

Sign up To VIsuality newsletter

READ ALSO

MCP Template for Rails applications by Paweł Strzałkowski

MCP Template for Rails applications

11
.
06
.
2025
Paweł Strzałkowski
Ruby on Rails
LLM

Stimulus: Managing State with Outlets and Events

20
.
08
.
2025
Grzegorz Płóciniak
Hotwire
Ruby on Rails
Frontend
Tradeoffs of Anonymising Production Data by Michał Łęcicki

Tradeoffs of Anonymising Production Data

11
.
06
.
2025
Michał Łęcicki
Postgresql
Software
Ruby MCP Client in Rails by Paweł Strzałkowski

MCP Client in Rails using ruby-mcp-client gem

11
.
06
.
2025
Paweł Strzałkowski
LLM
Ruby on Rails
Actionmcp in Ruby on Rails by Paweł Strzałkowski

MCP Server with Rails and ActionMCP

11
.
06
.
2025
Paweł Strzałkowski
LLM
Ruby on Rails
Banner - MCP Server with FastMCP and Rails by Paweł Strzałkowski

MCP Server with Rails and FastMCP

11
.
06
.
2025
Paweł Strzałkowski
LLM
Ruby
Ruby on Rails

Ruby on Rails and Model Context Protocol

11
.
06
.
2025
Paweł Strzałkowski
Ruby on Rails
LLM
Title image

Highlights from wroclove.rb 2025

24
.
07
.
2025
Kaja Witek
Conferences
Ruby
Jarosław Kowalewski - Migration from Heroku using Kamal

Migration from Heroku using Kamal

11
.
06
.
2025
Jarosław Kowalewski
Backend
store-vs-store_accessor by Michał Łęcicki

Active Record - store vs store_accessor

11
.
06
.
2025
Michał Łęcicki
Ruby
Ruby on Rails
How to become a Ruby Certified Programmer Title image

How to become a Ruby Certified Programmer

11
.
06
.
2025
Michał Łęcicki
Ruby
Visuality
Vector Search in Ruby - Paweł Strzałkowski

Vector Search in Ruby

11
.
06
.
2025
Paweł Strzałkowski
ChatGPT
Embeddings
Postgresql
Ruby
Ruby on Rails
LLM Embeddings in Ruby - Paweł Strzałkowski

LLM Embeddings in Ruby

11
.
06
.
2025
Paweł Strzałkowski
Ruby
LLM
Embeddings
ChatGPT
Ollama
Handling Errors in Concurrent Ruby, Michał Łęcicki

Handling Errors in Concurrent Ruby

11
.
06
.
2025
Michał Łęcicki
Ruby
Ruby on Rails
Tutorial
Recap of Friendly.rb 2024 conference

Insights and Inspiration from Friendly.rb: A Ruby Conference Recap

24
.
07
.
2025
Kaja Witek
Conferences
Ruby on Rails

Covering indexes - Postgres Stories

11
.
06
.
2025
Jarosław Kowalewski
Ruby on Rails
Postgresql
Backend
Ula Sołogub - SQL Injection in Ruby on Rails

The Deadly Sins in RoR security - SQL Injection

11
.
06
.
2025
Urszula Sołogub
Backend
Ruby on Rails
Software
Michal - Highlights from Ruby Unconf 2024

Highlights from Ruby Unconf 2024

11
.
06
.
2025
Michał Łęcicki
Conferences
Visuality
Cezary Kłos - Optimizing Cloud Infrastructure by $40 000 Annually

Optimizing Cloud Infrastructure by $40 000 Annually

11
.
06
.
2025
Cezary Kłos
Backend
Ruby on Rails

Smooth Concurrent Updates with Hotwire Stimulus

11
.
06
.
2025
Michał Łęcicki
Hotwire
Ruby on Rails
Software
Tutorial

Freelancers vs Software house

11
.
06
.
2025
Michał Krochecki
Visuality
Business

Table partitioning in Rails, part 2 - Postgres Stories

11
.
06
.
2025
Jarosław Kowalewski
Backend
Postgresql
Ruby on Rails