Federico Mariani created CAMEL-26400:
----------------------------------------

             Summary: camel-jbang-mcp - camel_eval_expression cannot set 
headers, variables, resultType or predicate mode, so an XPath function such as 
string() or boolean() fails and header or variable lookups come back null
                 Key: CAMEL-26400
                 URL: https://issues.apache.org/jira/browse/CAMEL-26400
             Project: Camel
          Issue Type: Improvement
          Components: camel-jbang, camel-jbang-mcp
    Affects Versions: 4.23.0
            Reporter: Federico Mariani
            Assignee: Federico Mariani


Found on main (4.24.0-SNAPSHOT, commit ffef175654d1); the line numbers below 
are from that commit. The same code is in the 4.23.0 release.

h3. Reproduction

{code}
camel_eval_expression 
{"language":"xpath","body":"<x><y/></x>","expression":"boolean(/*[local-name()='x'])"}
-> Invalid xpath: boolean(/*[local-name()='x']). Reason: ... XPathException: 
Can not convert #BOOLEAN to a NodeList!
camel_eval_expression 
{"language":"xpath","body":"<x><y/></x>","expression":"local-name(/*[local-name()='x']/*[1])"}
-> Invalid xpath: ... Can not convert #STRING to a NodeList!
camel_eval_expression {"language":"groovy","expression":"def total = 
headers.totalOrdersRows[0].total_orders as long ..."}
-> Cannot invoke method getAt() on null object
camel_eval_expression {"language":"jq","body":"[...]","expression":"[ 
(variable(\"requestBodyJson\") | fromjson).products[] | ... ]"}
-> JsonQueryTypeException: null (null) only strings can be parsed
{code}

These are correct expressions: in a route the XPath runs with {{resultType: 
java.lang.String}} (or as a predicate), and the header or variable is set by an 
earlier step. The tool takes only {{expression}}, {{language}}, {{body}} and 
{{name}}, so it has no way to evaluate them the way the route will. The XPath 
language evaluates to a node set by default, and the scratch exchange has no 
headers or variables.

Eval evidence (200 trials on 4.24.0-SNAPSHOT): 9 failed calls.
* 5 XPath calls ({{string()}}, {{boolean()}}, {{local-name()}}, 
{{not(boolean(...))}}): GLM 5.3, 3 trials. In one of them the route was failing 
with the same "Invalid xpath ... #BOOLEAN to a NodeList" (an XPath boolean 
written as an expression), and the agent used the tool to find out why. 3 tries 
in a row, then it gave up on the tool and read the xpath doc.
* 4 calls that read a header or variable the tool cannot set: Claude Haiku 5.5 
(groovy {{headers.x}}, 1), GLM 5.3 (jq {{variable(...)}}, 3). GLM tried to put 
the value in as a default argument, then wrote the JSON into the expression 
itself.

h3. Cause

* The MCP wrapper and the shared tool take no headers, variables, resultType or 
predicate argument ({{camel-jbang-mcp/.../mcp/AuthoringTools.java:310-321}}; 
{{camel-jbang-core/.../commands/ai/AuthoringTools.java:388-405}}).
* {{ExpressionEvaluator.evaluateInProcess}} sends only {{language}}, 
{{predicate}}, {{template}} and {{body}} 
({{commands/ai/ExpressionEvaluator.java:122-132}}). The eval action of the CLI 
connector already accepts {{headers}} and {{variables}} 
({{dsl/camel-cli-connector/.../LocalCliConnector.java:1208-1237}}), and so does 
{{EvalLanguageDevConsole}} 
({{core/camel-console/.../EvalLanguageDevConsole.java:55-59, 76-94}}).
* Predicate mode is inferred only for simple ({{ExpressionEvaluator.java:72}}), 
so an XPath or jsonpath predicate is always evaluated as an expression.
* {{EvalLanguageDevConsole}} and {{ExpressionEvaluator.evaluateWith}} 
({{:194-226}}) call {{language.createExpression(text)}} with no language 
options, so an XPath expression keeps its default NODESET result type.

h3. Fix

* {{camel_eval_expression}} gets optional {{headers}} and {{variables}} (JSON 
objects, or {{key=value}} lines like {{camel_runtime_send}}). They go to the 
eval action, which already supports them, and are set on the scratch exchange 
for local evaluation.
* An optional {{predicate}} (boolean) for every language, in place of the 
simple-only guess (keep the guess as the default for simple).
* An optional {{resultType}} (e.g. {{java.lang.String}}, 
{{java.lang.Boolean}}), passed as the language's own option (XPath, jsonpath, 
jq), in {{EvalLanguageDevConsole}} and in {{evaluateWith}}.
* When XPath fails with "Can not convert #STRING/#BOOLEAN/#NUMBER to a 
NodeList", answer with the fix: "this XPath returns a string: pass resultType 
java.lang.String (in the route: xpath: {expression: ..., resultType: 
java.lang.String}), or predicate=true for a boolean", in the same shape as the 
CAMEL-25952 hint.




--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to