You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Federico Mariani (Jira)" <ji...@apache.org> on 2026/10/14 08:15:00 UTC

[jira] [Created] (CAMEL-25642) camel-jbang-mcp - defects in the tools outside the catalog path, found in a code review: runtime wiring (receive, routeId, prompts), migration recipe data, OpenAPI scaffold

Federico Mariani created CAMEL-25642:
----------------------------------------

             Summary: camel-jbang-mcp - defects in the tools outside the catalog path, found in a code review: runtime wiring (receive, routeId, prompts), migration recipe data, OpenAPI scaffold
                 Key: CAMEL-25642
                 URL: https://issues.apache.org/jira/browse/CAMEL-25642
             Project: Camel
          Issue Type: Bug
          Components: camel-jbang-mcp
            Reporter: Federico Mariani


Umbrella for what a code review of all 86 tools (October 2026, main 4.23.0-SNAPSHOT) found in tools that no session of the coding-agent evaluation ever called, so none of it has eval evidence; everything below was verified by reading the code. Three independent PRs, one per section; the full per-tool review with file:line anchors is attached to the consolidation issue's thread.

h2. A. Runtime tools wiring
Found while reviewing all 86 tools of camel-jbang-mcp on main (4.23.0-SNAPSHOT). Five wiring defects in the runtime group, one PR.

h3. 1. {{camel_runtime_receive}} starts a permanent consumer, steals messages and returns none

{{RuntimeTools.java:693-709}} sends {{enabled=true, endpoint}} to the {{receive}} console and returns its answer. {{core/camel-console/.../ReceiveDevConsole.java:245-253}} then creates and starts a {{Consumer}} on the matching endpoint that keeps running until {{enabled=false}} is sent, which no MCP tool ever sends; received messages go into the console's queue, read only with {{dump=true}}, which is never sent either. So the tool consumes messages from the real route (seda, jms, kafka, ...), leaks a consumer per call, and the answer is just {{{enabled, endpoints}}} while the description says "consumes one message from the endpoint". It is annotated {{readOnlyHint=false, destructiveHint=false}}, so a read-write client may call it.

Fix: either drop the tool, or implement it as enable, wait for one message with a timeout, dump, disable, in one call, and mark it destructive.

h3. 2. {{routeId}} is silently ignored by route_dump, route_structure, route_analysis (and the {{routeFilter}} of ai_trace)

{{camel-jbang-core/.../commands/ai/ToolRegistry.java:250, 261, 691, 694}} put the pattern under the key {{id}}; {{dsl/camel-cli-connector/.../LocalCliConnector.java:750}} ({{doActionRouteDumpTask}}) reads {{root.getString("filter")}} and {{:775}} ({{doActionRouteStructureTask}}) reads {{getStringOrDefault("filter", "*")}}. The CLI's own commands send {{filter}} ({{CamelRouteDumpAction.java:120}}). Net effect: every call dumps all routes regardless of {{routeId}}, which with the unbounded output of these consoles is the largest answer the server gives. Only {{processor-detail}} works because {{LocalCliConnector.java:808-811}} accepts both {{routeId}} and {{id}}. No test in camel-jbang-core or camel-jbang-mcp covers these registry tools. The same tools never pass the {{limit}}/{{brief}} the consoles support ({{RouteDumpDevConsole.java:75}}, {{RouteStructureDevConsole.java:78}}).

h3. 3. The {{camel_diagnose_route}} and {{camel_optimize_route}} prompts call tools that do not exist

{{PromptDefinitions.java:242-266, 322-342}} instruct the model to call {{get_context}}, {{get_routes}}, {{get_health}}, {{get_errors}}, {{get_history}}, {{get_route_source}}, {{get_top_processors}}, {{get_inflight}}, {{get_blocked}}, {{get_memory}}, {{get_endpoints}}, {{get_route_analysis}}, {{get_eip_stats}}, {{get_route_dump}}. Those are registry names; the MCP tools are {{camel_runtime_context}}, {{camel_runtime_routes}}, ..., and {{get_top_processors}} has no counterpart at all ({{camel_runtime_top}}). Both prompts are dead on arrival.

h3. 4. {{camel_runtime_ai_trace}}

{{AiTraceTools.java:77}}: {{nameOrPid}} has no {{required = false}} ({{ToolArg.required()}} defaults to true in quarkus-mcp-server 2.0.2), contradicting the doc ("all tools accept an optional nameOrPid") and the other 41 runtime tools. {{:112-120}} swallows {{ToolExecutionException}} (including IPC timeouts) and returns {{{}}}, so a dead process yields the success answer "No AI components detected".

