diff --git a/crates/language_model_core/src/tool_schema.rs b/crates/language_model_core/src/tool_schema.rs index 0e82b2f41081469c6c04d16765e8336eb903fd94..86e6d6d137e469dc3b743a40eeb1f2f50348395b 100644 --- a/crates/language_model_core/src/tool_schema.rs +++ b/crates/language_model_core/src/tool_schema.rs @@ -118,6 +118,15 @@ fn adapt_to_json_schema_subset(json: &mut Value) -> Result<()> { } } + // Ensure that the type field is not an array. This can happen with MCP tool + // schemas that use multiple types (e.g. `["string", "number"]` or `["string", "null"]`). + if let Some(type_value) = obj.get_mut("type") + && let Some(types) = type_value.as_array() + && let Some(first_type) = types.first().cloned() + { + *type_value = first_type; + } + if matches!(obj.get("description"), Some(Value::String(_))) && !obj.contains_key("type") && !(obj.contains_key("anyOf") @@ -307,6 +316,42 @@ mod tests { ); } + #[test] + fn test_transform_array_type_to_single_type() { + let mut json = json!({ + "type": "object", + "properties": { + "projectSlugOrId": { + "type": ["string", "number"], + "description": "Project slug or numeric ID" + }, + "optionalName": { + "type": ["string", "null"], + "description": "An optional name" + } + } + }); + + adapt_to_json_schema_subset(&mut json).unwrap(); + + assert_eq!( + json, + json!({ + "type": "object", + "properties": { + "projectSlugOrId": { + "type": "string", + "description": "Project slug or numeric ID" + }, + "optionalName": { + "type": "string", + "description": "An optional name" + } + } + }) + ); + } + #[test] fn test_transform_fails_if_unsupported_keys_exist() { let mut json = json!({