Kuberwastaken/claurst · error

mcpServers. is missing command/url

Error message

mcpServers.{name} is missing command/url

What it means

parse_mcp_servers requires every MCP server entry to define at least one of "command" (stdio server) or "url" (HTTP/SSE server), both as strings. An object with neither is unusable and produces this error naming the server.

Solutions

  1. Add "command": "<executable>" for a stdio server, or "url": "<endpoint>" for a remote server
  2. Rename tool-specific keys (cmd/serverUrl/endpoint) to command/url expected by the importer
  3. Quote the command value as a string rather than a number or array

Example fix

// before
{ "mcpServers": { "fs": { "cmd": "npx" } } }
// after
{ "mcpServers": { "fs": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-fs"] } } }
Defensive patterns

Strategy: validation

Validate before calling

for (const [name, e] of Object.entries(cfg.mcpServers ?? {})) {
  if (typeof e.command !== 'string' && typeof e.url !== 'string') throw new Error(`mcpServers.${name} needs string "command" or "url"`);
}

Type guard

const isRunnableServer = (e) => !!e && typeof e === 'object' && (typeof e.command === 'string' || typeof e.url === 'string');

Try / catch

try { importConfig(path) } catch (e) { if (String(e).includes('is missing command/url')) { console.error('Add a string "command" or "url" to the named server entry'); process.exitCode = 1; } else { throw e; } }

Prevention

When it happens

Trigger: Importing an mcpServers entry like {"fs": {"args": ["x"]}} or {"fs": {"command": 123}} (command present but not a string) so both extracted values are None.

Common situations: Config from another tool using different field names (e.g. "cmd", "endpoint", "serverUrl"), a server entry left empty after removing a key, or command defined as a non-string (number/array).

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/df9488f7aa6ea3b7. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/core/src/import_config.rs:663

    let Some(obj) = value.as_object() else {
        return Err(anyhow!("mcpServers must be an object"));
    };

    let mut servers = Vec::new();
    for (name, entry) in obj {
        let entry_obj = entry
            .as_object()
            .ok_or_else(|| anyhow!("mcpServers.{name} must be an object"))?;
        let command = entry_obj
            .get("command")
            .and_then(Value::as_str)
            .map(ToString::to_string);
        let url = entry_obj
            .get("url")
            .and_then(Value::as_str)
            .map(ToString::to_string);
        if command.is_none() && url.is_none() {
            return Err(anyhow!("mcpServers.{name} is missing command/url"));
        }
        let args = entry_obj
            .get("args")
            .and_then(Value::as_array)
            .map(|items| {
                items
                    .iter()
                    .filter_map(Value::as_str)
                    .map(ToString::to_string)
                    .collect::<Vec<_>>()
            })
            .unwrap_or_default();
        let env = entry_obj
            .get("env")
            .and_then(Value::as_object)
            .map(|map| {
                map.iter()
                    .filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), s.to_string())))

View on GitHub (pinned to b0637c97ec)