h3. 5. Smaller

* {{camel_runtime_http_request}} ({{RuntimeTools.java:322-341}}) drops the {{timeoutSeconds}} argument the registry declares ({{ToolRegistry.java:479}}), so the TUI and the MCP server differ.
* {{camel_runtime_memory_leak}}: default mode {{dual}} ({{RuntimeTools.java:564}}) runs two JFR recordings synchronously with {{Thread.sleep(3000)}} polling ({{:582-669}}), about 90 s, longer than most MCP client timeouts; the argument description says "default 60" but dual uses 30 ({{:583}}); {{Integer.parseInt(duration)}} at {{:585}} is unguarded.
* {{camel_runtime_history}} says "always captured (no need to enable tracing)" ({{:685-687}}); {{BacklogTracer.java:139}} records only when {{(enabled || standby) && isMessageHistory()}}. To verify at runtime and document.

h3. Hints while here
{{camel_runtime_send}} is {{destructiveHint=true}} in MCP ({{:440}}) but not in the registry ({{:330}}); {{camel_runtime_route_control}} is destructive for all four commands ({{:243}}) while the registry marks only {{stop}} ({{:562}}); {{camel_runtime_trace}} is {{readOnlyHint=false}} for the {{dump}} action too ({{:462}}), so read-only clients cannot dump traces; {{camel_runtime_heap_dump}} does not validate {{name}} for path separators ({{:524-526}}).

h2. B. Migration and dependency tools answer with wrong data
Found while reviewing all tools of camel-jbang-mcp on main (4.23.0-SNAPSHOT); all in the migration/dependency group ({{dsl/camel-jbang/camel-jbang-mcp/.../mcp/}}), verified by reading.

