SKILL.md
readonlyread-only
name
ruby-mcp-server-generator
description
使用官方 MCP Ruby SDK 寶石,生成完整的模型上下文協定伺服器專案。
Ruby MCP Server Generator
使用官方 Ruby SDK 生成一個完整、可上線的 MCP 伺服器。
專案生成
當被要求建立一個 Ruby MCP 伺服器時,請生成具有以下結構的完整專案:
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
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
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]
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'
end
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
lib/my_mcp_server/tools/greet_tool.rb 模板
# frozen_string_literal: true
module MyMcpServer
module Tools
class GreetTool < MCP::Tool
tool_name 'greet'
description '產生問候訊息'
input_schema(
properties: {
name: {
type: 'string',
description: '要問候的名稱'
}
},
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
lib/my_mcp_server/tools/calculate_tool.rb 模板
# frozen_string_literal: true
module MyMcpServer
module Tools
class CalculateTool < MCP::Tool
tool_name 'calculate'
description '執行數學運算'
input_schema(
properties: {
operation: {
type: 'string',
description: '要執行的運算',
enum: ['add', 'subtract', 'multiply', 'divide']
},
a: {
type: 'number',
description: '第一個運算元'
},
b: {
type: 'number',
description: '第二個運算元'
}
},
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('除以零') if b.zero?
a / b.to_f
else
return error_response("未知運算: #{operation}")
end
structured_data = {
result: result,
operation: operation
}
MCP::Tool::Response.new(
[{ type: 'text', text: "結果: #{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
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 '產生程式碼審查提示'
arguments [
MCP::Prompt::Argument.new(
name: 'language',
description: '程式語言',
required: true
),
MCP::Prompt::Argument.new(
name: 'focus',
description: '審查重點(例如:效能、安全性)',
required: false
)
]
meta(
version: '1.0',
category: 'development'
)
def self.template(args, server_context:)
language = args['language'] || 'Ruby'
focus = args['focus'] || '一般品質'
MCP::Prompt::Result.new(
description: "針對 #{language} 的程式碼審查,重點在 #{focus}",
messages: [
MCP::Prompt::Message.new(
role: 'user',
content: MCP::Content::Text.new(
"請審查這段 #{language} 程式碼,重點在 #{focus}。"
)
),
MCP::Prompt::Message.new(
role: 'assistant',
content: MCP::Content::Text.new(
"我將專注於 #{focus} 來審查程式碼。請提供程式碼。"
)
),
MCP::Prompt::Message.new(
role: 'user',
content: MCP::Content::Text.new(
'[在此貼上程式碼]'
)
)
]
)
end
end
end
end
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: '範例資源資料',
mime_type: 'application/json'
)
end
def self.read(uri)
return [] unless uri == RESOURCE_URI
data = {
message: '範例資源資料',
timestamp: Time.now.iso8601,
version: MyMcpServer::VERSION
}
[{
uri: uri,
mimeType: 'application/json',
text: data.to_json
}]
end
end
end
end
bin/mcp-server 模板
#!/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 "\n正在關閉伺服器..."
exit 0
rescue StandardError => e
warn "錯誤: #{e.message}"
warn e.backtrace.join("\n")
exit 1
end
讓檔案可執行:
chmod +x bin/mcp-server
test/test_helper.rb 模板
# frozen_string_literal: true
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
require 'my_mcp_server'
require 'minitest/autorun'
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
end
test/tools/calculate_tool_test.rb 模板
# frozen_string_literal: true
require 'test_helper'
module MyMcpServer
module Tools
class CalculateToolTest < Minitest::Test
def test_addition
response = CalculateTool.call(
operation: 'add',
a: 5,
b: 3,
server_context: {}
)
refute response.is_error
assert_equal 8, response.structured_content[:result]
end
def test_subtraction
response = CalculateTool.call(
operation: 'subtract',
a: 10,
b: 4,
server_context: {}
)
refute response.is_error
assert_equal 6, response.structured_content[:result]
end
def test_multiplication
response = CalculateTool.call(
operation: 'multiply',
a: 6,
b: 7,
server_context: {}
)
refute response.is_error
assert_equal 42, response.structured_content[:result]
end
def test_division
response = CalculateTool.call(
operation: 'divide',
a: 15,
b: 3,
server_context: {}
)
refute response.is_error
assert_equal 5.0, response.structured_content[:result]
end
def test_division_by_zero
response = CalculateTool.call(
operation: 'divide',
a: 10,
b: 0,
server_context: {}
)
assert response.is_error
assert_match(/除以零/, response.content.first[:text])
end
def test_unknown_operation
response = CalculateTool.call(
operation: 'modulo',
a: 10,
b: 3,
server_context: {}
)
assert response.is_error
assert_match(/未知運算/, response.content.first[:text])
end
end
end
end
README.md 模板
# My MCP Server
一個使用 Ruby 和官方 MCP Ruby SDK 建立的模型上下文協定伺服器。
## 功能特色
- ✅ 工具:greet, calculate
- ✅ 提示:code_review
- ✅ 資源:example-data
- ✅ 輸入/輸出結構定義
- ✅ 工具註解
- ✅ 結構化內容
- ✅ 完整的測試覆蓋
## 系統需求
- Ruby 3.0 或更新版本
## 安裝
```bash
bundle install
使用方式
Stdio 傳輸
執行伺服器:
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"}}}
Rails 整合
加入 Rails 控制器:
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
測試
執行測試:
bundle exec rake test
執行語法檢查:
bundle exec rake rubocop
執行所有檢查:
bundle exec rake
與 Claude Desktop 整合
加入 claude_desktop_config.json:
{
"mcpServers": {
"my-mcp-server": {
"command": "bundle",
"args": ["exec", "bin/mcp-server"],
"cwd": "/path/to/my-mcp-server"
}
}
}
專案結構
my-mcp-server/
├── Gemfile # 相依套件
├── Rakefile # 建置任務
├── lib/ # 原始碼
│ ├── my_mcp_server.rb # 主要進入點
│ └── my_mcp_server/ # 模組命名空間
│ ├── server.rb # 伺服器設定
│ ├── tools/ # 工具實作
│ ├── prompts/ # 提示模板
│ └── resources/ # 資源處理器
├── bin/ # 可執行檔
│ └── mcp-server # Stdio 伺服器
├── test/ # 測試套件
│ ├── test_helper.rb # 測試設定
│ └── tools/ # 工具測試
└── README.md # 本檔案
授權條款
MIT
### 生成說明
1. **詢問專案名稱與描述**
2. **生成所有檔案**,使用正確的命名與模組結構
3. **使用類別來組織工具與提示**,以獲得更好的結構
4. **包含輸入/輸出結構定義**,確保型別安全
5. **加入工具註解**,提供行為提示
6. **在回應中包含結構化內容**
7. **為所有工具實作完整的測試**
8. **遵循 Ruby 慣例**(蛇底命名、模組、frozen_string_literal)
9. **加入適當的錯誤處理**,使用 is_error 標記
10. **提供 stdio 與 HTTP 兩種使用範例**






