Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
Loading