ruby_llm-mcp 0.6.1 → 0.6.3
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/lib/generators/ruby_llm/mcp/install_generator.rb +14 -1
- data/lib/ruby_llm/mcp/notifications/initialize.rb +1 -1
- data/lib/ruby_llm/mcp/parameter.rb +3 -2
- data/lib/ruby_llm/mcp/providers/anthropic/complex_parameter_support.rb +5 -1
- data/lib/ruby_llm/mcp/providers/gemini/complex_parameter_support.rb +4 -0
- data/lib/ruby_llm/mcp/providers/openai/complex_parameter_support.rb +4 -0
- data/lib/ruby_llm/mcp/railtie.rb +2 -2
- data/lib/ruby_llm/mcp/tool.rb +27 -3
- data/lib/ruby_llm/mcp/transports/sse.rb +84 -38
- data/lib/ruby_llm/mcp/transports/streamable_http.rb +15 -8
- data/lib/ruby_llm/mcp/version.rb +1 -1
- data/lib/tasks/release.rake +2 -2
- metadata +1 -16
- data/lib/generators/ruby_llm/mcp/templates/README.txt +0 -32
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa780ea2ca1b1ba71c5efa1784b14e9473ad351af94f0dc35d94aab4d6057325
|
|
4
|
+
data.tar.gz: 1fd76e02e0f6e22087943eff186dbb05cd059e931927442982752cbb9250aa98
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5c37a73381c487a02d61bb8365e39b064b37a0d0668bd46eae1bd25ad225982c8f15229867cd4110e89689ec5757e395ce3825795298aabc3f4ed3b8cd49e0e5
|
|
7
|
+
data.tar.gz: ecb7f5524d9af14c3386abb3ddae91bee454046449ae2e0bba758c95060157c057222a57ce1b9eae5af197e5ec8187e34474fb3801b7cdabb92fdb3cbe14ddd2
|
|
@@ -19,7 +19,20 @@ module RubyLlm
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def display_readme
|
|
22
|
-
|
|
22
|
+
return unless behavior == :invoke
|
|
23
|
+
|
|
24
|
+
say "✅ RubyLLM MCP installed!", :green
|
|
25
|
+
say ""
|
|
26
|
+
say "Next steps:", :blue
|
|
27
|
+
say " 1. Configure config/initializers/ruby_llm_mcp.rb (main settings)"
|
|
28
|
+
say " 2. Define servers in config/mcps.yml"
|
|
29
|
+
say " 3. Install MCP servers (e.g., npm install @modelcontextprotocol/server-filesystem)"
|
|
30
|
+
say " 4. Set environment variables for authentication"
|
|
31
|
+
say ""
|
|
32
|
+
say "📚 Full docs: https://www.rubyllm-mcp.com/", :cyan
|
|
33
|
+
say ""
|
|
34
|
+
say "⭐ Help us improve!", :magenta
|
|
35
|
+
say " Report issues or show your support with a GitHub star: https://github.com/patvice/ruby_llm-mcp"
|
|
23
36
|
end
|
|
24
37
|
end
|
|
25
38
|
end
|
|
@@ -5,10 +5,11 @@ require "ruby_llm/tool"
|
|
|
5
5
|
module RubyLLM
|
|
6
6
|
module MCP
|
|
7
7
|
class Parameter < RubyLLM::Parameter
|
|
8
|
-
attr_accessor :items, :properties, :enum, :union_type, :default
|
|
8
|
+
attr_accessor :items, :properties, :enum, :union_type, :default, :title
|
|
9
9
|
|
|
10
|
-
def initialize(name, type: "string", desc: nil, required: true, default: nil, union_type: nil) # rubocop:disable Metrics/ParameterLists
|
|
10
|
+
def initialize(name, type: "string", title: nil, desc: nil, required: true, default: nil, union_type: nil) # rubocop:disable Metrics/ParameterLists
|
|
11
11
|
super(name, type: type.to_sym, desc: desc, required: required)
|
|
12
|
+
@title = title
|
|
12
13
|
@properties = {}
|
|
13
14
|
@union_type = union_type
|
|
14
15
|
@default = default
|
|
@@ -17,18 +17,20 @@ module RubyLLM
|
|
|
17
17
|
parameters.select { |_, param| param.required }.keys
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def build_properties(param)
|
|
20
|
+
def build_properties(param) # rubocop:disable Metrics/MethodLength
|
|
21
21
|
case param.type
|
|
22
22
|
when :array
|
|
23
23
|
if param.item_type == :object
|
|
24
24
|
{
|
|
25
25
|
type: param.type,
|
|
26
|
+
title: param.title,
|
|
26
27
|
description: param.description,
|
|
27
28
|
items: { type: param.item_type, properties: clean_parameters(param.properties) }
|
|
28
29
|
}.compact
|
|
29
30
|
else
|
|
30
31
|
{
|
|
31
32
|
type: param.type,
|
|
33
|
+
title: param.title,
|
|
32
34
|
description: param.description,
|
|
33
35
|
default: param.default,
|
|
34
36
|
items: { type: param.item_type, enum: param.enum }.compact
|
|
@@ -37,6 +39,7 @@ module RubyLLM
|
|
|
37
39
|
when :object
|
|
38
40
|
{
|
|
39
41
|
type: param.type,
|
|
42
|
+
title: param.title,
|
|
40
43
|
description: param.description,
|
|
41
44
|
properties: clean_parameters(param.properties),
|
|
42
45
|
required: required_parameters(param.properties)
|
|
@@ -48,6 +51,7 @@ module RubyLLM
|
|
|
48
51
|
else
|
|
49
52
|
{
|
|
50
53
|
type: param.type,
|
|
54
|
+
title: param.title,
|
|
51
55
|
description: param.description
|
|
52
56
|
}.compact
|
|
53
57
|
end
|
|
@@ -22,6 +22,7 @@ module RubyLLM
|
|
|
22
22
|
if param.item_type == :object
|
|
23
23
|
{
|
|
24
24
|
type: param_type_for_gemini(param.type),
|
|
25
|
+
title: param.title,
|
|
25
26
|
description: param.description,
|
|
26
27
|
items: {
|
|
27
28
|
type: param_type_for_gemini(param.item_type),
|
|
@@ -31,6 +32,7 @@ module RubyLLM
|
|
|
31
32
|
else
|
|
32
33
|
{
|
|
33
34
|
type: param_type_for_gemini(param.type),
|
|
35
|
+
title: param.title,
|
|
34
36
|
description: param.description,
|
|
35
37
|
default: param.default,
|
|
36
38
|
items: { type: param_type_for_gemini(param.item_type), enum: param.enum }.compact
|
|
@@ -39,6 +41,7 @@ module RubyLLM
|
|
|
39
41
|
when :object
|
|
40
42
|
{
|
|
41
43
|
type: param_type_for_gemini(param.type),
|
|
44
|
+
title: param.title,
|
|
42
45
|
description: param.description,
|
|
43
46
|
properties: param.properties.transform_values { |value| build_properties(value) },
|
|
44
47
|
required: param.properties.select { |_, p| p.required }.keys
|
|
@@ -50,6 +53,7 @@ module RubyLLM
|
|
|
50
53
|
else
|
|
51
54
|
{
|
|
52
55
|
type: param_type_for_gemini(param.type),
|
|
56
|
+
title: param.title,
|
|
53
57
|
description: param.description
|
|
54
58
|
}
|
|
55
59
|
end
|
|
@@ -13,6 +13,7 @@ module RubyLLM
|
|
|
13
13
|
if param.item_type == :object
|
|
14
14
|
{
|
|
15
15
|
type: param.type,
|
|
16
|
+
title: param.title,
|
|
16
17
|
description: param.description,
|
|
17
18
|
items: {
|
|
18
19
|
type: param.item_type,
|
|
@@ -22,6 +23,7 @@ module RubyLLM
|
|
|
22
23
|
else
|
|
23
24
|
{
|
|
24
25
|
type: param.type,
|
|
26
|
+
title: param.title,
|
|
25
27
|
description: param.description,
|
|
26
28
|
default: param.default,
|
|
27
29
|
items: { type: param.item_type, enum: param.enum }.compact
|
|
@@ -30,6 +32,7 @@ module RubyLLM
|
|
|
30
32
|
when :object
|
|
31
33
|
{
|
|
32
34
|
type: param.type,
|
|
35
|
+
title: param.title,
|
|
33
36
|
description: param.description,
|
|
34
37
|
properties: param.properties.transform_values { |value| param_schema(value) },
|
|
35
38
|
required: param.properties.select { |_, p| p.required }.keys
|
|
@@ -41,6 +44,7 @@ module RubyLLM
|
|
|
41
44
|
else
|
|
42
45
|
{
|
|
43
46
|
type: param.type,
|
|
47
|
+
title: param.title,
|
|
44
48
|
description: param.description
|
|
45
49
|
}.compact
|
|
46
50
|
end
|
data/lib/ruby_llm/mcp/railtie.rb
CHANGED
|
@@ -5,9 +5,9 @@ module RubyLLM
|
|
|
5
5
|
class Railtie < Rails::Railtie
|
|
6
6
|
config.after_initialize do
|
|
7
7
|
if RubyLLM::MCP.config.launch_control == :automatic
|
|
8
|
-
RubyLLM::MCP.clients.map(&:start)
|
|
8
|
+
RubyLLM::MCP.clients.each_value.map(&:start)
|
|
9
9
|
at_exit do
|
|
10
|
-
RubyLLM::MCP.clients.map(&:stop)
|
|
10
|
+
RubyLLM::MCP.clients.each_value.map(&:stop)
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
end
|
data/lib/ruby_llm/mcp/tool.rb
CHANGED
|
@@ -25,7 +25,7 @@ module RubyLLM
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
class Tool < RubyLLM::Tool
|
|
28
|
-
attr_reader :name, :description, :parameters, :coordinator, :tool_response, :with_prefix
|
|
28
|
+
attr_reader :name, :title, :description, :parameters, :coordinator, :tool_response, :with_prefix
|
|
29
29
|
|
|
30
30
|
def initialize(coordinator, tool_response, with_prefix: false)
|
|
31
31
|
super()
|
|
@@ -98,6 +98,7 @@ module RubyLLM
|
|
|
98
98
|
|
|
99
99
|
schema["properties"].each_key do |key|
|
|
100
100
|
param_data = schema.dig("properties", key)
|
|
101
|
+
param_data = expand_shorthand_type_to_anyof(param_data)
|
|
101
102
|
|
|
102
103
|
param = if param_data.key?("oneOf") || param_data.key?("anyOf") || param_data.key?("allOf")
|
|
103
104
|
process_union_parameter(key, param_data)
|
|
@@ -116,11 +117,18 @@ module RubyLLM
|
|
|
116
117
|
param = RubyLLM::MCP::Parameter.new(
|
|
117
118
|
key,
|
|
118
119
|
type: :union,
|
|
120
|
+
title: param_data["title"],
|
|
121
|
+
desc: param_data["description"],
|
|
119
122
|
union_type: union_type
|
|
120
123
|
)
|
|
121
124
|
|
|
122
125
|
param.properties = param_data[union_type].map do |value|
|
|
123
|
-
|
|
126
|
+
expanded_value = expand_shorthand_type_to_anyof(value)
|
|
127
|
+
if expanded_value.key?("anyOf")
|
|
128
|
+
process_union_parameter(key, expanded_value)
|
|
129
|
+
else
|
|
130
|
+
process_parameter(key, value, lifted_type: param_data["type"])
|
|
131
|
+
end
|
|
124
132
|
end.compact
|
|
125
133
|
|
|
126
134
|
param
|
|
@@ -129,7 +137,8 @@ module RubyLLM
|
|
|
129
137
|
def process_parameter(key, param_data, lifted_type: nil)
|
|
130
138
|
param = RubyLLM::MCP::Parameter.new(
|
|
131
139
|
key,
|
|
132
|
-
type: param_data["type"] || lifted_type,
|
|
140
|
+
type: param_data["type"] || lifted_type || "string",
|
|
141
|
+
title: param_data["title"],
|
|
133
142
|
desc: param_data["description"],
|
|
134
143
|
required: param_data["required"],
|
|
135
144
|
default: param_data["default"]
|
|
@@ -195,6 +204,21 @@ module RubyLLM
|
|
|
195
204
|
name
|
|
196
205
|
end
|
|
197
206
|
end
|
|
207
|
+
|
|
208
|
+
# Expands shorthand type arrays into explicit anyOf unions
|
|
209
|
+
# Converts { "type": ["string", "number"] } into { "anyOf": [{"type": "string"}, {"type": "number"}] }
|
|
210
|
+
# This keeps $ref references clean and provides a consistent structure for union types
|
|
211
|
+
#
|
|
212
|
+
# @param param_data [Hash] The parameter data that may contain a shorthand type array
|
|
213
|
+
# @return [Hash] The expanded parameter data with anyOf, or the original if not a shorthand
|
|
214
|
+
def expand_shorthand_type_to_anyof(param_data)
|
|
215
|
+
type = param_data["type"]
|
|
216
|
+
return param_data unless type.is_a?(Array)
|
|
217
|
+
|
|
218
|
+
{
|
|
219
|
+
"anyOf" => type.map { |t| { "type" => t } }
|
|
220
|
+
}.merge(param_data.except("type"))
|
|
221
|
+
end
|
|
198
222
|
end
|
|
199
223
|
end
|
|
200
224
|
end
|
|
@@ -30,7 +30,6 @@ module RubyLLM
|
|
|
30
30
|
"Accept" => "text/event-stream",
|
|
31
31
|
"Content-Type" => "application/json",
|
|
32
32
|
"Cache-Control" => "no-cache",
|
|
33
|
-
"Connection" => "keep-alive",
|
|
34
33
|
"X-CLIENT-ID" => @client_id
|
|
35
34
|
})
|
|
36
35
|
|
|
@@ -167,41 +166,82 @@ module RubyLLM
|
|
|
167
166
|
end
|
|
168
167
|
|
|
169
168
|
def stream_events_from_server
|
|
170
|
-
sse_client =
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
)
|
|
169
|
+
sse_client = create_sse_client
|
|
170
|
+
response = sse_client.get(@event_url, stream: true)
|
|
171
|
+
validate_sse_response!(response)
|
|
172
|
+
process_event_stream(response)
|
|
173
|
+
end
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
)
|
|
179
|
-
end
|
|
175
|
+
def create_sse_client
|
|
176
|
+
sse_client = HTTPX.plugin(:stream).with(headers: @headers)
|
|
177
|
+
return sse_client unless @version == :http1
|
|
180
178
|
|
|
181
|
-
|
|
179
|
+
sse_client.with(ssl: { alpn_protocols: ["http/1.1"] })
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def validate_sse_response!(response)
|
|
183
|
+
return unless response.status >= 400
|
|
184
|
+
|
|
185
|
+
error_body = read_error_body(response)
|
|
186
|
+
error_message = "HTTP #{response.status} error from SSE endpoint: #{error_body}"
|
|
187
|
+
RubyLLM::MCP.logger.error error_message
|
|
188
|
+
|
|
189
|
+
handle_client_error!(error_message, response.status) if response.status < 500
|
|
190
|
+
|
|
191
|
+
raise StandardError, error_message
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def handle_client_error!(error_message, status_code)
|
|
195
|
+
@running = false
|
|
196
|
+
raise Errors::TransportError.new(
|
|
197
|
+
message: error_message,
|
|
198
|
+
code: status_code
|
|
199
|
+
)
|
|
200
|
+
end
|
|
182
201
|
|
|
202
|
+
def process_event_stream(response)
|
|
183
203
|
event_buffer = []
|
|
184
204
|
response.each_line do |event_line|
|
|
185
|
-
unless
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
end
|
|
205
|
+
break unless handle_event_line?(event_line, event_buffer, response)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
189
208
|
|
|
190
|
-
|
|
191
|
-
|
|
209
|
+
def handle_event_line?(event_line, event_buffer, response)
|
|
210
|
+
unless @running
|
|
211
|
+
response.body.close
|
|
212
|
+
return false
|
|
213
|
+
end
|
|
192
214
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
215
|
+
line = event_line.strip
|
|
216
|
+
|
|
217
|
+
if line.empty?
|
|
218
|
+
process_buffered_event(event_buffer)
|
|
219
|
+
else
|
|
220
|
+
event_buffer << line
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
true
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def process_buffered_event(event_buffer)
|
|
227
|
+
return unless event_buffer.any?
|
|
228
|
+
|
|
229
|
+
events = parse_event(event_buffer.join("\n"))
|
|
230
|
+
events.each { |event| process_event(event) }
|
|
231
|
+
event_buffer.clear
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def read_error_body(response)
|
|
235
|
+
# Try to read the error body from the response
|
|
236
|
+
body = ""
|
|
237
|
+
begin
|
|
238
|
+
response.each do |chunk|
|
|
239
|
+
body << chunk
|
|
203
240
|
end
|
|
241
|
+
rescue StandardError
|
|
242
|
+
# If we can't read the body, just use what we have
|
|
204
243
|
end
|
|
244
|
+
body.strip.empty? ? "No error details provided" : body.strip
|
|
205
245
|
end
|
|
206
246
|
|
|
207
247
|
def handle_connection_error(message, error)
|
|
@@ -275,19 +315,25 @@ module RubyLLM
|
|
|
275
315
|
end
|
|
276
316
|
|
|
277
317
|
def parse_event(raw)
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
event
|
|
318
|
+
event_blocks = raw.split(/\n\s*\n/)
|
|
319
|
+
|
|
320
|
+
events = event_blocks.map do |event_block|
|
|
321
|
+
event = {}
|
|
322
|
+
event_block.each_line do |line|
|
|
323
|
+
case line
|
|
324
|
+
when /^data:\s*(.*)/
|
|
325
|
+
(event[:data] ||= []) << ::Regexp.last_match(1)
|
|
326
|
+
when /^event:\s*(.*)/
|
|
327
|
+
event[:event] = ::Regexp.last_match(1)
|
|
328
|
+
when /^id:\s*(.*)/
|
|
329
|
+
event[:id] = ::Regexp.last_match(1)
|
|
330
|
+
end
|
|
287
331
|
end
|
|
332
|
+
event[:data] = event[:data]&.join("\n")
|
|
333
|
+
event
|
|
288
334
|
end
|
|
289
|
-
|
|
290
|
-
event
|
|
335
|
+
|
|
336
|
+
events.reject { |event| event.empty? || event[:data].nil? }
|
|
291
337
|
end
|
|
292
338
|
end
|
|
293
339
|
end
|
|
@@ -122,7 +122,6 @@ module RubyLLM
|
|
|
122
122
|
|
|
123
123
|
response_queue = setup_response_queue(request_id, wait_for_response)
|
|
124
124
|
result = send_http_request(body, request_id, is_initialization: is_initialization)
|
|
125
|
-
|
|
126
125
|
return result if result.is_a?(RubyLLM::MCP::Result)
|
|
127
126
|
|
|
128
127
|
if wait_for_response && request_id
|
|
@@ -365,16 +364,17 @@ module RubyLLM
|
|
|
365
364
|
end
|
|
366
365
|
|
|
367
366
|
def handle_success_response(response, request_id, _original_message)
|
|
368
|
-
# Safely access content type
|
|
369
367
|
content_type = response.respond_to?(:headers) ? response.headers["content-type"] : nil
|
|
370
368
|
|
|
371
369
|
if content_type&.include?("text/event-stream")
|
|
372
|
-
# SSE response - let the streaming handler process it
|
|
373
370
|
start_sse_stream
|
|
374
371
|
nil
|
|
375
372
|
elsif content_type&.include?("application/json")
|
|
376
|
-
# Direct JSON response
|
|
377
373
|
response_body = response.respond_to?(:body) ? response.body.to_s : "{}"
|
|
374
|
+
if response_body == "null" # Fix related to official MCP Ruby SDK implementation
|
|
375
|
+
response_body = "{}"
|
|
376
|
+
end
|
|
377
|
+
|
|
378
378
|
json_response = JSON.parse(response_body)
|
|
379
379
|
result = RubyLLM::MCP::Result.new(json_response, session_id: @session_id)
|
|
380
380
|
|
|
@@ -594,10 +594,17 @@ module RubyLLM
|
|
|
594
594
|
end
|
|
595
595
|
|
|
596
596
|
def extract_sse_event(buffer)
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
597
|
+
# Support both Unix (\n\n) and Windows (\r\n\r\n) line endings
|
|
598
|
+
separator = if buffer.include?("\r\n\r\n")
|
|
599
|
+
"\r\n\r\n"
|
|
600
|
+
elsif buffer.include?("\n\n")
|
|
601
|
+
"\n\n"
|
|
602
|
+
else
|
|
603
|
+
return nil
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
raw, rest = buffer.split(separator, 2)
|
|
607
|
+
[parse_sse_event(raw), rest || ""]
|
|
601
608
|
end
|
|
602
609
|
|
|
603
610
|
def parse_sse_event(raw)
|
data/lib/ruby_llm/mcp/version.rb
CHANGED
data/lib/tasks/release.rake
CHANGED
|
@@ -4,8 +4,8 @@ namespace :release do
|
|
|
4
4
|
desc "Release a new version of the gem"
|
|
5
5
|
task :version do
|
|
6
6
|
# Load the current version from version.rb
|
|
7
|
-
require_relative "../../lib/ruby_llm/
|
|
8
|
-
version =
|
|
7
|
+
require_relative "../../lib/ruby_llm/mcp/version"
|
|
8
|
+
version = RubyLLM::MCP::VERSION
|
|
9
9
|
|
|
10
10
|
puts "Releasing version #{version}..."
|
|
11
11
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_llm-mcp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrick Vice
|
|
@@ -51,20 +51,6 @@ dependencies:
|
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
version: '1.3'
|
|
54
|
-
- !ruby/object:Gem::Dependency
|
|
55
|
-
name: thor
|
|
56
|
-
requirement: !ruby/object:Gem::Requirement
|
|
57
|
-
requirements:
|
|
58
|
-
- - "~>"
|
|
59
|
-
- !ruby/object:Gem::Version
|
|
60
|
-
version: '1.3'
|
|
61
|
-
type: :runtime
|
|
62
|
-
prerelease: false
|
|
63
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
-
requirements:
|
|
65
|
-
- - "~>"
|
|
66
|
-
- !ruby/object:Gem::Version
|
|
67
|
-
version: '1.3'
|
|
68
54
|
- !ruby/object:Gem::Dependency
|
|
69
55
|
name: zeitwerk
|
|
70
56
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -93,7 +79,6 @@ files:
|
|
|
93
79
|
- LICENSE
|
|
94
80
|
- README.md
|
|
95
81
|
- lib/generators/ruby_llm/mcp/install_generator.rb
|
|
96
|
-
- lib/generators/ruby_llm/mcp/templates/README.txt
|
|
97
82
|
- lib/generators/ruby_llm/mcp/templates/initializer.rb
|
|
98
83
|
- lib/generators/ruby_llm/mcp/templates/mcps.yml
|
|
99
84
|
- lib/ruby_llm/chat.rb
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
RubyLLM MCP has been successfully installed!
|
|
2
|
-
|
|
3
|
-
The following files have been created:
|
|
4
|
-
|
|
5
|
-
config/initializers/ruby_llm_mcp.rb - Main configuration file
|
|
6
|
-
config/mcps.json - MCP servers configuration
|
|
7
|
-
|
|
8
|
-
Next steps:
|
|
9
|
-
|
|
10
|
-
1. Edit config/initializers/ruby_llm_mcp.rb to configure your MCP settings
|
|
11
|
-
2. Edit config/mcps.json to define your MCP servers
|
|
12
|
-
3. Install any MCP servers you want to use (e.g., npm install @modelcontextprotocol/server-filesystem) or use remote MCPs
|
|
13
|
-
4. Update environment variables for any MCP servers that require authentication
|
|
14
|
-
|
|
15
|
-
Example usage in your Rails application:
|
|
16
|
-
|
|
17
|
-
# With Ruby::MCP installed in a controller or service
|
|
18
|
-
clients = RubyLLM::MCP.clients
|
|
19
|
-
|
|
20
|
-
# Get all tools use the configured client
|
|
21
|
-
tools = RubyLLM::MCP.tools
|
|
22
|
-
|
|
23
|
-
# Or use the configured client
|
|
24
|
-
client = RubyLLM::MCP.clients["file-system"]
|
|
25
|
-
|
|
26
|
-
# Or use the configured client
|
|
27
|
-
tools = client.tools
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
For more information, visit: https://github.com/patvice/ruby_llm-mcp
|
|
31
|
-
|
|
32
|
-
===============================================================================
|