You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 6497315
Browse filesBrowse the repository at this point in the historyBrowse files
feat(mcp): auto_approve server flag with operator-owned trust rules (#136)
Adds auto_approve: true|false to mcp_servers entries. A trusted server
skips the project-server approval prompt and the per-tool registration
prompts; schema guard scans, size caps, name-shadowing rejection, env
sanitization, and artifact-ref fail-closed all still apply — the flag
removes prompts, not checks.
Trust rules (the approval gate exists because ./odek.json is
attacker-controllable, so the flag cannot be):
- global ~/.odek/config.json: honored on any server entry
- global trust marker: a command-less global entry whose name matches a
project-defined server applies the flag to it (marker never becomes a
connectable entry); project definition changes no longer re-prompt
- project ./odek.json: stripped with a warning — a cloned repo must never
self-approve its MCP servers
Also exposes auto_approve in GET /api/mcp. Docs: field reference, approval
methods list, and a dedicated section in docs/MCP.md.
Tests: gate skips (server + per-tool, empty stdin proves no prompt), and
loader trust rules (project strip, marker merge by name, bare marker
dropped, global flag preserved).
// Project-level auto_approve is a self-approval attempt surface: a
1089
+
// cloned repo must never be able to mark its own MCP servers trusted.
1090
+
// Strip it (the operator can grant the same trust from the global
1091
+
// config, where it is honored).
1092
+
forname, mc:=rangeproject.MCPServers {
1093
+
ifmc.AutoApprove {
1094
+
fmt.Fprintf(os.Stderr, "odek: WARNING: ignoring mcp_servers.%s.auto_approve from project config (%s); set auto_approve in ~/.odek/config.json to trust this server\n", name, ProjectConfigPath())
1095
+
mc.AutoApprove=false
1096
+
project.MCPServers[name] =mc
1097
+
}
1098
+
}
1099
+
1088
1100
// Start with global, overlay project
1089
1101
cfg:=overlayFile(FileConfig{}, global)
1090
1102
cfg=overlayFile(cfg, project)
1091
1103
1104
+
// Global auto_approve trust markers survive the project overlay: when
1105
+
// the global config carries the flag for a name the project defines
1106
+
// (preserved in overlayFile below) the merged server keeps it. A marker
1107
+
// with no definition behind it (auto_approve + empty command) is not a
1108
+
// server — drop it so nothing tries to connect to it.
1109
+
forname, mc:=rangecfg.MCPServers {
1110
+
ifmc.AutoApprove&&mc.Command=="" {
1111
+
delete(cfg.MCPServers, name)
1112
+
}
1113
+
}
1114
+
1092
1115
// Remember which MCP servers came from the project config so commands can
1093
1116
// require explicit approval before spawning potentially untrusted subprocesses.
0 commit comments