luigidemasi commented on code in PR #149:
URL: https://github.com/apache/camel-kit/pull/149#discussion_r4490109775


##########
kit/camel-kit-core/src/main/java/org/apache/camel/kit/generator/OpenCodeGenerator.java:
##########
@@ -30,22 +41,108 @@ public void generate(InitContext ctx) throws Exception {
         Map<String, Object> data = new HashMap<>(
                 Map.of(
                         "COMMAND_PREFIX", ctx.commandPrefix()));
-        // AGENTS.md already generated by the shared generator flow.
+
+        List<String> mcpServers = readMcpServerNames(ctx);
+        Set<String> seen = new LinkedHashSet<>();
+        boolean collisionDetected = false;
+        StringBuilder denials = new StringBuilder();
+        for (String server : mcpServers) {
+            String normalized = normalizeServerName(server);
+            if (BUILTIN_PERMISSION_PREFIXES.contains(normalized)) {
+                collisionDetected = true;
+            } else if (seen.add(normalized)) {
+                denials.append("  ").append(normalized).append("_*: deny\n");
+            }
+        }
+        data.put("MCP_TOOL_DENIALS", denials.toString());
 
         // OpenCode-specific: generate agent definitions
-        generateAgents(ctx, data);
+        generateAgents(ctx, data, !collisionDetected);
+    }
+
+    static String normalizeServerName(String name) {
+        StringBuilder sb = new StringBuilder(name.length());
+        for (int i = 0; i < name.length(); i++) {
+            char c = name.charAt(i);
+            sb.append(isAsciiAlphanumericOrHyphen(c) ? c : '_');
+        }
+        return sb.toString();
+    }
+
+    private static boolean isAsciiAlphanumericOrHyphen(char c) {
+        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' 
&& c <= '9') || c == '-';
+    }
+
+    private List<String> readMcpServerNames(InitContext ctx) throws 
IOException {
+        Set<String> names = new LinkedHashSet<>();
+        for (Path configFile : 
OpenCodeProjectConfig.existingFiles(ctx.projectDir())) {
+            collectMcpServersFromFile(configFile, names);
+        }
+        for (Path globalFile : globalConfigFiles()) {
+            collectMcpServersFromFile(globalFile, names);

Review Comment:
   [P1] Include inherited and explicit OpenCode configuration in the MCP 
inventory
   
   The added global scan fixes the standard XDG case, but this still 
inventories only the four files immediately inside `ctx.projectDir()` plus two 
global files. OpenCode 2.2.5 also loads ancestor project configuration and 
`OPENCODE_CONFIG` ([host 
discovery](https://github.com/anomalyco/opencode/blob/v2.2.5/packages/core/src/config/discovery.ts)).
 With a `probe` server already present in either source **before generation**, 
the generated worker has no `probe_*: deny`. I reproduced both cases using the 
actual OpenCode `subagent` tool: `camel-ship-worker` invoked the harmless 
`probe_mark` MCP tool and wrote its canary despite `mcp: deny`. Adding the 
missing `probe_*` denial blocked each identical run.
   
   Please derive denials from the effective host configuration, including 
inherited/explicit sources, or disable native dispatch when that inventory 
cannot be established. Add regressions for both pre-init cases. This bypasses 
the promised read-only worker using configuration that was available at 
initialization.
   
   _AI-generated by Codex on behalf of @luigidemasi._



##########
kit/camel-kit-core/src/main/java/org/apache/camel/kit/generator/OpenCodeGenerator.java:
##########
@@ -30,22 +41,108 @@ public void generate(InitContext ctx) throws Exception {
         Map<String, Object> data = new HashMap<>(
                 Map.of(
                         "COMMAND_PREFIX", ctx.commandPrefix()));
-        // AGENTS.md already generated by the shared generator flow.
+
+        List<String> mcpServers = readMcpServerNames(ctx);
+        Set<String> seen = new LinkedHashSet<>();
+        boolean collisionDetected = false;
+        StringBuilder denials = new StringBuilder();
+        for (String server : mcpServers) {
+            String normalized = normalizeServerName(server);
+            if (BUILTIN_PERMISSION_PREFIXES.contains(normalized)) {
+                collisionDetected = true;
+            } else if (seen.add(normalized)) {
+                denials.append("  ").append(normalized).append("_*: deny\n");
+            }
+        }
+        data.put("MCP_TOOL_DENIALS", denials.toString());
 
         // OpenCode-specific: generate agent definitions
-        generateAgents(ctx, data);
+        generateAgents(ctx, data, !collisionDetected);
+    }
+
+    static String normalizeServerName(String name) {
+        StringBuilder sb = new StringBuilder(name.length());
+        for (int i = 0; i < name.length(); i++) {
+            char c = name.charAt(i);
+            sb.append(isAsciiAlphanumericOrHyphen(c) ? c : '_');
+        }
+        return sb.toString();
+    }
+
+    private static boolean isAsciiAlphanumericOrHyphen(char c) {
+        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' 
&& c <= '9') || c == '-';
+    }
+
+    private List<String> readMcpServerNames(InitContext ctx) throws 
IOException {
+        Set<String> names = new LinkedHashSet<>();
+        for (Path configFile : 
OpenCodeProjectConfig.existingFiles(ctx.projectDir())) {
+            collectMcpServersFromFile(configFile, names);
+        }
+        for (Path globalFile : globalConfigFiles()) {
+            collectMcpServersFromFile(globalFile, names);
+        }
+        return List.copyOf(names);
+    }
+
+    private static void collectMcpServersFromFile(Path configFile, Set<String> 
names) throws IOException {
+        JsonNode config = 
OpenCodeProjectConfig.newJsonMapper().readTree(configFile.toFile());
+        if (config == null) {
+            return;
+        }
+        JsonNode mcp = config.path("mcp");
+        if (!mcp.isObject()) {
+            return;
+        }
+        JsonNode servers = mcp.path("servers");
+        boolean hasNativeContainer = servers.isObject() && 
!servers.has("type");

Review Comment:
   [P1] Distinguish a server's type discriminator from a server named `type`
   
   `servers.has("type")` is also true for valid native configuration containing 
a server named `type`, such as `mcp.servers = {"type": {"type": "local", ...}, 
"probe": {"type": "local", ...}}`. The [native 
schema](https://github.com/anomalyco/opencode/blob/v2.2.5/packages/schema/src/config/mcp.ts)
 allows arbitrary string server names. This branch treats the whole map as a 
legacy server named `servers`, emits `servers_*: deny`, and omits denials for 
**every actual server in that map**.
   
   With that configuration present before generation, an actual OpenCode 2.2.5 
`camel-ship-worker` child successfully called `probe_mark`; adding `probe_*: 
deny` blocked the same canary. Distinguish the scalar server-type discriminator 
from an object-valued server entry (or parse the supported schemas explicitly), 
and cover a native map containing both `type` and another server while 
retaining the real legacy server-named-`servers` case.
   
   _AI-generated by Codex on behalf of @luigidemasi._



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to