2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rubyで簡易的なMCPサーバーを作ってみる

Posted at

はじめに

少し前ですが、MCPのRuby SDKがリリースされていたので、それを使って簡易的なMCPサーバーを作ってみようと思います。

Transport Support

  • stdio: Notifications are sent as JSON-RPC 2.0 messages to stdout
  • Streamable HTTP: Notifications are sent as JSON-RPC 2.0 messages over HTTP with streaming (chunked transfer or SSE)

とあるように、標準入出力とStreamable HTTPに対応しています。
今回は標準入出力を使ったMCPサーバーを実装してみます。

最小構成でMCPサーバーを起動する

特にpromptsやtools, resourcesを設定しない場合、以下の記述だけでMCPサーバーを起動することできます。

stdio.rb
require "mcp"

server = MCP::Server.new(
  name: "example",
)
transport = MCP::Server::Transports::StdioTransport.new(server)
transport.open

この状態でサーバーを起動すると、標準入出力経由でメッセージをやり取りできるようになります。

$ ruby stdio.rb
{"jsonrpc":"2.0","id":"1","method":"ping"}
{"jsonrpc":"2.0","id":"1","result":{}}
{"jsonrpc":"2.0","id":"2","method":"tools/list"}
{"jsonrpc":"2.0","id":"2","result":{"tools":[]}}

実行できるメソッドは以下になります。
https://github.com/modelcontextprotocol/ruby-sdk?tab=readme-ov-file#supported-methods

Supported Methods

  • initialize - Initializes the protocol and returns server capabilities
  • ping - Simple health check
  • tools/list - Lists all registered tools and their schemas
  • tools/call - Invokes a specific tool with provided arguments
  • prompts/list - Lists all registered prompts and their schemas
  • prompts/get - Retrieves a specific prompt by name
  • resources/list - Lists all registered resources and their schemas
  • resources/read - Retrieves a specific resource by name
  • resources/templates/list - Lists all registered resource templates and their schemas

toolsを追加してみる

toolsとして、簡単な足し算の機能を追加してみます。

MCP::Toolを継承したクラスを作成し、入力のschemaや実際に呼び出し時に実行されるメソッドを定義するだけで作成することができます。

class ExampleTool < MCP::Tool
  title "Example tool for sum"
  description "This tool adds two numbers."
  input_schema(
    properties: {
      a: { type: "number" },
      b: { type: "number" },
    },
    required: ["a", "b"]
  )

  def self.call(a:, b:, server_context:)
    MCP::Tool::Response.new([{ type: "text", text: "#{a} + #{b} = #{a + b}"}])
  end
end

MCP::Serverの初期化時にtoolsパラメータに配列で渡すだけで簡単に追加することができます。

server = MCP::Server.new(
  name: "example",
+ tools: [ExampleTool],
)

この状態でtools/listメソッドを実行すると、上記のtoolsが追加されていることが確認できます。

{"jsonrpc":"2.0","id":"1","method":"tools/list"}
{"jsonrpc":"2.0","id":"1","result":{"tools":[{"name":"example_tool","title":"Example tool","description":"This tool adds two numbers.","inputSchema":{"type":"object","properties":{"a":{"type":"number"},"b":{"type":"number"}},"required":["a","b"]}}]}}

input_schemaに沿ったJSONをパラメータにツールを実行すると、ExampleTool.callで定義した処理が実行されて返されます。

{"jsonrpc":"2.0","id":"2","method":"tools/call","params":{"name":"example_tool","arguments":{"a":7, "b": 7}}}
{"jsonrpc":"2.0","id":"2","result":{"content":[{"type":"text","text":"7 + 7 = 14"}],"isError":false}}

resourcesを追加してみる

次に、固定のテキストファイルの内容を返すresourcesを追加してみます。

まずは、resources/listに応答するためのリソース情報を定義します。
ここではexample.txtというローカルファイルをひとつ公開します。

resource = MCP::Resource.new(
  uri: "file:///Users/tsuzuki-takaaki/example.txt",
  name: "Example Resource",
  title: "Example Resource",
  description: "An example text file",
  mime_type: "text/plain",
)

これもtoolsと同様に、MCP::Serverの初期化時にresourcesパラメータに配列で渡すだけで簡単に追加することができます。

server = MCP::Server.new(
  name: "example",
  tools: [ExampleTool],
+ resources: [resource],
)

この状態でresources/listを実行すると、追加されていることが確認できます。

{"jsonrpc":"2.0","id":"2","method":"resources/list"}
{"jsonrpc":"2.0","id":"2","result":{"resources":[{"uri":"file:///Users/tsuzuki-takaaki/example.txt","name":"Example Resource","title":"Example Resource","description":"An example text file","mimeType":"text/plain"}]}}

このままだと、resources/readメソッドに反応できないので、リソースの実際の中身を返す処理を登録します。
uriで指定されたファイルのコンテンツを読む処理を追加しました。

server.resources_read_handler do |params|
  [{
    uri: params[:uri],
    mimeType: "text/plain",
    text: File.read(params[:uri].sub("file://", "")),
  }]
end

resources/readを実行してみると、uriで指定したファイルのコンテンツが読まれていそうです。

{"jsonrpc":"2.0","id":"1","method":"resources/read", "params": {"uri": "file:///Users/tsuzuki-takaaki/example.txt"}}
{"jsonrpc":"2.0","id":"1","result":{"contents":[{"uri":"file:///Users/tsuzuki-takaaki/example.txt","mimeType":"text/plain","text":"Example\n"}]}}

Claude Desktopで使ってみる

設定 -> 開発者 -> 設定を編集で、claude_desktop_config.jsonを編集することができます。

commandには、実行したいRubyのパスを、argsには作成したMCP server用のファイルのパスを指定します。

{
  "mcpServers": {
    "example": {
      "command": "{実行したいRubyのパス}",
      "args": [
        "{MCP server用のファイルのパス}"
      ]
    }
  }
}

問題なく設定が完了すると、設定画面に以下のように出力され、作成したMCPサーバーが使えるようになります。

スクリーンショット 2025-10-31 3.38.25.png

終わりに

今回はtoolsとresourcesしか追加しませんでしたが、もちろんpromptsもあるので、そのあたりも触ってみたいなと思いました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?