Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/google/adk/tools/_gemini_schema_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ def _sanitize_schema_formats_for_gemini(
)
for item in schema
]
# JSON Schema allows boolean schemas: `true` (accept any value) and `false`
# (reject all values). Gemini has no equivalent for either. `true` is
# approximated as an unconstrained object schema; `false` has no meaningful
# Gemini representation and is also mapped to an object schema as a safe
# fallback so that schema conversion does not crash.
if isinstance(schema, bool):
return {"type": "object"}
if not isinstance(schema, dict):
return schema

Expand Down
82 changes: 82 additions & 0 deletions tests/unittests/tools/test_gemini_schema_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,88 @@ def test_to_gemini_schema_properties_is_none(self):
assert gemini_schema.type == Type.OBJECT
assert gemini_schema.properties is None

def test_to_gemini_schema_boolean_true_property(self):
"""Tests that a JSON Schema boolean `true` property is handled.

JSON Schema allows `true` as a schema meaning "accept any value".
Some MCP servers use this pattern for fields whose content is not
further constrained.
"""
openapi_schema = {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"refId": {"type": "string"},
"model": True, # JSON Schema boolean schema
},
},
}
},
}
gemini_schema = _to_gemini_schema(openapi_schema)
assert isinstance(gemini_schema, Schema)
items_schema = gemini_schema.properties["items"]
assert items_schema.type == Type.ARRAY
# `model: true` should be converted to an object schema
model_schema = items_schema.items.properties["model"]
assert model_schema.type == Type.OBJECT

def test_to_gemini_schema_boolean_false_property(self):
"""Tests that a JSON Schema boolean `false` property does not raise.

`false` means "no value is valid" in JSON Schema, which has no Gemini
equivalent. Conversion falls back to an object schema to avoid crashing;
the result is semantically imprecise but safe.
"""
openapi_schema = {
"type": "object",
"properties": {
"anything": False, # JSON Schema boolean schema (reject all)
},
}
# Should not raise even though `false` has no Gemini equivalent.
gemini_schema = _to_gemini_schema(openapi_schema)
assert isinstance(gemini_schema, Schema)
assert gemini_schema.properties["anything"] is not None

def test_to_gemini_schema_boolean_true_in_array_items_properties(self):
"""Regression test: boolean `true` schema inside array item properties.

Some MCP servers use `"field": true` in an array item's properties to
indicate an unconstrained field, which is valid JSON Schema.
"""
openapi_schema = {
"type": "object",
"properties": {
"title": {"type": "string"},
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"datasourceUid": {"type": "string"},
"model": True,
"queryType": {"type": "string"},
"refId": {"type": "string"},
},
},
},
},
"required": ["title", "data"],
}
# Should not raise a ValidationError
gemini_schema = _to_gemini_schema(openapi_schema)
assert isinstance(gemini_schema, Schema)
assert gemini_schema.type == Type.OBJECT
data_schema = gemini_schema.properties["data"]
assert data_schema.type == Type.ARRAY
model_schema = data_schema.items.properties["model"]
assert model_schema.type == Type.OBJECT


class TestToSnakeCase:

Expand Down