MCP Server
JVM since3.39.0 Native since3.39.0
The MCP Server extension exposes Camel routes registered via the ai-tool component as tools of a Model Context Protocol (MCP) server, served through the quarkiverse quarkus-mcp-server extension. No route is needed for the server itself: add the extension, tag the ai-tool routes to expose, and any MCP client (another Camel application, an IDE, a coding agent) can discover and call them.
The server is exposed over streamable HTTP. Tool semantics — tag-based opt-in (the untagged default pool is never exposed), flat-namespace collision refusal, per-call timeout and error sanitization — are owned by the camel-mcp-server-api bridge. Serving concerns (endpoint path, authentication) are owned by quarkus-mcp-server and configured via quarkus.mcp.server.*.
Maven coordinates
Or add the coordinates to your existing project:
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-mcp-server</artifactId>
</dependency> Check the User guide for more information about writing Camel Quarkus applications.
Usage
Define tools as regular ai-tool routes and give them tags:
from("ai-tool:query_db?tags=crm&description=Query customer database"
+ "¶meter.customerId=string¶meter.customerId.required=true")
.to("jdbc:dataSource"); or in YAML DSL:
- route:
from:
uri: "ai-tool:send_email"
parameters:
description: "Send email notification"
tags: "notify"
parameter.to: string
parameter.to.description: "Recipient address"
parameter.to.required: "true"
parameter.subject: string
parameter.priority: string
parameter.priority.enum: "low,normal,high"
steps:
- to: "smtp://mail.example.com" Tool parameters are declared with the parameter.NAME options: the value is the JSON type (string, integer, number, boolean), and the parameter.NAME.description, parameter.NAME.required and parameter.NAME.enum options refine the generated input schema. Arguments arrive as message headers in the route (${header.customerId}).
Combining the Camel and quarkus-mcp-server configuration
The configuration is split by ownership: quarkus.camel.mcp-server. decides *which tools exist and how they execute (semantics owned by the camel-mcp-server-api bridge), while quarkus.mcp.server. decides *how the server is exposed. Both are set side by side in application.properties:
# Camel-owned: tool selection and execution
quarkus.camel.mcp-server.tags = crm,notify
quarkus.camel.mcp-server.tool-timeout = 10000
# quarkus-mcp-server-owned: serving and server identity
quarkus.mcp.server.server-info.name = my-integration-app
quarkus.mcp.server.server-info.version = 1.0.0
quarkus.mcp.server.http.root-path = /mcp
# quarkus-mcp-server-owned: diagnostics while developing
quarkus.mcp.server.traffic-logging.enabled = true
quarkus.mcp.server.traffic-logging.text-limit = 200 See the quarkus-mcp-server configuration reference for the full list of quarkus.mcp.server.* properties (dev UI, authentication, guardrails, pagination, timeouts).
Connecting MCP clients
Any MCP client can connect over streamable HTTP. Another Camel integration can consume the tools with the camel-openai MCP client and automatic tool execution:
from("direct:agent")
.to("openai:chat-completion"
+ "?model={{llm.model}}"
+ "&autoToolExecution=true"
+ "&mcpServer.myCamelTools.transportType=streamableHttp"
+ "&mcpServer.myCamelTools.url=http://localhost:8080/mcp"); A coding agent or IDE is configured with the same URL, e.g. in an mcp.json-style client configuration:
{
"mcpServers": {
"my-integration-app": {
"type": "http",
"url": "http://localhost:8080/mcp"
}
}
} The tools are served over streamable HTTP only. The stdio transport, used by MCP clients that launch the server as a subprocess, is not supported by this extension.
Mixing with quarkus-mcp-server annotated tools
Camel tools coexist with tools defined natively with quarkus-mcp-server — both are served by the same MCP server and appear in the same tools/list. For example, a @Tool-annotated business method:
public class CalculatorTools {
@Tool(name = "add_numbers", description = "Add two numbers")
String add(
@ToolArg(description = "First addend") long a,
@ToolArg(description = "Second addend") long b) {
return String.valueOf(a + b);
}
} is exposed alongside the ai-tool routes. Annotated tools are registered at build time; Camel tools are added and removed dynamically with the route lifecycle. Choose distinct tool names — MCP has a flat tool namespace.
Dynamic tools
The exposed tool list follows the route lifecycle: stopping or suspending an ai-tool route removes its tool, starting or resuming it publishes the tool again, and connected clients are notified via notifications/tools/list_changed:
camelContext.getRouteController().stopRoute("query-db-route"); // tool disappears
camelContext.getRouteController().startRoute("query-db-route"); // tool is back Error handling
Results returned to MCP clients are sanitized by the bridge: a route exception produces an error result with the generic message Tool execution failed (the cause is logged server-side and never sent to the client), a missing or invalid argument returns the validation message, and a call exceeding quarkus.camel.mcp-server.tool-timeout returns Tool execution timed out while the route keeps running until it completes on its own.
Additional Camel Quarkus configuration
| Configuration property | Type | Default |
|---|---|---|
Whether to expose ai-tool routes as MCP tools through the quarkus-mcp-server extension. |
|
|
Comma-separated list of ai-tool tags to expose as MCP tools. Only tools registered under one of these tags are exposed; the untagged default pool is never exposed. When not set, no tools are exposed. |
| |
Per-call tool execution timeout in milliseconds. A call exceeding the timeout returns an error result to the MCP client; the underlying route keeps running until it completes on its own. |
|
|
Configuration property fixed at build time. All other configuration properties are overridable at runtime.