From a0a5c08a4a53e07f9c8514fa0c8cd2e286c8e581 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Tue, 20 Oct 2026 09:53:03 +0200 Subject: [PATCH 1/2] chore: the examples move to Camel 4.23.0: CI tests with it, and ai/mcp-server and contracts/openapi-server use what it brings CI pins Camel 4.23.0 for the CLI and for the integrations the Citrus tests start, as camel@apache/camel defaults to the latest LTS release (4.22.0). ai/mcp-server sets the server title, description and instructions, its README says that the server serves ai-resource routes next to the tools, and the log lines it shows are those of 4.23.0. contracts/openapi-server keeps its /api base path, but its README no longer says the servers entry must have a path: on 4.23 an entry without one serves the operations at the root. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .github/workflows/build.yml | 13 ++++++++++--- ai/mcp-server/README.md | 25 +++++++++++++++---------- ai/mcp-server/application.properties | 3 +++ contracts/openapi-server/README.md | 4 ++-- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e1fc747..826f22e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,6 +22,13 @@ on: branches: - main +env: + # the Camel release the examples are tested with: camel@apache/camel defaults to the latest LTS release + CAMEL_VERSION: 4.23.0 + # the Camel version of the integrations the Citrus tests start + CITRUS_CAMEL_JBANG_VERSION: 4.23.0 + CITRUS_CAMEL_CLI_VERSION: 4.23.0 + jobs: integration-tests: runs-on: ubuntu-latest @@ -135,8 +142,8 @@ jobs: jbang trust add https://github.com/apache/camel/ - jbang camel@apache/camel --version - jbang camel@apache/camel plugin add test + jbang -Dcamel.jbang.version=$CAMEL_VERSION camel@apache/camel --version + jbang -Dcamel.jbang.version=$CAMEL_VERSION camel@apache/camel plugin add test - name: Run tests env: CITRUS_CAMEL_JBANG_DUMP_INTEGRATION_OUTPUT: "true" @@ -144,7 +151,7 @@ jobs: CITRUS_TESTCONTAINERS_REGISTRY_MIRROR: "mirror.gcr.io" run: | source "/home/runner/.sdkman/bin/sdkman-init.sh" - jbang camel@apache/camel test run ${{ matrix.path }}/test + jbang -Dcamel.jbang.version=$CAMEL_VERSION camel@apache/camel test run ${{ matrix.path }}/test - uses: actions/upload-artifact@v4 if: always() with: diff --git a/ai/mcp-server/README.md b/ai/mcp-server/README.md index 9eb62a7..5253818 100644 --- a/ai/mcp-server/README.md +++ b/ai/mcp-server/README.md @@ -9,14 +9,14 @@ that tag becomes a tool any MCP client can discover and call, a coding agent inc ```text $ camel run * ... -INFO ... VertxMcpServerEngine : MCP server 'webshop' serving tools on path /mcp +INFO ... VertxMcpServerEngine : MCP server 'webshop' serving tools and resources on path /mcp INFO ... Started stock-level (ai-tool://stock_level) INFO ... Started order-status (ai-tool://order_status) when a client calls the tools: -INFO ... mcp-server.camel.yaml:38 : Tool stock_level(CAMEL-MUG): 42 CAMEL-MUG in stock -INFO ... mcp-server.camel.yaml:81 : Tool order_status(ORD-1003): Order ORD-1003 for customer C-134 in US is pending with 3 line(s) +INFO ... mcp-server.camel.yaml:44 : Tool stock_level(CAMEL-MUG): 42 CAMEL-MUG in stock +INFO ... mcp-server.camel.yaml:84 : Tool order_status(ORD-1003): Order ORD-1003 for customer C-134 in US is pending with 3 line(s) ``` ## Install Camel CLI @@ -62,20 +62,25 @@ The MCP server is a preview feature since Camel 4.22. and `readOnlyHint` as an advisory hint. When a client calls the tool, the arguments arrive as headers and the route's final body is the tool result. - `tags: shop` groups the tools; `camel.server.mcp-tags=shop` in `application.properties` exposes that group. - `camel.server.mcp-enabled=true` starts the MCP server on the CLI's HTTP server and `camel.server.mcp-server-name` - is what the client shows; Camel 4.23 adds a title, description and instructions next to it. + `camel.server.mcp-enabled=true` starts the MCP server on the CLI's HTTP server. `camel.server.mcp-server-name`, + `mcp-server-title` and `mcp-server-description` are what the client shows, and `mcp-instructions` is the text + the client hands its model with the tool list: when to use which tool and what the ids look like. - `order_status` reads the order file with `pollEnrich` and a file name built from the id, `order-1001.json` for `ORD-1001`, and answers a sentence; a missing file leaves the body null, which becomes the unknown answer. +- Next to tools, the server serves MCP resources: an `ai-resource` route with the same tag is content the client + reads (`resources/list` and `resources/read`) rather than an action the model calls. This example has tools + only; *Try changing* adds a resource. - Nothing here is specific to MCP: the same `ai-tool` routes are the tools of a Camel agent built with `langchain4j-agent` or `openai`, selected by the same tags. ## Build it step by step -1. One `ai-tool` route that answers a fixed text, with the four `camel.server.mcp-*` properties; run it and see - the server line in the log, then `initialize` and `tools/list` with `curl`. -2. Add a parameter and use `${header.sku}` in the answer; call it with `tools/call`. -3. Answer from `stock.json`: unmarshal it, find the SKU with Groovy and add the unknown case. -4. Add the second tool and connect a real agent. +1. One `ai-tool` route that answers a fixed text, with `camel.server.mcp-enabled`, `mcp-tags` and + `mcp-server-name`; run it and see the server line in the log, then `initialize` and `tools/list` with `curl`. +2. Add the title, description and instructions, and see them in the `initialize` answer. +3. Add a parameter and use `${header.sku}` in the answer; call it with `tools/call`. +4. Answer from `stock.json`: unmarshal it, find the SKU with Groovy and add the unknown case. +5. Add the second tool and connect a real agent. ## Try changing diff --git a/ai/mcp-server/application.properties b/ai/mcp-server/application.properties index 13ca646..b30dad5 100644 --- a/ai/mcp-server/application.properties +++ b/ai/mcp-server/application.properties @@ -20,3 +20,6 @@ camel.server.port=8080 camel.server.mcp-enabled=true camel.server.mcp-tags=shop camel.server.mcp-server-name=webshop +camel.server.mcp-server-title=Web shop +camel.server.mcp-server-description=Stock levels and order status of the web shop +camel.server.mcp-instructions=Use stock_level for how many of a product are in the warehouse, and order_status for the status and lines of an order. Product SKUs look like CAMEL-MUG, order ids like ORD-1001. diff --git a/contracts/openapi-server/README.md b/contracts/openapi-server/README.md index 746aaa9..2fb9be6 100644 --- a/contracts/openapi-server/README.md +++ b/contracts/openapi-server/README.md @@ -42,8 +42,8 @@ Stop it with `ctrl` + `c`. ## How it works - `rest` with `openApi: specification: stock-api.json` is the whole API definition: paths, verbs and parameters - come from the contract, not from the route file, and the base path `/api` from its `servers` entry, which - must have a path. `restConfiguration` switches on `clientRequestValidation`, + come from the contract, not from the route file, and the base path `/api` from its `servers` entry (an entry + without a path serves the operations at the root). `restConfiguration` switches on `clientRequestValidation`, which rejects a request without the body or content type the contract requires with 400, and `apiContextPath: openapi` serves the contract. - Each operation is a `direct` route named after its `operationId`: `listStock`, `getStock`, `reserveStock`. From 1e8026792c73e1ff7461571f5ee82f80259f7567 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Tue, 20 Oct 2026 09:55:40 +0200 Subject: [PATCH 2/2] chore: the catalog no longer lists the tickets-out files ai/ticket-classifier writes at runtime The catalog was generated in a directory where the example had run, so it listed tickets-out/*/T-*.json, which are not in the repository; fetching them from GitHub answers 404. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- camel-jbang-example-catalog.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/camel-jbang-example-catalog.json b/camel-jbang-example-catalog.json index 63ecd5c..54d2fc4 100644 --- a/camel-jbang-example-catalog.json +++ b/camel-jbang-example-catalog.json @@ -213,9 +213,6 @@ "README.md", "application.properties", "ticket-classifier.camel.yaml", - "tickets-out/account/T-3.json", - "tickets-out/billing/T-2.json", - "tickets-out/shipping/T-1.json", "tickets/T-1.json", "tickets/T-2.json", "tickets/T-3.json"