From bc00e907b88e9e94cab364c6e31fac74e3b93c1a Mon Sep 17 00:00:00 2001 From: Nick Van der Auwermeulen Date: Fri, 3 Oct 2025 09:53:04 -0700 Subject: [PATCH] fix: Fix issue with MCP tools throwing an error. The error "parameters.properties[segmentation_classes].items: missing field" indicates _to_gemini_schema isn't correctly handling array types. --- src/google/adk/tools/_gemini_schema_util.py | 48 +++++++++++-------- .../tools/test_gemini_schema_util.py | 4 +- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/google/adk/tools/_gemini_schema_util.py b/src/google/adk/tools/_gemini_schema_util.py index c87763431d..3c3310e9df 100644 --- a/src/google/adk/tools/_gemini_schema_util.py +++ b/src/google/adk/tools/_gemini_schema_util.py @@ -75,26 +75,34 @@ def _to_snake_case(text: str) -> str: def _sanitize_schema_type(schema: dict[str, Any]) -> dict[str, Any]: - if ("type" not in schema or not schema["type"]) and schema.keys().isdisjoint( - schema - ): - schema["type"] = "object" - if isinstance(schema.get("type"), list): - nullable = False - non_null_type = None - for t in schema["type"]: - if t == "null": - nullable = True - elif not non_null_type: - non_null_type = t - if not non_null_type: - non_null_type = "object" - if nullable: - schema["type"] = [non_null_type, "null"] - else: - schema["type"] = non_null_type - elif schema.get("type") == "null": - schema["type"] = ["object", "null"] + """Sanitizes the 'type' field and adds default 'items' for arrays.""" + type_val = schema.get("type") + non_null_type = None + nullable = False + + # First, determine the base type and nullability + if isinstance(type_val, list): + nullable = "null" in type_val + non_null_types = [t for t in type_val if t != "null"] + non_null_type = non_null_types[0] if non_null_types else None + elif type_val == "null": + nullable = True + else: + non_null_type = type_val + + # Default to 'object' if no other type is found + if not non_null_type: + non_null_type = "object" + + # Single, consolidated check to add default 'items' for arrays + if non_null_type == "array" and "items" not in schema: + schema["items"] = {"type": "string"} + + # Finally, set the schema 'type' based on nullability + if nullable: + schema["type"] = [non_null_type, "null"] + else: + schema["type"] = non_null_type return schema diff --git a/tests/unittests/tools/test_gemini_schema_util.py b/tests/unittests/tools/test_gemini_schema_util.py index f4c594d827..400fcc3889 100644 --- a/tests/unittests/tools/test_gemini_schema_util.py +++ b/tests/unittests/tools/test_gemini_schema_util.py @@ -91,7 +91,7 @@ def test_to_gemini_schema_array_string_types(self): assert gemini_schema.properties["multi_types_nullable"].nullable assert gemini_schema.properties["empty_default_object"].type == Type.OBJECT - assert gemini_schema.properties["empty_default_object"].nullable is None + assert gemini_schema.properties["empty_default_object"].nullable is False def test_to_gemini_schema_nested_objects(self): openapi_schema = { @@ -148,7 +148,7 @@ def test_to_gemini_schema_any_of(self): def test_to_gemini_schema_general_list(self): openapi_schema = { - "type": "array", + "type": "object", "properties": { "list_field": {"type": "array", "items": {"type": "string"}}, },