Skip to main content

lean_ctx/core/
client_constraints.rs

1#[derive(Debug, Clone, Copy)]
2pub struct ClientConstraints {
3    pub id: &'static str,
4    pub display_name: &'static str,
5    /// Max chars accepted by MCP `instructions` field, if documented.
6    pub mcp_instructions_max_chars: Option<usize>,
7    /// Whether the client documents `autoApprove` in its MCP config schema.
8    pub supports_auto_approve: bool,
9    /// Whether the client accepts an `instructions` field in `mcp_config.json`.
10    /// Clients like Antigravity reject/ignore configs with unknown fields (GH #1447).
11    pub supports_config_instructions: bool,
12}
13
14// Keep this aligned with `docs/integrations/client-constraints-matrix-v1.md`.
15pub const ALL_CLIENTS: &[ClientConstraints] = &[
16    ClientConstraints {
17        id: "cursor",
18        display_name: "Cursor",
19        mcp_instructions_max_chars: None,
20        supports_auto_approve: true,
21        supports_config_instructions: true,
22    },
23    ClientConstraints {
24        id: "claude-code",
25        display_name: "Claude Code",
26        mcp_instructions_max_chars: Some(2048),
27        supports_auto_approve: true,
28        // Captured /v1/messages bodies (Claude Code 2.1.287, 2026-10-02): an
29        // `instructions` key in the ~/.claude.json server entry never reaches
30        // the model; only the initialize `instructions` do. Writing it only
31        // added a second, drifting copy of the rules.
32        supports_config_instructions: false,
33    },
34    ClientConstraints {
35        id: "codebuddy",
36        display_name: "CodeBuddy",
37        mcp_instructions_max_chars: Some(2048),
38        supports_auto_approve: true,
39        supports_config_instructions: true,
40    },
41    ClientConstraints {
42        id: "vscode-copilot",
43        display_name: "VS Code / GitHub Copilot",
44        mcp_instructions_max_chars: None,
45        supports_auto_approve: false,
46        supports_config_instructions: true,
47    },
48    ClientConstraints {
49        id: "windsurf",
50        display_name: "Windsurf",
51        mcp_instructions_max_chars: None,
52        supports_auto_approve: false,
53        supports_config_instructions: true,
54    },
55    ClientConstraints {
56        id: "zed",
57        display_name: "Zed",
58        mcp_instructions_max_chars: None,
59        supports_auto_approve: false,
60        supports_config_instructions: true,
61    },
62    ClientConstraints {
63        id: "jetbrains",
64        display_name: "JetBrains IDEs",
65        mcp_instructions_max_chars: None,
66        supports_auto_approve: false,
67        supports_config_instructions: true,
68    },
69    ClientConstraints {
70        id: "opencode",
71        display_name: "OpenCode",
72        mcp_instructions_max_chars: None,
73        supports_auto_approve: false,
74        supports_config_instructions: true,
75    },
76    ClientConstraints {
77        id: "crush",
78        display_name: "Crush",
79        mcp_instructions_max_chars: None,
80        supports_auto_approve: false,
81        supports_config_instructions: true,
82    },
83    ClientConstraints {
84        id: "amp",
85        display_name: "Amp",
86        mcp_instructions_max_chars: None,
87        supports_auto_approve: false,
88        supports_config_instructions: true,
89    },
90    ClientConstraints {
91        id: "hermes",
92        display_name: "Hermes Agent",
93        mcp_instructions_max_chars: None,
94        supports_auto_approve: false,
95        supports_config_instructions: true,
96    },
97    ClientConstraints {
98        id: "kiro",
99        display_name: "AWS Kiro",
100        mcp_instructions_max_chars: None,
101        supports_auto_approve: true,
102        supports_config_instructions: true,
103    },
104    ClientConstraints {
105        id: "amazonq",
106        display_name: "Amazon Q Developer",
107        mcp_instructions_max_chars: None,
108        supports_auto_approve: false,
109        supports_config_instructions: true,
110    },
111    ClientConstraints {
112        id: "gemini-cli",
113        display_name: "Gemini CLI",
114        mcp_instructions_max_chars: None,
115        supports_auto_approve: false,
116        supports_config_instructions: false,
117    },
118    ClientConstraints {
119        id: "antigravity",
120        display_name: "Antigravity",
121        mcp_instructions_max_chars: None,
122        supports_auto_approve: false,
123        supports_config_instructions: false,
124    },
125    ClientConstraints {
126        id: "codex",
127        display_name: "Codex CLI",
128        mcp_instructions_max_chars: None,
129        supports_auto_approve: false,
130        supports_config_instructions: true,
131    },
132    ClientConstraints {
133        id: "grok",
134        display_name: "Grok",
135        mcp_instructions_max_chars: None,
136        supports_auto_approve: false,
137        supports_config_instructions: true,
138    },
139    // #1402: CodeWhale's MCP loader fails closed on unknown fields in the
140    // entries it validates, and neither `instructions` nor `autoApprove` is
141    // part of its documented per-server schema — so lean-ctx writes the bare
142    // `command` entry its reporter verified against v0.9.9.
143    ClientConstraints {
144        id: "codewhale",
145        display_name: "CodeWhale",
146        mcp_instructions_max_chars: None,
147        supports_auto_approve: false,
148        supports_config_instructions: false,
149    },
150    // #2198: Muse Code warns on and ignores unknown per-server fields; neither
151    // `instructions` nor `autoApprove` is part of its documented `mcpServers`
152    // schema, so lean-ctx writes the plain stdio entry only.
153    ClientConstraints {
154        id: "muse",
155        display_name: "Muse Code",
156        mcp_instructions_max_chars: None,
157        supports_auto_approve: false,
158        supports_config_instructions: false,
159    },
160    ClientConstraints {
161        id: "trae",
162        display_name: "Trae",
163        mcp_instructions_max_chars: None,
164        supports_auto_approve: false,
165        supports_config_instructions: true,
166    },
167    ClientConstraints {
168        id: "qwen-code",
169        display_name: "Qwen Code",
170        mcp_instructions_max_chars: None,
171        supports_auto_approve: false,
172        supports_config_instructions: true,
173    },
174    ClientConstraints {
175        id: "verdent",
176        display_name: "Verdent",
177        mcp_instructions_max_chars: None,
178        supports_auto_approve: false,
179        supports_config_instructions: true,
180    },
181    ClientConstraints {
182        id: "pi",
183        display_name: "Pi Coding Agent",
184        mcp_instructions_max_chars: None,
185        supports_auto_approve: false,
186        supports_config_instructions: true,
187    },
188    ClientConstraints {
189        id: "cline",
190        display_name: "Cline",
191        mcp_instructions_max_chars: None,
192        supports_auto_approve: false,
193        supports_config_instructions: true,
194    },
195    ClientConstraints {
196        id: "roo",
197        display_name: "Roo Code",
198        mcp_instructions_max_chars: None,
199        supports_auto_approve: false,
200        supports_config_instructions: true,
201    },
202];
203
204pub fn by_client_id(id: &str) -> Option<&'static ClientConstraints> {
205    let id = id.trim();
206    ALL_CLIENTS.iter().find(|c| c.id == id)
207}
208
209pub(crate) fn by_editor_name(name: &str) -> Option<&'static ClientConstraints> {
210    match name {
211        "Cursor" => by_client_id("cursor"),
212        "Claude Code" => by_client_id("claude-code"),
213        "VS Code" => by_client_id("vscode-copilot"),
214        "Copilot CLI" => by_client_id("copilot-cli"),
215        "Windsurf" => by_client_id("windsurf"),
216        "Zed" => by_client_id("zed"),
217        "JetBrains IDEs" => by_client_id("jetbrains"),
218        "OpenCode" => by_client_id("opencode"),
219        "Crush" => by_client_id("crush"),
220        "Amp" => by_client_id("amp"),
221        "Hermes Agent" => by_client_id("hermes"),
222        "AWS Kiro" => by_client_id("kiro"),
223        "Amazon Q Developer" => by_client_id("amazonq"),
224        "Gemini CLI" => by_client_id("gemini-cli"),
225        "Antigravity" => by_client_id("antigravity"),
226        "Codex CLI" => by_client_id("codex"),
227        "Grok" => by_client_id("grok"),
228        "CodeWhale" => by_client_id("codewhale"),
229        "Muse Code" => by_client_id("muse"),
230        "Trae" => by_client_id("trae"),
231        "Qwen Code" => by_client_id("qwen-code"),
232        "Verdent" => by_client_id("verdent"),
233        "Pi Coding Agent" => by_client_id("pi"),
234        "Cline" => by_client_id("cline"),
235        "Roo Code" => by_client_id("roo"),
236        _ => None,
237    }
238}