ruby-sdk/lib/mcp/tool/input_schema.rb
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

28 lines
668 B
Ruby

# frozen_string_literal: true
require_relative "schema"
module MCP
class Tool
class InputSchema < Schema
class ValidationError < StandardError; end
def missing_required_arguments?(arguments)
missing_required_arguments(arguments).any?
end
def missing_required_arguments(arguments)
return [] unless schema[:required].is_a?(Array)
(schema[:required] - arguments.keys.map(&:to_s))
end
def validate_arguments(arguments)
errors = fully_validate(arguments)
if errors.any?
raise ValidationError, "Invalid arguments: #{errors.join(", ")}"
end
end
end
end
end