"""Tests for MCP tool adapters — input model generation and argument serialization.""" import pytest from pydantic import ValidationError from openharness.tools.mcp_tool import _input_model_from_schema class TestInputModelFromSchema: """Verify _input_model_from_schema maps JSON Schema types correctly.""" def test_required_string_rejects_none(self): schema = { "type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"], } Model = _input_model_from_schema("search", schema) with pytest.raises(ValidationError): Model(query=None) def test_required_string_accepts_value(self): schema = { "type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"], } Model = _input_model_from_schema("search", schema) m = Model(query="zigzag") assert m.query == "zigzag" def test_optional_string_defaults_to_none(self): schema = { "type": "object", "properties": { "query": {"type": "string"}, "wing": {"type": "string"}, }, "required": ["query"], } Model = _input_model_from_schema("search", schema) m = Model(query="test") assert m.wing is None def test_exclude_none_omits_optional_keeps_required(self): schema = { "type": "object", "properties": { "query": {"type": "string"}, "wing": {"type": "string"}, "limit": {"type": "integer"}, }, "required": ["query"], } Model = _input_model_from_schema("search", schema) m = Model(query="test") dumped = m.model_dump(mode="json", exclude_none=True) assert dumped == {"query": "test"} def test_all_json_types_mapped(self): schema = { "type": "object", "properties": { "name": {"type": "string"}, "count": {"type": "integer"}, "score": {"type": "number"}, "active": {"type": "boolean"}, "tags": {"type": "array"}, "meta": {"type": "object"}, }, "required": ["name", "count", "score", "active", "tags", "meta"], } Model = _input_model_from_schema("full", schema) m = Model(name="x", count=1, score=0.5, active=True, tags=["a"], meta={"k": "v"}) dumped = m.model_dump(mode="json") assert dumped == { "name": "x", "count": 1, "score": 0.5, "active": True, "tags": ["a"], "meta": {"k": "v"}, } def test_empty_schema_creates_valid_model(self): Model = _input_model_from_schema("empty", {"type": "object"}) m = Model() assert m.model_dump(mode="json") == {} def test_model_rejects_null_for_required_integer(self): schema = { "type": "object", "properties": {"limit": {"type": "integer"}}, "required": ["limit"], } Model = _input_model_from_schema("limited", schema) with pytest.raises(ValidationError): Model(limit=None)