MCPRuby
一个易于使用且极简的 Ruby 模型上下文协议 (MCP) 服务器实现。
sergiobayona
README
MCPRuby
MCPRuby 提供了服务器端工具,用于在 Ruby 应用程序中实现 模型上下文协议 (MCP)。 MCP 是一种规范,用于定义大型语言模型 (LLM) 如何发现和与由独立应用程序(MCP 服务器)提供的外部工具、资源和提示进行交互。
该库使您可以轻松创建 MCP 服务器,将应用程序的功能(如函数、数据源或预定义的提示模板)暴露给兼容的 LLM 客户端(例如,Claude Desktop App、自定义客户端)。
特性
- MCP 规范遵循: 实现了 MCP 规范的核心服务器端方面。
- 工具: 定义和注册 LLM 可以调用的自定义工具(函数)。
- 资源: 暴露数据源(文件、数据库结果、API 输出)供 LLM 读取。
- 提示: 提供 LLM 可以请求和使用的结构化提示模板。
- 多种传输方式:
- Stdio: 使用标准输入/输出的简单传输方式,非常适合基于进程的服务器。
- SSE (服务器发送事件): 使用现代
async
/falcon
生态系统的异步网络传输方式。
- 可扩展的处理程序: 为核心 MCP 方法提供默认处理程序,可以覆盖这些处理程序。
- 清晰的错误处理: 自定义错误类,映射到 JSON-RPC/MCP 错误代码。
- Ruby 风格的 API: 使用块来注册处理程序,遵循惯用的 Ruby 模式。
安装
将此行添加到您的应用程序的 Gemfile 中:
gem 'mcp_ruby'
然后执行:
$ bundle install
或者自己安装:
$ gem install mcp_ruby
注意:SSE 传输需要额外的 gem (async
, async-http
, falcon
, rack
)。 如果您安装 mcp_ruby
,这些 gem 将自动安装。
快速入门 (Stdio 示例)
此示例创建一个通过标准输入/输出运行并提供一个简单工具的服务器。
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'mcp_ruby'
# 可选:设置日志级别 (DEBUG, INFO, WARN, ERROR, FATAL)
MCPRuby.logger.level = Logger::INFO
# 1. 创建一个服务器实例
server = MCPRuby.new_server(name: "MySimpleStdioServer", version: "1.0")
# 2. 注册一个工具
server.register_tool(
name: "simple_echo",
description: "回显提供的消息。",
# 使用 JSON Schema 格式定义预期的输入
input_schema: {
type: "object",
properties: {
message: { type: "string", description: "要回显的消息。" }
},
required: ["message"]
}
# 该块接收参数(哈希)和会话对象
) do |args, _session|
input = args["message"] || args[:message] # 处理字符串/符号键
server.logger.info "正在回显: #{input}"
# 返回值将转换为 MCP 'content' 格式
"您发送了: #{input}"
end
# 3. 使用 stdio 传输方式运行服务器
begin
server.run(transport: :stdio)
rescue Interrupt
MCPRuby.logger.info("服务器已停止。")
rescue StandardError => e
MCPRuby.logger.fatal("服务器崩溃: #{e.message}\n#{e.backtrace.join("\n")}")
exit 1
end
要运行此示例:
-
将其另存为
my_server.rb
。 -
运行
ruby my_server.rb
。 -
服务器现在正在监听 stdin/stdout。 您可以通过发送 JSON-RPC 消息(请参阅 MCP 规范)与之交互:
- 发送 Initialize:
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"ManualClient","version":"0.1"}}}
- (服务器响应)
- 发送 Initialized:
{"jsonrpc":"2.0","method":"initialized","params":{}}
- 列出工具:
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
- (服务器响应
simple_echo
工具定义) - 调用工具:
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"simple_echo","arguments":{"message":"Hello MCPRuby!"}}}
- (服务器响应回显结果)
- 发送 Initialize:
用法
创建服务器
使用工厂方法实例化服务器:
require 'mcp_ruby'
server = MCPRuby.new_server(
name: "MyAwesomeServer",
version: "2.1.0",
log_level: Logger::DEBUG # 可选:默认为 INFO
)
注册工具
工具是您的服务器公开的函数。 使用带有块的 register_tool
。
server.register_tool(
name: "calculate_sum",
description: "将两个数字相加。",
input_schema: {
type: "object",
properties: {
a: { type: "number", description: "第一个数字" },
b: { type: "number", description: "第二个数字" }
},
required: ["a", "b"]
}
) do |args, session|
# args 是一个哈希,例如 { "a" => 10, "b" => 5 }
# session 对象提供会话上下文(例如,session.initialized?)
sum = (args["a"] || 0) + (args["b"] || 0)
"总和是: #{sum}" # 返回值转换为 {type: "text", text: ...}
end
input_schema
必须是一个哈希,表示描述工具预期参数的有效 JSON Schema 对象。- 该块接收参数哈希和
MCPRuby::Session
对象。 - 块的返回值由
MCPRuby::Util.convert_to_mcp_content
自动转换为 MCPcontent
数组格式。 您可以返回:String
: 变为{ type: 'text', text: '...' }
。- 与 MCP 内容结构匹配的
Hash
({ type: 'text', ... }
,{ type: 'image', ... }
等): 按原样使用。 - 其他
Hash
对象: JSON 编码为{ type: 'text', text: '...', mimeType: 'application/json' }
。 - 二进制字符串 (
Encoding::ASCII_8BIT
): Base64 编码为{ type: 'blob', blob: '...', mimeType: 'application/octet-stream' }
。 - 上述的
Array
: 每个元素都会被转换和组合。 - 其他对象: 使用
to_s
转换为{ type: 'text', text: '...' }
。
注册资源
资源提供客户端可以读取的数据。
server.register_resource(
uri: "memory://status", # 此资源的唯一 URI
name: "服务器状态",
description: "提供当前的服务器状态。",
mime_type: "application/json" # 可选:默认为 text/plain
) do |session|
# 处理程序块接收会话对象
{
status: "OK",
uptime: Time.now - server_start_time, # 示例值
initialized: session.initialized?
} # 由于 mime_type,哈希将被 JSON 编码
end
# 返回二进制数据的资源
server.register_resource(
uri: "file://logo.png",
name: "Logo 图像",
description: "服务器的 Logo。",
mime_type: "image/png"
) do |session|
# 重要提示:将二进制数据作为带有 ASCII-8BIT 编码的字符串返回
File.binread("path/to/logo.png")
end
- 该块接收
MCPRuby::Session
对象。 - 返回
String
作为文本,或返回二进制String
(Encoding::ASCII_8BIT
) 作为二进制数据。 其他类型通常会被 JSON 编码。
注册提示
提示为客户端/LLM 提供模板。
server.register_prompt(
name: "summarize_document",
description: "创建一个用于总结文档的提示。",
# 定义客户端可以提供的参数
arguments: [
{ name: "doc_uri", description: "要总结的文档资源的 URI。", required: true },
{ name: "length", description: "所需的摘要长度(例如,“short”、“medium”、“long”)。", required: false }
]
) do |args, session|
# args 是一个哈希,例如 { "doc_uri" => "file://...", "length" => "short" }
doc_uri = args["doc_uri"]
length_hint = args["length"] ? " 保持摘要 #{args['length']}。" : ""
# 处理程序必须返回消息哈希数组
[
{
role: "user",
content: { type: "text", text: "请总结以下文档。#{length_hint}" }
},
# 您可以在此处读取资源以包含其内容,或者让客户端执行此操作
# 示例:在提示处理程序中读取资源(对于大文件,请谨慎使用)
# begin
# # 注意:read_resource 处理程序本身在服务器上下文中运行
# # 如果不小心,直接在此处访问它可能会阻塞。
# # 更好的模式可能是只引用 URI。
# resource_content = server.resources[doc_uri]&.handler&.call(session) || "[未找到文档内容]"
# {
# role: "user",
# content: { type: "text", text: "文档内容:\n#{resource_content}" }
# }
# rescue => e
# { role: "user", content: { type: "text", text: "[读取文档时出错:#{e.message}]"} }
# end
# 示例:引用资源 URI(首选)
{
role: "user",
# 这假设客户端了解如何获取和包含资源内容
content: { type: "text", text: "要总结的文档 URI:#{doc_uri}" }
}
]
end
arguments
数组描述了客户端在请求提示时可以传递的参数。- 该块接收参数哈希和会话。
- 该块必须返回一个哈希数组,其中每个哈希都符合 MCP
PromptMessage
结构 ({ role: 'user'|'assistant', content: { type: 'text'|'image'|'resource', ... } }
)。
运行服务器
使用 run
方法,指定所需的传输方式。
Stdio:
server.run(transport: :stdio)
SSE:
需要 async
、falcon
等 gem。
server.run(
transport: :sse,
options: {
host: "0.0.0.0", # 默认值: 'localhost'
port: 8080, # 默认值: 8000
path_prefix: "/my_mcp" # 默认值: '/mcp'。 端点变为 /my_mcp/sse 和 /my_mcp/message
}
)
SSE 服务器使用 Falcon 并异步运行。 使用 Ctrl+C (SIGINT) 或 SIGTERM 优雅地停止它。
自定义处理程序
您可以覆盖默认处理程序或为非标准方法添加处理程序:
# 覆盖默认 ping
server.on_request("ping") do |_params, _session, _server|
{ received_ping_at: Time.now }
end
# 处理自定义通知
server.on_notification("custom/my_event") do |params, session, server|
server.logger.info "收到 my_event: #{params.inspect}"
# 做一些事情...
end
架构
MCPRuby::Server
: 主类。 管理注册、状态并将传入消息分派到适当的处理程序。MCPRuby::Transport::{Stdio, SSE}
: 处理通过不同通道(stdin/stdout 或 HTTP SSE)进行通信的细节。 它们读取原始数据,解析 JSON,调用Server#handle_message
,并发送回格式化的 JSON-RPC 响应/错误。MCPRuby::Session
: 保存与特定客户端连接相关的状态,主要是初始化状态和协商的功能。 传递给处理程序。MCPRuby::Definitions::{Tool, Resource, Prompt}
: 简单的结构,保存注册的功能信息和处理程序块。MCPRuby::Handlers::Core
: 包含标准 MCP 方法的默认实现。MCPRuby::Errors
: 映射到 JSON-RPC 错误代码的自定义异常类。MCPRuby::Util
: 实用函数。
开发
检出 repo 后:
- 安装依赖项:
$ bundle install
- 运行测试:
$ bundle exec rspec
- 运行示例服务器:
$ bundle exec ruby examples/stdio_server.rb # 或 $ bundle exec ruby examples/simple_server.rb # 对于 SSE
您还可以运行 bin/console
以获得一个交互式提示,允许您进行实验。
要将此 gem 安装到您的本地计算机上,请运行 bundle exec rake install
。 要发布新版本,请更新 lib/mcp_ruby/version.rb
中的版本号,然后运行 bundle exec rake release
,这将为该版本创建一个 git 标签,推送 git 提交和创建的标签,并将 .gem
文件推送到 rubygems.org。
贡献
欢迎在 GitHub 上提交错误报告和拉取请求:https://github.com/sergiobayona/mcp_ruby。
许可证
该 gem 在 MIT 许可证 的条款下作为开源提供。
推荐服务器
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
MCP Package Docs Server
促进大型语言模型高效访问和获取 Go、Python 和 NPM 包的结构化文档,通过多语言支持和性能优化来增强软件开发。
Claude Code MCP
一个实现了 Claude Code 作为模型上下文协议(Model Context Protocol, MCP)服务器的方案,它可以通过标准化的 MCP 接口来使用 Claude 的软件工程能力(代码生成、编辑、审查和文件操作)。
@kazuph/mcp-taskmanager
用于任务管理的模型上下文协议服务器。它允许 Claude Desktop(或任何 MCP 客户端)在基于队列的系统中管理和执行任务。
mermaid-mcp-server
一个模型上下文协议 (MCP) 服务器,用于将 Mermaid 图表转换为 PNG 图像。
Jira-Context-MCP
MCP 服务器向 AI 编码助手(如 Cursor)提供 Jira 工单信息。

Linear MCP Server
一个模型上下文协议(Model Context Protocol)服务器,它与 Linear 的问题跟踪系统集成,允许大型语言模型(LLM)通过自然语言交互来创建、更新、搜索和评论 Linear 问题。

Sequential Thinking MCP Server
这个服务器通过将复杂问题分解为顺序步骤来促进结构化的问题解决,支持修订,并通过完整的 MCP 集成来实现多条解决方案路径。
Curri MCP Server
通过管理文本笔记、提供笔记创建工具以及使用结构化提示生成摘要,从而实现与 Curri API 的交互。