activerecord-mcp

CI

The read-only MCP server Rails developers have been looking for.

Drop it into any Rails app and your AI tools can introspect your ActiveRecord models and query your database instantly — no standalone process, no raw SQL, no credentials handed to a client. By default every query runs against a read-only database role, so production data stays safe. If you need writes, swap in any role your app already has.

Built on the official MCP Ruby SDK and mounted as a Rails Engine, it shares Puma's thread pool and your existing connection pool. Nothing extra to run.

Why activerecord-mcp

  • Read-only by default — queries run against a named database role (:reading); your write replica or primary is never touched unless you configure it
  • No raw SQL — all queries go through hash conditions validated against actual column names; no string interpolation reaches the database
  • Fine-grained access control — allowlist models, denylist columns by exact name or regex, or define a per-model column allowlist in a YAML file
  • OAuth 2.1 + PKCE — every request requires a scoped Bearer token via Doorkeeper; tokens from other clients are rejected at the middleware layer
  • Zero extra infrastructure — mounts as a Rails Engine; shares Puma threads and ActiveRecord connections with the rest of your app
  • Extensible — register custom tools alongside the built-ins using a simple DSL

Table of contents

Installation

Add to your Gemfile:

gem "activerecord-mcp"
gem "doorkeeper"
bundle install
bin/rails generate doorkeeper:install
bin/rails generate doorkeeper:migration
bin/rails db:migrate

Basic setup

1. Configure Doorkeeper (config/initializers/doorkeeper.rb):

Doorkeeper.configure do
  orm :active_record
  pkce_code_challenge_methods %w[S256]

  resource_owner_authenticator do
    current_user || redirect_to(new_user_session_url)
  end
end

2. Mount the engine (config/routes.rb):

Rails.application.routes.draw do
  use_doorkeeper
  mount RailsMcp::Engine, at: "/mcp"
end

3. Generate the initializer:

bin/rails generate rails_mcp:install

This creates config/initializers/rails_mcp.rb with every option documented and commented out. Edit it to restrict access:

RailsMcp.configure do |config|
  config.allowed_models = %w[User Post Order]
  config.denied_columns = ["password_digest", /token/i, /secret/i]
end

That's it — the five built-in query tools are live at /mcp.

Quick example

# Get a Bearer token (see docs/authentication.md)
TOKEN="eyJhbGc..."

# List accessible models
curl -X POST https://your-app.com/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"list_models","arguments":{}},"id":1}'

# Query records
curl -X POST https://your-app.com/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
      "name": "query_records",
      "arguments": {
        "model": "User",
        "conditions": { "active": true },
        "fields": ["id", "name", "email"],
        "limit": 10
      }
    },
    "id": 2
  }'

Documentation

Topic Description
Authentication OAuth 2.1 + PKCE setup, Bearer tokens, discovery endpoint
Querying All five built-in tools with full argument reference
Configuration All config options with defaults and explanations
Advanced usage YAML model allowlist, explicit column deny, custom tools DSL

Development

bundle install
bundle exec rake test

Bug reports and pull requests welcome at https://github.com/pauloancheta/rails-mcp.