This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch pr/CAMEL-24698-mcp-optional-args in repository https://gitbox.apache.org/repos/asf/camel.git
commit dbc8fac218cd8e8f6c96fc7ce8cb6db200ae7e58 Author: Claus Ibsen <[email protected]> AuthorDate: Sun Sep 13 15:09:07 2026 +0200 CAMEL-24698: camel-jbang-mcp - runtime, camelVersion, platformBom, filter, label and limit are optional on the catalog tools; a non-version means the default catalog; EIP names in any case Squash of the 5 commits on fix/CAMEL-24698-mcp-optional-args (the run-by-run history is on bench/after-run). The old camel_catalog_doc wrapper the branch touched is gone on main since CAMEL-24695. camel-jbang-mcp - runtime, camelVersion and platformBom are optional on every catalog tool camel-jbang-mcp - a camelVersion that is not a version (main, latest) means the default catalog camel-jbang-mcp - the running Camel version, and a version that cannot be downloaded, answer from the default catalog camel-jbang-mcp - filter, label, limit and camelVersion are optional on the catalog list and doc tools camel-jbang-mcp - camel_catalog_eip_doc accepts circuit-breaker, circuitbreaker and Circuit Breaker for circuitBreaker Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Bp3538HRBPMQkb5ta9xRaj --- .../jbang/core/commands/mcp/CatalogService.java | 34 ++++++- .../dsl/jbang/core/commands/mcp/CatalogTools.java | 108 +++++++++++++-------- .../commands/mcp/ComponentPropertiesTools.java | 6 +- .../commands/mcp/ConfigurationValidateTools.java | 6 +- .../core/commands/mcp/DependencyCheckTools.java | 6 +- .../commands/mcp/DependencySecurityAuditTools.java | 6 +- .../dsl/jbang/core/commands/mcp/DiagnoseTools.java | 6 +- .../dsl/jbang/core/commands/mcp/ExplainTools.java | 6 +- .../dsl/jbang/core/commands/mcp/HardenTools.java | 6 +- .../jbang/core/commands/mcp/TestScaffoldTools.java | 4 +- .../jbang/core/commands/mcp/TransformTools.java | 6 +- .../dsl/jbang/core/commands/mcp/VersionTools.java | 2 +- .../jbang/core/commands/mcp/CatalogToolsTest.java | 9 ++ .../mcp/ConfigurationValidateToolsTest.java | 12 +++ 14 files changed, 149 insertions(+), 68 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogService.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogService.java index b43153820fdf..f148c4f76312 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogService.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogService.java @@ -79,7 +79,14 @@ public class CatalogService { public CamelCatalog loadCatalog(String runtime, String camelVersion, String platformBom) throws Exception { RuntimeType runtimeType = resolveRuntime(runtime); - boolean hasVersion = camelVersion != null && !camelVersion.isBlank(); + // "main", "latest", "current" or "default" (what an assistant writes when it means the version in use) is + // the default catalog, not a version to download + boolean hasVersion = camelVersion != null && !camelVersion.isBlank() && !camelVersion.isEmpty() + && Character.isDigit(camelVersion.trim().charAt(0)); + if (hasVersion && sameAsDefault(camelVersion)) { + // the version in use (4.23.0 for a 4.23.0-SNAPSHOT build): nothing to download + hasVersion = false; + } boolean hasBom = platformBom != null && !platformBom.isBlank(); // No version-specific parameters and main runtime -> default catalog @@ -105,7 +112,7 @@ public class CatalogService { normalizedVersion = platformBomGav.getVersion(); } } - if (platformBomGav == null && platformBom != null) { + if (platformBomGav == null && hasBom) { String[] parts = platformBom.split(":"); if (parts.length != 3) { throw new ToolCallException( @@ -121,11 +128,32 @@ public class CatalogService { return cached; } - CamelCatalog loaded = doLoadCatalog(runtimeType, camelVersion, platformBomGav); + CamelCatalog loaded; + try { + loaded = doLoadCatalog(runtimeType, camelVersion, platformBomGav); + } catch (Exception e) { + if (runtimeType == RuntimeType.main && hasVersion && !hasBom) { + // a version that cannot be downloaded (not released, no network): answer from the default catalog + // rather than fail the tool call + return defaultCatalog; + } + throw e; + } cache.putIfAbsent(key, loaded); return cache.get(key); } + /** Whether the version is the default catalog's, with or without a -SNAPSHOT qualifier. */ + boolean sameAsDefault(String camelVersion) { + String mine = defaultCatalog.getCatalogVersion(); + if (mine == null) { + return false; + } + String v = camelVersion.trim(); + return v.equals(mine) || v.equals(mine.replace("-SNAPSHOT", "")) + || mine.equals(v.replace("-SNAPSHOT", "")); + } + /** * Resolve a runtime string to a {@link RuntimeType} enum value. * diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogTools.java index 5a3b862a307d..659541cd3333 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogTools.java @@ -53,12 +53,14 @@ public class CatalogTools { + "camel_catalog_component_doc for that). " + "Use filter to search by name, label to filter by category.") public ComponentListResult camel_catalog_components( - @ToolArg(description = "Filter components by name (case-insensitive substring match)") String filter, - @ToolArg(description = "Filter by category label (e.g., cloud, messaging, database, file)") String label, - @ToolArg(description = "Maximum number of results to return (default: 20)") Integer limit, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.VERSION_QUERY) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = "Filter components by name (case-insensitive substring match)", + required = false) String filter, + @ToolArg(description = "Filter by category label (e.g., cloud, messaging, database, file)", + required = false) String label, + @ToolArg(description = "Maximum number of results to return (default: 20)", required = false) Integer limit, + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.VERSION_QUERY, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { int maxResults = limit != null ? limit : 20; @@ -106,9 +108,9 @@ public class CatalogTools { @ToolArg(description = "Whether to include message headers in the response (default: false). " + "Headers show the CamelXxx header names, their Java constants, types, and consumer/producer group.", required = false) Boolean includeHeaders, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.VERSION_QUERY) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.VERSION_QUERY, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (component == null || component.isBlank()) { throw new ToolCallException("Component name is required", null); @@ -165,9 +167,9 @@ public class CatalogTools { + "for adding it as a dependency.") public ComponentMavenResult camel_catalog_component_maven( @ToolArg(description = "Component name (e.g., kafka, http, file, timer)") String component, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.VERSION_QUERY) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.VERSION_QUERY, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (component == null || component.isBlank()) { throw new ToolCallException("Component name is required", null); @@ -199,11 +201,11 @@ public class CatalogTools { description = "List available Camel data formats for marshalling/unmarshalling " + "(e.g., json, xml, csv, avro, protobuf).") public DataFormatListResult camel_catalog_dataformats( - @ToolArg(description = "Filter by name") String filter, - @ToolArg(description = "Maximum results (default: 20)") Integer limit, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = "Filter by name", required = false) String filter, + @ToolArg(description = "Maximum results (default: 20)", required = false) Integer limit, + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { int maxResults = limit != null ? limit : 20; @@ -232,10 +234,10 @@ public class CatalogTools { description = "List available Camel expression languages " + "(e.g., simple, jsonpath, xpath, groovy, jq).") public LanguageListResult camel_catalog_languages( - @ToolArg(description = "Filter by name") String filter, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = "Filter by name", required = false) String filter, + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { try { CamelCatalog cat = catalogService.loadCatalog(runtime, camelVersion, platformBom); @@ -262,9 +264,9 @@ public class CatalogTools { + "Maven coordinates, and configuration parameters.") public DataFormatDetailResult camel_catalog_dataformat_doc( @ToolArg(description = "Data format name (e.g., json-jackson, avro, csv, protobuf, jaxb)") String dataformat, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (dataformat == null || dataformat.isBlank()) { throw new ToolCallException("Data format name is required", null); @@ -296,9 +298,9 @@ public class CatalogTools { + "Maven coordinates, and configuration parameters.") public LanguageDetailResult camel_catalog_language_doc( @ToolArg(description = "Language name (e.g., simple, jsonpath, xpath, jq, groovy)") String language, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (language == null || language.isBlank()) { throw new ToolCallException("Language name is required", null); @@ -330,11 +332,13 @@ public class CatalogTools { "EIPs have aliases for common AI/modern terms (e.g., fan-out, scatter-gather, retry, dedup). " + "Filter also matches aliases with dash normalization (fan-out, fanout, fanOut all match).") public EipListResult camel_catalog_eips( - @ToolArg(description = "Filter by name, title, description, or alias (e.g., fan-out, dedup, rate-limit)") String filter, - @ToolArg(description = "Filter by category (e.g., routing, transformation, error handling)") String label, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = "Filter by name, title, description, or alias (e.g., fan-out, dedup, rate-limit)", + required = false) String filter, + @ToolArg(description = "Filter by category (e.g., routing, transformation, error handling)", + required = false) String label, + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { try { CamelCatalog cat = catalogService.loadCatalog(runtime, camelVersion, platformBom); @@ -361,9 +365,9 @@ public class CatalogTools { description = "Get detailed documentation for a Camel EIP (Enterprise Integration Pattern).") public EipDetailResult camel_catalog_eip_doc( @ToolArg(description = "EIP name (e.g., split, aggregate, choice, filter)") String eip, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (eip == null || eip.isBlank()) { throw new ToolCallException("EIP name is required", null); @@ -373,6 +377,19 @@ public class CatalogTools { CamelCatalog cat = catalogService.loadCatalog(runtime, camelVersion, platformBom); EipModel model = cat.eipModel(eip); + if (model == null) { + // circuit-breaker, Circuit Breaker: the catalog names EIPs in camelCase + String camel = toCamelCase(eip); + model = cat.eipModel(camel); + if (model == null) { + for (String n : cat.findModelNames()) { + if (n.equalsIgnoreCase(camel)) { + model = cat.eipModel(n); + break; + } + } + } + } if (model == null) { throw new ToolCallException("EIP not found: " + eip, null); } @@ -399,9 +416,9 @@ public class CatalogTools { + "with usage examples, code snippets, and best practices. " + "Only available from Camel 4.22 onwards.") public DocListResult camel_catalog_docs( - @ToolArg(description = "Filter page names by substring (case-insensitive)") String filter, - @ToolArg(description = "Maximum number of results to return (default: 50)") Integer limit, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion) { + @ToolArg(description = "Filter page names by substring (case-insensitive)", required = false) String filter, + @ToolArg(description = "Maximum number of results to return (default: 50)", required = false) Integer limit, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion) { int maxResults = limit != null ? limit : 50; @@ -613,6 +630,21 @@ public class CatalogTools { model.getAliases().isEmpty() ? null : model.getAliases()); } + /** circuit-breaker, circuit_breaker or "Circuit Breaker" as circuitBreaker. */ + static String toCamelCase(String name) { + StringBuilder sb = new StringBuilder(); + boolean upper = false; + for (char ch : name.trim().toCharArray()) { + if (ch == '-' || ch == '_' || ch == ' ') { + upper = sb.length() > 0; + } else { + sb.append(upper ? Character.toUpperCase(ch) : ch); + upper = false; + } + } + return sb.toString(); + } + private EipDetailResult toEipDetailResult(EipModel model) { List<OptionInfo> options = new ArrayList<>(); if (model.getOptions() != null) { diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ComponentPropertiesTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ComponentPropertiesTools.java index 3b14f515aee2..f285ddd0409b 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ComponentPropertiesTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ComponentPropertiesTools.java @@ -53,9 +53,9 @@ public class ComponentPropertiesTools { "component-level defaults via the same prefix in application.properties.") public ComponentPropertiesResult camel_component_properties( @ToolArg(description = "Component name / scheme (e.g., kafka, http, file, timer)") String component, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.VERSION_QUERY) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.VERSION_QUERY, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (component == null || component.isBlank()) { throw new ToolCallException("Component name is required", null); diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ConfigurationValidateTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ConfigurationValidateTools.java index 8bff50d125c9..de13bfd8647b 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ConfigurationValidateTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ConfigurationValidateTools.java @@ -57,9 +57,9 @@ public class ConfigurationValidateTools { public ConfigurationValidateResult camel_configuration_validate( @ToolArg(description = "Configuration property lines to validate. Can be a single line " + "(e.g. \"camel.main.streamCaching=true\") or multiple lines separated by newlines.") String properties, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (properties == null || properties.isBlank()) { throw new ToolCallException("properties argument is required", null); diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DependencyCheckTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DependencyCheckTools.java index bc5b92da8616..a7fe216bf01d 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DependencyCheckTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DependencyCheckTools.java @@ -61,9 +61,9 @@ public class DependencyCheckTools { + "Sensitive content is automatically detected and masked.") String pomContent, @ToolArg(description = "Route definitions (YAML, XML, or Java DSL) to check for missing component dependencies. " + "Multiple routes can be provided concatenated.") String routes, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom, + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom, @ToolArg(description = "If true (default), automatically sanitize POM content by masking credentials") Boolean sanitizePom) { if (pomContent == null || pomContent.isBlank()) { diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DependencySecurityAuditTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DependencySecurityAuditTools.java index f482d0419992..05b5cf2a6217 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DependencySecurityAuditTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DependencySecurityAuditTools.java @@ -58,9 +58,9 @@ public class DependencySecurityAuditTools { @ToolArg(description = "The pom.xml file content") String pomContent, @ToolArg(description = "Route definitions (YAML, XML, or Java DSL) to determine which components " + "are actually used (for reachability analysis)") String routes, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom, + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom, @ToolArg(description = "If true (default), mask credentials in POM content") Boolean sanitizePom) { if (pomContent == null || pomContent.isBlank()) { diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DiagnoseTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DiagnoseTools.java index b3d8dcfb2dac..53d151e5d0c8 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DiagnoseTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/DiagnoseTools.java @@ -52,9 +52,9 @@ public class DiagnoseTools { + "ResolveEndpointFailedException, FailedToCreateRouteException, and more.") public JsonObject camel_error_diagnose( @ToolArg(description = "The Camel stack trace or error message to diagnose") String error, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (error == null || error.isBlank()) { throw new ToolCallException("Error message or stack trace is required", null); diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ExplainTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ExplainTools.java index 46cbe959d89d..57a7c75c452a 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ExplainTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/ExplainTools.java @@ -53,9 +53,9 @@ public class ExplainTools { public RouteContextResult camel_route_context( @ToolArg(description = "The Camel route content (YAML, XML, or Java DSL)") String route, @ToolArg(description = "Route format: yaml, xml, or java (default: yaml)") String format, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (route == null || route.isBlank()) { throw new ToolCallException("Route content is required", null); diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/HardenTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/HardenTools.java index 7f7bd5213ec1..9b178b0d78cc 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/HardenTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/HardenTools.java @@ -68,9 +68,9 @@ public class HardenTools { public HardenContextResult camel_route_harden_context( @ToolArg(description = "The Camel route content (YAML, XML, or Java DSL)") String route, @ToolArg(description = "Route format: yaml, xml, or java (default: yaml)") String format, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (route == null || route.isBlank()) { throw new ToolCallException("Route content is required", null); diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TestScaffoldTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TestScaffoldTools.java index 35ec249b8f87..ad0b078da2f8 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TestScaffoldTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TestScaffoldTools.java @@ -83,8 +83,8 @@ public class TestScaffoldTools { @ToolArg(description = "The Camel route definition (YAML or XML)") String route, @ToolArg(description = "Route format: yaml or xml (default: yaml)") String format, @ToolArg(description = "Target runtime: main or spring-boot (default: main)") String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (route == null || route.isBlank()) { throw new ToolCallException("Route content is required", null); diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TransformTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TransformTools.java index 37eb945716a3..a8e64dd850d1 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TransformTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TransformTools.java @@ -71,9 +71,9 @@ public class TransformTools { public ValidationResult camel_validate_route( @ToolArg(description = "Camel endpoint URI to validate (e.g., 'kafka:myTopic?brokers=localhost:9092')") String uri, @ToolArg(description = "YAML route definition to validate") String route, - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, - @ToolArg(description = ToolArgDocs.CAMEL_VERSION) String camelVersion, - @ToolArg(description = ToolArgDocs.PLATFORM_BOM) String platformBom) { + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, + @ToolArg(description = ToolArgDocs.CAMEL_VERSION, required = false) String camelVersion, + @ToolArg(description = ToolArgDocs.PLATFORM_BOM, required = false) String platformBom) { if (uri == null && route == null) { throw new ToolCallException("Either 'uri' or 'route' is required", null); diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/VersionTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/VersionTools.java index 38bbed64491d..39aa96e8f2e1 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/VersionTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/VersionTools.java @@ -46,7 +46,7 @@ public class VersionTools { description = "List available Camel versions for a specific runtime (main, spring-boot, quarkus). " + "Returns version information including release date, JDK requirements, and LTS status.") public VersionListResult camel_version_list( - @ToolArg(description = ToolArgDocs.RUNTIME) String runtime, + @ToolArg(description = ToolArgDocs.RUNTIME, required = false) String runtime, @ToolArg(description = "Only show LTS (Long Term Support) releases (default: false)") Boolean lts, @ToolArg(description = "Minimum Camel version to include (e.g., 4.0)") String fromVersion, @ToolArg(description = "Maximum number of versions to return (default: 10)") Integer limit) { diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogToolsTest.java b/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogToolsTest.java index 57ddd62c027f..3cd8fbdda06f 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogToolsTest.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/CatalogToolsTest.java @@ -355,4 +355,13 @@ class CatalogToolsTest { assertThat(mavenResult.version()).isEqualTo(requestedVersion); assertThat(mavenResult.version()).isNotEqualTo(BUILTIN_VERSION); } + + @Test + void eipDocAcceptsKebabCaseAndAnyCase() { + CatalogTools tools = createTools(null); + assertThat(tools.camel_catalog_eip_doc("circuit-breaker", null, null, null).name()).isEqualTo("circuitBreaker"); + assertThat(tools.camel_catalog_eip_doc("circuitbreaker", null, null, null).name()).isEqualTo("circuitBreaker"); + assertThat(tools.camel_catalog_eip_doc("Circuit Breaker", null, null, null).name()).isEqualTo("circuitBreaker"); + assertThat(CatalogTools.toCamelCase("poll-enrich")).isEqualTo("pollEnrich"); + } } diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/ConfigurationValidateToolsTest.java b/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/ConfigurationValidateToolsTest.java index ecbfe9248fe8..bf1a6159faae 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/ConfigurationValidateToolsTest.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/ConfigurationValidateToolsTest.java @@ -57,6 +57,18 @@ class ConfigurationValidateToolsTest { assertThat(info.issues()).isEmpty(); } + @Test + void theRunningVersionWithoutSnapshotIsTheDefaultCatalog() { + // an assistant that reads "4.23.0-SNAPSHOT" from the server asks for 4.23.0, which is not on Maven Central + ConfigurationValidateTools tools = createTools(); + String mine = tools.catalogService.getDefaultCatalog().getCatalogVersion().replace("-SNAPSHOT", ""); + + ConfigurationValidateTools.ConfigurationValidateResult result + = tools.camel_configuration_validate("camel.main.streamCachingEnabled=true", "main", mine, null); + + assertThat(result.summary().valid()).isEqualTo(1); + } + @Test void detectsUnknownOption() { ConfigurationValidateTools tools = createTools();
