使用说明
Apache Camel MCP Component
Apache Camel 4 extension that speaks the Model Context Protocol (MCP) over JSON-RPC so agents and automations can call your Camel routes as tools.
Project Home: https://github.com/dscope-io/dscope-camel-mcp#readme
🏷 Repository Metadata
- Description: Apache Camel MCP component enabling Model Context Protocol client/server routes over HTTP/WebSocket.
- Topics:
ai-integration,apache-camel,camel-component,java,json-rpc,mcp,model-context-protocol
Note: These values mirror the GitHub repository settings (Description, Topics, Homepage). Keep both in sync when updating project metadata.
📦 Versions
| Channel | Version | Maven Coordinate | Notes |
|---|---|---|---|
| Latest Release | 1.5.0 | io.dscope.camel:camel-mcp:1.5.0 |
Recommended for production use |
| Local build | 1.5.0 | io.dscope.camel:camel-mcp:1.5.0 |
Build from source (mvn install); includes reusable MCP Events webhooks |
Maven Central:
- https://central.sonatype.com/artifact/io.dscope.camel/camel-mcp
- https://repo1.maven.org/maven2/io/dscope/camel/camel-mcp/
📋 Requirements
- Java 21+
- Maven 3.9+
- Apache Camel 4.22.0+
🚀 Features
- Producer (client) mode: Send MCP JSON-RPC requests to remote servers via
to("mcp:http://host/mcp?method=tools/list"). - Consumer (server) mode: Expose MCP endpoints with
from("mcp:http://0.0.0.0:3000/mcp")— built-in request validation, JSON-RPC parsing, rate limiting, and response serialization. - Implements core MCP methods:
initialize,ping,resources/list,resources/read,resources/get,tools/list,tools/call,health, andstream. - MCP Apps Bridge support:
ui/initialize,ui/message,ui/update-model-context, andui/tools/callfor embedded UI integration. - MCP Events (2026-07-28): Application provider SPI and optional discovery, signed callback verification and delivery with public-address pinning. See Events API.
- Notifications:
notifications/initialized,notifications/cancelled,notifications/progress. - HTTP and WebSocket transports for both producer and consumer modes.
- Ships 20+ registry processors for JSON-RPC envelopes, tool catalogs, resource catalogs, and notification workflows.
- Apache Karavan integration: Generated visual designer metadata for drag-and-drop MCP route building.
- Camel tooling support:
@UriEndpoint-based component descriptor generation (mcp.json) for IDE autocompletion and documentation. - Two sample projects and Postman collections to exercise MCP flows end-to-end.
📖 Development Guide - Learn how to build your own MCP services with YAML and Java routes.
🛠 Installation
Maven Dependency (Release)
<dependency>
<groupId>io.dscope.camel</groupId>
<artifactId>camel-mcp</artifactId>
<version>1.5.0</version>
</dependency>
Gradle Dependency (Release)
dependencies {
implementation "io.dscope.camel:camel-mcp:1.5.0"
}
Build From Source (Snapshot)
git clone https://github.com/dscope-io/dscope-camel-mcp.git
cd dscope-camel-mcp
mvn clean install
🔧 Configuration
URI Format
Producer (Client) Mode:
mcp:http://host:port/mcp?method=tools/list
mcp:camel:direct:localMcpRoute?method=tools/list
Consumer (Server) Mode:
mcp:http://host:port/path
mcp:http://host:port/path?websocket=true
Configuration Options
| Option | Default | Mode | Purpose |
|---|---|---|---|
method |
tools/list |
Producer | MCP JSON-RPC method to invoke when producing |
websocket |
false |
Consumer | Enable WebSocket transport instead of HTTP |
sendToAll |
false |
Consumer | Broadcast WebSocket messages to all clients |
allowedOrigins |
* |
Consumer | CORS allowed origins for WebSocket |
httpMethodRestrict |
POST |
Consumer | Restrict HTTP methods (e.g., POST, GET) |
Producer Mode
The exchange body should be a Map representing MCP params. The producer enriches it with jsonrpc, id, and the configured method before invoking the downstream HTTP endpoint.
You can override the endpoint method per message with header CamelMcpMethod.
For local MCP services exposed as Camel routes, use the URI prefix camel: after mcp:.
Dispatch is selected by endpoint URI structure:
mcp:camel:<camel-endpoint-uri>-> local Camel route dispatch (in-process)mcp:http://.../mcp:https://...-> remote JSON transport dispatch
Example local dispatch from Java routes:
from("direct:start")
.setBody(constant(Map.of("clientInfo", Map.of("name", "local-client", "version", "1.0.0"))))
.to("mcp:camel:direct:localMcpService?method=initialize")
.log("${body}");
Remote vs Local Producer (YAML)
Remote MCP producer route:
- route:
id: remote-mcp-client
from:
uri: "direct:remoteMcp"
steps:
- setBody:
constant:
clientInfo:
name: "camel-client"
version: "1.0.0"
- to:
uri: "mcp:http://localhost:8080/mcp?method=initialize"
- setBody:
simple: "${body[result]}"
Local MCP producer route + local service route:
- route:
id: local-mcp-client
from:
uri: "direct:localMcpClient"
steps:
- setBody:
constant:
probe: true
- to:
uri: "mcp:camel:direct:localMcpService?method=ping"
- setBody:
simple: "${body[result]}"
- route:
id: local-mcp-service
from:
uri: "direct:localMcpService"
steps:
- setBody:
simple: |
{
"jsonrpc": "2.0",
"id": "${body[id]}",
"result": {
"method": "${body[method]}",
"pong": true,
"local": true
}
}
- unmarshal:
json:
library: Jackson
Java Helper API
Use io.dscope.camel.mcp.McpClient for Java-friendly calls that return MCP result payloads directly:
ProducerTemplate template = camelContext.createProducerTemplate();
String endpoint = "mcp:http://localhost:8080/mcp?method=initialize";
Object pingResult = McpClient.pingResult(template, endpoint);
Object toolsResult = McpClient.toolsListResult(template, endpoint);
JsonNode pingJson = McpClient.pingResultJson(template, endpoint);
JsonNode toolsJson = McpClient.toolsListResultJson(template, endpoint);
Object initializeResult = McpClient.callResult(
template,
endpoint,
"initialize",
Map.of("clientInfo", Map.of("name", "java-client", "version", "1.0.0"))
);
JsonNode initializeJson = McpClient.callResultJson(
template,
endpoint,
"initialize",
Map.of("clientInfo", Map.of("name", "java-client", "version", "1.0.0"))
);
Consumer Mode
The consumer creates an HTTP or WebSocket server endpoint that:
- Validates incoming requests (headers, content-type)
- Parses JSON-RPC envelopes
- Extracts method and parameters to exchange properties
- Routes to your processor
- Serializes responses to JSON
Exchange properties set by the consumer:
mcp.jsonrpc.type- REQUEST, NOTIFICATION, or RESPONSEmcp.jsonrpc.id- Request ID for responsesmcp.jsonrpc.method- The MCP method being calledmcp.tool.name- Tool name (for tools/call)
� WebSocket Transport
The component supports WebSocket connections for persistent, bidirectional MCP sessions. This is ideal for:
- Long-running agent sessions
- Streaming responses
- Real-time notifications
Endpoints
| Protocol | Endpoint | Purpose |
|---|---|---|
| HTTP | http://localhost:8080/mcp |
Request/response style |
| WebSocket | ws://localhost:8090/mcp |
Persistent bidirectional |
WebSocket Route Configuration
The sample service configures WebSocket via Undertow:
- route:
id: mcp-service-ws
from:
uri: "undertow:ws://127.0.0.1:8090/mcp?sendToAll=false&allowedOrigins=http://localhost,http://127.0.0.1&exchangePattern=InOut"
| Option | Default | Purpose |
|---|---|---|
sendToAll |
false |
Send response only to originating client |
allowedOrigins |
* |
CORS allowed origins (use specific domains in production) |
exchangePattern |
InOut |
Enable request/response pattern |
Connecting with wscat
# Install wscat (one-time)
npm install -g wscat
# Connect to MCP WebSocket
npx wscat -c ws://localhost:8090/mcp
Alternative WebSocket Clients
- websocat:
websocat ws://localhost:8090/mcp - VS Code: Install "WebSocket Client" extension
- Postman: Import WebSocket collection from
samples/mcp-service/postman/ - Python: Use
websocketslibrary - JavaScript: Native
WebSocketAPI orwspackage
Python Example
import asyncio
import websockets
import json
async def mcp_client():
async with websockets.connect('ws://localhost:8090/mcp') as ws:
# Initialize session
await ws.send(json.dumps({
"jsonrpc": "2.0",
"id": "1",
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": {"name": "python-client", "version": "1.0.0"}
}
}))
print(await ws.recv())
# List tools
await ws.send(json.dumps({
"jsonrpc": "2.0",
"id": "2",
"method": "tools/list"
}))
print(await ws.recv())
asyncio.run(mcp_client())
JavaScript/Node.js Example
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:8090/mcp');
ws.on('open', () => {
// Initialize session
ws.send(JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "initialize",
params: {
protocolVersion: "2024-11-05",
clientInfo: { name: "node-client", version: "1.0.0" }
}
}));
});
ws.on('message', (data) => {
console.log('Received:', JSON.parse(data));
});
�📚 Usage Examples
Calling MCP Methods via curl
All MCP methods use JSON-RPC 2.0 format. Here's how to call each supported method:
initialize - Start an MCP session
curl -s -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": {
"name": "my-client",
"version": "1.0.0"
},
"capabilities": {}
}
}' \
http://localhost:8080/mcp | jq '.'
ping - Health check
curl -s -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"jsonrpc": "2.0", "id": "2", "method": "ping"}' \
http://localhost:8080/mcp | jq '.'
tools/list - List available tools
curl -s -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"jsonrpc": "2.0", "id": "3", "method": "tools/list"}' \
http://localhost:8080/mcp | jq '.'
resources/list - List available resources
curl -s -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"jsonrpc": "2.0", "id": "4", "method": "resources/list"}' \
http://localhost:8080/mcp | jq '.'
tools/call - Execute a tool
curl -s -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "4",
"method": "tools/call",
"params": {
"name": "echo",
"arguments": {
"message": "Hello from MCP!"
}
}
}' \
http://localhost:8080/mcp | jq '.'
resources/get - Fetch a resource
# JSON resource
curl -s -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "5",
"method": "resources/get",
"params": {
"resource": "example-resource"
}
}' \
http://localhost:8080/mcp | jq '.'
# Binary resource (returns base64)
curl -s -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"jsonrpc": "2.0", "id": "6", "method": "resources/get", "params": {"resource": "sample-image.jpg"}}' \
http://localhost:8080/mcp | jq '.'
MCP Apps Bridge (UI Methods)
The component supports the MCP Apps Bridge specification for embedding interactive UIs within AI agent workflows.
ui/initialize - Start a UI session
curl -s -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "ui-1",
"method": "ui/initialize",
"params": {
"clientInfo": {"name": "my-ui", "version": "1.0.0"},
"resourceUri": "mcp://resource/chart-editor.html",
"toolName": "chart-editor"
}
}' \
http://localhost:8080/mcp | jq '.'
Response includes a sessionId for subsequent UI calls:
{
"result": {
"sessionId": "abc123-...",
"hostInfo": {"name": "camel-mcp", "version": "1.5.0"},
"capabilities": ["tools/call", "ui/message", "ui/update-model-context"]
}
}
ui/tools/call - Execute a tool from UI context
curl -s -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "ui-2",
"method": "ui/tools/call",
"params": {
"sessionId": "<sessionId-from-ui-initialize>",
"name": "echo",
"arguments": {"text": "Hello from UI!"}
}
}' \
http://localhost:8080/mcp | jq '.'
ui/message - Send messages from embedded UI
curl -s -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "ui-3",
"method": "ui/message",
"params": {
"sessionId": "<sessionId>",
"type": "user-action",
"payload": {"action": "button-clicked"}
}
}' \
http://localhost:8080/mcp | jq '.'
ui/update-model-context - Update AI model context
curl -s -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "ui-4",
"method": "ui/update-model-context",
"params": {
"sessionId": "<sessionId>",
"context": {"chartConfig": {"type": "bar", "data": [1,2,3]}},
"mode": "merge"
}
}' \
http://localhost:8080/mcp | jq '.'
Calling MCP Methods via WebSocket
npx wscat -c ws://localhost:8090/mcp
# Initialize
> {"jsonrpc":"2.0","id":"1","method":"initialize","params":{"protocolVersion":"2024-11-05","clientInfo":{"name":"ws-client","version":"1.0.0"}}}
# Ping
> {"jsonrpc":"2.0","id":"2","method":"ping"}
# List tools
> {"jsonrpc":"2.0","id":"3","method":"tools/list"}
# Call a tool
> {"jsonrpc":"2.0","id":"4","method":"tools/call","params":{"name":"echo","arguments":{"message":"Hello"}}}
# Get a resource
> {"jsonrpc":"2.0","id":"5","method":"resources/get","params":{"resource":"example-resource"}}
Minimal YAML Client (Camel Route)
- route:
id: example-mcp-client
from:
uri: "timer://runOnce?repeatCount=1"
steps:
- setBody:
constant: |
{
"method": "initialize",
"params": {
"clientInfo": {
"name": "camel-mcp",
"version": "1.0.0"
}
}
}
- unmarshal:
json:
library: Jackson
- to:
uri: "mcp:http://localhost:8080/mcp?method=initialize"
- log:
message: "MCP Response: ${body}"
Resources/Get With Sample Service
The resources/get method supports automatic content type detection:
- Binary (images, PDFs, fonts) → returned as base64
blob - Text (html, css, js, md) → returned as
textwith MIME type - JSON (no extension) → returned as structured data
- route:
id: example-resources-client
from:
uri: "timer://resources?repeatCount=1"
steps:
- setBody:
constant: |
{
"params": {
"resource": "example-resource"
}
}
- unmarshal:
json:
library: Jackson
- to:
uri: "mcp:http://localhost:8080/mcp?method=resources/get"
- log:
message: "Resource payload: ${body[result]}"
MCP Server (Consumer) Examples
The MCP consumer allows you to create MCP protocol servers that listen for incoming JSON-RPC requests.
Basic HTTP Server
from("mcp:http://localhost:8080/mcp")
.process(exchange -> {
// Your custom MCP request processing
String method = exchange.getProperty("mcp.jsonrpc.method", String.class);
Map<String, Object> params = exchange.getIn().getBody(Map.class);
// Process request and set response
Map<String, Object> response = Map.of(
"jsonrpc", "2.0",
"id", exchange.getProperty("mcp.jsonrpc.id"),
"result", Map.of("status", "ok")
);
exchange.getMessage().setBody(response);
});
WebSocket Server
from("mcp:http://localhost:8090/mcp?websocket=true")
.process(exchange -> {
// Process MCP requests over WebSocket
// Response automatically serialized to JSON
});
YAML-Based Server
- route:
id: mcp-server
from:
uri: "mcp:http://0.0.0.0:8080/mcp"
steps:
- choice:
when:
- simple: "${exchangeProperty.mcp.jsonrpc.method} == 'ping'"
steps:
- setBody:
constant:
jsonrpc: "2.0"
result: {}
- simple: "${exchangeProperty.mcp.jsonrpc.method} == 'tools/list'"
steps:
- setBody:
constant:
jsonrpc: "2.0"
result:
tools:
- name: "echo"
description: "Echo the input"
The consumer automatically:
- Validates HTTP headers (Content-Type, Accept)
- Parses JSON-RPC envelopes
- Extracts method and parameters as exchange properties
- Applies rate limiting and request size guards
- Serializes response bodies to JSON
🤖 MCP Tooling
AbstractMcpRequestProcessorandAbstractMcpResponseProcessorprovide templates for custom tool handlers.McpResourcesGetProcessorhandles resource loading with automatic content type detection and helper methods:isBinaryResource(name)/isTextResource(name)— check content typegetMimeType(name)— resolve MIME type from extensionblobResource(uri, mimeType, bytes)— create binary responsetextResource(uri, mimeType, content)— create text responsejsonResource(uri, data)— create JSON response
McpNotificationProcessornormalizes JSON-RPC notifications and exchange properties.- Tool catalogs load from
classpath:mcp/methods.yamland feedtools/listresponses automatically.
🧪 Testing
mvn clean install
The integration test boots a mock MCP server defined in src/test/resources/routes via Camel Main.
🧰 Samples
mcp-service (Kamelet/YAML routes)
Full-featured MCP server with Kamelet-based routing, UI Bridge, resource catalog, and OpenAPI generation.
mvn -f samples/mcp-service/pom.xml exec:java
# HTTP: http://localhost:8080/mcp | WebSocket: ws://localhost:8090/mcp
mcp-consumer (Direct consumer URI)
Minimal MCP server demonstrating the from("mcp:...") consumer approach — pure Java, no YAML needed.
mvn -f samples/mcp-consumer/pom.xml exec:java
# HTTP: http://localhost:3000/mcp | WebSocket: ws://localhost:3001/mcp
See samples/mcp-consumer/README.md for details and curl examples.
Core component smoke test
mvn exec:java -Dexec.mainClass=org.apache.camel.main.Main
When the sample is running you can exercise the MCP HTTP endpoint:
# JSON resource (no extension)
curl -s -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":"1","method":"resources/get","params":{"resource":"example-resource"}}' \
http://localhost:8080/mcp
# HTML resource
curl -s -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":"2","method":"resources/get","params":{"resource":"sample.html"}}' \
http://localhost:8080/mcp
# Binary image resource
curl -s -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":"3","method":"resources/get","params":{"resource":"sample-image.jpg"}}' \
http://localhost:8080/mcp
HTTP endpoints listen on http://localhost:8080; WebSocket helpers are available on ws://localhost:8090/mcp. Generated OpenAPI definitions live under samples/mcp-service/target/openapi/. Postman collections are bundled in samples/mcp-service/postman/ for interactive exploration.
🔌 IDE & Tooling Integration
Camel Component Descriptor
The build generates a standard Camel component descriptor at src/generated/resources/META-INF/io/dscope/camel/mcp/mcp.json. This enables:
- IDE autocompletion for
mcp:URIs in YAML / Java routes - Auto-generated option tables in documentation
- Property validation via
McpEndpointConfigurerandMcpComponentConfigurer
Additional Camel-standard properties are exposed automatically: bridgeErrorHandler, lazyStartProducer, exceptionHandler, exchangePattern, autowiredEnabled.
Apache Karavan Integration
Generate visual designer metadata for Apache Karavan:
mvn -Pkaravan-metadata compile exec:java
This produces metadata under src/main/resources/karavan/metadata/:
| File | Purpose |
|---|---|
component/mcp.json |
Component descriptor with all properties and method enums |
mcp-methods.json |
Catalog of 13 request methods + 3 notification methods |
kamelet/mcp-rest-service.json |
REST kamelet descriptor (port 8080) |
kamelet/mcp-ws-service.json |
WebSocket kamelet descriptor (port 8090) |
model-labels.json |
Human-friendly labels for methods and kamelets |
Regenerate after adding new MCP methods or changing component properties.
🧱 Project Layout
io.dscope.camel.mcp/
├── McpComponent # Camel component entry point
├── McpEndpoint # Holds configuration, creates producer/consumer (@UriEndpoint, Category.AI)
├── McpConfiguration # URI path/param bindings with Camel annotations
├── McpProducer # Sends MCP JSON-RPC requests to remote servers (client mode)
├── McpConsumer # Receives MCP requests via HTTP/WebSocket (server mode)
├── processor/ # 20+ built-in processors for JSON-RPC, tools, resources, UI, notifications
├── catalog/ # McpMethodCatalog + McpResourceCatalog (loaded from YAML)
├── service/ # McpUiSessionRegistry, McpWebSocketNotifier
├── model/ # Jackson POJOs: requests, responses, resources, UI sessions, notifications
└── tools/karavan/ # McpKaravanMetadataGenerator for Karavan visual designer
samples/
├── mcp-service/ # Full-featured MCP server using Kamelets/YAML routes (port 8080/8090)
└── mcp-consumer/ # Minimal MCP server using direct consumer URI (port 3000/3001)
src/generated/ # Auto-generated component descriptors (mcp.json, configurers, URI factory)
src/main/resources/karavan/metadata/ # Generated Karavan metadata (component, kamelets, labels)
src/main/docs/mcp-component.adoc # AsciiDoc component documentation for Camel tooling
📄 License
Licensed under the Apache License 2.0. See LICENSE for the full text.