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 ae1a9db5f44e CAMEL-23853: Embed MCP server on camel run/dev and Camel 
Main
ae1a9db5f44e is described below

commit ae1a9db5f44e5eb7884242ee2ed1ecaaa190a73c
Author: Omar Atie <[email protected]>
AuthorDate: Thu Aug 6 03:08:42 2026 -0700

    CAMEL-23853: Embed MCP server on camel run/dev and Camel Main
    
    Add embedded MCP (Model Context Protocol) server support to Camel Main
    and JBang CLI. When enabled via --mcp flag or camel.jbang.mcp property,
    the management HTTP server exposes JBang ToolRegistry tools as MCP tools
    using VertxMcpServerEngine on a /mcp endpoint bound to 127.0.0.1.
    
    The MCP server is pluggable: camel-mcp-server is downloaded on demand
    (not a compile dependency) and JBang tool classes are resolved
    reflectively via ClassResolver. Configuration uses
    camel.management.mcpEnabled/mcpPath properties with insecure:dev
    security annotation.
    
    Closes #25203
    
    Co-authored-by: Cursor Agent <[email protected]>
---
 .../org/apache/camel/catalog/docs/main.adoc        |   4 +-
 .../jbang/camel-jbang-configuration-metadata.json  |   1 +
 .../main/camel-main-configuration-metadata.json    |   2 +
 components/camel-ai/camel-mcp-server/pom.xml       |   4 +-
 .../mcp/server/jbang/JbangDevMcpMainListener.java  |  42 ++++
 .../mcp/server/jbang/JbangDevMcpServer.java        | 253 +++++++++++++++++++++
 ...entServerConfigurationPropertiesConfigurer.java |  14 ++
 .../camel-main-configuration-metadata.json         |   2 +
 core/camel-main/src/main/docs/main.adoc            |   4 +-
 ...ttpManagementServerConfigurationProperties.java |  39 ++++
 .../ROOT/pages/camel-jbang-configuration.adoc      |   3 +-
 .../pages/jbang-commands/camel-jbang-debug.adoc    |   1 +
 .../ROOT/pages/jbang-commands/camel-jbang-dev.adoc |   1 +
 .../ROOT/pages/jbang-commands/camel-jbang-run.adoc |   1 +
 dsl/camel-jbang/camel-jbang-core/pom.xml           |  29 +++
 .../META-INF/camel-jbang-commands-metadata.json    |   6 +-
 .../camel-jbang-configuration-metadata.json        |   1 +
 .../apache/camel/dsl/jbang/core/commands/Run.java  |  18 ++
 .../dsl/jbang/core/common/CamelJBangConstants.java |   4 +
 .../dsl/jbang/core/commands/RunMcpOptionTest.java  |  41 ++++
 .../core/commands/mcp/JbangDevMcpServerTest.java   |  97 ++++++++
 .../java/org/apache/camel/main/KameletMain.java    |  15 ++
 .../camel-main-known-dependencies.properties       |   1 +
 23 files changed, 575 insertions(+), 8 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/main.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/main.adoc
index ffa14c8dfd9d..e3d33c3295b0 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/main.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/main.adoc
@@ -230,7 +230,7 @@ The camel.server supports 26 options, which are listed 
below.
 
 
 === Camel Embedded HTTP management Server (only for standalone; not Spring 
Boot or Quarkus) configurations
-The camel.management supports 29 options, which are listed below.
+The camel.management supports 31 options, which are listed below.
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
@@ -255,6 +255,8 @@ The camel.management supports 29 options, which are listed 
below.
 | *camel.management.jwtKeystorePassword* | Password from the keystore used for 
JWT tokens validation. |  | String
 | *camel.management.jwtKeystorePath* | Path to the keystore file used for JWT 
tokens validation. |  | String
 | *camel.management.jwtKeystoreType* | Type of the keystore used for JWT 
tokens validation (jks, pkcs12, etc.). |  | String
+| *camel.management.mcpEnabled* | Whether to expose dev/diagnostics MCP tools 
on this management server (requires camel-mcp-server on the classpath). 
Currently honored only when Camel JBang registers JbangDevMcpMainListener (for 
example camel run --mcp). For route-based MCP on the main HTTP server in plain 
camel-main, configure camel.server.mcpEnabled instead. Not intended for 
production use. | false | boolean
+| *camel.management.mcpPath* | HTTP path where the management MCP endpoint is 
served. | /mcp | String
 | *camel.management.metricsEnabled* | Whether to enable metrics. If enabled 
then you can access metrics on context-path: /observe/metrics | false | boolean
 | *camel.management.openapiUiEnabled* | Whether to enable Swagger UI for REST 
DSL OpenAPI documents. If enabled then you can browse the API at context-path: 
/q/openapi. The OpenAPI document is expected at openapiUiSpecPath (by default 
/q/openapi.json from REST DSL apiContextPath ). | false | boolean
 | *camel.management.openapiUiSpecPath* | Path or URL of the OpenAPI document 
