Skip to content

Instantly share code, notes, and snippets.

@technicalpickles
Created June 24, 2025 14:00
Show Gist options
  • Save technicalpickles/73a74e4f9e75cd9184ce49bb33312dcf to your computer and use it in GitHub Desktop.
Save technicalpickles/73a74e4f9e75cd9184ce49bb33312dcf to your computer and use it in GitHub Desktop.
require "thor"
require "fast_mcp"
require "debug"
class Thorsty < Thor
def self.arguments(&block)
end
def exit_on_failure?
true
end
end
class MyCLI < Thorsty
desc "hello NAME", "say hello to NAME"
def hello(name, from=nil)
puts "from: #{from}" if from
puts "Hello #{name}"
end
module Tools
end
end
def capture_output(&block)
stdout, stderr = StringIO.new, StringIO.new
$stdout, $stderr = stdout, stderr
block.call
# restore normal output
$stdout, $stderr = STDOUT, STDERR
[stdout.string, stderr.string]
end
def command_to_tool(command)
tool_class = Class.new(FastMcp::Tool) do
tool_name command.name
description command.description
def call
stdout, _ = capture_output { command.run }
stdout
end
end
tool_class
end
# Create a simple Rack application
app = lambda do |_env|
[200, { 'Content-Type' => 'text/html' },
['<html><body><h1>Hello from Rack!</h1><p>This is a simple Rack app with MCP middleware.</p></body></html>']]
end
debugger
# Create the MCP middleware
mcp_app = FastMcp.rack_middleware(
app,
name: 'thorsty', version: '1.0.0',
logger: Logger.new($stdout)
) do |server|
MyCLI.commands.each do |name, command|
puts "Command: #{name}"
puts "Description: #{command.description}"
command.arguments.each do |arg|
puts " Argument: #{arg.name} (required: #{arg.required}, type: #{arg.type})"
end
tool = command_to_tool(MyCLI, command)
server.register_tool(tool)
end
end
# Run the Rack application with Puma
puts 'Starting Rack application with MCP middleware on http://localhost:9292'
puts 'MCP endpoints:'
puts ' - http://localhost:9292/mcp/sse (SSE endpoint)'
puts ' - http://localhost:9292/mcp/messages (JSON-RPC endpoint)'
puts 'Press Ctrl+C to stop'
# Use the Puma server directly instead of going through Rack::Handler
require 'puma'
require 'puma/configuration'
require 'puma/launcher'
app = Rack::Builder.new { run mcp_app }
config = Puma::Configuration.new do |user_config|
user_config.bind 'tcp://localhost:9292'
user_config.app app
end
launcher = Puma::Launcher.new(config)
launcher.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment