Redis Storage - nagstler/mcp_on_ruby GitHub Wiki

Rails Integration with Redis Storage

This guide shows how to integrate Ruby MCP with Redis as a storage backend in a Rails application.

Prerequisites

  • A Rails application
  • Redis server installed and running
  • Ruby MCP gem added to your project

Installation

Add the Ruby MCP gem to your Rails application's Gemfile:

gem 'mcp_on_ruby'

Install the gem:

bundle install

Configuration

Create an Initializer

Create a file at config/initializers/ruby_mcp.rb:

require 'ruby_mcp'

RubyMCP.configure do |config|
  config.storage = :redis
  config.redis = {
    url: ENV.fetch('REDIS_URL', 'redis://localhost:6379/0'),
    namespace: "app_mcp_#{Rails.env}",
    ttl: 86400  # 1 day in seconds
  }
end

# Make the client available globally
Rails.application.config.mcp_client = RubyMCP.client

Configuration Options

The Redis configuration supports these options:

Option Description Default
url Redis connection URL redis://localhost:6379/0
namespace Prefix for all Redis keys ruby_mcp
ttl Time-to-live in seconds 86400 (1 day)
host Redis server hostname localhost
port Redis server port 6379
db Redis database number 0
password Redis server password nil

Usage in Controllers

Example Controller

Here's a complete example controller that demonstrates all common operations:

class McpTestController < ApplicationController
  def create_context
    client = Rails.application.config.mcp_client

    # Create a new context
    context_id = "ctx_#{Time.now.to_i}"
    context = {
      "id" => context_id,
      "name" => "Test Context",
      "metadata" => { "created_at" => Time.now.iso8601 }
    }

    client.storage.create_context(context)

    # Add a test message
    message = {
      "id" => "msg_#{Time.now.to_i}",
      "role" => "user",
      "content" => "This is a test message",
      "metadata" => { "timestamp" => Time.now.iso8601 }
    }

    client.storage.add_message(context_id, message)

    # Add some content
    content_id = "cont_#{Time.now.to_i}"
    content_data = "This is some test content"

    client.storage.add_content(context_id, content_id, content_data)

    render json: {
      status: "success",
      context_id: context_id,
      content_id: content_id,
      message: "Context, message, and content created successfully"
    }
  end

  def get_context
    client = Rails.application.config.mcp_client
    context_id = params[:id]

    context = client.storage.get_context(context_id)

    if context
      render json: {
        status: "success",
        context: context
      }
    else
      render json: {
        status: "error",
        message: "Context not found"
      }, status: 404
    end
  end

  def list_contexts
    client = Rails.application.config.mcp_client

    contexts = client.storage.list_contexts(
      limit: params[:limit]&.to_i || 10,
      offset: params[:offset]&.to_i || 0
    )

    render json: {
      status: "success",
      count: contexts.size,
      contexts: contexts
    }
  end

  def get_content
    client = Rails.application.config.mcp_client
    context_id = params[:context_id]
    content_id = params[:content_id]

    content = client.storage.get_content(context_id, content_id)

    if content
      render json: {
        status: "success",
        content: content
      }
    else
      render json: {
        status: "error",
        message: "Content not found"
      }, status: 404
    end
  end
end

Example Routes

Add these routes to your config/routes.rb file:

Rails.application.routes.draw do
  post '/mcp_test/create_context', to: 'mcp_test#create_context'
  get '/mcp_test/context/:id', to: 'mcp_test#get_context'
  get '/mcp_test/contexts', to: 'mcp_test#list_contexts'
  get '/mcp_test/content/:context_id/:content_id', to: 'mcp_test#get_content'
end

Testing with cURL

Test your implementation with these cURL commands:

# Create a context (with message and content)
curl -X POST http://localhost:3000/mcp_test/create_context

# Get a context (use the context_id from the previous response)
curl http://localhost:3000/mcp_test/context/ctx_1234567890

# List all contexts
curl http://localhost:3000/mcp_test/contexts

# Get content
curl http://localhost:3000/mcp_test/content/ctx_1234567890/cont_1234567890

Verifying Redis Storage

You can verify that data is being stored correctly in Redis:

redis-cli
> keys app_mcp_development:*

You should see keys like:

1) "app_mcp_development:context:ctx_1234567890"
2) "app_mcp_development:context:ctx_1234567890:messages"
3) "app_mcp_development:context:ctx_1234567890:content:cont_1234567890"
4) "app_mcp_development:contexts:index"

Data Storage Schema

The Redis storage implementation uses the following key structure:

  • {namespace}:context:{context_id} - JSON-encoded context data
  • {namespace}:context:{context_id}:messages - List of JSON-encoded messages
  • {namespace}:context:{context_id}:content:{content_id} - Content data
  • {namespace}:contexts:index - Sorted set of context IDs with creation timestamps

Troubleshooting

Redis Connection Issues

If you encounter Redis connection problems:

  1. Verify Redis is running: redis-cli ping should return PONG
  2. Check your Redis URL for typos
  3. Verify network connectivity to your Redis server

Missing Data

If data appears to be missing:

  1. Check that the namespace is correct
  2. Verify TTL settings aren't too short
  3. Check Redis directly to see if the keys exist:
redis-cli
> keys app_mcp_development:*

Production Considerations

For production environments:

  1. Use a dedicated Redis instance or service
  2. Configure appropriate TTL values based on your data retention needs
  3. Use a password-protected Redis instance
  4. Consider Redis persistence options (RDB or AOF)
  5. Implement proper monitoring and backups

Environment-Specific Configuration

For different environments, use environment variables:

RubyMCP.configure do |config|
  config.storage = :redis
  config.redis = {
    url: ENV.fetch('REDIS_URL', 'redis://localhost:6379/0'),
    namespace: "app_mcp_#{Rails.env}",
    ttl: ENV.fetch('RUBY_MCP_REDIS_TTL', 86400).to_i
  }
end

This approach allows for different Redis configurations in development, test, and production environments.