Model Context Protocol

Episode #521 by Teacher's Avatar David Kimura

Summary

Model Context Protocol (MCP) is an API interface for your applications that are formatted in a way that machine learning platforms can interact with them. They can be used to generate AI insights, perform tasks based on user input or other things.
rails ai machine learning api 12:16

Chapters

  • Introduction (0:00)
  • Setting up FastMCP (3:57)
  • Creating a User model (4:22)
  • Exploring the generated files (4:37)
  • Setting up the MCP for external calls (6:10)
  • Setting up Claude (7:35)
  • Creating and interacting with data (8:23)
  • Creating additional tools (9:09)
  • Interacting with the new tool (10:14)
  • Warning about hallucinations (10:46)
  • Final Thoughts (11:44)

Resources

Download Source Code

Summary

# Terminal
bundle add fast-mcp
bin/rails g fast_mcp:install
rails g model user name email age:integer
npx @modelcontextprotocol/inspector

# app/resources/application_resource.rb
# frozen_string_literal: true

class ApplicationResource < ActionResource::Base
  # write your custom logic to be shared across all resources here
end

# app/resources/sample_resource.rb
# frozen_string_literal: true

class SampleResource < ApplicationResource
  uri "examples/users"
  resource_name "Users"
  description "A user resource for demonstration"
  mime_type "application/json"

  def content
    JSON.generate(User.all.as_json)
  end
end

# app/tools/application_tool.rb
# frozen_string_literal: true

class ApplicationTool < ActionTool::Base
  # write your custom logic to be shared across all tools here
end

# app/tools/sample_tool.rb
# frozen_string_literal: true

class SampleTool < ApplicationTool
  description "Greet a user"

  arguments do
    required(:id).filled(:integer).description("ID of the user to greet")
    optional(:prefix).filled(:string).description("Prefix to add to the greeting")
  end

  def call(id:, prefix: "Hey")
    user = User.find(id)

    "#{prefix} #{user.name} !"
  end
end

# app/tools/users_create_tool.rb
# frozen_string_literal: true

class UsersCreateTool < ApplicationTool
  description "Create a user"

  arguments do
    required(:name).filled(:string).description("Name of the user")
    required(:email).filled(:string).description("Email of the user")
    required(:age).filled(:integer).description("Age of the user")
  end

  def call(name:, email:, age:)
    user = User.create!(name: name, email: email, age: age)

    "User created: #{user.inspect}"
  end
end

# config/initializers/fast_mcp.rb
# frozen_string_literal: true

# FastMcp - Model Context Protocol for Rails
# This initializer sets up the MCP middleware in your Rails application.
#
# In Rails applications, you can use:
# - ActionTool::Base as an alias for FastMcp::Tool
# - ActionResource::Base as an alias for FastMcp::Resource
#
# All your tools should inherit from ApplicationTool which already uses ActionTool::Base,
# and all your resources should inherit from ApplicationResource which uses ActionResource::Base.

# Mount the MCP middleware in your Rails application
# You can customize the options below to fit your needs.
require "fast_mcp"

FastMcp.mount_in_rails(
  Rails.application,
  name: Rails.application.class.module_parent_name.underscore.dasherize,
  version: "1.0.0",
  path_prefix: "/mcp", # This is the default path prefix
  messages_route: "messages", # This is the default route for the messages endpoint
  sse_route: "sse", # This is the default route for the SSE endpoint
  # Add allowed origins below, it defaults to Rails.application.config.hosts
  allowed_origins: [ "localhost", "127.0.0.1", "[::1]", "b69340af24ec.ngrok-free.app", /.*\.example\.com/ ],
  localhost_only: false, # Set to false to allow connections from other hosts
  # whitelist specific ips to if you want to run on localhost and allow connections from other IPs
  # allowed_ips: ['127.0.0.1', '::1']
  # authenticate: true,       # Uncomment to enable authentication
  # auth_token: 'your-token', # Required if authenticate: true
) do |server|
  Rails.application.config.after_initialize do
    # FastMcp will automatically discover and register:
    # - All classes that inherit from ApplicationTool (which uses ActionTool::Base)
    # - All classes that inherit from ApplicationResource (which uses ActionResource::Base)
    server.register_tools(*ApplicationTool.descendants)
    server.register_resources(*ApplicationResource.descendants)
    # alternatively, you can register tools and resources manually:
    # server.register_tool(MyTool)
    # server.register_resource(MyResource)
  end
end