[
https://issues.apache.org/jira/browse/CAMEL-25640?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18127094#comment-18127094
]
Guillaume Nodet commented on CAMEL-25640:
-----------------------------------------
This issue is being investigated by a coding agent (on behalf of gnodet).
All three sub-bugs are confirmed in current code on main:
*Bug 1 - Catalog rebuilt per call*: AuthoringTools.call() creates new
ToolContext() on every MCP tool invocation. ToolContext lazily creates a
CamelCatalog with double-checked locking, but since a new instance is created
per call, the catalog is never reused. The existing CatalogService (which
caches per version/runtime) is not used.
*Bug 2 - Kamelet tools hash-ordered subset*:
KameletTools.camel_catalog_kamelets() calls KameletCatalogHelper.loadKamelets()
on every call (no caching). The limit is applied while iterating a HashMap
before sorting, so the returned subset depends on hash iteration order -
non-deterministic across JVM runs.
*Bug 3 - Repeated-call detection counts failed calls*:
RepeatedToolCalls.repeatOf() increments the per-key count via counts.merge()
before the tool runs. If the tool throws ToolCallException, the count is
already incremented, consuming one of the two allowed attempts for an answer
that was never delivered.
_Note: This comment was generated by an AI coding agent and requires manual
verification._
> camel-jbang-mcp - catalog built per call for the authoring tools, Kamelet
> tools reload per call and return a hash-ordered subset, repeated-call
> detection counts failed calls
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-25640
> URL: https://issues.apache.org/jira/browse/CAMEL-25640
> Project: Camel
> Issue Type: Bug
> Components: camel-jbang-mcp
> Reporter: Federico Mariani
> Assignee: Guillaume Nodet
> Priority: Major
>
> Found while reviewing all tools of camel-jbang-mcp on main (4.23.0-SNAPSHOT).
> h3. 1. A catalog per call
> The 15 shared authoring tools ({{camel_catalog_doc}}, {{camel_catalog_find}},
> {{camel_validate_source}}, {{camel_error_diagnose}} ...) go through
> {{MCP/AuthoringTools.java:347}}: {{ToolRegistry.execute(tool, new
> ToolContext(), args)}}. A new {{ToolContext}} means a new
> {{DefaultCamelCatalog()}} with the cache *off*
> ({{camel-jbang-core/.../ai/ToolContext.java:174-177}}), so every call
> re-parses the JSON it touches ({{ErrorDiagnoser}} iterates all EIP models per
> call), and with {{camelVersion}} a fresh Maven resolution plus a
> {{DependencyDownloaderClassLoader}} per call ({{CatalogLoader.java:70-100}})
> that is never cached nor closed. The server's own {{CatalogService}} (cached
> per version/runtime, honours {{camel.catalog.repos}}) is not used by these
> tools. Fix: a per-version {{ToolContext}}/catalog cache in the MCP wrapper,
> or route {{ctx.catalog()}} through {{CatalogService}}.
> h3. 2. Kamelet tools
> * {{camel_catalog_kamelets}} ({{KameletTools.java:84-92}}) applies {{limit}}
> while iterating the {{HashMap}} of {{KameletsCatalog}} and sorts afterwards,
> so the default answer is the first 50 of 200+ Kamelets in hash order, with no
> {{total}} to signal the truncation.
> * Both Kamelet tools run {{KameletCatalogHelper.loadKamelets}} (new
> downloader and classloader) on every call ({{:62, 120}}), while
> {{KameletDefinitions}} in camel-jbang-core already caches the same catalog
> per version for {{camel_catalog_doc kind=kamelet}}.
> * {{:148-151}} reports any {{Throwable}} (network, Maven) as "Kamelet not
> found".
> (The consolidation issue proposes folding both into
> {{camel_catalog_doc}}/{{camel_catalog_find}}; if that lands first, only the
> cache part remains.)
> h3. 3. Repeated-call detection
> {{RepeatedToolCalls.java:64}} increments the per-session count *before* the
> tool runs, so a call that throws (catalog download failure, unsupported file
> type in {{camel_validate_source}}, missing required argument) counts as
> answered in full, and the third attempt gets "it is in your earlier tool
> result" for an answer that never existed. Count after a successful answer
> only. Also not covered although deterministic: {{camel_catalog_docs}},
> {{camel_component_properties}}, the Kamelet and example tools,
> {{camel_configuration_validate}}, {{camel_transform_route}}.
> h3. 4. Smaller
> * {{CatalogService.java:109-120, 207-211}}: {{runtime=quarkus}} with
> {{camelVersion}} and no {{platformBom}} skips the BOM lookup and calls
> {{loadQuarkusCatalog(null, ...)}}; {{ToolArgDocs.VERSION_QUERY}} explicitly
> invites that input. {{CatalogServiceTest}} covers BOM forms only.
> * {{LAST_REFUSED}}
> ({{camel-jbang-core/.../ai/AuthoringTools.java:1203-1210}}) is a static map
> keyed by path, cleared only on a successful write, shared across all MCP
> connections: unbounded, and one client's refusal count leaks into another's
> message.
> * {{CatalogTools.java:74-76}}: a negative {{limit}} ends in
> {{IllegalArgumentException}} ("Failed to list") instead of the default;
> {{ExampleTools}} treats {{<= 0}} as default and {{KameletTools}} uses it raw.
> _Claude Code on behalf of Croway_
--
This message was sent by Atlassian Jira
(v8.20.10#820010)