Follow-up to https://github.com/modelcontextprotocol/ruby-sdk/pull/147.
According to the specification schema, `content` is not optional and therefore cannot be omitted:
```typescript
interface CallToolResult {
_meta?: { [key: string]: unknown };
content: ContentBlock[];
isError?: boolean;
structuredContent?: { [key: string]: unknown };
[key: string]: unknown;
}
```
https://modelcontextprotocol.io/specification/2025-06-18/schema#calltoolresult
Instead of `nil`, an empty array is set as the default value.
There may be a better value for `content`, but at the very least it should not be missing.
This commit implements optional JSON Schema validation for tool outputs according to the MCP specification:
- Add MCP::Tool::OutputSchema class mirroring InputSchema functionality
- Support output_schema in class definitions, Tool.define, and OutputSchema objects
- Include validate_result method for runtime validation
- Update MCP::Client::Tool to track output schemas
- Add comprehensive test coverage with 249 passing tests
- Update README with dedicated Tool Output Schemas section
- Follow MCP spec requirements for server/client validation
According to the specification, `destructive_hint`, `idempotent_hint`, `open_world_hint`,
and `read_only_hint` of `ToolAnnotations` are optional with default values:
https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations
This PR sets their default values in accordance with the specification.
Additionally, for readability, the hints have been reordered to follow the specification.
The tests related to `MCP::Tool::Annotations` will be extracted from the `MCP::ToolTest` test class
into a dedicated `MCP::Tool::AnnotationsTest` unit test class as a testing pair.
This improves test clarity, file level test independence, and file level execution speed.
It also ensures consistent placement as a testing pair under `MCP::Tool::*`:
```console
$ ls lib/mcp/tool/
annotations.rb input_schema.rb response.rb
$ ls test/mcp/tool/
annotations_test.rb input_schema_test.rb response_test.rb
```
Both the combination of positional argument and naming does not feel
like Ruby.
This change makes `is_error` argument a keyword argument called `error`.
Thanks to this, the usage is more self-explanatory:
```ruby
response = Response.new([], error: true)
```
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.
16d91abb68/schema/2025-06-18/schema.ts (L896-L900)