ruby_llm-mcp 0.2.1 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 49b1593de3f38afce9d3002a696c7034c2bea82711742ea4bd96a5f155f113e3
4
- data.tar.gz: 6fb3c4b87bc82684bb9ef093b70b13eea91e759f5ee44a08b4be543cc45d30d3
3
+ metadata.gz: 53435b09aee8d32aaede3da3463b8fb782a6d00f6abcabc3b9925f1301cd60c9
4
+ data.tar.gz: 366cf4d89bef7f79904cd897a7db006ee21a8766c8ff1675e51225576e8c87f4
5
5
  SHA512:
6
- metadata.gz: 6950867fde16315dba705049ec2d23cc89f3977808d323af20b5bf343b2453228145190e183bfd6350b95df856ae96bf4f60a83145eb0137dad0003454c889d3
7
- data.tar.gz: 1ed01c5ec46651c1b420971a429299e60b59707255403f1a167c8832cfde9ee5ba1a5ed00ba1edea8f2bf710006f1d605896781c329f02f5ca056642fe246100
6
+ metadata.gz: 94754a9b6d8799252bebfb19ccc3dedfc6767fdbe07468960ed3eb56978954d734425f79b366fb92610f4c059970a0607c249b3c6c35bca943fbab7e5a721e77
7
+ data.tar.gz: d0e757cdc7d064ffc4334b0b1c2a1ebc1feff3dc684d35d28f0b51ce5761a3c80ad427654767fae97da8c8ddacbc182d3d896ef4dedc45ce4d6d8e6297b81fe3
data/README.md CHANGED
@@ -12,13 +12,16 @@ This project is a Ruby client for the [Model Context Protocol (MCP)](https://mod
12
12
  - 🛠️ **Tool Integration**: Automatically converts MCP tools into RubyLLM-compatible tools
13
13
  - 📄 **Resource Management**: Access and include MCP resources (files, data) and resource templates in conversations
14
14
  - 🎯 **Prompt Integration**: Use predefined MCP prompts with arguments for consistent interactions
15
- - 🔄 **Real-time Communication**: Efficient bidirectional communication with MCP servers
16
15
  - 🎨 **Enhanced Chat Interface**: Extended RubyLLM chat methods for seamless MCP integration
17
16
  - 📚 **Simple API**: Easy-to-use interface that integrates seamlessly with RubyLLM
18
17
 
19
18
  ## Installation
20
19
 
21
- Add this line to your application's Gemfile:
20
+ ```bash
21
+ bundle add ruby_llm-mcp
22
+ ```
23
+
24
+ or add this line to your application's Gemfile:
22
25
 
23
26
  ```ruby
24
27
  gem 'ruby_llm-mcp'
@@ -152,12 +155,12 @@ MCP servers can provide access to resources - structured data that can be includ
152
155
  # Get available resources from the MCP server
153
156
  resources = client.resources
154
157
  puts "Available resources:"
155
- resources.each do |name, resource|
156
- puts "- #{name}: #{resource.description}"
158
+ resources.each do |resource|
159
+ puts "- #{resource.name}: #{resource.description}"
157
160
  end
158
161
 
159
- # Access a specific resource
160
- file_resource = resources["project_readme"]
162
+ # Access a specific resource by name
163
+ file_resource = client.resource("project_readme")
161
164
  content = file_resource.content
162
165
  puts "Resource content: #{content}"
163
166
 
@@ -179,11 +182,11 @@ Resource templates are parameterized resources that can be dynamically configure
179
182
  ```ruby
180
183
  # Get available resource templates
181
184
  templates = client.resource_templates
182
- log_template = templates["application_logs"]
185
+ log_template = client.resource_template("application_logs")
183
186
 
184
187
  # Use a template with parameters
185
188
  chat = RubyLLM.chat(model: "gpt-4")
186
- chat.with_resource(log_template, arguments: {
189
+ chat.with_resource_template(log_template, arguments: {
187
190
  date: "2024-01-15",
188
191
  level: "error"
189
192
  })
@@ -192,7 +195,7 @@ response = chat.ask("What errors occurred on this date?")
192
195
  puts response
193
196
 
194
197
  # You can also get templated content directly
195
- content = log_template.content(arguments: {
198
+ content = log_template.to_content(arguments: {
196
199
  date: "2024-01-15",
197
200
  level: "error"
198
201
  })
@@ -204,12 +207,12 @@ puts content
204
207
  For resource templates, you can get suggested values for arguments:
205
208
 
206
209
  ```ruby
207
- template = client.resource_templates["user_profile"]
210
+ template = client.resource_template("user_profile")
208
211
 
209
212
  # Search for possible values for a specific argument
210
- suggestions = template.arguments_search("username", "john")
213
+ suggestions = template.complete("username", "john")
211
214
  puts "Suggested usernames:"
212
- suggestions.arg_values.each do |value|
215
+ suggestions.values.each do |value|
213
216
  puts "- #{value}"
214
217
  end
215
218
  puts "Total matches: #{suggestions.total}"
@@ -224,15 +227,15 @@ MCP servers can provide predefined prompts that can be used in conversations:
224
227
  # Get available prompts from the MCP server
225
228
  prompts = client.prompts
226
229
  puts "Available prompts:"
227
- prompts.each do |name, prompt|
228
- puts "- #{name}: #{prompt.description}"
230
+ prompts.each do |prompt|
231
+ puts "- #{prompt.name}: #{prompt.description}"
229
232
  prompt.arguments.each do |arg|
230
233
  puts " - #{arg.name}: #{arg.description} (required: #{arg.required})"
231
234
  end
232
235
  end
233
236
 
234
237
  # Use a prompt in a conversation
235
- greeting_prompt = prompts["daily_greeting"]
238
+ greeting_prompt = client.prompt("daily_greeting")
236
239
  chat = RubyLLM.chat(model: "gpt-4")
237
240
 
238
241
  # Method 1: Ask prompt directly
@@ -261,15 +264,15 @@ chat = RubyLLM.chat(model: "gpt-4")
261
264
  chat.with_tools(*client.tools)
262
265
 
263
266
  # Add resources for context
264
- chat.with_resource(client.resources["project_structure"])
267
+ chat.with_resource(client.resource("project_structure"))
265
268
  chat.with_resource(
266
- client.resource_templates["recent_commits"],
269
+ client.resource_template("recent_commits"),
267
270
  arguments: { days: 7 }
268
271
  )
269
272
 
270
273
  # Add prompts for guidance
271
274
  chat.with_prompt(
272
- client.prompts["code_review_checklist"],
275
+ client.prompt("code_review_checklist"),
273
276
  arguments: { focus: "security" }
274
277
  )
275
278
 
@@ -278,6 +281,88 @@ response = chat.ask("Please review the recent commits using the checklist and su
278
281
  puts response
279
282
  ```
280
283
 
284
+ ## Argument Completion
285
+
286
+ Some MCP servers support argument completion for prompts and resource templates:
287
+
288
+ ```ruby
289
+ # For prompts
290
+ prompt = client.prompt("user_search")
291
+ suggestions = prompt.complete("username", "jo")
292
+ puts "Suggestions: #{suggestions.values}" # ["john", "joanna", "joseph"]
293
+
294
+ # For resource templates
295
+ template = client.resource_template("user_logs")
296
+ suggestions = template.complete("user_id", "123")
297
+ puts "Total matches: #{suggestions.total}"
298
+ puts "Has more results: #{suggestions.has_more}"
299
+ ```
300
+
301
+ ## Additional Chat Methods
302
+
303
+ The gem extends RubyLLM's chat interface with convenient methods for MCP integration:
304
+
305
+ ```ruby
306
+ chat = RubyLLM.chat(model: "gpt-4")
307
+
308
+ # Add a single resource
309
+ chat.with_resource(resource)
310
+
311
+ # Add multiple resources
312
+ chat.with_resources(resource1, resource2, resource3)
313
+
314
+ # Add a resource template with arguments
315
+ chat.with_resource_template(resource_template, arguments: { key: "value" })
316
+
317
+ # Add a prompt with arguments
318
+ chat.with_prompt(prompt, arguments: { name: "Alice" })
319
+
320
+ # Ask using a prompt directly
321
+ response = chat.ask_prompt(prompt, arguments: { name: "Alice" })
322
+ ```
323
+
324
+ ## Client Lifecycle Management
325
+
326
+ You can manage the MCP client connection lifecycle:
327
+
328
+ ```ruby
329
+ client = RubyLLM::MCP.client(name: "my-server", transport_type: :stdio, start: false, config: {...})
330
+
331
+ # Manually start the connection
332
+ client.start
333
+
334
+ # Check if connection is alive
335
+ puts client.alive?
336
+
337
+ # Restart the connection
338
+ client.restart!
339
+
340
+ # Stop the connection
341
+ client.stop
342
+ ```
343
+
344
+ ## Refreshing Cached Data
345
+
346
+ The client caches tools, resources, prompts, and resource templates list calls are cached to reduce round trips back to the MCP server. You can refresh this cache:
347
+
348
+ ```ruby
349
+ # Refresh all cached tools
350
+ tools = client.tools(refresh: true)
351
+
352
+ # Refresh a specific tool
353
+ tool = client.tool("search_files", refresh: true)
354
+
355
+ # Same pattern works for resources, prompts, and resource templates
356
+ resources = client.resources(refresh: true)
357
+ prompts = client.prompts(refresh: true)
358
+ templates = client.resource_templates(refresh: true)
359
+
360
+ # Or refresh specific items
361
+ resource = client.resource("project_readme", refresh: true)
362
+ prompt = client.prompt("daily_greeting", refresh: true)
363
+ template = client.resource_template("user_logs", refresh: true)
364
+ ```
365
+
281
366
  ## Transport Types
282
367
 
283
368
  ### SSE (Server-Sent Events)
@@ -289,7 +374,8 @@ client = RubyLLM::MCP.client(
289
374
  name: "web-mcp-server",
290
375
  transport_type: :sse,
291
376
  config: {
292
- url: "https://your-mcp-server.com/mcp/sse"
377
+ url: "https://your-mcp-server.com/mcp/sse",
378
+ headers: { "Authorization" => "Bearer your-token" }
293
379
  }
294
380
  )
295
381
  ```
@@ -329,9 +415,10 @@ client = RubyLLM::MCP.client(
329
415
 
330
416
  - `name`: A unique identifier for your MCP client
331
417
  - `transport_type`: Either `:sse`, `:streamable`, or `:stdio`
418
+ - `start`: Whether to automatically start the connection (default: true)
332
419
  - `request_timeout`: Timeout for requests in milliseconds (default: 8000)
333
420
  - `config`: Transport-specific configuration
334
- - For SSE: `{ url: "http://..." }`
421
+ - For SSE: `{ url: "http://...", headers: {...} }`
335
422
  - For Streamable: `{ url: "http://...", headers: {...} }`
336
423
  - For stdio: `{ command: "...", args: [...], env: {...} }`
337
424
 
@@ -339,13 +426,16 @@ client = RubyLLM::MCP.client(
339
426
 
340
427
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
341
428
 
342
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
429
+ To install this gem onto your local machine, run `bundle exec rake install`. Run `bundle exec rake` to test specs and run linters. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
343
430
 
344
431
  ## Examples
345
432
 
346
433
  Check out the `examples/` directory for more detailed usage examples:
347
434
 
348
- - `examples/test_local_mcp.rb` - Complete example with SSE transport
435
+ - `examples/tools/local_mcp.rb` - Complete example with stdio transport
436
+ - `examples/tools/sse_mcp_with_gpt.rb` - Example using SSE transport with GPT
437
+ - `examples/resources/list_resources.rb` - Example of listing and using resources
438
+ - `examples/prompts/streamable_prompt_call.rb` - Example of using prompts with streamable transport
349
439
 
350
440
  ## Contributing
351
441
 
data/lib/ruby_llm/chat.rb CHANGED
@@ -10,8 +10,14 @@ module RubyLLM
10
10
  self
11
11
  end
12
12
 
13
- def with_resource(resource, **args)
14
- resource.include(self, **args)
13
+ def with_resource(resource)
14
+ resource.include(self)
15
+ self
16
+ end
17
+
18
+ def with_resource_template(resource_template, arguments: {})
19
+ resource = resource_template.fetch_resource(arguments: arguments)
20
+ resource.include(self)
15
21
  self
16
22
  end
17
23
 
@@ -3,9 +3,9 @@
3
3
  module RubyLLM
4
4
  module MCP
5
5
  class Capabilities
6
- attr_reader :capabilities
6
+ attr_accessor :capabilities
7
7
 
8
- def initialize(capabilities)
8
+ def initialize(capabilities = {})
9
9
  @capabilities = capabilities
10
10
  end
11
11
 
@@ -22,7 +22,7 @@ module RubyLLM
22
22
  end
23
23
 
24
24
  def completion?
25
- @capabilities["completion"].present?
25
+ !@capabilities["completions"].nil?
26
26
  end
27
27
  end
28
28
  end
@@ -1,145 +1,103 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "forwardable"
4
+
3
5
  module RubyLLM
4
6
  module MCP
5
7
  class Client
6
- PROTOCOL_VERSION = "2025-03-26"
7
- PV_2024_11_05 = "2024-11-05"
8
+ extend Forwardable
8
9
 
9
- attr_reader :name, :config, :transport_type, :transport, :request_timeout, :reverse_proxy_url, :protocol_version,
10
- :capabilities
10
+ attr_reader :name, :config, :transport_type, :request_timeout
11
11
 
12
- def initialize(name:, transport_type:, request_timeout: 8000, reverse_proxy_url: nil, config: {})
12
+ def initialize(name:, transport_type:, start: true, request_timeout: 8000, config: {})
13
13
  @name = name
14
- @config = config
15
- @protocol_version = PROTOCOL_VERSION
16
- @headers = config[:headers] || {}
17
-
14
+ @config = config.merge(request_timeout: request_timeout)
18
15
  @transport_type = transport_type.to_sym
19
-
20
- case @transport_type
21
- when :sse
22
- @transport = RubyLLM::MCP::Transport::SSE.new(@config[:url], headers: @headers)
23
- when :stdio
24
- @transport = RubyLLM::MCP::Transport::Stdio.new(@config[:command], args: @config[:args], env: @config[:env])
25
- when :streamable
26
- @transport = RubyLLM::MCP::Transport::Streamable.new(@config[:url], headers: @headers)
27
- else
28
- raise "Invalid transport type: #{transport_type}"
29
- end
30
- @capabilities = nil
31
-
32
16
  @request_timeout = request_timeout
33
- @reverse_proxy_url = reverse_proxy_url
34
17
 
35
- initialize_request
36
- notification_request
37
- end
18
+ @coordinator = Coordinator.new(self, transport_type: @transport_type, config: @config)
38
19
 
39
- def request(body, **options)
40
- @transport.request(body, **options)
20
+ start_transport if start
41
21
  end
42
22
 
43
- def tools(refresh: false)
44
- @tools = nil if refresh
45
- @tools ||= fetch_and_create_tools
46
- end
23
+ def_delegators :@coordinator, :start_transport, :stop_transport, :restart_transport, :alive?, :capabilities
47
24
 
48
- def resources(refresh: false)
49
- @resources = nil if refresh
50
- @resources ||= fetch_and_create_resources
51
- end
25
+ alias start start_transport
26
+ alias stop stop_transport
27
+ alias restart! restart_transport
52
28
 
53
- def resource_templates(refresh: false)
54
- @resource_templates = nil if refresh
55
- @resource_templates ||= fetch_and_create_resources(set_as_template: true)
56
- end
29
+ def tools(refresh: false)
30
+ fetch(:tools, refresh) do
31
+ tools_data = @coordinator.tool_list.dig("result", "tools")
32
+ build_map(tools_data, MCP::Tool)
33
+ end
57
34
 
58
- def prompts(refresh: false)
59
- @prompts = nil if refresh
60
- @prompts ||= fetch_and_create_prompts
35
+ @tools.values
61
36
  end
62
37
 
63
- def execute_tool(**args)
64
- RubyLLM::MCP::Requests::ToolCall.new(self, **args).call
65
- end
38
+ def tool(name, refresh: false)
39
+ tools(refresh: refresh)
66
40
 
67
- def resource_read_request(**args)
68
- RubyLLM::MCP::Requests::ResourceRead.new(self, **args).call
41
+ @tools[name]
69
42
  end
70
43
 
71
- def completion(**args)
72
- RubyLLM::MCP::Requests::Completion.new(self, **args).call
73
- end
44
+ def resources(refresh: false)
45
+ fetch(:resources, refresh) do
46
+ resources_data = @coordinator.resource_list.dig("result", "resources")
47
+ build_map(resources_data, MCP::Resource)
48
+ end
74
49
 
75
- def execute_prompt(**args)
76
- RubyLLM::MCP::Requests::PromptCall.new(self, **args).call
50
+ @resources.values
77
51
  end
78
52
 
79
- private
80
-
81
- def initialize_request
82
- @initialize_response = RubyLLM::MCP::Requests::Initialization.new(self).call
83
- @capabilities = RubyLLM::MCP::Capabilities.new(@initialize_response["result"]["capabilities"])
84
- end
53
+ def resource(name, refresh: false)
54
+ resources(refresh: refresh)
85
55
 
86
- def notification_request
87
- RubyLLM::MCP::Requests::Notification.new(self).call
56
+ @resources[name]
88
57
  end
89
58
 
90
- def tool_list_request
91
- RubyLLM::MCP::Requests::ToolList.new(self).call
92
- end
59
+ def resource_templates(refresh: false)
60
+ fetch(:resource_templates, refresh) do
61
+ templates_data = @coordinator.resource_template_list.dig("result", "resourceTemplates")
62
+ build_map(templates_data, MCP::ResourceTemplate)
63
+ end
93
64
 
94
- def resources_list_request
95
- RubyLLM::MCP::Requests::ResourceList.new(self).call
65
+ @resource_templates.values
96
66
  end
97
67
 
98
- def resource_template_list_request
99
- RubyLLM::MCP::Requests::ResourceTemplateList.new(self).call
100
- end
68
+ def resource_template(name, refresh: false)
69
+ resource_templates(refresh: refresh)
101
70
 
102
- def prompt_list_request
103
- RubyLLM::MCP::Requests::PromptList.new(self).call
71
+ @resource_templates[name]
104
72
  end
105
73
 
106
- def fetch_and_create_tools
107
- tools_response = tool_list_request
108
- tools_response = tools_response["result"]["tools"]
109
-
110
- @tools = tools_response.map do |tool|
111
- RubyLLM::MCP::Tool.new(self, tool)
74
+ def prompts(refresh: false)
75
+ fetch(:prompts, refresh) do
76
+ prompts_data = @coordinator.prompt_list.dig("result", "prompts")
77
+ build_map(prompts_data, MCP::Prompt)
112
78
  end
113
- end
114
79
 
115
- def fetch_and_create_resources(set_as_template: false)
116
- resources_response = resources_list_request
117
- resources_response = resources_response["result"]["resources"]
80
+ @prompts.values
81
+ end
118
82
 
119
- resources = {}
120
- resources_response.each do |resource|
121
- new_resource = RubyLLM::MCP::Resource.new(self, resource, template: set_as_template)
122
- resources[new_resource.name] = new_resource
123
- end
83
+ def prompt(name, refresh: false)
84
+ prompts(refresh: refresh)
124
85
 
125
- resources
86
+ @prompts[name]
126
87
  end
127
88
 
128
- def fetch_and_create_prompts
129
- prompts_response = prompt_list_request
130
- prompts_response = prompts_response["result"]["prompts"]
89
+ private
131
90
 
132
- prompts = {}
133
- prompts_response.each do |prompt|
134
- new_prompt = RubyLLM::MCP::Prompt.new(self,
135
- name: prompt["name"],
136
- description: prompt["description"],
137
- arguments: prompt["arguments"])
91
+ def fetch(cache_key, refresh)
92
+ instance_variable_set("@#{cache_key}", nil) if refresh
93
+ instance_variable_get("@#{cache_key}") || instance_variable_set("@#{cache_key}", yield)
94
+ end
138
95
 
139
- prompts[new_prompt.name] = new_prompt
96
+ def build_map(raw_data, klass)
97
+ raw_data.each_with_object({}) do |item, acc|
98
+ instance = klass.new(@coordinator, item)
99
+ acc[instance.name] = instance
140
100
  end
141
-
142
- prompts
143
101
  end
144
102
  end
145
103
  end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module MCP
5
+ class Coordinator
6
+ PROTOCOL_VERSION = "2025-03-26"
7
+ PV_2024_11_05 = "2024-11-05"
8
+
9
+ attr_reader :client, :transport_type, :config, :request_timeout, :headers, :transport, :initialize_response,
10
+ :capabilities, :protocol_version
11
+
12
+ def initialize(client, transport_type:, config: {})
13
+ @client = client
14
+ @transport_type = transport_type
15
+ @config = config
16
+
17
+ @protocol_version = PROTOCOL_VERSION
18
+ @headers = config[:headers] || {}
19
+
20
+ @transport = nil
21
+ @capabilities = nil
22
+ end
23
+
24
+ def request(body, **options)
25
+ @transport.request(body, **options)
26
+ end
27
+
28
+ def start_transport
29
+ case @transport_type
30
+ when :sse
31
+ @transport = RubyLLM::MCP::Transport::SSE.new(@config[:url],
32
+ request_timeout: @config[:request_timeout],
33
+ headers: @headers)
34
+ when :stdio
35
+ @transport = RubyLLM::MCP::Transport::Stdio.new(@config[:command],
36
+ request_timeout: @config[:request_timeout],
37
+ args: @config[:args],
38
+ env: @config[:env])
39
+ when :streamable
40
+ @transport = RubyLLM::MCP::Transport::Streamable.new(@config[:url],
41
+ request_timeout: @config[:request_timeout],
42
+ headers: @headers)
43
+ else
44
+ message = "Invalid transport type: :#{transport_type}. Supported types are :sse, :stdio, :streamable"
45
+ raise Errors::InvalidTransportType.new(message: message)
46
+ end
47
+
48
+ @initialize_response = initialize_request
49
+ @capabilities = RubyLLM::MCP::Capabilities.new(@initialize_response["result"]["capabilities"])
50
+ initialize_notification
51
+ end
52
+
53
+ def stop_transport
54
+ @transport&.close
55
+ @transport = nil
56
+ end
57
+
58
+ def restart_transport
59
+ stop_transport
60
+ start_transport
61
+ end
62
+
63
+ def alive?
64
+ !!@transport&.alive?
65
+ end
66
+
67
+ def execute_tool(**args)
68
+ RubyLLM::MCP::Requests::ToolCall.new(self, **args).call
69
+ end
70
+
71
+ def resource_read(**args)
72
+ RubyLLM::MCP::Requests::ResourceRead.new(self, **args).call
73
+ end
74
+
75
+ def completion_resource(**args)
76
+ RubyLLM::MCP::Requests::CompletionResource.new(self, **args).call
77
+ end
78
+
79
+ def completion_prompt(**args)
80
+ RubyLLM::MCP::Requests::CompletionPrompt.new(self, **args).call
81
+ end
82
+
83
+ def execute_prompt(**args)
84
+ RubyLLM::MCP::Requests::PromptCall.new(self, **args).call
85
+ end
86
+
87
+ def initialize_request
88
+ RubyLLM::MCP::Requests::Initialization.new(self).call
89
+ end
90
+
91
+ def initialize_notification
92
+ RubyLLM::MCP::Requests::InitializeNotification.new(self).call
93
+ end
94
+
95
+ def tool_list
96
+ RubyLLM::MCP::Requests::ToolList.new(self).call
97
+ end
98
+
99
+ def resource_list
100
+ RubyLLM::MCP::Requests::ResourceList.new(self).call
101
+ end
102
+
103
+ def resource_template_list
104
+ RubyLLM::MCP::Requests::ResourceTemplateList.new(self).call
105
+ end
106
+
107
+ def prompt_list
108
+ RubyLLM::MCP::Requests::PromptList.new(self).call
109
+ end
110
+ end
111
+ end
112
+ end
@@ -12,15 +12,17 @@ module RubyLLM
12
12
  end
13
13
  end
14
14
 
15
+ class CompletionNotAvailable < BaseError; end
16
+
17
+ class PromptArgumentError < BaseError; end
18
+
15
19
  class InvalidProtocolVersionError < BaseError; end
16
20
 
17
21
  class SessionExpiredError < BaseError; end
18
22
 
19
23
  class TimeoutError < BaseError; end
20
24
 
21
- class PromptArgumentError < BaseError; end
22
-
23
- class CompletionNotAvailable < BaseError; end
25
+ class InvalidTransportType < BaseError; end
24
26
  end
25
27
  end
26
28
  end
@@ -3,7 +3,18 @@
3
3
  module RubyLLM
4
4
  module MCP
5
5
  class Parameter < RubyLLM::Parameter
6
- attr_accessor :items, :properties
6
+ attr_accessor :items, :properties, :enum, :union_type, :default
7
+
8
+ def initialize(name, type: "string", desc: nil, required: true, default: nil, union_type: nil) # rubocop:disable Metrics/ParameterLists
9
+ super(name, type: type.to_sym, desc: desc, required: required)
10
+ @properties = {}
11
+ @union_type = union_type
12
+ @default = default
13
+ end
14
+
15
+ def item_type
16
+ @items["type"].to_sym
17
+ end
7
18
  end
8
19
  end
9
20
  end