diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d8144b..cfc63206 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Expose the server's `annotations` field on `MCP::Client::Tool` — `Client#tools`/`#list_tools` previously dropped it + ## [0.23.0] - 2026-07-07 ### Added diff --git a/lib/mcp/client.rb b/lib/mcp/client.rb index f568b25a..2d46a31e 100644 --- a/lib/mcp/client.rb +++ b/lib/mcp/client.rb @@ -131,6 +131,7 @@ def list_tools(cursor: nil, meta: nil, cancellation: nil) description: tool["description"], input_schema: tool["inputSchema"], output_schema: tool["outputSchema"], + annotations: tool["annotations"], ) end diff --git a/lib/mcp/client/tool.rb b/lib/mcp/client/tool.rb index b348d4de..bfefda85 100644 --- a/lib/mcp/client/tool.rb +++ b/lib/mcp/client/tool.rb @@ -3,13 +3,14 @@ module MCP class Client class Tool - attr_reader :name, :description, :input_schema, :output_schema + attr_reader :name, :description, :input_schema, :output_schema, :annotations - def initialize(name:, description:, input_schema:, output_schema: nil) + def initialize(name:, description:, input_schema:, output_schema: nil, annotations: nil) @name = name @description = description @input_schema = input_schema @output_schema = output_schema + @annotations = annotations end end end diff --git a/test/mcp/client/tool_test.rb b/test/mcp/client/tool_test.rb index 88e82e91..f2025abf 100644 --- a/test/mcp/client/tool_test.rb +++ b/test/mcp/client/tool_test.rb @@ -33,6 +33,24 @@ def test_output_schema_returns_nil_when_not_provided assert_nil(@tool.output_schema) end + def test_annotations_returns_nil_when_not_provided + assert_nil(@tool.annotations) + end + + def test_annotations_returns_annotations_when_provided + tool_with_annotations = Tool.new( + name: "test_tool_with_annotations", + description: "A test tool with annotations", + input_schema: { "type" => "object" }, + annotations: { "readOnlyHint" => true, "title" => "Test Tool" }, + ) + + assert_equal( + { "readOnlyHint" => true, "title" => "Test Tool" }, + tool_with_annotations.annotations, + ) + end + def test_output_schema_returns_output_schema_when_provided tool_with_output = Tool.new( name: "test_tool_with_output", @@ -53,12 +71,14 @@ def test_initialization_with_all_parameters description: "A tool with all parameters", input_schema: { "type" => "object" }, output_schema: { "type" => "object", "properties" => { "status" => { "type" => "boolean" } } }, + annotations: { "readOnlyHint" => true }, ) assert_equal("full_tool", tool.name) assert_equal("A tool with all parameters", tool.description) assert_equal({ "type" => "object" }, tool.input_schema) assert_equal({ "type" => "object", "properties" => { "status" => { "type" => "boolean" } } }, tool.output_schema) + assert_equal({ "readOnlyHint" => true }, tool.annotations) end end end diff --git a/test/mcp/client_test.rb b/test/mcp/client_test.rb index 296c0f53..68caba8f 100644 --- a/test/mcp/client_test.rb +++ b/test/mcp/client_test.rb @@ -86,6 +86,7 @@ def test_tools_sends_request_to_transport_and_returns_tools_array "description" => "tool1", "inputSchema" => {}, "outputSchema" => { "type" => "object", "properties" => { "result" => { "type" => "string" } } }, + "annotations" => { "readOnlyHint" => true, "title" => "Tool One" }, }, { "name" => "tool2", "description" => "tool2", "inputSchema" => {} }, ], @@ -103,8 +104,10 @@ def test_tools_sends_request_to_transport_and_returns_tools_array assert_equal(2, tools.size) assert_equal("tool1", tools.first.name) assert_equal({ "type" => "object", "properties" => { "result" => { "type" => "string" } } }, tools.first.output_schema) + assert_equal({ "readOnlyHint" => true, "title" => "Tool One" }, tools.first.annotations) assert_equal("tool2", tools.last.name) assert_nil(tools.last.output_schema) + assert_nil(tools.last.annotations) end def test_tools_returns_empty_array_when_no_tools