Mcp Server

The MCP Server starter exposes Camel routes registered via the ai-tool component as tools of a Model Context Protocol (MCP) server, served through the Spring AI MCP server over streamable HTTP. No route is needed for the server itself: add the starter, tag the ai-tool routes to expose, and any MCP client (another Camel application, an IDE, a coding agent) can discover and call them.

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 runtime-agnostic camel-mcp-server-api bridge and are identical on every Camel runtime. Serving concerns (endpoint path, protocol, server identity, authentication) are owned by the Spring AI MCP server and configured via spring.ai.mcp.server.*; use spring.ai.mcp.server.protocol=STREAMABLE for the streamable HTTP transport.

Maven coordinates

<dependency>
    <groupId>org.apache.camel.springboot</groupId>
    <artifactId>camel-mcp-server-starter</artifactId>
</dependency>

Usage

Define tools as regular ai-tool routes and give them tags:

from("ai-tool:query_db?tags=crm&description=Query customer database"
     + "&parameter.customerId=string&parameter.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 JSON Schema. Arguments arrive as message headers in the route (${header.customerId}).

Select the tags to expose in application.properties:

camel.mcp-server.tags = crm,notify

# per-call execution timeout (milliseconds, default 20000)
camel.mcp-server.tool-timeout = 10000

The streamable HTTP transport has to be selected explicitly with spring.ai.mcp.server.protocol=STREAMABLE; when the property is not set, Spring AI serves the deprecated SSE transport instead and there is no endpoint at /mcp.

Serving concerns are configured on the Spring AI MCP server — see the Spring AI MCP server documentation for the full list of spring.ai.mcp.server.* options. For example:

spring.ai.mcp.server.protocol = STREAMABLE
spring.ai.mcp.server.name = my-integration-app
spring.ai.mcp.server.version = 1.0.0
spring.ai.mcp.server.streamable-http.mcp-endpoint = /mcp

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"
    }
  }
}

Serving over stdio

Out of the box the tools are served over streamable HTTP: the starter brings in spring-ai-starter-mcp-server-webmvc. MCP clients that launch the server as a subprocess speak over stdin/stdout instead, which Spring AI serves with the plain spring-ai-starter-mcp-server. Swap the transport starter:

<dependency>
    <groupId>org.apache.camel.springboot</groupId>
    <artifactId>camel-mcp-server-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server</artifactId>
    <version>2.0.0</version>
</dependency>

and enable the stdio transport:

spring.ai.mcp.server.stdio = true
spring.main.web-application-type = none
spring.main.banner-mode = off

# stdout carries the MCP protocol, so nothing else may be written to it
logging.threshold.console = OFF
logging.file.name = my-integration-app.log

Because stdout carries the MCP protocol, the application must not run as a web application, the banner has to be switched off and console logging has to be turned off — writing the log to a file instead. Leaving console logging on corrupts the protocol stream, as the Spring Boot startup log is then interleaved with the JSON-RPC messages.

A stdio server is launched by the client instead of being connected to over a URL:

{
  "mcpServers": {
    "my-integration-app": {
      "command": "java",
      "args": ["-jar", "/path/to/my-integration-app-1.0.0.jar"]
    }
  }
}

See the Spring AI MCP Server Boot Starter documentation for the transport options and the full list of spring.ai.mcp.server.* properties. On Quarkus the equivalent setup is described in the quarkus-mcp-server stdio guide.

Mixing with Spring-defined tools

Camel tools coexist with tools defined natively in Spring AI — both are served by the same MCP server and appear in the same tools/list. For example, a @McpTool-annotated bean:

@Component
public class CalculatorTools {

    @McpTool(name = "add_numbers", description = "Add two numbers")
    public String add(
            @McpToolParam(description = "First addend", required = true) int a,
            @McpToolParam(description = "Second addend", required = true) int b) {
        return String.valueOf(a + b);
    }
}

is exposed alongside the ai-tool routes. Spring-defined tools are registered when the server is created; 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 isError 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 camel.mcp-server.tool-timeout returns Tool execution timed out while the route keeps running until it completes on its own.

On Camel Main and Camel JBang the equivalent setup is the camel-mcp-server module with the camel.server.mcp-* options; on Quarkus it is the camel-quarkus-mcp-server extension.

Spring Boot Auto-Configuration

The starter supports 3 options, which are listed below.

Name Description Default Type

camel.mcp-server.enabled

Whether to expose ai-tool routes as MCP tools through the Spring AI MCP server. Enabled by default when the starter is on the classpath.

true

Boolean

camel.mcp-server.tags

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.

String

camel.mcp-server.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

Long