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    ClientConstraints {
151        id: "trae",
152        display_name: "Trae",
153        mcp_instructions_max_chars: None,
154        supports_auto_approve: false,
155        supports_config_instructions: true,
156    },
157    ClientConstraints {
158        id: "qwen-code",
159        display_name: "Qwen Code",
160        mcp_instructions_max_chars: None,
161        supports_auto_approve: false,
162        supports_config_instructions: true,
163    },
164    ClientConstraints {
165        id: "verdent",
166        display_name: "Verdent",
167        mcp_instructions_max_chars: None,
168        supports_auto_approve: false,
169        supports_config_instructions: true,
170    },
171    ClientConstraints {
172        id: "pi",
173        display_name: "Pi Coding Agent",
174        mcp_instructions_max_chars: None,
175        supports_auto_approve: false,
176        supports_config_instructions: true,
177    },
178    ClientConstraints {
179        id: "cline",
180        display_name: "Cline",
181        mcp_instructions_max_chars: None,
182        supports_auto_approve: false,
183        supports_config_instructions: true,
184    },
185    ClientConstraints {
186        id: "roo",
187        display_name: "Roo Code",
188        mcp_instructions_max_chars: None,
189        supports_auto_approve: false,
190        supports_config_instructions: true,
191    },
192];
193
194pub fn by_client_id(id: &str) -> Option<&'static ClientConstraints> {
195    let id = id.trim();
196    ALL_CLIENTS.iter().find(|c| c.id == id)
197}
198
199pub(crate) fn by_editor_name(name: &str) -> Option<&'static ClientConstraints> {
200    match name {
201        "Cursor" => by_client_id("cursor"),
202        "Claude Code" => by_client_id("claude-code"),
203        "VS Code" => by_client_id("vscode-copilot"),
204        "Copilot CLI" => by_client_id("copilot-cli"),
205        "Windsurf" => by_client_id("windsurf"),
206        "Zed" => by_client_id("zed"),
207        "JetBrains IDEs" => by_client_id("jetbrains"),
208        "OpenCode" => by_client_id("opencode"),
209        "Crush" => by_client_id("crush"),
210        "Amp" => by_client_id("amp"),
211        "Hermes Agent" => by_client_id("hermes"),
212        "AWS Kiro" => by_client_id("kiro"),
213        "Amazon Q Developer" => by_client_id("amazonq"),
214        "Gemini CLI" => by_client_id("gemini-cli"),
215        "Antigravity" => by_client_id("antigravity"),
216        "Codex CLI" => by_client_id("codex"),
217        "Grok" => by_client_id("grok"),
218        "CodeWhale" => by_client_id("codewhale"),
219        "Trae" => by_client_id("trae"),
220        "Qwen Code" => by_client_id("qwen-code"),
221        "Verdent" => by_client_id("verdent"),
222        "Pi Coding Agent" => by_client_id("pi"),
223        "Cline" => by_client_id("cline"),
224        "Roo Code" => by_client_id("roo"),
225        _ => None,
226    }
227}