如何使用 Ruby 和 Gemini CLI 进行本地 MCP 开发

31 阅读6分钟

这年头,会用AI不算什么,要学会构建自己的MCP,才叫厉害。

Python 长期以来主导着 AI 和机器学习领域的开发。然而,模型上下文协议(MCP)的一大优势在于其实现细节与开发语言无关。并非所有项目都基于 Python,MCP 可以让开发者使用自己熟悉的语言来连接最新的 AI 能力。

本文的目标是构建一个最小可用的 Ruby MCP Stdio 服务器,并在本地通过 Gemini CLI 进行交互。

为什么选择 Ruby?

Ruby 是一种动态的、通用的编程语言,以注重简洁和开发效率著称。它是一种开源的面向对象语言,旨在提供优雅的语法,读起来自然,写起来容易。通过 MCP,Ruby 代码可以无缝对接大模型,充当连接本地数据与 AI 的桥梁。

Ruby 版本管理

Ruby 的广泛部署,会出现一些坑。在不同平台上管理语言版本以及维护受支持的版本较为困难。通常,开发者会使用 RVM 或 rbenv 这样的版本管理工具。

然而,这些工具的安装过程往往涉及 GPG 密钥验证、编译源代码等复杂步骤,对于初学者或希望快速上手的开发者来说,这往往是第一道门槛。

使用 ServBay 管理 Ruby 环境

为了跳过繁琐的编译和配置步骤,推荐使用 ServBay。ServBay 是一个集成的开发环境管理工具,它内置了 Ruby 环境

使用 ServBay,无需处理复杂的安装脚本,在「软件包」中启用> Ruby 模块即可。

在终端中验证 Ruby 环境是否就绪:

# 验证 Ruby 版本
ruby -v

这样,一个 Ruby 环境就准备好了。

Gemini CLI

Gemini CLI 是 Google 提供的命令行工具,用于与源文件交互并提供实时辅助。在 MCP 开发中,它扮演客户端的角色。

Node 版本管理

Gemini CLI 依赖于 Node.js 环境。这里还是使用ServBay来管理Node.js版本。

ServBay 支持一键部署 Node.js 环境,这使得安装基于 Node 的工具变得非常直接。我们无需额外安装 NVM。

在确保 ServBay 运行且 Node 模块已启用的情况下,安装 Gemini CLI:

npm install -g @google/gemini-cli

测试 Gemini CLI 环境

安装完成并确保拥有正确的 Node.js 版本后,可以测试 Gemini CLI 的启动。这里需要使用 API Key 或 Google 账户进行认证:

gemini auth

登录成功后,运行 gemini 命令将进入交互模式。

从哪里开始?

MCP 开发的策略是采用循序渐进的方法。

  1. 首先,设置基本的开发环境,配置所需的系统变量,并确保 Gemini CLI 正常工作。

  2. 然后,构建一个具有 stdio 传输功能的最小 "Hello World" 风格的 Ruby MCP 服务器。

  3. 验证 Gemini CLI 与本地进程通过 MCP 的连接。

  4. 最后,扩展基本的 MCP 服务器,添加更多实用工具。

使用 STDIO 传输的 Hello World

MCP 库的一个主要功能是抽象各种传输方法。无论 MCP 客户端使用何种低级传输通道/方法连接到 MCP 服务器,高级工具的实现都是相同的。

SDK 支持的最简单的传输方式是 stdio(标准输入/输出)传输,它连接本地运行的进程。MCP 客户端和 MCP 服务器必须在同一环境中运行。

连接建立的代码逻辑如下:

# 代码示例
logger.info "启动 MCP 服务器..."
transport = MCP::Server::Transports::Stdio.new
server.run(transport)

项目配置 (Gemfile)

在项目目录中创建 Gemfile,引入 MCP SDK 和日志库:

# frozen_string_literal: true

source 'https://rubygems.org'

# 使用 ServBay 提供的 Ruby 版本
ruby '3.2.0'

gem 'logger'
gem 'mcp-sdk' # 注意:此处需根据实际可用的 gem 名称调整

运行安装命令:

bundle install

编写 Ruby 代码

我们在项目目录下创建一个名为 server.rb 的文件。这段代码将初始化服务器、注册工具并启动监听。

require 'mcp'
require 'logger'
require 'json'

