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
13 changes: 10 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -135,16 +142,16 @@ 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"
CITRUS_TESTCONTAINERS_REGISTRY_MIRROR_ENABLED: "true"
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:
Expand Down
25 changes: 15 additions & 10 deletions ai/mcp-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions ai/mcp-server/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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.
3 changes: 0 additions & 3 deletions camel-jbang-example-catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions contracts/openapi-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
Loading