ruby_llm-mcp 0.8.0 → 1.0.0
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 +4 -4
- data/README.md +144 -162
- data/lib/generators/ruby_llm/mcp/install/templates/initializer.rb +21 -4
- data/lib/generators/ruby_llm/mcp/install/templates/mcps.yml +20 -0
- data/lib/ruby_llm/mcp/adapters/base_adapter.rb +215 -0
- data/lib/ruby_llm/mcp/adapters/mcp_sdk_adapter.rb +413 -0
- data/lib/ruby_llm/mcp/adapters/mcp_transports/coordinator_stub.rb +41 -0
- data/lib/ruby_llm/mcp/adapters/mcp_transports/sse.rb +56 -0
- data/lib/ruby_llm/mcp/adapters/mcp_transports/stdio.rb +56 -0
- data/lib/ruby_llm/mcp/adapters/mcp_transports/streamable_http.rb +90 -0
- data/lib/ruby_llm/mcp/adapters/ruby_llm_adapter.rb +216 -0
- data/lib/ruby_llm/mcp/auth/browser/callback_server.rb +7 -1
- data/lib/ruby_llm/mcp/auth/browser/http_server.rb +0 -3
- data/lib/ruby_llm/mcp/auth/browser/opener.rb +0 -2
- data/lib/ruby_llm/mcp/auth/browser/pages.rb +100 -32
- data/lib/ruby_llm/mcp/auth/browser_oauth_provider.rb +230 -57
- data/lib/ruby_llm/mcp/auth/discoverer.rb +157 -26
- data/lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb +19 -2
- data/lib/ruby_llm/mcp/auth/flows/client_credentials_flow.rb +3 -2
- data/lib/ruby_llm/mcp/auth/http_response_handler.rb +0 -2
- data/lib/ruby_llm/mcp/auth/memory_storage.rb +31 -12
- data/lib/ruby_llm/mcp/auth/oauth_provider.rb +124 -9
- data/lib/ruby_llm/mcp/auth/session_manager.rb +0 -2
- data/lib/ruby_llm/mcp/auth/token_manager.rb +74 -3
- data/lib/ruby_llm/mcp/auth/transport_oauth_helper.rb +107 -0
- data/lib/ruby_llm/mcp/auth/url_builder.rb +72 -15
- data/lib/ruby_llm/mcp/auth.rb +19 -7
- data/lib/ruby_llm/mcp/client.rb +267 -39
- data/lib/ruby_llm/mcp/configuration.rb +161 -12
- data/lib/ruby_llm/mcp/elicitation.rb +261 -14
- data/lib/ruby_llm/mcp/errors.rb +18 -0
- data/lib/ruby_llm/mcp/extensions/apps/constants.rb +28 -0
- data/lib/ruby_llm/mcp/extensions/apps/resource_metadata.rb +24 -0
- data/lib/ruby_llm/mcp/extensions/apps/tool_metadata.rb +45 -0
- data/lib/ruby_llm/mcp/extensions/configuration.rb +72 -0
- data/lib/ruby_llm/mcp/extensions/constants.rb +16 -0
- data/lib/ruby_llm/mcp/extensions/registry.rb +85 -0
- data/lib/ruby_llm/mcp/handlers/approval_decision.rb +90 -0
- data/lib/ruby_llm/mcp/handlers/async_response.rb +181 -0
- data/lib/ruby_llm/mcp/handlers/concerns/approval_actions.rb +42 -0
- data/lib/ruby_llm/mcp/handlers/concerns/async_execution.rb +80 -0
- data/lib/ruby_llm/mcp/handlers/concerns/elicitation_actions.rb +42 -0
- data/lib/ruby_llm/mcp/handlers/concerns/error_handling.rb +29 -0
- data/lib/ruby_llm/mcp/handlers/concerns/guard_checks.rb +72 -0
- data/lib/ruby_llm/mcp/handlers/concerns/lifecycle.rb +84 -0
- data/lib/ruby_llm/mcp/handlers/concerns/logging.rb +19 -0
- data/lib/ruby_llm/mcp/handlers/concerns/model_filtering.rb +36 -0
- data/lib/ruby_llm/mcp/handlers/concerns/options.rb +83 -0
- data/lib/ruby_llm/mcp/handlers/concerns/registry_integration.rb +54 -0
- data/lib/ruby_llm/mcp/handlers/concerns/sampling_actions.rb +84 -0
- data/lib/ruby_llm/mcp/handlers/concerns/timeouts.rb +52 -0
- data/lib/ruby_llm/mcp/handlers/concerns/tool_filtering.rb +50 -0
- data/lib/ruby_llm/mcp/handlers/elicitation_handler.rb +58 -0
- data/lib/ruby_llm/mcp/handlers/elicitation_registry.rb +203 -0
- data/lib/ruby_llm/mcp/handlers/human_in_the_loop_handler.rb +93 -0
- data/lib/ruby_llm/mcp/handlers/human_in_the_loop_registry.rb +271 -0
- data/lib/ruby_llm/mcp/handlers/promise.rb +192 -0
- data/lib/ruby_llm/mcp/handlers/sampling_handler.rb +64 -0
- data/lib/ruby_llm/mcp/handlers.rb +14 -0
- data/lib/ruby_llm/mcp/native/cancellable_operation.rb +94 -0
- data/lib/ruby_llm/mcp/native/client.rb +551 -0
- data/lib/ruby_llm/mcp/native/json_rpc.rb +170 -0
- data/lib/ruby_llm/mcp/native/messages/helpers.rb +39 -0
- data/lib/ruby_llm/mcp/native/messages/notifications.rb +60 -0
- data/lib/ruby_llm/mcp/native/messages/requests.rb +267 -0
- data/lib/ruby_llm/mcp/native/messages/responses.rb +114 -0
- data/lib/ruby_llm/mcp/native/messages.rb +43 -0
- data/lib/ruby_llm/mcp/native/notification.rb +16 -0
- data/lib/ruby_llm/mcp/native/protocol.rb +79 -0
- data/lib/ruby_llm/mcp/native/response_handler.rb +220 -0
- data/lib/ruby_llm/mcp/native/task_registry.rb +62 -0
- data/lib/ruby_llm/mcp/native/transport.rb +88 -0
- data/lib/ruby_llm/mcp/native/transports/sse.rb +655 -0
- data/lib/ruby_llm/mcp/native/transports/stdio.rb +367 -0
- data/lib/ruby_llm/mcp/native/transports/streamable_http.rb +1024 -0
- data/lib/ruby_llm/mcp/native/transports/support/http_client.rb +28 -0
- data/lib/ruby_llm/mcp/native/transports/support/rate_limiter.rb +49 -0
- data/lib/ruby_llm/mcp/native/transports/support/timeout.rb +36 -0
- data/lib/ruby_llm/mcp/native.rb +12 -0
- data/lib/ruby_llm/mcp/notification_handler.rb +43 -5
- data/lib/ruby_llm/mcp/prompt.rb +7 -7
- data/lib/ruby_llm/mcp/railtie.rb +8 -6
- data/lib/ruby_llm/mcp/resource.rb +17 -8
- data/lib/ruby_llm/mcp/resource_template.rb +8 -7
- data/lib/ruby_llm/mcp/result.rb +8 -4
- data/lib/ruby_llm/mcp/roots.rb +4 -4
- data/lib/ruby_llm/mcp/sample.rb +83 -13
- data/lib/ruby_llm/mcp/schema_validator.rb +33 -0
- data/lib/ruby_llm/mcp/server_capabilities.rb +41 -0
- data/lib/ruby_llm/mcp/task.rb +65 -0
- data/lib/ruby_llm/mcp/tool.rb +33 -27
- data/lib/ruby_llm/mcp/version.rb +1 -1
- data/lib/ruby_llm/mcp.rb +31 -7
- data/lib/tasks/smoke.rake +66 -0
- metadata +77 -36
- data/lib/ruby_llm/mcp/coordinator.rb +0 -304
- data/lib/ruby_llm/mcp/notifications/cancelled.rb +0 -32
- data/lib/ruby_llm/mcp/notifications/initialize.rb +0 -24
- data/lib/ruby_llm/mcp/notifications/roots_list_change.rb +0 -26
- data/lib/ruby_llm/mcp/protocol.rb +0 -34
- data/lib/ruby_llm/mcp/requests/completion_prompt.rb +0 -50
- data/lib/ruby_llm/mcp/requests/completion_resource.rb +0 -50
- data/lib/ruby_llm/mcp/requests/initialization.rb +0 -34
- data/lib/ruby_llm/mcp/requests/logging_set_level.rb +0 -28
- data/lib/ruby_llm/mcp/requests/ping.rb +0 -24
- data/lib/ruby_llm/mcp/requests/prompt_call.rb +0 -32
- data/lib/ruby_llm/mcp/requests/prompt_list.rb +0 -31
- data/lib/ruby_llm/mcp/requests/resource_list.rb +0 -31
- data/lib/ruby_llm/mcp/requests/resource_read.rb +0 -30
- data/lib/ruby_llm/mcp/requests/resource_template_list.rb +0 -31
- data/lib/ruby_llm/mcp/requests/resources_subscribe.rb +0 -30
- data/lib/ruby_llm/mcp/requests/shared/meta.rb +0 -32
- data/lib/ruby_llm/mcp/requests/shared/pagination.rb +0 -17
- data/lib/ruby_llm/mcp/requests/tool_call.rb +0 -35
- data/lib/ruby_llm/mcp/requests/tool_list.rb +0 -31
- data/lib/ruby_llm/mcp/response_handler.rb +0 -67
- data/lib/ruby_llm/mcp/responses/elicitation.rb +0 -33
- data/lib/ruby_llm/mcp/responses/error.rb +0 -33
- data/lib/ruby_llm/mcp/responses/ping.rb +0 -28
- data/lib/ruby_llm/mcp/responses/roots_list.rb +0 -31
- data/lib/ruby_llm/mcp/responses/sampling_create_message.rb +0 -50
- data/lib/ruby_llm/mcp/transport.rb +0 -151
- data/lib/ruby_llm/mcp/transports/sse.rb +0 -435
- data/lib/ruby_llm/mcp/transports/stdio.rb +0 -231
- data/lib/ruby_llm/mcp/transports/streamable_http.rb +0 -725
- data/lib/ruby_llm/mcp/transports/support/http_client.rb +0 -28
- data/lib/ruby_llm/mcp/transports/support/rate_limit.rb +0 -47
- data/lib/ruby_llm/mcp/transports/support/timeout.rb +0 -34
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a516cd88de84929d95dbaaea467780ba499dc8362001a02d00ac0c8672107506
|
|
4
|
+
data.tar.gz: b852e278be156403a32454a00fa4ad450491d219d6243d9629098680576056d2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a63c3650a2db47782d7db7eae32feec794302e63f2fe9967a584d1253fb42de75dfe004c87ba8758e9c09d06be856dc0d645183d0fc5b80e18a0cb294c5cda68
|
|
7
|
+
data.tar.gz: a89b6bffe3d03b95a9b2734c39f8b6152c7a07f945a9fe70f6eb3f3cb5423939a4fa7e16de2db94e5b01acdc82fde6b0d0d7eadcf4ce94ebd91a6654fa65565f
|
data/README.md
CHANGED
|
@@ -1,235 +1,217 @@
|
|
|
1
|
-
<
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<img src="docs/assets/images/rubyllm-mcp-logo-text.svg#gh-light-mode-only" alt="RubyLLM::MCP" height="120" width="250">
|
|
4
|
+
<img src="docs/assets/images/rubyllm-mcp-logo-text-white.svg#gh-dark-mode-only" alt="RubyLLM::MCP" height="120" width="250">
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
<strong>MCP for Ruby and RubyLLM, as easy as possible.</strong>
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
[](https://badge.fury.io/rb/ruby_llm-mcp)
|
|
9
|
+
[](https://rubygems.org/gems/ruby_llm-mcp)
|
|
8
10
|
|
|
9
|
-
Currently full support for MCP protocol version up to `2025-06-18`.
|
|
10
|
-
|
|
11
|
-
<div class="badge-container">
|
|
12
|
-
<a href="https://badge.fury.io/rb/ruby_llm-mcp"><img src="https://badge.fury.io/rb/ruby_llm-mcp.svg" alt="Gem Version" /></a>
|
|
13
|
-
<a href="https://rubygems.org/gems/ruby_llm-mcp"><img alt="Gem Downloads" src="https://img.shields.io/gem/dt/ruby_llm-mcp"></a>
|
|
14
11
|
</div>
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- 🔌 **Multiple Transport Types**: Streamable HTTP, and STDIO and legacy SSE transports
|
|
19
|
-
- 🛠️ **Tool Integration**: Automatically converts MCP tools into RubyLLM-compatible tools
|
|
20
|
-
- 📄 **Resource Management**: Access and include MCP resources (files, data) and resource templates in conversations
|
|
21
|
-
- 🎯 **Prompt Integration**: Use predefined MCP prompts with arguments for consistent interactions
|
|
22
|
-
- 🎛️ **Client Features**: Support for sampling, roots, and elicitation
|
|
23
|
-
- 🎨 **Enhanced Chat Interface**: Extended RubyLLM chat methods for seamless MCP integration
|
|
24
|
-
- 🔄 **Multiple Client Management**: Create and manage multiple MCP clients simultaneously for different servers and purposes
|
|
25
|
-
- 📚 **Simple API**: Easy-to-use interface that integrates seamlessly with RubyLLM
|
|
13
|
+
RubyLLM::MCP is a Ruby client for the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/), built to work cleanly with [RubyLLM](https://github.com/crmne/ruby_llm). Aiming to be completely spec compliant.
|
|
26
14
|
|
|
27
|
-
|
|
15
|
+
Use MCP tools, resources, and prompts from your RubyLLM chats over `stdio`, streamable HTTP, or SSE.
|
|
28
16
|
|
|
29
|
-
|
|
30
|
-
bundle add ruby_llm-mcp
|
|
31
|
-
```
|
|
17
|
+
**Protocol support:** Fully supports MCP spec `2025-06-18` (stable), with draft spec `2026-01-26` available.
|
|
32
18
|
|
|
33
|
-
|
|
19
|
+
## RubyLLM::MCP Out of the Box
|
|
34
20
|
|
|
35
|
-
|
|
36
|
-
gem 'ruby_llm-mcp'
|
|
37
|
-
```
|
|
21
|
+
Our goal is to be able to plug MCP into Ruby/RubyLLM apps as easily as possible.
|
|
38
22
|
|
|
39
|
-
|
|
23
|
+
RubyLLM::MCP gives you that:
|
|
40
24
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
25
|
+
- Ruby-first API for using MCP tools, resources, and prompts directly in RubyLLM chat workflows
|
|
26
|
+
- Stable protocol track by default (`2025-06-18`), with opt-in draft track (`2026-01-26`)
|
|
27
|
+
- Built-in notification and response handlers for real-time and interactive workflows
|
|
28
|
+
- MCP OAuth 2.1 authentication support (PKCE, dynamic registration, discovery, and automatic token refresh)
|
|
29
|
+
- OAuth setup paths for Rails apps (per-user connections) and browser-based CLI flows
|
|
30
|
+
- Straightforward integration for any Ruby app, background job, or Rails project using RubyLLM
|
|
44
31
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
gem install ruby_llm-mcp
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Usage
|
|
52
|
-
|
|
53
|
-
### Basic Setup
|
|
54
|
-
|
|
55
|
-
First, configure your RubyLLM client and create an MCP connection:
|
|
32
|
+
## Show me the code
|
|
56
33
|
|
|
57
34
|
```ruby
|
|
58
|
-
|
|
35
|
+
# Basic setup
|
|
36
|
+
require "ruby_llm/mcp"
|
|
59
37
|
|
|
60
|
-
# Configure RubyLLM
|
|
61
38
|
RubyLLM.configure do |config|
|
|
62
|
-
config.openai_api_key = "
|
|
39
|
+
config.openai_api_key = ENV.fetch("OPENAI_API_KEY")
|
|
63
40
|
end
|
|
64
41
|
|
|
65
|
-
# Connect to an MCP server via SSE
|
|
66
42
|
client = RubyLLM::MCP.client(
|
|
67
|
-
name: "
|
|
68
|
-
transport_type: :sse,
|
|
69
|
-
config: {
|
|
70
|
-
url: "http://localhost:9292/mcp/sse"
|
|
71
|
-
}
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
# Or connect via stdio
|
|
75
|
-
client = RubyLLM::MCP.client(
|
|
76
|
-
name: "my-mcp-server",
|
|
43
|
+
name: "filesystem",
|
|
77
44
|
transport_type: :stdio,
|
|
78
45
|
config: {
|
|
79
|
-
command: "
|
|
80
|
-
args: ["
|
|
81
|
-
env: { "NODE_ENV" => "production" }
|
|
46
|
+
command: "bunx",
|
|
47
|
+
args: ["@modelcontextprotocol/server-filesystem", Dir.pwd]
|
|
82
48
|
}
|
|
83
49
|
)
|
|
84
50
|
|
|
85
|
-
|
|
86
|
-
client
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
51
|
+
chat = RubyLLM.chat(model: "gpt-4.1-mini")
|
|
52
|
+
chat.with_tools(*client.tools)
|
|
53
|
+
|
|
54
|
+
puts chat.ask("Find Ruby files modified today and summarize what changed.")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
# Resources
|
|
59
|
+
resource = client.resource("release_notes")
|
|
60
|
+
chat = RubyLLM.chat(model: "gpt-4.1-mini")
|
|
61
|
+
chat.with_resource(resource)
|
|
62
|
+
|
|
63
|
+
puts chat.ask("Summarize release notes for the team in 5 bullet points.")
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
# Prompts
|
|
68
|
+
prompt = client.prompt("code_review")
|
|
69
|
+
chat = RubyLLM.chat(model: "gpt-4.1-mini")
|
|
70
|
+
|
|
71
|
+
response = chat.ask_prompt(
|
|
72
|
+
prompt,
|
|
73
|
+
arguments: {
|
|
74
|
+
language: "ruby",
|
|
75
|
+
focus: "security"
|
|
92
76
|
}
|
|
93
77
|
)
|
|
94
|
-
```
|
|
95
78
|
|
|
96
|
-
|
|
79
|
+
puts response
|
|
80
|
+
```
|
|
97
81
|
|
|
98
82
|
```ruby
|
|
99
|
-
#
|
|
100
|
-
|
|
101
|
-
puts "
|
|
102
|
-
tools.each do |tool|
|
|
103
|
-
puts "- #{tool.name}: #{tool.description}"
|
|
83
|
+
# Handlers (response + notifications)
|
|
84
|
+
client.on_progress do |progress|
|
|
85
|
+
puts "Progress: #{progress.progress}% - #{progress.message}"
|
|
104
86
|
end
|
|
105
87
|
|
|
106
|
-
|
|
107
|
-
|
|
88
|
+
client.on_logging do |logging|
|
|
89
|
+
puts "[#{logging.level}] #{logging.message}"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
chat = RubyLLM.chat(model: "gpt-4.1-mini")
|
|
108
93
|
chat.with_tools(*client.tools)
|
|
109
94
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
95
|
+
chat.ask("Run a repository scan and summarize risks.") do |chunk|
|
|
96
|
+
print chunk.content
|
|
97
|
+
end
|
|
113
98
|
```
|
|
114
99
|
|
|
115
|
-
### Manual Tool Execution
|
|
116
|
-
|
|
117
|
-
You can also execute MCP tools directly:
|
|
118
|
-
|
|
119
100
|
```ruby
|
|
120
|
-
#
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
101
|
+
# OAuth setup (Rails and CLI)
|
|
102
|
+
# Rails: per-user OAuth client (after running rails generate ruby_llm:mcp:oauth:install User)
|
|
103
|
+
client = current_user.mcp_client
|
|
104
|
+
chat = RubyLLM.chat(model: "gpt-4.1-mini")
|
|
105
|
+
chat.with_tools(*client.tools)
|
|
106
|
+
puts chat.ask("What changed in my connected repos this week?")
|
|
107
|
+
|
|
108
|
+
# CLI: browser-based OAuth flow
|
|
109
|
+
cli_client = RubyLLM::MCP.client(
|
|
110
|
+
name: "oauth-server",
|
|
111
|
+
transport_type: :streamable,
|
|
112
|
+
start: false,
|
|
113
|
+
config: {
|
|
114
|
+
url: ENV.fetch("MCP_SERVER_URL"),
|
|
115
|
+
oauth: { scope: "mcp:read mcp:write" }
|
|
129
116
|
}
|
|
130
117
|
)
|
|
131
118
|
|
|
132
|
-
|
|
119
|
+
cli_client.oauth(type: :browser).authenticate
|
|
120
|
+
cli_client.start
|
|
121
|
+
puts RubyLLM.chat(model: "gpt-4.1-mini").with_tools(*cli_client.tools).ask("List my open tasks.")
|
|
122
|
+
cli_client.stop
|
|
133
123
|
```
|
|
134
124
|
|
|
135
|
-
|
|
125
|
+
## Features
|
|
126
|
+
|
|
127
|
+
- **Tools:** Convert MCP tools into RubyLLM-compatible tools
|
|
128
|
+
- **Resources:** Work with resources and resource templates in chat context
|
|
129
|
+
- **Prompts:** Execute server prompts with typed arguments
|
|
130
|
+
- **Transports:** `:stdio`, `:streamable`, and `:sse`
|
|
131
|
+
- **Client capabilities:** Sampling, roots, progress tracking, and elicitation
|
|
132
|
+
- **Handlers:** Built-in notification and response handlers for real-time and interactive workflows
|
|
133
|
+
- **MCP Authentication:** OAuth 2.1 support with PKCE, dynamic registration, discovery, and automatic token refresh
|
|
134
|
+
- **OAuth setup paths:** Rails per-user OAuth setup and browser-based OAuth for CLI tools
|
|
135
|
+
- **Extensions:** Global/per-client extension negotiation, including MCP Apps
|
|
136
|
+
- **Multi-client support:** Manage multiple MCP servers in one workflow
|
|
137
|
+
- **Protocol control:** Stable default with explicit draft opt-in
|
|
138
|
+
- **Adapters:** Native `:ruby_llm` adapter (full feature set) and optional `:mcp_sdk`
|
|
136
139
|
|
|
137
|
-
|
|
140
|
+
## Installation
|
|
138
141
|
|
|
139
|
-
|
|
142
|
+
Add to your Gemfile:
|
|
140
143
|
|
|
141
144
|
```ruby
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
puts "Available resources:"
|
|
145
|
-
resources.each do |resource|
|
|
146
|
-
puts "- #{resource.name}: #{resource.description}"
|
|
147
|
-
end
|
|
145
|
+
gem "ruby_llm-mcp"
|
|
146
|
+
```
|
|
148
147
|
|
|
149
|
-
|
|
150
|
-
file_resource = client.resource("project_readme")
|
|
151
|
-
content = file_resource.content
|
|
152
|
-
puts "Resource content: #{content}"
|
|
148
|
+
Then run:
|
|
153
149
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
```bash
|
|
151
|
+
bundle install
|
|
152
|
+
```
|
|
157
153
|
|
|
158
|
-
|
|
159
|
-
file_resource.include(chat)
|
|
154
|
+
If you want the official SDK adapter, also add:
|
|
160
155
|
|
|
161
|
-
|
|
162
|
-
|
|
156
|
+
```ruby
|
|
157
|
+
gem "mcp", "~> 0.7"
|
|
163
158
|
```
|
|
164
159
|
|
|
165
|
-
|
|
160
|
+
## Rails
|
|
166
161
|
|
|
167
|
-
|
|
162
|
+
```bash
|
|
163
|
+
rails generate ruby_llm:mcp:install
|
|
164
|
+
```
|
|
168
165
|
|
|
169
|
-
|
|
170
|
-
# Get available resource templates
|
|
171
|
-
templates = client.resource_templates
|
|
172
|
-
log_template = client.resource_template("application_logs")
|
|
173
|
-
|
|
174
|
-
# Use a template with parameters
|
|
175
|
-
chat = RubyLLM.chat(model: "gpt-4")
|
|
176
|
-
chat.with_resource_template(log_template, arguments: {
|
|
177
|
-
date: "2024-01-15",
|
|
178
|
-
level: "error"
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
response = chat.ask("What errors occurred on this date?")
|
|
182
|
-
puts response
|
|
166
|
+
For OAuth-based user connections:
|
|
183
167
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
date: "2024-01-15",
|
|
187
|
-
level: "error"
|
|
188
|
-
})
|
|
189
|
-
puts content
|
|
168
|
+
```bash
|
|
169
|
+
rails generate ruby_llm:mcp:oauth:install User
|
|
190
170
|
```
|
|
191
171
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
MCP servers can provide predefined prompts that can be used in conversations:
|
|
172
|
+
OAuth quick example:
|
|
195
173
|
|
|
196
174
|
```ruby
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
175
|
+
client = RubyLLM::MCP.client(
|
|
176
|
+
name: "oauth-server",
|
|
177
|
+
transport_type: :streamable,
|
|
178
|
+
start: false,
|
|
179
|
+
config: {
|
|
180
|
+
url: ENV.fetch("MCP_SERVER_URL"),
|
|
181
|
+
oauth: { scope: "mcp:read mcp:write" }
|
|
182
|
+
}
|
|
183
|
+
)
|
|
206
184
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
chat = RubyLLM.chat(model: "gpt-4")
|
|
185
|
+
client.oauth(type: :browser).authenticate
|
|
186
|
+
client.start
|
|
210
187
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
puts
|
|
188
|
+
chat = RubyLLM.chat(model: "gpt-4.1-mini")
|
|
189
|
+
chat.with_tools(*client.tools)
|
|
190
|
+
puts chat.ask("What should I prioritize today?")
|
|
214
191
|
|
|
215
|
-
|
|
216
|
-
chat.with_prompt(greeting_prompt, arguments: { name: "Alice", time: "morning" })
|
|
217
|
-
response = chat.ask("Continue with the greeting")
|
|
192
|
+
client.stop
|
|
218
193
|
```
|
|
219
194
|
|
|
220
|
-
|
|
195
|
+
Then use explicit connection blocks in jobs/controllers/services:
|
|
221
196
|
|
|
222
|
-
|
|
197
|
+
```ruby
|
|
198
|
+
RubyLLM::MCP.establish_connection do |clients|
|
|
199
|
+
chat = RubyLLM.chat(model: "gpt-4.1-mini")
|
|
200
|
+
chat.with_tools(*clients.tools)
|
|
201
|
+
chat.ask("Analyze this pull request and list risks.")
|
|
202
|
+
end
|
|
203
|
+
```
|
|
223
204
|
|
|
224
|
-
|
|
205
|
+
## Documentation
|
|
225
206
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
207
|
+
- [rubyllm-mcp.com](https://rubyllm-mcp.com/)
|
|
208
|
+
- [Getting Started](https://rubyllm-mcp.com/getting-started/getting-started.html)
|
|
209
|
+
- [Rails Integration](https://rubyllm-mcp.com/guides/rails-integration.html)
|
|
210
|
+
- [Adapters and transports](https://rubyllm-mcp.com/guides/adapters.html)
|
|
229
211
|
|
|
230
212
|
## Contributing
|
|
231
213
|
|
|
232
|
-
|
|
214
|
+
Issues and pull requests are welcome at [patvice/ruby_llm-mcp](https://github.com/patvice/ruby_llm-mcp).
|
|
233
215
|
|
|
234
216
|
## License
|
|
235
217
|
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
# Configure RubyLLM MCP
|
|
4
4
|
RubyLLM::MCP.configure do |config|
|
|
5
|
+
# Default SDK adapter to use (:ruby_llm or :mcp_sdk)
|
|
6
|
+
# - :ruby_llm: Full-featured, supports all MCP features + extensions
|
|
7
|
+
# - :mcp_sdk: Official SDK, limited features but maintained by Anthropic
|
|
8
|
+
config.default_adapter = :ruby_llm
|
|
9
|
+
|
|
5
10
|
# Request timeout in milliseconds
|
|
6
11
|
config.request_timeout = 8000
|
|
7
12
|
|
|
@@ -17,23 +22,35 @@ RubyLLM::MCP.configure do |config|
|
|
|
17
22
|
# Launch MCPs (:automatic, :manual)
|
|
18
23
|
config.launch_control = :automatic
|
|
19
24
|
|
|
20
|
-
# Configure roots for file system access
|
|
25
|
+
# Configure roots for file system access (RubyLLM adapter only)
|
|
21
26
|
# config.roots = [
|
|
22
27
|
# Rails.root.to_s
|
|
23
28
|
# ]
|
|
24
29
|
|
|
25
|
-
# Configure sampling (
|
|
30
|
+
# Configure sampling (RubyLLM adapter only)
|
|
26
31
|
config.sampling.enabled = false
|
|
27
32
|
|
|
28
33
|
# Set preferred model for sampling
|
|
29
34
|
# config.sampling.preferred_model do
|
|
30
|
-
# # Return the preferred model name
|
|
31
35
|
# "claude-sonnet-4"
|
|
32
36
|
# end
|
|
33
37
|
|
|
34
38
|
# Set a guard for sampling
|
|
35
39
|
# config.sampling.guard do
|
|
36
|
-
# # Return true to enable sampling, false to disable
|
|
37
40
|
# Rails.env.development?
|
|
38
41
|
# end
|
|
42
|
+
|
|
43
|
+
# Event handlers (RubyLLM adapter only)
|
|
44
|
+
# config.on_progress do |progress_token, progress, total|
|
|
45
|
+
# # Handle progress updates
|
|
46
|
+
# end
|
|
47
|
+
|
|
48
|
+
# config.on_human_in_the_loop do |tool_name, arguments|
|
|
49
|
+
# # Return true to allow, false to deny
|
|
50
|
+
# true
|
|
51
|
+
# end
|
|
52
|
+
|
|
53
|
+
# config.on_logging do |level, logger_name, data|
|
|
54
|
+
# # Handle logging from MCP servers
|
|
55
|
+
# end
|
|
39
56
|
end
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
mcp_servers:
|
|
2
2
|
filesystem:
|
|
3
|
+
# SDK adapter to use (optional, defaults to config.default_adapter)
|
|
4
|
+
# Options: ruby_llm, mcp_sdk
|
|
5
|
+
# adapter: ruby_llm
|
|
6
|
+
|
|
3
7
|
transport_type: stdio
|
|
4
8
|
command: npx
|
|
5
9
|
args:
|
|
@@ -7,3 +11,19 @@ mcp_servers:
|
|
|
7
11
|
- "<%%= Rails.root %>"
|
|
8
12
|
env: {}
|
|
9
13
|
with_prefix: true
|
|
14
|
+
|
|
15
|
+
# Example with MCP SDK (official)
|
|
16
|
+
# weather:
|
|
17
|
+
# adapter: mcp_sdk
|
|
18
|
+
# transport_type: http
|
|
19
|
+
# url: "https://api.example.com/mcp"
|
|
20
|
+
# headers:
|
|
21
|
+
# Authorization: "Bearer <%%= ENV['WEATHER_API_KEY'] %>"
|
|
22
|
+
|
|
23
|
+
# Example with SSE (RubyLLM adapter only)
|
|
24
|
+
# notifications:
|
|
25
|
+
# adapter: ruby_llm
|
|
26
|
+
# transport_type: sse
|
|
27
|
+
# url: "https://api.example.com/mcp/sse"
|
|
28
|
+
# headers:
|
|
29
|
+
# Authorization: "Bearer <%%= ENV['API_KEY'] %>"
|