Skip to content

Commit ccddd87

Browse files
authored
Merge pull request #266 from koic/allow_client_call_tool_to_accept_a_tool_name
Allow `Client#call_tool` to accept a tool name
2 parents 1b8e45f + 73070f1 commit ccddd87

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

lib/mcp/client.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,21 +92,29 @@ def prompts
9292

9393
# Calls a tool via the transport layer and returns the full response from the server.
9494
#
95+
# @param name [String] The name of the tool to call.
9596
# @param tool [MCP::Client::Tool] The tool to be called.
9697
# @param arguments [Object, nil] The arguments to pass to the tool.
9798
# @param progress_token [String, Integer, nil] A token to request progress notifications from the server during tool execution.
9899
# @return [Hash] The full JSON-RPC response from the transport.
99100
#
100-
# @example
101+
# @example Call by name
102+
# response = client.call_tool(name: "my_tool", arguments: { foo: "bar" })
103+
# content = response.dig("result", "content")
104+
#
105+
# @example Call with a tool object
101106
# tool = client.tools.first
102107
# response = client.call_tool(tool: tool, arguments: { foo: "bar" })
103108
# structured_content = response.dig("result", "structuredContent")
104109
#
105110
# @note
106111
# The exact requirements for `arguments` are determined by the transport layer in use.
107112
# Consult the documentation for your transport (e.g., MCP::Client::HTTP) for details.
108-
def call_tool(tool:, arguments: nil, progress_token: nil)
109-
params = { name: tool.name, arguments: arguments }
113+
def call_tool(name: nil, tool: nil, arguments: nil, progress_token: nil)
114+
tool_name = name || tool&.name
115+
raise ArgumentError, "Either `name:` or `tool:` must be provided." unless tool_name
116+
117+
params = { name: tool_name, arguments: arguments }
110118
if progress_token
111119
params[:_meta] = { progressToken: progress_token }
112120
end

test/mcp/client_test.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,32 @@ def test_call_tool_sends_request_to_transport_and_returns_content
6767
assert_equal([{ type: "text", text: "Hello, world!" }], content)
6868
end
6969

70+
def test_call_tool_by_name
71+
transport = mock
72+
arguments = { foo: "bar" }
73+
mock_response = {
74+
"result" => { "content" => [{ "type": "text", "text": "Hello, world!" }] },
75+
}
76+
77+
transport.expects(:send_request).with do |args|
78+
args.dig(:request, :params, :name) == "tool1" &&
79+
args.dig(:request, :params, :arguments) == arguments
80+
end.returns(mock_response).once
81+
82+
client = Client.new(transport: transport)
83+
result = client.call_tool(name: "tool1", arguments: arguments)
84+
content = result.dig("result", "content")
85+
86+
assert_equal([{ type: "text", text: "Hello, world!" }], content)
87+
end
88+
89+
def test_call_tool_raises_when_no_name_or_tool
90+
client = Client.new(transport: mock)
91+
92+
error = assert_raises(ArgumentError) { client.call_tool(arguments: { foo: "bar" }) }
93+
assert_equal("Either `name:` or `tool:` must be provided.", error.message)
94+
end
95+
7096
def test_resources_sends_request_to_transport_and_returns_resources_array
7197
transport = mock
7298
mock_response = {

0 commit comments

Comments
 (0)