This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new cdb20287834b CAMEL-24332: Add MCP tool annotation hints to ai-tool 
endpoint
cdb20287834b is described below

commit cdb20287834beff16e29f8836d160650cc3efbfa
Author: Omar Atie <[email protected]>
AuthorDate: Thu Aug 6 12:09:06 2026 -0700

    CAMEL-24332: Add MCP tool annotation hints to ai-tool endpoint
    
    Add optional MCP ToolAnnotations metadata (title, readOnlyHint,
    destructiveHint, idempotentHint, openWorldHint) on ai-tool consumer
    endpoints. Hints are carried through AiToolSpec, McpServerTool SPI,
    and the Vert.x MCP engine to published MCP tools. Advisory only per
    the MCP spec — not enforced by Camel.
    
    Closes #25395
    
    Co-authored-by: Cursor Agent <[email protected]>
---
 .../apache/camel/catalog/components/ai-tool.json   |  26 ++-
 .../camel/catalog/docs/ai-tool-component.adoc      |  44 ++++
 .../org/apache/camel/catalog/docs/mcp-server.adoc  |   8 +
 .../ai/tool/AiToolComponentConfigurer.java         |  27 +++
 .../ai/tool/AiToolConfigurationConfigurer.java     |  27 +++
 .../ai/tool/AiToolEndpointConfigurer.java          |  27 +++
 .../ai/tool/AiToolEndpointUriFactory.java          |   7 +-
 .../apache/camel/component/ai/tool/ai-tool.json    |  26 ++-
 .../src/main/docs/ai-tool-component.adoc           |  44 ++++
 .../camel/component/ai/tool/AiToolAnnotations.java |  54 +++++
 .../component/ai/tool/AiToolConfiguration.java     |  64 ++++++
 .../camel/component/ai/tool/AiToolConsumer.java    |   3 +-
 .../apache/camel/component/ai/tool/AiToolSpec.java |  13 +-
 .../component/ai/tool/AiToolAnnotationsTest.java   |  91 +++++++++
 .../ai/tool/AiToolEndpointLifecycleTest.java       |  29 ++-
 .../component/ai/tool/AiToolExecutorTest.java      |   6 +-
 .../ai/tool/AiToolRegistryListenerTest.java        |   2 +-
 .../component/ai/tool/AiToolRegistryTest.java      |  50 ++---
 .../agent/AiToolSpecToLangChain4jTest.java         |  20 +-
 .../component/mcp/server/McpServerBridge.java      |   6 +
 .../camel/component/mcp/server/McpServerTool.java  |   8 +
 .../component/mcp/server/McpServerBridgeTest.java  |  21 +-
 .../camel-mcp-server/src/main/docs/mcp-server.adoc |   8 +
 .../mcp/server/vertx/VertxMcpServerEngine.java     |  44 +++-
 .../vertx/VertxMcpServerToolAnnotationsTest.java   | 221 +++++++++++++++++++++
 .../dsl/AiToolComponentBuilderFactory.java         |  94 +++++++++
 .../endpoint/dsl/AiToolEndpointBuilderFactory.java | 149 ++++++++++++++
 27 files changed, 1055 insertions(+), 64 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ai-tool.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ai-tool.json
index e0ae716192d7..8f3f695b609a 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ai-tool.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ai-tool.json
@@ -28,18 +28,28 @@
     "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": 
