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.
- checksums.yaml +4 -4
- data/README.md +257 -13
- data/lib/mcp_client/client.rb +225 -6
- data/lib/mcp_client/errors.rb +18 -0
- data/lib/mcp_client/prompt.rb +41 -0
- data/lib/mcp_client/resource.rb +61 -0
- data/lib/mcp_client/resource_content.rb +80 -0
- data/lib/mcp_client/resource_template.rb +57 -0
- data/lib/mcp_client/server_base.rb +55 -0
- data/lib/mcp_client/server_http.rb +142 -0
- data/lib/mcp_client/server_sse/json_rpc_transport.rb +1 -0
- data/lib/mcp_client/server_sse.rb +217 -1
- data/lib/mcp_client/server_stdio/json_rpc_transport.rb +6 -0
- data/lib/mcp_client/server_stdio.rb +182 -0
- data/lib/mcp_client/server_streamable_http.rb +201 -0
- data/lib/mcp_client/version.rb +1 -1
- data/lib/mcp_client.rb +4 -0
- metadata +6 -2
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MCPClient
|
4
|
+
# Representation of an MCP prompt
|
5
|
+
class Prompt
|
6
|
+
# @!attribute [r] name
|
7
|
+
# @return [String] the name of the prompt
|
8
|
+
# @!attribute [r] description
|
9
|
+
# @return [String] the description of the prompt
|
10
|
+
# @!attribute [r] arguments
|
11
|
+
# @return [Hash] the JSON arguments for the prompt
|
12
|
+
# @!attribute [r] server
|
13
|
+
# @return [MCPClient::ServerBase, nil] the server this prompt belongs to
|
14
|
+
attr_reader :name, :description, :arguments, :server
|
15
|
+
|
16
|
+
# Initialize a new prompt
|
17
|
+
# @param name [String] the name of the prompt
|
18
|
+
# @param description [String] the description of the prompt
|
19
|
+
# @param arguments [Hash] the JSON arguments for the prompt
|
20
|
+
# @param server [MCPClient::ServerBase, nil] the server this prompt belongs to
|
21
|
+
def initialize(name:, description:, arguments: {}, server: nil)
|
22
|
+
@name = name
|
23
|
+
@description = description
|
24
|
+
@arguments = arguments
|
25
|
+
@server = server
|
26
|
+
end
|
27
|
+
|
28
|
+
# Create a Prompt instance from JSON data
|
29
|
+
# @param data [Hash] JSON data from MCP server
|
30
|
+
# @param server [MCPClient::ServerBase, nil] the server this prompt belongs to
|
31
|
+
# @return [MCPClient::Prompt] prompt instance
|
32
|
+
def self.from_json(data, server: nil)
|
33
|
+
new(
|
34
|
+
name: data['name'],
|
35
|
+
description: data['description'],
|
36
|
+
arguments: data['arguments'] || {},
|
37
|
+
server: server
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MCPClient
|
4
|
+
# Representation of an MCP resource
|
5
|
+
class Resource
|
6
|
+
# @!attribute [r] uri
|
7
|
+
# @return [String] unique identifier for the resource
|
8
|
+
# @!attribute [r] name
|
9
|
+
# @return [String] the name of the resource
|
10
|
+
# @!attribute [r] title
|
11
|
+
# @return [String, nil] optional human-readable name of the resource for display purposes
|
12
|
+
# @!attribute [r] description
|
13
|
+
# @return [String, nil] optional description
|
14
|
+
# @!attribute [r] mime_type
|
15
|
+
# @return [String, nil] optional MIME type
|
16
|
+
# @!attribute [r] size
|
17
|
+
# @return [Integer, nil] optional size in bytes
|
18
|
+
# @!attribute [r] annotations
|
19
|
+
# @return [Hash, nil] optional annotations that provide hints to clients
|
20
|
+
# @!attribute [r] server
|
21
|
+
# @return [MCPClient::ServerBase, nil] the server this resource belongs to
|
22
|
+
attr_reader :uri, :name, :title, :description, :mime_type, :size, :annotations, :server
|
23
|
+
|
24
|
+
# Initialize a new resource
|
25
|
+
# @param uri [String] unique identifier for the resource
|
26
|
+
# @param name [String] the name of the resource
|
27
|
+
# @param title [String, nil] optional human-readable name of the resource for display purposes
|
28
|
+
# @param description [String, nil] optional description
|
29
|
+
# @param mime_type [String, nil] optional MIME type
|
30
|
+
# @param size [Integer, nil] optional size in bytes
|
31
|
+
# @param annotations [Hash, nil] optional annotations that provide hints to clients
|
32
|
+
# @param server [MCPClient::ServerBase, nil] the server this resource belongs to
|
33
|
+
def initialize(uri:, name:, title: nil, description: nil, mime_type: nil, size: nil, annotations: nil, server: nil)
|
34
|
+
@uri = uri
|
35
|
+
@name = name
|
36
|
+
@title = title
|
37
|
+
@description = description
|
38
|
+
@mime_type = mime_type
|
39
|
+
@size = size
|
40
|
+
@annotations = annotations
|
41
|
+
@server = server
|
42
|
+
end
|
43
|
+
|
44
|
+
# Create a Resource instance from JSON data
|
45
|
+
# @param data [Hash] JSON data from MCP server
|
46
|
+
# @param server [MCPClient::ServerBase, nil] the server this resource belongs to
|
47
|
+
# @return [MCPClient::Resource] resource instance
|
48
|
+
def self.from_json(data, server: nil)
|
49
|
+
new(
|
50
|
+
uri: data['uri'],
|
51
|
+
name: data['name'],
|
52
|
+
title: data['title'],
|
53
|
+
description: data['description'],
|
54
|
+
mime_type: data['mimeType'],
|
55
|
+
size: data['size'],
|
56
|
+
annotations: data['annotations'],
|
57
|
+
server: server
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MCPClient
|
4
|
+
# Representation of MCP resource content
|
5
|
+
# Resources can contain either text or binary data
|
6
|
+
class ResourceContent
|
7
|
+
# @!attribute [r] uri
|
8
|
+
# @return [String] unique identifier for the resource
|
9
|
+
# @!attribute [r] name
|
10
|
+
# @return [String] the name of the resource
|
11
|
+
# @!attribute [r] title
|
12
|
+
# @return [String, nil] optional human-readable name for display purposes
|
13
|
+
# @!attribute [r] mime_type
|
14
|
+
# @return [String, nil] optional MIME type
|
15
|
+
# @!attribute [r] text
|
16
|
+
# @return [String, nil] text content (mutually exclusive with blob)
|
17
|
+
# @!attribute [r] blob
|
18
|
+
# @return [String, nil] base64-encoded binary content (mutually exclusive with text)
|
19
|
+
# @!attribute [r] annotations
|
20
|
+
# @return [Hash, nil] optional annotations that provide hints to clients
|
21
|
+
attr_reader :uri, :name, :title, :mime_type, :text, :blob, :annotations
|
22
|
+
|
23
|
+
# Initialize resource content
|
24
|
+
# @param uri [String] unique identifier for the resource
|
25
|
+
# @param name [String] the name of the resource
|
26
|
+
# @param title [String, nil] optional human-readable name for display purposes
|
27
|
+
# @param mime_type [String, nil] optional MIME type
|
28
|
+
# @param text [String, nil] text content (mutually exclusive with blob)
|
29
|
+
# @param blob [String, nil] base64-encoded binary content (mutually exclusive with text)
|
30
|
+
# @param annotations [Hash, nil] optional annotations that provide hints to clients
|
31
|
+
def initialize(uri:, name:, title: nil, mime_type: nil, text: nil, blob: nil, annotations: nil)
|
32
|
+
raise ArgumentError, 'ResourceContent cannot have both text and blob' if text && blob
|
33
|
+
raise ArgumentError, 'ResourceContent must have either text or blob' if !text && !blob
|
34
|
+
|
35
|
+
@uri = uri
|
36
|
+
@name = name
|
37
|
+
@title = title
|
38
|
+
@mime_type = mime_type
|
39
|
+
@text = text
|
40
|
+
@blob = blob
|
41
|
+
@annotations = annotations
|
42
|
+
end
|
43
|
+
|
44
|
+
# Create a ResourceContent instance from JSON data
|
45
|
+
# @param data [Hash] JSON data from MCP server
|
46
|
+
# @return [MCPClient::ResourceContent] resource content instance
|
47
|
+
def self.from_json(data)
|
48
|
+
new(
|
49
|
+
uri: data['uri'],
|
50
|
+
name: data['name'],
|
51
|
+
title: data['title'],
|
52
|
+
mime_type: data['mimeType'],
|
53
|
+
text: data['text'],
|
54
|
+
blob: data['blob'],
|
55
|
+
annotations: data['annotations']
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Check if content is text
|
60
|
+
# @return [Boolean] true if content is text
|
61
|
+
def text?
|
62
|
+
!@text.nil?
|
63
|
+
end
|
64
|
+
|
65
|
+
# Check if content is binary
|
66
|
+
# @return [Boolean] true if content is binary
|
67
|
+
def binary?
|
68
|
+
!@blob.nil?
|
69
|
+
end
|
70
|
+
|
71
|
+
# Get the content (text or decoded blob)
|
72
|
+
# @return [String] the content
|
73
|
+
def content
|
74
|
+
return @text if text?
|
75
|
+
|
76
|
+
require 'base64'
|
77
|
+
Base64.decode64(@blob)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MCPClient
|
4
|
+
# Representation of an MCP resource template
|
5
|
+
# Resource templates allow servers to expose parameterized resources using URI templates
|
6
|
+
class ResourceTemplate
|
7
|
+
# @!attribute [r] uri_template
|
8
|
+
# @return [String] URI template following RFC 6570
|
9
|
+
# @!attribute [r] name
|
10
|
+
# @return [String] the name of the resource template
|
11
|
+
# @!attribute [r] title
|
12
|
+
# @return [String, nil] optional human-readable name for display purposes
|
13
|
+
# @!attribute [r] description
|
14
|
+
# @return [String, nil] optional description
|
15
|
+
# @!attribute [r] mime_type
|
16
|
+
# @return [String, nil] optional MIME type for resources created from this template
|
17
|
+
# @!attribute [r] annotations
|
18
|
+
# @return [Hash, nil] optional annotations that provide hints to clients
|
19
|
+
# @!attribute [r] server
|
20
|
+
# @return [MCPClient::ServerBase, nil] the server this resource template belongs to
|
21
|
+
attr_reader :uri_template, :name, :title, :description, :mime_type, :annotations, :server
|
22
|
+
|
23
|
+
# Initialize a new resource template
|
24
|
+
# @param uri_template [String] URI template following RFC 6570
|
25
|
+
# @param name [String] the name of the resource template
|
26
|
+
# @param title [String, nil] optional human-readable name for display purposes
|
27
|
+
# @param description [String, nil] optional description
|
28
|
+
# @param mime_type [String, nil] optional MIME type
|
29
|
+
# @param annotations [Hash, nil] optional annotations that provide hints to clients
|
30
|
+
# @param server [MCPClient::ServerBase, nil] the server this resource template belongs to
|
31
|
+
def initialize(uri_template:, name:, title: nil, description: nil, mime_type: nil, annotations: nil, server: nil)
|
32
|
+
@uri_template = uri_template
|
33
|
+
@name = name
|
34
|
+
@title = title
|
35
|
+
@description = description
|
36
|
+
@mime_type = mime_type
|
37
|
+
@annotations = annotations
|
38
|
+
@server = server
|
39
|
+
end
|
40
|
+
|
41
|
+
# Create a ResourceTemplate instance from JSON data
|
42
|
+
# @param data [Hash] JSON data from MCP server
|
43
|
+
# @param server [MCPClient::ServerBase, nil] the server this resource template belongs to
|
44
|
+
# @return [MCPClient::ResourceTemplate] resource template instance
|
45
|
+
def self.from_json(data, server: nil)
|
46
|
+
new(
|
47
|
+
uri_template: data['uriTemplate'],
|
48
|
+
name: data['name'],
|
49
|
+
title: data['title'],
|
50
|
+
description: data['description'],
|
51
|
+
mime_type: data['mimeType'],
|
52
|
+
annotations: data['annotations'],
|
53
|
+
server: server
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -33,6 +33,61 @@ module MCPClient
|
|
33
33
|
raise NotImplementedError, 'Subclasses must implement call_tool'
|
34
34
|
end
|
35
35
|
|
36
|
+
# List all prompts available from the MCP server
|
37
|
+
# @return [Array<MCPClient::Prompt>] list of available prompts
|
38
|
+
def list_prompts
|
39
|
+
raise NotImplementedError, 'Subclasses must implement list_prompts'
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get a prompt with the given parameters
|
43
|
+
# @param prompt_name [String] the name of the prompt to get
|
44
|
+
# @param parameters [Hash] the parameters to pass to the prompt
|
45
|
+
# @return [Object] the result of the prompt interpolation
|
46
|
+
def get_prompt(prompt_name, parameters)
|
47
|
+
raise NotImplementedError, 'Subclasses must implement get_prompt'
|
48
|
+
end
|
49
|
+
|
50
|
+
# List all resources available from the MCP server
|
51
|
+
# @param cursor [String, nil] optional cursor for pagination
|
52
|
+
# @return [Hash] result containing resources array and optional nextCursor
|
53
|
+
def list_resources(cursor: nil)
|
54
|
+
raise NotImplementedError, 'Subclasses must implement list_resources'
|
55
|
+
end
|
56
|
+
|
57
|
+
# Read a resource by its URI
|
58
|
+
# @param uri [String] the URI of the resource to read
|
59
|
+
# @return [Array<MCPClient::ResourceContent>] array of resource contents
|
60
|
+
def read_resource(uri)
|
61
|
+
raise NotImplementedError, 'Subclasses must implement read_resource'
|
62
|
+
end
|
63
|
+
|
64
|
+
# List all resource templates available from the MCP server
|
65
|
+
# @param cursor [String, nil] optional cursor for pagination
|
66
|
+
# @return [Hash] result containing resourceTemplates array and optional nextCursor
|
67
|
+
def list_resource_templates(cursor: nil)
|
68
|
+
raise NotImplementedError, 'Subclasses must implement list_resource_templates'
|
69
|
+
end
|
70
|
+
|
71
|
+
# Subscribe to resource updates
|
72
|
+
# @param uri [String] the URI of the resource to subscribe to
|
73
|
+
# @return [Boolean] true if subscription successful
|
74
|
+
def subscribe_resource(uri)
|
75
|
+
raise NotImplementedError, 'Subclasses must implement subscribe_resource'
|
76
|
+
end
|
77
|
+
|
78
|
+
# Unsubscribe from resource updates
|
79
|
+
# @param uri [String] the URI of the resource to unsubscribe from
|
80
|
+
# @return [Boolean] true if unsubscription successful
|
81
|
+
def unsubscribe_resource(uri)
|
82
|
+
raise NotImplementedError, 'Subclasses must implement unsubscribe_resource'
|
83
|
+
end
|
84
|
+
|
85
|
+
# Get server capabilities
|
86
|
+
# @return [Hash, nil] server capabilities
|
87
|
+
def capabilities
|
88
|
+
raise NotImplementedError, 'Subclasses must implement capabilities'
|
89
|
+
end
|
90
|
+
|
36
91
|
# Clean up the server connection
|
37
92
|
def cleanup
|
38
93
|
raise NotImplementedError, 'Subclasses must implement cleanup'
|
@@ -216,6 +216,148 @@ module MCPClient
|
|
216
216
|
end
|
217
217
|
end
|
218
218
|
|
219
|
+
# List all prompts available from the MCP server
|
220
|
+
# @return [Array<MCPClient::Prompt>] list of available prompts
|
221
|
+
# @raise [MCPClient::Errors::ServerError] if server returns an error
|
222
|
+
# @raise [MCPClient::Errors::TransportError] if response isn't valid JSON
|
223
|
+
# @raise [MCPClient::Errors::PromptGetError] for other errors during prompt listing
|
224
|
+
def list_prompts
|
225
|
+
@mutex.synchronize do
|
226
|
+
return @prompts if @prompts
|
227
|
+
end
|
228
|
+
|
229
|
+
begin
|
230
|
+
ensure_connected
|
231
|
+
|
232
|
+
prompts_data = rpc_request('prompts/list')
|
233
|
+
prompts = prompts_data['prompts'] || []
|
234
|
+
|
235
|
+
@mutex.synchronize do
|
236
|
+
@prompts = prompts.map do |prompt_data|
|
237
|
+
MCPClient::Prompt.from_json(prompt_data, server: self)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
@mutex.synchronize { @prompts }
|
242
|
+
rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError, MCPClient::Errors::ServerError
|
243
|
+
raise
|
244
|
+
rescue StandardError => e
|
245
|
+
raise MCPClient::Errors::PromptGetError, "Error listing prompts: #{e.message}"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# Get a prompt with the given parameters
|
250
|
+
# @param prompt_name [String] the name of the prompt to get
|
251
|
+
# @param parameters [Hash] the parameters to pass to the prompt
|
252
|
+
# @return [Object] the result of the prompt interpolation
|
253
|
+
# @raise [MCPClient::Errors::ServerError] if server returns an error
|
254
|
+
# @raise [MCPClient::Errors::TransportError] if response isn't valid JSON
|
255
|
+
# @raise [MCPClient::Errors::PromptGetError] for other errors during prompt interpolation
|
256
|
+
def get_prompt(prompt_name, parameters)
|
257
|
+
rpc_request('prompts/get', {
|
258
|
+
name: prompt_name,
|
259
|
+
arguments: parameters
|
260
|
+
})
|
261
|
+
rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError
|
262
|
+
raise
|
263
|
+
rescue StandardError => e
|
264
|
+
raise MCPClient::Errors::PromptGetError, "Error getting prompt '#{prompt_name}': #{e.message}"
|
265
|
+
end
|
266
|
+
|
267
|
+
# List all resources available from the MCP server
|
268
|
+
# @param cursor [String, nil] optional cursor for pagination
|
269
|
+
# @return [Hash] result containing resources array and optional nextCursor
|
270
|
+
# @raise [MCPClient::Errors::ResourceReadError] if resources list retrieval fails
|
271
|
+
def list_resources(cursor: nil)
|
272
|
+
@mutex.synchronize do
|
273
|
+
return @resources_result if @resources_result && !cursor
|
274
|
+
end
|
275
|
+
|
276
|
+
begin
|
277
|
+
ensure_connected
|
278
|
+
|
279
|
+
params = {}
|
280
|
+
params['cursor'] = cursor if cursor
|
281
|
+
result = rpc_request('resources/list', params)
|
282
|
+
|
283
|
+
resources = (result['resources'] || []).map do |resource_data|
|
284
|
+
MCPClient::Resource.from_json(resource_data, server: self)
|
285
|
+
end
|
286
|
+
|
287
|
+
resources_result = { 'resources' => resources, 'nextCursor' => result['nextCursor'] }
|
288
|
+
|
289
|
+
@mutex.synchronize do
|
290
|
+
@resources_result = resources_result unless cursor
|
291
|
+
end
|
292
|
+
|
293
|
+
resources_result
|
294
|
+
rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError, MCPClient::Errors::ServerError
|
295
|
+
raise
|
296
|
+
rescue StandardError => e
|
297
|
+
raise MCPClient::Errors::ResourceReadError, "Error listing resources: #{e.message}"
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# Read a resource by its URI
|
302
|
+
# @param uri [String] the URI of the resource to read
|
303
|
+
# @return [Array<MCPClient::ResourceContent>] array of resource contents
|
304
|
+
# @raise [MCPClient::Errors::ResourceReadError] if resource reading fails
|
305
|
+
def read_resource(uri)
|
306
|
+
result = rpc_request('resources/read', { uri: uri })
|
307
|
+
contents = result['contents'] || []
|
308
|
+
contents.map { |content| MCPClient::ResourceContent.from_json(content) }
|
309
|
+
rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError
|
310
|
+
raise
|
311
|
+
rescue StandardError => e
|
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
|
+
|
219
361
|
# Stream tool call (default implementation returns single-value stream)
|
220
362
|
# @param tool_name [String] the name of the tool to call
|
221
363
|
# @param parameters [Hash] the parameters to pass to the tool
|
@@ -7,6 +7,7 @@ module MCPClient
|
|
7
7
|
# JSON-RPC request/notification plumbing for SSE transport
|
8
8
|
module JsonRpcTransport
|
9
9
|
include JsonRpcCommon
|
10
|
+
|
10
11
|
# Generic JSON-RPC request: send method with params and return result
|
11
12
|
# @param method [String] JSON-RPC method name
|
12
13
|
# @param params [Hash] parameters for the request
|