Add camel-quarkus-mcp-server extension - #8950
Conversation
jamesnetherton
left a comment
There was a problem hiding this comment.
Some initial feedback before the Camel PR is merged. Otherwise it all looks good to me.
| <description>Integration tests for Camel Quarkus MCP Server extension</description> | ||
|
|
||
| <properties> | ||
| <mcp-java-sdk.version>2.0.0</mcp-java-sdk.version> |
There was a problem hiding this comment.
Please move this property to the root pom.xml with the other test version properties:
https://github.com/apache/camel-quarkus/blob/main/pom.xml#L187
| <dependency> | ||
| <groupId>io.modelcontextprotocol.sdk</groupId> | ||
| <artifactId>mcp-core</artifactId> | ||
| <version>${mcp-java-sdk.version}</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>io.modelcontextprotocol.sdk</groupId> | ||
| <artifactId>mcp-json-jackson2</artifactId> | ||
| <version>${mcp-java-sdk.version}</version> | ||
| <scope>test</scope> | ||
| </dependency> |
There was a problem hiding this comment.
Please add these to the dependabot config with the other test dependencies:
https://github.com/apache/camel-quarkus/blob/main/.github/dependabot.yml#L49
There was a problem hiding this comment.
Could we use McpAssured from quarkus-mcp-server-test instead of the raw MCP SDK? It would replace both mcp-core and mcp-json-jackson2 test dependencies and their dependabot/BOM entries.
| @Inject | ||
| CamelContext camelContext; |
There was a problem hiding this comment.
Instead of @Inject into the test class, can we add a JAX-RS resource class that interacts with the Camel context for the tests to interrogate the route status etc. It'll make life easier if we promote the extension to native mode support. You can get examples from other integration tests.
| <quarkiverse-freemarker.version>1.3.0</quarkiverse-freemarker.version><!-- https://repo1.maven.org/maven2/io/quarkiverse/freemarker/quarkus-freemarker-parent/ --> | ||
| <quarkiverse-fory.version>1.4.0</quarkiverse-fory.version><!-- https://repo1.maven.org/maven2/io/quarkiverse/fory/quarkus-fory-parent/ --> | ||
| <quarkiverse-groovy.version>3.38.0</quarkiverse-groovy.version><!-- https://repo1.maven.org/maven2/io/quarkiverse/groovy/quarkus-groovy-parent/ --> | ||
| <quarkiverse-mcp-server.version>1.13.1</quarkiverse-mcp-server.version><!-- https://repo1.maven.org/maven2/io/quarkiverse/mcp/quarkus-mcp-server-parent/ --> |
There was a problem hiding this comment.
Nitpick - can we keep alphabetical order and move it above the quarkiverse-micrometer.version property.
| <!-- the runtime-agnostic MCP bridge and engine SPI; the serving engine is provided | ||
| by the quarkiverse quarkus-mcp-server extension below (NOT the camel-mcp-server | ||
| Vert.x engine used on Camel Main / JBang) --> |
There was a problem hiding this comment.
Can probably remove this.
JiriOndrusek
left a comment
There was a problem hiding this comment.
So far looks good to me - but I need to review this PR in more details. Here is 1 small test issue (which caught my eye)
| private McpSyncClient client() { | ||
| if (client == null) { | ||
| client = McpClient | ||
| .sync(HttpClientStreamableHttpTransport.builder("http://localhost:8081").build()) |
There was a problem hiding this comment.
Hardcoded 8081 can cause troubles if user changes port. Better is to get value from the property (quarkus.http.test-port.)
|
@Croway I'm curious, what is blocking the native support? to my understanding the |
good point, in theory nothing, I am adding the native profile and I'm going to test it. |
|
The engine only uses ToolManager APIs from the core module. Would it be possible to depend on just the core and let users choose the transport ( |
|
@Croway, FYI the recent |
1a9f898 to
5042d09
Compare
mhhhh I would like to achieve the following, OOB Camel MCP will use the http transport, but somehow, the user can configure stdio if needed. As of now this is not possible, I'll do a research if this is feasible somehow on all the runtimes. WDYT @zbendhiba ? |
What I suggest is: instead of depending on I don't understand what's limiting us to HTTP. I don't know. WDYT @jamesnetherton @JiriOndrusek |
but this way the user should configure the http or the stdio when using quarkus, right? it won't work by adding the extension only |
|
If it is just literally a case of switching between If it's not that simple, then maybe we just go with HTTP initially? |
I'd go with HTTP, in particular, right now the following is possible:
This works with the current code, and can be documented, it might be a bit hacky, but this way the component is battery included, OOB, http works. |
I'm ok with that. Maybe @zbendhiba has more thoughts about it? I guess we can always adjust things as needed later. |
|
ok Thanks for the discussion |
2468779 to
b35850e
Compare
fe0ecac to
36f6209
Compare
Expose ai-tool routes as MCP tools over streamable HTTP through the quarkiverse quarkus-mcp-server extension (CAMEL-24308): - JVM-only extension depending on camel-mcp-server-api (the runtime-agnostic bridge + McpServerEngine SPI) - deliberately NOT the camel-mcp-server Vert.x engine used on Camel Main/JBang, so the MCP Java SDK and Reactor never reach the Quarkus classpath. - QuarkusMcpServerEngine publishes tools through the programmatic ToolManager API (list_changed emitted by quarkus-mcp-server); tool arguments are mapped from the ai-tool ParameterDef metadata. - quarkus.camel.mcp-server.* config (enabled default true, tags opt-in, tool-timeout 20s); serving concerns (path, transports, dev UI, auth, guardrails) stay owned by quarkus.mcp.server.*. - Integration tests run the engine conformance scenarios with the official MCP SDK client over streamable HTTP: tag filtering (untagged pool excluded), call success, sanitized execution errors, timeout, tools list following route stop/start. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ge docs - Prove @Tool-annotated business methods coexist with Camel ai-tool routes on the same MCP server. - Usage docs: combined quarkus.camel.mcp-server.* / quarkus.mcp.server.* configuration example with ownership split, link to the quarkus-mcp-server configuration reference, YAML DSL tool definition, MCP client configuration examples, dynamic tools and error handling. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…erver extension - Move the MCP Java SDK test dependency version to the root pom.xml test version properties, manage the artifacts in camel-quarkus-bom-test and drop the explicit versions from the integration test pom - Register io.modelcontextprotocol.sdk:mcp-core and mcp-json-jackson2 with the dependabot test dependencies - Replace the CamelContext injection in McpServerTest with an McpServerResource JAX-RS resource driven via RestAssured, so the test also works if the extension is promoted to native mode support - Keep quarkiverse-mcp-server.version in alphabetical order - Remove a redundant comment from the runtime pom - Regenerate the flattened BOMs Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
….test-port The hardcoded 8081 broke the test whenever the HTTP test port was configured to something else. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…pport The engine needed no changes to work in native mode: the native image builds without any reflection or resource registration and all engine conformance scenarios pass against the native binary. - Move the extension to extensions/ and the tests to integration-tests/, drop the JVM only warning build step and declare nativeSince - Add a native profile and McpServerIT to the test module - Assign mcp-server to the group-12 test category - Use McpAssured from quarkus-mcp-server-test to drive the server instead of the MCP Java SDK client, which removes the mcp-core and mcp-json-jackson2 test dependencies together with their version property, test BOM and dependabot entries - Regenerate the extension metadata, documentation and flattened BOMs Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The extension keeps streamable HTTP out of the box. Adding the quarkus-mcp-server-stdio transport serves the same Camel tools over stdin/stdout, and the HTTP transport of the default MCP server can be turned off to serve over stdio only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…rver HTTP transport
The servers map is annotated @WithUnnamedKey("<default>"), so
quarkus.mcp.server.http.enabled addresses the default server directly —
the quoted "<default>" key works but is not required, and the flat form
is what the quarkus-mcp-server configuration reference documents.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…t MCP server HTTP transport" This reverts commit 9f6fdd4.
…gation docs/modules/ROOT/nav.adoc is generated by the check-extension-pages goal of the catalog module and was missed when the extension was added, leaving the reference page unreachable from the navigation tree. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
36f6209 to
afe210d
Compare
|
This looks good to me. To avoid PR builds failing endlessly due to changes on the Camel |
Fixes #8949. The Quarkus runtime of CAMEL-24308 (camel-mcp-server).
What this adds
A
camel-quarkus-mcp-serverextension (JVM and native) exposingai-toolroutes as MCP tools over streamable HTTP, served through the quarkiverse quarkus-mcp-server (1.13.1) — per the design recorded on CAMEL-24308: Quarkus reuses its native MCP ecosystem (dev UI, guardrails, CDI, config) instead of the MCP Java SDK.camel-mcp-server-api(the runtime-agnostic bridge +McpServerEngineSPI) +quarkus-mcp-server-http.QuarkusMcpServerEnginemapstoolAdded/toolRemovedonto the programmaticToolManagerAPI (newTool(...).addArgument(...).setHandler(...).register()/removeTool), with tool arguments derived from the ai-toolParameterDefmetadata and sanitized results mapped toToolResponse.success/error. The MCP Java SDK and Reactor never reach the classpath.RuntimeCamelContextCustomizerBuildItem(gated onquarkus.camel.mcp-server.enabled) binds the engine into the Camel registry (the bridge resolves registry-first) and adds theMcpServerBridgeas a CamelContext-managed service.extensions/withnativeSincedeclared — the engine needed no reflection or resource registration, the native image builds clean and all conformance scenarios pass against the native binary (McpServerIT).quarkus.camel.mcp-server.enabled(default true) /.tags(unset ⇒ nothing exposed — the security default) /.tool-timeout(20s). Serving concerns (path, transports, dev UI, auth, guardrails) stay fully owned byquarkus.mcp.server.*, per the CAMEL-24311 precedence rule.quarkus.camel.mcp-server.*/quarkus.mcp.server.*configuration example with the ownership split, a link to the quarkus-mcp-server configuration reference, YAML DSL tool definition with the full parameter syntax, MCP client configuration examples (camel-openai agent +mcp.json-style), a Serving over stdio section (addquarkus-mcp-server-stdio, disable the default server's HTTP transport withquarkus.mcp.server."<default>".http.enabled=false, launch as a subprocess — typically a native executable), dynamic tools and error-handling semantics, and Camel Main/Spring Boot pointers.@Toolcoexistence proven by test: quarkus-mcp-server annotated business methods and Camelai-toolroutes serve from the same MCP server and the sametools/list(annotated tools register at build time, Camel tools follow the route lifecycle).cq:update-quarkus-metadata, docs regen,process-resources -Pformat, BOM entries forquarkus-mcp-server-http(-deployment)underquarkiverse-mcp-server.version,mcp-serverassigned to thegroup-12test category, dependabot entries.Testing
integration-tests/mcp-serverruns the engine conformance scenarios (CAMEL-24313) driven byMcpAssuredfromquarkus-mcp-server-testover streamable HTTP (no MCP Java SDK on the test classpath): tag-filteredtools/list(untagged default pool excluded), call success, execution error sanitized to a generic message, per-call timeout, the tools list following route stop/start (tools/list_changedpath), and@Toolcoexistence. Route control goes through a JAX-RS resource so the same tests run in JVM mode (McpServerTest) and against the native binary (McpServerIT). All 6 scenarios green in both modes.This PR was written by Claude Code on behalf of Federico Mariani (@Croway).
🤖 Generated with Claude Code