MCP Server
Since Camel 4.22
The camel-mcp-server module exposes Camel routes registered via the
ai-tool
component as tools of a
Model Context Protocol
(MCP) server, served
over MCP streamable HTTP. No route is needed for the server itself: add the
dependency, configure which tags to expose, and every matching
ai-tool
route
becomes an MCP tool that any MCP client (another Camel application, an IDE, a
coding agent) can discover and call.
Maven users will need to add the following dependency to their
pom.xml
:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-mcp-server</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency>
Architecture
The module is split in two artifacts:
-
camel-mcp-server-api— the runtime-agnostic bridge and the smallMcpServerEngineSPI. The bridge owns tool selection (tags), execution via the sharedAiToolExecutor(per-call timeout, error sanitization) and reacts toAiToolRegistrychanges when routes start and stop. It has no dependency on the MCP Java SDK. -
camel-mcp-server— the serving engine for Camel Main and Camel JBang, built on the official MCP Java SDK with a Vert.x streamable HTTP transport. The MCP endpoint is registered on the Camel main HTTP server’s router, so it serves on the main server port (camel.server.port) and inherits its lifecycle, authentication and CORS configuration.
Engine resolution mirrors the platform-http engine: a bean of type
McpServerEngine
in the Camel registry wins; otherwise the engine is
discovered on the classpath. Other runtimes plug native engines through the
same SPI: on Quarkus the
camel-quarkus-mcp-server
extension serves through
the Quarkiverse
quarkus-mcp-server
(configured via
quarkus.mcp.server.
),
and on Spring Boot the starter serves through the Spring AI MCP server
(configured via
spring.ai.mcp.server.
). Bridge behavior — tag selection,
timeout, sanitization — is identical on every runtime and verified by a shared
conformance test kit.
Usage
Define tools as regular
ai-tool
routes and give them tags:
-
Java
-
XML
-
YAML
from("ai-tool:query_db?tags=crm" +
"&description=Query customer database" +
"¶meter.customerId=string" +
"¶meter.customerId.description=The customer id" +
"¶meter.customerId.required=true")
.to("jdbc:dataSource");
<route>
<from uri="ai-tool:query_db?tags=crm&description=Query customer database&parameter.customerId=string&parameter.customerId.description=The customer id&parameter.customerId.required=true"/>
<to uri="jdbc:dataSource"/>
</route>
- route:
from:
uri: ai-tool:query_db
parameters:
tags: crm
description: "Query customer database"
parameter.customerId: string
parameter.customerId.description: "The customer id"
parameter.customerId.required: "true"
steps:
- to:
uri: jdbc:dataSource
Tool annotation hints
ai-tool
routes can declare optional MCP
ToolAnnotations
hints
(
title
,
readOnlyHint
,
destructiveHint
,
idempotentHint
,
openWorldHint
).
The bridge passes them through to the MCP engine. See
MCP Tool Annotation Hints
for configuration examples. Hints are advisory UX metadata only — not authorization.
On Camel Main and Camel JBang no code is needed — like Jolokia or Prometheus, the server starts from configuration properties alone:
camel.server.enabled = true
camel.server.mcp-enabled = true
camel.server.mcp-tags = crm,notify
camel.server.mcp-server-name = my-integration-app
Tag patterns support wildcards: use
to expose all tagged tools, or a
prefix pattern like
crm
to expose all tags starting with
crm
:
On other runtimes, or when wiring programmatically, add the
McpServerBridge
service to the CamelContext instead:
McpServerConfiguration configuration = new McpServerConfiguration();
configuration.setTags("crm,notify");
camelContext.addService(new McpServerBridge(configuration));
The MCP endpoint is then served at
http://<host>:<port>/mcp
on the Camel
main HTTP server. Any MCP client can connect over streamable HTTP, for
example another Camel integration using the
camel-openai
MCP client:
from("direct:agent")
.to("openai:chat-completion"
+ "?model={{llm.model}}"
+ "&autoToolExecution=true"
+ "&mcpServer.myCamelTools.transportType=streamableHttp"
+ "&mcpServer.myCamelTools.url=http://localhost:8080/mcp");
Options
The options, configurable as
camel.server.mcp-*
properties on Camel Main /
JBang (see the
camel-main
options) or on
McpServerConfiguration
programmatically:
| Option | Description | Default | Owner |
|---|---|---|---|
|
|
Whether to expose ai-tool routes as MCP tools over streamable HTTP. |
|
bridge |
|
|
Comma-separated list of ai-tool tag patterns to
expose as MCP tools. Patterns support exact match, wildcard prefix
(
|
bridge |
|
|
|
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. |
|
bridge |
|
|
HTTP path where the MCP endpoint is served. |
|
engine |
|
|
MCP server name advertised to clients. |
CamelContext name |
engine |
|
|
Keep-alive ping interval in
milliseconds for MCP sessions on the Vert.x streamable transport. Dead sessions
are evicted after consecutive ping failures.
|
|
engine |
|
|
Idle TTL in milliseconds for MCP
sessions on the Vert.x streamable transport. Sessions with no activity for
longer than this interval are evicted.
|
|
engine |
Bridge-owned options are honored identically on every runtime. Engine-owned options are consumed by the Vert.x engine only; on runtimes with a native engine (Quarkus, Spring Boot) the native configuration decides serving concerns and a startup WARN is logged when an ignored option is set.
Protocol
This section describes the Vert.x engine shipped in
camel-mcp-server
, which
serves on Camel Main and Camel JBang. On Quarkus and Spring Boot the transport
is owned by the native engine instead — quarkus-mcp-server and the Spring Boot
embedded HTTP server (Spring AI MCP server) respectively — and the details
below do not apply.
The Vert.x engine implements the MCP streamable HTTP transport:
-
POST /mcpansweringapplication/jsonortext/event-streamdepending on the request, -
a long-lived
GET /mcpSSE channel for server notifications, withLast-Event-IDreplay, -
session management via the
Mcp-Session-Idheader andDELETE /mcpfor session termination. -
active session eviction: keep-alive pings (default every 30 seconds) remove sessions whose ping fails repeatedly, and an idle TTL (default 5 minutes) removes sessions with no traffic. Configure with
camel.server.mcp-session-keep-alive-intervalandcamel.server.mcp-session-idle-ttl(set either to0to disable).
Tools appearing or disappearing (routes starting and stopping) emit
notifications/tools/list_changed
to connected clients.
Security
External MCP clients are untrusted senders under the Camel security model . The module applies the following rules:
-
Explicit opt-in per tool : only tools whose tags match the configured tag patterns are exposed. The untagged default pool is never exposed, even when using the
*wildcard. -
Flat namespace protection : a tool whose name collides with an already exposed tool is refused with an ERROR log — never silently replaced.
-
Error sanitization : route exceptions are mapped to a generic error message; the cause is logged server-side and never sent to the client. Argument validation messages (missing or invalid parameters) are returned as-is.
-
Bounded execution : every call is subject to the
toolTimeout. Note that a timed-out route keeps running server-side until it completes; the timeout bounds the MCP request, not the route. -
Authentication : the MCP endpoint is served through the main HTTP server router, so platform-http authentication (basic, JWT via
camel.server.authentication*options) applies to it. The MCP specification’s authorization model is OAuth 2.1; see camel-oauth for resource-server style protection. On Quarkus and Spring Boot, authentication is owned by the native runtime security.
Runtime notes
-
Camel Main / JBang : requires the Camel main HTTP server (
camel.server.enabled=truewithcamel-platform-http-main, automatic with Camel JBang) or aVertxPlatformHttpServerservice. Serving is fully asynchronous: tool calls are offloaded to the Vert.x worker pool and the long-lived SSE channel does not occupy a worker thread. -
Quarkus : use the
camel-quarkus-mcp-serverextension (serves through quarkus-mcp-server; the MCP Java SDK is not on the classpath). -
Spring Boot : use the
camel-mcp-server-starter(serves through the Spring AI MCP server).