settings_content: Make context server args optional (#59623)

# Objective

- Fixes #59614.
- A stdio `context_servers` entry defined with only a `command` (the
minimal form most MCP hosts accept, e.g. `{ "command": "echo" }`) fails
to deserialize. `ContextServerCommand.args` is a required field, so the
entry matches no variant of the untagged `ContextServerSettingsContent`;
the server silently never loads, and the only log line is the opaque
`data did not match any variant of untagged enum
ContextServerSettingsContent`. Other fields (`env`, `timeout`) are
already optional, and the docs only ever show `args` with a value
without stating it is required, so users reasonably assume it is
optional.

## Solution

- Add `#[serde(default)]` to `ContextServerCommand.args` in
`crates/settings_content/src/project.rs`, so it defaults to an empty
list when omitted, the same way `env` and `timeout` are already
optional. `{ "command": "echo" }` now defines a valid stdio server with
no arguments.

## Testing

- Added `test_stdio_context_server_without_args` in
`crates/settings_content/src/project.rs`, which deserializes `{
"command": "echo" }` (asserts empty `args`) and `{ "command": "echo",
"args": ["hello"] }` (regression guard).
- Fail-before/pass-after confirmed: without the change the new test
fails with the exact error from the issue; with it, `cargo test -p
settings_content` passes (24 passed, 0 failed).
- `cargo clippy -p settings_content --tests` and `cargo fmt -p
settings_content -- --check` are clean.
- serde-only change; platform-independent.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fixed stdio MCP servers configured with only a `command` (no `args`)
failing to load.
This commit is contained in:
Ibrahim Khan 2026-06-21 15:34:04 -07:00 committed by GitHub
parent 4d94097df0
commit ca2d7fd9e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -481,6 +481,7 @@ pub struct OAuthClientSettings {
pub struct ContextServerCommand {
#[serde(rename = "command")]
pub path: PathBuf,
#[serde(default)]
pub args: Vec<String>,
pub env: Option<HashMap<String, String>>,
/// Timeout for tool calls in seconds. Defaults to 60 if not specified.
@ -847,3 +848,27 @@ pub enum GitHostingProviderKind {
Forgejo,
SourceHut,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stdio_context_server_without_args() {
let settings: ContextServerSettingsContent =
serde_json::from_str(r#"{ "command": "echo" }"#)
.expect("stdio context server without `args` should parse");
let ContextServerSettingsContent::Stdio { command, .. } = settings else {
panic!("expected Stdio variant, got {settings:?}");
};
assert_eq!(command.path, PathBuf::from("echo"));
assert!(command.args.is_empty());
let settings: ContextServerSettingsContent =
serde_json::from_str(r#"{ "command": "echo", "args": ["hello"] }"#).unwrap();
let ContextServerSettingsContent::Stdio { command, .. } = settings else {
panic!("expected Stdio variant, got {settings:?}");
};
assert_eq!(command.args, vec!["hello".to_string()]);
}
}