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

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

commit 96385103753c60afe6de591c2a4b66309b95a0f4
Author: Jinal Sarvaiya <[email protected]>
AuthorDate: Fri Oct 23 19:33:31 2026 +0100

    fix #109: make Citrus MCP server opt-in via --with-citrus-mcp
---
 CHANGELOG.md                                       |   4 +
 .../luigidemasi/camelkit/command/InitCommand.java  |   5 +
 .../camelkit/generator/CodexConfigMerger.java      |  14 ++-
 .../camelkit/generator/InitContext.java            |   2 +
 .../camelkit/generator/McpConfigGenerator.java     |  10 +-
 .../camelkit/service/DoctorService.java            |  35 +++---
 .../luigidemasi/camelkit/service/InitRequest.java  |   1 +
 .../luigidemasi/camelkit/service/InitService.java  |   9 +-
 .../templates/mcp-configs/antigravity-mcp.json     |   4 +-
 .../resources/templates/mcp-configs/bob-mcp.json   |   4 +-
 .../templates/mcp-configs/claude-code-mcp.json     |   4 +-
 .../resources/templates/mcp-configs/codex-mcp.toml |   2 +
 .../templates/mcp-configs/copilot-mcp.json         |   4 +-
 .../templates/mcp-configs/opencode-mcp.json        |   8 +-
 .../resources/templates/mcp-configs/pi-mcp.json    |   4 +-
 .../resources/templates/mcp-configs/qwen-mcp.json  |   4 +-
 .../generator/AntigravityGeneratorTest.java        |   5 +-
 .../camelkit/generator/CodexCliSmokeTest.java      |   3 +
 .../camelkit/generator/CodexGeneratorTest.java     |  12 ++-
 .../camelkit/generator/CopilotGeneratorTest.java   |   4 +-
 .../camelkit/generator/OpenCodeGeneratorTest.java  |   4 +-
 .../camelkit/generator/PiGeneratorTest.java        |   4 +-
 .../camelkit/generator/QwenGeneratorTest.java      |   4 +-
 .../generator/ResourceConsistencyTest.java         |   3 +-
 .../generator/ShippedAssetStructureTest.java       |  16 ++-
 .../camelkit/service/DoctorServiceTest.java        | 119 +++++++++------------
 .../camelkit/service/InitServiceTest.java          |  67 +++++++++++-
 .../camelkit/workflow/WorkflowManifestTest.java    |   4 +-
 28 files changed, 229 insertions(+), 130 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 498f7b09..9084f3e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,10 @@ and this project adheres to [Semantic 
Versioning](https://semver.org/spec/v2.0.0
 
 ### Changed
 
+- **Make Citrus MCP server opt-in (#109)** — `camel-kit init` no longer writes 
Citrus MCP server
+  configuration by default. Pass `--with-citrus-mcp` to include it. Workspaces 
created before this
+  change that have `citrus.mcp.version` but no `citrus.mcp.enabled` are 
treated as implicitly opted
+  in for backward compatibility. `camel-kit doctor` skips Citrus health checks 
when not opted in.
 - **Claude Code native skill discovery (#243)** — skills are now installed to 
`.claude/skills/` with
   `user-invocable` and `description` frontmatter so Claude Code discovers them 
natively without command stubs.
   Legacy `.claude/commands/camel-*.md` stubs are cleaned up on regeneration; 
user-created commands are preserved.
diff --git 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/command/InitCommand.java
 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/command/InitCommand.java
index 8b2081fd..72953a72 100644
--- 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/command/InitCommand.java
+++ 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/command/InitCommand.java
@@ -48,6 +48,10 @@ public class InitCommand extends CamelKitCommand {
             defaultValue = "default")
     public String citrusVersion;
 
+    @Option(names = {"--with-citrus-mcp"},
+            description = "Include the Citrus MCP server in agent 
configuration (default: off)")
+    public boolean withCitrusMcp;
+
     @Option(names = {"--no-fetch"}, description = "Skip external catalog 
fetching")
     public boolean noFetch;
 
@@ -170,6 +174,7 @@ public class InitCommand extends CamelKitCommand {
                 resolvedTargetDir,
                 citrusVersion,
                 noFetch,
+                withCitrusMcp,
                 sourcePlatform,
                 detectCommandPrefix(),
                 CamelKitMain.DEFAULT_CITRUS_VERSION,
diff --git 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/CodexConfigMerger.java
 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/CodexConfigMerger.java
index 9f2b044f..8a3d574f 100644
--- 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/CodexConfigMerger.java
+++ 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/CodexConfigMerger.java
@@ -14,22 +14,26 @@ final class CodexConfigMerger {
     static final String BEGIN_MARKER = "# BEGIN CAMEL-KIT MANAGED MCP SERVERS";
     static final String END_MARKER = "# END CAMEL-KIT MANAGED MCP SERVERS";
 
-    private static final List<String> MANAGED_SERVERS = List.of("camel", 
"camel-knowledge", "citrus");
+    static List<String> managedServers(boolean citrusEnabled) {
+        return citrusEnabled
+                ? List.of("camel", "camel-knowledge", "citrus")
+                : List.of("camel", "camel-knowledge");
+    }
 
-    void merge(Path configFile, String renderedConfig) throws IOException {
+    void merge(Path configFile, String renderedConfig, boolean citrusEnabled) 
throws IOException {
         validateToml(renderedConfig, "generated Codex MCP configuration");
 
         String managedBlock = BEGIN_MARKER + System.lineSeparator()
                               + renderedConfig.strip() + System.lineSeparator()
                               + END_MARKER;
         String existing = Files.isRegularFile(configFile) ? 
Files.readString(configFile) : "";
-        String merged = merge(existing, managedBlock);
+        String merged = merge(existing, managedBlock, citrusEnabled);
         validateToml(merged, configFile.toString());
         AtomicFileWriter.write(configFile,
                 merged + (merged.endsWith(System.lineSeparator()) ? "" : 
System.lineSeparator()));
     }
 
-    private String merge(String existing, String managedBlock) throws 
IOException {
+    private String merge(String existing, String managedBlock, boolean 
citrusEnabled) throws IOException {
         if (existing.isBlank()) {
             return managedBlock;
         }
@@ -47,7 +51,7 @@ final class CodexConfigMerger {
 
         Object mcpServers = Toml.parse(existing).get("mcp_servers");
         if (mcpServers instanceof TomlTable servers) {
-            List<String> conflicts = MANAGED_SERVERS.stream()
+            List<String> conflicts = managedServers(citrusEnabled).stream()
                     .filter(server -> servers.get(server) instanceof TomlTable)
                     .toList();
             if (!conflicts.isEmpty()) {
diff --git 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/InitContext.java
 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/InitContext.java
index 6beb1926..2e588402 100644
--- 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/InitContext.java
+++ 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/InitContext.java
@@ -14,6 +14,7 @@ public record InitContext(
         Path projectDir,
         String commandPrefix,
         DistributionConfig distribution,
+        boolean withCitrusMcp,
         Printer printer) {
 
     public InitContext(
@@ -32,6 +33,7 @@ public record InitContext(
              projectDir,
              commandPrefix,
              DistributionConfig.loadFromClasspathOrDefaults(),
+             false,
              printer);
     }
 }
diff --git 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/McpConfigGenerator.java
 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/McpConfigGenerator.java
index 895ff739..4a83adce 100644
--- 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/McpConfigGenerator.java
+++ 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/generator/McpConfigGenerator.java
@@ -31,9 +31,10 @@ class McpConfigGenerator {
 
             QuteTemplateEngine qute = new QuteTemplateEngine();
             String template = 
TemplateUtils.readTemplate(ctx.agent().mcpConfigTemplatePath());
-            String processed = qute.renderString(template, 
templateData(ctx.distribution(), workflow));
+            String processed
+                    = qute.renderString(template, 
templateData(ctx.distribution(), workflow, ctx.withCitrusMcp()));
             if ("toml".equals(ctx.agent().mcpConfigFormat())) {
-                new CodexConfigMerger().merge(configFile, processed);
+                new CodexConfigMerger().merge(configFile, processed, 
ctx.withCitrusMcp());
             } else if ("opencode".equals(ctx.agentName())) {
                 new OpenCodeConfigMerger().merge(configFile, processed);
             } else if ("antigravity".equals(ctx.agentName())) {
@@ -90,7 +91,9 @@ class McpConfigGenerator {
         }
     }
 
-    private Map<String, Object> templateData(DistributionConfig dist, 
WorkflowManifest workflow) throws IOException {
+    private Map<String, Object> templateData(
+            DistributionConfig dist, WorkflowManifest workflow, boolean 
withCitrusMcp)
+            throws IOException {
         Map<String, Object> data = new java.util.HashMap<>(
                 VersionPlaceholderResolver.buildVersionTemplateData(dist));
 
@@ -101,6 +104,7 @@ class McpConfigGenerator {
         data.put("KNOWLEDGE_TOOLS_JSON", 
toJsonArray(knowledgeServer.allowedTools()));
         data.put("KNOWLEDGE_DESCRIPTION", knowledgeServer.description());
 
+        data.put("CITRUS_ENABLED", withCitrusMcp);
         WorkflowManifest.WorkflowMcpServer citrusServer = 
workflow.mcpServer("citrus");
         data.put("CITRUS_TOOLS_JSON", 
toJsonArray(citrusServer.allowedTools()));
         data.put("CITRUS_DESCRIPTION", citrusServer.description());
diff --git 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/DoctorService.java
 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/DoctorService.java
index 88ba10c1..d6facb95 100644
--- 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/DoctorService.java
+++ 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/DoctorService.java
@@ -48,11 +48,6 @@ public class DoctorService {
     private static final String NESTED_RULE = "\n";
     private static final ObjectMapper JSONC_MAPPER = 
OpenCodeProjectConfig.newJsonMapper();
     private static final Duration PREREQUISITE_TIMEOUT = Duration.ofSeconds(3);
-    private static final Set<String> PRE_CITRUS_JSON_AGENTS = Set.of(
-            AgentGeneratorStrategy.BOB2.descriptorValue(),
-            AgentGeneratorStrategy.CLAUDE.descriptorValue(),
-            AgentGeneratorStrategy.OPENCODE.descriptorValue(),
-            AgentGeneratorStrategy.QWEN.descriptorValue());
     private static final Set<String> OPENCODE_PERMISSION_ACTIONS = 
Set.of("allow", "ask", "deny");
 
     private static final List<String> REQUIRED_CONFIG_KEYS = List.of(
@@ -534,7 +529,7 @@ public class DoctorService {
 
             AgentConfig configuredAgent = 
AgentRegistry.get(normalizedAgentName);
             if (configuredAgent != null && 
"toml".equals(configuredAgent.mcpConfigFormat())) {
-                checkCodexMcp(root, mcpFile, findings);
+                checkCodexMcp(root, mcpFile, config, findings);
                 return;
             }
 
@@ -573,19 +568,16 @@ public class DoctorService {
         boolean knowledgeOk = checkMcpServer(
                 root, mcpFile, servers, "camel-knowledge", 
expectations.knowledgeMcpTools(), copilotToolsSchema,
                 piDirectToolsSchema, qwenIncludeToolsSchema, openCodeSchema, 
antigravitySchema, findings);
-        boolean citrusOptional = 
PRE_CITRUS_JSON_AGENTS.contains(normalizedAgentName)
-                && !config.containsKey("citrus.version")
-                && !config.containsKey("citrus.mcp.version");
+        boolean citrusMcpEnabled = 
"true".equals(config.getProperty("citrus.mcp.enabled"));
+        if (!config.containsKey("citrus.mcp.enabled") && 
config.containsKey("citrus.mcp.version")) {
+            citrusMcpEnabled = true;
+        }
         boolean citrusOk;
-        if (servers.has("citrus") || !citrusOptional) {
+        if (citrusMcpEnabled || servers.has("citrus")) {
             citrusOk = checkMcpServer(
                     root, mcpFile, servers, "citrus", 
expectations.citrusMcpTools(), copilotToolsSchema,
                     piDirectToolsSchema, qwenIncludeToolsSchema, 
openCodeSchema, antigravitySchema, findings);
         } else {
-            // Only legacy-capable JSON agents without persisted Citrus 
metadata reach this branch.
-            findings.add(DoctorFinding.warn("mcp", relativize(root, mcpFile),
-                    "MCP server 'citrus' is not configured; camel-test cannot 
verify Citrus actions",
-                    "Regenerate the MCP config with camel-kit init --here 
--force to add the Citrus MCP server."));
             citrusOk = true;
         }
         boolean openCodePermissionsOk = !openCodeSchema
@@ -710,7 +702,7 @@ public class DoctorService {
         });
     }
 
-    private void checkCodexMcp(Path root, Path mcpFile, List<DoctorFinding> 
findings) {
+    private void checkCodexMcp(Path root, Path mcpFile, Properties config, 
List<DoctorFinding> findings) {
         TomlParseResult parsed;
         try {
             parsed = Toml.parse(mcpFile);
@@ -738,8 +730,17 @@ public class DoctorService {
                 root, mcpFile, servers, "camel", expectations.camelMcpTools(), 
findings);
         boolean knowledgeOk = checkCodexMcpServer(
                 root, mcpFile, servers, "camel-knowledge", 
expectations.knowledgeMcpTools(), findings);
-        boolean citrusOk = checkCodexMcpServer(
-                root, mcpFile, servers, "citrus", 
expectations.citrusMcpTools(), findings);
+        boolean codexCitrusEnabled = 
"true".equals(config.getProperty("citrus.mcp.enabled"));
+        if (!config.containsKey("citrus.mcp.enabled") && 
config.containsKey("citrus.mcp.version")) {
+            codexCitrusEnabled = true;
+        }
+        boolean citrusOk;
+        if (codexCitrusEnabled || servers.get("citrus") instanceof TomlTable) {
+            citrusOk = checkCodexMcpServer(
+                    root, mcpFile, servers, "citrus", 
expectations.citrusMcpTools(), findings);
+        } else {
+            citrusOk = true;
+        }
         if (camelOk && knowledgeOk && citrusOk) {
             findings.add(DoctorFinding.pass("mcp", relativize(root, mcpFile),
                     "Codex MCP config is valid TOML and all tool allowlists 
match Camel-Kit expectations",
diff --git 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/InitRequest.java
 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/InitRequest.java
index 0ae425d3..8729394f 100644
--- 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/InitRequest.java
+++ 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/InitRequest.java
@@ -15,6 +15,7 @@ public record InitRequest(
         Path targetDir,
         String citrusVersion,
         boolean noFetch,
+        boolean withCitrusMcp,
         String sourcePlatform,
         String commandPrefix,
         String defaultCitrusVersion,
diff --git 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/InitService.java
 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/InitService.java
index 7da03216..69c45f0b 100644
--- 
a/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/InitService.java
+++ 
b/camel-kit-core/src/main/java/io/github/luigidemasi/camelkit/service/InitService.java
@@ -54,7 +54,7 @@ public class InitService {
         InitContext genCtx = new InitContext(
                 agent, request.agentName(), commandsDir,
                 skillsDir, targetDir,
-                request.commandPrefix(), request.distribution(), 
request.printer());
+                request.commandPrefix(), request.distribution(), 
request.withCitrusMcp(), request.printer());
         AgentGenerator generator = 
AgentGeneratorFactory.create(request.agentName());
         requireRealAgentDirectories(targetDir, skillsDir, commandsDir);
         generator.preflight(genCtx);
@@ -156,7 +156,12 @@ public class InitService {
         config.setProperty("agent.name", agentName);
         config.setProperty("agent.folder", agent.folder());
         config.setProperty("citrus.version", request.resolvedCitrusVersion());
-        config.setProperty("citrus.mcp.version", 
request.distribution().citrusMcpVersion());
+        if (request.withCitrusMcp()) {
+            config.setProperty("citrus.mcp.version", 
request.distribution().citrusMcpVersion());
+            config.setProperty("citrus.mcp.enabled", "true");
+        } else {
+            config.setProperty("citrus.mcp.enabled", "false");
+        }
         writeVersionConfig(config, request.distribution(), "main");
         if (request.sourcePlatform() != null && 
!"auto".equals(request.sourcePlatform())) {
             config.setProperty("project.sourcePlatform", 
request.sourcePlatform());
diff --git 
a/camel-kit-core/src/main/resources/templates/mcp-configs/antigravity-mcp.json 
b/camel-kit-core/src/main/resources/templates/mcp-configs/antigravity-mcp.json
index 3f0467fc..7f6b1cac 100644
--- 
a/camel-kit-core/src/main/resources/templates/mcp-configs/antigravity-mcp.json
+++ 
b/camel-kit-core/src/main/resources/templates/mcp-configs/antigravity-mcp.json
@@ -17,7 +17,7 @@
         "-Dquarkus.log.level=WARN",
         
"io.github.luigidemasi:camel-kit-knowledge-mcp:{KNOWLEDGE_VERSION}:runner"
       ]
-    },
+    }{#if CITRUS_ENABLED},
     "citrus": {
       "command": "jbang",
       "args": [
@@ -26,6 +26,6 @@
         "-Dquarkus.http.port=-1",
         "org.citrusframework:citrus-mcp-server:{CITRUS_MCP_VERSION}:runner"
       ]
-    }
+    }{/if}
   }
 }
diff --git 
a/camel-kit-core/src/main/resources/templates/mcp-configs/bob-mcp.json 
b/camel-kit-core/src/main/resources/templates/mcp-configs/bob-mcp.json
index 76f8f547..39fa77d8 100644
--- a/camel-kit-core/src/main/resources/templates/mcp-configs/bob-mcp.json
+++ b/camel-kit-core/src/main/resources/templates/mcp-configs/bob-mcp.json
@@ -23,7 +23,7 @@
       "description": "{KNOWLEDGE_DESCRIPTION}",
       "autoApprove": {KNOWLEDGE_TOOLS_JSON},
       "alwaysAllow": {KNOWLEDGE_TOOLS_JSON}
-    },
+    }{#if CITRUS_ENABLED},
     "citrus": {
       "command": "jbang",
       "args": [
@@ -35,6 +35,6 @@
       "description": "{CITRUS_DESCRIPTION}",
       "autoApprove": {CITRUS_TOOLS_JSON},
       "alwaysAllow": {CITRUS_TOOLS_JSON}
-    }
+    }{/if}
   }
 }
diff --git 
a/camel-kit-core/src/main/resources/templates/mcp-configs/claude-code-mcp.json 
b/camel-kit-core/src/main/resources/templates/mcp-configs/claude-code-mcp.json
index 76f8f547..39fa77d8 100644
--- 
a/camel-kit-core/src/main/resources/templates/mcp-configs/claude-code-mcp.json
+++ 
b/camel-kit-core/src/main/resources/templates/mcp-configs/claude-code-mcp.json
@@ -23,7 +23,7 @@
       "description": "{KNOWLEDGE_DESCRIPTION}",
       "autoApprove": {KNOWLEDGE_TOOLS_JSON},
       "alwaysAllow": {KNOWLEDGE_TOOLS_JSON}
-    },
+    }{#if CITRUS_ENABLED},
     "citrus": {
       "command": "jbang",
       "args": [
@@ -35,6 +35,6 @@
       "description": "{CITRUS_DESCRIPTION}",
       "autoApprove": {CITRUS_TOOLS_JSON},
       "alwaysAllow": {CITRUS_TOOLS_JSON}
-    }
+    }{/if}
   }
 }
diff --git 
a/camel-kit-core/src/main/resources/templates/mcp-configs/codex-mcp.toml 
b/camel-kit-core/src/main/resources/templates/mcp-configs/codex-mcp.toml
index d9c6343a..d19e2f88 100644
--- a/camel-kit-core/src/main/resources/templates/mcp-configs/codex-mcp.toml
+++ b/camel-kit-core/src/main/resources/templates/mcp-configs/codex-mcp.toml
@@ -19,6 +19,7 @@ args = [
 ]
 enabled_tools = {KNOWLEDGE_TOOLS_JSON}
 default_tools_approval_mode = "prompt"
+{#if CITRUS_ENABLED}
 
 [mcp_servers.citrus]
 command = "jbang"
@@ -30,3 +31,4 @@ args = [
 ]
 enabled_tools = {CITRUS_TOOLS_JSON}
 default_tools_approval_mode = "prompt"
+{/if}
diff --git 
a/camel-kit-core/src/main/resources/templates/mcp-configs/copilot-mcp.json 
b/camel-kit-core/src/main/resources/templates/mcp-configs/copilot-mcp.json
index 4dfc1ee6..33287595 100644
--- a/camel-kit-core/src/main/resources/templates/mcp-configs/copilot-mcp.json
+++ b/camel-kit-core/src/main/resources/templates/mcp-configs/copilot-mcp.json
@@ -23,7 +23,7 @@
       ],
       "description": "{KNOWLEDGE_DESCRIPTION}",
       "tools": {KNOWLEDGE_TOOLS_JSON}
-    },
+    }{#if CITRUS_ENABLED},
     "citrus": {
       "type": "stdio",
       "command": "jbang",
@@ -35,6 +35,6 @@
       ],
       "description": "{CITRUS_DESCRIPTION}",
       "tools": {CITRUS_TOOLS_JSON}
-    }
+    }{/if}
   }
 }
diff --git 
a/camel-kit-core/src/main/resources/templates/mcp-configs/opencode-mcp.json 
b/camel-kit-core/src/main/resources/templates/mcp-configs/opencode-mcp.json
index 6baedd19..ed536d09 100644
--- a/camel-kit-core/src/main/resources/templates/mcp-configs/opencode-mcp.json
+++ b/camel-kit-core/src/main/resources/templates/mcp-configs/opencode-mcp.json
@@ -2,8 +2,8 @@
   "$schema": "https://opencode.ai/config.json";,
   "permission": {
     "camel_*": "ask",
-    "camel-knowledge_*": "ask",
-    "citrus_*": "ask"
+    "camel-knowledge_*": "ask"{#if CITRUS_ENABLED},
+    "citrus_*": "ask"{/if}
   },
   "mcp": {
     "camel": {
@@ -27,7 +27,7 @@
         
"io.github.luigidemasi:camel-kit-knowledge-mcp:{KNOWLEDGE_VERSION}:runner"
       ],
       "enabled": true
-    },
+    }{#if CITRUS_ENABLED},
     "citrus": {
       "type": "local",
       "command": [
@@ -38,6 +38,6 @@
         "org.citrusframework:citrus-mcp-server:{CITRUS_MCP_VERSION}:runner"
       ],
       "enabled": true
-    }
+    }{/if}
   }
 }
diff --git 
a/camel-kit-core/src/main/resources/templates/mcp-configs/pi-mcp.json 
b/camel-kit-core/src/main/resources/templates/mcp-configs/pi-mcp.json
index e17cc1e3..c7539b1c 100644
--- a/camel-kit-core/src/main/resources/templates/mcp-configs/pi-mcp.json
+++ b/camel-kit-core/src/main/resources/templates/mcp-configs/pi-mcp.json
@@ -23,7 +23,7 @@
       "description": "{KNOWLEDGE_DESCRIPTION}",
       "directTools": {KNOWLEDGE_TOOLS_JSON},
       "excludeTools": []
-    },
+    }{#if CITRUS_ENABLED},
     "citrus": {
       "command": "jbang",
       "args": [
@@ -35,6 +35,6 @@
       "description": "{CITRUS_DESCRIPTION}",
       "directTools": {CITRUS_TOOLS_JSON},
       "excludeTools": []
-    }
+    }{/if}
   }
 }
diff --git 
a/camel-kit-core/src/main/resources/templates/mcp-configs/qwen-mcp.json 
b/camel-kit-core/src/main/resources/templates/mcp-configs/qwen-mcp.json
index 3f8b5f87..94c348d8 100644
--- a/camel-kit-core/src/main/resources/templates/mcp-configs/qwen-mcp.json
+++ b/camel-kit-core/src/main/resources/templates/mcp-configs/qwen-mcp.json
@@ -21,7 +21,7 @@
       ],
       "description": "{KNOWLEDGE_DESCRIPTION}",
       "includeTools": {KNOWLEDGE_TOOLS_JSON}
-    },
+    }{#if CITRUS_ENABLED},
     "citrus": {
       "command": "jbang",
       "args": [
@@ -32,6 +32,6 @@
       ],
       "description": "{CITRUS_DESCRIPTION}",
       "includeTools": {CITRUS_TOOLS_JSON}
-    }
+    }{/if}
   }
 }
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/AntigravityGeneratorTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/AntigravityGeneratorTest.java
index 1f1b92c7..bd83092a 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/AntigravityGeneratorTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/AntigravityGeneratorTest.java
@@ -6,6 +6,7 @@ import java.util.List;
 import java.util.Set;
 
 import io.github.luigidemasi.camelkit.config.AgentRegistry;
+import io.github.luigidemasi.camelkit.config.DistributionConfig;
 import io.github.luigidemasi.camelkit.output.Printer;
 
 import com.fasterxml.jackson.databind.JsonNode;
@@ -25,7 +26,9 @@ class AntigravityGeneratorTest {
     private InitContext context(String prefix) {
         var agent = AgentRegistry.get("antigravity");
         Path skills = tempDir.resolve(agent.skillsDirectory());
-        return new InitContext(agent, "antigravity", skills, skills, tempDir, 
prefix, Printer.noop());
+        return new InitContext(
+                agent, "antigravity", skills, skills, tempDir, prefix,
+                DistributionConfig.loadFromClasspathOrDefaults(), true, 
Printer.noop());
     }
 
     @ParameterizedTest
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CodexCliSmokeTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CodexCliSmokeTest.java
index c35ccf9e..740c32b5 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CodexCliSmokeTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CodexCliSmokeTest.java
@@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit;
 
 import io.github.luigidemasi.camelkit.config.AgentConfig;
 import io.github.luigidemasi.camelkit.config.AgentRegistry;
+import io.github.luigidemasi.camelkit.config.DistributionConfig;
 import io.github.luigidemasi.camelkit.output.Printer;
 import io.github.luigidemasi.camelkit.workflow.WorkflowManifestLoader;
 
@@ -97,6 +98,8 @@ class CodexCliSmokeTest {
                 workspace.resolve(agent.skillsDirectory()),
                 workspace,
                 "camel-kit",
+                DistributionConfig.loadFromClasspathOrDefaults(),
+                true,
                 Printer.noop());
         AgentGeneratorFactory.create("codex").generate(context);
 
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CodexGeneratorTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CodexGeneratorTest.java
index 220ecf3f..d989a1ac 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CodexGeneratorTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CodexGeneratorTest.java
@@ -12,6 +12,7 @@ import java.util.stream.Collectors;
 import io.github.luigidemasi.camelkit.config.AgentConfig;
 import io.github.luigidemasi.camelkit.config.AgentDescriptor;
 import io.github.luigidemasi.camelkit.config.AgentRegistry;
+import io.github.luigidemasi.camelkit.config.DistributionConfig;
 import io.github.luigidemasi.camelkit.output.Printer;
 import io.github.luigidemasi.camelkit.workflow.WorkflowManifest;
 import io.github.luigidemasi.camelkit.workflow.WorkflowManifestLoader;
@@ -118,8 +119,7 @@ class CodexGeneratorTest {
                 ctx.distribution().camelMcpVersion());
         assertServer(servers, "camel-knowledge", 
workflow.mcpServer("camel-knowledge").allowedTools(),
                 ctx.distribution().knowledgeMcpVersion());
-        assertServer(servers, "citrus", 
workflow.mcpServer("citrus").allowedTools(),
-                ctx.distribution().citrusMcpVersion());
+        assertNull(servers.get("citrus"), "Citrus server must be absent when 
not opted in");
     }
 
     @Test
@@ -133,7 +133,7 @@ class CodexGeneratorTest {
                 enabled_tools = ["read"]
                 """);
 
-        new CodexGenerator().generate(createContext(tempDir));
+        new CodexGenerator().generate(createContext(tempDir, true));
 
         TomlParseResult config = Toml.parse(codexDir.resolve("config.toml"));
         assertFalse(config.hasErrors(), config.errors().toString());
@@ -229,6 +229,10 @@ class CodexGeneratorTest {
     }
 
     private InitContext createContext(Path projectDir) {
+        return createContext(projectDir, false);
+    }
+
+    private InitContext createContext(Path projectDir, boolean withCitrusMcp) {
         AgentConfig agent = AgentRegistry.get("codex");
         return new InitContext(
                 agent,
@@ -237,6 +241,8 @@ class CodexGeneratorTest {
                 projectDir.resolve(agent.skillsDirectory()),
                 projectDir,
                 "camel-kit",
+                DistributionConfig.loadFromClasspathOrDefaults(),
+                withCitrusMcp,
                 Printer.noop());
     }
 
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CopilotGeneratorTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CopilotGeneratorTest.java
index 0c8bf0d3..fca21776 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CopilotGeneratorTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/CopilotGeneratorTest.java
@@ -9,6 +9,7 @@ import java.util.Set;
 import io.github.luigidemasi.camelkit.config.AgentConfig;
 import io.github.luigidemasi.camelkit.config.AgentDescriptor;
 import io.github.luigidemasi.camelkit.config.AgentRegistry;
+import io.github.luigidemasi.camelkit.config.DistributionConfig;
 import io.github.luigidemasi.camelkit.output.Printer;
 
 import com.fasterxml.jackson.databind.JsonNode;
@@ -35,7 +36,8 @@ class CopilotGeneratorTest {
         Path skillsDir = tempDir.resolve(agent.skillsDirectory());
         return new InitContext(
                 agent, "copilot", skillsDir, skillsDir, tempDir,
-                "camel-kit", Printer.noop());
+                "camel-kit", DistributionConfig.loadFromClasspathOrDefaults(),
+                true, Printer.noop());
     }
 
     @Test
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/OpenCodeGeneratorTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/OpenCodeGeneratorTest.java
index f9f7fd96..ec678c5a 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/OpenCodeGeneratorTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/OpenCodeGeneratorTest.java
@@ -14,6 +14,7 @@ import java.util.stream.Collectors;
 import io.github.luigidemasi.camelkit.config.AgentConfig;
 import io.github.luigidemasi.camelkit.config.AgentDescriptor;
 import io.github.luigidemasi.camelkit.config.AgentRegistry;
+import io.github.luigidemasi.camelkit.config.DistributionConfig;
 import io.github.luigidemasi.camelkit.config.OpenCodeProjectConfig;
 import io.github.luigidemasi.camelkit.output.Printer;
 
@@ -50,7 +51,8 @@ class OpenCodeGeneratorTest {
         Path skillsDir = tempDir.resolve(agentBaseFolder + "/skills");
         return new InitContext(
                 agent, "opencode", commandsDir, skillsDir, tempDir,
-                commandPrefix, Printer.noop());
+                commandPrefix, 
DistributionConfig.loadFromClasspathOrDefaults(),
+                true, Printer.noop());
     }
 
     @Test
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/PiGeneratorTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/PiGeneratorTest.java
index 8433a230..02756d0e 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/PiGeneratorTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/PiGeneratorTest.java
@@ -8,6 +8,7 @@ import java.util.regex.Pattern;
 import io.github.luigidemasi.camelkit.config.AgentConfig;
 import io.github.luigidemasi.camelkit.config.AgentDescriptor;
 import io.github.luigidemasi.camelkit.config.AgentRegistry;
+import io.github.luigidemasi.camelkit.config.DistributionConfig;
 import io.github.luigidemasi.camelkit.output.Printer;
 
 import com.fasterxml.jackson.databind.JsonNode;
@@ -36,7 +37,8 @@ class PiGeneratorTest {
         Path skillsDir = tempDir.resolve(agentBaseFolder + "/skills");
         return new InitContext(
                 agent, "pi", commandsDir, skillsDir, tempDir,
-                "camel-kit", Printer.noop());
+                "camel-kit", DistributionConfig.loadFromClasspathOrDefaults(),
+                true, Printer.noop());
     }
 
     @Test
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/QwenGeneratorTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/QwenGeneratorTest.java
index c9946154..3618d478 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/QwenGeneratorTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/QwenGeneratorTest.java
@@ -9,6 +9,7 @@ import java.util.stream.Collectors;
 import io.github.luigidemasi.camelkit.config.AgentConfig;
 import io.github.luigidemasi.camelkit.config.AgentDescriptor;
 import io.github.luigidemasi.camelkit.config.AgentRegistry;
+import io.github.luigidemasi.camelkit.config.DistributionConfig;
 import io.github.luigidemasi.camelkit.output.Printer;
 
 import com.fasterxml.jackson.databind.JsonNode;
@@ -30,7 +31,8 @@ class QwenGeneratorTest {
         Path skillsDir = tempDir.resolve(agentBaseFolder + "/skills");
         return new InitContext(
                 agent, "qwen", commandsDir, skillsDir, tempDir,
-                "camel-kit", Printer.noop());
+                "camel-kit", DistributionConfig.loadFromClasspathOrDefaults(),
+                true, Printer.noop());
     }
 
     @Test
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/ResourceConsistencyTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/ResourceConsistencyTest.java
index 7f38b131..63717aca 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/ResourceConsistencyTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/ResourceConsistencyTest.java
@@ -1658,7 +1658,8 @@ class ResourceConsistencyTest {
         Path skillsDir = projectDir.resolve(agent.skillsDirectory());
         return new InitContext(
                 agent, agentName, commandsDir, skillsDir, projectDir,
-                "camel-kit", Printer.noop());
+                "camel-kit", DistributionConfig.loadFromClasspathOrDefaults(),
+                true, Printer.noop());
     }
 
     private static List<String> sortedAgentNames() {
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/ShippedAssetStructureTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/ShippedAssetStructureTest.java
index 1859d4f6..cec219f4 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/ShippedAssetStructureTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/generator/ShippedAssetStructureTest.java
@@ -1200,8 +1200,13 @@ class ShippedAssetStructureTest {
             assertInstanceOf(TomlTable.class, servers.get("camel"), agentName 
+ " MCP config missing camel server");
             assertInstanceOf(TomlTable.class, servers.get("camel-knowledge"),
                     agentName + " MCP config missing camel-knowledge server");
-            assertInstanceOf(TomlTable.class, servers.get("citrus"),
-                    agentName + " MCP config missing citrus server");
+            if (ctx.withCitrusMcp()) {
+                assertInstanceOf(TomlTable.class, servers.get("citrus"),
+                        agentName + " MCP config missing citrus server");
+            } else {
+                assertNull(servers.get("citrus"),
+                        agentName + " MCP config must not contain citrus 
server when not opted in");
+            }
             return;
         }
 
@@ -1210,7 +1215,12 @@ class ShippedAssetStructureTest {
         assertNotNull(servers, agentName + " MCP config missing " + 
ctx.agent().mcpServerContainerKey());
         assertTrue(servers.has("camel"), agentName + " MCP config missing 
camel server");
         assertTrue(servers.has("camel-knowledge"), agentName + " MCP config 
missing camel-knowledge server");
-        assertTrue(servers.has("citrus"), agentName + " MCP config missing 
citrus server");
+        if (ctx.withCitrusMcp()) {
+            assertTrue(servers.has("citrus"), agentName + " MCP config missing 
citrus server");
+        } else {
+            assertFalse(servers.has("citrus"),
+                    agentName + " MCP config must not contain citrus server 
when not opted in");
+        }
     }
 
     private static InitContext createContext(String agentName, Path 
projectDir) {
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/service/DoctorServiceTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/service/DoctorServiceTest.java
index d6964d7a..59a5ee76 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/service/DoctorServiceTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/service/DoctorServiceTest.java
@@ -10,6 +10,7 @@ import java.util.Map;
 import io.github.luigidemasi.camelkit.config.AgentConfig;
 import io.github.luigidemasi.camelkit.config.AgentGeneratorStrategy;
 import io.github.luigidemasi.camelkit.config.AgentRegistry;
+import io.github.luigidemasi.camelkit.config.DistributionConfig;
 import io.github.luigidemasi.camelkit.generator.AgentGeneratorFactory;
 import io.github.luigidemasi.camelkit.generator.InitContext;
 import io.github.luigidemasi.camelkit.output.Printer;
@@ -41,8 +42,8 @@ class DoctorServiceTest {
     Path tempDir;
 
     @Test
-    void antigravityMcpUsesNativeSchemaAndRequiresCitrus() throws Exception {
-        createHealthyWorkspace(tempDir, "antigravity");
+    void antigravityMcpUsesNativeSchemaAndRequiresCitrusWhenOptedIn() throws 
Exception {
+        createHealthyWorkspaceWithCitrus(tempDir, "antigravity");
         Path commented = tempDir.resolve(".agents/mcp_config.json");
         Files.writeString(commented, 
Files.readString(commented).replaceFirst("\\{", "{ // custom comment\n"));
         DoctorResult healthy = new DoctorService().inspect(new 
DoctorRequest(tempDir));
@@ -998,81 +999,26 @@ class DoctorServiceTest {
     }
 
     @Test
-    void 
missingCitrusServerWarnsWithoutVersionPropertiesInLayeredOpenCodeWorkspace() 
throws Exception {
-        createHealthyWorkspace(tempDir, OPENCODE);
-        writeMcpConfig(tempDir, OPENCODE, """
-                {
-                  "mcp": {
-                    "camel": {"type": "local"},
-                    "camel-knowledge": {"type": "local"}
-                  }
-                }
-                """);
-        Files.writeString(tempDir.resolve("opencode.jsonc"), """
-                {
-                  "permission": {
-                    "camel_*": "ask",
-                    "camel-knowledge_*": "ask"
-                  }
-                }
-                """);
-
-        DoctorResult result = new DoctorService().inspect(new 
DoctorRequest(tempDir));
-
-        assertFalse(result.hasFailures(), result.findings().toString());
-        assertTrue(hasFinding(result, DoctorFinding.Status.WARN, "mcp",
-                "MCP server 'citrus' is not configured", "Regenerate"));
-        assertFalse(hasFinding(result, DoctorFinding.Status.FAIL, "mcp", 
"citrus", null));
-        assertFalse(hasFinding(result, DoctorFinding.Status.PASS, "mcp",
-                "uses supported server fields", null));
-
-        markCitrusGenerated(tempDir, "citrus.mcp.version");
-        DoctorResult currentResult = new DoctorService().inspect(new 
DoctorRequest(tempDir));
-
-        assertTrue(currentResult.hasFailures(), 
currentResult.findings().toString());
-        assertTrue(hasFinding(currentResult, DoctorFinding.Status.FAIL, "mcp",
-                "MCP server 'citrus' is missing", "Regenerate"));
-        assertFalse(hasFinding(currentResult, DoctorFinding.Status.WARN, "mcp",
-                "MCP server 'citrus' is not configured", null));
-    }
-
-    @Test
-    void 
missingCitrusServerWarnsWithoutVersionPropertiesForLegacyCapableJsonAgents() 
throws Exception {
-        for (String agentName : List.of("bob2", CLAUDE, OPENCODE, QWEN)) {
+    void missingCitrusServerPassesWhenNotOptedIn() throws Exception {
+        for (String agentName : List.of("bob2", CLAUDE, OPENCODE, QWEN, 
COPILOT, PI)) {
             Path root = tempDir.resolve(agentName);
             createHealthyWorkspace(root, agentName);
-            removeCitrusServer(root, agentName);
 
             DoctorResult result = new DoctorService().inspect(new 
DoctorRequest(root));
 
             assertFalse(result.hasFailures(), agentName + ": " + 
result.findings());
-            assertTrue(hasFinding(result, DoctorFinding.Status.WARN, "mcp",
-                    "MCP server 'citrus' is not configured", "Regenerate"),
+            assertFalse(hasFinding(result, DoctorFinding.Status.FAIL, "mcp", 
"citrus", null),
                     agentName + ": " + result.findings());
-            assertFalse(hasFinding(result, DoctorFinding.Status.FAIL, "mcp",
-                    "MCP server 'citrus' is missing", null),
-                    agentName + ": " + result.findings());
-            assertFalse(result.findings().stream().anyMatch(finding -> 
finding.status() == DoctorFinding.Status.PASS
-                    && "mcp".equals(finding.category())),
+            assertFalse(hasFinding(result, DoctorFinding.Status.WARN, "mcp", 
"citrus", null),
                     agentName + ": " + result.findings());
         }
-
-        Path currentRoot = tempDir.resolve(CLAUDE);
-        markCitrusGenerated(currentRoot, "citrus.version");
-        DoctorResult currentResult = new DoctorService().inspect(new 
DoctorRequest(currentRoot));
-
-        assertTrue(currentResult.hasFailures(), 
currentResult.findings().toString());
-        assertTrue(hasFinding(currentResult, DoctorFinding.Status.FAIL, "mcp",
-                "MCP server 'citrus' is missing", "Regenerate"));
-        assertFalse(hasFinding(currentResult, DoctorFinding.Status.WARN, "mcp",
-                "MCP server 'citrus' is not configured", null));
     }
 
     @Test
-    void missingCitrusServerFailsForJsonAgentsIntroducedAfterCitrus() throws 
Exception {
-        for (String agentName : List.of(COPILOT, PI)) {
-            Path root = tempDir.resolve(agentName);
-            createHealthyWorkspace(root, agentName);
+    void missingCitrusServerFailsWhenOptedIn() throws Exception {
+        for (String agentName : List.of("bob2", CLAUDE, COPILOT, PI, QWEN)) {
+            Path root = tempDir.resolve("enabled-" + agentName);
+            createHealthyWorkspaceWithCitrus(root, agentName);
             removeCitrusServer(root, agentName);
 
             DoctorResult result = new DoctorService().inspect(new 
DoctorRequest(root));
@@ -1081,12 +1027,22 @@ class DoctorServiceTest {
             assertTrue(hasFinding(result, DoctorFinding.Status.FAIL, "mcp",
                     "MCP server 'citrus' is missing", "Regenerate"),
                     agentName + ": " + result.findings());
-            assertFalse(hasFinding(result, DoctorFinding.Status.WARN, "mcp",
-                    "MCP server 'citrus' is not configured", null),
-                    agentName + ": " + result.findings());
         }
     }
 
+    @Test
+    void missingCitrusServerFailsWithLegacyBackwardCompat() throws Exception {
+        Path root = tempDir.resolve("legacy-citrus");
+        createHealthyWorkspace(root, CLAUDE);
+        markCitrusGenerated(root, "citrus.mcp.version");
+
+        DoctorResult result = new DoctorService().inspect(new 
DoctorRequest(root));
+
+        assertTrue(result.hasFailures(), result.findings().toString());
+        assertTrue(hasFinding(result, DoctorFinding.Status.FAIL, "mcp",
+                "MCP server 'citrus' is missing", "Regenerate"));
+    }
+
     @Test
     void citrusToolAllowlistMismatchFailsForEachJsonAllowlistSchema() throws 
Exception {
         Map<String, List<String>> schemas = Map.of(
@@ -1098,7 +1054,7 @@ class DoctorServiceTest {
         for (Map.Entry<String, List<String>> schema : schemas.entrySet()) {
             String agentName = schema.getKey();
             Path root = tempDir.resolve(agentName);
-            createHealthyWorkspace(root, agentName);
+            createHealthyWorkspaceWithCitrus(root, agentName);
             Path mcpFile = 
root.resolve(AgentRegistry.get(agentName).mcpConfigPath());
             ObjectNode config = (ObjectNode) MAPPER.readTree(mcpFile.toFile());
             ObjectNode citrus = (ObjectNode) 
config.path(AgentRegistry.get(agentName).mcpServerContainerKey())
@@ -1697,6 +1653,31 @@ class DoctorServiceTest {
         AgentGeneratorFactory.create(agentName).generate(context);
     }
 
+    private void createHealthyWorkspaceWithCitrus(Path root, String agentName) 
throws Exception {
+        AgentConfig agent = AgentRegistry.get(agentName);
+        Files.createDirectories(root.resolve(".camel-kit"));
+        Files.writeString(root.resolve(".camel-kit/config.properties"), 
String.format(Locale.ROOT, """
+                project.name=orders
+                project.command-prefix=camel-kit
+                project.runtime=main
+                project.camelVersion=4.20.0
+                project.platformBomVersion=4.20.0
+                agent.name=%s
+                agent.folder=%s
+                citrus.mcp.enabled=true
+                citrus.mcp.version=5.0.1
+                """, agentName, agent.folder()));
+        Files.writeString(root.resolve(".camel-kit/project-graph.json"), "{}");
+        Files.writeString(root.resolve("mvnw"), "#!/bin/sh\n");
+        Path commands = agent.generatesCommandStubs()
+                ? root.resolve(agent.commandDirectory())
+                : root.resolve(".codex/commands");
+        InitContext context = new InitContext(
+                agent, agentName, commands, 
root.resolve(agent.skillsDirectory()), root, "camel-kit",
+                DistributionConfig.loadFromClasspathOrDefaults(), true, 
Printer.noop());
+        AgentGeneratorFactory.create(agentName).generate(context);
+    }
+
     private void writeMcpConfig(Path root, String agentName, String content) 
throws Exception {
         AgentConfig agent = AgentRegistry.get(agentName);
         Path mcpFile = root.resolve(agent.mcpConfigPath());
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/service/InitServiceTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/service/InitServiceTest.java
index c9f75073..3022883a 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/service/InitServiceTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/service/InitServiceTest.java
@@ -56,7 +56,8 @@ class InitServiceTest {
         assertTrue(config.contains("agent.name=bob2"));
         assertTrue(config.contains("project.sourcePlatform=mulesoft"));
         assertTrue(config.contains("citrus.version=5.0.1"));
-        assertTrue(config.contains("citrus.mcp.version=" + 
EXPECTED_CITRUS_MCP_VERSION));
+        assertTrue(config.contains("citrus.mcp.enabled=false"));
+        assertFalse(config.contains("citrus.mcp.version="));
 
         assertTrue(progress.events().contains("start:Creating project 
structure"));
         assertTrue(progress.events().contains("start:Generating IBM Bob 2 
workspace"));
@@ -65,14 +66,35 @@ class InitServiceTest {
     }
 
     @Test
-    void allAgentsGenerateTheDefaultCitrusRunnerAndPassDoctorMcpChecks() 
throws Exception {
+    void allAgentsOmitCitrusByDefaultAndPassDoctorMcpChecks() throws Exception 
{
         for (String agentName : AgentRegistry.names()) {
             Path targetDir = tempDir.resolve(agentName);
             new InitService().initialize(request(targetDir, agentName, 
InitProgress.noop(), InitReporter.noop()));
 
+            String mcp = 
Files.readString(targetDir.resolve(AgentRegistry.get(agentName).mcpConfigPath()));
+            assertFalse(mcp.contains("citrus-mcp-server"), agentName + ": 
citrus should be absent by default");
+            DoctorResult result = new DoctorService().inspect(new 
DoctorRequest(targetDir));
+            assertTrue(result.findings().stream().anyMatch(finding -> 
"mcp".equals(finding.category())
+                    && finding.status() == DoctorFinding.Status.PASS), 
agentName + ": " + result.findings());
+            assertFalse(result.findings().stream().anyMatch(finding -> 
"mcp".equals(finding.category())
+                    && finding.status() == DoctorFinding.Status.FAIL), 
agentName + ": " + result.findings());
+        }
+    }
+
+    @Test
+    void allAgentsIncludeCitrusWhenOptedInAndPassDoctorMcpChecks() throws 
Exception {
+        for (String agentName : AgentRegistry.names()) {
+            Path targetDir = tempDir.resolve("citrus-" + agentName);
+            new InitService().initialize(requestWithCitrusMcp(targetDir, 
agentName));
+
             String mcp = 
Files.readString(targetDir.resolve(AgentRegistry.get(agentName).mcpConfigPath()));
             assertTrue(mcp.contains(
                     "org.citrusframework:citrus-mcp-server:" + 
EXPECTED_CITRUS_MCP_VERSION + ":runner"), agentName);
+
+            String config = 
Files.readString(targetDir.resolve(".camel-kit/config.properties"));
+            assertTrue(config.contains("citrus.mcp.enabled=true"), agentName);
+            assertTrue(config.contains("citrus.mcp.version=" + 
EXPECTED_CITRUS_MCP_VERSION), agentName);
+
             DoctorResult result = new DoctorService().inspect(new 
DoctorRequest(targetDir));
             assertTrue(result.findings().stream().anyMatch(finding -> 
"mcp".equals(finding.category())
                     && finding.status() == DoctorFinding.Status.PASS), 
agentName + ": " + result.findings());
@@ -428,12 +450,14 @@ class InitServiceTest {
         Path targetDir = tempDir.resolve("orders");
 
         InitResult result = new InitService().initialize(
-                request(targetDir, "bob2", "4.9.2", InitProgress.noop(), 
InitReporter.noop()));
+                request(targetDir, "bob2", "4.9.2", 
CamelKitMain.distribution(), true, true,
+                        InitProgress.noop(), InitReporter.noop()));
 
         assertEquals("4.9.2", result.citrusVersion());
         String config = 
Files.readString(targetDir.resolve(".camel-kit/config.properties"));
         assertTrue(config.contains("citrus.version=4.9.2"));
         assertTrue(config.contains("citrus.mcp.version=" + 
EXPECTED_CITRUS_MCP_VERSION));
+        assertTrue(config.contains("citrus.mcp.enabled=true"));
         String mcp = Files.readString(targetDir.resolve(".bob/mcp.json"));
         assertTrue(mcp.contains(
                 "org.citrusframework:citrus-mcp-server:" + 
EXPECTED_CITRUS_MCP_VERSION + ":runner"));
@@ -448,12 +472,14 @@ class InitServiceTest {
         DistributionConfig distribution = DistributionConfig.load(properties);
 
         InitResult result = new InitService().initialize(
-                request(targetDir, "bob2", "4.9.2", distribution, 
InitProgress.noop(), InitReporter.noop()));
+                request(targetDir, "bob2", "4.9.2", distribution, true, true,
+                        InitProgress.noop(), InitReporter.noop()));
 
         assertEquals("4.9.2", result.citrusVersion());
         String config = 
Files.readString(targetDir.resolve(".camel-kit/config.properties"));
         assertTrue(config.contains("citrus.version=4.9.2"));
         assertTrue(config.contains("citrus.mcp.version=4.10.1"));
+        assertTrue(config.contains("citrus.mcp.enabled=true"));
         String mcp = Files.readString(targetDir.resolve(".bob/mcp.json"));
         
assertTrue(mcp.contains("org.citrusframework:citrus-mcp-server:4.10.1:runner"));
         
assertFalse(mcp.contains("org.citrusframework:citrus-mcp-server:4.9.2:runner"));
@@ -553,6 +579,7 @@ class InitServiceTest {
                 targetDir,
                 "default",
                 true,
+                false,
                 "mulesoft",
                 "camel-kit",
                 "5.0.1",
@@ -578,6 +605,23 @@ class InitServiceTest {
         return entries;
     }
 
+    private InitRequest requestWithCitrusMcp(Path targetDir, String agentName) 
{
+        return new InitRequest(
+                "orders",
+                agentName,
+                targetDir,
+                "default",
+                true,
+                true,
+                "mulesoft",
+                "camel-kit",
+                "5.0.1",
+                CamelKitMain.distribution(),
+                Printer.noop(),
+                InitProgress.noop(),
+                InitReporter.noop());
+    }
+
     private InitRequest request(
             Path targetDir,
             String agentName,
@@ -594,7 +638,18 @@ class InitServiceTest {
             DistributionConfig distribution,
             InitProgress progress,
             InitReporter reporter) {
-        return request(targetDir, agentName, citrusVersion, distribution, 
true, progress, reporter);
+        return request(targetDir, agentName, citrusVersion, distribution, 
true, false, progress, reporter);
+    }
+
+    private InitRequest request(
+            Path targetDir,
+            String agentName,
+            String citrusVersion,
+            DistributionConfig distribution,
+            boolean noFetch,
+            InitProgress progress,
+            InitReporter reporter) {
+        return request(targetDir, agentName, citrusVersion, distribution, 
noFetch, false, progress, reporter);
     }
 
     private InitRequest request(
@@ -603,6 +658,7 @@ class InitServiceTest {
             String citrusVersion,
             DistributionConfig distribution,
             boolean noFetch,
+            boolean withCitrusMcp,
             InitProgress progress,
             InitReporter reporter) {
         return new InitRequest(
@@ -611,6 +667,7 @@ class InitServiceTest {
                 targetDir,
                 citrusVersion,
                 noFetch,
+                withCitrusMcp,
                 "mulesoft",
                 "camel-kit",
                 "5.0.1",
diff --git 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/workflow/WorkflowManifestTest.java
 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/workflow/WorkflowManifestTest.java
index f9f168c3..3a5bd539 100644
--- 
a/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/workflow/WorkflowManifestTest.java
+++ 
b/camel-kit-core/src/test/java/io/github/luigidemasi/camelkit/workflow/WorkflowManifestTest.java
@@ -15,6 +15,7 @@ import java.util.stream.Stream;
 
 import io.github.luigidemasi.camelkit.config.AgentConfig;
 import io.github.luigidemasi.camelkit.config.AgentRegistry;
+import io.github.luigidemasi.camelkit.config.DistributionConfig;
 import io.github.luigidemasi.camelkit.generator.AgentGeneratorFactory;
 import io.github.luigidemasi.camelkit.generator.DefaultGenerator;
 import io.github.luigidemasi.camelkit.generator.InitContext;
@@ -420,7 +421,8 @@ class WorkflowManifestTest {
                 : skillsDir;
         return new InitContext(
                 agent, agentName, commandsDir, skillsDir, tempDir,
-                "camel-kit", Printer.noop());
+                "camel-kit", DistributionConfig.loadFromClasspathOrDefaults(),
+                true, Printer.noop());
     }
 
     private static Path resourcePath(String resource) throws Exception {

Reply via email to