Skip to content

Commit 4dc2ef9

Browse files
committed
support ruby version 3.1 again, only run mcp specs on 3.2 >. Improved docs and references to adapters being in +1.0
1 parent 0e75779 commit 4dc2ef9

File tree

21 files changed

+400
-382
lines changed

21 files changed

+400
-382
lines changed

.github/workflows/cicd.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
runs-on: ubuntu-latest
1212
strategy:
1313
matrix:
14-
ruby: ['3.2', '3.3', '3.4']
14+
ruby: ['3.1', '3.2', '3.3', '3.4']
1515

1616
steps:
1717
- uses: actions/checkout@v4

.rubocop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins:
66

77
AllCops:
88
NewCops: enable
9-
TargetRubyVersion: 3.2
9+
TargetRubyVersion: 3.1
1010
Exclude:
1111
- 'vendor/**/*'
1212
- 'bin/**/*'

Gemfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ source "https://rubygems.org"
55
gemspec
66

77
group :development do
8-
gem "mcp", "~> 0.4"
8+
if RUBY_VERSION >= "3.2.0"
9+
gem "mcp", "~> 0.4"
10+
end
911

1012
# Development dependencies
1113
gem "activesupport"

docs/guides/adapters.md

Lines changed: 233 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
---
22
layout: default
3-
title: Adapters
3+
title: Adapters & Transports
44
parent: Guides
5-
nav_order: 5
6-
description: "Understanding and using MCP adapters in RubyLLM"
5+
nav_order: 4
6+
description: "Understanding MCP adapters, transports, and building custom transport implementations"
77
---
88

9-
# Adapters
9+
# Adapters & Transports
1010
{: .no_toc }
1111

1212
{: .label .label-green }
13-
0.8+
13+
1.0+
1414

15-
Starting with version 0.8.0, RubyLLM MCP supports multiple SDK adapters, allowing you to choose between the native full-featured implementation or the official MCP SDK.
15+
RubyLLM MCP 1.0 provides a mature, stable adapter system with multiple SDK implementations and transport types, giving you complete control over how your application communicates with MCP servers.
1616

1717
## Table of contents
1818
{: .no_toc .text-delta }
@@ -24,43 +24,48 @@ Starting with version 0.8.0, RubyLLM MCP supports multiple SDK adapters, allowin
2424

2525
## Overview
2626

27-
The adapter pattern in RubyLLM MCP allows you to choose which SDK implementation powers your MCP clients. This gives you flexibility to:
27+
RubyLLM MCP provides two key architectural components:
2828

29-
- Use the native `:ruby_llm` adapter for full MCP feature support build inside the gem
30-
- Use the official `:mcp_sdk` adapter (still under development, but making great progress)
29+
**Adapters** - Choose which SDK implementation powers your MCP clients:
30+
- Use the native `:ruby_llm` adapter for full MCP feature support built inside the gem
31+
- Use the official `:mcp_sdk` adapter maintained by Anthropic (requires Ruby 3.2+)
3132
- Mix both adapters in the same application for different servers
3233

34+
**Transports** - Handle the communication layer between your Ruby client and MCP servers:
35+
- Establish connections
36+
- Send requests and receive responses
37+
- Manage the connection lifecycle
38+
- Handle protocol-specific details
39+
3340
## Available Adapters
3441

3542
### RubyLLM Adapter (`:ruby_llm`)
3643

3744
The default, full-featured adapter that implements the complete MCP protocol with extensions.
3845

39-
**When to use:**
40-
- You need advanced features like sampling, roots, or progress tracking
41-
- You want SSE transport support
42-
- You need human-in-the-loop approvals
43-
- You're using elicitation for interactive workflows
46+
**Key Features:**
47+
- ✅ Complete MCP protocol implementation with advanced features (sampling, roots, progress tracking, elicitation)
48+
- ✅ All transport types supported (stdio, SSE, streamable HTTP)
49+
- **Custom transport support** - Register and use your own transport implementations
50+
- ✅ Ruby 2.7+ compatible
4451

45-
**Advantages:**
46-
- Complete MCP protocol implementation
47-
- All transport types supported
48-
- Additional features beyond core spec
49-
- Optimized for RubyLLM integration
52+
**Best for:** Full-featured MCP integrations, custom transport requirements, and advanced protocol features.
5053

5154
### MCP SDK Adapter (`:mcp_sdk`)
5255

5356
Wraps the official MCP SDK maintained by Anthropic.
5457

55-
**When to use:**
56-
- You prefer the official Anthropic-maintained implementation
57-
- You only need core MCP features (tools, resources, prompts)
58-
- You want to ensure compatibility with the reference implementation
58+
{: .important }
59+
> **Ruby 3.2+ Required**
60+
> The official `mcp` gem requires Ruby 3.2 or higher. If you're using an older Ruby version, use the `:ruby_llm` adapter instead.
61+
62+
**Key Features:**
63+
- ✅ Official Anthropic-maintained implementation
64+
- ✅ Core MCP features (tools, resources, prompts)
65+
- ✅ Basic transports (stdio, HTTP) with custom wrapper support
66+
- ⚠️ No custom transport registration - requires Ruby 3.2+
5967