"Bridge Error Handler", "group": "consumer", "label": "consumer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Allows for bridging the consumer to the Camel routing Error Handler, which 
mean any exceptions (if possible) occurred while the Camel consumer is trying 
to pickup incoming messages, or the like [...]
     "configuration": { "index": 2, "kind": "property", "displayName": 
"Configuration", "group": "consumer", "label": "", "required": false, "type": 
"object", "javaType": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"deprecated": false, "autowired": false, "secret": false, "description": "The 
component configuration" },
     "description": { "index": 3, "kind": "property", "displayName": 
"Description", "group": "consumer", "label": "consumer", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Human-readable 
description of what this tool does. Passed verbatim to the LLM; be  [...]
-    "parameters": { "index": 4, "kind": "property", "displayName": 
"Parameters", "group": "consumer", "label": "consumer", "required": false, 
"type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.String>", "prefix": "parameter.", "multiValue": true, "deprecated": 
false, "deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Tool in [...]
-    "tags": { "index": 5, "kind": "property", "displayName": "Tags", "group": 
"consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Comma-separated list of tags used to group 
tools. Producers filter the registry by these tags to [...]
-    "autowiredEnabled": { "index": 6, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
+    "destructiveHint": { "index": 4, "kind": "property", "displayName": 
"Destructive Hint", "group": "consumer", "label": "consumer", "required": 
false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool may perform destructive 
o [...]
+    "idempotentHint": { "index": 5, "kind": "property", "displayName": 
"Idempotent Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that repeating the tool call with the 
sam [...]
+    "openWorldHint": { "index": 6, "kind": "property", "displayName": "Open 
World Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool interacts with external 
syst [...]
+    "parameters": { "index": 7, "kind": "property", "displayName": 
"Parameters", "group": "consumer", "label": "consumer", "required": false, 
"type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.String>", "prefix": "parameter.", "multiValue": true, "deprecated": 
false, "deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Tool in [...]
+    "readOnlyHint": { "index": 8, "kind": "property", "displayName": "Read 
Only Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool only reads data and 
does not m [...]
+    "tags": { "index": 9, "kind": "property", "displayName": "Tags", "group": 
"consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Comma-separated list of tags used to group 
tools. Producers filter the registry by these tags to [...]
+    "title": { "index": 10, "kind": "property", "displayName": "Title", 
"group": "consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Optional display title for MCP tool listings. 
Advisory hint for MCP clients only." },
+    "autowiredEnabled": { "index": 11, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching  [...]
   },
   "properties": {
     "toolName": { "index": 0, "kind": "path", "displayName": "Tool Name", 
"group": "consumer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The tool name. This is the 
name the LLM sees and uses to invoke the tool." },
     "argSchema": { "index": 1, "kind": "parameter", "displayName": "Arg 
Schema", "group": "consumer", "label": "consumer", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"supportFileReference": true, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Raw JSON Schema for tool input parameters. 
Supports in [...]
     "description": { "index": 2, "kind": "parameter", "displayName": 
"Description", "group": "consumer", "label": "consumer", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Human-readable 
description of what this tool does. Passed verbatim to the LLM; be [...]
-    "parameters": { "index": 3, "kind": "parameter", "displayName": 
"Parameters", "group": "consumer", "label": "consumer", "required": false, 
"type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.String>", "prefix": "parameter.", "multiValue": true, "deprecated": 
false, "deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Tool i [...]
-    "tags": { "index": 4, "kind": "parameter", "displayName": "Tags", "group": 
"consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Comma-separated list of tags used to group 
tools. Producers filter the registry by these tags t [...]
-    "bridgeErrorHandler": { "index": 5, "kind": "parameter", "displayName": 
"Bridge Error Handler", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Allows for bridging the consumer to the 
Camel routing Error Handler, which mean any exceptions (if possible) occurred 
while the Camel consumer is trying to pickup incoming  [...]
-    "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": 
"Exception Handler", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", 
"deprecated": false, "autowired": false, "secret": false, "description": "To 
let the consumer use a custom ExceptionHandler. Notice if the option 
bridgeErrorHandler is enabled then this option is not in use. By def [...]
-    "exchangePattern": { "index": 7, "kind": "parameter", "displayName": 
"Exchange Pattern", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "enum", "javaType": 
"org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], 
"deprecated": false, "autowired": false, "secret": false, "description": "Sets 
the exchange pattern when the consumer creates an exchange." }
+    "destructiveHint": { "index": 3, "kind": "parameter", "displayName": 
"Destructive Hint", "group": "consumer", "label": "consumer", "required": 
false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool may perform destructive 
 [...]
+    "idempotentHint": { "index": 4, "kind": "parameter", "displayName": 
"Idempotent Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that repeating the tool call with the 
sa [...]
+    "openWorldHint": { "index": 5, "kind": "parameter", "displayName": "Open 
World Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool interacts with external 
sys [...]
+    "parameters": { "index": 6, "kind": "parameter", "displayName": 
"Parameters", "group": "consumer", "label": "consumer", "required": false, 
"type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.String>", "prefix": "parameter.", "multiValue": true, "deprecated": 
false, "deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Tool i [...]
+    "readOnlyHint": { "index": 7, "kind": "parameter", "displayName": "Read 
Only Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool only reads data and 
does not  [...]
+    "tags": { "index": 8, "kind": "parameter", "displayName": "Tags", "group": 
"consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Comma-separated list of tags used to group 
tools. Producers filter the registry by these tags t [...]
+    "title": { "index": 9, "kind": "parameter", "displayName": "Title", 
"group": "consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Optional display title for MCP tool listings. 
Advisory hint for MCP clients only." },
+    "bridgeErrorHandler": { "index": 10, "kind": "parameter", "displayName": 
"Bridge Error Handler", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Allows for bridging the consumer to the 
Camel routing Error Handler, which mean any exceptions (if possible) occurred 
while the Camel consumer is trying to pickup incoming [...]
+    "exceptionHandler": { "index": 11, "kind": "parameter", "displayName": 
"Exception Handler", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", 
"deprecated": false, "autowired": false, "secret": false, "description": "To 
let the consumer use a custom ExceptionHandler. Notice if the option 
bridgeErrorHandler is enabled then this option is not in use. By de [...]
+    "exchangePattern": { "index": 12, "kind": "parameter", "displayName": 
"Exchange Pattern", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "enum", "javaType": 
"org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], 
"deprecated": false, "autowired": false, "secret": false, "description": "Sets 
the exchange pattern when the consumer creates an exchange." }
   }
 }
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/ai-tool-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/ai-tool-component.adoc
index a55a8b898782..04ea72c081c1 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/ai-tool-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/ai-tool-component.adoc
@@ -197,6 +197,50 @@ Top-level schema properties are exposed as exchange 
headers. Nested values are p
 
 The root schema must be a JSON Schema object with a top-level `properties` 
map. Camel always allowlists top-level property names when invoking the tool 
route, even if the schema sets `additionalProperties: true`. Nested fields are 
not flattened into headers; only top-level properties become exchange headers 
(Map/List/primitive values).
 
+=== MCP Tool Annotation Hints
+
+When exposing `ai-tool` routes through the 
xref:components::mcp-server.adoc[MCP Server] component, you can declare 
optional behavioral hints aligned with the MCP specification 
(`ToolAnnotations`). MCP clients may use these hints for per-tool policy (for 
example auto-approving read-only tools or requiring confirmation before 
destructive ones).
+
+These hints are **advisory only** — Camel does not enforce them. MCP clients 
must treat them as untrusted UX metadata (per the MCP specification), not as 
authorization. Inaccurate hints can mislead client-side confirmation flows.
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("ai-tool:delete_order?tags=orders&description=Delete an order"
+     + "&title=Delete order"
+     + "&readOnlyHint=false"
+     + "&destructiveHint=true"
+     + "&idempotentHint=false"
+     + "&openWorldHint=true")
+    .to("direct:deleteOrder");
+----
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: ai-tool:delete_order
+      parameters:
+        tags: orders
+        description: "Delete an order"
+        title: "Delete order"
+        readOnlyHint: false
+        destructiveHint: true
+        idempotentHint: false
+        openWorldHint: true
+      steps:
+        - to: direct:deleteOrder
+----
+====
+
+Supported options: `title`, `readOnlyHint`, `destructiveHint`, 
`idempotentHint`, and `openWorldHint`. When a hint is omitted, it is not 
published; MCP clients then apply their own defaults (for example assuming 
destructive/open-world unless told otherwise).
+
+The `title` option maps to the MCP tool's top-level `title` field (not 
`ToolAnnotations.title`). Boolean hint options use nullable configuration: when 
unset, Camel omits them from the published MCP tool even though the component 
catalog may list `defaultValue: false` for documentation tooling.
+
 === Tag-Based Discovery
 
 Tags group tools so that AI producers can select relevant subsets.
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mcp-server.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mcp-server.adoc
index 17e3b436e191..ffe21a708a75 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mcp-server.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mcp-server.adoc
@@ -101,6 +101,14 @@ YAML::
 ----
 ====
 
+=== Tool annotation hints
+
+`ai-tool` routes can declare optional MCP `ToolAnnotations` hints
+(`title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, 
`openWorldHint`).
+The bridge passes them through to the MCP engine. See
+xref:ROOT:ai-tool-component.adoc#_mcp_tool_annotation_hints[MCP Tool 
Annotation Hints]
+for configuration examples. Hints are advisory UX metadata only — not 
authorization.
+
 On Camel Main and Camel JBang no code is needed — like Jolokia or
 Prometheus, the server starts from configuration properties alone:
 
diff --git 
a/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolComponentConfigurer.java
 
b/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolComponentConfigurer.java
index 029c6b816335..f5a2d7183da4 100644
--- 
a/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolComponentConfigurer.java
+++ 
b/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolComponentConfigurer.java
@@ -38,8 +38,17 @@ public class AiToolComponentConfigurer extends 
PropertyConfigurerSupport impleme
         case "bridgeErrorHandler": 
target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); 
return true;
         case "configuration": target.setConfiguration(property(camelContext, 
org.apache.camel.component.ai.tool.AiToolConfiguration.class, value)); return 
true;
         case "description": 
getOrCreateConfiguration(target).setDescription(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "destructivehint":
+        case "destructiveHint": 
getOrCreateConfiguration(target).setDestructiveHint(property(camelContext, 
java.lang.Boolean.class, value)); return true;
+        case "idempotenthint":
+        case "idempotentHint": 
getOrCreateConfiguration(target).setIdempotentHint(property(camelContext, 
java.lang.Boolean.class, value)); return true;
+        case "openworldhint":
+        case "openWorldHint": 
getOrCreateConfiguration(target).setOpenWorldHint(property(camelContext, 
java.lang.Boolean.class, value)); return true;
         case "parameters": 
getOrCreateConfiguration(target).setParameters(property(camelContext, 
java.util.Map.class, value)); return true;
+        case "readonlyhint":
+        case "readOnlyHint": 
getOrCreateConfiguration(target).setReadOnlyHint(property(camelContext, 
java.lang.Boolean.class, value)); return true;
         case "tags": 
getOrCreateConfiguration(target).setTags(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "title": 
getOrCreateConfiguration(target).setTitle(property(camelContext, 
java.lang.String.class, value)); return true;
         default: return false;
         }
     }
@@ -55,8 +64,17 @@ public class AiToolComponentConfigurer extends 
PropertyConfigurerSupport impleme
         case "bridgeErrorHandler": return boolean.class;
         case "configuration": return 
org.apache.camel.component.ai.tool.AiToolConfiguration.class;
         case "description": return java.lang.String.class;
+        case "destructivehint":
+        case "destructiveHint": return java.lang.Boolean.class;
+        case "idempotenthint":
+        case "idempotentHint": return java.lang.Boolean.class;
+        case "openworldhint":
+        case "openWorldHint": return java.lang.Boolean.class;
         case "parameters": return java.util.Map.class;
+        case "readonlyhint":
+        case "readOnlyHint": return java.lang.Boolean.class;
         case "tags": return java.lang.String.class;
+        case "title": return java.lang.String.class;
         default: return null;
         }
     }
@@ -73,8 +91,17 @@ public class AiToolComponentConfigurer extends 
PropertyConfigurerSupport impleme
         case "bridgeErrorHandler": return target.isBridgeErrorHandler();
         case "configuration": return target.getConfiguration();
         case "description": return 
getOrCreateConfiguration(target).getDescription();
+        case "destructivehint":
+        case "destructiveHint": return 
getOrCreateConfiguration(target).getDestructiveHint();
+        case "idempotenthint":
+        case "idempotentHint": return 
getOrCreateConfiguration(target).getIdempotentHint();
+        case "openworldhint":
+        case "openWorldHint": return 
getOrCreateConfiguration(target).getOpenWorldHint();
         case "parameters": return 
getOrCreateConfiguration(target).getParameters();
+        case "readonlyhint":
+        case "readOnlyHint": return 
getOrCreateConfiguration(target).getReadOnlyHint();
         case "tags": return getOrCreateConfiguration(target).getTags();
+        case "title": return getOrCreateConfiguration(target).getTitle();
         default: return null;
         }
     }
diff --git 
a/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolConfigurationConfigurer.java
 
b/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolConfigurationConfigurer.java
index f79d66df604b..d20e0c4742a1 100644
--- 
a/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolConfigurationConfigurer.java
+++ 
b/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolConfigurationConfigurer.java
@@ -26,8 +26,17 @@ public class AiToolConfigurationConfigurer extends 
org.apache.camel.support.comp
         case "argschema":
         case "argSchema": target.setArgSchema(property(camelContext, 
java.lang.String.class, value)); return true;
         case "description": target.setDescription(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "destructivehint":
+        case "destructiveHint": 
target.setDestructiveHint(property(camelContext, java.lang.Boolean.class, 
value)); return true;
+        case "idempotenthint":
+        case "idempotentHint": target.setIdempotentHint(property(camelContext, 
java.lang.Boolean.class, value)); return true;
+        case "openworldhint":
+        case "openWorldHint": target.setOpenWorldHint(property(camelContext, 
java.lang.Boolean.class, value)); return true;
         case "parameters": target.setParameters(property(camelContext, 
java.util.Map.class, value)); return true;
+        case "readonlyhint":
+        case "readOnlyHint": target.setReadOnlyHint(property(camelContext, 
java.lang.Boolean.class, value)); return true;
         case "tags": target.setTags(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "title": target.setTitle(property(camelContext, 
java.lang.String.class, value)); return true;
         default: return false;
         }
     }
@@ -38,8 +47,17 @@ public class AiToolConfigurationConfigurer extends 
org.apache.camel.support.comp
         case "argschema":
         case "argSchema": return java.lang.String.class;
         case "description": return java.lang.String.class;
+        case "destructivehint":
+        case "destructiveHint": return java.lang.Boolean.class;
+        case "idempotenthint":
+        case "idempotentHint": return java.lang.Boolean.class;
+        case "openworldhint":
+        case "openWorldHint": return java.lang.Boolean.class;
         case "parameters": return java.util.Map.class;
+        case "readonlyhint":
+        case "readOnlyHint": return java.lang.Boolean.class;
         case "tags": return java.lang.String.class;
+        case "title": return java.lang.String.class;
         default: return null;
         }
     }
@@ -51,8 +69,17 @@ public class AiToolConfigurationConfigurer extends 
org.apache.camel.support.comp
         case "argschema":
         case "argSchema": return target.getArgSchema();
         case "description": return target.getDescription();
+        case "destructivehint":
+        case "destructiveHint": return target.getDestructiveHint();
+        case "idempotenthint":
+        case "idempotentHint": return target.getIdempotentHint();
+        case "openworldhint":
+        case "openWorldHint": return target.getOpenWorldHint();
         case "parameters": return target.getParameters();
+        case "readonlyhint":
+        case "readOnlyHint": return target.getReadOnlyHint();
         case "tags": return target.getTags();
+        case "title": return target.getTitle();
         default: return null;
         }
     }
diff --git 
a/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolEndpointConfigurer.java
 
b/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolEndpointConfigurer.java
index d658045e6821..d369d659852a 100644
--- 
a/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolEndpointConfigurer.java
+++ 
b/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolEndpointConfigurer.java
@@ -28,12 +28,21 @@ public class AiToolEndpointConfigurer extends 
PropertyConfigurerSupport implemen
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": 
target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); 
return true;
         case "description": 
target.getConfiguration().setDescription(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "destructivehint":
+        case "destructiveHint": 
target.getConfiguration().setDestructiveHint(property(camelContext, 
java.lang.Boolean.class, value)); return true;
         case "exceptionhandler":
         case "exceptionHandler": 
target.setExceptionHandler(property(camelContext, 
org.apache.camel.spi.ExceptionHandler.class, value)); return true;
         case "exchangepattern":
         case "exchangePattern": 
target.setExchangePattern(property(camelContext, 
org.apache.camel.ExchangePattern.class, value)); return true;
+        case "idempotenthint":
+        case "idempotentHint": 
target.getConfiguration().setIdempotentHint(property(camelContext, 
java.lang.Boolean.class, value)); return true;
+        case "openworldhint":
+        case "openWorldHint": 
target.getConfiguration().setOpenWorldHint(property(camelContext, 
java.lang.Boolean.class, value)); return true;
         case "parameters": 
target.getConfiguration().setParameters(property(camelContext, 
java.util.Map.class, value)); return true;
+        case "readonlyhint":
+        case "readOnlyHint": 
target.getConfiguration().setReadOnlyHint(property(camelContext, 
java.lang.Boolean.class, value)); return true;
         case "tags": target.getConfiguration().setTags(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "title": 
target.getConfiguration().setTitle(property(camelContext, 
java.lang.String.class, value)); return true;
         default: return false;
         }
     }
@@ -46,12 +55,21 @@ public class AiToolEndpointConfigurer extends 
PropertyConfigurerSupport implemen
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": return boolean.class;
         case "description": return java.lang.String.class;
+        case "destructivehint":
+        case "destructiveHint": return java.lang.Boolean.class;
         case "exceptionhandler":
         case "exceptionHandler": return 
org.apache.camel.spi.ExceptionHandler.class;
         case "exchangepattern":
         case "exchangePattern": return org.apache.camel.ExchangePattern.class;
+        case "idempotenthint":
+        case "idempotentHint": return java.lang.Boolean.class;
+        case "openworldhint":
+        case "openWorldHint": return java.lang.Boolean.class;
         case "parameters": return java.util.Map.class;
+        case "readonlyhint":
+        case "readOnlyHint": return java.lang.Boolean.class;
         case "tags": return java.lang.String.class;
+        case "title": return java.lang.String.class;
         default: return null;
         }
     }
@@ -65,12 +83,21 @@ public class AiToolEndpointConfigurer extends 
PropertyConfigurerSupport implemen
         case "bridgeerrorhandler":
         case "bridgeErrorHandler": return target.isBridgeErrorHandler();
         case "description": return target.getConfiguration().getDescription();
+        case "destructivehint":
+        case "destructiveHint": return 
target.getConfiguration().getDestructiveHint();
         case "exceptionhandler":
         case "exceptionHandler": return target.getExceptionHandler();
         case "exchangepattern":
         case "exchangePattern": return target.getExchangePattern();
+        case "idempotenthint":
+        case "idempotentHint": return 
target.getConfiguration().getIdempotentHint();
+        case "openworldhint":
+        case "openWorldHint": return 
target.getConfiguration().getOpenWorldHint();
         case "parameters": return target.getConfiguration().getParameters();
+        case "readonlyhint":
+        case "readOnlyHint": return 
target.getConfiguration().getReadOnlyHint();
         case "tags": return target.getConfiguration().getTags();
+        case "title": return target.getConfiguration().getTitle();
         default: return null;
         }
     }
diff --git 
a/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolEndpointUriFactory.java
 
b/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolEndpointUriFactory.java
index 85d40f65427c..0a4c6a4f9e2c 100644
--- 
a/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolEndpointUriFactory.java
+++ 
b/components/camel-ai/camel-ai-tool/src/generated/java/org/apache/camel/component/ai/tool/AiToolEndpointUriFactory.java
@@ -24,14 +24,19 @@ public class AiToolEndpointUriFactory extends 
org.apache.camel.support.component
     private static final Set<String> ENDPOINT_IDENTITY_PROPERTY_NAMES;
     private static final Map<String, String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(8);
+        Set<String> props = new HashSet<>(13);
         props.add("argSchema");
         props.add("bridgeErrorHandler");
         props.add("description");
+        props.add("destructiveHint");
         props.add("exceptionHandler");
         props.add("exchangePattern");
+        props.add("idempotentHint");
+        props.add("openWorldHint");
         props.add("parameters");
+        props.add("readOnlyHint");
         props.add("tags");
+        props.add("title");
         props.add("toolName");
         PROPERTY_NAMES = Collections.unmodifiableSet(props);
         SECRET_PROPERTY_NAMES = Collections.emptySet();
diff --git 
a/components/camel-ai/camel-ai-tool/src/generated/resources/META-INF/org/apache/camel/component/ai/tool/ai-tool.json
 
b/components/camel-ai/camel-ai-tool/src/generated/resources/META-INF/org/apache/camel/component/ai/tool/ai-tool.json
index e0ae716192d7..8f3f695b609a 100644
--- 
a/components/camel-ai/camel-ai-tool/src/generated/resources/META-INF/org/apache/camel/component/ai/tool/ai-tool.json
+++ 
b/components/camel-ai/camel-ai-tool/src/generated/resources/META-INF/org/apache/camel/component/ai/tool/ai-tool.json
@@ -28,18 +28,28 @@
     "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": 
"Bridge Error Handler", "group": "consumer", "label": "consumer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Allows for bridging the consumer to the Camel routing Error Handler, which 
mean any exceptions (if possible) occurred while the Camel consumer is trying 
to pickup incoming messages, or the like [...]
     "configuration": { "index": 2, "kind": "property", "displayName": 
"Configuration", "group": "consumer", "label": "", "required": false, "type": 
"object", "javaType": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"deprecated": false, "autowired": false, "secret": false, "description": "The 
component configuration" },
     "description": { "index": 3, "kind": "property", "displayName": 
"Description", "group": "consumer", "label": "consumer", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Human-readable 
description of what this tool does. Passed verbatim to the LLM; be  [...]
-    "parameters": { "index": 4, "kind": "property", "displayName": 
"Parameters", "group": "consumer", "label": "consumer", "required": false, 
"type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.String>", "prefix": "parameter.", "multiValue": true, "deprecated": 
false, "deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Tool in [...]
-    "tags": { "index": 5, "kind": "property", "displayName": "Tags", "group": 
"consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Comma-separated list of tags used to group 
tools. Producers filter the registry by these tags to [...]
-    "autowiredEnabled": { "index": 6, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
+    "destructiveHint": { "index": 4, "kind": "property", "displayName": 
"Destructive Hint", "group": "consumer", "label": "consumer", "required": 
false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool may perform destructive 
o [...]
+    "idempotentHint": { "index": 5, "kind": "property", "displayName": 
"Idempotent Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that repeating the tool call with the 
sam [...]
+    "openWorldHint": { "index": 6, "kind": "property", "displayName": "Open 
World Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool interacts with external 
syst [...]
+    "parameters": { "index": 7, "kind": "property", "displayName": 
"Parameters", "group": "consumer", "label": "consumer", "required": false, 
"type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.String>", "prefix": "parameter.", "multiValue": true, "deprecated": 
false, "deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Tool in [...]
+    "readOnlyHint": { "index": 8, "kind": "property", "displayName": "Read 
Only Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool only reads data and 
does not m [...]
+    "tags": { "index": 9, "kind": "property", "displayName": "Tags", "group": 
"consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Comma-separated list of tags used to group 
tools. Producers filter the registry by these tags to [...]
+    "title": { "index": 10, "kind": "property", "displayName": "Title", 
"group": "consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Optional display title for MCP tool listings. 
Advisory hint for MCP clients only." },
+    "autowiredEnabled": { "index": 11, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching  [...]
   },
   "properties": {
     "toolName": { "index": 0, "kind": "path", "displayName": "Tool Name", 
"group": "consumer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The tool name. This is the 
name the LLM sees and uses to invoke the tool." },
     "argSchema": { "index": 1, "kind": "parameter", "displayName": "Arg 
Schema", "group": "consumer", "label": "consumer", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"supportFileReference": true, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Raw JSON Schema for tool input parameters. 
Supports in [...]
     "description": { "index": 2, "kind": "parameter", "displayName": 
"Description", "group": "consumer", "label": "consumer", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Human-readable 
description of what this tool does. Passed verbatim to the LLM; be [...]
-    "parameters": { "index": 3, "kind": "parameter", "displayName": 
"Parameters", "group": "consumer", "label": "consumer", "required": false, 
"type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.String>", "prefix": "parameter.", "multiValue": true, "deprecated": 
false, "deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Tool i [...]
-    "tags": { "index": 4, "kind": "parameter", "displayName": "Tags", "group": 
"consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Comma-separated list of tags used to group 
tools. Producers filter the registry by these tags t [...]
-    "bridgeErrorHandler": { "index": 5, "kind": "parameter", "displayName": 
"Bridge Error Handler", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Allows for bridging the consumer to the 
Camel routing Error Handler, which mean any exceptions (if possible) occurred 
while the Camel consumer is trying to pickup incoming  [...]
-    "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": 
"Exception Handler", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", 
"deprecated": false, "autowired": false, "secret": false, "description": "To 
let the consumer use a custom ExceptionHandler. Notice if the option 
bridgeErrorHandler is enabled then this option is not in use. By def [...]
-    "exchangePattern": { "index": 7, "kind": "parameter", "displayName": 
"Exchange Pattern", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "enum", "javaType": 
"org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], 
"deprecated": false, "autowired": false, "secret": false, "description": "Sets 
the exchange pattern when the consumer creates an exchange." }
+    "destructiveHint": { "index": 3, "kind": "parameter", "displayName": 
"Destructive Hint", "group": "consumer", "label": "consumer", "required": 
false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool may perform destructive 
 [...]
+    "idempotentHint": { "index": 4, "kind": "parameter", "displayName": 
"Idempotent Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that repeating the tool call with the 
sa [...]
+    "openWorldHint": { "index": 5, "kind": "parameter", "displayName": "Open 
World Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool interacts with external 
sys [...]
+    "parameters": { "index": 6, "kind": "parameter", "displayName": 
"Parameters", "group": "consumer", "label": "consumer", "required": false, 
"type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.String>", "prefix": "parameter.", "multiValue": true, "deprecated": 
false, "deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", 
"configurationField": "configuration", "description": "Tool i [...]
+    "readOnlyHint": { "index": 7, "kind": "parameter", "displayName": "Read 
Only Hint", "group": "consumer", "label": "consumer", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "MCP hint that the tool only reads data and 
does not  [...]
+    "tags": { "index": 8, "kind": "parameter", "displayName": "Tags", "group": 
"consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Comma-separated list of tags used to group 
tools. Producers filter the registry by these tags t [...]
+    "title": { "index": 9, "kind": "parameter", "displayName": "Title", 
"group": "consumer", "label": "consumer", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": 
"configuration", "description": "Optional display title for MCP tool listings. 
Advisory hint for MCP clients only." },
+    "bridgeErrorHandler": { "index": 10, "kind": "parameter", "displayName": 
"Bridge Error Handler", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Allows for bridging the consumer to the 
Camel routing Error Handler, which mean any exceptions (if possible) occurred 
while the Camel consumer is trying to pickup incoming [...]
+    "exceptionHandler": { "index": 11, "kind": "parameter", "displayName": 
"Exception Handler", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", 
"deprecated": false, "autowired": false, "secret": false, "description": "To 
let the consumer use a custom ExceptionHandler. Notice if the option 
bridgeErrorHandler is enabled then this option is not in use. By de [...]
+    "exchangePattern": { "index": 12, "kind": "parameter", "displayName": 
"Exchange Pattern", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "enum", "javaType": 
"org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], 
"deprecated": false, "autowired": false, "secret": false, "description": "Sets 
the exchange pattern when the consumer creates an exchange." }
   }
 }
diff --git 
a/components/camel-ai/camel-ai-tool/src/main/docs/ai-tool-component.adoc 
b/components/camel-ai/camel-ai-tool/src/main/docs/ai-tool-component.adoc
index a55a8b898782..04ea72c081c1 100644
--- a/components/camel-ai/camel-ai-tool/src/main/docs/ai-tool-component.adoc
+++ b/components/camel-ai/camel-ai-tool/src/main/docs/ai-tool-component.adoc
@@ -197,6 +197,50 @@ Top-level schema properties are exposed as exchange 
headers. Nested values are p
 
 The root schema must be a JSON Schema object with a top-level `properties` 
map. Camel always allowlists top-level property names when invoking the tool 
route, even if the schema sets `additionalProperties: true`. Nested fields are 
not flattened into headers; only top-level properties become exchange headers 
(Map/List/primitive values).
 
+=== MCP Tool Annotation Hints
+
+When exposing `ai-tool` routes through the 
xref:components::mcp-server.adoc[MCP Server] component, you can declare 
optional behavioral hints aligned with the MCP specification 
(`ToolAnnotations`). MCP clients may use these hints for per-tool policy (for 
example auto-approving read-only tools or requiring confirmation before 
destructive ones).
+
+These hints are **advisory only** — Camel does not enforce them. MCP clients 
must treat them as untrusted UX metadata (per the MCP specification), not as 
authorization. Inaccurate hints can mislead client-side confirmation flows.
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("ai-tool:delete_order?tags=orders&description=Delete an order"
+     + "&title=Delete order"
+     + "&readOnlyHint=false"
+     + "&destructiveHint=true"
+     + "&idempotentHint=false"
+     + "&openWorldHint=true")
+    .to("direct:deleteOrder");
+----
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: ai-tool:delete_order
+      parameters:
+        tags: orders
+        description: "Delete an order"
+        title: "Delete order"
+        readOnlyHint: false
+        destructiveHint: true
+        idempotentHint: false
+        openWorldHint: true
+      steps:
+        - to: direct:deleteOrder
+----
+====
+
+Supported options: `title`, `readOnlyHint`, `destructiveHint`, 
`idempotentHint`, and `openWorldHint`. When a hint is omitted, it is not 
published; MCP clients then apply their own defaults (for example assuming 
destructive/open-world unless told otherwise).
+
+The `title` option maps to the MCP tool's top-level `title` field (not 
`ToolAnnotations.title`). Boolean hint options use nullable configuration: when 
unset, Camel omits them from the published MCP tool even though the component 
catalog may list `defaultValue: false` for documentation tooling.
+
 === Tag-Based Discovery
 
 Tags group tools so that AI producers can select relevant subsets.
diff --git 
a/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolAnnotations.java
 
b/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolAnnotations.java
new file mode 100644
index 000000000000..b17ea8a22e86
--- /dev/null
+++ 
b/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolAnnotations.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.ai.tool;
+
+/**
+ * Optional MCP tool annotation hints for a route-based {@code ai-tool}. 
Values are advisory for MCP clients and are not
+ * enforced by Camel.
+ *
+ * @since 4.22
+ */
+public record AiToolAnnotations(
+        String title,
+        Boolean readOnlyHint,
+        Boolean destructiveHint,
+        Boolean idempotentHint,
+        Boolean openWorldHint) {
+
+    /**
+     * Builds annotations from endpoint configuration, or {@code null} when no 
hint is configured.
+     */
+    public static AiToolAnnotations fromConfiguration(AiToolConfiguration 
configuration) {
+        if (configuration == null) {
+            return null;
+        }
+        String title = blankToNull(configuration.getTitle());
+        Boolean readOnlyHint = configuration.getReadOnlyHint();
+        Boolean destructiveHint = configuration.getDestructiveHint();
+        Boolean idempotentHint = configuration.getIdempotentHint();
+        Boolean openWorldHint = configuration.getOpenWorldHint();
+        if (title == null && readOnlyHint == null && destructiveHint == null 
&& idempotentHint == null
+                && openWorldHint == null) {
+            return null;
+        }
+        return new AiToolAnnotations(title, readOnlyHint, destructiveHint, 
idempotentHint, openWorldHint);
+    }
+
+    private static String blankToNull(String value) {
+        return value == null || value.isBlank() ? null : value.trim();
+    }
+}
diff --git 
a/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolConfiguration.java
 
b/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolConfiguration.java
index 78259c98687e..715ef848e10a 100644
--- 
a/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolConfiguration.java
+++ 
b/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolConfiguration.java
@@ -61,6 +61,30 @@ public class AiToolConfiguration implements Cloneable {
     @Metadata(label = "consumer", supportFileReference = true, largeInput = 
true, inputLanguage = "json")
     private String argSchema;
 
+    @Metadata(label = "consumer")
+    @UriParam(description = "Optional display title for MCP tool listings. 
Advisory hint for MCP clients only.")
+    private String title;
+
+    @Metadata(label = "consumer")
+    @UriParam(description = "MCP hint that the tool only reads data and does 
not modify state. Advisory for MCP clients; "
+                            + "not enforced by Camel.")
+    private Boolean readOnlyHint;
+
+    @Metadata(label = "consumer")
+    @UriParam(description = "MCP hint that the tool may perform destructive or 
irreversible updates. Advisory for MCP "
+                            + "clients; not enforced by Camel.")
+    private Boolean destructiveHint;
+
+    @Metadata(label = "consumer")
+    @UriParam(description = "MCP hint that repeating the tool call with the 
same arguments has no additional effect. "
+                            + "Advisory for MCP clients; not enforced by 
Camel.")
+    private Boolean idempotentHint;
+
+    @Metadata(label = "consumer")
+    @UriParam(description = "MCP hint that the tool interacts with external 
systems outside the application's control. "
+                            + "Advisory for MCP clients; not enforced by 
Camel.")
+    private Boolean openWorldHint;
+
     public AiToolConfiguration() {
     }
 
@@ -96,6 +120,46 @@ public class AiToolConfiguration implements Cloneable {
         this.argSchema = argSchema;
     }
 
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public Boolean getReadOnlyHint() {
+        return readOnlyHint;
+    }
+
+    public void setReadOnlyHint(Boolean readOnlyHint) {
+        this.readOnlyHint = readOnlyHint;
+    }
+
+    public Boolean getDestructiveHint() {
+        return destructiveHint;
+    }
+
+    public void setDestructiveHint(Boolean destructiveHint) {
+        this.destructiveHint = destructiveHint;
+    }
+
+    public Boolean getIdempotentHint() {
+        return idempotentHint;
+    }
+
+    public void setIdempotentHint(Boolean idempotentHint) {
+        this.idempotentHint = idempotentHint;
+    }
+
+    public Boolean getOpenWorldHint() {
+        return openWorldHint;
+    }
+
+    public void setOpenWorldHint(Boolean openWorldHint) {
+        this.openWorldHint = openWorldHint;
+    }
+
     public AiToolConfiguration copy() {
         try {
             AiToolConfiguration copy = (AiToolConfiguration) super.clone();
diff --git 
a/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolConsumer.java
 
b/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolConsumer.java
index a2ca9db90a38..1f9c587bb7f4 100644
--- 
a/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolConsumer.java
+++ 
b/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolConsumer.java
@@ -67,8 +67,9 @@ public class AiToolConsumer extends DefaultConsumer {
             desc = toolName;
         }
 
+        AiToolAnnotations annotations = 
AiToolAnnotations.fromConfiguration(configuration);
         registeredSpec = new AiToolSpec(
-                toolName, desc, parameterDefs, jsonSchema, this);
+                toolName, desc, parameterDefs, jsonSchema, annotations, this);
 
         String tags = configuration.getTags();
         String[] parsedTags = (tags != null && !tags.isBlank())
diff --git 
a/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolSpec.java
 
b/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolSpec.java
index 2206b06fc6d0..3a21fb3bbe4a 100644
--- 
a/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolSpec.java
+++ 
b/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolSpec.java
@@ -40,6 +40,7 @@ public final class AiToolSpec {
     private final String parametersJsonSchema;
     private final Set<String> declaredArgumentNames;
     private final Set<String> requiredArgumentNames;
+    private final AiToolAnnotations annotations;
     private final DefaultConsumer consumer;
 
     public AiToolSpec(
@@ -47,6 +48,7 @@ public final class AiToolSpec {
                       String description,
                       Map<String, AiToolParameterHelper.ParameterDef> 
parameterDefs,
                       String parametersJsonSchema,
+                      AiToolAnnotations annotations,
                       DefaultConsumer consumer) {
         this.name = name;
         this.description = description;
@@ -65,6 +67,7 @@ public final class AiToolSpec {
             this.declaredArgumentNames = Set.of();
             this.requiredArgumentNames = Set.of();
         }
+        this.annotations = annotations;
         this.consumer = consumer;
     }
 
@@ -108,6 +111,13 @@ public final class AiToolSpec {
         return requiredArgumentNames;
     }
 
+    /**
+     * Optional MCP tool annotation hints, or {@code null} when none are 
configured.
+     */
+    public AiToolAnnotations getAnnotations() {
+        return annotations;
+    }
+
     /**
      * The Camel consumer that executes this tool's route when the LLM invokes 
it.
      */
@@ -132,13 +142,14 @@ public final class AiToolSpec {
                 && Objects.equals(parametersJsonSchema, 
that.parametersJsonSchema)
                 && Objects.equals(declaredArgumentNames, 
that.declaredArgumentNames)
                 && Objects.equals(requiredArgumentNames, 
that.requiredArgumentNames)
+                && Objects.equals(annotations, that.annotations)
                 && Objects.equals(consumer, that.consumer);
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(name, description, parameterDefs, 
parametersJsonSchema, declaredArgumentNames,
-                requiredArgumentNames, consumer);
+                requiredArgumentNames, annotations, consumer);
     }
 
     @Override
diff --git 
a/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolAnnotationsTest.java
 
b/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolAnnotationsTest.java
new file mode 100644
index 000000000000..7190d6c154ea
--- /dev/null
+++ 
b/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolAnnotationsTest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.ai.tool;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class AiToolAnnotationsTest {
+
+    @Test
+    void shouldReturnNullWhenNoHintsConfigured() {
+        AiToolConfiguration configuration = new AiToolConfiguration();
+
+        
assertThat(AiToolAnnotations.fromConfiguration(configuration)).isNull();
+    }
+
+    @Test
+    void shouldBuildAnnotationsFromConfiguration() {
+        AiToolConfiguration configuration = new AiToolConfiguration();
+        configuration.setTitle("Delete order");
+        configuration.setReadOnlyHint(false);
+        configuration.setDestructiveHint(true);
+        configuration.setIdempotentHint(false);
+        configuration.setOpenWorldHint(true);
+
+        AiToolAnnotations annotations = 
AiToolAnnotations.fromConfiguration(configuration);
+
+        assertThat(annotations).isNotNull();
+        assertThat(annotations.title()).isEqualTo("Delete order");
+        assertThat(annotations.readOnlyHint()).isFalse();
+        assertThat(annotations.destructiveHint()).isTrue();
+        assertThat(annotations.idempotentHint()).isFalse();
+        assertThat(annotations.openWorldHint()).isTrue();
+    }
+
+    @Test
+    void shouldIgnoreBlankTitle() {
+        AiToolConfiguration configuration = new AiToolConfiguration();
+        configuration.setTitle("   ");
+        configuration.setReadOnlyHint(true);
+
+        AiToolAnnotations annotations = 
AiToolAnnotations.fromConfiguration(configuration);
+
+        assertThat(annotations).isNotNull();
+        assertThat(annotations.title()).isNull();
+        assertThat(annotations.readOnlyHint()).isTrue();
+    }
+
+    @Test
+    void shouldBuildTitleOnlyAnnotations() {
+        AiToolConfiguration configuration = new AiToolConfiguration();
+        configuration.setTitle("Lookup customer");
+
+        AiToolAnnotations annotations = 
AiToolAnnotations.fromConfiguration(configuration);
+
+        assertThat(annotations).isNotNull();
+        assertThat(annotations.title()).isEqualTo("Lookup customer");
+        assertThat(annotations.readOnlyHint()).isNull();
+        assertThat(annotations.destructiveHint()).isNull();
+        assertThat(annotations.idempotentHint()).isNull();
+        assertThat(annotations.openWorldHint()).isNull();
+    }
+
+    @Test
+    void shouldBuildPartialBooleanHintsOnly() {
+        AiToolConfiguration configuration = new AiToolConfiguration();
+        configuration.setDestructiveHint(true);
+
+        AiToolAnnotations annotations = 
AiToolAnnotations.fromConfiguration(configuration);
+
+        assertThat(annotations).isNotNull();
+        assertThat(annotations.title()).isNull();
+        assertThat(annotations.destructiveHint()).isTrue();
+        assertThat(annotations.readOnlyHint()).isNull();
+    }
+}
diff --git 
a/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolEndpointLifecycleTest.java
 
b/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolEndpointLifecycleTest.java
index d5367b4b8222..e9b1aa829455 100644
--- 
a/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolEndpointLifecycleTest.java
+++ 
b/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolEndpointLifecycleTest.java
@@ -357,7 +357,34 @@ public class AiToolEndpointLifecycleTest extends 
CamelTestSupport {
     }
 
     @Test
-    public void testGetAllToolsReturnsAllPools() throws Exception {
+    void testMcpAnnotationsRegisteredOnSpec() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            public void configure() {
+                from("ai-tool:delete_order"
+                     + "?tags=orders"
+                     + "&description=Delete an order"
+                     + "&title=Delete order"
+                     + "&readOnlyHint=false"
+                     + "&destructiveHint=true"
+                     + "&idempotentHint=false"
+                     + "&openWorldHint=true")
+                        .setBody(constant("deleted"));
+            }
+        });
+
+        AiToolSpec spec = 
AiToolRegistry.getOrCreate(context).getToolsByTag("orders").iterator().next();
+        AiToolAnnotations annotations = spec.getAnnotations();
+
+        assertThat(annotations).isNotNull();
+        assertThat(annotations.title()).isEqualTo("Delete order");
+        assertThat(annotations.readOnlyHint()).isFalse();
+        assertThat(annotations.destructiveHint()).isTrue();
+        assertThat(annotations.idempotentHint()).isFalse();
+        assertThat(annotations.openWorldHint()).isTrue();
+    }
+
+    @Test
+    void testGetAllToolsReturnsAllPools() throws Exception {
         context.addRoutes(new RouteBuilder() {
             public void configure() {
                 from("ai-tool:toolA?tags=alpha&description=Tool A")
diff --git 
a/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolExecutorTest.java
 
b/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolExecutorTest.java
index 605486c8d798..028be078bd31 100644
--- 
a/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolExecutorTest.java
+++ 
b/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolExecutorTest.java
@@ -217,7 +217,7 @@ public class AiToolExecutorTest extends CamelTestSupport {
 
     @Test
     public void testExecuteReturnsExecutionErrorForNullConsumer() {
-        AiToolSpec spec = new AiToolSpec("ghostTool", "A tool with no 
consumer", Map.of(), null, null);
+        AiToolSpec spec = new AiToolSpec("ghostTool", "A tool with no 
consumer", Map.of(), null, null, null);
         Exchange exchange = new DefaultExchange(context);
 
         AiToolResult result = AiToolExecutor.execute(spec, null, exchange);
@@ -235,7 +235,7 @@ public class AiToolExecutorTest extends CamelTestSupport {
         DefaultConsumer consumerWithNullProcessor = new 
DefaultConsumer(endpoint, null);
 
         AiToolSpec spec = new AiToolSpec(
-                "nullProc", "test", Map.of(), null, consumerWithNullProcessor);
+                "nullProc", "test", Map.of(), null, null, 
consumerWithNullProcessor);
         Exchange exchange = new DefaultExchange(context);
 
         AiToolResult result = AiToolExecutor.execute(spec, null, exchange);
@@ -370,7 +370,7 @@ public class AiToolExecutorTest extends CamelTestSupport {
                   "required": ["country"]
                 }
                 """;
-        AiToolSpec spec = new AiToolSpec("badRequired", "test", Map.of(), 
schema, findSpec("greetUser").getConsumer());
+        AiToolSpec spec = new AiToolSpec("badRequired", "test", Map.of(), 
schema, null, findSpec("greetUser").getConsumer());
         Exchange exchange = new DefaultExchange(context);
 
         Map<String, Object> arguments = Map.of("country", "Paris");
diff --git 
a/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolRegistryListenerTest.java
 
b/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolRegistryListenerTest.java
index 3d1c5e009acf..5244083f452d 100644
--- 
a/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolRegistryListenerTest.java
+++ 
b/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolRegistryListenerTest.java
@@ -136,7 +136,7 @@ class AiToolRegistryListenerTest {
     }
 
     private static AiToolSpec spec(String name) {
-        return new AiToolSpec(name, name + " description", null, null, null);
+        return new AiToolSpec(name, name + " description", null, null, null, 
null);
     }
 
     private record Event(String type, String tag, AiToolSpec spec) {
diff --git 
a/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolRegistryTest.java
 
b/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolRegistryTest.java
index e6993e82d5f2..d65a153a5c8f 100644
--- 
a/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolRegistryTest.java
+++ 
b/components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolRegistryTest.java
@@ -43,7 +43,7 @@ public class AiToolRegistryTest {
 
     @Test
     public void testPutAndGetTool() {
-        AiToolSpec spec = new AiToolSpec("getTool", "A test tool", Map.of(), 
null, null);
+        AiToolSpec spec = new AiToolSpec("getTool", "A test tool", Map.of(), 
null, null, null);
 
         registry.put("weather", spec);
 
@@ -56,7 +56,7 @@ public class AiToolRegistryTest {
 
     @Test
     public void testRemoveTool() {
-        AiToolSpec spec = new AiToolSpec("getTool", "A test tool", Map.of(), 
null, null);
+        AiToolSpec spec = new AiToolSpec("getTool", "A test tool", Map.of(), 
null, null, null);
 
         registry.put("weather", spec);
         assertThat(registry.getTools().get("weather"))
@@ -71,8 +71,8 @@ public class AiToolRegistryTest {
 
     @Test
     public void testMultipleToolsWithSameTag() {
-        AiToolSpec spec1 = new AiToolSpec("tool1", "Tool 1", Map.of(), null, 
null);
-        AiToolSpec spec2 = new AiToolSpec("tool2", "Tool 2", Map.of(), null, 
null);
+        AiToolSpec spec1 = new AiToolSpec("tool1", "Tool 1", Map.of(), null, 
null, null);
+        AiToolSpec spec2 = new AiToolSpec("tool2", "Tool 2", Map.of(), null, 
null, null);
 
         registry.put("assistant", spec1);
         registry.put("assistant", spec2);
@@ -84,8 +84,8 @@ public class AiToolRegistryTest {
 
     @Test
     public void testRemoveOneOfMultipleTools() {
-        AiToolSpec spec1 = new AiToolSpec("tool1", "Tool 1", Map.of(), null, 
null);
-        AiToolSpec spec2 = new AiToolSpec("tool2", "Tool 2", Map.of(), null, 
null);
+        AiToolSpec spec1 = new AiToolSpec("tool1", "Tool 1", Map.of(), null, 
null, null);
+        AiToolSpec spec2 = new AiToolSpec("tool2", "Tool 2", Map.of(), null, 
null, null);
 
         registry.put("assistant", spec1);
         registry.put("assistant", spec2);
@@ -101,8 +101,8 @@ public class AiToolRegistryTest {
 
     @Test
     public void testTagIsolation() {
-        AiToolSpec weatherSpec = new AiToolSpec("weather", "Weather", 
Map.of(), null, null);
-        AiToolSpec emailSpec = new AiToolSpec("email", "Email", Map.of(), 
null, null);
+        AiToolSpec weatherSpec = new AiToolSpec("weather", "Weather", 
Map.of(), null, null, null);
+        AiToolSpec emailSpec = new AiToolSpec("email", "Email", Map.of(), 
null, null, null);
 
         registry.put("weather", weatherSpec);
         registry.put("email", emailSpec);
@@ -120,7 +120,7 @@ public class AiToolRegistryTest {
 
     @Test
     public void testRemoveFromNonExistentTag() {
-        AiToolSpec spec = new AiToolSpec("tool", "A tool", Map.of(), null, 
null);
+        AiToolSpec spec = new AiToolSpec("tool", "A tool", Map.of(), null, 
null, null);
         registry.remove("nonexistent", spec);
 
         assertThat(registry.getTools())
@@ -133,7 +133,7 @@ public class AiToolRegistryTest {
 
     @Test
     public void testDefaultPoolPutAndRemove() {
-        AiToolSpec spec = new AiToolSpec("defaultTool", "Default", Map.of(), 
null, null);
+        AiToolSpec spec = new AiToolSpec("defaultTool", "Default", Map.of(), 
null, null, null);
 
         registry.putDefault(spec);
         assertThat(registry.getDefaultTools())
@@ -149,8 +149,8 @@ public class AiToolRegistryTest {
 
     @Test
     public void testGetToolsByTagIncludesDefaultPool() {
-        AiToolSpec taggedTool = new AiToolSpec("tagged", "Tagged", Map.of(), 
null, null);
-        AiToolSpec defaultTool = new AiToolSpec("default", "Default", 
Map.of(), null, null);
+        AiToolSpec taggedTool = new AiToolSpec("tagged", "Tagged", Map.of(), 
null, null, null);
+        AiToolSpec defaultTool = new AiToolSpec("default", "Default", 
Map.of(), null, null, null);
 
         registry.put("weather", taggedTool);
         registry.putDefault(defaultTool);
@@ -164,7 +164,7 @@ public class AiToolRegistryTest {
 
     @Test
     public void testGetToolsByTagWithNoMatchReturnsDefaultOnly() {
-        AiToolSpec defaultTool = new AiToolSpec("default", "Default", 
Map.of(), null, null);
+        AiToolSpec defaultTool = new AiToolSpec("default", "Default", 
Map.of(), null, null, null);
         registry.putDefault(defaultTool);
 
         assertThat(registry.getToolsByTag("nonexistent"))
@@ -192,7 +192,7 @@ public class AiToolRegistryTest {
                 }
                 for (int i = 0; i < opsPerThread; i++) {
                     AiToolSpec spec = new AiToolSpec(
-                            "tool-" + threadId + "-" + i, "desc", Map.of(), 
null, null);
+                            "tool-" + threadId + "-" + i, "desc", Map.of(), 
null, null, null);
                     registry.put("concurrent", spec);
                     registry.getToolsByTag("concurrent");
                     registry.getAllTools();
@@ -215,8 +215,8 @@ public class AiToolRegistryTest {
 
     @Test
     public void testDuplicateToolNameUnderSameTagThrows() {
-        AiToolSpec spec1 = new AiToolSpec("sameName", "First", Map.of(), null, 
null);
-        AiToolSpec spec2 = new AiToolSpec("sameName", "Second", Map.of(), 
null, null);
+        AiToolSpec spec1 = new AiToolSpec("sameName", "First", Map.of(), null, 
null, null);
+        AiToolSpec spec2 = new AiToolSpec("sameName", "Second", Map.of(), 
null, null, null);
 
         registry.put("weather", spec1);
 
@@ -233,8 +233,8 @@ public class AiToolRegistryTest {
 
     @Test
     public void testDuplicateToolNameInDefaultPoolThrows() {
-        AiToolSpec spec1 = new AiToolSpec("sameName", "First", Map.of(), null, 
null);
-        AiToolSpec spec2 = new AiToolSpec("sameName", "Second", Map.of(), 
null, null);
+        AiToolSpec spec1 = new AiToolSpec("sameName", "First", Map.of(), null, 
null, null);
+        AiToolSpec spec2 = new AiToolSpec("sameName", "Second", Map.of(), 
null, null, null);
 
         registry.putDefault(spec1);
 
@@ -251,8 +251,8 @@ public class AiToolRegistryTest {
 
     @Test
     public void testSameToolNameDifferentTagsIsAllowed() {
-        AiToolSpec spec1 = new AiToolSpec("sameName", "Weather version", 
Map.of(), null, null);
-        AiToolSpec spec2 = new AiToolSpec("sameName", "Email version", 
Map.of(), null, null);
+        AiToolSpec spec1 = new AiToolSpec("sameName", "Weather version", 
Map.of(), null, null, null);
+        AiToolSpec spec2 = new AiToolSpec("sameName", "Email version", 
Map.of(), null, null, null);
 
         registry.put("weather", spec1);
         registry.put("email", spec2);
@@ -263,8 +263,8 @@ public class AiToolRegistryTest {
 
     @Test
     public void testReRegisterAfterRemoveIsAllowed() {
-        AiToolSpec spec1 = new AiToolSpec("tool", "First", Map.of(), null, 
null);
-        AiToolSpec spec2 = new AiToolSpec("tool", "Second", Map.of(), null, 
null);
+        AiToolSpec spec1 = new AiToolSpec("tool", "First", Map.of(), null, 
null, null);
+        AiToolSpec spec2 = new AiToolSpec("tool", "Second", Map.of(), null, 
null, null);
 
         registry.put("weather", spec1);
         registry.remove("weather", spec1);
@@ -277,9 +277,9 @@ public class AiToolRegistryTest {
 
     @Test
     public void testGetAllToolsMergesTaggedAndDefault() {
-        AiToolSpec tool1 = new AiToolSpec("tool1", "Tool 1", Map.of(), null, 
null);
-        AiToolSpec tool2 = new AiToolSpec("tool2", "Tool 2", Map.of(), null, 
null);
-        AiToolSpec defaultTool = new AiToolSpec("default", "Default", 
Map.of(), null, null);
+        AiToolSpec tool1 = new AiToolSpec("tool1", "Tool 1", Map.of(), null, 
null, null);
+        AiToolSpec tool2 = new AiToolSpec("tool2", "Tool 2", Map.of(), null, 
null, null);
+        AiToolSpec defaultTool = new AiToolSpec("default", "Default", 
Map.of(), null, null, null);
 
         registry.put("weather", tool1);
         registry.put("email", tool2);
diff --git 
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/AiToolSpecToLangChain4jTest.java
 
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/AiToolSpecToLangChain4jTest.java
index ae8d51b65465..e8904027d1ac 100644
--- 
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/AiToolSpecToLangChain4jTest.java
+++ 
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/AiToolSpecToLangChain4jTest.java
@@ -41,7 +41,7 @@ class AiToolSpecToLangChain4jTest {
 
     @Test
     void testBasicToolSpecConversion() {
-        AiToolSpec spec = new AiToolSpec("myTool", "A test tool", Map.of(), 
null, null);
+        AiToolSpec spec = new AiToolSpec("myTool", "A test tool", Map.of(), 
null, null, null);
 
         ToolSpecification result = 
AiToolSpecToLangChain4j.toToolSpecification(spec);
 
@@ -56,7 +56,7 @@ class AiToolSpecToLangChain4jTest {
         rawParams.put("city", "string");
 
         Map<String, AiToolParameterHelper.ParameterDef> defs = 
AiToolParameterHelper.parseParameterMetadata(rawParams);
-        AiToolSpec spec = new AiToolSpec("weather", "Get weather", defs, null, 
null);
+        AiToolSpec spec = new AiToolSpec("weather", "Get weather", defs, null, 
null, null);
 
         ToolSpecification result = 
AiToolSpecToLangChain4j.toToolSpecification(spec);
 
@@ -71,7 +71,7 @@ class AiToolSpecToLangChain4jTest {
         rawParams.put("count", "integer");
 
         Map<String, AiToolParameterHelper.ParameterDef> defs = 
AiToolParameterHelper.parseParameterMetadata(rawParams);
-        AiToolSpec spec = new AiToolSpec("counter", "Count items", defs, null, 
null);
+        AiToolSpec spec = new AiToolSpec("counter", "Count items", defs, null, 
null, null);
 
         ToolSpecification result = 
AiToolSpecToLangChain4j.toToolSpecification(spec);
 
@@ -84,7 +84,7 @@ class AiToolSpecToLangChain4jTest {
         rawParams.put("price", "number");
 
         Map<String, AiToolParameterHelper.ParameterDef> defs = 
AiToolParameterHelper.parseParameterMetadata(rawParams);
-        AiToolSpec spec = new AiToolSpec("pricer", "Get price", defs, null, 
null);
+        AiToolSpec spec = new AiToolSpec("pricer", "Get price", defs, null, 
null, null);
 
         ToolSpecification result = 
AiToolSpecToLangChain4j.toToolSpecification(spec);
 
@@ -97,7 +97,7 @@ class AiToolSpecToLangChain4jTest {
         rawParams.put("active", "boolean");
 
         Map<String, AiToolParameterHelper.ParameterDef> defs = 
AiToolParameterHelper.parseParameterMetadata(rawParams);
-        AiToolSpec spec = new AiToolSpec("checker", "Check status", defs, 
null, null);
+        AiToolSpec spec = new AiToolSpec("checker", "Check status", defs, 
null, null, null);
 
         ToolSpecification result = 
AiToolSpecToLangChain4j.toToolSpecification(spec);
 
@@ -111,7 +111,7 @@ class AiToolSpecToLangChain4jTest {
         rawParams.put("color.enum", "red,green,blue");
 
         Map<String, AiToolParameterHelper.ParameterDef> defs = 
AiToolParameterHelper.parseParameterMetadata(rawParams);
-        AiToolSpec spec = new AiToolSpec("colorPicker", "Pick a color", defs, 
null, null);
+        AiToolSpec spec = new AiToolSpec("colorPicker", "Pick a color", defs, 
null, null, null);
 
         ToolSpecification result = 
AiToolSpecToLangChain4j.toToolSpecification(spec);
 
@@ -129,7 +129,7 @@ class AiToolSpecToLangChain4jTest {
         rawParams.put("userId.required", "true");
 
         Map<String, AiToolParameterHelper.ParameterDef> defs = 
AiToolParameterHelper.parseParameterMetadata(rawParams);
-        AiToolSpec spec = new AiToolSpec("userLookup", "Look up user", defs, 
null, null);
+        AiToolSpec spec = new AiToolSpec("userLookup", "Look up user", defs, 
null, null, null);
 
         ToolSpecification result = 
AiToolSpecToLangChain4j.toToolSpecification(spec);
 
@@ -147,7 +147,7 @@ class AiToolSpecToLangChain4jTest {
         rawParams.put("active", "boolean");
 
         Map<String, AiToolParameterHelper.ParameterDef> defs = 
AiToolParameterHelper.parseParameterMetadata(rawParams);
-        AiToolSpec spec = new AiToolSpec("multiTool", "Multi-param tool", 
defs, null, null);
+        AiToolSpec spec = new AiToolSpec("multiTool", "Multi-param tool", 
defs, null, null, null);
 
         ToolSpecification result = 
AiToolSpecToLangChain4j.toToolSpecification(spec);
 
@@ -189,7 +189,7 @@ class AiToolSpecToLangChain4jTest {
                 }
                 """;
 
-        AiToolSpec spec = new AiToolSpec("createOrder", "Create order", 
Map.of(), schema, null);
+        AiToolSpec spec = new AiToolSpec("createOrder", "Create order", 
Map.of(), schema, null, null);
         ToolSpecification result = 
AiToolSpecToLangChain4j.toToolSpecification(spec);
 
         assertThat(result.parameters()).isNotNull();
@@ -199,7 +199,7 @@ class AiToolSpecToLangChain4jTest {
 
     @Test
     void testEmptyParameters() {
-        AiToolSpec spec = new AiToolSpec("noParams", "Tool with no params", 
Map.of(), null, null);
+        AiToolSpec spec = new AiToolSpec("noParams", "Tool with no params", 
Map.of(), null, null, null);
 
         ToolSpecification result = 
AiToolSpecToLangChain4j.toToolSpecification(spec);
 
diff --git 
a/components/camel-ai/camel-mcp-server-api/src/main/java/org/apache/camel/component/mcp/server/McpServerBridge.java
 
b/components/camel-ai/camel-mcp-server-api/src/main/java/org/apache/camel/component/mcp/server/McpServerBridge.java
index c3021ab31007..cb94a38b520a 100644
--- 
a/components/camel-ai/camel-mcp-server-api/src/main/java/org/apache/camel/component/mcp/server/McpServerBridge.java
+++ 
b/components/camel-ai/camel-mcp-server-api/src/main/java/org/apache/camel/component/mcp/server/McpServerBridge.java
@@ -32,6 +32,7 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.Exchange;
 import org.apache.camel.StaticService;
+import org.apache.camel.component.ai.tool.AiToolAnnotations;
 import org.apache.camel.component.ai.tool.AiToolExecutor;
 import org.apache.camel.component.ai.tool.AiToolParameterHelper;
 import org.apache.camel.component.ai.tool.AiToolParameterHelper.ParameterDef;
@@ -243,6 +244,11 @@ public class McpServerBridge extends ServiceSupport 
implements CamelContextAware
             public McpToolCallHandler handler() {
                 return handler;
             }
+
+            @Override
+            public AiToolAnnotations annotations() {
+                return spec.getAnnotations();
+            }
         };
     }
 
diff --git 
a/components/camel-ai/camel-mcp-server-api/src/main/java/org/apache/camel/component/mcp/server/McpServerTool.java
 
b/components/camel-ai/camel-mcp-server-api/src/main/java/org/apache/camel/component/mcp/server/McpServerTool.java
index 06b6d00986dc..f348c6059d2a 100644
--- 
a/components/camel-ai/camel-mcp-server-api/src/main/java/org/apache/camel/component/mcp/server/McpServerTool.java
+++ 
b/components/camel-ai/camel-mcp-server-api/src/main/java/org/apache/camel/component/mcp/server/McpServerTool.java
@@ -18,6 +18,7 @@ package org.apache.camel.component.mcp.server;
 
 import java.util.Map;
 
+import org.apache.camel.component.ai.tool.AiToolAnnotations;
 import org.apache.camel.component.ai.tool.AiToolParameterHelper.ParameterDef;
 
 /**
@@ -52,4 +53,11 @@ public interface McpServerTool {
      * The handler executing the tool. Blocking, timeout-bounded and 
pre-sanitized by the bridge.
      */
     McpToolCallHandler handler();
+
+    /**
+     * Optional MCP tool annotation hints, or {@code null} when none are 
configured.
+     */
+    default AiToolAnnotations annotations() {
+        return null;
+    }
 }
diff --git 
a/components/camel-ai/camel-mcp-server-api/src/test/java/org/apache/camel/component/mcp/server/McpServerBridgeTest.java
 
b/components/camel-ai/camel-mcp-server-api/src/test/java/org/apache/camel/component/mcp/server/McpServerBridgeTest.java
index 9018fa48777a..6d9db5c79793 100644
--- 
a/components/camel-ai/camel-mcp-server-api/src/test/java/org/apache/camel/component/mcp/server/McpServerBridgeTest.java
+++ 
b/components/camel-ai/camel-mcp-server-api/src/test/java/org/apache/camel/component/mcp/server/McpServerBridgeTest.java
@@ -48,10 +48,16 @@ class McpServerBridgeTest extends CamelTestSupport {
         return new RouteBuilder() {
             public void configure() {
                 from("ai-tool:query_db?tags=crm&description=Query the customer 
database"
-                     + 
"&parameter.customerId=string&parameter.customerId.required=true")
+                     + 
"&parameter.customerId=string&parameter.customerId.required=true"
+                     + "&readOnlyHint=true&title=Query database")
                         .routeId("query-db-route")
                         .setBody(simple("customer-${header.customerId}"));
 
+                from("ai-tool:delete_order?tags=crm&description=Delete an 
order"
+                     + "&destructiveHint=true&idempotentHint=false")
+                        .routeId("delete-order-route")
+                        .setBody(constant("deleted"));
+
                 from("ai-tool:send_email?tags=notify,crm&description=Send an 
email")
                         .routeId("send-email-route")
                         .setBody(constant("sent"));
@@ -89,6 +95,19 @@ class McpServerBridgeTest extends CamelTestSupport {
         assertThat(tool.parameters()).containsKey("customerId");
     }
 
+    @Test
+    void testToolAnnotationsPassedThroughBridge() {
+        McpServerTool readTool = engine.tools().get("query_db");
+        assertThat(readTool.annotations()).isNotNull();
+        assertThat(readTool.annotations().title()).isEqualTo("Query database");
+        assertThat(readTool.annotations().readOnlyHint()).isTrue();
+
+        McpServerTool destructiveTool = engine.tools().get("delete_order");
+        assertThat(destructiveTool.annotations()).isNotNull();
+        assertThat(destructiveTool.annotations().destructiveHint()).isTrue();
+        assertThat(destructiveTool.annotations().idempotentHint()).isFalse();
+    }
+
     @Test
     void testCallToolSuccess() {
         McpToolCallResult result = 
engine.tools().get("query_db").handler().call(Map.of("customerId", "42"));
diff --git a/components/camel-ai/camel-mcp-server/src/main/docs/mcp-server.adoc 
b/components/camel-ai/camel-mcp-server/src/main/docs/mcp-server.adoc
index 17e3b436e191..ffe21a708a75 100644
--- a/components/camel-ai/camel-mcp-server/src/main/docs/mcp-server.adoc
+++ b/components/camel-ai/camel-mcp-server/src/main/docs/mcp-server.adoc
@@ -101,6 +101,14 @@ YAML::
 ----
 ====
 
+=== Tool annotation hints
+
+`ai-tool` routes can declare optional MCP `ToolAnnotations` hints
+(`title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, 
`openWorldHint`).
+The bridge passes them through to the MCP engine. See
+xref:ROOT:ai-tool-component.adoc#_mcp_tool_annotation_hints[MCP Tool 
Annotation Hints]
+for configuration examples. Hints are advisory UX metadata only — not 
authorization.
+
 On Camel Main and Camel JBang no code is needed — like Jolokia or
 Prometheus, the server starts from configuration properties alone:
 
diff --git 
a/components/camel-ai/camel-mcp-server/src/main/java/org/apache/camel/component/mcp/server/vertx/VertxMcpServerEngine.java
 
b/components/camel-ai/camel-mcp-server/src/main/java/org/apache/camel/component/mcp/server/vertx/VertxMcpServerEngine.java
index 2f9b21b2d548..a8381639dbd3 100644
--- 
a/components/camel-ai/camel-mcp-server/src/main/java/org/apache/camel/component/mcp/server/vertx/VertxMcpServerEngine.java
+++ 
b/components/camel-ai/camel-mcp-server/src/main/java/org/apache/camel/component/mcp/server/vertx/VertxMcpServerEngine.java
@@ -26,6 +26,7 @@ import io.modelcontextprotocol.server.McpServerFeatures;
 import io.modelcontextprotocol.server.McpSyncServer;
 import io.modelcontextprotocol.spec.McpSchema;
 import org.apache.camel.CamelContext;
+import org.apache.camel.component.ai.tool.AiToolAnnotations;
 import org.apache.camel.component.mcp.server.McpServerConstants;
 import org.apache.camel.component.mcp.server.McpServerEngine;
 import org.apache.camel.component.mcp.server.McpServerInfo;
@@ -140,10 +141,7 @@ public class VertxMcpServerEngine extends ServiceSupport 
implements McpServerEng
 
     @Override
     public void toolAdded(McpServerTool tool) {
-        String schema = tool.inputSchemaJson() != null ? 
tool.inputSchemaJson() : EMPTY_OBJECT_SCHEMA;
-        McpSchema.Tool mcpTool = McpSchema.Tool.builder(tool.name(), 
jsonMapper, schema)
-                .description(tool.description())
-                .build();
+        McpSchema.Tool mcpTool = buildMcpTool(tool);
         McpServerFeatures.SyncToolSpecification spec = 
McpServerFeatures.SyncToolSpecification.builder()
                 .tool(mcpTool)
                 .callHandler((exchange, request) -> {
@@ -169,6 +167,44 @@ public class VertxMcpServerEngine extends ServiceSupport 
implements McpServerEng
         }
     }
 
+    private McpSchema.Tool buildMcpTool(McpServerTool tool) {
+        String schema = tool.inputSchemaJson() != null ? 
tool.inputSchemaJson() : EMPTY_OBJECT_SCHEMA;
+        McpSchema.Tool.Builder builder = McpSchema.Tool.builder(tool.name(), 
jsonMapper, schema)
+                .description(tool.description());
+        applyAnnotations(builder, tool.annotations());
+        return builder.build();
+    }
+
+    private static void applyAnnotations(McpSchema.Tool.Builder builder, 
AiToolAnnotations annotations) {
+        if (annotations == null) {
+            return;
+        }
+        if (annotations.title() != null) {
+            builder.title(annotations.title());
+        }
+        McpSchema.ToolAnnotations.Builder hintBuilder = 
McpSchema.ToolAnnotations.builder();
+        boolean hasHints = false;
+        if (annotations.readOnlyHint() != null) {
+            hintBuilder.readOnlyHint(annotations.readOnlyHint());
+            hasHints = true;
+        }
+        if (annotations.destructiveHint() != null) {
+            hintBuilder.destructiveHint(annotations.destructiveHint());
+            hasHints = true;
+        }
+        if (annotations.idempotentHint() != null) {
+            hintBuilder.idempotentHint(annotations.idempotentHint());
+            hasHints = true;
+        }
+        if (annotations.openWorldHint() != null) {
+            hintBuilder.openWorldHint(annotations.openWorldHint());
+            hasHints = true;
+        }
+        if (hasHints) {
+            builder.annotations(hintBuilder.build());
+        }
+    }
+
     private VertxPlatformHttpRouter lookupRouter() {
         boolean mainTarget = 
VertxPlatformHttpRouter.SERVER_TYPE_SERVER.equals(targetServerType);
         Set<VertxPlatformHttpRouter> routers = 
camelContext.getRegistry().findByType(VertxPlatformHttpRouter.class);
diff --git 
a/components/camel-ai/camel-mcp-server/src/test/java/org/apache/camel/component/mcp/server/vertx/VertxMcpServerToolAnnotationsTest.java
 
b/components/camel-ai/camel-mcp-server/src/test/java/org/apache/camel/component/mcp/server/vertx/VertxMcpServerToolAnnotationsTest.java
new file mode 100644
index 000000000000..cb549b461083
--- /dev/null
+++ 
b/components/camel-ai/camel-mcp-server/src/test/java/org/apache/camel/component/mcp/server/vertx/VertxMcpServerToolAnnotationsTest.java
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.mcp.server.vertx;
+
+import java.time.Duration;
+import java.util.List;
+import java.util.Map;
+
+import io.modelcontextprotocol.client.McpClient;
+import io.modelcontextprotocol.client.McpSyncClient;
+import 
io.modelcontextprotocol.client.transport.HttpClientStreamableHttpTransport;
+import io.modelcontextprotocol.spec.McpSchema;
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.ai.tool.AiToolAnnotations;
+import org.apache.camel.component.ai.tool.AiToolConfiguration;
+import org.apache.camel.component.ai.tool.AiToolParameterHelper.ParameterDef;
+import org.apache.camel.component.mcp.server.McpServerInfo;
+import org.apache.camel.component.mcp.server.McpServerTool;
+import org.apache.camel.component.mcp.server.McpToolCallHandler;
+import org.apache.camel.component.mcp.server.McpToolCallResult;
+import org.apache.camel.component.platform.http.main.MainHttpServer;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.test.AvailablePortFinder;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class VertxMcpServerToolAnnotationsTest {
+
+    @Test
+    void testEnginePublishesTitleOnlyHint() throws Exception {
+        int port = AvailablePortFinder.getNextAvailable();
+        CamelContext camelContext = new DefaultCamelContext();
+        VertxMcpServerEngine engine = new VertxMcpServerEngine();
+        McpSyncClient client = null;
+        try {
+            MainHttpServer main = new MainHttpServer();
+            main.setCamelContext(camelContext);
+            main.setHost("0.0.0.0");
+            main.setPort(port);
+            camelContext.addService(main);
+            camelContext.start();
+
+            engine.setCamelContext(camelContext);
+            engine.initialize(new McpServerInfo("tool-hints", "1.0", "/mcp"));
+            engine.start();
+
+            AiToolConfiguration configuration = new AiToolConfiguration();
+            configuration.setTitle("Lookup customer");
+            AiToolAnnotations annotations = 
AiToolAnnotations.fromConfiguration(configuration);
+
+            engine.toolAdded(tool("lookup", "Lookup a customer", annotations,
+                    arguments -> new McpToolCallResult("ok", false)));
+
+            client = 
McpClient.sync(HttpClientStreamableHttpTransport.builder("http://localhost:"; + 
port).build())
+                    .requestTimeout(Duration.ofSeconds(10))
+                    .initializationTimeout(Duration.ofSeconds(10))
+                    .build();
+            client.initialize();
+
+            List<McpSchema.Tool> tools = client.listTools().tools();
+            McpSchema.Tool lookup = tools.stream().filter(t -> 
"lookup".equals(t.name())).findFirst().orElseThrow();
+
+            assertThat(lookup.title()).isEqualTo("Lookup customer");
+            assertThat(lookup.annotations()).isNull();
+        } finally {
+            if (client != null) {
+                client.closeGracefully();
+            }
+            engine.stop();
+            camelContext.stop();
+        }
+    }
+
+    @Test
+    void testEnginePublishesPartialBooleanHints() throws Exception {
+        int port = AvailablePortFinder.getNextAvailable();
+        CamelContext camelContext = new DefaultCamelContext();
+        VertxMcpServerEngine engine = new VertxMcpServerEngine();
+        McpSyncClient client = null;
+        try {
+            MainHttpServer main = new MainHttpServer();
+            main.setCamelContext(camelContext);
+            main.setHost("0.0.0.0");
+            main.setPort(port);
+            camelContext.addService(main);
+            camelContext.start();
+
+            engine.setCamelContext(camelContext);
+            engine.initialize(new McpServerInfo("tool-hints", "1.0", "/mcp"));
+            engine.start();
+
+            AiToolConfiguration configuration = new AiToolConfiguration();
+            configuration.setDestructiveHint(true);
+            AiToolAnnotations annotations = 
AiToolAnnotations.fromConfiguration(configuration);
+
+            engine.toolAdded(tool("delete", "Delete resource", annotations,
+                    arguments -> new McpToolCallResult("ok", false)));
+
+            client = 
McpClient.sync(HttpClientStreamableHttpTransport.builder("http://localhost:"; + 
port).build())
+                    .requestTimeout(Duration.ofSeconds(10))
+                    .initializationTimeout(Duration.ofSeconds(10))
+                    .build();
+            client.initialize();
+
+            List<McpSchema.Tool> tools = client.listTools().tools();
+            McpSchema.Tool delete = tools.stream().filter(t -> 
"delete".equals(t.name())).findFirst().orElseThrow();
+
+            assertThat(delete.title()).isNull();
+            assertThat(delete.annotations()).isNotNull();
+            assertThat(delete.annotations().destructiveHint()).isTrue();
+            assertThat(delete.annotations().readOnlyHint()).isNull();
+        } finally {
+            if (client != null) {
+                client.closeGracefully();
+            }
+            engine.stop();
+            camelContext.stop();
+        }
+    }
+
+    @Test
+    void testEnginePublishesToolAnnotationHints() throws Exception {
+        int port = AvailablePortFinder.getNextAvailable();
+        CamelContext camelContext = new DefaultCamelContext();
+        VertxMcpServerEngine engine = new VertxMcpServerEngine();
+        McpSyncClient client = null;
+        try {
+            MainHttpServer main = new MainHttpServer();
+            main.setCamelContext(camelContext);
+            main.setHost("0.0.0.0");
+            main.setPort(port);
+            camelContext.addService(main);
+            camelContext.start();
+
+            engine.setCamelContext(camelContext);
+            engine.initialize(new McpServerInfo("tool-hints", "1.0", "/mcp"));
+            engine.start();
+
+            AiToolConfiguration configuration = new AiToolConfiguration();
+            configuration.setTitle("Read only tool");
+            configuration.setReadOnlyHint(true);
+            configuration.setDestructiveHint(false);
+            configuration.setOpenWorldHint(false);
+            AiToolAnnotations annotations = 
AiToolAnnotations.fromConfiguration(configuration);
+
+            engine.toolAdded(tool("read_only", "Read-only lookup", annotations,
+                    arguments -> new McpToolCallResult("ok", false)));
+
+            client = 
McpClient.sync(HttpClientStreamableHttpTransport.builder("http://localhost:"; + 
port).build())
+                    .requestTimeout(Duration.ofSeconds(10))
+                    .initializationTimeout(Duration.ofSeconds(10))
+                    .build();
+            client.initialize();
+
+            List<McpSchema.Tool> tools = client.listTools().tools();
+            McpSchema.Tool readOnly = tools.stream().filter(t -> 
"read_only".equals(t.name())).findFirst().orElseThrow();
+
+            assertThat(readOnly.title()).isEqualTo("Read only tool");
+            assertThat(readOnly.annotations()).isNotNull();
+            assertThat(readOnly.annotations().readOnlyHint()).isTrue();
+            assertThat(readOnly.annotations().destructiveHint()).isFalse();
+            assertThat(readOnly.annotations().openWorldHint()).isFalse();
+        } finally {
+            if (client != null) {
+                client.closeGracefully();
+            }
+            engine.stop();
+            camelContext.stop();
+        }
+    }
+
+    private static McpServerTool tool(
+            String name, String description, AiToolAnnotations annotations, 
McpToolCallHandler handler) {
+        return new McpServerTool() {
+            @Override
+            public String name() {
+                return name;
+            }
+
+            @Override
+            public String description() {
+                return description;
+            }
+
+            @Override
+            public String inputSchemaJson() {
+                return null;
+            }
+
+            @Override
+            public Map<String, ParameterDef> parameters() {
+                return Map.of();
+            }
+
+            @Override
+            public McpToolCallHandler handler() {
+                return handler;
+            }
+
+            @Override
+            public AiToolAnnotations annotations() {
+                return annotations;
+            }
+        };
+    }
+}
diff --git 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AiToolComponentBuilderFactory.java
 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AiToolComponentBuilderFactory.java
index b91bac833c9d..21ab68bca404 100644
--- 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AiToolComponentBuilderFactory.java
+++ 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/AiToolComponentBuilderFactory.java
@@ -134,6 +134,61 @@ public interface AiToolComponentBuilderFactory {
             return this;
         }
     
+        
+        /**
+         * MCP hint that the tool may perform destructive or irreversible
+         * updates. Advisory for MCP clients; not enforced by Camel.
+         * 
+         * The option is a: &lt;code&gt;java.lang.Boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param destructiveHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolComponentBuilder destructiveHint(java.lang.Boolean 
destructiveHint) {
+            doSetProperty("destructiveHint", destructiveHint);
+            return this;
+        }
+    
+        
+        /**
+         * MCP hint that repeating the tool call with the same arguments has no
+         * additional effect. Advisory for MCP clients; not enforced by Camel.
+         * 
+         * The option is a: &lt;code&gt;java.lang.Boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param idempotentHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolComponentBuilder idempotentHint(java.lang.Boolean 
idempotentHint) {
+            doSetProperty("idempotentHint", idempotentHint);
+            return this;
+        }
+    
+        
+        /**
+         * MCP hint that the tool interacts with external systems outside the
+         * application's control. Advisory for MCP clients; not enforced by
+         * Camel.
+         * 
+         * The option is a: &lt;code&gt;java.lang.Boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param openWorldHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolComponentBuilder openWorldHint(java.lang.Boolean 
openWorldHint) {
+            doSetProperty("openWorldHint", openWorldHint);
+            return this;
+        }
+    
         /**
          * Tool input parameters. Format: parameter.NAME=TYPE,
          * parameter.NAME.description=TEXT, parameter.NAME.required=true or
@@ -154,6 +209,24 @@ public interface AiToolComponentBuilderFactory {
             return this;
         }
     
+        
+        /**
+         * MCP hint that the tool only reads data and does not modify state.
+         * Advisory for MCP clients; not enforced by Camel.
+         * 
+         * The option is a: &lt;code&gt;java.lang.Boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param readOnlyHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolComponentBuilder readOnlyHint(java.lang.Boolean 
readOnlyHint) {
+            doSetProperty("readOnlyHint", readOnlyHint);
+            return this;
+        }
+    
         /**
          * Comma-separated list of tags used to group tools. Producers filter
          * the registry by these tags to select which tools to expose to the
@@ -172,6 +245,22 @@ public interface AiToolComponentBuilderFactory {
             return this;
         }
     
+        /**
+         * Optional display title for MCP tool listings. Advisory hint for MCP
+         * clients only.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: consumer
+         * 
+         * @param title the value to set
+         * @return the dsl builder
+         */
+        default AiToolComponentBuilder title(java.lang.String title) {
+            doSetProperty("title", title);
+            return this;
+        }
+    
         
         /**
          * Whether autowiring is enabled. This is used for automatic autowiring
@@ -218,8 +307,13 @@ public interface AiToolComponentBuilderFactory {
             case "bridgeErrorHandler": ((AiToolComponent) 
component).setBridgeErrorHandler((boolean) value); return true;
             case "configuration": ((AiToolComponent) 
component).setConfiguration((org.apache.camel.component.ai.tool.AiToolConfiguration)
 value); return true;
             case "description": getOrCreateConfiguration((AiToolComponent) 
component).setDescription((java.lang.String) value); return true;
+            case "destructiveHint": getOrCreateConfiguration((AiToolComponent) 
component).setDestructiveHint((java.lang.Boolean) value); return true;
+            case "idempotentHint": getOrCreateConfiguration((AiToolComponent) 
component).setIdempotentHint((java.lang.Boolean) value); return true;
+            case "openWorldHint": getOrCreateConfiguration((AiToolComponent) 
component).setOpenWorldHint((java.lang.Boolean) value); return true;
             case "parameters": getOrCreateConfiguration((AiToolComponent) 
component).setParameters((java.util.Map) value); return true;
+            case "readOnlyHint": getOrCreateConfiguration((AiToolComponent) 
component).setReadOnlyHint((java.lang.Boolean) value); return true;
             case "tags": getOrCreateConfiguration((AiToolComponent) 
component).setTags((java.lang.String) value); return true;
+            case "title": getOrCreateConfiguration((AiToolComponent) 
component).setTitle((java.lang.String) value); return true;
             case "autowiredEnabled": ((AiToolComponent) 
component).setAutowiredEnabled((boolean) value); return true;
             default: return false;
             }
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AiToolEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AiToolEndpointBuilderFactory.java
index abf21d5ff39e..74e7abf42bfd 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AiToolEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AiToolEndpointBuilderFactory.java
@@ -81,6 +81,107 @@ public interface AiToolEndpointBuilderFactory {
             doSetProperty("description", description);
             return this;
         }
+        /**
+         * MCP hint that the tool may perform destructive or irreversible
+         * updates. Advisory for MCP clients; not enforced by Camel.
+         * 
+         * The option is a: <code>java.lang.Boolean</code> type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param destructiveHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolEndpointBuilder destructiveHint(Boolean destructiveHint) 
{
+            doSetProperty("destructiveHint", destructiveHint);
+            return this;
+        }
+        /**
+         * MCP hint that the tool may perform destructive or irreversible
+         * updates. Advisory for MCP clients; not enforced by Camel.
+         * 
+         * The option will be converted to a <code>java.lang.Boolean</code>
+         * type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param destructiveHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolEndpointBuilder destructiveHint(String destructiveHint) {
+            doSetProperty("destructiveHint", destructiveHint);
+            return this;
+        }
+        /**
+         * MCP hint that repeating the tool call with the same arguments has no
+         * additional effect. Advisory for MCP clients; not enforced by Camel.
+         * 
+         * The option is a: <code>java.lang.Boolean</code> type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param idempotentHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolEndpointBuilder idempotentHint(Boolean idempotentHint) {
+            doSetProperty("idempotentHint", idempotentHint);
+            return this;
+        }
+        /**
+         * MCP hint that repeating the tool call with the same arguments has no
+         * additional effect. Advisory for MCP clients; not enforced by Camel.
+         * 
+         * The option will be converted to a <code>java.lang.Boolean</code>
+         * type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param idempotentHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolEndpointBuilder idempotentHint(String idempotentHint) {
+            doSetProperty("idempotentHint", idempotentHint);
+            return this;
+        }
+        /**
+         * MCP hint that the tool interacts with external systems outside the
+         * application's control. Advisory for MCP clients; not enforced by
+         * Camel.
+         * 
+         * The option is a: <code>java.lang.Boolean</code> type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param openWorldHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolEndpointBuilder openWorldHint(Boolean openWorldHint) {
+            doSetProperty("openWorldHint", openWorldHint);
+            return this;
+        }
+        /**
+         * MCP hint that the tool interacts with external systems outside the
+         * application's control. Advisory for MCP clients; not enforced by
+         * Camel.
+         * 
+         * The option will be converted to a <code>java.lang.Boolean</code>
+         * type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param openWorldHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolEndpointBuilder openWorldHint(String openWorldHint) {
+            doSetProperty("openWorldHint", openWorldHint);
+            return this;
+        }
         /**
          * Tool input parameters. Format: parameter.NAME=TYPE,
          * parameter.NAME.description=TEXT, parameter.NAME.required=true or
@@ -126,6 +227,39 @@ public interface AiToolEndpointBuilderFactory {
             doSetMultiValueProperties("parameters", "parameter.", values);
             return this;
         }
+        /**
+         * MCP hint that the tool only reads data and does not modify state.
+         * Advisory for MCP clients; not enforced by Camel.
+         * 
+         * The option is a: <code>java.lang.Boolean</code> type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param readOnlyHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolEndpointBuilder readOnlyHint(Boolean readOnlyHint) {
+            doSetProperty("readOnlyHint", readOnlyHint);
+            return this;
+        }
+        /**
+         * MCP hint that the tool only reads data and does not modify state.
+         * Advisory for MCP clients; not enforced by Camel.
+         * 
+         * The option will be converted to a <code>java.lang.Boolean</code>
+         * type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param readOnlyHint the value to set
+         * @return the dsl builder
+         */
+        default AiToolEndpointBuilder readOnlyHint(String readOnlyHint) {
+            doSetProperty("readOnlyHint", readOnlyHint);
+            return this;
+        }
         /**
          * Comma-separated list of tags used to group tools. Producers filter
          * the registry by these tags to select which tools to expose to the
@@ -143,6 +277,21 @@ public interface AiToolEndpointBuilderFactory {
             doSetProperty("tags", tags);
             return this;
         }
+        /**
+         * Optional display title for MCP tool listings. Advisory hint for MCP
+         * clients only.
+         * 
+         * The option is a: <code>java.lang.String</code> type.
+         * 
+         * Group: consumer
+         * 
+         * @param title the value to set
+         * @return the dsl builder
+         */
+        default AiToolEndpointBuilder title(String title) {
+            doSetProperty("title", title);
+            return this;
+        }
     }
 
     /**

Reply via email to