CAMEL-24369: camel-mcp-server jackson-annotations alignment + camel-openai deferred MCP client init - #25404
Conversation
…-databind for camel-bom users The MCP Java SDK (mcp-core) declares jackson-annotations 2.20, which nearest-wins resolution picks over the 2.22 required by jackson-databind 2.22.1 when an application imports only camel-bom, failing at MCP engine startup with NoClassDefFoundError: com/fasterxml/jackson/annotation/JsonSerializeAs. Declare the aligned jackson-annotations directly so consumers resolve a consistent version with or without the jackson-bom. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…hable at endpoint startup An application consuming its own MCP endpoint (or one of a service starting concurrently) failed route startup on runtimes where the HTTP server only accepts connections after the application has started (e.g. Quarkus). An MCP server that is unreachable during doStart is now recorded with a WARN and its initialization is deferred and retried on first use, reusing the existing reconnect path and per-server locks. Invalid configuration still fails fast. This aligns the behavior across Camel Main, Spring Boot and Quarkus and matches the in-process registration model of annotated tools, which cannot hit this ordering problem. Also update the stale ai-tool See Also section: langchain4j-agent and spring-ai-chat discover ai-tool routes today, not in a future release. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
davsclaus
left a comment
There was a problem hiding this comment.
Clean, well-structured PR that addresses a real cross-runtime compatibility issue.
Highlights:
- Smart reuse of the existing
doReconnectMcpServerpath for deferred init — no duplicated logic - Fast-fail preserved:
transportTypevalidation stays before the try-catch, so invalid config still fails the route at startup - Thread safety is sound:
ConcurrentHashMap.newKeySet()forpendingMcpServers,tryLock()to avoid blocking on concurrentgetMcpToolState()calls, andmcpStoppeddouble-check inside the lock prevents zombie initialization afterdoStop() - Tests cover the key scenarios (startup resilience, lazy init, eager init, stopped endpoint safety)
- jackson-annotations alignment is correct and well-commented
- Doc updates are accurate (future-tense → present-tense in See Also, error table reflects new behavior)
Minor observation (non-blocking): when the server is still unreachable, each getMcpToolState() call triggers doReconnectMcpServer, which logs at LOG.error on failure. For the deferred-init use case this is expected transient behavior — could consider a follow-up to suppress the ERROR log during deferred retries.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
|
There are uncommitted changes |
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
🧪 CI tested the following changed modules:
🔬 Scalpel shadow comparison — Scalpel: 15 tested, 28 compile-only — current: 14 all testedMaveniverse Scalpel detected 43 affected modules (current approach: 14).
|
JIRA: CAMEL-24369
Two fixes found by running the same ai-tool + mcp-server application on Camel Main, Spring Boot and Quarkus (companion PRs in apache/camel-spring-boot and apache/camel-quarkus):
camel-mcp-server: jackson-annotations alignment
An application importing only
camel-bomfails at MCP engine startup withNoClassDefFoundError: com/fasterxml/jackson/annotation/JsonSerializeAs: the MCP Java SDK (mcp-core, still latest 2.0.0) declaresjackson-annotations:2.20, which nearest-wins resolution picks over the 2.22 required byjackson-databind:2.22.1. A direct dependency on the alignedjackson-annotationsmakes consumers resolve a consistent version with or without the jackson-bom.camel-openai: defer initialization of MCP servers unreachable at endpoint startup
openai:chat-completion?mcpServer.x.url=<own /mcp>(an application consuming its own MCP endpoint — the pattern shown in the mcp-server docs) initializes its MCP client eagerly on route warm-up. On Quarkus the HTTP server only accepts connections after the application has started, so the route — and the whole application — failed to start; on Spring Boot the client started with 0 tools; on Camel Main it worked. Now an MCP server that is unreachable duringdoStartis recorded with a WARN and initialized lazily on first use, reusing the existing reconnect path and per-server locks. Invalid configuration (e.g. missingtransportType) still fails fast. This aligns behavior across runtimes and matches the in-process registration model of annotated tools (quarkiverse@Tool, Spring AI@McpTool), which cannot hit this ordering problem.Includes a new unit test (
OpenAIEndpointMcpDeferredInitTest, 4 scenarios), theopenai-mcp.adocerror-table update, and a fix for the stale ai-tool "See Also" section (langchain4j-agent and spring-ai-chat discover ai-tool routes today, not "in a future release").Verified end-to-end: 27/27 MCP conformance scenario checks on all three runtimes with local Ollama.
Claude Code on behalf of Croway (Federico Mariani)
🤖 Generated with Claude Code