Fast MCP
About
A Ruby implementation of the Model Context Protocol (MCP) server for integrating AI models into Ruby applications.
Details
- Author
- yjacquin
- Categories
- Developer Tools, AI
Jump to
Setup
Install Fast MCP in your MCP client (Claude Desktop, Cursor, Windsurf, and others).
Repository: https://github.com/yjacquin/fast-mcp
Follow the installation instructions in the repository README, then restart your MCP client.
Connect AI models to your Ruby applications with ease
No complex protocols, no integration headaches, no compatibility issues – just beautiful, expressive Ruby code.
🌟 Interface your Servers with LLMs in minutes
AI models are powerful, but they need to interact with your applications to be truly useful. Traditional approaches mean wrestling with:
- 🔄 Complex communication protocols and custom JSON formats
- 🔌 Integration challenges with different model providers
- 🧩 Compatibility issues between your app and AI tools
- 🧠 Managing the state between AI interactions and your data
Fast MCP solves all these problems by providing a clean, Ruby-focused implementation of theModel Context Protocol, making AI integration a joy, not a chore.
# Define tools for AI models to use server = FastMcp::Server.new(name: 'popular-users', version: '1.0.0') # Define a tool by inheriting from FastMcp::Tool class CreateUserTool < FastMcp::Tool description "Create a user" # These arguments will generate the needed JSON to be presented to the MCP Client # And they will be validated at run time. # The validation is based off Dry-Schema, with the addition of the description. arguments do required(:first_name).filled(:string).description("First name of the user") optional(:age).filled(:integer).description("Age of the user") required(:address).description("The shipping address").hash do required(:street).filled(:string).description("Street address") optional(:city).filled(:string).description("City name") optional(:zipcode).maybe(:string).description("Postal code") end end def call(first_name:, age: nil, address: {}) User.create!(first_name:, age:, address:) end end # Register the tool with the server server.register_tool(CreateUserTool) # Share data resources with AI models by inheriting from FastMcp::Resource class PopularUsers < FastMcp::Resource uri "myapp:///users/popular" resource_name "Popular Users" mime_type "application/json" def content JSON.generate(User.popular.limit(5).as_json) end end class User < FastMcp::Resource uri "myapp:///users/{id}" # This is a resource template resource_name "user" mime_type "application/json" def content id = params[:id] # params are computed from the uri pattern JSON.generate(User.find(id).as_json) end end # Register the resource with the server server.register_resources(PopularUsers, User) # Accessing the resource through the server server.read_resource(PopularUsers.uri) # Notify the resource content has been updated to clients server.notify_resource_updated(PopularUsers.variabilized_uri) # Notifiy the content of a resource from a template has been updated to clients server.notify_resource_updated(User.variabilized_uri(id: 1))
Control which tools and resources are available based on request context:
# Tag your tools for easy filtering class AdminTool < FastMcp::Tool tags :admin, :dangerous description "Perform admin operations" def call # Admin only functionality end end # Filter tools based on user permissions server.filter_tools do |request, tools| user_role = request.params['role'] case user_role when 'admin' tools # Admins see all tools when 'user' tools.reject { |t| t.tags.include?(:admin) } else tools.select { |t| t.tags.include?(:public) } end end
bundle add fast-mcp bin/rails generate fast_mcp:install
This will add a configurablefast_mcp.rbinitializer
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', 'example.com', /.\.example\.com/], # localhost_only: true, # 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
- add app/resources folder
- add app/tools folder
- add app/tools/sample_tool.rb
- add app/resources/sample_resource.rb
- add ApplicationTool to inherit from
- add ApplicationResource to inherit from as well
For Rails applications, FastMCP provides Rails-style class names to better fit with Rails conventions:
- ActionTool::Base- An alias forFastMcp::Tool
- ActionResource::Base- An alias forFastMcp::Resource
These are automatically set up in Rails applications. You can use either naming convention in your code:
# Using Rails-style naming: class MyTool < ActionTool::Base description "My awesome tool" arguments do required(:input).filled(:string) end def call(input:) # Your implementation end end # Using standard FastMcp naming: class AnotherTool < FastMcp::Tool # Both styles work interchangeably in Rails apps end
When creating new tools or resources, the generators will use the Rails naming convention by default:
# app/tools/application_tool.rb class ApplicationTool < ActionTool::Base # Base methods for all tools end # app/resources/application_resource.rb class ApplicationResource < ActionResource::Base # Base methods for all resources end
I'll let you check out the dedicatedsinatra integration docs.
Create a Server with Tools and Resources and STDIO transport
require 'fast_mcp' # Create an MCP server server = FastMcp::Server.new(name: 'my-ai-server', version: '1.0.0') # Define a tool by inheriting from FastMcp::Tool class SummarizeTool < FastMcp::Tool description "Summarize a given text" arguments do required(:text).filled(:string).description("Text to summarize") optional(:max_length).filled(:integer).description("Maximum length of summary") end def call(text:, max_length: 100) # Your summarization logic here text.split('.').first(3).join('.') + '...' end end # Register the tool with the server server.register_tool(SummarizeTool) # Create a resource by inheriting from FastMcp::Resource class StatisticsResource < FastMcp::Resource uri "data/statistics" resource_name "Usage Statistics" description "Current system statistics" mime_type "application/json" def content JSON.generate({ users_online: 120, queries_per_minute: 250, popular_topics: ["Ruby", "AI", "WebDev"] }) end end # Register the resource with the server server.register_resource(StatisticsResource) # Start the server server.start
MCP has developed a very[useful inspector. You can use it to validate your implementation. I suggest you use the examples I provided with this project as an easy boilerplate. Clone this project, then give it a go !
npx @modelcontextprotocol/inspector examples/server_with_stdio_transport.rb
Or to test with an SSE transport using a rack middleware:
npx @modelcontextprotocol/inspector examples/rack_middleware.rb
Or to test over SSE with an authenticated rack middleware:
npx @modelcontextprotocol/inspector examples/authenticated_rack_middleware.rb
You can test your custom implementation with the official MCP inspector by using:
…
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.




