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 small McpServerEngine SPI. The bridge owns tool selection (tags), execution via the shared AiToolExecutor (per-call timeout, error sanitization) and reacts to AiToolRegistry changes 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" +
    "&parameter.customerId=string" +
    "&parameter.customerId.description=The customer id" +
    "&parameter.customerId.required=true")
    .to("jdbc:dataSource");
<route>
  <from uri="ai-tool:query_db?tags=crm&amp;description=Query customer database&amp;parameter.customerId=string&amp;parameter.customerId.description=The customer id&amp;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

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

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

camel.server.mcp-enabled

Whether to expose ai-tool routes as MCP tools over streamable HTTP.

false

bridge

camel.server.mcp-tags

Comma-separated list of ai-tool tags to expose as MCP tools. Only tools registered under one of these tags are published; the untagged default pool is never exposed. When not set, no tools are published.

bridge

camel.server.mcp-tool-timeout

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.

20000

bridge

camel.server.mcp-path

HTTP path where the MCP endpoint is served.

/mcp

engine

camel.server.mcp-server-name

MCP server name advertised to clients.

CamelContext name

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 /mcp answering application/json or text/event-stream depending on the request,

  • a long-lived GET /mcp SSE channel for server notifications, with Last-Event-ID replay,

  • session management via the Mcp-Session-Id header and DELETE /mcp for session termination.

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 intersect the configured tags are exposed. The untagged default pool is never exposed implicitly.

  • 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=true with camel-platform-http-main, automatic with Camel JBang) or a VertxPlatformHttpServer service. 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-server extension (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).