ruby_llm-mcp 0.4.1 → 0.5.1
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 +313 -25
- data/lib/generators/ruby_llm/mcp/install_generator.rb +27 -0
- data/lib/generators/ruby_llm/mcp/templates/README.txt +32 -0
- data/lib/generators/ruby_llm/mcp/templates/initializer.rb +42 -0
- data/lib/generators/ruby_llm/mcp/templates/mcps.yml +9 -0
- data/lib/ruby_llm/chat.rb +2 -1
- data/lib/ruby_llm/mcp/client.rb +32 -13
- data/lib/ruby_llm/mcp/configuration.rb +123 -3
- data/lib/ruby_llm/mcp/coordinator.rb +108 -115
- data/lib/ruby_llm/mcp/errors.rb +3 -1
- data/lib/ruby_llm/mcp/notification_handler.rb +84 -0
- data/lib/ruby_llm/mcp/{requests/cancelled_notification.rb → notifications/cancelled.rb} +2 -2
- data/lib/ruby_llm/mcp/{requests/initialize_notification.rb → notifications/initialize.rb} +7 -3
- data/lib/ruby_llm/mcp/notifications/roots_list_change.rb +26 -0
- data/lib/ruby_llm/mcp/parameter.rb +19 -1
- data/lib/ruby_llm/mcp/progress.rb +3 -1
- data/lib/ruby_llm/mcp/prompt.rb +18 -0
- data/lib/ruby_llm/mcp/railtie.rb +20 -0
- data/lib/ruby_llm/mcp/requests/initialization.rb +8 -4
- data/lib/ruby_llm/mcp/requests/ping.rb +6 -2
- data/lib/ruby_llm/mcp/requests/prompt_list.rb +10 -2
- data/lib/ruby_llm/mcp/requests/resource_list.rb +12 -2
- data/lib/ruby_llm/mcp/requests/resource_template_list.rb +12 -2
- data/lib/ruby_llm/mcp/requests/shared/meta.rb +32 -0
- data/lib/ruby_llm/mcp/requests/shared/pagination.rb +17 -0
- data/lib/ruby_llm/mcp/requests/tool_call.rb +1 -1
- data/lib/ruby_llm/mcp/requests/tool_list.rb +10 -2
- data/lib/ruby_llm/mcp/resource.rb +17 -0
- data/lib/ruby_llm/mcp/response_handler.rb +58 -0
- data/lib/ruby_llm/mcp/responses/error.rb +33 -0
- data/lib/ruby_llm/mcp/{requests/ping_response.rb → responses/ping.rb} +2 -2
- data/lib/ruby_llm/mcp/responses/roots_list.rb +31 -0
- data/lib/ruby_llm/mcp/responses/sampling_create_message.rb +50 -0
- data/lib/ruby_llm/mcp/result.rb +21 -8
- data/lib/ruby_llm/mcp/roots.rb +45 -0
- data/lib/ruby_llm/mcp/sample.rb +148 -0
- data/lib/ruby_llm/mcp/{capabilities.rb → server_capabilities.rb} +1 -1
- data/lib/ruby_llm/mcp/tool.rb +35 -4
- data/lib/ruby_llm/mcp/transport.rb +58 -0
- data/lib/ruby_llm/mcp/transports/http_client.rb +26 -0
- data/lib/ruby_llm/mcp/{transport → transports}/sse.rb +25 -24
- data/lib/ruby_llm/mcp/{transport → transports}/stdio.rb +28 -26
- data/lib/ruby_llm/mcp/{transport → transports}/streamable_http.rb +25 -29
- data/lib/ruby_llm/mcp/transports/timeout.rb +32 -0
- data/lib/ruby_llm/mcp/version.rb +1 -1
- data/lib/ruby_llm/mcp.rb +60 -9
- metadata +27 -11
- data/lib/ruby_llm/mcp/requests/base.rb +0 -31
- data/lib/ruby_llm/mcp/requests/meta.rb +0 -30
data/lib/ruby_llm/mcp.rb
CHANGED
@@ -4,19 +4,59 @@ require "ruby_llm"
|
|
4
4
|
require "zeitwerk"
|
5
5
|
require_relative "chat"
|
6
6
|
|
7
|
-
loader = Zeitwerk::Loader.for_gem_extension(RubyLLM)
|
8
|
-
loader.inflector.inflect("mcp" => "MCP")
|
9
|
-
loader.inflector.inflect("sse" => "SSE")
|
10
|
-
loader.inflector.inflect("openai" => "OpenAI")
|
11
|
-
loader.inflector.inflect("streamable_http" => "StreamableHTTP")
|
12
|
-
loader.setup
|
13
|
-
|
14
7
|
module RubyLLM
|
15
8
|
module MCP
|
16
9
|
module_function
|
17
10
|
|
18
|
-
def
|
19
|
-
@
|
11
|
+
def clients(config = RubyLLM::MCP.config.mcp_configuration)
|
12
|
+
@clients ||= {}
|
13
|
+
config.map do |options|
|
14
|
+
@clients[options[:name]] ||= Client.new(**options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_client(options)
|
19
|
+
@clients ||= {}
|
20
|
+
@clients[options[:name]] ||= Client.new(**options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def remove_client(name)
|
24
|
+
@clients ||= {}
|
25
|
+
client = @clients.delete(name)
|
26
|
+
client&.stop
|
27
|
+
client
|
28
|
+
end
|
29
|
+
|
30
|
+
def client(...)
|
31
|
+
Client.new(...)
|
32
|
+
end
|
33
|
+
|
34
|
+
def establish_connection(&)
|
35
|
+
clients.each(&:start)
|
36
|
+
if block_given?
|
37
|
+
begin
|
38
|
+
yield clients
|
39
|
+
ensure
|
40
|
+
close_connection
|
41
|
+
end
|
42
|
+
else
|
43
|
+
clients
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def close_connection
|
48
|
+
clients.each do |client|
|
49
|
+
client.stop if client.alive?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def tools(blacklist: [], whitelist: [])
|
54
|
+
tools = @clients.values.map(&:tools)
|
55
|
+
.flatten
|
56
|
+
.reject { |tool| blacklist.include?(tool.name) }
|
57
|
+
|
58
|
+
tools = tools.select { |tool| whitelist.include?(tool.name) } if whitelist.any?
|
59
|
+
tools.uniq(&:name)
|
20
60
|
end
|
21
61
|
|
22
62
|
def support_complex_parameters!
|
@@ -41,3 +81,14 @@ module RubyLLM
|
|
41
81
|
end
|
42
82
|
end
|
43
83
|
end
|
84
|
+
|
85
|
+
require_relative "mcp/railtie" if defined?(Rails::Railtie)
|
86
|
+
|
87
|
+
loader = Zeitwerk::Loader.for_gem_extension(RubyLLM)
|
88
|
+
loader.inflector.inflect("mcp" => "MCP")
|
89
|
+
loader.inflector.inflect("sse" => "SSE")
|
90
|
+
loader.inflector.inflect("openai" => "OpenAI")
|
91
|
+
loader.inflector.inflect("streamable_http" => "StreamableHTTP")
|
92
|
+
loader.inflector.inflect("http_client" => "HTTPClient")
|
93
|
+
|
94
|
+
loader.setup
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_llm-mcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patrick Vice
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-07-
|
11
|
+
date: 2025-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpx
|
@@ -65,10 +65,13 @@ extra_rdoc_files: []
|
|
65
65
|
files:
|
66
66
|
- LICENSE
|
67
67
|
- README.md
|
68
|
+
- lib/generators/ruby_llm/mcp/install_generator.rb
|
69
|
+
- lib/generators/ruby_llm/mcp/templates/README.txt
|
70
|
+
- lib/generators/ruby_llm/mcp/templates/initializer.rb
|
71
|
+
- lib/generators/ruby_llm/mcp/templates/mcps.yml
|
68
72
|
- lib/ruby_llm/chat.rb
|
69
73
|
- lib/ruby_llm/mcp.rb
|
70
74
|
- lib/ruby_llm/mcp/attachment.rb
|
71
|
-
- lib/ruby_llm/mcp/capabilities.rb
|
72
75
|
- lib/ruby_llm/mcp/client.rb
|
73
76
|
- lib/ruby_llm/mcp/completion.rb
|
74
77
|
- lib/ruby_llm/mcp/configuration.rb
|
@@ -77,37 +80,50 @@ files:
|
|
77
80
|
- lib/ruby_llm/mcp/error.rb
|
78
81
|
- lib/ruby_llm/mcp/errors.rb
|
79
82
|
- lib/ruby_llm/mcp/logging.rb
|
83
|
+
- lib/ruby_llm/mcp/notification_handler.rb
|
84
|
+
- lib/ruby_llm/mcp/notifications/cancelled.rb
|
85
|
+
- lib/ruby_llm/mcp/notifications/initialize.rb
|
86
|
+
- lib/ruby_llm/mcp/notifications/roots_list_change.rb
|
80
87
|
- lib/ruby_llm/mcp/parameter.rb
|
81
88
|
- lib/ruby_llm/mcp/progress.rb
|
82
89
|
- lib/ruby_llm/mcp/prompt.rb
|
83
90
|
- lib/ruby_llm/mcp/providers/anthropic/complex_parameter_support.rb
|
84
91
|
- lib/ruby_llm/mcp/providers/gemini/complex_parameter_support.rb
|
85
92
|
- lib/ruby_llm/mcp/providers/openai/complex_parameter_support.rb
|
86
|
-
- lib/ruby_llm/mcp/
|
87
|
-
- lib/ruby_llm/mcp/requests/cancelled_notification.rb
|
93
|
+
- lib/ruby_llm/mcp/railtie.rb
|
88
94
|
- lib/ruby_llm/mcp/requests/completion_prompt.rb
|
89
95
|
- lib/ruby_llm/mcp/requests/completion_resource.rb
|
90
96
|
- lib/ruby_llm/mcp/requests/initialization.rb
|
91
|
-
- lib/ruby_llm/mcp/requests/initialize_notification.rb
|
92
97
|
- lib/ruby_llm/mcp/requests/logging_set_level.rb
|
93
|
-
- lib/ruby_llm/mcp/requests/meta.rb
|
94
98
|
- lib/ruby_llm/mcp/requests/ping.rb
|
95
|
-
- lib/ruby_llm/mcp/requests/ping_response.rb
|
96
99
|
- lib/ruby_llm/mcp/requests/prompt_call.rb
|
97
100
|
- lib/ruby_llm/mcp/requests/prompt_list.rb
|
98
101
|
- lib/ruby_llm/mcp/requests/resource_list.rb
|
99
102
|
- lib/ruby_llm/mcp/requests/resource_read.rb
|
100
103
|
- lib/ruby_llm/mcp/requests/resource_template_list.rb
|
101
104
|
- lib/ruby_llm/mcp/requests/resources_subscribe.rb
|
105
|
+
- lib/ruby_llm/mcp/requests/shared/meta.rb
|
106
|
+
- lib/ruby_llm/mcp/requests/shared/pagination.rb
|
102
107
|
- lib/ruby_llm/mcp/requests/tool_call.rb
|
103
108
|
- lib/ruby_llm/mcp/requests/tool_list.rb
|
104
109
|
- lib/ruby_llm/mcp/resource.rb
|
105
110
|
- lib/ruby_llm/mcp/resource_template.rb
|
111
|
+
- lib/ruby_llm/mcp/response_handler.rb
|
112
|
+
- lib/ruby_llm/mcp/responses/error.rb
|
113
|
+
- lib/ruby_llm/mcp/responses/ping.rb
|
114
|
+
- lib/ruby_llm/mcp/responses/roots_list.rb
|
115
|
+
- lib/ruby_llm/mcp/responses/sampling_create_message.rb
|
106
116
|
- lib/ruby_llm/mcp/result.rb
|
117
|
+
- lib/ruby_llm/mcp/roots.rb
|
118
|
+
- lib/ruby_llm/mcp/sample.rb
|
119
|
+
- lib/ruby_llm/mcp/server_capabilities.rb
|
107
120
|
- lib/ruby_llm/mcp/tool.rb
|
108
|
-
- lib/ruby_llm/mcp/transport
|
109
|
-
- lib/ruby_llm/mcp/
|
110
|
-
- lib/ruby_llm/mcp/
|
121
|
+
- lib/ruby_llm/mcp/transport.rb
|
122
|
+
- lib/ruby_llm/mcp/transports/http_client.rb
|
123
|
+
- lib/ruby_llm/mcp/transports/sse.rb
|
124
|
+
- lib/ruby_llm/mcp/transports/stdio.rb
|
125
|
+
- lib/ruby_llm/mcp/transports/streamable_http.rb
|
126
|
+
- lib/ruby_llm/mcp/transports/timeout.rb
|
111
127
|
- lib/ruby_llm/mcp/version.rb
|
112
128
|
- lib/tasks/release.rake
|
113
129
|
homepage: https://github.com/patvice/ruby_llm-mcp
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "json"
|
4
|
-
|
5
|
-
module RubyLLM
|
6
|
-
module MCP
|
7
|
-
module Requests
|
8
|
-
class Base
|
9
|
-
attr_reader :coordinator
|
10
|
-
|
11
|
-
def initialize(coordinator)
|
12
|
-
@coordinator = coordinator
|
13
|
-
end
|
14
|
-
|
15
|
-
def call
|
16
|
-
raise "Not implemented"
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def validate_response!(response, body)
|
22
|
-
# TODO: Implement response validation
|
23
|
-
end
|
24
|
-
|
25
|
-
def raise_error(error)
|
26
|
-
raise "MCP Error: code: #{error['code']} message: #{error['message']} data: #{error['data']}"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "securerandom"
|
4
|
-
|
5
|
-
module RubyLLM
|
6
|
-
module MCP
|
7
|
-
module Requests
|
8
|
-
module Meta
|
9
|
-
def merge_meta(body)
|
10
|
-
meta = {}
|
11
|
-
meta.merge!(progress_token) if @coordinator.client.tracking_progress?
|
12
|
-
|
13
|
-
body[:params] ||= {}
|
14
|
-
body[:params].merge!({ _meta: meta }) unless meta.empty?
|
15
|
-
body
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def progress_token
|
21
|
-
{ progressToken: generate_progress_token }
|
22
|
-
end
|
23
|
-
|
24
|
-
def generate_progress_token
|
25
|
-
SecureRandom.uuid
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|