h3. camel_migration_recipes ({{MigrationTools.java}})
* {{:241-244}}: the Quarkus command uses the *Camel* {{targetVersion}} ("e.g. 4.18.0", {{:217}}) as the {{quarkus-maven-plugin}} version: {{io.quarkus.platform:quarkus-maven-plugin:4.18.0:update}} does not exist. It needs the Quarkus platform version ({{camel_version_list}} already returns {{quarkusVersion}} per release).
* {{:265-269}}: the Spring Boot command activates {{org.apache.camel.upgrade.CamelMigrationRecipe}} for both artifacts. In {{camel-spring-boot-upgrade-recipes}} the recipe is {{org.apache.camel.upgrade.CamelSpringBootMigrationRecipe}} (verified in apache/camel-upgrade-recipes, {{META-INF/rewrite/*.yaml}}), so OpenRewrite fails with "recipe not found".
* {{:41}}: {{OPENREWRITE_VERSION = "6.29.0"}} hardcoded; the recipes README uses the unversioned {{rewrite-maven-plugin:run}}.

h3. camel_migration_compatibility ({{MigrationTools.java}})
* {{:146-151}} and {{:277-281}}: "Camel 4.19+ requires Java 21+", reported as a *blocker* ({{compatible=false}}) for every Java 17 user targeting 4.19 or later. The catalog's {{camel-releases.json}} says jdk {{17,21}} for 4.19.0 and {{17,21,25}} for 4.20 to 4.22, and {{camel_version_list}} reads exactly that, so the two tools contradict each other. Derive from {{catalog.camelReleases()}}.
* {{:120}}: the required {{camelComponents}} argument is validated and never used; the answer is two static guide URLs plus the wrong Java rule. With the Java check moved to {{camel_migration_recipes}} the tool can go (see the consolidation issue).

h3. camel_dependency_check / camel_dependency_security_audit / camel_migration_analyze
* {{DependencyCheckTools.java:179}} compares the catalog {{artifactId}} ({{camel-kafka}}) with the POM artifactIds exactly. Spring Boot POMs have {{camel-kafka-starter}} and Quarkus {{camel-quarkus-kafka}}, so every component is reported "missing" there. The runtime mapping that {{camel_dependency_for_class}} has ({{DependencyLookup.java}}) is what this needs.
* {{DependencyData.java:55-57}} recommends {{org.apache.camel.quarkus:camel-quarkus-bom:<camelVersion>}}; the Camel version is not a camel-quarkus-bom version.
* {{MigrationData.java:234-237}} collects artifactIds from {{<dependencyManagement>}} and plugin dependencies too, so a managed-but-unused component counts as declared.
* {{DependencySecurityAuditTools.java:78}}: when the POM has no detectable Camel version (parent-managed, the normal Spring Boot/Quarkus case) the audit uses the *server's own* catalog version and reports {{clean=true}} ({{:149}}) with no warning ({{DependencyCheckTools.java:128-133}} at least says "unknown"). {{AdvisoryService.java:119-128}} matches by {{advisory.getComponents()}} only, and 16 of the 76 bundled advisories carry no components, so they can never be reported here nor by {{camel_route_harden_context}} ({{HardenTools.java:151-171}}): "clean" is not "no CVEs". {{isReachable}} returns true when no routes are passed ({{:174-176}}) and the recommendation still says "directly used in routes" ({{:200-205}}). The upgrade recommendation ({{:214-218}}, {{DependencyCheckTools.java:135-142}}) compares against {{catalog.getCatalogVersion()}}, so a SNAPSHOT server recommends upgrading 4.22.1 to 4.23.0-SNAPSHOT; {{camelReleases()}} has the real latest.

h3. Runtime detection ({{MigrationData.java}})
* {{:155-158}} sets {{isWildfly}} on {{<packaging>war}} and {{runtimeType()}} ({{:527-529}}) checks WildFly first, so a Spring Boot WAR (Tomcat deploy) is sent to {{camel_migration_wildfly_karaf}}, told "WildFly Camel subsystem is discontinued" and instructed to recreate the project from an archetype ({{MigrationWildflyKarafTools.java:50-53}}).
* The markers {{maven-war-plugin}}, {{maven-bundle-plugin}}, {{org.wildfly.plugins}} ({{:86-95}}) are compared against {{<dependency>}} elements only ({{:221-232}}), never {{<plugin>}}: dead markers.

h3. camel_properties_translate ({{PropertiesTranslateTools.java:274-280}})
Every {{camel.springboot.*}} key is rewritten to {{camel.main.*}}, although the 4.5 guide says only the special Spring Boot options keep the {{camel.springboot}} name ({{camel.springboot.lenient-configuration-binding}} still exists), which produces an invalid {{camel.main.lenient-configuration-binding}}. {{:198}} also calls {{camel.server.*}} "jbang-only"; it is camel-main.

Related: CAMEL-25536 (guide search ranking), the consolidation issue (drop {{camel_migration_compatibility}}, fold {{camel_migration_analyze}} into {{camel_dependency_check}}).

h2. C. camel_openapi_scaffold and camel_openapi_mock_guidance disagree with camel-rest-openapi
{{OpenApiTools.java}} (camel-jbang-mcp, main) scaffolds routes and mock files for the {{rest-openapi}} component, with rules that do not match what {{components/camel-rest-openapi/.../DefaultRestOpenapiProcessorStrategy.java}} does.

* *Generated operation id*: for an operation without {{operationId}} the tool builds {{GENOPID_GET_pets_id}} ({{OpenApiTools.java:98}}: {{"GENOPID_" + method + path.replace("/", "_").replace("{", "").replace("}", "")}}, and {{:376-377}}); the component builds {{GENOPID_GET.pets._id_}} ({{DefaultRestOpenapiProcessorStrategy.java:169-171}}: {{/}} becomes {{.}}, {{\{}}/{{\}}}} become {{_}}). The scaffolded {{direct:GENOPID_...}} routes are never bound, so every spec operation without an id answers 404 or falls into the missing-operation mode.
* *Mock files*: the tool says {{camel-mock/<path>.<method><ext>}} with {{_id_}} placeholders ({{:279-282}}) and returns a {{directoryStructure}}/{{mockFiles}} listing built that way; the component matches a resource whose extension-stripped location *ends with the request path* ({{:296-299}}), with no method suffix and the real path values. The whole mock listing is wrong.
* {{:436-439}}: "apiKey in query is supported by Camel" reads as enforcement; the component enforces none of the security schemes.
* {{:66-71}}: "OpenAPI 3.1 ... may not be supported" is unverified; swagger-parser 2.1 parses 3.1 and the component has no 3.0-only path.

{{camel_openapi_mock_guidance}} is static mode text ({{:486-500}}) plus a per-operation walk that duplicates {{camel_openapi_scaffold}}'s; the consolidation issue proposes folding it into the scaffold's answer when {{missingOperation=mock}}.

h3. Fix
Take the id and mock-location rules from the component (expose them as static helpers in camel-rest-openapi if needed, so the two cannot drift), and a test that scaffolds the petstore spec and binds the routes with the real component.

_Claude Code on behalf of Croway_



--
This message was sent by Atlassian Jira
(v8.20.10#820010)