Web Analytics

mcp-on-rails

⭐ 142 stars English by pstrzalk

MCP on Rails (with optional OAuth)

A Rails application template that integrates the Model Context Protocol (MCP) with Ruby on Rails. During setup, the template asks whether to add OAuth 2.1 protection using Devise and Doorkeeper — so one template supports both plain MCP and fully authenticated setups.

Quick Start

git clone https://github.com/pstrzalk/mcp-on-rails.git
rails new myapp -m mcp-on-rails/mcp
cd myapp
rails db:migrate
rails server
The template will prompt:

Add Devise + Doorkeeper OAuth 2.1 authentication? (y/n)

Answer n for a plain MCP server or y for full OAuth protection.

Adding the MCP template to an existing Rails application

You may just as easily apply this template to an existing Rails app.

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


Plain MCP (answer "n")

Creates a Rails app with an open MCP server — no authentication required.

What you get

Usage

rails new myapp -m mcp-on-rails/mcp   # answer n
cd myapp && rails db:migrate

rails generate scaffold Post title:string body:text rails db:migrate rails server

Test it:

# MCP initialize
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'

List tools

curl -X POST http://localhost:3000/mcp \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

Project structure (plain mode)

app/
├── controllers/
│   └── mcp_controller.rb              # Open MCP endpoint (no auth)
├── models/
│   └── application_record.rb          # Extended with to_mcp_response
├── prompts/                           # MCP prompts (created via generator)
└── tools/                             # MCP tools (auto-generated per scaffold)

config/ ├── initializers/ │ └── mcp.rb # MCP tool and prompt autoloading └── routes.rb # MCP routes

lib/ ├── generators/ # MCP tool and prompt generators └── tasks/ └── mcp.rake # rake mcp:tools, rake mcp:prompts (and verbose variants)

Connecting AI assistants (plain mode)

{
  "name": "my-rails-app",
  "type": "StreamableHttp",
  "url": "http://localhost:3000/mcp"
}
No authentication needed — the /mcp endpoint is open.


OAuth MCP (answer "y")

Creates a Rails app with an OAuth 2.1-protected MCP server, including PKCE, dynamic client registration, and resource indicator support — everything needed for MCP's OAuth authorization flow.

What you get

Everything from plain mode, plus:

Usage

rails new myapp -m mcp-on-rails/mcp   # answer y
cd myapp && rails db:migrate

rails generate scaffold Post title:string body:text rails db:migrate rails server

The /mcp endpoint now requires a Bearer token — unauthenticated requests return 401.

OAuth flow

The full authorization flow follows MCP's OAuth specification:

Supported RFCs

| RFC | Description | Endpoint | |-----|-------------|----------| | OAuth 2.1 + PKCE | Authorization with Proof Key for Code Exchange (S256) | /oauth/authorize, /oauth/token | | RFC 7591 | Dynamic Client Registration | POST /oauth/register | | RFC 8414 | Authorization Server Metadata | GET /.well-known/oauth-authorization-server | | RFC 8707 | Resource Indicators | resource parameter in auth + token requests | | RFC 9728 | Protected Resource Metadata | GET /.well-known/oauth-protected-resource |

Project structure (OAuth mode)

app/
├── controllers/
│   ├── mcp_controller.rb                              # OAuth-protected MCP endpoint
│   ├── oauth_client_registration_controller.rb        # RFC 7591
│   └── oauth_authorization_server_metadata_controller.rb  # RFC 8414 + 9728
├── models/
│   ├── user.rb                                        # Devise user with OAuth associations
│   ├── oauth_application.rb
│   ├── oauth_access_token.rb
│   └── oauth_access_grant.rb
├── prompts/                                           # MCP prompts (created via generator)
├── tools/                                             # MCP tools (auto-generated per scaffold)
└── views/
    └── devise/                                        # Customizable auth views

config/ ├── initializers/ │ ├── doorkeeper.rb # OAuth + PKCE config │ ├── devise.rb # User auth config │ └── mcp.rb # MCP tool autoloading └── routes.rb # All OAuth + MCP routes

db/migrate/ ├── *_devise_create_users.rb ├── *_create_doorkeeper_tables.rb ├── *_enable_pkce.rb └── *_add_resource_to_oauth_tables.rb

Connecting AI assistants (OAuth mode)

{
  "name": "my-rails-app",
  "type": "StreamableHttp",
  "url": "http://localhost:3000/mcp"
}

The client must complete the OAuth PKCE flow before making MCP requests — the /mcp endpoint returns 401 without a valid Bearer token.


Common Features (both modes)

Scaffolding models with MCP tools

rails generate scaffold Post title:string content:text
rails db:migrate

This creates standard Rails files plus 5 MCP tools in app/tools/posts/:

Creating custom MCP tools

rails generate mcp_tool WeatherCheck location:string

Creating custom MCP prompts

rails generate mcp_prompt hotel_finder location:required check_in_date:required adults price_max

This creates app/prompts/hotel_finder.rb with a prompt class inheriting from MCP::Prompt. Arguments are optional by default — append :required to make them required.

Prompts are automatically loaded from app/prompts/ and registered with the MCP server. Unlike tools, prompts are not auto-generated during scaffolding — they are created explicitly via the generator.

Listing available tools and prompts

rake mcp:tools             # compact one-line-per-tool summary
rake mcp:tools:verbose     # full details with schema
rake mcp:prompts           # compact one-line-per-prompt summary
rake mcp:prompts:verbose   # full details with arguments

License

MIT License

--- Tranlated By Open Ai Tx | Last indexed: 2026-06-17 ---