This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 6ab243b20b31 CAMEL-23962: Preserve all MCP inputSchema keywords in 
tool conversion
6ab243b20b31 is described below

commit 6ab243b20b310aeb158420a1886e2d9f7b8a1f10
Author: Omar Atie <[email protected]>
AuthorDate: Sat Jul 18 00:13:38 2026 -0700

    CAMEL-23962: Preserve all MCP inputSchema keywords in tool conversion
    
    McpToolConverter.convertTool() previously only copied type, properties,
    and required from the MCP tool inputSchema, dropping all other JSON
    Schema keywords. This broke schemas using $defs/$ref, additionalProperties,
    oneOf/anyOf, and root-level description. Now copies the full inputSchema
    map, defaulting type to "object" when absent.
    
    Closes #24881
---
 .../camel/component/openai/McpToolConverter.java   | 15 +++-----
 .../component/openai/McpToolConverterTest.java     | 45 ++++++++++++++++++++++
 2 files changed, 51 insertions(+), 9 deletions(-)

diff --git 
a/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/McpToolConverter.java
 
b/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/McpToolConverter.java
index 03a9cfd7118b..e9bf4ab08ad1 100644
--- 
a/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/McpToolConverter.java
+++ 
b/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/McpToolConverter.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.openai;
 
 import java.util.List;
+import java.util.Map;
 
 import com.openai.core.JsonValue;
 import com.openai.models.FunctionDefinition;
@@ -48,17 +49,13 @@ final class McpToolConverter {
 
         if (tool.inputSchema() != null) {
             FunctionParameters.Builder paramsBuilder = 
FunctionParameters.builder();
-            paramsBuilder.putAdditionalProperty("type",
-                    JsonValue.from(tool.inputSchema().getOrDefault("type", 
"object")));
+            Map<String, Object> inputSchema = tool.inputSchema();
 
-            Object properties = tool.inputSchema().get("properties");
-            if (properties != null) {
-                paramsBuilder.putAdditionalProperty("properties", 
JsonValue.from(properties));
+            if (!inputSchema.containsKey("type")) {
+                paramsBuilder.putAdditionalProperty("type", 
JsonValue.from("object"));
             }
-
-            Object required = tool.inputSchema().get("required");
-            if (required != null) {
-                paramsBuilder.putAdditionalProperty("required", 
JsonValue.from(required));
+            for (Map.Entry<String, Object> entry : inputSchema.entrySet()) {
+                paramsBuilder.putAdditionalProperty(entry.getKey(), 
JsonValue.from(entry.getValue()));
             }
 
             funcBuilder.parameters(paramsBuilder.build());
diff --git 
a/components/camel-ai/camel-openai/src/test/java/org/apache/camel/component/openai/McpToolConverterTest.java
 
b/components/camel-ai/camel-openai/src/test/java/org/apache/camel/component/openai/McpToolConverterTest.java
index d496fdfad10b..d488f40be155 100644
--- 
a/components/camel-ai/camel-openai/src/test/java/org/apache/camel/component/openai/McpToolConverterTest.java
+++ 
b/components/camel-ai/camel-openai/src/test/java/org/apache/camel/component/openai/McpToolConverterTest.java
@@ -20,10 +20,13 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+import com.openai.core.JsonValue;
+import com.openai.models.FunctionParameters;
 import com.openai.models.chat.completions.ChatCompletionFunctionTool;
 import io.modelcontextprotocol.spec.McpSchema;
 import org.junit.jupiter.api.Test;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -98,4 +101,46 @@ class McpToolConverterTest {
         assertNotNull(result);
         assertTrue(result.isEmpty());
     }
+
+    @Test
+    void convertPreservesAllInputSchemaKeywords() {
+        Map<String, Object> addressDef = Map.of("type", "object", 
"properties", Map.of("city", Map.of("type", "string")));
+        Map<String, Object> inputSchema = Map.of(
+                "type", "object",
+                "description", "Search parameters",
+                "additionalProperties", false,
+                "$defs", Map.of("Address", addressDef),
+                "properties", Map.of("query", Map.of("type", "string"), 
"address", Map.of("$ref", "#/$defs/Address")),
+                "required", List.of("query"));
+
+        McpSchema.Tool tool = McpSchema.Tool.builder("search", inputSchema)
+                .description("Search tool")
+                .build();
+
+        FunctionParameters parameters = 
McpToolConverter.convert(List.of(tool)).get(0).function().parameters().get();
+        Map<String, JsonValue> converted = parameters._additionalProperties();
+
+        assertThat(converted).containsKeys("type", "description", 
"additionalProperties", "$defs", "properties", "required");
+        assertThat(converted.get("type").asString()).contains("object");
+        assertThat(converted.get("description").asString()).contains("Search 
parameters");
+        
assertThat(converted.get("additionalProperties").asBoolean()).contains(false);
+        @SuppressWarnings("unchecked")
+        Map<String, JsonValue> defs = (Map<String, JsonValue>) 
converted.get("$defs").asObject().orElse(Map.of());
+        @SuppressWarnings("unchecked")
+        Map<String, JsonValue> properties = (Map<String, JsonValue>) 
converted.get("properties").asObject().orElse(Map.of());
+        assertThat(defs).containsKey("Address");
+        assertThat(properties).containsKey("address");
+        assertThat(converted.get("required").asArray()).isNotEmpty();
+    }
+
+    @Test
+    void convertDefaultsTypeToObjectWhenMissing() {
+        McpSchema.Tool tool = McpSchema.Tool.builder("bare_schema", 
Map.of("properties", Map.of("x", Map.of("type", "string"))))
+                .build();
+
+        FunctionParameters parameters = 
McpToolConverter.convert(List.of(tool)).get(0).function().parameters().get();
+
+        
assertThat(parameters._additionalProperties().get("type").asString()).contains("object");
+        
assertThat(parameters._additionalProperties()).containsKey("properties");
+    }
 }

Reply via email to