Commit graph ruby-sdk/test/mcp/tool/input_schema_test.rb
Author SHA1 Message Date
Koichi ITO
1fc698bb8e Advertise JSON Schema 2020-12 dialect on emitted tool schemas
## Motivation and Context

MCP 2025-11-25 (SEP-1613) establishes JSON Schema 2020-12 as the default dialect
for MCP schema definitions.
 https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1613

The Ruby SDK was emitting tool input and output schemas with no `$schema` field,
leaving the dialect implicit and inconsistent with the TypeScript SDK
(`packages/core/src/util/standardSchema.ts`, which emits with `target: 'draft-2020-12'`)
and the Python SDK (which preserves `$schema` in its types and conformance fixtures).

`Tool::Schema#to_h` now includes `"$schema": "https://json-schema.org/draft/2020-12/schema"`
unless the user supplied a different `$schema` value, so clients see the canonical dialect URI
on the wire.

Runtime metaschema and argument validation remain on draft-04 because the `json-schema` gem
does not yet support 2020-12. Switching the runtime validator is left as a separate change
because it requires either replacing the gem or waiting for upstream 2020-12 support.

## How Has This Been Tested?

Updated `Tool::Schema#to_h` expectations across `input_schema_test`, `output_schema_test`,
`tool_test`, and the `tools/list` server tests to reflect the new `$schema` field.
Added focused regression tests:

- `to_h` preserves a user-supplied `$schema` URI rather than overwriting it
  (covered for both symbol-keyed input and the string-keyed Hash form that
  goes through the initializer's `symbolize_names` normalization)
- `validate_arguments` / `validate_result` continue to work when the user supplies
  a 2020-12 `$schema` URI on the schema (the validator strips the unknown top-level
  dialect URI before invoking the draft-04 validator, instead of raising `JSON::Schema::SchemaError`)
- `tools/list` JSON-RPC response includes the 2020-12 `$schema` on both `inputSchema`
  and `outputSchema` (transport-boundary assertion)

`bundle exec rake test` and `bundle exec rake rubocop` both pass.

## Breaking Changes

Additive change. Tolerant consumers of the `tools/list` payload are unaffected.
Consumers that strictly assert hash equality on the emitted `inputSchema` / `outputSchema`
need to account for the new `$schema` key, but no schema semantics change.

Schemas using 2020-12-only keywords (e.g. `prefixItems`, nested `$schema` on subschemas)
are still rejected by the draft-04 metaschema validator, as before.
Lifting that restriction depends on adopting a 2020-12-capable validator and is out of scope
for this change.
2026-05-11 13:44:30 +09:00
Koichi ITO
fa9f374d73
Merge pull request #237 from koic/replace_assert_empty_with_assert_equal_using_explicit_literals
Replace `assert_empty` with `assert_equal` using explicit literals
2026-03-03 01:05:16 +09:00
Koichi ITO
99cbefc610 Allow $ref in Tool::Schema for protocol version 2025-11-25
`Tool::Schema` rejected `$ref` with an `ArgumentError`.
Earlier MCP spec versions (2024-11-05 through 2025-06-18) did not define
a JSON Schema dialect or reference the `$ref` keyword. `inputSchema` was described
only as "JSON Schema defining expected parameters" with no further constraints:

- https://modelcontextprotocol.io/specification/2024-11-05/server/tools
- https://modelcontextprotocol.io/specification/2025-06-18/server/tools

The MCP spec 2025-11-25 introduced a "JSON Schema Usage" section that adopts
JSON Schema 2020-12 as the default dialect. Since `$ref` is a core keyword in 2020-12,
it is now allowed for protocol version 2025-11-25 and later.

- https://modelcontextprotocol.io/specification/2025-11-25/basic#json-schema-usage
- https://modelcontextprotocol.io/specification/2025-11-25/server/tools
- https://json-schema.org/draft/2020-12/release-notes

For backward compatibility with older protocol versions (2025-06-18 and earlier),
`Server#validate!` continues to raise `ArgumentError` when a tool input schema contains `$ref`.
This preserves the existing behavior for servers targeting those spec versions.
2026-02-27 14:33:36 +09:00
Koichi ITO
a44799b262 Replace assert_empty with assert_equal using explicit literals
Due to overly aggressive detection by RuboCop Minitest, the distinction between `[]` and `{}` was uniformly replaced with `assert_empty`,
making it impossible to differentiate between them.
As a result of https://github.com/rubocop/rubocop-minitest/issues/344, where the `Minitest/AssertEmptyLiteral` cop was disabled,
the return value has been expressed using explicit literal forms.
2026-02-24 16:09:34 +09:00
Edgars Beigarts
a3c24d2bcc
Refactor schema validation to reduce duplication and add additionalProperties support
This refactoring extracts common schema validation logic into a base Schema
class, eliminating ~100 lines of duplicate code between InputSchema and
OutputSchema. It also adds support for the JSON Schema `additionalProperties`
keyword to allow fine-grained control over extra properties in tool arguments.

Previously `additionalParameters` could be set only on OutputSchema.

Key changes:

- Created MCP::Tool::Schema base class consolidating:
  - Schema validation against JSON Schema Draft 4 metaschema
  - Deep key transformation (string to symbol conversion)
  - $ref disallowance checking
  - Common validation methods

- Refactored InputSchema to inherit from Schema:
  - Simplified constructor to accept full schema hash
  - Changed required fields storage from symbols to strings
  - Removed ~40 lines of duplicated validation logic

- Refactored OutputSchema to inherit from Schema:
  - Removed ~54 lines of duplicated validation logic
  - Now shares all common functionality with InputSchema

- Updated Tool.input_schema setter:
  - Simplified to pass full hash directly to InputSchema

- Added additionalProperties support:
  - By default, tools now allow additional properties (JSON Schema default)
  - Can explicitly set `additionalProperties: false` to disallow extras
  - Added comprehensive test coverage for both behaviors
2025-12-12 12:49:52 +02:00
Koichi ITO
122bbd0c6c
Merge pull request #102 from koic/remove_redundant_required_features
Remove redundant `require` statements
2025-08-04 06:22:56 +09:00
Koichi ITO
c5dde9ce2b Remove redundant require statements
This PR removes redundant `require` statements.
2025-08-02 00:57:31 +09:00
Piotr Usewicz
2508defc79
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.

16d91abb68/schema/2025-06-18/schema.ts (L896-L900)
2025-07-31 08:36:18 +02:00
Jens Kraemer
271ccb43d0 fixes input schema validation for schemas without required fields 2025-07-11 11:27:59 +02:00
Tyler Rowsell
8dee60cfc2
Fix: Disallow $ref in tool input schemas 2025-06-09 13:32:20 -04:00
Tyler Rowsell
934a5e8db4
Remove rescue block and add test for error bubbling in InputSchema validation 2025-06-09 10:25:51 -04:00
Tyler Rowsell
600c96f66a Validate ToolCall Args against Schema
(cherry picked from commit eeb287117535dfb43785704171625323f01d5bda)
2025-06-04 15:19:05 -04:00
Koichi ITO
f33fe309b4 Rename test directory from model_context_protocol to mcp
Follow-up to #24.

The directory structure of the product code and test code is expected to match.
2025-06-01 02:13:28 +09:00
Renamed from test/model_context_protocol/tool/input_schema_test.rb (Previous history)