Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ By default, the HTTP server is disabled. To enable it, set `quarkus.http.host-en

== Available Tools

The server exposes 15 tools organized into six functional areas.
The server exposes 16 tools organized into six functional areas.

=== Catalog Exploration

Expand Down Expand Up @@ -109,6 +109,11 @@ The server exposes 15 tools organized into six functional areas.
| Validates Camel endpoint URIs against the catalog schema. Catches unknown options, missing required parameters,
invalid enum values, and type mismatches. Also provides suggestions for misspelled option names.

| `camel_validate_yaml_dsl`
| Validates a YAML DSL route definition against the Camel YAML DSL JSON schema. Checks for valid DSL elements,
correct route structure, and returns detailed schema validation errors including instance path, error type,
and schema path.

| `camel_transform_route`
| Assists with route DSL format transformation between YAML and XML.
|===
Expand Down Expand Up @@ -273,6 +278,24 @@ Validate this Kafka endpoint: kafka:myTopic?brkers=localhost:9092&groupId=myGrou
The assistant calls `camel_validate_route` and detects the typo (`brkers`), reports the URI as invalid, and
suggests the correct option name (`brokers`).

=== Validating YAML DSL Structure

----
Validate this YAML route definition for me:

- route:
from:
uri: timer:yaml
steps:
- setCheese:
simple: Hello Camel
- log: ${body}
----

The assistant calls `camel_validate_yaml_dsl` which validates the route against the Camel YAML DSL JSON schema
and reports that `setCheese` is not a valid DSL element, returning the instance path and error type so the AI
can suggest the correct processor name (e.g., `setBody`).

=== Understanding a Route

Paste a route and ask:
Expand Down
6 changes: 6 additions & 0 deletions dsl/camel-jbang/camel-jbang-mcp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@
<artifactId>camel-jbang-core</artifactId>
</dependency>

<!-- Camel YAML DSL Validator for schema validation -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-yaml-dsl-validator</artifactId>
</dependency>

<!-- test dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,23 @@
*/
package org.apache.camel.dsl.jbang.core.commands.mcp;

import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jakarta.enterprise.context.ApplicationScoped;

import com.networknt.schema.ValidationMessage;
import io.quarkiverse.mcp.server.Tool;
import io.quarkiverse.mcp.server.ToolArg;
import io.quarkiverse.mcp.server.ToolCallException;
import org.apache.camel.catalog.CamelCatalog;
import org.apache.camel.catalog.DefaultCamelCatalog;
import org.apache.camel.catalog.EndpointValidationResult;
import org.apache.camel.dsl.yaml.validator.YamlValidator;

/**
* MCP Tools for validating and transforming Camel routes using Quarkus MCP Server.
Expand All @@ -37,6 +41,7 @@
public class TransformTools {

private final CamelCatalog catalog;
private YamlValidator yamlValidator;

public TransformTools() {
this.catalog = new DefaultCamelCatalog(true);
Expand Down Expand Up @@ -150,6 +155,49 @@ public TransformResult camel_transform_route(
return result;
}

/**
* Tool to validate a YAML DSL route definition against the Camel YAML DSL JSON schema.
*/
@Tool(description = "Validate a YAML DSL route definition against the Camel YAML DSL JSON schema. "
+ "Checks for valid DSL elements, correct route structure, and returns detailed schema validation errors.")
public YamlDslValidationResult camel_validate_yaml_dsl(
@ToolArg(description = "YAML DSL route definition to validate") String route) {

if (route == null || route.isBlank()) {
throw new ToolCallException("'route' parameter is required", null);
}

try {
if (yamlValidator == null) {
yamlValidator = new YamlValidator();
yamlValidator.init();
}

File tempFile = File.createTempFile("camel-validate-", ".yaml");
try {
Files.writeString(tempFile.toPath(), route);
List<ValidationMessage> messages = yamlValidator.validate(tempFile);

List<YamlDslError> errors = null;
if (!messages.isEmpty()) {
errors = messages.stream()
.map(m -> new YamlDslError(
m.getMessage(),
m.getInstanceLocation() != null ? m.getInstanceLocation().toString() : null,
m.getType(),
m.getSchemaLocation() != null ? m.getSchemaLocation().toString() : null))
.toList();
}

return new YamlDslValidationResult(messages.isEmpty(), messages.size(), errors);
} finally {
tempFile.delete();
}
} catch (Exception e) {
throw new ToolCallException("Failed to validate YAML DSL: " + e.getMessage(), e);
}
}

/**
* Extract endpoint URIs from a YAML route definition.
*/
Expand Down Expand Up @@ -213,4 +261,10 @@ public static class TransformResult {
public boolean supported;
public String recommendation;
}

public record YamlDslValidationResult(boolean valid, int numberOfErrors, List<YamlDslError> errors) {
}

public record YamlDslError(String error, String instancePath, String type, String schemaPath) {
}
}