60-
**Advantages:**
61-
- Official Anthropic support
62-
- Reference implementation compatibility
63-
- Simpler, focused feature set
68+
**Best for:** Reference implementation compatibility and core MCP features only.
6469

6570
## Feature Comparison
6671

@@ -98,6 +103,113 @@ Custom transports are implemented by the adapter and are not part of the officia
98103
| `:streamable_http` || Custom |
99104
| `:sse` || Custom |
100105

106+
---
107+
108+
## Built-in Transport Types
109+
110+
### STDIO Transport
111+
112+
Best for local MCP servers that communicate via standard input/output:
113+
114+
```ruby
115+
client = RubyLLM::MCP.client(
116+
name: "local-server",
117+
transport_type: :stdio,
118+
config: {
119+
command: "python",
120+
args: ["-m", "my_mcp_server"],
121+
env: { "DEBUG" => "1" }
122+
}
123+
)
124+
```
125+
126+
**Use cases:**
127+
128+
- Local development
129+
- Command-line MCP servers
130+
- Subprocess-based servers
131+
132+
### SSE Transport (Server-Sent Events)
133+
134+
Best for web-based MCP servers using HTTP with server-sent events:
135+
136+
```ruby
137+
client = RubyLLM::MCP.client(
138+
name: "web-server",
139+
transport_type: :sse,
140+
config: {
141+
url: "https://api.example.com/mcp/sse",
142+
version: :http2, # You can force HTTP/1.1 by setting this to :http1, default will try to setup HTTP/2 connection
143+
headers: { "Authorization" => "Bearer token" }
144+
}
145+
)
146+
```
147+
148+
**Use cases:**
149+
150+
- Web-based MCP services
151+
- Real-time communication needs
152+
- HTTP-based infrastructure
153+
154+
### Streamable HTTP Transport
155+
156+
Best for HTTP-based MCP servers that support streaming responses:
157+
158+
```ruby
159+
client = RubyLLM::MCP.client(
160+
name: "streaming-server",
161+
transport_type: :streamable,
162+
config: {
163+
url: "https://api.example.com/mcp",
164+
version: :http2, # You can force HTTP/1.1 by setting this to :http1, default will try to setup HTTP/2 connection
165+
headers: { "Content-Type" => "application/json" }
166+
}
167+
)
168+
```
169+
170+
#### OAuth Authentication
171+
172+
{: .new }
173+
OAuth authentication is available in MCP Protocol 2025-06-18 for Streamable HTTP transport.
174+
175+
For servers requiring OAuth authentication:
176+
177+
```ruby
178+
client = RubyLLM::MCP.client(
179+
name: "oauth-server",
180+
transport_type: :streamable,
181+
config: {
182+
url: "https://api.example.com/mcp",
183+
oauth: {
184+
issuer: "https://oauth.provider.com",
185+
client_id: "your-client-id",
186+
client_secret: "your-client-secret",
187+
scope: "mcp:read mcp:write" # Optional
188+
}
189+
}
190+
)
191+
```
192+
193+
**OAuth Configuration:**
194+
195+
| Option | Description | Required |
196+
|--------|-------------|----------|
197+
| `issuer` | OAuth provider's issuer URL | Yes |
198+
| `client_id` | OAuth client identifier | Yes |
199+
| `client_secret` | OAuth client secret | Yes |
200+
| `scope` | Requested OAuth scopes | No |
201+
202+
The client automatically handles token acquisition, refresh, and authorization headers.
203+
204+
**Use cases:**
205+
206+
- REST API-based MCP servers
207+
- HTTP-first architectures
208+
- Cloud-based MCP services
209+
- Enterprise servers requiring OAuth
210+
211+
---
212+
101213
## Configuration
102214

103215
### Global Default Adapter
@@ -163,11 +275,15 @@ mcp_servers:
163275
164276
### Installation
165277
278+
{: .warning }
279+
> **Ruby 3.2+ Required**
280+
> The official `mcp` gem requires Ruby 3.2 or higher. Ensure your Ruby version is compatible before proceeding.
281+
166282
The official MCP SDK is an optional dependency. Add it to your Gemfile when using the `:mcp_sdk` adapter:
167283

168284
```ruby
169-
gem 'ruby_llm-mcp', '~> 0.8'
170-
gem 'mcp', '~> 0.4' # Required for mcp_sdk adapter
285+
gem 'ruby_llm-mcp', '~> 1.0'
286+
gem 'mcp', '~> 0.4' # Required for mcp_sdk adapter (Ruby 3.2+)
171287
```
172288