# 设置日志输出到标准错误流 (stderr),因为 stdout 被协议占用
$logger = Logger.new($stderr)
$logger.level = Logger::INFO

class SimpleRubyServer
  def initialize
    @mcp_server = MCP::Server.new("MyLocalRubyServer", "1.0.0")
    register_capabilities
  end

  def register_capabilities
    # 注册一个简单的问候工具
    @mcp_server.register_tool("say_hello", "向用户致以问候", {
      type: "object",
      properties: {
        username: { type: "string", description: "用户的名字" }
      },
      required: ["username"]
    }) do |params|
      execute_hello(params)
    end
  end

  def execute_hello(params)
    user = params['username'] || "Anonymous"
    $logger.info "收到问候请求,对象: #{user}"
    
    # 返回符合 MCP 协议的响应格式
    { 
      content: [
        { 
          type: "text", 
          text: "你好, #{user}! 这里是运行在本地的 Ruby MCP 服务器。" 
        }
      ] 
    }
  end

  def start
    $logger.info "服务器准备就绪,正在监听 Stdio..."
    # 实例化 Stdio 传输层并运行
    transport = MCP::Server::Transports::Stdio.new
    @mcp_server.run(transport)
  rescue => e
    $logger.error "服务器运行出错: #{e.message}"
  end
end

# 入口点
if __FILE__ == $0
  SimpleRubyServer.new.start
end

运行测试

在连接 Gemini 之前,可以先尝试运行脚本确保无语法错误:

ruby server.rb

程序启动后会挂起等待输入,这是正常的。

配置 Gemini CLI (settings.json)

Gemini CLI 需要知道如何启动我们的 Ruby 服务器。修改 Gemini 的配置文件:

{
  "mcpServers": {
    "ruby-demo": {
      "command": "ruby",
      "args": [
        "/你的/项目/绝对路径/server.rb"
      ]
    }
  }
}

使用 Gemini CLI 审查项目

启动 Gemini CLI,它将读取配置并尝试连接服务器。

gemini

在交互界面中,我们可以检查服务器状态:

> /mcp list

Configured MCP servers:
🟢 ruby-demo - Ready (1 tool)
  Tools:
  - say_hello

验证与交互

现在,通过 Gemini CLI 与 Ruby 代码进行实际交互。

输入指令:

> 请使用 ruby-demo 服务器向 "ServBay 开发者" 打个招呼。

Gemini 将解析请求,调用本地 Ruby 进程,并输出结果:

✦ I will call the say_hello tool with the username "ServBay 开发者".

╭──────────────────────────────────────────────────────────────────╮
│ ✓  say_hello (ruby-demo MCP Server) {"username":"ServBay 开发者"}  │
│                                                                  │
│ 你好, ServBay 开发者! 这里是运行在本地的 Ruby MCP 服务器。             │
╰──────────────────────────────────────────────────────────────────╯

扩展 Ruby MCP 服务器

基本的 MCP 功能已通过 Gemini CLI 验证。接下来,我们可以通过添加获取系统信息的工具来扩展服务器。

server.rbregister_capabilities 方法中添加新工具:

    # 注册系统信息工具
    @mcp_server.register_tool("system_specs", "获取当前运行环境的 Ruby 和系统信息", {}) do |_|
      get_specs
    end

并添加对应的处理方法:

  def get_specs
    specs = {
      ruby_v: RUBY_VERSION,
      platform: RUBY_PLATFORM,
      servbay_env: ENV['SERVBAY_ROOT'] ? "Detected" : "Not Detected",
      time: Time.now.to_s
    }
    { content: [{ type: "text", text: JSON.pretty_generate(specs) }] }
  end

重启 Gemini CLI 后,新的工具即可被调用。

> 获取当前系统的 Ruby 环境信息。

Gemini 将返回包含 Ruby 版本和 ServBay 环境检测结果的 JSON 数据,并据此回答你的问题。

总结

通过循序渐进的方法,我们验证了使用 Ruby 和 Gemini CLI 进行 MCP 开发的可行性。

借助 ServBay,我们省去了配置 Ruby 版本管理器和 Node.js 环境的繁杂过程,能够直接专注于代码实现。通过构建最小的 Stdio 传输服务器,我们成功让本地 Ruby 代码与 Gemini 大模型建立了连接。这种方法可以进一步扩展,利用 Ruby 丰富的生态系统处理更复杂的本地任务。