The project is in a healthy, maintained state
Enables FastMcp RackTransport to authenticate users via JWT tokens passed through Authorization headers with configurable callbacks for token decoding and user lookup
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

~> 2.0
~> 5.16
~> 1.21

Runtime

>= 7.0
 Project Readme

FastMcp JWT Auth

JWT Authorization header authentication extension for FastMcp RackTransport.

This gem extends the FastMcp gem to enable JWT-based user authentication via Authorization headers in Rails applications. It provides configurable callbacks for token decoding, user lookup, and validation.

Problem

FastMcp::Transports::RackTransport doesn't have built-in JWT authentication support. For integrating with external MCP clients that use JWT tokens for authentication, you need a way to:

  1. Extract JWT tokens from Authorization headers
  2. Decode and validate the tokens
  3. Find users based on token payload
  4. Set Current.user for the request duration

Solution

This gem provides a monkey patch for FastMcp::Transports::RackTransport that:

  1. Extracts JWT tokens from Authorization: Bearer headers
  2. Decodes tokens using configurable callbacks
  3. Validates token expiration and other claims
  4. Finds users using configurable lookup logic
  5. Sets Current.user for request duration
  6. Cleans up Current after request processing

Installation

Prerequisites: This gem requires the fast-mcp gem to be installed first.

Add both gems to your application's Gemfile:

gem 'fast-mcp'                                    # Required base gem
gem 'fast_mcp_jwt_auth', github: 'jchsoft/fast_mcp_jwt_auth'  # This extension

And then execute:

bundle install

Note: The fast-mcp gem provides the core MCP (Model Context Protocol) server functionality, while this gem extends it with JWT authentication support.

Usage

Automatic Integration

No configuration needed for basic usage! Just add the gem to your Gemfile and configure the callbacks.

The gem will:

  • Automatically patch FastMcp::Transports::RackTransport during Rails initialization
  • Extract JWT tokens from Authorization: Bearer headers automatically
  • Use Rails.logger for logging (no configuration required)
  • Handle errors gracefully with fallback to normal request processing

MCP Server Configuration

⚠️ IMPORTANT: This gem enables JWT authentication for your Rails application when used with the fast_mcp gem. For MCP clients to authenticate with your Rails app, they need to send JWT tokens in the Authorization: Bearer header.

Client-Side MCP Configuration

When your Rails app is running as an MCP server (using fast_mcp gem and fast_mcp_jwt_auth gem), MCP clients need to be configured with proper authentication headers to connect to it.

For example create or update your .mcp.json configuration file:

cp .mcp.json.example .mcp.json

Critical: The headers section with Authorization: Bearer is essential for JWT authentication:

{
  "mcpServers": {
    "your-rails-app": {
      "type": "sse",
      "name": "Your Rails MCP Server",
      "url": "https://your-rails-app.com/mcp/sse",
      "headers": {
        "Authorization": "Bearer ${JWT_TOKEN}"
      }
    }
  }
}

Real Example - WorkVector Integration

{
  "mcpServers": {
    "workvector-production": {
      "type": "sse",
      "name": "WorkVector Production", 
      "url": "https://workvector.com/mcp/sse",
      "headers": {
        "Authorization": "Bearer ${WORKVECTOR_TOKEN}"
      }
    }
  }
}

Why Headers are Critical

This WON'T work - missing authentication:

{
  "mcpServers": {
    "your-app": {
      "type": "sse",
      "url": "https://your-app.com/mcp/sse"
    }
  }
}

This WILL work - includes JWT authentication header:

{
  "mcpServers": {
    "your-app": {
      "type": "sse", 
      "url": "https://your-app.com/mcp/sse",
      "headers": {
        "Authorization": "Bearer ${JWT_TOKEN}"
      }
    }
  }
}

Environment Variables

Use environment variables for sensitive tokens in your .mcp.json:

  • ${WORKVECTOR_TOKEN} - Your WorkVector authentication token
  • ${MCP_JWT_TOKEN} - JWT token for other MCP servers
  • ${PWD} - Current working directory path

Set these in your environment or .env file:

export WORKVECTOR_TOKEN="your_workvector_token_here"
export MCP_JWT_TOKEN="your_jwt_token_here"

Security Best Practices

  • Never commit .mcp.json to version control (it's in .gitignore)
  • Use environment variables for tokens instead of hardcoding them
  • Keep tokens secure and rotate them regularly
  • Use the example file as a template for new environments

Configuration

Create an initializer to configure JWT decoding and user lookup:

# config/initializers/fast_mcp_jwt_auth.rb
FastMcpJwtAuth.configure do |config|
  config.enabled = true
  
  # JWT token decoding callback
  config.jwt_decoder = ->(jwt_token) do
    JWT.decode(jwt_token, Rails.application.credentials.secret_key_base, true, algorithm: 'HS256')[0]
  end
  
  # User lookup callback
  config.user_finder = ->(decoded_token) do
    User.find_by(authentication_token: decoded_token['authentication_token'])
  end
  
  # Optional: Token validation callback (defaults to expiration check)
  config.token_validator = ->(decoded_token) do
    decoded_token['exp'].nil? || decoded_token['exp'] >= Time.current.to_i
  end
  
  # Optional: Custom current user setter (defaults to Current.user=)
  config.current_user_setter = ->(user) do
    Current.user = user
  end
  
  # Optional: Custom context resetter (defaults to Current.reset)
  config.current_resetter = -> do
    Current.reset
  end
end

WorkVector Integration Example

For WorkVector-style JWT integration using JwtIdClaim:

# config/initializers/fast_mcp_jwt_auth.rb
FastMcpJwtAuth.configure do |config|
  config.enabled = true
  
  # Use JwtIdClaim for token decoding (WorkVector pattern)
  config.jwt_decoder = ->(jwt_token) do
    JwtIdClaim.decode(jwt_token)
  end
  
  # Find user by authentication_token from JWT payload
  config.user_finder = ->(decoded_token) do
    User.find_by(authentication_token: decoded_token[:authentication_token])
  end
end

Configuration Callbacks

The gem provides these configurable callbacks:

  • jwt_decoder: Callback for JWT token decoding (required)
  • user_finder: Callback for user lookup from decoded token (required)
  • token_validator: Callback for token validation (optional, defaults to expiration check)
  • current_user_setter: Callback for setting current user (optional, defaults to Current.user=)
  • current_resetter: Callback for resetting current context (optional, defaults to Current.reset)

How It Works

  1. Request Processing: When FastMcp processes an MCP request, the patch intercepts it
  2. Header Extraction: Looks for Authorization: Bearer <token> header
  3. Token Decoding: Uses configured jwt_decoder callback to decode the JWT
  4. Token Validation: Validates token using token_validator callback
  5. User Lookup: Finds user using user_finder callback
  6. Context Setting: Sets current user using current_user_setter callback
  7. Request Processing: Continues with normal MCP request processing
  8. Cleanup: Resets current context using current_resetter callback

Error Handling

The gem handles errors gracefully:

  • Invalid JWT tokens are logged as warnings but don't break request processing
  • Missing or malformed Authorization headers are ignored silently
  • Decoding errors fall back to normal request processing without authentication
  • User lookup failures result in no authentication but normal request processing

Requirements

  • Ruby >= 3.1.0
  • Rails >= 7.0
  • FastMcp gem

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install.

Testing

rake test
rubocop

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/jchsoft/fast_mcp_jwt_auth.

License

The gem is available as open source under the terms of the MIT License.