Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 51 additions & 27 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,37 @@

## Architecture Overview

This is an Apache Camel 4 component that implements the Model Context Protocol (MCP) for AI agent integration. The component follows Camel's standard plugin architecture:
This is an Apache Camel 4 component (v1.3.0) that implements the Model Context Protocol (MCP) for AI agent integration. The component follows Camel's standard plugin architecture and supports both **producer** (client) and **consumer** (server) modes.

- **Component Registration**: `src/main/resources/META-INF/services/org/apache/camel/component/mcp` registers `McpComponent`
- **Protocol Flow**: Routes act as MCP clients sending JSON-RPC 2.0 requests (`initialize`, `tools/list`, `tools/call`)
- **Transport**: HTTP-based communication using Camel's HTTP components internally
- **Protocol Flow**: Routes can act as MCP clients (`to("mcp:...")`) sending JSON-RPC 2.0 requests, or as MCP servers (`from("mcp:...")`) receiving and processing them
- **Transport**: HTTP and WebSocket via Camel Undertow

### Key Files to Understand
- `McpComponent.java` - Entry point, creates endpoints from URIs like `mcp:http://localhost:8080/mcp?method=initialize`
- `McpEndpoint.java` - Holds `McpConfiguration` and instantiates producer/consumer singletons
- `McpEndpoint.java` - `@UriEndpoint(scheme="mcp", category=Category.AI)`, creates producer/consumer, delegates config to `McpConfiguration`
- `McpConfiguration.java` - `@UriPath`/`@UriParam` annotated configuration (uri, method, websocket, etc.)
- `McpProducer.java` - Handles outbound MCP requests, wraps payloads in JSON-RPC format
- `McpConsumer.java` - Placeholder for inbound MCP server functionality (Undertow listener not wired yet)
- `model/` - JSON-RPC request/response POJOs using Jackson
- `CamelMcpRunner.java` - Boots a sample YAML route for local smoke tests (loads from `src/test/resources/routes`)
- `McpConsumer.java` - Fully implemented inbound MCP server wrapping Undertow with processor pipeline: SizeGuard → HttpValidator → RateLimit → JsonRpcEnvelope → user processor → JSON serialization
- `processor/` - 20+ built-in processors for JSON-RPC, tools, resources, UI Bridge, health, streaming, and notifications
- `catalog/` - `McpMethodCatalog` (tool definitions from `methods.yaml`) and `McpResourceCatalog` (resource definitions from `resources.yaml`)
- `service/` - `McpUiSessionRegistry` (session lifecycle, 1h TTL) and `McpWebSocketNotifier` (WebSocket notifications)
- `model/` - Jackson POJOs: requests, responses, resources, UI sessions, notifications
- `tools/karavan/McpKaravanMetadataGenerator.java` - Generates Apache Karavan visual designer metadata

### Generated Artifacts
- `src/generated/` - Auto-generated by `camel-package-maven-plugin`: component JSON descriptor (`mcp.json`), `McpEndpointConfigurer`, `McpComponentConfigurer`, `McpEndpointUriFactory`
- `src/main/resources/karavan/metadata/` - Karavan metadata: component descriptor, method catalog, kamelet descriptors, labels
- `src/main/docs/mcp-component.adoc` - AsciiDoc component docs with auto-updated option tables

## Development Workflows

### Building & Testing
```bash
# Requires Java 21+
mvn clean install
mvn exec:java -Dexec.mainClass=org.apache.camel.main.Main # Run example route
mvn clean install # Build + run 87 tests
mvn exec:java -Dexec.mainClass=org.apache.camel.main.Main # Run example route
mvn -Pkaravan-metadata compile exec:java # Regenerate Karavan metadata
```

Use VS Code tasks: "Build with Maven" and "Run Camel MCP" for convenience. Both commands rely on Camel's YAML DSL loader, so keep `camel-yaml-dsl` on the classpath.
Expand All @@ -35,39 +45,51 @@ Integration-style assertions are done on raw HTTP responses; spin up both routes

The YAML DSL examples set JSON strings with `setBody.constant` and immediately `unmarshal.json` to build the Map payload the producer expects—mirror that pattern when adding new scenarios.

