ruby-mcp-client 0.7.3 → 0.8.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.
@@ -99,6 +99,10 @@ module MCPClient
99
99
  @read_timeout = opts[:read_timeout]
100
100
  @tools = nil
101
101
  @tools_data = nil
102
+ @prompts = nil
103
+ @prompts_data = nil
104
+ @resources = nil
105
+ @resources_data = nil
102
106
  @request_id = 0
103
107
  @mutex = Monitor.new
104
108
  @connection_established = false
@@ -211,6 +215,149 @@ module MCPClient
211
215
  end
212
216
  end
213
217
 
218
+ # List all prompts available from the MCP server
219
+ # @return [Array<MCPClient::Prompt>] list of available prompts
220
+ # @raise [MCPClient::Errors::PromptGetError] if prompts list retrieval fails
221
+ def list_prompts
222
+ @mutex.synchronize do
223
+ return @prompts if @prompts
224
+ end
225
+
226
+ begin
227
+ ensure_connected
228
+
229
+ prompts_data = request_prompts_list
230
+ @mutex.synchronize do
231
+ @prompts = prompts_data.map do |prompt_data|
232
+ MCPClient::Prompt.from_json(prompt_data, server: self)
233
+ end
234
+ end
235
+
236
+ @mutex.synchronize { @prompts }
237
+ rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError, MCPClient::Errors::ServerError
238
+ # Re-raise these errors directly
239
+ raise
240
+ rescue StandardError => e
241
+ raise MCPClient::Errors::PromptGetError, "Error listing prompts: #{e.message}"
242
+ end
243
+ end
244
+
245
+ # Get a prompt with the given parameters
246
+ # @param prompt_name [String] the name of the prompt to get
247
+ # @param parameters [Hash] the parameters to pass to the prompt
248
+ # @return [Object] the result of the prompt (with string keys for backward compatibility)
249
+ # @raise [MCPClient::Errors::PromptGetError] if prompt retrieval fails
250
+ def get_prompt(prompt_name, parameters)
251
+ rpc_request('prompts/get', {
252
+ name: prompt_name,
253
+ arguments: parameters.except(:_meta),
254
+ **parameters.slice(:_meta)
255
+ })
256
+ rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError
257
+ # Re-raise connection/transport errors directly
258
+ raise
259
+ rescue StandardError => e
260
+ # For all other errors, wrap in PromptGetError
261
+ raise MCPClient::Errors::PromptGetError, "Error getting prompt '#{prompt_name}': #{e.message}"
262
+ end
263
+
264
+ # List all resources available from the MCP server
265
+ # @param cursor [String, nil] optional cursor for pagination
266
+ # @return [Hash] result containing resources array and optional nextCursor
267
+ # @raise [MCPClient::Errors::ResourceReadError] if resources list retrieval fails
268
+ def list_resources(cursor: nil)
269
+ @mutex.synchronize do
270
+ return @resources_result if @resources_result && !cursor
271
+ end
272
+
273
+ begin
274
+ ensure_connected
275
+
276
+ params = {}
277
+ params['cursor'] = cursor if cursor
278
+ result = rpc_request('resources/list', params)
279
+
280
+ resources = (result['resources'] || []).map do |resource_data|
281
+ MCPClient::Resource.from_json(resource_data, server: self)
282
+ end
283
+
284
+ resources_result = { 'resources' => resources, 'nextCursor' => result['nextCursor'] }
285
+
286
+ @mutex.synchronize do
287
+ @resources_result = resources_result unless cursor
288
+ end
289
+
290
+ resources_result
291
+ rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError, MCPClient::Errors::ServerError
292
+ # Re-raise these errors directly
293
+ raise
294
+ rescue StandardError => e
295
+ raise MCPClient::Errors::ResourceReadError, "Error listing resources: #{e.message}"
296
+ end
297
+ end
298
+
299
+ # Read a resource by its URI
300
+ # @param uri [String] the URI of the resource to read
301
+ # @return [Array<MCPClient::ResourceContent>] array of resource contents
302
+ # @raise [MCPClient::Errors::ResourceReadError] if resource reading fails
303
+ def read_resource(uri)
304
+ result = rpc_request('resources/read', { uri: uri })
305
+ contents = result['contents'] || []
306
+ contents.map { |content| MCPClient::ResourceContent.from_json(content) }
307
+ rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError
308
+ # Re-raise connection/transport errors directly
309
+ raise
310
+ rescue StandardError => e
311
+ # For all other errors, wrap in ResourceReadError
312
+ raise MCPClient::Errors::ResourceReadError, "Error reading resource '#{uri}': #{e.message}"
313
+ end
314
+
315
+ # List all resource templates available from the MCP server
316
+ # @param cursor [String, nil] optional cursor for pagination
317
+ # @return [Hash] result containing resourceTemplates array and optional nextCursor
318
+ # @raise [MCPClient::Errors::ResourceReadError] for other errors during resource template listing
319
+ def list_resource_templates(cursor: nil)
320
+ params = {}
321
+ params['cursor'] = cursor if cursor
322
+ result = rpc_request('resources/templates/list', params)
323
+
324
+ templates = (result['resourceTemplates'] || []).map do |template_data|
325
+ MCPClient::ResourceTemplate.from_json(template_data, server: self)
326
+ end
327
+
328
+ { 'resourceTemplates' => templates, 'nextCursor' => result['nextCursor'] }
329
+ rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError, MCPClient::Errors::ServerError
330
+ raise
331
+ rescue StandardError => e
332
+ raise MCPClient::Errors::ResourceReadError, "Error listing resource templates: #{e.message}"
333
+ end
334
+
335
+ # Subscribe to resource updates
336
+ # @param uri [String] the URI of the resource to subscribe to
337
+ # @return [Boolean] true if subscription successful
338
+ # @raise [MCPClient::Errors::ResourceReadError] for other errors during subscription
339
+ def subscribe_resource(uri)
340
+ rpc_request('resources/subscribe', { uri: uri })
341
+ true
342
+ rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError, MCPClient::Errors::ServerError
343
+ raise
344
+ rescue StandardError => e
345
+ raise MCPClient::Errors::ResourceReadError, "Error subscribing to resource '#{uri}': #{e.message}"
346
+ end
347
+
348
+ # Unsubscribe from resource updates
349
+ # @param uri [String] the URI of the resource to unsubscribe from
350
+ # @return [Boolean] true if unsubscription successful
351
+ # @raise [MCPClient::Errors::ResourceReadError] for other errors during unsubscription
352
+ def unsubscribe_resource(uri)
353
+ rpc_request('resources/unsubscribe', { uri: uri })
354
+ true
355
+ rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError, MCPClient::Errors::ServerError
356
+ raise
357
+ rescue StandardError => e
358
+ raise MCPClient::Errors::ResourceReadError, "Error unsubscribing from resource '#{uri}': #{e.message}"
359
+ end
360
+
214
361
  # Override apply_request_headers to add session and SSE headers for MCP protocol
