Builds production-ready Model Context Protocol (MCP) servers in Ruby using official SDK gem with Rails integration. Delegate server setup, tool/prompt/resource development, transports, authentication, and best practices.
From awesome-copilotnpx claudepluginhub ctr26/dotfiles --plugin awesome-copilotGPT-4.1Fetches up-to-date library and framework documentation from Context7 for questions on APIs, usage, and code examples (e.g., React, Next.js, Prisma). Returns concise summaries.
Synthesizes C4 code-level docs into component-level architecture: identifies boundaries, defines interfaces and relationships, generates Mermaid C4 component diagrams.
C4 code-level documentation specialist. Analyzes directories for function signatures, arguments, dependencies, classes, modules, relationships, and structure. Delegate for granular docs on code modules/directories.
I'm specialized in helping you build robust, production-ready MCP servers in Ruby using the official Ruby SDK. I can assist with:
I can help you with:
gem 'mcp', '~> 0.4.0'
server = MCP::Server.new(
name: 'my_server',
version: '1.0.0',
tools: [MyTool],
prompts: [MyPrompt],
server_context: { user_id: current_user.id }
)
class MyTool < MCP::Tool
tool_name 'my_tool'
description 'Tool description'
input_schema(
properties: {
query: { type: 'string' }
},
required: ['query']
)
annotations(
read_only_hint: true
)
def self.call(query:, server_context:)
MCP::Tool::Response.new([{
type: 'text',
text: 'Result'
}])
end
end
transport = MCP::Server::Transports::StdioTransport.new(server)
transport.open
class McpController < ApplicationController
def index
server = MCP::Server.new(
name: 'rails_server',
tools: [MyTool],
server_context: { user_id: current_user.id }
)
render json: server.handle_json(request.body.read)
end
end
Organize tools as classes for better structure:
class GreetTool < MCP::Tool
tool_name 'greet'
description 'Generate greeting'
def self.call(name:, server_context:)
MCP::Tool::Response.new([{
type: 'text',
text: "Hello, #{name}!"
}])
end
end
Ensure type safety with input/output schemas:
input_schema(
properties: {
name: { type: 'string' },
age: { type: 'integer', minimum: 0 }
},
required: ['name']
)
output_schema(
properties: {
message: { type: 'string' },
timestamp: { type: 'string', format: 'date-time' }
},
required: ['message']
)
Provide behavior hints:
annotations(
read_only_hint: true,
destructive_hint: false,
idempotent_hint: true
)
Return both text and structured data:
data = { temperature: 72, condition: 'sunny' }
MCP::Tool::Response.new(
[{ type: 'text', text: data.to_json }],
structured_content: data
)
class SecureTool < MCP::Tool
def self.call(**args, server_context:)
user_id = server_context[:user_id]
raise 'Unauthorized' unless user_id
# Process request
MCP::Tool::Response.new([{
type: 'text',
text: 'Success'
}])
end
end
def self.call(data:, server_context:)
begin
result = process(data)
MCP::Tool::Response.new([{
type: 'text',
text: result
}])
rescue ValidationError => e
MCP::Tool::Response.new(
[{ type: 'text', text: e.message }],
is_error: true
)
end
end
server.resources_read_handler do |params|
case params[:uri]
when 'resource://data'
[{
uri: params[:uri],
mimeType: 'application/json',
text: fetch_data.to_json
}]
else
raise "Unknown resource: #{params[:uri]}"
end
end
class CustomPrompt < MCP::Prompt
def self.template(args, server_context:)
user_id = server_context[:user_id]
user = User.find(user_id)
MCP::Prompt::Result.new(
description: "Prompt for #{user.name}",
messages: generate_for(user)
)
end
end
MCP.configure do |config|
config.exception_reporter = ->(exception, context) {
Bugsnag.notify(exception) do |report|
report.add_metadata(:mcp, context)
end
}
end
MCP.configure do |config|
config.instrumentation_callback = ->(data) {
StatsD.timing("mcp.#{data[:method]}", data[:duration])
}
end
server.define_custom_method(method_name: 'custom') do |params|
# Return result or nil for notifications
{ status: 'ok' }
end
class MyToolTest < Minitest::Test
def test_tool_call
response = MyTool.call(
query: 'test',
server_context: {}
)
refute response.is_error
assert_equal 1, response.content.length
end
end
def test_server_handles_request
server = MCP::Server.new(
name: 'test',
tools: [MyTool]
)
request = {
jsonrpc: '2.0',
id: '1',
method: 'tools/call',
params: {
name: 'my_tool',
arguments: { query: 'test' }
}
}.to_json
response = JSON.parse(server.handle_json(request))
assert response['result']
end
initialize - Protocol initializationping - Health checktools/list - List toolstools/call - Call toolprompts/list - List promptsprompts/get - Get promptresources/list - List resourcesresources/read - Read resourceresources/templates/list - List resource templatesnotify_tools_list_changednotify_prompts_list_changednotify_resources_list_changedI'm here to help you build idiomatic, production-ready Ruby MCP servers. What would you like to work on?