Skip to content

Commit 762a513

Browse files
pusewiczbigH
authored andcommitted
inputSchema interface requires type key
When defining a tool without any arguments taken, it should be allowed to not have to define the `input_schema` at all, and the default value for such a scenario should be `{ type: "object" }` as per the schema. https://github.com/modelcontextprotocol/modelcontextprotocol/blob/16d91abb68bbc824944c5bda4ac2e2ccaaa74b0f/schema/2025-06-18/schema.ts#L896-L900
1 parent abd66b0 commit 762a513

File tree

5 files changed

+38
-6
lines changed

5 files changed

+38
-6
lines changed

lib/mcp/tool.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ class << self
66
NOT_SET = Object.new
77

88
attr_reader :description_value
9-
attr_reader :input_schema_value
109
attr_reader :annotations_value
1110

1211
def call(*args, server_context: nil)
@@ -43,6 +42,10 @@ def name_value
4342
@name_value || StringUtils.handle_from_class_name(name)
4443
end
4544

45+
def input_schema_value
46+
@input_schema_value || InputSchema.new
47+
end
48+
4649
def description(value = NOT_SET)
4750
if value == NOT_SET
4851
@description_value

lib/mcp/tool/input_schema.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,13 @@ def initialize(properties: {}, required: [])
1515
validate_schema!
1616
end
1717

18+
def ==(other)
19+
other.is_a?(InputSchema) && properties == other.properties && required == other.required
20+
end
21+
1822
def to_h
19-
{ type: "object", properties: }.tap do |hsh|
23+
{ type: "object" }.tap do |hsh|
24+
hsh[:properties] = properties if properties.any?
2025
hsh[:required] = required if required.any?
2126
end
2227
end

test/mcp/server_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ class ServerTest < ActiveSupport::TestCase
164164
assert_kind_of Array, result[:tools]
165165
assert_equal "test_tool", result[:tools][0][:name]
166166
assert_equal "Test tool", result[:tools][0][:description]
167-
assert_empty(result[:tools][0][:inputSchema])
167+
assert_equal({ type: "object" }, result[:tools][0][:inputSchema])
168168
assert_instrumentation_data({ method: "tools/list" })
169169
end
170170

test/mcp/tool/input_schema_test.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,21 @@ class InputSchemaTest < ActiveSupport::TestCase
7979
InputSchema.new(properties: { foo: { :$ref => "#/definitions/bar" } }, required: [:foo])
8080
end
8181
end
82+
83+
test "== compares two input schemas with the same properties and required fields" do
84+
schema1 = InputSchema.new(properties: { foo: { type: "string" } }, required: [:foo])
85+
schema2 = InputSchema.new(properties: { foo: { type: "string" } }, required: [:foo])
86+
assert_equal schema1, schema2
87+
88+
schema3 = InputSchema.new(properties: { bar: { type: "string" } }, required: [:bar])
89+
refute_equal schema1, schema3
90+
91+
schema4 = InputSchema.new(properties: { foo: { type: "string" } }, required: [:bar])
92+
refute_equal schema1, schema4
93+
94+
schema5 = InputSchema.new(properties: { bar: { type: "string" } }, required: [:foo])
95+
refute_equal schema1, schema5
96+
end
8297
end
8398
end
8499
end

test/mcp/tool_test.rb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def call(message:, server_context: nil)
2626

2727
test "#to_h returns a hash with name, description, and inputSchema" do
2828
tool = Tool.define(name: "mock_tool", description: "a mock tool for testing")
29-
assert_equal tool.to_h, { name: "mock_tool", description: "a mock tool for testing", inputSchema: {} }
29+
assert_equal tool.to_h, { name: "mock_tool", description: "a mock tool for testing", inputSchema: { type: "object" } }
3030
end
3131

3232
test "#to_h includes annotations when present" do
@@ -71,6 +71,15 @@ class DefaultNameTool < Tool
7171
assert_equal tool.tool_name, "default_name_tool"
7272
end
7373

74+
test "input schema defaults to an empty hash" do
75+
class NoInputSchemaTool < Tool; end
76+
77+
tool = NoInputSchemaTool
78+
79+
expected = { type: "object" }
80+
assert_equal expected, tool.input_schema.to_h
81+
end
82+
7483
test "accepts input schema as an InputSchema object" do
7584
class InputSchemaTool < Tool
7685
input_schema InputSchema.new(properties: { message: { type: "string" } }, required: [:message])
@@ -106,7 +115,7 @@ class InputSchemaTool < Tool
106115

107116
assert_equal tool.name_value, "mock_tool"
108117
assert_equal tool.description, "a mock tool for testing"
109-
assert_equal tool.input_schema, nil
118+
assert_equal tool.input_schema, Tool::InputSchema.new
110119
end
111120

112121
test ".define allows definition of tools with annotations" do
@@ -123,7 +132,7 @@ class InputSchemaTool < Tool
123132

124133
assert_equal tool.name_value, "mock_tool"
125134
assert_equal tool.description, "a mock tool for testing"
126-
assert_equal tool.input_schema, nil
135+
assert_equal tool.input_schema, Tool::InputSchema.new
127136
assert_equal tool.annotations_value.to_h, { title: "Mock Tool", readOnlyHint: true }
128137
end
129138

0 commit comments

Comments
 (0)