loaded by Swagger UI at /q/openapi. | /q/openapi.json | String
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json
index f4b422e1b40c..bd1bdf642d53 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json
@@ -35,6 +35,7 @@
     { "name": "camel.jbang.maven-settings", "required": false, "description": 
"Optional location of Maven settings.xml file to configure servers, 
repositories, mirrors, and proxies. If set to false, not even the default 
\/.m2\/settings.xml will be used.", "label": "maven", "type": "string", 
"javaType": "String", "secret": false },
     { "name": "camel.jbang.maven-settings-security", "required": false, 
"description": "Optional location of Maven settings-security.xml file to 
decrypt Maven Settings (settings.xml) file", "label": "maven", "type": 
"string", "javaType": "String", "secret": false },
     { "name": "camel.jbang.mavenWrapper", "required": false, "description": 
"Include Maven Wrapper files in the exported project", "type": "boolean", 
"javaType": "boolean", "defaultValue": true, "secret": false },
+    { "name": "camel.jbang.mcp", "required": false, "description": "Embed 
dev\/diagnostics MCP tools on the local HTTP management server (\/mcp by 
default)", "type": "boolean", "javaType": "boolean", "defaultValue": false, 
"secret": false, "security": "insecure:dev" },
     { "name": "camel.jbang.metrics", "required": false, "description": 
"Metrics (Micrometer and Prometheus) at \/observe\/metrics on local HTTP server 
(port 8080 by default) when running standalone Camel", "type": "boolean", 
"javaType": "boolean", "defaultValue": false, "secret": false, "deprecated": 
true },
     { "name": "camel.jbang.openApi", "required": false, "description": "File 
name of open-api spec file (JSON or YAML) to generate routes from the 
swagger\/openapi API spec file.", "type": "string", "javaType": "String", 
"secret": false },
     { "name": "camel.jbang.openapiUi", "required": false, "description": 
"Swagger UI for REST OpenAPI at \/q\/openapi on local HTTP server (port 8080 by 
default)", "type": "boolean", "javaType": "boolean", "defaultValue": false, 
"secret": false, "security": "insecure:dev" },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
index 5630025faa29..3d8ec1317988 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
@@ -309,6 +309,8 @@
     { "name": "camel.management.jwtKeystorePassword", "required": false, 
"description": "Password from the keystore used for JWT tokens validation.", 
"sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"string", "javaType": "java.lang.String", "secret": true, "security": "secret" 
},
     { "name": "camel.management.jwtKeystorePath", "required": false, 
"description": "Path to the keystore file used for JWT tokens validation.", 
"sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"string", "javaType": "java.lang.String", "secret": false },
     { "name": "camel.management.jwtKeystoreType", "required": false, 
"description": "Type of the keystore used for JWT tokens validation (jks, 
pkcs12, etc.).", "sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"string", "javaType": "java.lang.String", "secret": false },
+    { "name": "camel.management.mcpEnabled", "required": false, "description": 
"Whether to expose dev\/diagnostics MCP tools on this management server 
(requires camel-mcp-server on the classpath). Currently honored only when Camel 
JBang registers JbangDevMcpMainListener (for example camel run --mcp). For 
route-based MCP on the main HTTP server in plain camel-main, configure 
camel.server.mcpEnabled instead. Not intended for production use.", 
"sourceType": "org.apache.camel.main.HttpManage [...]
+    { "name": "camel.management.mcpPath", "required": false, "description": 
"HTTP path where the management MCP endpoint is served.", "sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"string", "javaType": "java.lang.String", "defaultValue": "\/mcp", "secret": 
false },
     { "name": "camel.management.metricsEnabled", "required": false, 
"description": "Whether to enable metrics. If enabled then you can access 
metrics on context-path: \/observe\/metrics", "sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"boolean", "javaType": "boolean", "defaultValue": false, "secret": false },
     { "name": "camel.management.openapiUiEnabled", "required": false, 
"description": "Whether to enable Swagger UI for REST DSL OpenAPI documents. If 
enabled then you can browse the API at context-path: \/q\/openapi. The OpenAPI 
document is expected at openapiUiSpecPath (by default \/q\/openapi.json from 
REST DSL apiContextPath ).", "sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"boolean", "javaType": "boolean", "defaultValue": false, "secret": [...]
     { "name": "camel.management.openapiUiSpecPath", "required": false, 
"description": "Path or URL of the OpenAPI document loaded by Swagger UI at 
\/q\/openapi.", "sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"string", "javaType": "java.lang.String", "defaultValue": "\/q\/openapi.json", 
"secret": false },
diff --git a/components/camel-ai/camel-mcp-server/pom.xml 
b/components/camel-ai/camel-mcp-server/pom.xml
index 2adf333c000d..feb84234815f 100644
--- a/components/camel-ai/camel-mcp-server/pom.xml
+++ b/components/camel-ai/camel-mcp-server/pom.xml
@@ -79,12 +79,12 @@
         <!-- integration tests -->
         <dependency>
             <groupId>org.apache.camel</groupId>
-            <artifactId>camel-openai</artifactId>
+            <artifactId>camel-platform-http-main</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
-            <artifactId>camel-platform-http-main</artifactId>
+            <artifactId>camel-openai</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git 
a/components/camel-ai/camel-mcp-server/src/main/java/org/apache/camel/component/mcp/server/jbang/JbangDevMcpMainListener.java
 
b/components/camel-ai/camel-mcp-server/src/main/java/org/apache/camel/component/mcp/server/jbang/JbangDevMcpMainListener.java
new file mode 100644
index 000000000000..ad701656d06e
--- /dev/null
+++ 
b/components/camel-ai/camel-mcp-server/src/main/java/org/apache/camel/component/mcp/server/jbang/JbangDevMcpMainListener.java
@@ -0,0 +1,42 @@
+/*
+ * 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.jbang;
+
+import org.apache.camel.main.BaseMainSupport;
+import org.apache.camel.main.MainListenerSupport;
+
+/**
+ * Starts {@link JbangDevMcpServer} on the management HTTP server when {@code 
camel.management.mcpEnabled} is set.
+ * Loaded at runtime when {@code camel-mcp-server} is on the classpath (e.g. 
{@code camel run --mcp}).
+ */
+public class JbangDevMcpMainListener extends MainListenerSupport {
+
+    @Override
+    public void afterConfigure(BaseMainSupport main) {
+        if (!main.configure().httpManagementServer().isMcpEnabled()) {
+            return;
+        }
+        JbangDevMcpServer server = new JbangDevMcpServer();
+        server.setCamelContext(main.getCamelContext());
+        server.setPath(main.configure().httpManagementServer().getMcpPath());
+        try {
+            main.getCamelContext().addService(server, true, true);
+        } catch (Exception e) {
+            throw new IllegalStateException("Unable to register JBang dev MCP 
server", e);
+        }
+    }
+}
diff --git 
a/components/camel-ai/camel-mcp-server/src/main/java/org/apache/camel/component/mcp/server/jbang/JbangDevMcpServer.java
 
b/components/camel-ai/camel-mcp-server/src/main/java/org/apache/camel/component/mcp/server/jbang/JbangDevMcpServer.java
new file mode 100644
index 000000000000..c67836463ccc
--- /dev/null
+++ 
b/components/camel-ai/camel-mcp-server/src/main/java/org/apache/camel/component/mcp/server/jbang/JbangDevMcpServer.java
@@ -0,0 +1,253 @@
+/*
+ * 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.jbang;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.component.ai.tool.AiToolParameterHelper;
+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.mcp.server.vertx.VertxMcpServerEngine;
+import org.apache.camel.component.platform.http.vertx.VertxPlatformHttpRouter;
+import org.apache.camel.support.service.ServiceSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Dev/diagnostics MCP server on the management HTTP port, exposing shared 
JBang {@code ToolRegistry} tools through
+ * {@link VertxMcpServerEngine}. JBang classes are resolved reflectively so 
{@code camel-jbang-core} is not required at
+ * compile time.
+ */
+public class JbangDevMcpServer extends ServiceSupport implements 
CamelContextAware {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(JbangDevMcpServer.class);
+    private static final String SERVER_NAME = "camel-jbang-dev-tools";
+    private static final String TOOL_REGISTRY = 
"org.apache.camel.dsl.jbang.core.commands.ai.ToolRegistry";
+    private static final String TOOL_CONTEXT = 
"org.apache.camel.dsl.jbang.core.commands.ai.ToolContext";
+
+    private CamelContext camelContext;
+    private String path = "/mcp";
+    private VertxMcpServerEngine engine;
+    private Object toolContext;
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        toolContext = createToolContext();
+
+        engine = new VertxMcpServerEngine();
+        engine.setCamelContext(camelContext);
+        engine.setTargetServerType(resolveTargetServerType());
+        String version = camelContext.getVersion();
+        if (version == null || version.isBlank()) {
+            version = "unknown";
+        }
+        engine.initialize(new McpServerInfo(SERVER_NAME, version, path));
+        engine.start();
+
+        for (Object descriptor : allToolDescriptors()) {
+            engine.toolAdded(toMcpTool(descriptor));
+        }
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        if (engine != null) {
+            engine.stop();
+            engine = null;
+        }
+        toolContext = null;
+    }
+
+    private McpServerTool toMcpTool(Object descriptor) {
+        String toolName = invokeString(descriptor, "name");
+        List<?> params = invokeList(descriptor, "params");
+        Map<String, ParameterDef> parameterDefs = buildParameterDefs(params);
+        McpToolCallHandler handler = arguments -> {
+            try {
+                Object result = executeTool(toolName, 
stringArguments(arguments));
+                return new McpToolCallResult(result != null ? 
result.toString() : "", false);
+            } catch (Exception e) {
+                Throwable failure = e;
+                if (e instanceof InvocationTargetException ite && 
ite.getCause() != null) {
+                    failure = ite.getCause();
+                }
+                String message = failure.getMessage();
+                if (message == null || message.isBlank()) {
+                    message = failure.getClass().getSimpleName();
+                }
+                return new McpToolCallResult(message, true);
+            }
+        };
+        return new McpServerTool() {
+            @Override
+            public String name() {
+                return toolName;
+            }
+
+            @Override
+            public String description() {
+                return invokeString(descriptor, "description");
+            }
+
+            @Override
+            public String inputSchemaJson() {
+                return parameterDefs.isEmpty() ? null : 
AiToolParameterHelper.buildJsonSchemaFromDefs(parameterDefs);
+            }
+
+            @Override
+            public Map<String, ParameterDef> parameters() {
+                return parameterDefs;
+            }
+
+            @Override
+            public McpToolCallHandler handler() {
+                return handler;
+            }
+        };
+    }
+
+    private Object createToolContext() throws ReflectiveOperationException {
+        Class<?> contextClass = mandatoryClass(TOOL_CONTEXT);
+        Object context = contextClass.getDeclaredConstructor().newInstance();
+        Method selectProcess = contextClass.getMethod("selectProcess", 
long.class);
+        selectProcess.invoke(context, ProcessHandle.current().pid());
+        return context;
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<Object> allToolDescriptors() throws 
ReflectiveOperationException {
+        Class<?> registry = mandatoryClass(TOOL_REGISTRY);
+        Method allTools = registry.getMethod("allTools");
+        return (List<Object>) allTools.invoke(null);
+    }
+
+    private Object executeTool(String name, Map<String, String> args) throws 
ReflectiveOperationException {
+        Class<?> registry = mandatoryClass(TOOL_REGISTRY);
+        Class<?> contextClass = mandatoryClass(TOOL_CONTEXT);
+        Method execute = registry.getMethod("execute", String.class, 
contextClass, Map.class);
+        return execute.invoke(null, name, toolContext, args);
+    }
+
+    private Class<?> mandatoryClass(String name) throws ClassNotFoundException 
{
+        return camelContext.getClassResolver().resolveMandatoryClass(name);
+    }
+
+    private static String invokeString(Object target, String method) {
+        try {
+            Object value = target.getClass().getMethod(method).invoke(target);
+            return value != null ? value.toString() : null;
+        } catch (ReflectiveOperationException e) {
+            return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static List<?> invokeList(Object target, String method) {
+        try {
+            return (List<?>) 
target.getClass().getMethod(method).invoke(target);
+        } catch (ReflectiveOperationException e) {
+            return List.of();
+        }
+    }
+
+    private static Map<String, ParameterDef> buildParameterDefs(List<?> 
params) {
+        if (params == null || params.isEmpty()) {
+            return Map.of();
+        }
+        Map<String, String> flat = new LinkedHashMap<>();
+        for (Object param : params) {
+            String name = invokeString(param, "name");
+            if (name == null || name.isBlank()) {
+                continue;
+            }
+            String type = invokeString(param, "type");
+            if (type != null && !type.isBlank()) {
+                flat.put(name, type);
+            }
+            String description = invokeString(param, "description");
+            if (description != null && !description.isBlank()) {
+                flat.put(name + ".description", description);
+            }
+            if (Boolean.TRUE.equals(invokeBoolean(param, "required"))) {
+                flat.put(name + ".required", "true");
+            }
+        }
+        return AiToolParameterHelper.parseParameterMetadata(flat);
+    }
+
+    private static Boolean invokeBoolean(Object target, String method) {
+        try {
+            return (Boolean) 
target.getClass().getMethod(method).invoke(target);
+        } catch (ReflectiveOperationException e) {
+            return false;
+        }
+    }
+
+    private static Map<String, String> stringArguments(Map<String, Object> 
args) {
+        Map<String, String> out = new LinkedHashMap<>();
+        if (args == null) {
+            return out;
+        }
+        for (Map.Entry<String, Object> entry : args.entrySet()) {
+            if (entry.getValue() != null) {
+                out.put(entry.getKey(), entry.getValue().toString());
+            }
+        }
+        return out;
+    }
+
+    private String resolveTargetServerType() {
+        Set<VertxPlatformHttpRouter> routers = 
camelContext.getRegistry().findByType(VertxPlatformHttpRouter.class);
+        boolean hasManagementRouter = routers.stream()
+                .anyMatch(r -> 
VertxPlatformHttpRouter.SERVER_TYPE_MANAGEMENT.equals(r.getServerType()));
+        if (hasManagementRouter) {
+            return VertxPlatformHttpRouter.SERVER_TYPE_MANAGEMENT;
+        }
+        LOG.warn("No management HTTP router found; attaching JBang dev MCP 
endpoint to the main HTTP server. "
+                 + "When management shares the main server port, MCP is served 
on the main server bind address "
+                 + "(for example 0.0.0.0) rather than 127.0.0.1.");
+        return VertxPlatformHttpRouter.SERVER_TYPE_SERVER;
+    }
+}
diff --git 
a/core/camel-main/src/generated/java/org/apache/camel/main/HttpManagementServerConfigurationPropertiesConfigurer.java
 
b/core/camel-main/src/generated/java/org/apache/camel/main/HttpManagementServerConfigurationPropertiesConfigurer.java
index 22c4403b0c29..e4e88879fb45 100644
--- 
a/core/camel-main/src/generated/java/org/apache/camel/main/HttpManagementServerConfigurationPropertiesConfigurer.java
+++ 
b/core/camel-main/src/generated/java/org/apache/camel/main/HttpManagementServerConfigurationPropertiesConfigurer.java
@@ -42,6 +42,8 @@ public class 
HttpManagementServerConfigurationPropertiesConfigurer extends org.a
         map.put("JwtKeystorePassword", java.lang.String.class);
         map.put("JwtKeystorePath", java.lang.String.class);
         map.put("JwtKeystoreType", java.lang.String.class);
+        map.put("McpEnabled", boolean.class);
+        map.put("McpPath", java.lang.String.class);
         map.put("MetricsEnabled", boolean.class);
         map.put("OpenapiUiEnabled", boolean.class);
         map.put("OpenapiUiSpecPath", java.lang.String.class);
@@ -96,6 +98,10 @@ public class 
HttpManagementServerConfigurationPropertiesConfigurer extends org.a
         case "jwtKeystorePath": 
target.setJwtKeystorePath(property(camelContext, java.lang.String.class, 
value)); return true;
         case "jwtkeystoretype":
         case "jwtKeystoreType": 
target.setJwtKeystoreType(property(camelContext, java.lang.String.class, 
value)); return true;
+        case "mcpenabled":
+        case "mcpEnabled": target.setMcpEnabled(property(camelContext, 
boolean.class, value)); return true;
+        case "mcppath":
+        case "mcpPath": target.setMcpPath(property(camelContext, 
java.lang.String.class, value)); return true;
         case "metricsenabled":
         case "metricsEnabled": target.setMetricsEnabled(property(camelContext, 
boolean.class, value)); return true;
         case "openapiuienabled":
@@ -162,6 +168,10 @@ public class 
HttpManagementServerConfigurationPropertiesConfigurer extends org.a
         case "jwtKeystorePath": return java.lang.String.class;
         case "jwtkeystoretype":
         case "jwtKeystoreType": return java.lang.String.class;
+        case "mcpenabled":
+        case "mcpEnabled": return boolean.class;
+        case "mcppath":
+        case "mcpPath": return java.lang.String.class;
         case "metricsenabled":
         case "metricsEnabled": return boolean.class;
         case "openapiuienabled":
@@ -224,6 +234,10 @@ public class 
HttpManagementServerConfigurationPropertiesConfigurer extends org.a
         case "jwtKeystorePath": return target.getJwtKeystorePath();
         case "jwtkeystoretype":
         case "jwtKeystoreType": return target.getJwtKeystoreType();
+        case "mcpenabled":
+        case "mcpEnabled": return target.isMcpEnabled();
+        case "mcppath":
+        case "mcpPath": return target.getMcpPath();
         case "metricsenabled":
         case "metricsEnabled": return target.isMetricsEnabled();
         case "openapiuienabled":
diff --git 
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
 
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index 5630025faa29..3d8ec1317988 100644
--- 
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++ 
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -309,6 +309,8 @@
     { "name": "camel.management.jwtKeystorePassword", "required": false, 
"description": "Password from the keystore used for JWT tokens validation.", 
"sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"string", "javaType": "java.lang.String", "secret": true, "security": "secret" 
},
     { "name": "camel.management.jwtKeystorePath", "required": false, 
"description": "Path to the keystore file used for JWT tokens validation.", 
"sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"string", "javaType": "java.lang.String", "secret": false },
     { "name": "camel.management.jwtKeystoreType", "required": false, 
"description": "Type of the keystore used for JWT tokens validation (jks, 
pkcs12, etc.).", "sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"string", "javaType": "java.lang.String", "secret": false },
+    { "name": "camel.management.mcpEnabled", "required": false, "description": 
"Whether to expose dev\/diagnostics MCP tools on this management server 
(requires camel-mcp-server on the classpath). Currently honored only when Camel 
JBang registers JbangDevMcpMainListener (for example camel run --mcp). For 
route-based MCP on the main HTTP server in plain camel-main, configure 
camel.server.mcpEnabled instead. Not intended for production use.", 
"sourceType": "org.apache.camel.main.HttpManage [...]
+    { "name": "camel.management.mcpPath", "required": false, "description": 
"HTTP path where the management MCP endpoint is served.", "sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"string", "javaType": "java.lang.String", "defaultValue": "\/mcp", "secret": 
false },
     { "name": "camel.management.metricsEnabled", "required": false, 
"description": "Whether to enable metrics. If enabled then you can access 
metrics on context-path: \/observe\/metrics", "sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"boolean", "javaType": "boolean", "defaultValue": false, "secret": false },
     { "name": "camel.management.openapiUiEnabled", "required": false, 
"description": "Whether to enable Swagger UI for REST DSL OpenAPI documents. If 
enabled then you can browse the API at context-path: \/q\/openapi. The OpenAPI 
document is expected at openapiUiSpecPath (by default \/q\/openapi.json from 
REST DSL apiContextPath ).", "sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"boolean", "javaType": "boolean", "defaultValue": false, "secret": [...]
     { "name": "camel.management.openapiUiSpecPath", "required": false, 
"description": "Path or URL of the OpenAPI document loaded by Swagger UI at 
\/q\/openapi.", "sourceType": 
"org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": 
"string", "javaType": "java.lang.String", "defaultValue": "\/q\/openapi.json", 
"secret": false },
diff --git a/core/camel-main/src/main/docs/main.adoc 
b/core/camel-main/src/main/docs/main.adoc
index ffa14c8dfd9d..e3d33c3295b0 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -230,7 +230,7 @@ The camel.server supports 26 options, which are listed 
below.
 
 
 === Camel Embedded HTTP management Server (only for standalone; not Spring 
Boot or Quarkus) configurations
-The camel.management supports 29 options, which are listed below.
+The camel.management supports 31 options, which are listed below.
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
@@ -255,6 +255,8 @@ The camel.management supports 29 options, which are listed 
below.
 | *camel.management.jwtKeystorePassword* | Password from the keystore used for 
JWT tokens validation. |  | String
 | *camel.management.jwtKeystorePath* | Path to the keystore file used for JWT 
tokens validation. |  | String
 | *camel.management.jwtKeystoreType* | Type of the keystore used for JWT 
tokens validation (jks, pkcs12, etc.). |  | String
+| *camel.management.mcpEnabled* | Whether to expose dev/diagnostics MCP tools 
on this management server (requires camel-mcp-server on the classpath). 
Currently honored only when Camel JBang registers JbangDevMcpMainListener (for 
example camel run --mcp). For route-based MCP on the main HTTP server in plain 
camel-main, configure camel.server.mcpEnabled instead. Not intended for 
production use. | false | boolean
+| *camel.management.mcpPath* | HTTP path where the management MCP endpoint is 
served. | /mcp | String
 | *camel.management.metricsEnabled* | Whether to enable metrics. If enabled 
then you can access metrics on context-path: /observe/metrics | false | boolean
 | *camel.management.openapiUiEnabled* | Whether to enable Swagger UI for REST 
DSL OpenAPI documents. If enabled then you can browse the API at context-path: 
/q/openapi. The OpenAPI document is expected at openapiUiSpecPath (by default 
/q/openapi.json from REST DSL apiContextPath ). | false | boolean
 | *camel.management.openapiUiSpecPath* | Path or URL of the OpenAPI document 
loaded by Swagger UI at /q/openapi. | /q/openapi.json | String
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java
 
b/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java
index 405635887d8e..17b788f8a690 100644
--- 
a/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java
@@ -84,6 +84,10 @@ public class HttpManagementServerConfigurationProperties 
implements BootstrapClo
     private String jwtAudience;
     @Metadata(label = "security", defaultValue = "false", security = 
"insecure:dev")
     private boolean jwtAllowMissingIssuerAndAudience;
+    @Metadata(security = "insecure:dev")
+    private boolean mcpEnabled;
+    @Metadata(defaultValue = "/mcp")
+    private String mcpPath = "/mcp";
 
     public 
HttpManagementServerConfigurationProperties(MainConfigurationProperties parent) 
{
         this.parent = parent;
@@ -573,6 +577,41 @@ public class HttpManagementServerConfigurationProperties 
implements BootstrapClo
         return this;
     }
 
+    public boolean isMcpEnabled() {
+        return mcpEnabled;
+    }
+
+    /**
+     * Whether to expose dev/diagnostics MCP tools on this management server 
(requires camel-mcp-server on the
+     * classpath). Currently honored only when Camel JBang registers 
JbangDevMcpMainListener (for example camel run
+     * --mcp). For route-based MCP on the main HTTP server in plain 
camel-main, configure camel.server.mcpEnabled
+     * instead. Not intended for production use.
+     */
+    public void setMcpEnabled(boolean mcpEnabled) {
+        this.mcpEnabled = mcpEnabled;
+    }
+
+    public String getMcpPath() {
+        return mcpPath;
+    }
+
+    /**
+     * HTTP path where the management MCP endpoint is served.
+     */
+    public void setMcpPath(String mcpPath) {
+        this.mcpPath = mcpPath;
+    }
+
+    public HttpManagementServerConfigurationProperties withMcpEnabled(boolean 
mcpEnabled) {
+        this.mcpEnabled = mcpEnabled;
+        return this;
+    }
+
+    public HttpManagementServerConfigurationProperties withMcpPath(String 
mcpPath) {
+        this.mcpPath = mcpPath;
+        return this;
+    }
+
     /**
      * Whether to enable HTTP authentication for embedded server (for 
standalone applications; not Spring Boot or
      * Quarkus).
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc
index 58d8bc24c988..2929345395f9 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc
@@ -4,7 +4,7 @@ This page covers configuring the Camel CLI — available options, 
configuration
 
 // jbang options: START
 == Camel CLI configurations
-The camel.jbang supports 52 options, which are listed below.
+The camel.jbang supports 53 options, which are listed below.
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
@@ -41,6 +41,7 @@ The camel.jbang supports 52 options, which are listed below.
 | *camel.jbang.maven-settings* | Optional location of Maven settings.xml file 
to configure servers, repositories, mirrors, and proxies. If set to false, not 
even the default /.m2/settings.xml will be used. |  | String
 | *camel.jbang.maven-settings-security* | Optional location of Maven 
settings-security.xml file to decrypt Maven Settings (settings.xml) file |  | 
String
 | *camel.jbang.mavenWrapper* | Include Maven Wrapper files in the exported 
project | true | boolean
+| *camel.jbang.mcp* | Embed dev/diagnostics MCP tools on the local HTTP 
management server (/mcp by default) | false | boolean
 | *camel.jbang.metrics* | Metrics (Micrometer and Prometheus) at 
/observe/metrics on local HTTP server (port 8080 by default) when running 
standalone Camel | false | boolean
 | *camel.jbang.openApi* | File name of open-api spec file (JSON or YAML) to 
generate routes from the swagger/openapi API spec file. |  | String
 | *camel.jbang.openapiUi* | Swagger UI for REST OpenAPI at /q/openapi on local 
HTTP server (port 8080 by default) | false | boolean
diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc
index de73fa1b3b02..1a7f77f79cef 100644
--- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc
@@ -61,6 +61,7 @@ camel debug [options]
 | `--max-idle-seconds` | For how long time in seconds Camel can be idle before 
stopping | 0 | int
 | `--max-messages` | Max number of messages to process before stopping | 0 | 
int
 | `--max-seconds` | Max seconds to run before stopping | 0 | int
+| `--mcp` | Embed dev/diagnostics MCP tools on the local HTTP management 
server (/mcp by default). When management shares the main HTTP port, MCP is 
served on the main server bind address. Also binds the management server to 
127.0.0.1 (affecting health/metrics when --observe is used). | false | boolean
 | `--metrics` _(deprecated)_ | Deprecated: use --observe instead. Metrics 
(Micrometer and Prometheus) at /q/metrics on local HTTP server (port 8080 by 
default) | false | boolean
 | `--modeline` | Whether to support JBang style //DEPS to specify additional 
dependencies | true | boolean
 | `--name` | The name of the Camel application | CamelJBang | String
diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc
index fbe37951b652..4d8ce342f534 100644
--- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc
@@ -57,6 +57,7 @@ camel dev [options]
 | `--max-idle-seconds` | For how long time in seconds Camel can be idle before 
stopping | 0 | int
 | `--max-messages` | Max number of messages to process before stopping | 0 | 
int
 | `--max-seconds` | Max seconds to run before stopping | 0 | int
+| `--mcp` | Embed dev/diagnostics MCP tools on the local HTTP management 
server (/mcp by default). When management shares the main HTTP port, MCP is 
served on the main server bind address. Also binds the management server to 
127.0.0.1 (affecting health/metrics when --observe is used). | false | boolean
 | `--metrics` _(deprecated)_ | Deprecated: use --observe instead. Metrics 
(Micrometer and Prometheus) at /q/metrics on local HTTP server (port 8080 by 
default) | false | boolean
 | `--modeline` | Whether to support JBang style //DEPS to specify additional 
dependencies | true | boolean
 | `--name` | The name of the Camel application | CamelJBang | String
diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc
index 205ec1b76c99..864a7fad313a 100644
--- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc
@@ -57,6 +57,7 @@ camel run [options]
 | `--max-idle-seconds` | For how long time in seconds Camel can be idle before 
stopping | 0 | int
 | `--max-messages` | Max number of messages to process before stopping | 0 | 
int
 | `--max-seconds` | Max seconds to run before stopping | 0 | int
+| `--mcp` | Embed dev/diagnostics MCP tools on the local HTTP management 
server (/mcp by default). When management shares the main HTTP port, MCP is 
served on the main server bind address. Also binds the management server to 
127.0.0.1 (affecting health/metrics when --observe is used). | false | boolean
 | `--metrics` _(deprecated)_ | Deprecated: use --observe instead. Metrics 
(Micrometer and Prometheus) at /q/metrics on local HTTP server (port 8080 by 
default) | false | boolean
 | `--modeline` | Whether to support JBang style //DEPS to specify additional 
dependencies | true | boolean
 | `--name` | The name of the Camel application | CamelJBang | String
diff --git a/dsl/camel-jbang/camel-jbang-core/pom.xml 
b/dsl/camel-jbang/camel-jbang-core/pom.xml
index d3066b4c5e6f..46e20103130d 100644
--- a/dsl/camel-jbang/camel-jbang-core/pom.xml
+++ b/dsl/camel-jbang/camel-jbang-core/pom.xml
@@ -196,6 +196,35 @@
             <version>${mockito-version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-platform-http-main</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-mcp-server</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.modelcontextprotocol.sdk</groupId>
+            <artifactId>mcp-core</artifactId>
+            <version>${mcp-java-sdk-version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.modelcontextprotocol.sdk</groupId>
+            <artifactId>mcp-json-jackson2</artifactId>
+            <version>${mcp-java-sdk-version}</version>
+            <scope>test</scope>
+        </dependency>
+        <!-- MCP SDK schema validation needs networknt 2.0.1 (Dialects); 
wiremock transitively pulls 1.5.x -->
+        <dependency>
+            <groupId>com.networknt</groupId>
+            <artifactId>json-schema-validator</artifactId>
+            <version>${networknt-json-schema-validator-version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
index aa34ac5e55bf..e155bf6a47e2 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
@@ -6,9 +6,9 @@
     { "name": "cmd", "fullName": "cmd", "description": "Performs commands in 
the running Camel integrations, such as start\/stop route, or change logging 
levels.", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.action.CamelAction", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"browse", "fullName": "cmd browse", "description": "Browse pending messages on 
endpoints [...]
     { "name": "completion", "fullName": "completion", "description": "Generate 
completion script for bash\/zsh", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Complete", "options": [ { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ] },
     { "name": "config", "fullName": "config", "description": "Get and set user 
configuration values", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.config.ConfigCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "get", 
"fullName": "config get", "description": "Display user configuration value", 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.config. [...]
-    { "name": "debug", "fullName": "debug", "description": "Debug local Camel 
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Debug", 
"options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd 
HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background", "description": "Run in the background", "defaultValue": 
"false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "To  [...]
+    { "name": "debug", "fullName": "debug", "description": "Debug local Camel 
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Debug", 
"options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd 
HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background", "description": "Run in the background", "defaultValue": 
"false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "To  [...]
     { "name": "dependency", "fullName": "dependency", "description": "Displays 
all Camel dependencies required to run", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.DependencyCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"copy", "fullName": "dependency copy", "description": "Copies all Camel 
dependencies required to run to a specific directory", "sourc [...]
-    { "name": "dev", "fullName": "dev", "description": "Run in dev mode with 
live reload", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Dev", 
"options": [ { "names": "--background", "description": "Run in the background", 
"defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "To wait for run in background to startup 
successfully, before returning", "defaultValue": "true", "javaType": "boolean", 
"type": "boolean" }, [...]
+    { "name": "dev", "fullName": "dev", "description": "Run in dev mode with 
live reload", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Dev", 
"options": [ { "names": "--background", "description": "Run in the background", 
"defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "To wait for run in background to startup 
successfully, before returning", "defaultValue": "true", "javaType": "boolean", 
"type": "boolean" }, [...]
     { "name": "dirty", "fullName": "dirty", "description": "Check if there are 
dirty files from previous Camel runs that did not terminate gracefully", 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.Dirty", 
"options": [ { "names": "--clean", "description": "Clean dirty files which are 
no longer in use", "defaultValue": "false", "javaType": "boolean", "type": 
"boolean" }, { "names": "-h,--help", "description": "Display the help and 
sub-commands", "javaType": "boolean", " [...]
     { "name": "doc", "fullName": "doc", "description": "Shows documentation 
for kamelet, component, and other Camel resources", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.catalog.CatalogDoc", "options": [ { 
"names": "--camel-version", "description": "To use a different Camel version 
than the default version", "javaType": "java.lang.String", "type": "string" }, 
{ "names": "--download", "description": "Whether to allow automatic downloading 
JAR dependencies (over the internet [...]
     { "name": "doctor", "fullName": "doctor", "description": "Checks the 
environment and reports potential issues", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Doctor", "options": [ { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ] },
@@ -26,7 +26,7 @@
     { "name": "plugin", "fullName": "plugin", "description": "Manage plugins 
that add sub-commands to this CLI", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.plugin.PluginCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "add", 
"fullName": "plugin add", "description": "Add new plugin", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.plugin.PluginA [...]
     { "name": "ps", "fullName": "ps", "description": "List running Camel 
integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.ListProcess", "options": [ { 
"names": "--json", "description": "Output in JSON Format", "javaType": 
"boolean", "type": "boolean" }, { "names": "--pid", "description": "List only 
pid in the output", "javaType": "boolean", "type": "boolean" }, { "names": 
"--remote", "description": "Break down counters into remote\/total pairs", 
"javaType": [...]
     { "name": "restart", "fullName": "restart", "description": "Restarts 
running Camel integrations (stop + re-launch)", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.RestartProcess", "options": [ 
{ "names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ] },
-    { "name": "run", "fullName": "run", "description": "Run as local Camel 
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Run", 
"options": [ { "names": "--background", "description": "Run in the background", 
"defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "To wait for run in background to startup 
successfully, before returning", "defaultValue": "true", "javaType": "boolean", 
"type": "boolean" }, { [...]
+    { "name": "run", "fullName": "run", "description": "Run as local Camel 
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Run", 
"options": [ { "names": "--background", "description": "Run in the background", 
"defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "To wait for run in background to startup 
successfully, before returning", "defaultValue": "true", "javaType": "boolean", 
"type": "boolean" }, { [...]
     { "name": "sbom", "fullName": "sbom", "description": "Generate a CycloneDX 
or SPDX SBOM for a specific project", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.SBOMGenerator", "options": [ { 
"names": "--build-property", "description": "Maven build properties, ex. 
--build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, { 
"names": "--camel-spring-boot-version", "description": "Camel version to use 
with Spring Boot", "javaType": "java.lang.String", "type" [...]
     { "name": "script", "fullName": "script", "description": "Run Camel 
integration as shell script for terminal scripting", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Script", "options": [ { "names": 
"--logging", "description": "Can be used to turn on logging (logs to file in 
<user home>\/.camel directory)", "defaultValue": "false", "javaType": 
"boolean", "type": "boolean" }, { "names": "--logging-level", "description": 
"Logging level (ERROR, WARN, INFO, DEBUG, TRACE)", "d [...]
     { "name": "shell", "fullName": "shell", "description": "Interactive Camel 
CLI shell.", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Shell", 
"options": [ { "names": "-h,--help", "description": "Display the help and 
sub-commands", "javaType": "boolean", "type": "boolean" } ] },
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json
 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json
index f4b422e1b40c..bd1bdf642d53 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json
@@ -35,6 +35,7 @@
     { "name": "camel.jbang.maven-settings", "required": false, "description": 
"Optional location of Maven settings.xml file to configure servers, 
repositories, mirrors, and proxies. If set to false, not even the default 
\/.m2\/settings.xml will be used.", "label": "maven", "type": "string", 
"javaType": "String", "secret": false },
     { "name": "camel.jbang.maven-settings-security", "required": false, 
"description": "Optional location of Maven settings-security.xml file to 
decrypt Maven Settings (settings.xml) file", "label": "maven", "type": 
"string", "javaType": "String", "secret": false },
     { "name": "camel.jbang.mavenWrapper", "required": false, "description": 
"Include Maven Wrapper files in the exported project", "type": "boolean", 
"javaType": "boolean", "defaultValue": true, "secret": false },
+    { "name": "camel.jbang.mcp", "required": false, "description": "Embed 
dev\/diagnostics MCP tools on the local HTTP management server (\/mcp by 
default)", "type": "boolean", "javaType": "boolean", "defaultValue": false, 
"secret": false, "security": "insecure:dev" },
     { "name": "camel.jbang.metrics", "required": false, "description": 
"Metrics (Micrometer and Prometheus) at \/observe\/metrics on local HTTP server 
(port 8080 by default) when running standalone Camel", "type": "boolean", 
"javaType": "boolean", "defaultValue": false, "secret": false, "deprecated": 
true },
     { "name": "camel.jbang.openApi", "required": false, "description": "File 
name of open-api spec file (JSON or YAML) to generate routes from the 
swagger\/openapi API spec file.", "type": "string", "javaType": "String", 
"secret": false },
     { "name": "camel.jbang.openapiUi", "required": false, "description": 
"Swagger UI for REST OpenAPI at \/q\/openapi on local HTTP server (port 8080 by 
default)", "type": "boolean", "javaType": "boolean", "defaultValue": false, 
"secret": false, "security": "insecure:dev" },
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index 29bf3e3d3b04..0cf49cf11e9f 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -602,6 +602,13 @@ public class Run extends CamelCommand {
         }
     }
 
+    private boolean isMcpEnabled(Properties profileProperties) {
+        String val = profileProperties != null
+                ? profileProperties.getProperty(MCP, serverOptions.mcp ? 
"true" : "false")
+                : (serverOptions.mcp ? "true" : "false");
+        return "true".equals(val);
+    }
+
     private void writeSetting(KameletMain main, Properties existing, String 
key, Supplier<String> value) {
         String val = existing != null ? existing.getProperty(key, value.get()) 
: value.get();
         if (val != null) {
@@ -846,6 +853,7 @@ public class Run extends CamelCommand {
         writeSetting(main, profileProperties, HEALTH, serverOptions.health ? 
"true" : "false");
         writeSetting(main, profileProperties, METRICS, serverOptions.metrics ? 
"true" : "false");
         writeSetting(main, profileProperties, CONSOLE, serverOptions.console ? 
"true" : "false");
+        writeSetting(main, profileProperties, MCP, serverOptions.mcp ? "true" 
: "false");
         writeSetting(main, profileProperties, OPENAPI_UI, 
serverOptions.openapiUi ? "true" : "false");
         writeSetting(main, profileProperties, VERBOSE, verbose ? "true" : 
"false");
         // the runtime version of Camel is what is loaded via the catalog
@@ -1258,6 +1266,10 @@ public class Run extends CamelCommand {
             dependencies.add("camel:openapi-java");
             applyOpenApiUiRuntimeOptions(main);
         }
+        if (isMcpEnabled(profileProperties)) {
+            dependencies.add("camel:platform-http-main");
+            dependencies.add("camel:mcp-server");
+        }
         if (debugOptions.openTelemetryAgent) {
             dependencies.add("camel:opentelemetry2");
             boolean externalExport = 
"otlp".equals(debugOptions.openTelemetryAgentExport)
@@ -3089,6 +3101,12 @@ public class Run extends CamelCommand {
                 description = "Developer console at /q/dev on local HTTP 
server (port 8080 by default)")
         boolean console;
 
+        @Option(names = { "--mcp" }, defaultValue = "false",
+                description = "Embed dev/diagnostics MCP tools on the local 
HTTP management server (/mcp by default). "
+                              + "When management shares the main HTTP port, 
MCP is served on the main server bind address. "
+                              + "Also binds the management server to 127.0.0.1 
(affecting health/metrics when --observe is used).")
+        boolean mcp;
+
         @Option(names = { "--openapi-ui" }, defaultValue = "false",
                 description = "Swagger UI for REST OpenAPI at /q/openapi 
(OpenAPI document at /q/openapi.json; port 8080 by default)")
         boolean openapiUi;
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java
index b95d4668448c..6c4789d27729 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java
@@ -205,6 +205,10 @@ public final class CamelJBangConstants {
               javaType = "boolean")
     public static final String CONSOLE = "camel.jbang.console";
 
+    @Metadata(description = "Embed dev/diagnostics MCP tools on the local HTTP 
management server (/mcp by default)",
+              javaType = "boolean", security = "insecure:dev")
+    public static final String MCP = "camel.jbang.mcp";
+
     @Metadata(description = "Swagger UI for REST OpenAPI at /q/openapi on 
local HTTP server (port 8080 by default)",
               javaType = "boolean", security = "insecure:dev")
     public static final String OPENAPI_UI = "camel.jbang.openapiUi";
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunMcpOptionTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunMcpOptionTest.java
new file mode 100644
index 000000000000..063609f8512b
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunMcpOptionTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.dsl.jbang.core.commands;
+
+import org.junit.jupiter.api.Test;
+import picocli.CommandLine;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class RunMcpOptionTest {
+
+    @Test
+    void parseMcpFlag() {
+        Run run = new Run(new CamelJBangMain());
+        CommandLine cmd = new CommandLine(run);
+        cmd.parseArgs("hello.yaml", "--mcp");
+        assertThat(run.serverOptions.mcp).isTrue();
+    }
+
+    @Test
+    void mcpDefaultsToFalse() {
+        Run run = new Run(new CamelJBangMain());
+        CommandLine cmd = new CommandLine(run);
+        cmd.parseArgs("hello.yaml");
+        assertThat(run.serverOptions.mcp).isFalse();
+    }
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/JbangDevMcpServerTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/JbangDevMcpServerTest.java
new file mode 100644
index 000000000000..36a65375ce00
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/mcp/JbangDevMcpServerTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.dsl.jbang.core.commands.mcp;
+
+import java.time.Duration;
+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.mcp.server.jbang.JbangDevMcpServer;
+import org.apache.camel.component.platform.http.main.MainHttpServer;
+import org.apache.camel.component.platform.http.main.ManagementHttpServer;
+import org.apache.camel.dsl.jbang.core.commands.ai.ToolRegistry;
+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 JbangDevMcpServerTest {
+
+    @Test
+    void exposesToolRegistryOnManagementServer() throws Exception {
+        int mainPort = AvailablePortFinder.getNextAvailable();
+        int managementPort = AvailablePortFinder.getNextAvailable();
+
+        CamelContext camelContext = new DefaultCamelContext();
+        JbangDevMcpServer devMcp = new JbangDevMcpServer();
+        McpSyncClient client = null;
+        try {
+            MainHttpServer main = new MainHttpServer();
+            main.setCamelContext(camelContext);
+            main.setHost("127.0.0.1");
+            main.setPort(mainPort);
+            camelContext.addService(main);
+
+            ManagementHttpServer management = new ManagementHttpServer();
+            management.setCamelContext(camelContext);
+            management.setHost("127.0.0.1");
+            management.setPort(managementPort);
+            management.setPath("/");
+            camelContext.addService(management);
+
+            devMcp.setCamelContext(camelContext);
+            devMcp.setPath("/mcp");
+            camelContext.addService(devMcp);
+
+            camelContext.start();
+
+            client = McpClient.sync(
+                    
HttpClientStreamableHttpTransport.builder("http://127.0.0.1:"; + 
managementPort).build())
+                    .requestTimeout(Duration.ofSeconds(10))
+                    .initializationTimeout(Duration.ofSeconds(10))
+                    .build();
+            McpSchema.InitializeResult init = client.initialize();
+            
assertThat(init.serverInfo().name()).isEqualTo("camel-jbang-dev-tools");
+
+            assertThat(client.listTools().tools())
+                    .extracting(McpSchema.Tool::name)
+                    .contains(ToolRegistry.allTools().get(0).name());
+
+            McpSchema.Tool parameterizedTool = 
client.listTools().tools().stream()
+                    .filter(t -> "select_process".equals(t.name()))
+                    .findFirst()
+                    .orElseThrow();
+            assertThat(parameterizedTool.inputSchema()).isNotNull();
+            
assertThat(parameterizedTool.inputSchema().toString()).contains("name").contains("required");
+
+            McpSchema.CallToolResult result = client.callTool(
+                    new McpSchema.CallToolRequest("list_processes", Map.of()));
+            assertThat(result.isError()).isNotEqualTo(Boolean.TRUE);
+            assertThat(result.content().toString()).contains("processes");
+        } finally {
+            if (client != null) {
+                client.closeGracefully();
+            }
+            camelContext.stop();
+        }
+    }
+}
diff --git 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index 7d7cade212fe..419f2ae9fe1a 100644
--- 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -594,6 +594,21 @@ public class KameletMain extends MainCommandLineSupport {
             configure().httpManagementServer().withEnabled(true);
             configure().httpManagementServer().withInfoEnabled(true);
         }
+        boolean mcp = 
"true".equals(getInitialProperties().get(getInstanceType() + ".mcp"));
+        if (mcp) {
+            configure().httpManagementServer().withEnabled(true);
+            configure().httpManagementServer().withMcpEnabled(true);
+            if (!isConfigured("camel.management.host")) {
+                configure().httpManagementServer().withHost("127.0.0.1");
+            }
+            String listeners = 
getInitialProperties().getProperty("camel.main.mainListenerClasses");
+            String embedded = 
"org.apache.camel.component.mcp.server.jbang.JbangDevMcpMainListener";
+            if (listeners == null || listeners.isBlank()) {
+                addInitialProperty("camel.main.mainListenerClasses", embedded);
+            } else if (!listeners.contains(embedded)) {
+                addInitialProperty("camel.main.mainListenerClasses", listeners 
+ "," + embedded);
+            }
+        }
         // Deprecated: to be replaced by observe flag
         boolean health = 
"true".equals(getInitialProperties().get(getInstanceType() + ".health"));
         if (health) {
diff --git 
a/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties
 
b/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties
index 70730cfcc430..4f98022c4f35 100644
--- 
a/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties
+++ 
b/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties
@@ -42,6 +42,7 @@ org.eclipse.microprofile.config.inject.ConfigProperty = 
camel:microprofile-confi
 
 camel.opentelemetry = camel:opentelemetry
 camel.opentelemetry2 = camel:opentelemetry2
+org.apache.camel.component.mcp.server.jbang.JbangDevMcpMainListener = 
camel:mcp-server
 camel.lra = camel:lra
 camel.telemetryDev = camel:telemetry-dev
 camel.cluster.file = camel:file

Reply via email to