使用 ruby-mcp-development 插件在 Ruby 中构建生产级 MCP 服务器:从项目生成到 Rails 集成全指南
【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot
Model Context Protocol(MCP)是连接 AI 应用与外部工具、数据源的开放协议。awesome-copilot 仓库中的ruby-mcp-development插件,为在 Ruby 生态中基于官方 MCP Ruby SDK gem 构建 MCP 服务器提供了一站式工具链:一条斜杠命令负责生成完整可运行的项目骨架,一个专属 Agent(ruby-mcp-expert)负责提供专家级开发指导,并配套一份作用于*.rb、Gemfile、Rakefile的编码规范文档。读完本文,你将掌握从零生成 MCP 服务器、实现 Tools/Prompts/Resources、接入 stdio 与 Rails HTTP 传输、编写测试并接入 Claude Desktop 的完整实战路径。
插件概览:一个命令、一个 Agent、一套规范
ruby-mcp-development插件定义在 plugins/ruby-mcp-development/plugin.json 中,元数据信息如下:
- 名称:
ruby-mcp-development - 版本:
1.0.0 - 许可证:MIT(与仓库根目录 LICENSE 一致)
- 关键词:
ruby、mcp、model-context-protocol、server-development、sdk、rails、gem - 作者:Awesome Copilot Community
从plugin.json的extensions声明可以清晰看到,该插件由三部分构成,分别覆盖"生成、指导、规范"三个环节:
| 组成 | 仓库位置 | 作用 |
|---|---|---|
| Skill(斜杠命令) | skills/ruby-mcp-server-generator/SKILL.md | 生成完整的 Ruby MCP 服务器项目 |
| Agent | agents/ruby-mcp-expert.agent.md | 专家对话模式,提供架构、配置、排错指导 |
| Instructions | instructions/ruby-mcp-server.instructions.md | 自动作用于 Ruby 文件的编码最佳实践 |
插件核心声明(README.md)中的能力清单如下:
Commands(斜杠命令)
| Command | Description |
|---|---|
/ruby-mcp-development:ruby-mcp-server-generator | Generate a complete Model Context Protocol server project in Ruby using the official MCP Ruby SDK gem. |
Agents
| Agent | Description |
|---|---|
ruby-mcp-expert | Expert assistance for building Model Context Protocol servers in Ruby using the official MCP Ruby SDK gem with Rails integration. |
安装插件
该插件属于 awesome-copilot 社区扩展集,通过 GitHub Copilot CLI 的插件机制安装,在终端执行:
# Using Copilot CLI copilot plugin install ruby-mcp-development@awesome-copilot安装完成后,/ruby-mcp-development:ruby-mcp-server-generator斜杠命令即可用;同时在 Agent 选择器中会出现ruby-mcp-expert专家模式;后续对*.rb、Gemfile、*.gemspec、Rakefile的编辑将自动套用ruby-mcp-server.instructions.md中声明的编码约束(该约束定义在文件头部 frontmatter 的applyTo字段)。
一条命令生成完整项目骨架
调用/ruby-mcp-development:ruby-mcp-server-generator后,Skill 会按 SKILL.md 中的 Generation Instructions 执行:先询问项目名称与描述,再生成符合 Ruby 工程惯例的完整目录结构。
目录结构
my-mcp-server/ ├── Gemfile ├── Rakefile ├── lib/ │ ├── my_mcp_server.rb │ ├── my_mcp_server/ │ │ ├── server.rb │ │ ├── tools/ │ │ │ ├── greet_tool.rb │ │ │ └── calculate_tool.rb │ │ ├── prompts/ │ │ │ └── code_review_prompt.rb │ │ └── resources/ │ │ └── example_resource.rb ├── bin/ │ └── mcp-server ├── test/ │ ├── test_helper.rb │ └── tools/ │ ├── greet_tool_test.rb │ └── calculate_tool_test.rb └── README.md该结构遵循 Ruby 社区惯例:lib/存放源码并按模块命名空间/职责子目录(tools、prompts、resources)组织,bin/放可执行入口,test/与源码结构一一对应。
依赖与任务定义:Gemfile 与 Rakefile
# Gemfile source 'https://rubygems.org' gem 'mcp', '~> 0.4.0' group :development, :test do gem 'minitest', '~> 5.0' gem 'rake', '~> 13.0' gem 'rubocop', '~> 1.50' end依赖核心是官方mcpgem(约0.4.0版本线),开发与测试组配套minitest、rake、rubocop。
# Rakefile require 'rake/testtask' require 'rubocop/rake_task' Rake::TestTask.new(:test) do |t| t.libs << 'test' t.libs << 'lib' t.test_files = FileList['test/**/*_test.rb'] end RuboCop::RakeTask.new task default: %i[test rubocop]Rakefile将测试与静态检查绑定为默认任务,即bundle exec rake会先跑全部test/**/*_test.rb再执行 RuboCop。
入口文件与 Server 类
主入口 lib/my_mcp_server.rb 模板负责加载 SDK 与各组件:
# lib/my_mcp_server.rb # frozen_string_literal: true require 'mcp' require_relative 'my_mcp_server/server' require_relative 'my_mcp_server/tools/greet_tool' require_relative 'my_mcp_server/tools/calculate_tool' require_relative 'my_mcp_server/prompts/code_review_prompt' require_relative 'my_mcp_server/resources/example_resource' module MyMcpServer VERSION = '1.0.0' endServer类集中完成 MCP 实例的装配,这是整个服务的组装核心:
# lib/my_mcp_server/server.rb # frozen_string_literal: true module MyMcpServer class Server attr_reader :mcp_server def initialize(server_context: {}) @mcp_server = MCP::Server.new( name: 'my_mcp_server', version: MyMcpServer::VERSION, tools: [ Tools::GreetTool, Tools::CalculateTool ], prompts: [ Prompts::CodeReviewPrompt ], resources: [ Resources::ExampleResource.resource ], server_context: server_context ) setup_resource_handler end def handle_json(json_string) mcp_server.handle_json(json_string) end def start_stdio transport = MCP::Server::Transports::StdioTransport.new(mcp_server) transport.open end private def setup_resource_handler mcp_server.resources_read_handler do |params| Resources::ExampleResource.read(params[:uri]) end end end end从源码结构可以看出Server层承担三类职责:装配(把 tools/prompts/resources 注册进MCP::Server)、协议入口(handle_json处理 JSON-RPC 请求,供 HTTP 场景复用)、传输启动(start_stdio打开标准输入输出传输)。server_context参数则贯穿始终,为工具与提示词提供请求级上下文。
实现 Tools:schema、注解、结构化内容与错误处理
Skill 默认生成两个工具,完整展示了官方 SDK 的推荐写法。
greet:最小完整工具
# lib/my_mcp_server/tools/greet_tool.rb # frozen_string_literal: true module MyMcpServer module Tools class GreetTool < MCP::Tool tool_name 'greet' description 'Generate a greeting message' input_schema( properties: { name: { type: 'string', description: 'Name to greet' } }, required: ['name'] ) output_schema( properties: { message: { type: 'string' }, timestamp: { type: 'string', format: 'date-time' } }, required: ['message', 'timestamp'] ) annotations( read_only_hint: true, idempotent_hint: true ) def self.call(name:, server_context:) timestamp = Time.now.iso8601 message = "Hello, #{name}! Welcome to MCP." structured_data = { message: message, timestamp: timestamp } MCP::Tool::Response.new( [{ type: 'text', text: message }], structured_content: structured_data ) end end end end要点拆解:
tool_name/description:注册给客户端的工具标识与语义说明;input_schema:声明参数结构(name为必填字符串),SDK 据此做入参校验;output_schema:声明返回结构(message、timestamp,后者带format: 'date-time'),可配合output_schema.validate_result在返回前做校验(见 instructions/ruby-mcp-server.instructions.md 中的 WeatherTool 示例);annotations:read_only_hint: true、idempotent_hint: true告知客户端该工具只读且幂等,便于客户端决定缓存与并发策略;structured_content:在人类可读文本之外附带结构化数据,兼顾对话展示与程序化消费。
calculate:分支逻辑与 is_error 错误协议
# lib/my_mcp_server/tools/calculate_tool.rb # frozen_string_literal: true module MyMcpServer module Tools class CalculateTool < MCP::Tool tool_name 'calculate' description 'Perform mathematical calculations' input_schema( properties: { operation: { type: 'string', description: 'Operation to perform', enum: ['add', 'subtract', 'multiply', 'divide'] }, a: { type: 'number', description: 'First operand' }, b: { type: 'number', description: 'Second operand' } }, required: ['operation', 'a', 'b'] ) output_schema( properties: { result: { type: 'number' }, operation: { type: 'string' } }, required: ['result', 'operation'] ) annotations( read_only_hint: true, idempotent_hint: true ) def self.call(operation:, a:, b:, server_context:) result = case operation when 'add' then a + b when 'subtract' then a - b when 'multiply' then a * b when 'divide' return error_response('Division by zero') if b.zero? a / b.to_f else return error_response("Unknown operation: #{operation}") end structured_data = { result: result, operation: operation } MCP::Tool::Response.new( [{ type: 'text', text: "Result: #{result}" }], structured_content: structured_data ) end def self.error_response(message) MCP::Tool::Response.new( [{ type: 'text', text: message }], is_error: true ) end end end end关键设计:operation参数用enum约束取值范围;is_error: true是 SDK 的错误响应协议,让客户端能区分业务结果与失败;除零与未知运算均走error_response,保证工具失败时返回结构化错误而非抛出未处理异常。从 instructions/ruby-mcp-server.instructions.md 还可看到另一种风格——用server.define_tool块式注册同等功能的工具,适合轻量场景。
实现 Prompts:多轮对话模板
# lib/my_mcp_server/prompts/code_review_prompt.rb # frozen_string_literal: true module MyMcpServer module Prompts class CodeReviewPrompt < MCP::Prompt prompt_name 'code_review' description 'Generate a code review prompt' arguments [ MCP::Prompt::Argument.new( name: 'language', description: 'Programming language', required: true ), MCP::Prompt::Argument.new( name: 'focus', description: 'Review focus area (e.g., performance, security)', required: false ) ] meta( version: '1.0', category: 'development' ) def self.template(args, server_context:) language = args['language'] || 'Ruby' focus = args['focus'] || 'general quality' MCP::Prompt::Result.new( description: "Code review for #{language} with focus on #{focus}", messages: [ MCP::Prompt::Message.new( role: 'user', content: MCP::Content::Text.new( "Please review this #{language} code with focus on #{focus}." ) ), MCP::Prompt::Message.new( role: 'assistant', content: MCP::Content::Text.new( "I'll review the code focusing on #{focus}. Please share the code." ) ), MCP::Prompt::Message.new( role: 'user', content: MCP::Content::Text.new('[paste code here]') ) ] ) end end end endMCP::Prompt负责声明可复用的提示词模板:arguments定义模板参数(含必填/可选),template方法接收参数与server_context动态生成多轮Message序列。模板中的默认值兜底(|| 'Ruby'、|| 'general quality')体现了参数缺失时的健壮处理。Agent 定义(agents/ruby-mcp-expert.agent.md)还展示了进阶用法:在template中读取server_context[:user_id]后查询当前用户,动态生成个性化提示词。
实现 Resources:资源注册与读取 handler
# lib/my_mcp_server/resources/example_resource.rb # frozen_string_literal: true module MyMcpServer module Resources class ExampleResource RESOURCE_URI = 'resource://data/example' def self.resource MCP::Resource.new( uri: RESOURCE_URI, name: 'example-data', description: 'Example resource data', mime_type: 'application/json' ) end def self.read(uri) return [] unless uri == RESOURCE_URI data = { message: 'Example resource data', timestamp: Time.now.iso8601, version: MyMcpServer::VERSION } [{ uri: uri, mimeType: 'application/json', text: data.to_json }] end end end end资源模式分两步:resource方法声明资源元数据(URI、名称、MIME 类型),read方法提供实际数据;在Server中通过resources_read_handler把读取逻辑挂到 SDK 上。返回体按 MCP 规范携带uri、mimeType、text三要素。
若需要动态资源,instructions/ruby-mcp-server.instructions.md 提供了MCP::ResourceTemplate与 URI 模板(如users://{user_id}/profile)的用法,可针对每个占位符动态产出资源;分页资源则可在 read handler 中读取params[:page]实现。
启动服务器:stdio 传输与 JSON-RPC 调试
bin/mcp-server是可执行入口,负责实例化Server并打开 stdio 传输:
#!/usr/bin/env ruby # frozen_string_literal: true require_relative '../lib/my_mcp_server' begin server = MyMcpServer::Server.new server.start_stdio rescue Interrupt warn "\nShutting down server..." exit 0 rescue StandardError => e warn "Error: #{e.message}" warn e.backtrace.join("\n") exit 1 end先赋予执行权限再运行:
chmod +x bin/mcp-server bundle install bundle exec bin/mcp-server启动后可在标准输入逐行发送 JSON-RPC 请求进行冒烟测试:
{"jsonrpc":"2.0","id":"1","method":"ping"} {"jsonrpc":"2.0","id":"2","method":"tools/list"} {"jsonrpc":"2.0","id":"3","method":"tools/call","params":{"name":"greet","arguments":{"name":"Ruby"}}}从 instructions/ruby-mcp-server.instructions.md 的 Supported Methods 清单看,SDK 覆盖了initialize、ping、tools/list、tools/call、prompts/list、prompts/get、resources/list、resources/read、resources/templates/list等标准协议方法,此外还支持notify_tools_list_changed、notify_prompts_list_changed、notify_resources_list_changed三类列表变更通知。
Rails 集成:HTTP 传输与认证上下文
Skill 生成的项目默认支持两种运行形态。除 stdio 外,Server#handle_json让同一个服务器实例可以直接挂在 Rails 控制器上,这也是 Agent 声明中"Rails integration support"的核心:
# app/controllers/mcp_controller.rb class McpController < ApplicationController def index server = MyMcpServer::Server.new( server_context: { user_id: current_user.id } ) render json: server.handle_json(request.body.read) end end配合 instructions/ruby-mcp-server.instructions.md 中的 server_context 章节,server_context可以携带user_id、request_id、auth_token等请求级信息,工具内部按需取用做授权:
class AuthenticatedTool < MCP::Tool def self.call(query:, server_context:) user_id = server_context[:user_id] # Use user_id for authorization MCP::Tool::Response.new([{ type: 'text', text: 'Authorized' }]) end end若采用 SSE 推送(如列表变更通知),SDK 提供MCP::Server::Transports::StreamableHTTPTransport;在流式传输下调用server.notify_tools_list_changed即可实时通知客户端刷新工具列表(参见 instructions 的 Streamable HTTP Transport 章节)。
测试策略:minitest 全覆盖
Skill 生成两套测试,覆盖成功路径与异常路径。test_helper.rb把lib加入加载路径并引入minitest/autorun:
# test/test_helper.rb # frozen_string_literal: true $LOAD_PATH.unshift File.expand_path('../lib', __dir__) require 'my_mcp_server' require 'minitest/autorun'greet 工具的测试同时验证文本内容、结构化内容与输出 schema 字段:
# test/tools/greet_tool_test.rb # frozen_string_literal: true require 'test_helper' module MyMcpServer module Tools class GreetToolTest < Minitest::Test def test_greet_with_name response = GreetTool.call(name: 'Ruby', server_context: {}) refute response.is_error assert_equal 1, response.content.length assert_match(/Ruby/, response.content.first[:text]) assert response.structured_content assert_equal 'Hello, Ruby! Welcome to MCP.', response.structured_content[:message] end def test_output_schema_validation response = GreetTool.call(name: 'Test', server_context: {}) assert response.structured_content.key?(:message) assert response.structured_content.key?(:timestamp) end end end endcalculate 工具测试则针对四则运算、除零、未知操作符分别断言(calculate_tool_test.rb 中完整包含 6 个用例),其中test_division_by_zero与test_unknown_operation验证is_error协议与错误文案。
运行方式:
bundle exec rake test # 运行全部测试 bundle exec rake rubocop # 运行 linter bundle exec rake # 默认任务:test + rubocopAgent 定义还提供了集成测试范式:构造 JSON-RPC 请求 JSON,经server.handle_json处理后用JSON.parse断言response['result'],可直接验证协议层的完整链路。
接入 Claude Desktop
生成的项目 README 模板给出了桌面客户端接入配置,将claude_desktop_config.json指向项目:
{ "mcpServers": { "my-mcp-server": { "command": "bundle", "args": ["exec", "bin/mcp-server"], "cwd": "/path/to/my-mcp-server" } } }运行环境要求Ruby 3.0 或更高版本(README 模板 Requirements 章节明确声明),配置后 Claude Desktop 即可通过 stdio 拉起该 MCP 服务器并发现其工具、提示词与资源。
生产级配置:异常上报、埋点、协议版本与自定义方法
Agent 与 instructions 共同给出 SDK 的运行时配置面(MCP.configure全局配置):
# 异常上报:接入 Bugsnag / Sentry 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]) } endinstructions 明确列出了 instrumentation 回调携带的数据字段:method(如tools/call)、tool_name、prompt_name、resource_uri、error(查找失败时的错误码)、duration(秒)。Rails 场景下可直接写入Rails.logger或用 StatsD 聚合。
协议版本与自定义 JSON-RPC 方法:
# 覆盖协议版本 configuration = MCP::Configuration.new(protocol_version: '2025-06-18') server = MCP::Server.new(name: 'my_server', configuration: configuration) # 自定义方法(返回结果即为响应;返回 nil 表示通知) server.define_custom_method(method_name: 'add') do |params| params[:a] + params[:b] end server.define_custom_method(method_name: 'notify') do |params| puts "Notification: #{params[:message]}" nil end客户端侧用法
instructions 同样覆盖了 MCP 客户端构建(配合faraday),便于自测或服务间调用:
require 'mcp' require 'faraday' http_transport = MCP::Client::HTTP.new( url: 'https://api.example.com/mcp', headers: { 'Authorization' => "Bearer #{token}" } ) client = MCP::Client.new(transport: http_transport) # 列出工具 tools = client.tools tools.each do |tool| puts "Tool: #{tool.name}" puts "Description: #{tool.description}" end # 调用工具 response = client.call_tool( tool: tools.first, arguments: { message: 'Hello, world!' } )最佳实践清单
综合 SKILL.md 的 Generation Instructions、instructions/ruby-mcp-server.instructions.md 的 Best Practices 章节与 Agent 建议,整理出构建生产级 Ruby MCP 服务器的十条准则:
- 复杂工具用类实现(继承
MCP::Tool),结构清晰、可测试性强;简单工具可用define_tool块式注册; - 为每个工具定义 input/output schema,保证类型安全与入参校验;
- 添加 annotations(
read_only_hint、destructive_hint、idempotent_hint、open_world_hint),帮助客户端理解工具行为; - 响应中携带 structured_content,同时提供文本与结构化数据;
- 善用 server_context传递认证与请求上下文,实现授权工具与个性化提示词;
- 配置 exception_reporter,生产环境异常可观测;
- 实现 instrumentation_callback,跟踪协议方法级性能指标;
- 列表变更时发送通知(
notify_*_list_changed),保持客户端同步; - 用
is_error: true规范化业务错误,配合 rescue 与exception_reporter区分"业务失败"与"系统异常"; - 遵循 Ruby 惯例:
snake_case命名、模块化组织、# frozen_string_literal: true注释、合理缩进。
小结
ruby-mcp-development插件的价值在于把"从零构建 Ruby MCP 服务器"压缩为一条命令:/ruby-mcp-development:ruby-mcp-server-generator产出可运行的工程骨架,ruby-mcp-expertAgent 提供从架构设计到性能优化的专家咨询,applyTo声明使编码规范在编辑时自动生效。结合官方mcpgem 的 class 化组织方式与 stdio/HTTP 双传输能力,开发者可以在 CLI 工具、Rails Web 服务甚至 SSE 流式场景中快速落地符合协议规范的 MCP 服务端实现。
【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考