claude_code 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rspec_status +114 -0
- data/.rubocop.yml +51 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +37 -0
- data/LICENSE +21 -0
- data/README.md +288 -0
- data/Rakefile +32 -0
- data/USAGE_EXAMPLES.md +428 -0
- data/claude_code.gemspec +47 -0
- data/docs/README.md +254 -0
- data/docs/mcp_integration.md +404 -0
- data/docs/streaming.md +316 -0
- data/examples/authentication_examples.rb +133 -0
- data/examples/basic_usage.rb +73 -0
- data/examples/conversation_resuming.rb +96 -0
- data/examples/irb_helpers.rb +168 -0
- data/examples/jsonl_cli_equivalent.rb +108 -0
- data/examples/mcp_examples.rb +166 -0
- data/examples/model_examples.rb +111 -0
- data/examples/quick_start.rb +75 -0
- data/examples/rails_sidekiq_example.rb +336 -0
- data/examples/streaming_examples.rb +195 -0
- data/examples/streaming_json_input.rb +171 -0
- data/hello.txt +1 -0
- data/lib/claude_code/client.rb +437 -0
- data/lib/claude_code/errors.rb +48 -0
- data/lib/claude_code/types.rb +237 -0
- data/lib/claude_code/version.rb +5 -0
- data/lib/claude_code.rb +265 -0
- metadata +219 -0
data/docs/README.md
ADDED
@@ -0,0 +1,254 @@
|
|
1
|
+
# Claude Code SDK for Ruby
|
2
|
+
|
3
|
+
Ruby SDK for Claude Code with streaming support and ergonomic MCP integration. See the [Claude Code SDK documentation](https://docs.anthropic.com/en/docs/claude-code/sdk) for more information.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'claude_code_sdk'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
```bash
|
16
|
+
bundle install
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
gem install claude_code_sdk
|
23
|
+
```
|
24
|
+
|
25
|
+
**Prerequisites:**
|
26
|
+
- Ruby 3.0+
|
27
|
+
- Node.js
|
28
|
+
- Claude Code: `npm install -g @anthropic-ai/claude-code`
|
29
|
+
|
30
|
+
## Quick Start
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
require 'claude_code_sdk'
|
34
|
+
|
35
|
+
# Simple query with streaming
|
36
|
+
ClaudeCodeSDK.query(prompt: "What is 2 + 2?").each do |message|
|
37
|
+
if message.is_a?(ClaudeCodeSDK::AssistantMessage)
|
38
|
+
message.content.each do |block|
|
39
|
+
if block.is_a?(ClaudeCodeSDK::TextBlock)
|
40
|
+
puts block.text
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
## Features
|
48
|
+
|
49
|
+
### 🌊 **Real-time Streaming**
|
50
|
+
- Messages arrive as they're generated (not after completion)
|
51
|
+
- Low memory footprint - process one message at a time
|
52
|
+
- Perfect for interactive applications and long-running operations
|
53
|
+
|
54
|
+
### 🔧 **Ergonomic MCP Integration**
|
55
|
+
- Simple one-line MCP server configuration
|
56
|
+
- Support for HTTP, SSE, and stdio MCP servers
|
57
|
+
- Built-in helpers for common use cases
|
58
|
+
|
59
|
+
### 🎯 **Model Selection**
|
60
|
+
- Support for model aliases (`sonnet`, `haiku`, `opus`)
|
61
|
+
- Full model name specification
|
62
|
+
- Easy switching between models
|
63
|
+
|
64
|
+
### ⚙️ **Complete Configuration**
|
65
|
+
- All Claude Code CLI options supported
|
66
|
+
- Custom system prompts
|
67
|
+
- Tool permission management
|
68
|
+
- Working directory control
|
69
|
+
|
70
|
+
## Examples
|
71
|
+
|
72
|
+
### Basic Usage
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
require 'claude_code_sdk'
|
76
|
+
|
77
|
+
# With options
|
78
|
+
options = ClaudeCodeSDK::ClaudeCodeOptions.new(
|
79
|
+
model: "sonnet",
|
80
|
+
system_prompt: "You are a helpful assistant",
|
81
|
+
max_turns: 1
|
82
|
+
)
|
83
|
+
|
84
|
+
ClaudeCodeSDK.query(
|
85
|
+
prompt: "Explain Ruby blocks",
|
86
|
+
options: options,
|
87
|
+
cli_path: "/path/to/claude"
|
88
|
+
).each do |message|
|
89
|
+
# Process streaming messages
|
90
|
+
end
|
91
|
+
```
|
92
|
+
|
93
|
+
### MCP Integration
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
# Ultra-convenient MCP usage
|
97
|
+
ClaudeCodeSDK.quick_mcp_query(
|
98
|
+
"Use the about tool to describe yourself",
|
99
|
+
server_name: "ninja",
|
100
|
+
server_url: "https://mcp-creator-ninja-v1-4-0.mcp.soy/",
|
101
|
+
tools: "about"
|
102
|
+
).each do |message|
|
103
|
+
# Process MCP responses
|
104
|
+
end
|
105
|
+
|
106
|
+
# Advanced MCP configuration
|
107
|
+
mcp_servers = ClaudeCodeSDK.add_mcp_server("my_server", {
|
108
|
+
command: "node",
|
109
|
+
args: ["my-mcp-server.js"],
|
110
|
+
env: { "API_KEY" => "secret" }
|
111
|
+
})
|
112
|
+
|
113
|
+
options = ClaudeCodeSDK::ClaudeCodeOptions.new(
|
114
|
+
allowed_tools: ["mcp__my_server__my_tool"],
|
115
|
+
mcp_servers: mcp_servers
|
116
|
+
)
|
117
|
+
```
|
118
|
+
|
119
|
+
### Streaming with Custom Handling
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
# Auto-formatted streaming
|
123
|
+
ClaudeCodeSDK.stream_query(
|
124
|
+
prompt: "Count from 1 to 5",
|
125
|
+
options: ClaudeCodeSDK::ClaudeCodeOptions.new(max_turns: 1)
|
126
|
+
)
|
127
|
+
|
128
|
+
# Custom streaming with timestamps
|
129
|
+
start_time = Time.now
|
130
|
+
ClaudeCodeSDK.stream_query(
|
131
|
+
prompt: "Explain inheritance",
|
132
|
+
options: ClaudeCodeSDK::ClaudeCodeOptions.new(max_turns: 1)
|
133
|
+
) do |message, index|
|
134
|
+
timestamp = Time.now - start_time
|
135
|
+
puts "[#{format('%.2f', timestamp)}s] #{message}"
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
### Rails + Sidekiq Integration
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
# Background job with real-time streaming
|
143
|
+
class ClaudeStreamingJob
|
144
|
+
include Sidekiq::Job
|
145
|
+
|
146
|
+
def perform(user_id, query_id, prompt, options = {})
|
147
|
+
channel = "claude_stream_#{user_id}_#{query_id}"
|
148
|
+
|
149
|
+
ClaudeCodeSDK.query(prompt: prompt, options: options).each do |message|
|
150
|
+
# Broadcast to ActionCable
|
151
|
+
ActionCable.server.broadcast(channel, {
|
152
|
+
type: 'message',
|
153
|
+
data: serialize_message(message),
|
154
|
+
timestamp: Time.current
|
155
|
+
})
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
## API Reference
|
162
|
+
|
163
|
+
### Core Methods
|
164
|
+
|
165
|
+
#### `ClaudeCodeSDK.query(prompt:, options: nil, cli_path: nil, mcp_servers: {})`
|
166
|
+
Main method for querying Claude with streaming support.
|
167
|
+
|
168
|
+
#### `ClaudeCodeSDK.quick_mcp_query(prompt, server_name:, server_url:, tools:, **options)`
|
169
|
+
Convenient method for quick MCP server usage.
|
170
|
+
|
171
|
+
#### `ClaudeCodeSDK.stream_query(prompt:, options: nil, cli_path: nil, mcp_servers: {}, &block)`
|
172
|
+
Streaming helper with auto-formatting or custom block handling.
|
173
|
+
|
174
|
+
#### `ClaudeCodeSDK.add_mcp_server(name, config)`
|
175
|
+
Helper to create MCP server configurations.
|
176
|
+
|
177
|
+
### Configuration Classes
|
178
|
+
|
179
|
+
#### `ClaudeCodeOptions`
|
180
|
+
Main configuration class with all CLI options:
|
181
|
+
- `model` - Model alias or full name
|
182
|
+
- `max_turns` - Limit conversation turns
|
183
|
+
- `system_prompt` - Custom system prompt
|
184
|
+
- `allowed_tools` - Tools to allow
|
185
|
+
- `mcp_servers` - MCP server configurations
|
186
|
+
- `permission_mode` - Permission handling mode
|
187
|
+
- `cwd` - Working directory
|
188
|
+
|
189
|
+
#### MCP Server Configurations
|
190
|
+
- `McpHttpServerConfig` - HTTP/HTTPS MCP servers
|
191
|
+
- `McpSSEServerConfig` - Server-Sent Events MCP servers
|
192
|
+
- `McpStdioServerConfig` - Stdio MCP servers
|
193
|
+
|
194
|
+
### Message Types
|
195
|
+
|
196
|
+
#### `SystemMessage`
|
197
|
+
- `subtype` - Message subtype (e.g., "init")
|
198
|
+
- `data` - System data (session_id, tools, etc.)
|
199
|
+
|
200
|
+
#### `AssistantMessage`
|
201
|
+
- `content` - Array of content blocks
|
202
|
+
|
203
|
+
#### Content Blocks
|
204
|
+
- `TextBlock` - Text content
|
205
|
+
- `ToolUseBlock` - Tool usage with input
|
206
|
+
- `ToolResultBlock` - Tool results
|
207
|
+
|
208
|
+
#### `ResultMessage`
|
209
|
+
- `duration_ms` - Total duration
|
210
|
+
- `total_cost_usd` - API cost
|
211
|
+
- `session_id` - Conversation session
|
212
|
+
- `result` - Final result text
|
213
|
+
|
214
|
+
## Error Handling
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
begin
|
218
|
+
ClaudeCodeSDK.query(prompt: "Hello").each do |message|
|
219
|
+
# Process message
|
220
|
+
end
|
221
|
+
rescue ClaudeCodeSDK::CLINotFoundError
|
222
|
+
puts "Please install Claude Code"
|
223
|
+
rescue ClaudeCodeSDK::ProcessError => e
|
224
|
+
puts "Process failed: #{e.exit_code}"
|
225
|
+
rescue ClaudeCodeSDK::CLIJSONDecodeError => e
|
226
|
+
puts "JSON parsing failed: #{e.message}"
|
227
|
+
end
|
228
|
+
```
|
229
|
+
|
230
|
+
## Examples Directory
|
231
|
+
|
232
|
+
- `examples/basic_usage.rb` - Basic SDK usage
|
233
|
+
- `examples/model_examples.rb` - Model specification examples
|
234
|
+
- `examples/mcp_examples.rb` - MCP integration examples
|
235
|
+
- `examples/streaming_examples.rb` - Streaming demonstrations
|
236
|
+
- `examples/rails_sidekiq_example.rb` - Rails/Sidekiq integration
|
237
|
+
- `examples/irb_helpers.rb` - IRB convenience functions
|
238
|
+
|
239
|
+
## IRB Quick Start
|
240
|
+
|
241
|
+
```ruby
|
242
|
+
# Load helpers
|
243
|
+
require_relative 'examples/irb_helpers'
|
244
|
+
|
245
|
+
# Try these commands:
|
246
|
+
quick_claude("What is Ruby?")
|
247
|
+
stream_claude("Explain blocks")
|
248
|
+
ninja_test("Tell me about yourself")
|
249
|
+
auto_stream("Count to 5")
|
250
|
+
```
|
251
|
+
|
252
|
+
## License
|
253
|
+
|
254
|
+
MIT
|
@@ -0,0 +1,404 @@
|
|
1
|
+
# MCP Integration
|
2
|
+
|
3
|
+
The Ruby Claude Code SDK provides ergonomic integration with Model Context Protocol (MCP) servers, allowing you to extend Claude's capabilities with custom tools and resources.
|
4
|
+
|
5
|
+
## Quick Start
|
6
|
+
|
7
|
+
### Ultra-Convenient Method
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
# Simplest way to use MCP
|
11
|
+
ClaudeCodeSDK.quick_mcp_query(
|
12
|
+
"Use the about tool to describe yourself",
|
13
|
+
server_name: "ninja",
|
14
|
+
server_url: "https://mcp-creator-ninja-v1-4-0.mcp.soy/",
|
15
|
+
tools: "about" # String or array of tools
|
16
|
+
).each do |message|
|
17
|
+
# Process streaming MCP responses
|
18
|
+
end
|
19
|
+
```
|
20
|
+
|
21
|
+
## MCP Server Configuration
|
22
|
+
|
23
|
+
### 1. HTTP/HTTPS Servers
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
# Simple URL string (auto-detected as HTTP)
|
27
|
+
mcp_servers = ClaudeCodeSDK.add_mcp_server(
|
28
|
+
"my_server",
|
29
|
+
"https://my-mcp-server.com/"
|
30
|
+
)
|
31
|
+
|
32
|
+
# Explicit HTTP configuration with headers
|
33
|
+
mcp_servers = ClaudeCodeSDK.add_mcp_server("api_server", {
|
34
|
+
type: "http",
|
35
|
+
url: "https://api.example.com/mcp",
|
36
|
+
headers: {
|
37
|
+
"Authorization" => "Bearer token123",
|
38
|
+
"X-API-Key" => "secret"
|
39
|
+
}
|
40
|
+
})
|
41
|
+
```
|
42
|
+
|
43
|
+
### 2. Server-Sent Events (SSE)
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
mcp_servers = ClaudeCodeSDK.add_mcp_server("sse_server", {
|
47
|
+
type: "sse",
|
48
|
+
url: "https://stream.example.com/mcp",
|
49
|
+
headers: {
|
50
|
+
"Authorization" => "Bearer token123"
|
51
|
+
}
|
52
|
+
})
|
53
|
+
```
|
54
|
+
|
55
|
+
### 3. Stdio (Command-line) Servers
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
# Simple command string
|
59
|
+
mcp_servers = ClaudeCodeSDK.add_mcp_server(
|
60
|
+
"local_server",
|
61
|
+
"node my-mcp-server.js"
|
62
|
+
)
|
63
|
+
|
64
|
+
# Full stdio configuration
|
65
|
+
mcp_servers = ClaudeCodeSDK.add_mcp_server("github_server", {
|
66
|
+
command: "npx",
|
67
|
+
args: ["@modelcontextprotocol/server-github"],
|
68
|
+
env: {
|
69
|
+
"GITHUB_TOKEN" => "your-github-token"
|
70
|
+
}
|
71
|
+
})
|
72
|
+
```
|
73
|
+
|
74
|
+
## Usage Patterns
|
75
|
+
|
76
|
+
### Method 1: Separate MCP Servers Parameter
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
# Build server configuration
|
80
|
+
mcp_servers = ClaudeCodeSDK.add_mcp_server(
|
81
|
+
"ninja",
|
82
|
+
"https://mcp-creator-ninja-v1-4-0.mcp.soy/"
|
83
|
+
)
|
84
|
+
|
85
|
+
# Configure options
|
86
|
+
options = ClaudeCodeSDK::ClaudeCodeOptions.new(
|
87
|
+
allowed_tools: ["mcp__ninja__about"],
|
88
|
+
max_turns: 1
|
89
|
+
)
|
90
|
+
|
91
|
+
# Query with MCP servers
|
92
|
+
ClaudeCodeSDK.query(
|
93
|
+
prompt: "Use the about tool",
|
94
|
+
options: options,
|
95
|
+
mcp_servers: mcp_servers
|
96
|
+
).each do |message|
|
97
|
+
# Process response
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
101
|
+
### Method 2: Options-based Configuration
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
# Configure everything in options
|
105
|
+
options = ClaudeCodeSDK::ClaudeCodeOptions.new(
|
106
|
+
mcp_servers: {
|
107
|
+
"ninja" => ClaudeCodeSDK::McpHttpServerConfig.new(
|
108
|
+
url: "https://mcp-creator-ninja-v1-4-0.mcp.soy/"
|
109
|
+
),
|
110
|
+
"local" => ClaudeCodeSDK::McpStdioServerConfig.new(
|
111
|
+
command: "node",
|
112
|
+
args: ["my-server.js"]
|
113
|
+
)
|
114
|
+
},
|
115
|
+
allowed_tools: ["mcp__ninja__about", "mcp__local__my_tool"]
|
116
|
+
)
|
117
|
+
|
118
|
+
ClaudeCodeSDK.query(prompt: "Use available tools", options: options)
|
119
|
+
```
|
120
|
+
|
121
|
+
### Method 3: Multiple Servers
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
# Build multiple servers
|
125
|
+
servers = {}
|
126
|
+
servers.merge!(ClaudeCodeSDK.add_mcp_server("ninja", "https://..."))
|
127
|
+
servers.merge!(ClaudeCodeSDK.add_mcp_server("github", {
|
128
|
+
command: "npx",
|
129
|
+
args: ["@modelcontextprotocol/server-github"],
|
130
|
+
env: { "GITHUB_TOKEN" => ENV["GITHUB_TOKEN"] }
|
131
|
+
}))
|
132
|
+
servers.merge!(ClaudeCodeSDK.add_mcp_server("filesystem", "npx @modelcontextprotocol/server-filesystem /allowed/path"))
|
133
|
+
|
134
|
+
options = ClaudeCodeSDK::ClaudeCodeOptions.new(
|
135
|
+
allowed_tools: [
|
136
|
+
"mcp__ninja__about",
|
137
|
+
"mcp__github__search_repositories",
|
138
|
+
"mcp__filesystem__read_file"
|
139
|
+
]
|
140
|
+
)
|
141
|
+
|
142
|
+
ClaudeCodeSDK.query(
|
143
|
+
prompt: "Use available tools to help me",
|
144
|
+
options: options,
|
145
|
+
mcp_servers: servers
|
146
|
+
)
|
147
|
+
```
|
148
|
+
|
149
|
+
## Tool Permission Management
|
150
|
+
|
151
|
+
### Tool Naming Convention
|
152
|
+
|
153
|
+
MCP tools follow the pattern: `mcp__<server_name>__<tool_name>`
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
# Allow specific tools
|
157
|
+
allowed_tools: ["mcp__ninja__about", "mcp__github__search_repositories"]
|
158
|
+
|
159
|
+
# Allow all tools from a server (use with caution)
|
160
|
+
allowed_tools: ["mcp__ninja"] # Allows all ninja server tools
|
161
|
+
```
|
162
|
+
|
163
|
+
### Permission Modes
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
options = ClaudeCodeSDK::ClaudeCodeOptions.new(
|
167
|
+
permission_mode: "default", # Prompt for dangerous tools
|
168
|
+
# permission_mode: "acceptEdits", # Auto-accept file edits
|
169
|
+
# permission_mode: "bypassPermissions" # Allow all tools (dangerous)
|
170
|
+
)
|
171
|
+
```
|
172
|
+
|
173
|
+
## Streaming MCP Responses
|
174
|
+
|
175
|
+
MCP tool calls stream in real-time, showing tool usage and results as they happen:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
ClaudeCodeSDK.quick_mcp_query(
|
179
|
+
"Use multiple tools to analyze this project",
|
180
|
+
server_name: "ninja",
|
181
|
+
server_url: "https://mcp-creator-ninja-v1-4-0.mcp.soy/",
|
182
|
+
tools: ["about", "create"], # Multiple tools
|
183
|
+
max_turns: 3
|
184
|
+
).each do |message|
|
185
|
+
case message
|
186
|
+
when ClaudeCodeSDK::SystemMessage
|
187
|
+
puts "🔧 System: MCP servers: #{message.data['mcp_servers'].length}"
|
188
|
+
|
189
|
+
when ClaudeCodeSDK::AssistantMessage
|
190
|
+
message.content.each do |block|
|
191
|
+
case block
|
192
|
+
when ClaudeCodeSDK::TextBlock
|
193
|
+
puts "💬 #{block.text}"
|
194
|
+
|
195
|
+
when ClaudeCodeSDK::ToolUseBlock
|
196
|
+
puts "🔧 Using tool: #{block.name}"
|
197
|
+
puts "📥 Input: #{block.input}"
|
198
|
+
|
199
|
+
when ClaudeCodeSDK::ToolResultBlock
|
200
|
+
puts "📤 Tool result:"
|
201
|
+
puts " Content: #{block.content}"
|
202
|
+
puts " Error: #{block.is_error ? 'Yes' : 'No'}"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
when ClaudeCodeSDK::ResultMessage
|
207
|
+
puts "✅ Completed - Cost: $#{format('%.6f', message.total_cost_usd || 0)}"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
```
|
211
|
+
|
212
|
+
## Common MCP Servers
|
213
|
+
|
214
|
+
### Creator Ninja (Example/Testing)
|
215
|
+
```ruby
|
216
|
+
ClaudeCodeSDK.add_mcp_server(
|
217
|
+
"ninja",
|
218
|
+
"https://mcp-creator-ninja-v1-4-0.mcp.soy/"
|
219
|
+
)
|
220
|
+
# Tools: about, create
|
221
|
+
```
|
222
|
+
|
223
|
+
### Filesystem Server
|
224
|
+
```ruby
|
225
|
+
ClaudeCodeSDK.add_mcp_server("filesystem", {
|
226
|
+
command: "npx",
|
227
|
+
args: ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"],
|
228
|
+
})
|
229
|
+
# Tools: read_file, write_file, list_directory, etc.
|
230
|
+
```
|
231
|
+
|
232
|
+
### GitHub Server
|
233
|
+
```ruby
|
234
|
+
ClaudeCodeSDK.add_mcp_server("github", {
|
235
|
+
command: "npx",
|
236
|
+
args: ["-y", "@modelcontextprotocol/server-github"],
|
237
|
+
env: {
|
238
|
+
"GITHUB_TOKEN" => ENV["GITHUB_TOKEN"]
|
239
|
+
}
|
240
|
+
})
|
241
|
+
# Tools: search_repositories, get_file_contents, create_issue, etc.
|
242
|
+
```
|
243
|
+
|
244
|
+
### Database Server (Example)
|
245
|
+
```ruby
|
246
|
+
ClaudeCodeSDK.add_mcp_server("database", {
|
247
|
+
command: "node",
|
248
|
+
args: ["database-mcp-server.js"],
|
249
|
+
env: {
|
250
|
+
"DATABASE_URL" => ENV["DATABASE_URL"]
|
251
|
+
}
|
252
|
+
})
|
253
|
+
# Tools: query, schema, insert, update, etc.
|
254
|
+
```
|
255
|
+
|
256
|
+
## Error Handling
|
257
|
+
|
258
|
+
```ruby
|
259
|
+
begin
|
260
|
+
ClaudeCodeSDK.quick_mcp_query(
|
261
|
+
"Use unavailable tool",
|
262
|
+
server_name: "ninja",
|
263
|
+
server_url: "https://bad-url.com/",
|
264
|
+
tools: "nonexistent"
|
265
|
+
).each do |message|
|
266
|
+
# Process message
|
267
|
+
end
|
268
|
+
rescue ClaudeCodeSDK::ProcessError => e
|
269
|
+
puts "MCP server failed: #{e.message}"
|
270
|
+
puts "Exit code: #{e.exit_code}"
|
271
|
+
rescue ClaudeCodeSDK::CLIConnectionError => e
|
272
|
+
puts "Connection failed: #{e.message}"
|
273
|
+
end
|
274
|
+
```
|
275
|
+
|
276
|
+
## Rails Integration
|
277
|
+
|
278
|
+
```ruby
|
279
|
+
class McpService
|
280
|
+
def self.query_with_mcp(prompt, mcp_config = {})
|
281
|
+
servers = build_mcp_servers(mcp_config)
|
282
|
+
|
283
|
+
options = ClaudeCodeSDK::ClaudeCodeOptions.new(
|
284
|
+
allowed_tools: mcp_config[:allowed_tools] || [],
|
285
|
+
permission_mode: "acceptEdits" # For automated environments
|
286
|
+
)
|
287
|
+
|
288
|
+
ClaudeCodeSDK.query(
|
289
|
+
prompt: prompt,
|
290
|
+
options: options,
|
291
|
+
mcp_servers: servers
|
292
|
+
)
|
293
|
+
end
|
294
|
+
|
295
|
+
private
|
296
|
+
|
297
|
+
def self.build_mcp_servers(config)
|
298
|
+
servers = {}
|
299
|
+
|
300
|
+
config[:servers]&.each do |name, server_config|
|
301
|
+
servers.merge!(ClaudeCodeSDK.add_mcp_server(name, server_config))
|
302
|
+
end
|
303
|
+
|
304
|
+
servers
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
# Usage in Rails
|
309
|
+
McpService.query_with_mcp(
|
310
|
+
"Analyze our GitHub repository",
|
311
|
+
servers: {
|
312
|
+
"github" => {
|
313
|
+
command: "npx",
|
314
|
+
args: ["@modelcontextprotocol/server-github"],
|
315
|
+
env: { "GITHUB_TOKEN" => Rails.application.credentials.github_token }
|
316
|
+
}
|
317
|
+
},
|
318
|
+
allowed_tools: ["mcp__github__search_repositories", "mcp__github__get_file_contents"]
|
319
|
+
).each do |message|
|
320
|
+
# Process in background job with ActionCable broadcasting
|
321
|
+
end
|
322
|
+
```
|
323
|
+
|
324
|
+
## Configuration Examples
|
325
|
+
|
326
|
+
### Development Environment
|
327
|
+
```ruby
|
328
|
+
# config/claude_mcp.yml
|
329
|
+
development:
|
330
|
+
servers:
|
331
|
+
filesystem:
|
332
|
+
command: "npx"
|
333
|
+
args: ["-y", "@modelcontextprotocol/server-filesystem", "<%= Rails.root %>"]
|
334
|
+
github:
|
335
|
+
command: "npx"
|
336
|
+
args: ["-y", "@modelcontextprotocol/server-github"]
|
337
|
+
env:
|
338
|
+
GITHUB_TOKEN: "<%= Rails.application.credentials.github_token %>"
|
339
|
+
|
340
|
+
# Load in initializer
|
341
|
+
CLAUDE_MCP_CONFIG = YAML.load_file(Rails.root.join('config/claude_mcp.yml'))[Rails.env]
|
342
|
+
```
|
343
|
+
|
344
|
+
### Production Environment
|
345
|
+
```ruby
|
346
|
+
# Use environment variables for security
|
347
|
+
ClaudeCodeSDK.add_mcp_server("production_api", {
|
348
|
+
type: "http",
|
349
|
+
url: ENV["MCP_API_URL"],
|
350
|
+
headers: {
|
351
|
+
"Authorization" => "Bearer #{ENV['MCP_API_TOKEN']}",
|
352
|
+
"X-Environment" => Rails.env
|
353
|
+
}
|
354
|
+
})
|
355
|
+
```
|
356
|
+
|
357
|
+
## Testing MCP Integration
|
358
|
+
|
359
|
+
```ruby
|
360
|
+
# spec/support/mcp_helpers.rb
|
361
|
+
module McpHelpers
|
362
|
+
def mock_mcp_server(name, tools = ["about"])
|
363
|
+
allow(ClaudeCodeSDK).to receive(:add_mcp_server).with(name, anything).and_return({
|
364
|
+
name => double("MockMcpServer")
|
365
|
+
})
|
366
|
+
|
367
|
+
allow(ClaudeCodeSDK).to receive(:query).and_return([
|
368
|
+
mock_assistant_message_with_tools(tools)
|
369
|
+
])
|
370
|
+
end
|
371
|
+
|
372
|
+
def mock_assistant_message_with_tools(tools)
|
373
|
+
content = tools.map do |tool|
|
374
|
+
ClaudeCodeSDK::ToolUseBlock.new(
|
375
|
+
id: "test-#{tool}",
|
376
|
+
name: "mcp__test__#{tool}",
|
377
|
+
input: {}
|
378
|
+
)
|
379
|
+
end
|
380
|
+
|
381
|
+
ClaudeCodeSDK::AssistantMessage.new(content)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
# In tests
|
386
|
+
RSpec.describe "MCP Integration" do
|
387
|
+
include McpHelpers
|
388
|
+
|
389
|
+
it "uses MCP tools" do
|
390
|
+
mock_mcp_server("test", ["about"])
|
391
|
+
|
392
|
+
result = ClaudeCodeSDK.quick_mcp_query(
|
393
|
+
"Test prompt",
|
394
|
+
server_name: "test",
|
395
|
+
server_url: "http://test.com",
|
396
|
+
tools: "about"
|
397
|
+
)
|
398
|
+
|
399
|
+
expect(result).to include(have_attributes(class: ClaudeCodeSDK::AssistantMessage))
|
400
|
+
end
|
401
|
+
end
|
402
|
+
```
|
403
|
+
|
404
|
+
The MCP integration provides a powerful way to extend Claude's capabilities with custom tools while maintaining the same streaming performance and ergonomic API as the core SDK.
|