### Sample Projects
- `samples/mcp-service/` - Full-featured MCP server with Kamelets/YAML routes (port 8080/8090)
- `samples/mcp-consumer/` - Minimal MCP server using direct `from("mcp:...")` consumer (port 3000/3001)

## Component Conventions

### URI Format

**Producer (Client):**
```
mcp:targetUri?method=mcpMethod
```

**Consumer (Server):**
```
mcp:targetUri?method=mcpMethod&param=value
mcp:http://host:port/path # HTTP server
mcp:http://host:port/path?websocket=true # WebSocket server
```
- `targetUri` - HTTP endpoint of the MCP server
- `method` - MCP JSON-RPC method (defaults to `tools/list`)

### Message Flow
### Producer Message Flow
1. Incoming exchange body must be a `Map` that becomes the JSON-RPC `params`; null produces an empty payload
2. Producer injects `jsonrpc: "2.0"`, random UUID `id`, and the configured `method`
3. Body is serialized with Jackson and sent using `ProducerTemplate.requestBody(...)` to the target URI
4. Response JSON is parsed into `McpResponse` and set on the OUT message; callers should extract `getResult()`

### Configuration Pattern
`McpConfiguration` uses Camel's `@UriPath` and `@UriParam` annotations for automatic parameter binding from route URIs. Validate new query parameters here so Camel tooling (autocompletion/docs) stays accurate.

### Server-Side Roadmap
`McpConsumer.doStart()` is currently a stub. The intended flow is to register an Undertow HTTP endpoint that unmarshals JSON-RPC requests, delegates to the route `Processor`, and writes an `McpResponse`. Keep this in mind when adding consumer-related code—no server transport exists yet.
### Consumer Message Flow
1. Undertow server receives HTTP POST or WebSocket message
2. `McpRequestSizeGuardProcessor` validates request size
3. `McpHttpValidatorProcessor` validates headers (HTTP only; checks Accept includes `application/json` + `text/event-stream`)
4. `McpRateLimitProcessor` applies rate limiting
5. `McpJsonRpcEnvelopeProcessor` parses JSON-RPC, sets exchange properties: `mcp.jsonrpc.method`, `mcp.jsonrpc.id`, `mcp.jsonrpc.type`, `mcp.tool.name`
6. User processor handles the request and sets the response body
7. Response is serialized to JSON with `application/json` content type

When filling this in, reuse the producer's `ObjectMapper` settings so request/response schemas stay aligned. Plan to:
- Spin up Undertow via Camel's `UndertowComponent` listening on the configured URI
- Convert incoming JSON to `McpRequest`, invoke `Processor.process(exchange)`
- Serialize the `Exchange` body (expecting `McpResponse`) back to JSON before returning HTTP 200
### Configuration Pattern
`McpConfiguration` uses Camel's `@UriPath` and `@UriParam` annotations for automatic parameter binding from route URIs. `McpEndpoint` duplicates these as delegate fields for the `camel-package-maven-plugin` to generate proper metadata. Validate new query parameters in `McpConfiguration` so Camel tooling (autocompletion/docs) stays accurate.

## Key Dependencies & Integration