215
362
  def apply_request_headers(req, request)
216
363
  super
@@ -294,6 +441,10 @@ module MCPClient
294
441
  # Clear cached data
295
442
  @tools = nil
296
443
  @tools_data = nil
444
+ @prompts = nil
445
+ @prompts_data = nil
446
+ @resources = nil
447
+ @resources_data = nil
297
448
  @buffer = ''
298
449
 
299
450
  @logger.info('Cleanup completed')
@@ -381,6 +532,56 @@ module MCPClient
381
532
  raise MCPClient::Errors::ToolCallError, 'Failed to get tools list from JSON-RPC request'
382
533
  end
383
534
 
535
+ # Request the prompts list using JSON-RPC
536
+ # @return [Array<Hash>] the prompts data
537
+ # @raise [MCPClient::Errors::PromptGetError] if prompts list retrieval fails
538
+ def request_prompts_list
539
+ @mutex.synchronize do
540
+ return @prompts_data if @prompts_data
541
+ end
542
+
543
+ result = rpc_request('prompts/list')
544
+
545
+ if result.is_a?(Hash) && result['prompts']
546
+ @mutex.synchronize do
547
+ @prompts_data = result['prompts']
548
+ end
549
+ return @mutex.synchronize { @prompts_data.dup }
550
+ elsif result.is_a?(Array) || result
551
+ @mutex.synchronize do
552
+ @prompts_data = result
553
+ end
554
+ return @mutex.synchronize { @prompts_data.dup }
555
+ end
556
+
557
+ raise MCPClient::Errors::PromptGetError, 'Failed to get prompts list from JSON-RPC request'
558
+ end
559
+
560
+ # Request the resources list using JSON-RPC
561
+ # @return [Array<Hash>] the resources data
562
+ # @raise [MCPClient::Errors::ResourceReadError] if resources list retrieval fails
563
+ def request_resources_list
564
+ @mutex.synchronize do
565
+ return @resources_data if @resources_data
566
+ end
567
+
568
+ result = rpc_request('resources/list')
569
+
570
+ if result.is_a?(Hash) && result['resources']
571
+ @mutex.synchronize do
572
+ @resources_data = result['resources']
573
+ end
574
+ return @mutex.synchronize { @resources_data.dup }
575
+ elsif result.is_a?(Array) || result
576
+ @mutex.synchronize do
577
+ @resources_data = result
578
+ end
579
+ return @mutex.synchronize { @resources_data.dup }
580
+ end
581
+
582
+ raise MCPClient::Errors::ResourceReadError, 'Failed to get resources list from JSON-RPC request'
583
+ end
584
+
384
585
  # Start the long-lived GET connection for server events
385
586
  # Creates a separate thread to maintain SSE connection for server notifications
386
587
  # @return [void]
@@ -2,7 +2,7 @@
2
2
 
3
3
  module MCPClient
4
4
  # Current version of the MCP client gem
5
- VERSION = '0.7.3'
5
+ VERSION = '0.8.1'
6
6
 
7
7
  # MCP protocol version (date-based) - unified across all transports
8
8
  PROTOCOL_VERSION = '2025-03-26'
data/lib/mcp_client.rb CHANGED
@@ -3,6 +3,10 @@
3
3
  # Load all MCPClient components
4
4
  require_relative 'mcp_client/errors'
5
5
  require_relative 'mcp_client/tool'
6
+ require_relative 'mcp_client/prompt'
7
+ require_relative 'mcp_client/resource'
8
+ require_relative 'mcp_client/resource_template'
9
+ require_relative 'mcp_client/resource_content'
6
10
  require_relative 'mcp_client/server_base'
7
11
  require_relative 'mcp_client/server_stdio'
8
12
  require_relative 'mcp_client/server_sse'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-mcp-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Szymon Kurcab
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-09-01 00:00:00.000000000 Z
11
+ date: 2025-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -127,6 +127,10 @@ files:
127
127
  - lib/mcp_client/http_transport_base.rb
128
128
  - lib/mcp_client/json_rpc_common.rb
129
129
  - lib/mcp_client/oauth_client.rb
130
+ - lib/mcp_client/prompt.rb
131
+ - lib/mcp_client/resource.rb
132
+ - lib/mcp_client/resource_content.rb
133
+ - lib/mcp_client/resource_template.rb
130
134
  - lib/mcp_client/server_base.rb
131
135
  - lib/mcp_client/server_factory.rb
132
136
  - lib/mcp_client/server_http.rb