Project

flehmen

0.0
No release in over 3 years
A generic Ruby gem that auto-discovers ActiveRecord models and provides read-only query tools via the Model Context Protocol (MCP) for Claude Desktop integration.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

 Project Readme

Flehmen

flehmen-response-cat

A Ruby gem that exposes Rails ActiveRecord models to Claude Desktop via the Model Context Protocol (MCP). It auto-discovers models, provides read-only query tools, and filters sensitive fields.

Installation

Add to your Gemfile:

gem "flehmen"

Setup

Rails initializer

Create config/initializers/flehmen.rb:

Flehmen.configure do |config|
  config.exclude_models = []
  config.sensitive_fields = %i[
    password_digest encrypted_password token secret
    api_key api_secret access_token refresh_token
    otp_secret reset_password_token confirmation_token
    unlock_token remember_token authentication_token
  ]
  config.max_results = 100
end

Flehmen.catloaf(Rails.application, path_prefix: "/mcp", localhost_only: false)

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "flehmen": {
      "command": "npx",
      "args": ["mcp-remote", "http://localhost:3000/mcp/sse", "--allow-http"]
    }
  }
}

Note: The URL must end with /mcp/sse. The underlying fast_mcp gem uses SSE transport, so /mcp alone will return 404.

Configuration

Option Type Default Description
models :all or Array :all Models to expose. :all auto-discovers all ApplicationRecord descendants
exclude_models Array [] Model classes or strings to exclude
sensitive_fields Array<Symbol> See below Fields masked with [FILTERED] across all models
model_sensitive_fields Hash {} Per-model sensitive fields
max_results Integer 100 Maximum records returned by any query
read_only_connection Boolean true Wraps all queries in while_preventing_writes to block accidental writes at the Rails level
auth_token String or nil nil Static Bearer token for simple authentication (mutually exclusive with authenticate)
authenticate Proc or nil nil Custom auth callback (headers) -> user | truthy | nil (mutually exclusive with auth_token)

Authentication

Authentication is opt-in. By default the MCP endpoint is open, so it is strongly recommended to either restrict access via localhost_only: true or configure one of the two authentication modes below.

Mode 1: Static token

The simplest option. Uses FastMcp's built-in Bearer token authentication. Requests must include Authorization: Bearer <token>.

Flehmen.configure do |config|
  config.auth_token = ENV['MCP_AUTH_TOKEN']
end

Flehmen.catloaf(Rails.application, path_prefix: "/mcp")

Mode 2: Custom authentication callback

For JWT, per-user API keys, or any other auth logic. Provide a Proc that receives the request headers hash and returns a truthy value (typically a user object) to allow, or nil/false to deny.

Header keys are lowercase and hyphen-separated (e.g. 'authorization', 'x-api-key').

Flehmen.configure do |config|
  config.authenticate = ->(headers) {
    token = headers['authorization']&.sub(/\ABearer /, '')
    User.find_by(api_token: token)
  }
end

The return value is exposed as current_user inside any tool subclass:

class MyCustomTool < Flehmen::Tools::Base
  def execute
    "Hello, #{current_user.name}"
  end
end

Note: auth_token and authenticate are mutually exclusive. Setting both raises Flehmen::ConfigurationError.

Note: The STDIO transport (bin/flehmen) skips authentication regardless of this setting, as it is inherently local.

Default sensitive fields

%i[
  password_digest encrypted_password token secret
  api_key api_secret access_token refresh_token
  otp_secret reset_password_token confirmation_token
  unlock_token remember_token authentication_token
]

Example

Flehmen.configure do |config|
  config.exclude_models = [AdminUser, "InternalLog"]
  config.sensitive_fields += [:ssn, :credit_card_number]
  config.model_sensitive_fields = {
    "User" => [:phone_number, :address]
  }
  config.max_results = 50
end

Tools

flehmen_list_models

Lists all discovered models.

Arguments: none

Returns:

[
  {
    "name": "User",
    "table_name": "users",
    "column_count": 15,
    "association_count": 8,
    "enum_count": 2
  }
]

flehmen_describe_model

Returns schema details (columns, associations, enums) for a model.

Arguments:
  model_name (required) - e.g. "User"

flehmen_find_record

Finds a single record by primary key.

Arguments:
  model_name (required)
  id         (required)

flehmen_search_records

Searches records with structured conditions.

Arguments:
  model_name (required)
  conditions (optional) - JSON string
  order_by   (optional) - Column name to sort by
  order_dir  (optional) - "asc" or "desc" (default: "asc")
  limit      (optional)
  offset     (optional)

Conditions format:

[
  {"field": "status", "operator": "eq", "value": "active"},
  {"field": "created_at", "operator": "gte", "value": "2025-01-01"}
]

Supported operators: eq, not_eq, gt, gte, lt, lte, like, not_like, in, not_in, null, not_null

flehmen_count_records

Counts records matching conditions.

Arguments:
  model_name (required)
  conditions (optional) - Same format as search_records

flehmen_show_associations

Fetches associated records for a given record.

Arguments:
  model_name       (required)
  id               (required)
  association_name (required) - e.g. "posts", "company"
  limit            (optional) - For has_many associations
  offset           (optional)

Resources

flehmen://schema/overview

Returns a JSON overview of all models including columns, associations, and enums.

Architecture

Flehmen.catloaf(app)
  └── FastMcp.mount_in_rails (Rack middleware)
        ├── GET  /mcp/sse       → SSE connection (keep-alive)
        └── POST /mcp/messages  → JSON-RPC message handling
  • ModelRegistry - Auto-discovers models on first access (lazy loading)
  • FieldFilter - Masks sensitive fields with [FILTERED]
  • QueryBuilder - Builds Arel-based queries from structured conditions (SQL injection safe)
  • Serializer - Converts records to filtered hashes

Dependencies

  • Ruby >= 3.1.0
  • fast-mcp ~> 1.5
  • activerecord ~> 7.0
  • activesupport ~> 7.0
  • railties ~> 7.0

License

MIT