173289
Then run:
@@ -298,6 +414,77 @@ RubyLLM::MCP.establish_connection do |clients|
298414
end
299415
```
300416

417+
---
418+
419+
## Custom Transports
420+
421+
{: .label .label-blue }
422+
RubyLLM Adapter Only
423+
424+
The `:ruby_llm` adapter supports registering custom transport implementations, allowing you to extend the gem with your own communication protocols.
425+
426+
### Transport Interface
427+
428+
All transport implementations must implement the following interface:
429+
430+
```ruby
431+
class CustomTransport
432+
# Initialize the transport
433+
def initialize(coordinator:, **config)
434+
@coordinator = coordinator
435+
@config = config
436+
end
437+
438+
# Send a request and optionally wait for response
439+
def request(body, add_id: true, wait_for_response: true)
440+
# Implementation specific
441+
end
442+
443+
# Check if transport is alive/connected
444+
def alive?
445+
# Implementation specific
446+
end
447+
448+
# Start the transport connection
449+
def start
450+
# Implementation specific
451+
end
452+
453+
# Close the transport connection
454+
def close
455+
# Implementation specific
456+
end
457+
458+
# Set the MCP protocol version
459+
def set_protocol_version(version)
460+
@protocol_version = version
461+
end
462+
end
463+
```
464+
465+
### Registering Custom Transports
466+
467+
Once you've created a custom transport, register it with the transport factory:
468+
469+
```ruby
470+
# Register your custom transport
471+
RubyLLM::MCP::Native::Transport.register_transport(:websocket, WebSocketTransport)
472+
RubyLLM::MCP::Native::Transport.register_transport(:redis_pubsub, RedisPubSubTransport)
473+
474+
# Now you can use it with any client using the ruby_llm adapter
475+
client = RubyLLM::MCP.client(
476+
name: "websocket-server",
477+
adapter: :ruby_llm, # Custom transports only work with ruby_llm adapter
478+
transport_type: :websocket,
479+
config: {
480+
url: "ws://localhost:8080/mcp",
481+
headers: { "Authorization" => "Bearer token" }
482+
}
483+
)
484+
```
485+
486+
---
487+
301488
## Best Practices
302489

303490
### Choosing an Adapter
@@ -306,22 +493,16 @@ end
306493
2. **Use `:mcp_sdk`** when you specifically need the official implementation
307494
3. **Check feature requirements** before choosing an adapter
308495
4. **Consider transport needs** - SSE requires `:ruby_llm`
496+
5. **Check Ruby version** - `:mcp_sdk` requires Ruby 3.2+
309497

310-
### Performance Considerations
498+
### Upgrading from 1.0
311499

312-
- Both adapters have similar performance for core operations
313-
- `:ruby_llm` has additional overhead for advanced features when enabled
314-
- `:mcp_sdk` is lighter if you only need core functionality
315-
316-
### Upgrading from 0.7
317-
318-
If you're upgrading from version 0.7:
500+
If you're upgrading from version 1.0:
319501

320502
1. The default adapter is `:ruby_llm` - no changes needed for existing code
321503
2. All existing features continue to work as before
322504
3. Optionally migrate specific clients to `:mcp_sdk` if desired
323505

324-
See the [Upgrading from 0.7 to 0.8]({% link guides/upgrading-0.7-to-0.8.md %}) guide for detailed migration steps.
325506

326507
## Troubleshooting
327508

@@ -347,11 +528,23 @@ If you see "LoadError: cannot load such file -- mcp":
347528

348529
1. Add `gem 'mcp', '~> 0.4'` to your Gemfile
349530
2. Run `bundle install`
350-
3. This is only needed when using `adapter: :mcp_sdk`
531+
3. Ensure you're running Ruby 3.2 or higher
532+
4. This is only needed when using `adapter: :mcp_sdk`
533+
534+
### Ruby Version Compatibility
535+
536+
If you encounter issues with the `:mcp_sdk` adapter:
537+
538+
1. Check your Ruby version: `ruby -v`
539+
2. The `mcp` gem requires Ruby 3.2 or higher
540+
3. Switch to `:ruby_llm` adapter if you're on an older Ruby version
541+
4. Consider upgrading Ruby if you need the official SDK
351542

352543
## Next Steps
353544

354545
- **[Configuration]({% link configuration.md %})** - Detailed configuration options
546+
- **[Getting Started]({% link guides/getting-started.md %})** - Quick start guide
355547
- **[Tools]({% link server/tools.md %})** - Working with MCP tools
356548
- **[Resources]({% link server/resources.md %})** - Managing resources
357-
- **[Upgrading]({% link guides/upgrading-0.7-to-0.8.md %})** - Migration guide
549+
- **[Notifications]({% link server/notifications.md %})** - Handling real-time updates
550+
- **[Upgrading from 0.8 to 1.0]({% link guides/upgrading-0.8-to-1.0.md %})** - Migration guide

0 commit comments

Comments
 (0)