- **Jackson** for JSON serialization of MCP protocol messages (default `ObjectMapper`, no custom modules yet)
- **camel-http`/HTTP URIs** for the synchronous producer transport; this component piggybacks on whatever Camel endpoint backs the target URI
- **camel-http/HTTP URIs** for the synchronous producer transport; this component piggybacks on whatever Camel endpoint backs the target URI
- **camel-main** to bootstrap routes for tests and samples (YAML loader is configured through `RoutesIncludePattern`)
- **camel-yaml-dsl** so Camel can parse the YAML route definitions that drive the tests
- **camel-undertow** intended for server-side MCP endpoints (not implemented, safe to remove unless consumer work resumes)
- **camel-undertow** for consumer-side HTTP/WebSocket server endpoints
- **camel-package-maven-plugin** generates component JSON descriptor and configurers from `@UriEndpoint` annotations
- **logback-classic** (test scope) provides the SLF4J backend during Maven Surefire runs

## Publishing & Deployment
Expand All @@ -81,6 +103,8 @@ Project is configured for Maven Central publication via GitHub Actions:

- Add method presets by constraining `McpConfiguration.setMethod` (e.g., validate enums or expose fluent options)
- Expand request metadata via `McpRequest` if MCP spec evolves; adjust serialization in `McpProducer`
- Implement `McpConsumer.doStart()` with Undertow routing when server support is needed; ensure JSON parsing mirrors `McpProducer`
- When adding fields to responses, update `McpResponse` and the mock route payloads so tests keep passing
- Add new protocol hooks by extending the YAML route examples—e.g. create `tools/list` payloads in `example-mcp.yaml` and define matching canned responses in `mock-mcp-server.yaml`
- Add new processors by extending `AbstractMcpResponseProcessor` and registering with `@BindToRegistry`
- When adding fields to responses, update the model POJOs and the mock route payloads so tests keep passing
- Add new protocol hooks by extending the YAML route examples—e.g. create payloads in `example-mcp.yaml` and define matching canned responses in `mock-mcp-server.yaml`
- After adding new MCP methods or properties, regenerate Karavan metadata: `mvn -Pkaravan-metadata compile exec:java`
- Add new `@UriParam` fields to `McpConfiguration` (and delegate in `McpEndpoint`) then rebuild to update the generated component descriptor
67 changes: 64 additions & 3 deletions CAMEL_MCP_APPS_BRIDGE_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Add **MCP Apps UI Bridge** support to `io.dscope:camel-mcp` to enable the librar
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ MCP Apps Host Bridge │
│ (New in camel-mcp 1.2.0) │
│ (New in camel-mcp 1.3.0) │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ postMessage ┌──────────────────────────────────┐│
Expand Down Expand Up @@ -140,7 +140,7 @@ public class McpUiInitializeResult {

public static class McpHostInfo {
private String name; // "camel-mcp"
private String version; // "1.2.0"
private String version; // "1.3.0"
}
}
```
Expand Down Expand Up @@ -265,7 +265,7 @@ public class McpUiInitializeProcessor extends AbstractMcpResponseProcessor {
// Build response
McpUiInitializeResult result = new McpUiInitializeResult();
result.setSessionId(session.getSessionId());
result.setHostInfo(new McpHostInfo("camel-mcp", "1.2.0"));
result.setHostInfo(new McpHostInfo("camel-mcp", "1.3.0"));
result.setCapabilities(List.of(
"tools/call",
"ui/message",
Expand Down Expand Up @@ -596,6 +596,65 @@ public class McpAppsClient {

---

## MCP Consumer Implementation (Completed)

The `McpConsumer` class has been implemented to provide programmatic MCP server creation through Camel component URIs.

### Features Implemented

1. **HTTP Server Support**: Create MCP servers via `mcp:http://host:port/path`
2. **WebSocket Server Support**: Enable WebSocket via `mcp:http://host:port/path?websocket=true`
3. **Automatic Request Processing**:
- Request size validation
- HTTP header validation (Accept, Content-Type)
- Rate limiting
- JSON-RPC envelope parsing
- Exchange property population
4. **Response Serialization**: Automatic JSON serialization of Map/POJO responses
5. **Lifecycle Management**: Proper startup and shutdown of Undertow server endpoints

### Consumer Architecture

```
McpConsumer wraps UndertowConsumer:
McpRequestSizeGuardProcessor
McpHttpValidatorProcessor (HTTP only)
McpRateLimitProcessor
McpJsonRpcEnvelopeProcessor
User Processor (route logic)
JSON Serialization
Response
```

### Usage Example

```java
// HTTP Server
from("mcp:http://localhost:8080/mcp")
.process(myMcpProcessor);

// WebSocket Server
from("mcp:http://localhost:8090/mcp?websocket=true")
.process(myMcpProcessor);
```

### Tests

All consumer functionality is validated in `McpConsumerTest.java`:
- HTTP consumer basic operation
- WebSocket consumer configuration
- JSON-RPC envelope parsing
- Consumer lifecycle management

---

## Summary

The `io.dscope:camel-mcp` library needs these additions to become a full MCP Apps host:
Expand All @@ -607,3 +666,5 @@ The `io.dscope:camel-mcp` library needs these additions to become a full MCP App
5. **Notification push** via WebSocket for `ui/notifications/*`

The existing `tools/list`, `resources/list`, `resources/read`, and `tools/call` implementations are already MCP Apps compliant for server mode.

**Consumer Implementation**: ✅ Complete - The `McpConsumer` provides full MCP server functionality with HTTP and WebSocket support.
Loading