Skip to content

Commit b10a96b

Browse files
Preapprove house MCP tools for Codex (#1512)
Fixes #1511. ## What changed - Add `mcp_servers.<name>.default_tools_approval_mode = "approve"` to generated Codex MCP soft defaults. - Keep it soft, so user config can still override the server default or a single tool. - Add an eval assertion covering the generated entry. ## Validation - `nix-instantiate --parse lib/util/mcp.nix` - `nix-instantiate --parse tests/default.nix` - `nix eval --raw --impure --expr 'let flake = builtins.getFlake (toString ./.); in builtins.toJSON (flake.lib.mcp.toCodexEntries { index = { transport = "stdio"; command = "/bin/ix-mcp"; args = [ "serve" ]; }; })'` - `nix eval --raw --impure --expr 'let flake = builtins.getFlake (toString ./.); tests = import ./tests { nixpkgs = flake.inputs.nixpkgs; ix = flake.lib; paths = flake.lib.paths; }; in builtins.toJSON tests.groups.mcp'` - `nix build .#codex -L --no-link --print-out-paths`, then read the generated launch spec and confirmed `mcp_servers.index.default_tools_approval_mode` is present with value `"approve"`. Skipped full `nix build .#check`: it fails before reaching this change because `repoPackages.nix-fast-build` is missing at `lib/per-system.nix:245`. (sent by an AI agent via Claude Code) <!-- Macroscope's pull request summary starts here --> <!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. --> <!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. --> > [!NOTE] > ### Preapprove house MCP tools for Codex by setting `default_tools_approval_mode` to `approve` > - Updates `codexEntriesOne` in [mcp.nix](https://github.com/indexable-inc/index/pull/1512/files#diff-30f208a31e39d4388eb8b510d8a6962b9cd1a5d7b074429d38190a855a620744) to prepend a `mcp_servers.<name>.default_tools_approval_mode = "approve"` entry for every MCP server (both stdio and http), so house tools are trusted by default without requiring user confirmation. > - Adds a test group in [tests/default.nix](https://github.com/indexable-inc/index/pull/1512/files#diff-1cc580de297308d93d82f7b72446ae4b98832a8aae3378e9e134102519a0e33a) that asserts the generated Codex entries include this approval mode entry for a sample stdio server. > - Behavioral Change: Codex will now auto-approve tool calls from house MCP servers unless user config explicitly overrides `default_tools_approval_mode`. > > <!-- Macroscope's review summary starts here --> > > <sup><a href="https://app.macroscope.com">Macroscope</a> summarized 3a030f8.</sup> > <!-- Macroscope's review summary ends here --> > <!-- macroscope-ui-refresh --> <!-- Macroscope's pull request summary ends here -->
1 parent 6879a7f commit b10a96b

2 files changed

Lines changed: 50 additions & 18 deletions

File tree

lib/util/mcp.nix

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ let
4242
# config-launch turns into `-c <key>=<value>` flags (so a user's own
4343
# `mcp_servers.<name>` in config.toml still wins per the per-leaf presence
4444
# check). Codex keys stdio servers by `command`/`args`/`env` and HTTP servers
45-
# by `url`, mirroring `[mcp_servers.<name>]` tables in config.toml.
45+
# by `url`, mirroring `[mcp_servers.<name>]` tables in config.toml. House MCP
46+
# tools are trusted defaults, so approve server tools unless the user config
47+
# sets a stricter `default_tools_approval_mode` or per-tool override.
4648
codexEntriesOne =
4749
name: def:
4850
let
@@ -52,25 +54,33 @@ let
5254
value = toml.scalar v;
5355
}) (def.env or { });
5456
in
55-
if isStdio def then
56-
[
57-
{
58-
key = "${prefix}.command";
59-
value = toml.scalar def.command;
60-
}
61-
]
62-
++ lib.optional (def ? args) {
63-
key = "${prefix}.args";
64-
value = tomlArray def.args;
57+
[
58+
{
59+
key = "${prefix}.default_tools_approval_mode";
60+
value = toml.scalar "approve";
6561
}
66-
++ envEntries
67-
else
68-
[
69-
{
70-
key = "${prefix}.url";
71-
value = toml.scalar def.url;
62+
]
63+
++ (
64+
if isStdio def then
65+
[
66+
{
67+
key = "${prefix}.command";
68+
value = toml.scalar def.command;
69+
}
70+
]
71+
++ lib.optional (def ? args) {
72+
key = "${prefix}.args";
73+
value = tomlArray def.args;
7274
}
73-
];
75+
++ envEntries
76+
else
77+
[
78+
{
79+
key = "${prefix}.url";
80+
value = toml.scalar def.url;
81+
}
82+
]
83+
);
7484
in
7585
{
7686
/**

tests/default.nix

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,16 @@ let
138138
# ix guest sidecars are opened by the shared platform base config.
139139
baseFirewallTcpPorts = [ 5001 ];
140140
baseFirewallUdpPorts = [ 8443 ];
141+
sampleCodexMcpEntries = ix.mcp.toCodexEntries {
142+
index = {
143+
transport = "stdio";
144+
command = "/bin/ix-mcp";
145+
args = [ "serve" ];
146+
};
147+
};
148+
sampleCodexMcpEntry =
149+
key:
150+
lib.findFirst (entry: entry.key == key) null sampleCodexMcpEntries;
141151

142152
minecraft =
143153
let
@@ -2437,6 +2447,18 @@ let
24372447
];
24382448

24392449
groups = {
2450+
mcp = [
2451+
{
2452+
assertion =
2453+
sampleCodexMcpEntry "mcp_servers.index.default_tools_approval_mode"
2454+
== {
2455+
key = "mcp_servers.index.default_tools_approval_mode";
2456+
value = "\"approve\"";
2457+
};
2458+
message = "Codex MCP entries should approve trusted house server tools by default";
2459+
}
2460+
];
2461+
24402462
ix-ray = [
24412463
{
24422464
# The head runs both daemons (Ray GCS + the ix-mcp engine that drives it).

0 commit comments

Comments
 (0)